#include "cmdlib.h"
#include "mathlib.h"
#include "lbmlib.h"
#include "wadlib.h"
#include <math.h>

typedef struct
{
	char	texture[16];
	int		numpoints;
	float	points[4][6];		// or more [xyzuvl]
} idpol_t;


idpol_t	*faces[0x8000];
int		numfaces;

byte	pic[64000];
byte	*palette;

int		width, height;
int		iwidth, iheight;

float	scale;

char	texname[20];


/*
================
BoundFaces
================
*/

float	mins[3], maxs[3];

void BoundFaces (void)
{
	int		i,j,k;
	idpol_t	*pol;
	float	v;

	for (i=0 ; i<numfaces ; i++)
	{
		pol = faces[i];
		for (j=0 ; j<pol->numpoints ; j++)
			for (k=0 ; k<3 ; k++)
			{
				v = pol->points[j][k];
				if (v<mins[k])
					mins[k] = v;
				if (v>maxs[k])
					maxs[k] = v;
			}	
	}
	
	for (i=0 ; i<3 ; i++)
	{
		mins[i] = floor(mins[i]);
		maxs[i] = ceil(maxs[i]);
	}
	
	width = maxs[0] - mins[0];
	height = maxs[2] - mins[2];
	
	printf ("width: %i  height: %i\n",width, height);

	scale = 8;
	if (width*scale >= 150)
		scale = 150.0 / width;	
	if (height*scale >= 190)
		scale = 190.0 / height;
	iwidth = ceil(width*scale) + 4;
	iheight = ceil(height*scale) + 4;
	
	printf ("scale: %f\n",scale);
	printf ("iwidth: %i  iheight: %i\n",iwidth, iheight);
}


/*
============
DrawLine
============
*/
void DrawLine (vec3_t v1, vec3_t v2)
{
	int		dx, dy;
	int		adx, ady;
	int		count;
	float	xfrac, yfrac, xstep, ystep;
	unsigned		sx, sy;
	float		u, v;
	
	dx = v2[3] - v1[3];
	dy = v2[4] - v1[4];
	adx = abs(dx);
	ady = abs(dy); 
	
	count = adx > ady ? adx : ady;
	count ++;
	
	xfrac = v1[3];
	yfrac = v1[4];
	
	xstep = (float)dx / count;
	ystep = (float)dy / count;
	
	do
	{
		for (u=-0.1 ; u<=0.9 ; u+=0.999)
			for (v=-0.1 ; v<=0.9 ; v+=0.999)
			{
				sx = xfrac+u;
				sy = yfrac+v;
				if (sx < 320 && sy < 200)
					pic[sy*320+sx] = 255;
			}
			
		xfrac += xstep;
		yfrac += ystep;
		count--;
	} while (count);
}


/*
============
AddFace
============
*/
void AddFace (idpol_t *f)
{
	vec3_t		v1, v2, normal;
	int		basex, basey;
	int			i;

//
// determine which side to map the teture to
//
	VectorSubtract (f->points[0], f->points[1], v1);
	VectorSubtract (f->points[2], f->points[1], v2);
	CrossProduct (v1, v2, normal);
	
	if (normal[1] > 0)
		basex = iwidth + 2;
	else
		basex = 2;
	basey = 2;

	for (i=0 ; i<f->numpoints ; i++)
	{
		f->points[i][3] = rint((f->points[i][0] - mins[0])*scale + basex);
		f->points[i][4] = rint( (maxs[2] - f->points[i][2])*scale + basey);
	}
	
//
// draw lines
//
	for (i=0 ; i<f->numpoints ; i++)
		DrawLine (f->points[i], f->points[(i+1)%f->numpoints]);
}


/*
============
CalcPalette
============
*/
void CalcPalette (void)
{
	byte *picture;
// FIXME: hardcoded...
	LoadLBM ("/raid/quake/id1/gfx/gamepal.lbm", &picture, &palette);
}

/*
==============================================================================

==============================================================================
*/

/*************************************************************/
/*                        Alias                              */
/* No implied or expressed warantee or guarentee or golftee. */
/*                                                           */
/* Purpose: to read an Alias triangle output file (object    */
/* separators format). This file does not attempt to explain */
/* the format, for that there is an accompanying document;   */
/* Alias Internal Document Ref: RD-DS.RE.19-1.2 entitled:    */
/* "Triangle Output from Alias". Check it out!   APP         */
   
// on disk representation of a face


#define	FLOAT_START	99999.0
#define	FLOAT_END	-FLOAT_START
#define MAGIC       123322

//#define NOISY 1

typedef struct {
	float v[3];
} vector;

typedef struct
{
	vector n;    /* normal */
	vector p;    /* point */
	vector c;    /* color */
	float  u;    /* u */
	float  v;    /* v */
} aliaspoint_t;

typedef struct {
	aliaspoint_t	pt[3];
} tf_triangle;

float	coordscale = 1;
char	*texture;


void ByteSwapTri (tf_triangle *tri)
{
	int		i;
	
	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
	{
		((int *)tri)[i] = BigLong (((int *)tri)[i]);
	}
}

void OutputIdPoly (tf_triangle *tri)
{
	int			i,j;
	
	faces[numfaces] = malloc(sizeof(idpol_t));
	memset (faces[numfaces], 0, sizeof(idpol_t) );
	
	faces[numfaces]->numpoints = 3;
	for (i=0 ; i<3 ; i++)
	{
		for (j=0 ; j<3 ; j++)
			faces[numfaces]-> points[i][j] = tri->pt[i].p.v[j] * coordscale;
	}
	numfaces++;
}


int iLevel;

/*
==================
LoadAliasFile

Loads an alias object seperated triangle file into memory
FIXME: just use trilib.c
==================
*/
void LoadAliasFile (char *filename)
{
	FILE        *input;
	float        start;
	char         name[256], tex[256];
	int          i, count, magic;
	tf_triangle  tri;

	printf ("input file : %s\n",filename);
	
	if ((input = fopen(filename, "r")) == 0)
		Error ("LoadAliasFile: could not open file '%s'\n", filename);

	iLevel = 0;

	fread(&magic, sizeof(int), 1, input);
	if (BigLong(magic) != MAGIC)
		Error ("File is not a Alias object separated triangle file, magic number is wrong.\n");

	while (feof(input) == 0) {
		fread(&start,  sizeof(float), 1, input);
		*(int *)&start = BigLong(*(int *)&start);
		if (start == FLOAT_START) {
			/* Start of an object or group of objects. */
			i = -1;
			do {
				/* There are probably better ways to read a string from */
				/* a file, but this does allow you to do error checking */
				/* (which I'm not doing) on a per character basis.      */
				++i;
				fread( &(name[i]), sizeof( char ), 1, input);
			} while( name[i] != '\0' );

//			indent();
//			fprintf(stdout,"OBJECT START: %s\n",name);
			fread( &count, sizeof(int), 1, input);
			count = BigLong(count);
			++iLevel;
			if (count != 0) {
//				indent();
				fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);

				i = -1;
				do {
					++i;
					fread( &(tex[i]), sizeof( char ), 1, input);
				} while( tex[i] != '\0' );

//				indent();
//				fprintf(stdout,"  Object texture name: '%s'\n",tex);
			}

			/* Else (count == 0) this is the start of a group, and */
			/* no texture name is present. */
		}
		else if (start == FLOAT_END) {
			/* End of an object or group. Yes, the name should be */
			/* obvious from context, but it is in here just to be */
			/* safe and to provide a little extra information for */
			/* those who do not wish to write a recursive reader. */
			/* Mia culpa. */
			--iLevel;
			i = -1;
			do {
				++i;
				fread( &(name[i]), sizeof( char ), 1, input);
			} while( name[i] != '\0' );

//			indent();
//			fprintf(stdout,"OBJECT END: %s\n",name);
			continue;
		}

//
// read the triangles
//		
		for (i = 0; i < count; ++i)
		{
			fread( &tri, sizeof(tf_triangle), 1, input );
			ByteSwapTri (&tri);
			OutputIdPoly (&tri);
		}
	}
}


//=============================================================================


/*
============
main
============
*/

void main (int argc, char **argv)
{
	int		i;
	char	filename[1024];
				
	if (argc != 2)
		Error ("texmake polfile[.idpol]\nGenerates polfile.lbm and polfile_t.idpol\n");

//
// read the polfile
//	
	LoadAliasFile (argv[1]);
	printf ("numfaces: %i\n",numfaces);
	
//
// generate the texture coordinates
//
	BoundFaces ();
	
//
// generate the lbm
//
	for (i=0 ; i<numfaces ; i++)
		AddFace (faces[i]);
		
//
// save the lbm
//
	strcpy (filename, argv[1]);
	StripExtension (filename);
	strcat (filename, ".lbm");

	printf ("output file: %s\n",filename);
	CalcPalette ();
	WriteLBMfile (filename, pic, 320, 200, palette);	
}
