
/*
 * This program generates the grid.c file used by the tron program.
 */

#include <stdio.h>

#define WALL		5
#define MAXVERT		32
#define MAXPRIM		1024

struct prim {
	int	type; 		/* 0 = polygon, 1 = line, 2 = closedline */
	int	numvert;
	int	vert[MAXVERT];
};

float		V[MAXVERT][3];
int		numv, totalv, numprim, red, green, blue, N, scale;
struct prim	prim[MAXPRIM];

void header (void)
{
	printf ("/*\n");
	printf (" * Do not edit this file, it was automatically generated "
		"by \"makegrid\".\n");
	printf (" * The width of the grid is %d.\n", N);
	printf (" */\n\n");
	printf ("#include <mbi.h>\n\n");
}

void initmg (char * v)
{
	int	i, j;

	numprim = 0;
	totalv = 0;

	printf ("static Vtx %s[] = {\n",v);
	
	for (i = 0; i < MAXPRIM; i++) {
		for (j = 0; j < MAXVERT; j++) {
			prim[i].vert[j] = 0;
		}
		prim[i].numvert = 0;
	}
}

void cpack (int c)
{
	red = c & 0xff;
	green = (c >> 8) & 0xff;
	blue = (c >> 16) & 0xff;
}

void bgnpolygon (void)
{
	numv = 0;
	prim[numprim].type = 0;
}

void bgnline (void)
{
	numv = 0;
	prim[numprim].type = 1;
}

void bgnclosedline (void)
{
	numv = 0;
	prim[numprim].type = 2;
}

void v3f (float v[3])
{
	if (numv == MAXVERT) {
		fprintf (stderr, "Too many vertices.\n");
		exit (1);
	}

	V[numv][0] = v[0] * scale;
	V[numv][1] = v[1] * scale;
	V[numv][2] = v[2] * scale;
	numv++;
}

void emitv (void)
{
	int	i;

	if (numprim == MAXPRIM) {
		fprintf (stderr, "Too many primitives.\n");
		exit (1);
	}
	for (i = 0; i < numv; i++) {
		printf ("\t{ %4d, %4d, %4d,\t0, 0, 0,\t%3d, %3d, %3d,\t255 },\n",
			(int)V[i][0], (int)V[i][1], (int)V[i][2],
			red, green, blue);
		prim[numprim].vert[i] = totalv++;
		prim[numprim].numvert++;
	}
	numprim++;
}

void endpolygon (void)
{
	emitv ();
}

void endline (void)
{
	int	i;

	if (numv * 2 >= MAXVERT) {
		fprintf (stderr, "Too many vertices for lines.\n");
		exit (1);
	}

	for (i = 0; i < numv; i++) {
		V[numv + i][0] = V[i][0] + 1;
		V[numv + i][1] = V[i][1] + 1;
		V[numv + i][2] = V[i][2] + 1;
	}

	numv *= 2;

	emitv ();
}

void endclosedline (void)
{
	endline ();
}

void exitmg (char *g, char * v)
{
	int i, j, half, len;

	printf ("};\n\n");

	len = 0;

	printf ("Gfx %s[] = {\n",g);
	for (i = 0; i < numprim; i++) {
		switch (prim[i].type) {
			case 0:	/* Polygon */
				printf ("\t/* Polygon %d */\n", i);
				printf ("\tgsSPVertex (%s + %d, %d, 0),\n",
					v, prim[i].vert[0], prim[i].numvert);
				len++;
				for (j = 2; j < prim[i].numvert; j++) {
					printf ("\tgsSP1Triangle (0, %d, %d, 0),\n",
						j - 1, j);
					len++;
				}
				break;
			case 1:	/* Line */
				printf ("\t/* Line %d */\n", i);
				printf ("\tgsSPVertex (%s + %d, %d, 0),\n",
					v, prim[i].vert[0], prim[i].numvert);
				len++;
				half = prim[i].numvert / 2;
				for (j = 0; j < half - 1; j++) {
					printf ("\tgsSP1Triangle (%d, %d, %d, 0),\n",
						j, j + 1, j + half + 1);
					printf ("\tgsSP1Triangle (%d, %d, %d, 0),\n",
						j, j + 1 + half , j + half);
					len += 2;
				}
				break;
			case 2:	/* Closed line */
				printf ("\t/* Closed line %d */\n", i);
				printf ("\tgsSPVertex (%s + %d, %d, 0),\n",
					v, prim[i].vert[0], prim[i].numvert);
				len++;
				half = prim[i].numvert / 2;
				for (j = 0; j < half; j++) {
					printf ("\tgsSP1Triangle (%d, %d, %d, 0),\n",
						j, (j + 1) % half,
						(j + 1) % half + half);
					printf ("\tgsSP1Triangle (%d, %d, %d, 0),\n",
						j, (j + 1) % half + half,
						j + half);
					len += 2;
				}
				break;
		}
		printf ("\n");
	}
	printf ("\tgsSPEndDisplayList (),\n\n");
	printf ("};   /* Length = %d */\n\n", len);
}

int main (int argc, char *argv[])
{
	int	i, j;
	float	v[3];

	N = 200; /* For now */
	scale = 20;

	header ();

	initmg ("v");

	/* Half of the floor tile colors */
	cpack (0x8a8a8a);

	/* Floor */
	bgnpolygon ();
	v[0] = 0;   v[1] = 0;    v[2] = 0;    v3f (v);
	v[0] = 0;   v[1] = 0;    v[2] = N;    v3f (v);
	v[0] = N;   v[1] = 0;    v[2] = N;    v3f (v);
	v[0] = N;   v[1] = 0;    v[2] = 0;    v3f (v);
	endpolygon ();

	/* Other half of the floor tile colors */
	cpack (0x0000c0);
	for (i = 0; i < N; i += 20) {
		for (j = 0; j < N; j += 20) {
			if ((i/20 + j/20) % 2 == 1) {
				bgnpolygon ();
				v[0] = i;      v[1] = 0; v[2] = j;      v3f(v);
				v[0] = i + 20; v[1] = 0; v[2] = j;      v3f(v);
				v[0] = i + 20; v[1] = 0; v[2] = j + 20; v3f(v);
				v[0] = i;      v[1] = 0; v[2] = j + 20; v3f(v);
				endpolygon ();
			}
		}
	}

	exitmg ("grid","v");

	initmg ("w");

	/* Walls */
	cpack (0x0000d0d0);
	bgnpolygon ();
	v[0] = 0;   v[1] = 0;    v[2] = 0;    v3f (v);
	v[0] = 0;   v[1] = WALL; v[2] = 0;    v3f (v);
	v[0] = N;   v[1] = WALL; v[2] = 0;    v3f (v);
	v[0] = N;   v[1] = 0;    v[2] = 0;    v3f (v);
	endpolygon ();
	bgnpolygon ();
	v[0] = 0;   v[1] = 0;    v[2] = N;    v3f (v);
	v[0] = 0;   v[1] = WALL; v[2] = N;    v3f (v);
	v[0] = N;   v[1] = WALL; v[2] = N;    v3f (v);
	v[0] = N;   v[1] = 0;    v[2] = N;    v3f (v);
	endpolygon ();
	cpack (0x0000d0d0);
	bgnpolygon ();
	v[0] = 0;   v[1] = 0;    v[2] = 0;    v3f (v);
	v[0] = 0;   v[1] = WALL; v[2] = 0;    v3f (v);
	v[0] = 0;   v[1] = WALL; v[2] = N;    v3f (v);
	v[0] = 0;   v[1] = 0;    v[2] = N;    v3f (v);
	endpolygon ();
	bgnpolygon ();
	v[0] = N;   v[1] = 0;    v[2] = 0;    v3f (v);
	v[0] = N;   v[1] = WALL; v[2] = 0;    v3f (v);
	v[0] = N;   v[1] = WALL; v[2] = N;    v3f (v);
	v[0] = N;   v[1] = 0;    v[2] = N;    v3f (v);
	endpolygon ();

	exitmg ("walls","w");
}

