// drvtest.c
#include "system/xmath.h"
#include "vmath/vmath.h"
#include "vmath/vector.h"
#include "vmath/matrix.h"
#include "system/xstdio.h"
#include "drivers/drv16.h"
#include "formats/vio.h"
#include "formats/v3o.h"
#include "objects/object.h"
#include "render16/rnd_util.h"
/*

#if defined(__DOS__)
#define DRIVER vgaDRV
#elif defined(__NT__)
*/
#define DRIVER dx16DRV
//#endif

extern DRV DRIVER;
static DRV *drv = &DRIVER;

static BYTE lighttab[LIGHTLEVELS * 256];
BUFF *buff;

#define MY_LIGHTLEVELS 64

/*
 * lighttable calculations for 32 bits RGB
 * fake linear calculations...
 *
 */

static int local_lighttable (BYTE light, BYTE ambient)
{
	int i,j;
	int col,c;
	float add;


//	if ((lighttab = (BYTE *)xmalloc (sizeof (BYTE) * LIGHTLEVELS * 256))==NULL) return FALSE;

	for (j=0;j<256;j++)
	{
		col = j;
		add = (col - ambient)/(float)(LIGHTLEVELS/2.0);
		for (i=0;i<LIGHTLEVELS/2.0;i++)
		{
			c = ambient + add*i;
			lighttab[j+i*256]=c;
		}
		add = (light - col) / (float)(LIGHTLEVELS/2.0);
		for (i=0;i<LIGHTLEVELS/2.0;i++)
		{
			c = col + add*i;
	//		if (c>255) c = 255;
			lighttab[j+(i+LIGHTLEVELS/2)*256]=c;

		}
	}
	return TRUE;
}
static float text_sine[512];
VECTOR cube_text[8] ={0,0,0, 0,255,0, 255,255,0, 255,0,0,
											0,0,0, 0,0,0, 0,0,0, 0,0,0};
VECTOR cube_vertex[8]={-80,80,80, 80,80,80, 80,-80,80, -80,-80,80,
											 -80,80,-80, 80,80,-80, 80,-80,-80, -80,-80,-80};
VECTOR rot_vertex[8];
int surftable[6][4]={{0,1,2,3},{7,6,5,4},{0,3,7,4},{5,1,0,4},{6,2,1,5},{3,2,6,7}};

RGBA surface_col[6]={192,0,0,0, 0,142,0,0, 0,0,142,0, 142,0,142,0, 142,142,0,0, 0,142,142,0};
static OBJECT torus;


/* do a fucking cube! */
static int xv,yv,zv,xva,yva,zva;
void update_ang (void)
{
	xv = (xv + xva) & (SINESIZE -1);
	yv = (yv + yva) & (SINESIZE -1);
	zv = (zv + zva) & (SINESIZE -1);
}
static void my_project (VECTOR *v, float xo, float yo, float zo, float d)
{
	float t;
	v->z += zo;

	t = d - v->z;
	t = d/t;

	v->x = (xo+v->x) * t;
	v->y = (yo+v->y) * t;
}
int hidden (int s)
{
	float x1,x2,y1,y2,f;
	int v1,v2,v3;

	v1 = surftable[s][0];
	v2 = surftable[s][1];
	v3 = surftable[s][2];


	x1=rot_vertex[v2].x - rot_vertex[v1].x;
	y1=rot_vertex[v2].y - rot_vertex[v1].y;

	x2=rot_vertex[v3].x - rot_vertex[v1].x;
	y2=rot_vertex[v3].y - rot_vertex[v1].y;

	f=(x1*y2-y1*x2);

	if (f>0) return 0;

	return 1;

}
static VIO *vio_image;
static int sine_count = 0;

#define TEX_SIZE 1024
#define TEX_RAD 128
void do_it2 (V3O *obj,int l)
{
	MATRIX m;
	int i;
	XYZ p1,p2,p3;
	V3OSURFACE *sf = obj->surface;

	update_ang ();


	buildrotationmatrix (xv,yv,zv,&m);
	for (i=0;i<obj->numvertex;i++)
	{
		vecmul (&m,&obj->orgvertex[i],&obj->rotvertex[i]);
		vecmul (&m,&obj->orgnormal[i],&obj->rotnormal[i]);

		my_project (&obj->rotvertex[i],0,0,1000,400);
		obj->rotvertex[i].x += buff->xorigo;
		obj->rotvertex[i].y += buff->yorigo;
	}

	p1.l = p2.l = p3.l = l;
	for (i=0;i<obj->numsurface;i++)
	{
		if (render_ishidden (obj, &sf[i]))
		{
			p1.x = obj->rotvertex[sf[i].v1].x;
			p1.y = obj->rotvertex[sf[i].v1].y;
			p1.z = obj->rotvertex[sf[i].v1].z;
			p1.tx = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v1].x;
			p1.ty = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v1].y;

			p2.x = obj->rotvertex[sf[i].v2].x;
			p2.y = obj->rotvertex[sf[i].v2].y;
			p2.z = obj->rotvertex[sf[i].v2].z;
			p2.tx = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v2].x;
			p2.ty = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v2].y;

			p3.x = obj->rotvertex[sf[i].v3].x;
			p3.y = obj->rotvertex[sf[i].v3].y;
			p3.z = obj->rotvertex[sf[i].v3].z;
			p3.tx = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v3].x;
			p3.ty = TEX_RAD+TEX_SIZE*obj->rotnormal[sf[i].v3].y;

			drv->tpoly (p1,p2,p3,(BYTE *)vio_image->image32);
		}
	}


}
void do_it (int l,float x, float y)
{
	MATRIX m;
	XYZ pts[4];
	int i,j;

	update_ang ();

	buildrotationmatrix (xv,yv,zv, &m);
	for (i=0;i<8;i++)
	{
		vecmul (&m,&cube_vertex[i],&rot_vertex[i]);
		my_project (&rot_vertex[i],0,0,1000,400);
		rot_vertex[i].x += buff->xorigo;
		rot_vertex[i].y += buff->yorigo;
	}

	for (i=0;i<6;i++)
	{
		for (j=0;j<4;j++)
		{
			pts[j].x = rot_vertex[surftable[i][j]].x;
			pts[j].y = rot_vertex[surftable[i][j]].y;
			pts[j].z = rot_vertex[surftable[i][j]].z;
			pts[j].z = 0;
			pts[j].tx = cube_text[j].x;//64+(int)(text_sine[sine_count]*cube_text[surftable[0][j]].x);
			pts[j].ty = cube_text[j].y;//64+(int)(text_sine[sine_count+128]*cube_text[surftable[0][j]].y);
			pts[j].l = l;
		}

		if (!hidden (i))
		{

			drv->poly (pts[0],pts[1],pts[2],surface_col[i]);
			drv->poly (pts[0],pts[2],pts[3],surface_col[i]);

//			pts[j].l = 32;

//			drv->tpoly (pts[0],pts[1],pts[2],(BYTE *)vio_image->image32);
//			drv->tpoly (pts[0],pts[2],pts[3],(BYTE *)vio_image->image32);


		}
	}
	sine_count = (sine_count+1) & 255;
}

int main( void)
{
	RGB color1 = {0,0,255};
	RGBA color2 = {255,0,0};
	RGB ambient = {0,0,0};
	RGB rgb_col = {32,0,0};
	RGB light = {64,64,64};
	int q = FALSE;
	int i,j,c,zv=0;
	int mt = 1;
	float x,y;
	BYTE c1,c2;
	float l=63;
	float xf;
	char *image;
	XYZ pt[4];
	VECTOR v[4],dv[4];
	MATRIX rm;
	RGBA cl_col={0,0,0};
	//BYTE *cp;

	xva = -20*4;
	yva = 32*3;
	zva = -24*4;

  xv = yv = zv = 0;
/*
	for (i=0;i<512;i++)	text_sine[i]=sin((float)i*M_PI/128.0);



	torus.type = T_V3O;
	if (object_load (&torus,"x:/scenes/torus.v3o","x:/")==NULL)
	{
		printf ("error: %s\n",object_geterror ());
		exit (1);
	}

	v3o_scale (torus.v3o,128,128,128);
	if ((vio_image = vio_load ("x:/envmap.vio"))==NULL)
	{
		printf ("unable to load rgb.vio\n");
		exit (1);
	}
	if (vio_image->image32==NULL)
	{
		printf ("unable to locate 32bit RGBA record in rgb.vio\n");
		exit (1);
	}

	*/

	mathinit ();
	if( !drv->setup())
	{
		printf("Driver setup failed(%s)\n", drv->geterror());
		exit( 1);
	}
	else
	{
		printf("Available modes:\n");
		for( i=0; i<drv->modes; i++)
			printf("%dx%d\n", drv->modelist[i].width, drv->modelist[i].height);
	}

  //if( !drv->init(drv->modelist[0].width, drv->modelist[0].height, DRVCFG_ZBUFFER))
	if( !drv->init(320,240, DRVCFG_ZBUFFER | DRVCFG_16BITS))
	{
		printf("Unable to initilize %s.(%s)\n", drv->name, drv->geterror());
		exit(0);
	}
  if (!drv->mouseinit( 0, 0, drv->width - 1, drv->height - 1))
	{
		drv->exit();
    printf("[!] Error: Unable to initilize mousedriver.\n");
		exit(0);
	}
	buff = drv->createbuff( 160,120);
	drv->setbuff( buff);
  local_lighttable (255,16);
	buff -> lighttab = lighttab;



	x = 160, y = 100;
	v[0].x = -128;
	v[0].y = -128;
	pt[0].z = 0;
	pt[0].tx = -64;
	pt[0].ty = -64;
	pt[0].l = l;

	v[1].x = 128;
	v[1].y = -128;
	pt[1].z = 0;
	pt[1].tx = 64;
	pt[1].ty = -64;
	pt[1].l = l;

	v[2].x = 128;
	v[2].y = 128;
	pt[2].z = 0;
	pt[2].tx = 64;
	pt[2].ty = 64;
	pt[2].l = l;

	v[3].x = -128;
	v[3].y = 128;
	pt[3].z = 0;
	pt[3].tx = -64;
	pt[3].ty = 64;
	pt[3].l = l;

	xf = 1.0;
	//putimage_8 ((RIX8 *)image);
	//putimage_16 (rix16);
	//test_lighttab ();
	l = 32;
	while( !q)
	{
		XYZ p1,p2,p3;
    int xadd,yadd;

		drv->vsync();
//    drv->xmovebuff(0, 0, cl_col);
		drv->copybuff (0,0);

    drv->getmousediff( &xadd, &yadd);
    x += (float)xadd / 10, y += (float)yadd / 10;
    p1.x = 0;
    p1.y = 0;
		p1.z = 0;
		p1.tx = 0;
		p1.ty = 0;
		p1.l = 32;

    p2.x = 128;
    p2.y = 0;
    p2.z = 0;
		p2.tx = 128;
		p2.ty = 0;
    p2.l = 32;


    p3.x = 0;
    p3.y = 128;
		p3.z = 0;
		p3.tx = 0;
		p3.ty = 128;
    p3.l = 32;
		// prevent checking for lighttab...
		buff->lighttab = NULL;
		//drv->tpoly( p1, p2, p3, (BYTE *)vio_image->image32);
		//drv->poly (p1,p2,p3,color2);

		do_it (l,x,y);

		//	do_it2 (torus.v3o,l);
		buildrotationmatrix (0,0,zv,&rm);

		for (i=0;i<4;i++)
		{
			vecmul (&rm,&v[i],&dv[i]);
			pt[i].x = xf*dv[i].x + x;
			pt[i].y = xf*dv[i].y + y;
			switch (mt)
			{
				case 2 : 	pt[i].l = l; break;
				case 1 : 	pt[i].l =  (l-i*4>0) ? (l-4*i) : 0; break;
			}
		}

		while( drv->kbhit())
		{
			switch( drv->getkey())
			{
				case 27: q = TRUE; break;
				case '+' : if (63>l) l++; break;
				case '-' : if (l>0) l--; break;
				case 'a' : xf+=0.1; break;
				case 'z' : if (xf>0) xf-=0.1; break;
				case 'q' : yv = (yv + 32) & (SINESIZE-1); break;
				case 'e' : yv = (yv - 32) & (SINESIZE-1); break;
				case '1' : mt = 1; break;
				case '2' : mt = 2; break;

//				case 32: debug_break(); break;
			}
		}
	}

	drv->destroybuff( buff);
	drv->exit();
/*
	cl_col=vio_image->image32[0];
	cp = (BYTE *) & cl_col;
	printf ("röd: %x, %x, %x, %x\n",cp[0],cp[1],cp[2],cp[3]);

	cl_col=vio_image->image32[150];
	cp = (BYTE *) & cl_col;
	printf ("grön: %x, %x, %x, %x\n",cp[0],cp[1],cp[2],cp[3]);

	cl_col=vio_image->image32[190];
	cp = (BYTE *) & cl_col;
	printf ("blå: %x, %x, %x, %x\n",cp[0],cp[1],cp[2],cp[3]);
*/
  return( 0);

}

