/*
 * Data structures for triangle renderer
 */

/*
 * transformation matrix: a 4x4 matrix, last row is always 0 0 0 1 so is not stored
 * numbers are 0.14 fractions (1 = 0x4000)
 */
typedef struct matrix {
	int	xrite, xdown, xhead, xposn;
	int	yrite, ydown, yhead, yposn;
	int	zrite, zdown, zhead, zposn;
} Matrix;

/*
 * points consist of the point + its vertex normal
 */
typedef struct point {
	int	x, y, z, one;
	int	vx, vy, vz, zero;
} Point;


/*
 * a texture map consists of:
 * (1) a discriminator: if the polygon's area is less than this,
 *	the texture map is used, otherwise the next texture map
 *	in the list is
 * (2) the width and height of the map
 * (3) blitter flags for the map
 * (4) a pointer to the actual texture map
 */
typedef struct texmap {
/*	long	discriminator; */
	int	width, height;
	long	blitflags;
	unsigned short data[0];
} Texmap;

/*
 * a "material" consists of:
 * flags (e.g. transparency)
 * a color (used for Gouraud shading)
 * a list of zero or more textures at different sizes
 * the list is terminated by a texture with a NULL
 * pointer
 */
typedef struct material {
	unsigned	color;
	unsigned	flags;
	Texmap		*tmap;
} Material;

/* triangle: occupies 5 phrases (keep points, etc. phrase aligned) */
typedef struct triangle {
	int	fx, fy, fz, fd;		/* plane equation for polygon (face normal and -normal*point) */

/* for each point, keep:
   (1) the index of the point into the points or tpoints table
   (2) a vertex normal (index into vnorms table)
   (3) texture map coordinates (U,V)
 */
	int	pa, uva;		/* point, U, V for first triangle point */
	int	pb, uvb;
	int	pc, uvc;

	int	reserved;		/* triangle flags: reserved for future use */
	int	material;		/* index into Materials table */
} Triangle;

/* object data: many objects may share the same object data (e.g. if there are 3 identical spaceships
   flying around, all 3 objects use the same data) */

typedef struct objdata {
	int	numtris;		/* number of triangles in object */
	int	numpoints;		/* number of points in object */
	Triangle *tris;			/* pointer to triangle mesh */
	Point	*points;		/* point table */
	Material *materials;		/* pointer to table of materials (e.g. colors) */
} Objdata;


/* finally, an object: a transformation matrix, pointer to object data, plus
 * whatever else we eventually decide to include.
 */

typedef struct object {
	Matrix	M;		/* object space -> world space */
	Objdata	*data;
} Object;


/* camera: a camera defines a point of view, and consists of:
 * (1) a transformation matrix (world space -> object space)
 * (2) x,y scales for the view screen
 * (3) x,y center for the view screen
 * (4) width, height for the view screen (for clipping)
 */

typedef struct camera {
	short	*outdata;		/* output address */
	long	outflags;		/* blitter flags for output */
	int	xscale,yscale;		/* scaling factors for output (8 bit) */
	int	xcenter,ycenter;	/* center (x,y) of output window */
	int	width,height;		/* width and height of output window */
	Matrix	M;
} Camera;


/*
 * a light can be of 1 of two types:
 * (1) an "in scene" light: this has attenuation based on distance to
 *	the point being illuminated
 * (2) sunlight: this is just a vector
 */

typedef struct light {
	int	x,y,z;		/* light position, for in scene, or normal vector for sunlight */
	unsigned bright;		/* base intensity, for in scene, or 0 for sunlight */
} Light;

/*
 * a lighting model consists of:
 * (1) ambient illumination (from 0-$ffff)
 * (2) some number of lights
 *
 * we (arbitrarily) impose a limit of MAXLIGHTS lights
 * per scene.
 */

#define MAXLIGHTS 4

typedef struct lightmodel {
	unsigned	ambient;	/* ambient illumination */
	int	numlights;		/* number of lights */
	Light	lights[MAXLIGHTS];		/* pointer to lights */
} Lightmodel;

void TRIrender(Object *obj, Camera *cam, Lightmodel *lmodel);

