#ifndef VECTORS_H_INCLUDED
#define VECTORS_H_INCLUDED

#include <float.h>

/* Single precision is probably enough. */
#define COORD_T float
#define EPSILON FLT_EPSILON

#ifndef SQR
#define SQR(x) ((x)*(x))
#endif SQR

/* Coordinate systems:
 *
 * I work with right handed coordinate systems. In the transformed coordinates,
 * Y points up, X right, and Z towards the observer.
 */

/* I treat vectors as column vectors, ie 3x1 matrices. */
typedef COORD_T Vector [3];

/* Vector with homogenous coordinates. Used only in the TransformVectors() function. */
typedef COORD_T HVector [4];

/* Transformations work with homogenous coordinates, to simplify translations and
 * central projection. First index in the matrix is the row. */
typedef COORD_T Matrix [4] [4];

/* Description of the view of the objects. */
struct Viewpoint
{
  Vector ref;               /* View reference point, the point upon which the
			     * eye is looking. */
  Vector direction;         /* View direction, from eye towards the reference point.
			     * Or more precisely, the direction from the origin of the
			     * projection plane towards the reference point.
			     * In transformed coordinates, this direction is aligned with
			     * the negative Z-axis */
  Vector upwards;           /* Up direction, not necessarily orthogonal to the
			     * view direction, but they must be linearly independent. */
  COORD_T  distance;        /* Distance from reference point to projection plane. */
  Vector centre;            /* Centre of projection in transformed coordinates,
			     * (relative to projection plane). That is, (0, 0, 1)
			     * means 1 unit right behind the projection plane. */
};

/* Compute C = A * B . A, B and C may be the same matrix */
void MatrixMult(Matrix A, Matrix B, Matrix C);

/* Transforms a list of points */
void TransformVectors(Matrix T, unsigned n, Vector src[], Vector dst[]);

/* Create transformation matrix from a Viewpoint structure */
void MakeTransform(struct Viewpoint *view, Matrix T);

#endif VECTORS_H_INCLUDED

