/*
	Ninja Sample
	
	COPYRIGHT (C) SEGA ENTERSRISES,LTD.

	Light Sample

	1997.12.08
*/
#include "main.h"

#if 0
/* F40 */
#define	CAR				object_F40_GTE_sh_null1_1_null1_1
#define	TEXLIST			texlist_F40_GTE_sh_null1_1
#define	PATH			"f40\\"

#else
/* PORCHE */
#define	CAR				object_por_model_model
#define	TEXLIST			texlist_por_model
#define	PATH			"por\\"
#endif

extern	NJS_OBJECT		CAR[];
extern	NJS_TEXLIST		TEXLIST;

NJS_VIEW	view;
NJS_SPRITE	sprite;
NJS_MATRIX	matrix[128];
NJS_TEXMEMLIST	tex[256];
NJS_VERTEX_BUF	vbuf[4096];

NJS_LIGHT	dlt;						/* Directional Point Light Sources */
NJS_LIGHT	plt1, plt2, plt3, plt4;		/* Point Light Source*/
NJS_LIGHT	splt;						/* Spot Lights */
NJS_LIGHT	ult;						/* User Light */

Angle		car_motion = 0;
Int			lt_num[7]={1,1,1,1,1,1,0};

Int			help_cnt = 0;

Int			spot_col_cnt = 0;
NJS_ARGB	spot_color[4] = 
{
	{1.f, _FLUORESCENT_LIGHT},
	{1.f, _PURPLE_LIGHT},
	{1.f, _GREEN_LIGHT},
	{1.f, _BLUE_LIGHT}
};

Int			pnt_col_cnt = 0;
NJS_ARGB	pnt_color[6] = 
{
	{1.f, _HALOGEN_LIGHT},
	{1.f, _SODIUM_LIGHT},
	{1.f, _FLUORESCENT_LIGHT},
	{1.f, _PURPLE_LIGHT},
	{1.f, _GREEN_LIGHT},
	{1.f, _BLUE_LIGHT}
};

Int		dir_col_cnt = 0;
NJS_ARGB	dir_color[2] = 
{
	{1.f, _NORMAL_LIGHT},
	{1.f, _FOG_LIGHT}
};

Int		attribute_cnt = 0;
Int		light_attribute[3] = 
{
	0x00,
	NJD_SIMPLE_LIGHT,
	NJD_BLOCK_LIGHT,
};

Int		lmp_cnt = 0;
Int		lmp_attribute[4] = 
{
	NJD_POINT_LIGHT,
	NJD_LAMBERT_POINT,
	NJD_SPEC_POINT,
	NJD_PHONG_POINT
};

Uint8		old_key;
Int			gcount = 0;
Float		rad = 0.f;

void
UserLight(NJS_ARGB* ptr_argb, NJS_POINT3* ptr_pnt, NJS_VECTOR* ptr_nml, NJS_LIGHT_PTR ptr_light)
{
	Float	deg;

	// inner product 
	deg = - ptr_nml->x * NJM_LIGHT_VECTOR(ptr_light).x
		  - ptr_nml->y * NJM_LIGHT_VECTOR(ptr_light).y
		  - ptr_nml->z * NJM_LIGHT_VECTOR(ptr_light).z;

	if (deg > 0.f) {
		ptr_argb->a = deg * NJM_LIGHT_DIF(ptr_light).a;
		ptr_argb->r = 0.5f * deg * NJM_LIGHT_DIF(ptr_light).r;
		ptr_argb->g = 0.25f * deg * NJM_LIGHT_DIF(ptr_light).g;
		ptr_argb->b = 0.125f * deg * NJM_LIGHT_DIF(ptr_light).b;
	}
}

void
SetLights(void)
{
	/********************************/
	/*		Creating Lights			*/
	/********************************/
	njCreateLight(&dlt, NJD_SPEC_DIR);
	njCreateLight(&plt1, lmp_attribute[lmp_cnt]|light_attribute[attribute_cnt]);
	njCreateLight(&plt2, lmp_attribute[lmp_cnt]|light_attribute[attribute_cnt]);
	njCreateLight(&plt3, lmp_attribute[lmp_cnt]|light_attribute[attribute_cnt]);
	njCreateLight(&plt4, lmp_attribute[lmp_cnt]|light_attribute[attribute_cnt]);
	njCreateLight(&splt, NJD_SPOT_LIGHT|light_attribute[attribute_cnt]);
	njCreateLight(&ult, NJD_USER_LIGHT);

	/********************************/
	/*		Setting Lights			*/
	/********************************/
	njSetLightColor(&dlt, 
					dir_color[dir_col_cnt].r,
					dir_color[dir_col_cnt].g, 
					dir_color[dir_col_cnt].b);
	njSetLightIntensity(&dlt, 0.6f, 0.8f, 0.f);

	njSetLightColor(&plt1, 
					pnt_color[pnt_col_cnt].r,
					pnt_color[pnt_col_cnt].g, 
					pnt_color[pnt_col_cnt].b);
	njSetLightIntensity(&plt1, 0.5f, 0.6f, 0.1f);
	njSetLightRange(&plt1, 2.f, 10.f);
	njSetLightAlpha(&plt1, 0.5f);
	njSetLightAngle(&plt1, NJM_RAD_ANG(NJD_PI/24.f), NJM_RAD_ANG(NJD_PI/6.f));
	plt2 = plt1;
	plt3 = plt1;
	plt4 = plt1;

	njSetLightColor(&splt, 
					spot_color[spot_col_cnt].r,
					spot_color[spot_col_cnt].g, 
					spot_color[spot_col_cnt].b);
	njSetLightDirection(&splt,0.f, -1.f, 0.f);
	njSetLightIntensity(&splt, 0.5f, 0.6f, 0.0f);
	njSetLightAlpha(&splt, 1.f);
	njSetLightAngle(&splt, NJM_RAD_ANG(NJD_PI/12.f), NJM_RAD_ANG(NJD_PI/6.f));
	njSetLightRange(&splt, 6.f, 10.f);

	njSetUserLight(&ult,UserLight);
	njSetLightDirection(&ult, 0.f, -1.f, 0.f);
	njSetLightIntensity(&ult, 0.f, 1.0f, 0.f);
}

void
DeleteLights(void)
{
	/********************************/
	/*		Deleting Lights			*/
	/********************************/
	njDeleteLight(&dlt);
	njDeleteLight(&plt1);
	njDeleteLight(&plt2);
	njDeleteLight(&plt3);
	njDeleteLight(&plt4);
	njDeleteLight(&splt);
	njDeleteLight(&ult);
}

void
LightOn(void)
{
	if (!lt_num[0]) njLightOn(&dlt);
	if (!lt_num[1]) njLightOn(&plt1);
	if (!lt_num[2]) njLightOn(&plt2);
	if (!lt_num[3]) njLightOn(&plt3);
	if (!lt_num[4]) njLightOn(&plt4);
	if (!lt_num[5]) njLightOn(&splt);
	if (!lt_num[6]) njLightOn(&ult);
}

void
LightOff(void)
{
	if (!lt_num[0]) njLightOff(&dlt);
	if (!lt_num[1]) njLightOff(&plt1);
	if (!lt_num[2]) njLightOff(&plt2);
	if (!lt_num[3]) njLightOff(&plt3);
	if (!lt_num[4]) njLightOff(&plt4);
	if (!lt_num[5]) njLightOff(&splt);
	if (!lt_num[6]) njLightOff(&ult);
}

Uint32
ChangeColor(NJS_ARGB* ptr_argb)
{
	Uint32 a, r, g, b;

	a = ((Uint32)(ptr_argb->a * 255)) & 0x000000ff;
	r = ((Uint32)(ptr_argb->r * 255)) & 0x000000ff;
	g = ((Uint32)(ptr_argb->g * 255)) & 0x000000ff;
	b = ((Uint32)(ptr_argb->b * 255)) & 0x000000ff;

	return (a << 24)|(r << 16)|(g << 8)|b;
}

void
DrawLightPoint(NJS_LIGHT* ptr_light)
{
	Int		i = 6;
	NJS_POINT3COL	pcol, pcol2;
	NJS_POINT3		p[6], p2[6];
	NJS_COLOR		col[6], col2[6];

	pcol.p = p;
	pcol.col = col;
	pcol2.p = p2;
	pcol2.col = col2;

	pcol.col[0].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[0].x = NJM_LIGHT_INIT_POINT(ptr_light).x - _LIGHT_DELTA;
	pcol.p[0].y = NJM_LIGHT_INIT_POINT(ptr_light).y;
	pcol.p[0].z = NJM_LIGHT_INIT_POINT(ptr_light).z;

	pcol.col[1].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[1].x = NJM_LIGHT_INIT_POINT(ptr_light).x + _LIGHT_DELTA;
	pcol.p[1].y = NJM_LIGHT_INIT_POINT(ptr_light).y;
	pcol.p[1].z = NJM_LIGHT_INIT_POINT(ptr_light).z;

	pcol.col[2].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[2].x = NJM_LIGHT_INIT_POINT(ptr_light).x;
	pcol.p[2].y = NJM_LIGHT_INIT_POINT(ptr_light).y - _LIGHT_DELTA;
	pcol.p[2].z = NJM_LIGHT_INIT_POINT(ptr_light).z;

	pcol.col[3].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[3].x = NJM_LIGHT_INIT_POINT(ptr_light).x;
	pcol.p[3].y = NJM_LIGHT_INIT_POINT(ptr_light).y + _LIGHT_DELTA;
	pcol.p[3].z = NJM_LIGHT_INIT_POINT(ptr_light).z;

	pcol.col[4].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[4].x = NJM_LIGHT_INIT_POINT(ptr_light).x;
	pcol.p[4].y = NJM_LIGHT_INIT_POINT(ptr_light).y;
	pcol.p[4].z = NJM_LIGHT_INIT_POINT(ptr_light).z - _LIGHT_DELTA;

	pcol.col[5].color = ChangeColor(&NJM_LIGHT_COLOR(ptr_light));
	pcol.p[5].x = NJM_LIGHT_INIT_POINT(ptr_light).x;
	pcol.p[5].y = NJM_LIGHT_INIT_POINT(ptr_light).y;
	pcol.p[5].z = NJM_LIGHT_INIT_POINT(ptr_light).z + _LIGHT_DELTA;

	njClearMatrix();
	while (i){
		i--;
		pcol2.col[i] = pcol.col[i];
		njCalcPoint(&NJM_LIGHT_MATRIX(ptr_light), &pcol.p[i], &pcol2.p[i]);
	}

	njDrawLine3D(&pcol2, 3, NJD_DRAW_NORMAL);
}

void
SetLightMatrix(void)
{
	rad = 0.01f * gcount;
	gcount++;
	
	if (rad >= NJD_2PI) {
		rad -= NJD_2PI;
	} else if (rad < 0.f) {
		rad += NJD_2PI;
	}

	njUnitLightMatrix(&dlt);
	njRotateLightX(&dlt, - NJM_RAD_ANG( NJD_PI * 0.25));

	njUnitLightMatrix(&plt1);
	njTranslateLight(&plt1, _LIGHT_X + _LIGHT_WX, _LIGHT_Y, _LIGHT_Z + _LIGHT_WZ);
	if (lt_num[1] != 0)	DrawLightPoint(&plt1);

	njUnitLightMatrix(&plt2);
	njTranslateLight(&plt2, _LIGHT_X - _LIGHT_WX, _LIGHT_Y, _LIGHT_Z + _LIGHT_WZ);
	if (lt_num[2] != 0)	DrawLightPoint(&plt2);

	njUnitLightMatrix(&plt3);
	njTranslateLight(&plt3, _LIGHT_X - _LIGHT_WX, _LIGHT_Y, _LIGHT_Z - _LIGHT_WZ);
	if (lt_num[3] != 0)	DrawLightPoint(&plt3);

	njUnitLightMatrix(&plt4);
	njTranslateLight(&plt4, _LIGHT_X + _LIGHT_WX, _LIGHT_Y, _LIGHT_Z - _LIGHT_WZ);
	if (lt_num[4] != 0)	DrawLightPoint(&plt4);

	njUnitLightMatrix(&splt);
	njTranslateLight(&splt,  _LIGHT_X, _LIGHT_Y + 0.5f, _LIGHT_Z );
	njRotateLightX( &splt, NJM_RAD_ANG(- rad * 10));
	if (lt_num[5] != 0)	DrawLightPoint(&splt);
}

void
CarMotion(void)
{
	car_motion += _CAR_ROT_STEP;
	njTranslate( NULL, _MODEL_X, _MODEL_Y, _MODEL_Z );
	njRotateY( NULL, (Angle)car_motion);
}

Int
Keys(void)
{
	Uint8 *cdata;
	Uint8 i;
	NJS_PERIPHERAL	*ch;

	ch = njGetPeripheral(NJD_PORT_SYSKEYBOARD);
	cdata = ch->extend;

	/*VK_ESCAPE*/
	if (cdata[0x1b]&0x80)	return 0;

	/*0-9,A-Z*/
	for (i = 0x30; i <= 0x5a; i++) {
		if (cdata[i]&0x80) break;
	}

	if (i == old_key) return 1;
	else old_key = i;

	switch(i)
	{
	case '0':	lt_num[0] ^= 1;		break;
	case '1':	lt_num[1] ^= 1;		break;
	case '2':	lt_num[2] ^= 1;		break;
	case '3':	lt_num[3] ^= 1;		break;
	case '4':	lt_num[4] ^= 1;		break;
	case '5':	lt_num[5] ^= 1;		break;
	case '6':	lt_num[6] ^= 1;		break;
	case 'A':
		lt_num[0] = 1;
		lt_num[1] = 1;
		lt_num[2] = 1;
		lt_num[3] = 1;
		lt_num[4] = 1;
		lt_num[5] = 1;
		lt_num[6] = 1;
		break;
	case 'C':
		attribute_cnt++;
		if (attribute_cnt > 2) attribute_cnt = 0;

		DeleteLights();
		SetLights();
		break;
	case 'D':
		dir_col_cnt++;
		if (dir_col_cnt > 1) dir_col_cnt = 0;

		njSetLightColor(&dlt, 
						dir_color[dir_col_cnt].r,
						dir_color[dir_col_cnt].g, 
						dir_color[dir_col_cnt].b);
		break;
	case 'H':
		help_cnt++;
		if (help_cnt > 1) help_cnt = 0;
		break;
	case 'L':
		lmp_cnt++;
		if (lmp_cnt > 3) lmp_cnt = 0;

		DeleteLights();
		SetLights();
		break;
	case 'N':
		lt_num[0] = 0;
		lt_num[1] = 0;
		lt_num[2] = 0;
		lt_num[3] = 0;
		lt_num[4] = 0;
		lt_num[5] = 0;
		lt_num[6] = 0;
		break;
	case 'P':
		pnt_col_cnt++;
		if (pnt_col_cnt > 5) pnt_col_cnt = 0;
		njSetLightColor(&plt1, 
						pnt_color[pnt_col_cnt].r,
						pnt_color[pnt_col_cnt].g, 
						pnt_color[pnt_col_cnt].b);
		njSetLightColor(&plt2,
						pnt_color[pnt_col_cnt].r,
						pnt_color[pnt_col_cnt].g, 
						pnt_color[pnt_col_cnt].b);
		njSetLightColor(&plt3,
						pnt_color[pnt_col_cnt].r,
						pnt_color[pnt_col_cnt].g, 
						pnt_color[pnt_col_cnt].b);
		njSetLightColor(&plt4,
						pnt_color[pnt_col_cnt].r,
						pnt_color[pnt_col_cnt].g, 
						pnt_color[pnt_col_cnt].b);
		break;
	case 'S':
		spot_col_cnt++;
		if (spot_col_cnt > 3) spot_col_cnt = 0;

		njSetLightColor(&splt, 
						spot_color[spot_col_cnt].r,
						spot_color[spot_col_cnt].g, 
						spot_color[spot_col_cnt].b);
		break;
	}
	return 1;
}

void njUserInit(void)
{
	njInitSystem( NJD_RESOLUTION_VGA, NJD_FRAMEBUFFER_MODE_RGB555, 1 );
	njInitVertexBuffer( 500000, 0, 500000, 0 );
	njInit3D( vbuf, 4096 );
	njInitMatrix( matrix, 128, 1 );
	njInitView( &view );
	njSetView( &view );

	njRotateViewX( &view, NJM_RAD_ANG(_VIEW_DIRECT));
	njTranslateView( &view, -_MODEL_X, -_MODEL_Y, -_MODEL_Z );
	njRotateViewY( &view, NJM_RAD_ANG(_VIEW_ROT_Y) );
	njTranslateView( &view, _MODEL_X, _MODEL_Y, _MODEL_Z );

	njInitTexture( tex, 256 );
	njSetTexturePath( PATH );
	njLoadTexture( &TEXLIST );
	njSetTexture( &TEXLIST );

	njControl3D(
		NJD_CONTROL_3D_CONSTANT_ATTR |
		NJD_CONTROL_3D_CONSTANT_TEXTURE_MATERIAL
	);
	njSetBackColor( 0xff000000,0xff000000,0xff0000ff );

	njSetConstantAttr( 0xffffffff, NJD_FILTER_BILINEAR|NJD_FLAG_USE_ANISOTROPIC );

/********************************/
	SetLights();
/********************************/
}

Sint32	rx,ry,rz;
NJS_PERIPHERAL *per;
Float	x,y,z=0.f;
Sint32 njUserMain(void)
{
	Uint8 c0[] = "h to HELP";
	Uint8 c1[] = "0 - 6 to TURN ON or OFF A LIGHT";
	Uint8 c2[] = "a     to TURN ON ALL LIGHTS";
	Uint8 c3[] = "n     to TURN OFF ALL LIGHTS";
	Uint8 c4[] = "p     to CHANGE POINT LIGHTS COLOR";
	Uint8 c5[] = "d     to CHANGE A DIRECT. LIGHT COLOR";
	Uint8 c6[] = "s     to CHANGE A SPOT LIGHT COLOR";
	Uint8 c7[] = "c     to CHANGE POINT LIGHTS ATTR.";
	Uint8 c8[] = "l     to CHANGE POINT LIGHTS";
	Uint8 p00[] = "0 :OFF  (DIRECT. LIGHT)";
	Uint8 p10[] = "1 :OFF ";
	Uint8 p20[] = "2 :OFF ";
	Uint8 p30[] = "3 :OFF ";
	Uint8 p40[] = "4 :OFF ";
	Uint8 p50[] = "5 :OFF  (SPOT LIGHT)";
	Uint8 p60[] = "6 :OFF  (USER LIGHT)";
	Uint8 p01[] = "0 :ON   (DIRECT. LIGHT)";
	Uint8 p11[] = "1 :ON " ;
	Uint8 p21[] = "2 :ON " ;
	Uint8 p31[] = "3 :ON " ;
	Uint8 p41[] = "4 :ON " ;
	Uint8 p51[] = "5 :ON   (SPOT LIGHT)";
	Uint8 p61[] = "6 :ON   (USER LIGHT)";
	Uint8 a0[] = "(NORMAL - ";
	Uint8 a1[] = "(SIMPLE - ";
	Uint8 a2[] = "(BLOCK  - ";
	Uint8 l0[] = "POINT LIGHT ONLY)";
	Uint8 l1[] = "LAMBERT LIGHT)";
	Uint8 l2[] = "POINT LIGHT WITH SPECULAR)";
	Uint8 l3[] = "PHONG LIGHT)";

	njClearMatrix();
/********************************/
	SetLightMatrix();
	LightOff();
/********************************/

	CarMotion();
	njDrawObject( CAR );
/********************************/
	LightOn();
/********************************/

	if (help_cnt) {
		njPrintC(NJM_LOCATION(40,45), c1);
		njPrintC(NJM_LOCATION(40,46), c2);
		njPrintC(NJM_LOCATION(40,47), c3);
		njPrintC(NJM_LOCATION(40,48), c4);
		njPrintC(NJM_LOCATION(40,49), c5);
		njPrintC(NJM_LOCATION(40,50), c6);
		njPrintC(NJM_LOCATION(40,51), c7);
		njPrintC(NJM_LOCATION(40,52), c8);

		if (lt_num[0] == 0) njPrintC(NJM_LOCATION(4,5), p00);
		else				njPrintC(NJM_LOCATION(4,5), p01);
		if (lt_num[1] == 0) njPrintC(NJM_LOCATION(4,6), p10);
		else				njPrintC(NJM_LOCATION(4,6), p11);
		if (lt_num[2] == 0) njPrintC(NJM_LOCATION(4,7), p20);
		else				njPrintC(NJM_LOCATION(4,7), p21);
		if (lt_num[3] == 0) njPrintC(NJM_LOCATION(4,8), p30);
		else				njPrintC(NJM_LOCATION(4,8), p31);
		if (lt_num[4] == 0) njPrintC(NJM_LOCATION(4,9), p40);
		else				njPrintC(NJM_LOCATION(4,9), p41);
		if (lt_num[5] == 0) njPrintC(NJM_LOCATION(4,10), p50);
		else				njPrintC(NJM_LOCATION(4,10), p51);
		if (lt_num[6] == 0) njPrintC(NJM_LOCATION(4,11), p60);
		else				njPrintC(NJM_LOCATION(4,11), p61);

		switch (attribute_cnt)
		{
		case 0:
			njPrintC(NJM_LOCATION(12,6), a0);
			njPrintC(NJM_LOCATION(12,7), a0);
			njPrintC(NJM_LOCATION(12,8), a0);
			njPrintC(NJM_LOCATION(12,9), a0);
			break;
		case 1:
			njPrintC(NJM_LOCATION(12,6), a1);
			njPrintC(NJM_LOCATION(12,7), a1);
			njPrintC(NJM_LOCATION(12,8), a1);
			njPrintC(NJM_LOCATION(12,9), a1);
			break;
		case 2:
			njPrintC(NJM_LOCATION(12,6), a2);
			njPrintC(NJM_LOCATION(12,7), a2);
			njPrintC(NJM_LOCATION(12,8), a2);
			njPrintC(NJM_LOCATION(12,9), a2);
			break;
		}

		switch (lmp_cnt)
		{
		case 0:
			njPrintC(NJM_LOCATION(20,6), l0);
			njPrintC(NJM_LOCATION(20,7), l0);
			njPrintC(NJM_LOCATION(20,8), l0);
			njPrintC(NJM_LOCATION(20,9), l0);
			break;
		case 1:
			njPrintC(NJM_LOCATION(20,6), l1);
			njPrintC(NJM_LOCATION(20,7), l1);
			njPrintC(NJM_LOCATION(20,8), l1);
			njPrintC(NJM_LOCATION(20,9), l1);
			break;
		case 2:
			njPrintC(NJM_LOCATION(20,6), l2);
			njPrintC(NJM_LOCATION(20,7), l2);
			njPrintC(NJM_LOCATION(20,8), l2);
			njPrintC(NJM_LOCATION(20,9), l2);
			break;
		case 3:
			njPrintC(NJM_LOCATION(20,6), l3);
			njPrintC(NJM_LOCATION(20,7), l3);
			njPrintC(NJM_LOCATION(20,8), l3);
			njPrintC(NJM_LOCATION(20,9), l3);
			break;
		}

	} else {
		njPrintC(NJM_LOCATION(4,5), c0);
	}

/********************************/
	if (Keys() != 1) return NJD_USER_EXIT;
/********************************/

	return NJD_USER_CONTINUE;
}

void njUserExit(void)
{
	njExitTexture();
	njExitSystem();
}
