/*--
*******************************************************************************
   Name     : kmCyberK
   Title    : KAMUI test program "CyberK" from VL
   Author   : VideoLogic Carlos Sarria / NEC Software Takeshi Muto
   Created  : April 1997 by VideoLogic
   Modified : Octover 30. 1997 by Takeshi Muto for KAMUI
              April   15. 1998 by Takeshi Muto for KAMUI SET5
   Description : 
   Copyright : 1997 by VideoLogic Limited. All rights reserved.
********************************************************************************
--*/
/*
#define		_X86_
*/
/* _X86_ flag for win95 : SET2 */

#define		FRAMES			(1000000)				// rendering frame number

#define		SUPERSAMPLE		TRUE
/*#define		SUPERSAMPLE		FALSE*/
/* Super sample filter mode */

#define		FILTERMODE	KM_BILINEAR
/*#define		FILTERMODE	KM_POINT_SAMPLE*/
#define		FOGMODE		KM_FOGTABLE
/*#define		FOGMODE		KM_NOFOG*/

#define		_DISPLAY_SKY_
/* if defined then display sky plane */

#define		_DISPLAY_TRANS_
/* if defined then display ground trans plane */

#define		_DISPLAY_STRING_
/* if defined then display strings on screen */

#define		_DISP_PERFORMANCE_
/* Display performance : for windows */

/* Set Display Mode */
#define NTSC 1

#include	<math.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<float.h>

#include	<Shinobi.h>

/*--
#include	<io.h>
#include	<FCNTL.H>
--*/

#if defined(_X86_)
	#include	<time.h>
	#include	<windows.h>
#endif

#include	"kamui.h"				/* for Kamui Call */
#include	"dispstr.h"				/* for DisplayString */

extern const unsigned char cyberk[];			/* texture data */
extern const unsigned char cyground[];
extern const unsigned char cysky[];


#if defined(_DISP_PERFORMANCE_)
#if defined(_X86_)
#else
	#include    "QPF.H"                 /* for QueryPerformance */
#endif
#endif

#define NK  (10)					/* Number of cyber kangaloo */
#define LAP (7)
#define TLP (0.3f)

#define SHADOW FALSE

#pragma warning (disable : 4244)  /* Float to Double Conversion Warning */
#pragma warning (disable : 4056)

#define PI (3.142f)

#define	RGBColour(r, g, b)	((KMUINT32) (((r) << 16) | ((g) << 8) | (b)))
#define	RGBA(r, g, b, a)	((KMUINT32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))

#define GRV		(-9.81)
#define HIGH	(30.0)

/* Macros for kamui */
#define		GetRED(col)			((KMFLOAT) ( ((col) & 0x00ff0000) >> 16 ) / 256.0f)
#define		GetGREEN(col)		((KMFLOAT) ( ((col) & 0x0000ff00) >>  8 ) / 256.0f)
#define		GetBLUE(col)		((KMFLOAT) ( ((col) & 0x000000ff)       ) / 256.0f)
#define		GetALPHA(col)		((KMFLOAT) ( ((col) & 0xff000000) >> 24 ) / 256.0f)

/* SGLŒÝŠ·TYPE */
typedef	KMUINT32	sgl_uint32;		/* type of sgl_uint32 */
typedef float		sgl_vector[3];	/* type of sgl_vector */
typedef float		sgl_2d_vec[2];	/* type of sgl_2d_vec */
typedef float		sgl_colour[3];	/* type of sgl_colour */
/*--
// ---------
// SGLVERTEX
// ---------
// This structure is currently physically equivalent to Direct3D's D3DTLVERTEX
// (so one can be cast to the other), with the exception that Direct3D's u and
// v values must be multiplied by the 1/w value.  RAVE vertices already contain
// u/w and v/w.
--*/
typedef struct tagSGLVERTEX
{
	/* Projected screen coordinates: */
	float		fX;		/* 0 <= fX < screen width (up to 1024) */
	float		fY;		/* 0 <= fY < screen height (up to 1024) */
	float		fZ;		/* 0.01 <= fZ <= 1, where 1 is infinite distance away */
	/* 1/w for the perspective projection (should be set to 1.0/fZ; fZ is actually ignored): */
	float		fInvW;
	KMUINT32	u32Colour;			/* Material colour (D3DCOLOR format):	*/
	KMUINT32	u32Specular;		/* Specular colour (D3DCOLOR format):	*/
	float		fUOverW, fVOverW;	/* Texture coordinates:					*/
} SGLVERTEX, *PSGLVERTEX;

/****************************************************************************/
/**	Valuables for KAMUI *****************************************************/
/****************************************************************************/
	KMSTATUS			status;					/* return status of KAMUI API */
	KMVERSIONINFO		VersionInfo;			/* KAMUI Version information */
	KMSURFACEDESC		PrimarySurfaceDesc;		/* Primary frame buffer */
	KMSURFACEDESC		BackSurfaceDesc;		/* Back-buffer frame buffer */
	KMSURFACEDESC		CyberKTex;				/* texture surface */
	KMSURFACEDESC		GroundTex;				/* texture surface */
	KMSURFACEDESC		SkyTex;					/* texture surface */
	KMVERTEXBUFFDESC	VertexBufferDesc;		/* Vertex-buffer */
	KMVERTEXCONTEXT		VertexContextGround;	/* Vertex context */
	KMVERTEXCONTEXT		VertexContextSky;		/* Vertex context */
	KMVERTEXCONTEXT		VertexContextCyberK;	/* Vertex context */


	int			frame;				
	int			frame_2 = 0;		
#if defined(_DISP_PERFORMANCE_)
	int			pcount_f;			
	double		nFPS;				
	double		aFPS;				
	double		MxFPS;				
	double		MnFPS;				
	__int64 	Time3i;				
	__int64		freqi;				
	double		freq;				
	double		Time3;				
	double		maxTime = 0.00001;	
	double		minTime = 99999;	
	double		OldTime3;		
	double		nowTime;			
	double		totalTime	= 0;	
	double		aveTime;			
#if defined(_X86_)
	time_t		start_time;			
#endif
#endif

/*------------------------------- Global Variables -----------------------------------*/
/*--
//static sgl_colour 	White   = {0.9f,0.9f,0.9f};
//static sgl_colour 	Black   = {0.0f,0.0f,0.0f};
//static sgl_colour 	Blue    = {0.1f,0.4f,0.6f};

//static sgl_colour 	Yellow  = {0.7f,0.7f,0.3f};

//static sgl_colour	Red     = {0.8f,0.1f,0.1f};
//static sgl_colour	Grey    = {0.5f,0.5f,0.5f};


//int Device;

//int GroundTex, SkyTex, CyberKTex;
//sgl_intermediate_map BuffTex[5];

//int frame, Movement;
--*/
int			Movement;
int			NumMax[NK];
int			LongK[NK];
int			StateK[NK];
int			TimerK[NK];
sgl_vector	RotVecK[NK];
sgl_vector	PathK[NK][200];
float		AngK[NK];
float		MovAngK[NK];

sgl_vector	p1[NK]={0.0f, 0.0f, 200.0f};
sgl_vector	p2[NK]={0.0f, 0.0f, 200.0f};
float		Sig[2] ={1.0f, -1.0f};
float		NewAng[50];
float		CamFocus = 600.0f;
/* SGLCONTEXT SGLContext; */

SGLVERTEX	PrismVect[3][20];
SGLVERTEX	TopVect[3][10];
SGLVERTEX	BotVect[3][20];
SGLVERTEX	ReflectVect[3][20];
sgl_vector	Prism3DVect [3][20];
 
int PrismFaces[][4] = { 
           {0,2,1,9},     {8,3,2,9},     {7,4,3,8},     {6,5,4,7},
           {0,1,11,10},   {1,2,12,11},   {2,3,13,12},   {3,4,14,13},   {4,5,15,14},
           {5,6,16,15},   {6,7,17,16},   {7,8,18,17},   {8,9,19,18},   {9,0,10,19},
           {10,12,11,19}, {18,13,12,19}, {17,14,13,18}, {16,15,14,17} };

sgl_uint32	PrismCol[NK][10];    

/* PCX : SGL-Direct fog table */
static KMUINT32 PCXFogTable[]={
	0x000000ff,	0x000000fe,	0x000000fd,	0x000000fb,	0x000000fa,	0x000000f9,	0x000000f7,	0x000000f6,
	0x000000f5,	0x000000f3,	0x000000f2,	0x000000f1,	0x000000ef,	0x000000ee,	0x000000ed,	0x000000ec,
	0x000000ea,	0x000000e9,	0x000000e8,	0x000000e6,	0x000000e5,	0x000000e4,	0x000000e3,	0x000000e2,
	0x000000e0,	0x000000df,	0x000000de,	0x000000dd,	0x000000db,	0x000000da,	0x000000d9,	0x000000d8,
	0x000000d7,	0x000000d6,	0x000000d4,	0x000000d3,	0x000000d2,	0x000000d1,	0x000000d0,	0x000000cf,
	0x000000ce,	0x000000cd,	0x000000cb,	0x000000ca,	0x000000c9,	0x000000c8,	0x000000c7,	0x000000c6,
	0x000000c5,	0x000000c4,	0x000000c3,	0x000000c2,	0x000000c1,	0x000000c0,	0x000000bf,	0x000000be,
	0x000000bd,	0x000000bc,	0x000000ba,	0x000000b9,	0x000000b8,	0x000000b7,	0x000000b6,	0x000000b6,
	0x000000b5,	0x000000b4,	0x000000b3,	0x000000b2,	0x000000b1,	0x000000b0,	0x000000af,	0x000000ae,
	0x000000ad,	0x000000ac,	0x000000ab,	0x000000aa,	0x000000a9,	0x000000a8,	0x000000a7,	0x000000a6,
	0x000000a5,	0x000000a5,	0x000000a4,	0x000000a3,	0x000000a2,	0x000000a1,	0x000000a0,	0x0000009f,
	0x0000009e,	0x0000009e,	0x0000009d,	0x0000009c,	0x0000009b,	0x0000009a,	0x00000099,	0x00000099,
	0x00000098,	0x00000097,	0x00000096,	0x00000095,	0x00000094,	0x00000094,	0x00000093,	0x00000092,
	0x00000091,	0x00000090,	0x00000090,	0x0000008f,	0x0000008e,	0x0000008d,	0x0000008d,	0x0000008c,
	0x0000008b,	0x0000008a,	0x0000008a,	0x00000089,	0x00000088,	0x00000087,	0x00000087,	0x00000086,
	0x00000085,	0x00000084,	0x00000084,	0x00000083,	0x00000082,	0x00000082,	0x00000081,	0x00000080
};

/*----------------------------  Routines Prototypes ---------------------------------*/

void SetupTextures   (void),
     SetupContext    (void),
     SetupPrism      (void);

void DrawGround      (void),
     DrawSky         (void),
     CreatePath      (int),
     NewPoint        (int),
     DrawCyberK      (int, int);

void Perspect (const sgl_vector, SGLVERTEX *);

/****************************************************************************/
/**	Check KAMUI function status *********************************************/
/****************************************************************************/
void	Check_Status(KMSTATUS status, char * func)
{
	switch(status) {
	case KMSTATUS_SUCCESS:
		/* No message is displayed when SUCCESS */
		break;
	case KMSTATUS_INVALID_DISPLAY_MODE:
		PRINTOUT(("%s:KMSTATUS_INVALID_DISPLAY_MODE\n",func)); break;
	case KMSTATUS_INVALID_VIDEO_MODE:
		PRINTOUT(("%s:KMSTATUS_INVALID_VIDEO_MODE\n",func)); break;
	case KMSTATUS_NOT_ENOUGH_MEMORY:
		PRINTOUT(("%s:KMSTATUS_NOT_ENOUGH_MEMORY\n",func)); break;
	case KMSTATUS_INVALID_TEXTURE_TYPE:
		PRINTOUT(("%s:KMSTATUS_INVALID_TEXTURE_TYPE\n",func)); break;
	case KMSTATUS_INVALID_MIPMAPED_TEXTURE:
		PRINTOUT(("%s:KMSTATUS_INVALID_MIPMAPED_TEXTURE\n",func)); break;
	case KMSTATUS_CANT_FLIP_SURFACE:
		PRINTOUT(("%s:KMSTATUS_CANT_FLIP_SURFACE\n",func)); break;
	case KMSTATUS_INVALID_ADDRESS:
		PRINTOUT(("%s:KMSTATUS_INVALID_ADDRESS\n",func)); break;
	case KMSTATUS_HARDWARE_NOT_PRESENTED:
		PRINTOUT(("%s:KMSTATUS_HARDWARE_NOT_PRESENTED\n",func)); break;
	case KMSTATUS_INVALID_SETTING:
		PRINTOUT(("%s:KMSTATUS_INVALID_SETTING\n",func)); break;
	case KMSTATUS_INVALID_VERTEX_TYPE:
		PRINTOUT(("%s:KMSTATUS_INVALID_VERTEX_TYPE\n",func)); break;
	case KMSTATUS_NOT_IMPLEMENTED:
		PRINTOUT(("%s:KMSTATUS_NOT_IMPREMENTED\n",func)); break;
	case KMSTATUS_INVALID_PARAMETER:
		PRINTOUT(("%s:KMSTATUS_INVALID_PARAMETER\n",func)); break;
	default:
		PRINTOUT(("%s:???Undefined status : %d\n", func, status));
		break;
	}
}

/****************************************************************************/
/**	Background surface setting **********************************************/
/****************************************************************************/
void	InitBackGround(void)
{
	KMSTATUS			status;
	KMVERTEXCONTEXT		BackVertexContext;		/* Vertex context */
	KMVERTEX_01			BV[3];					/* pointer to Vertex */
	PVOID				pBV[3];					/* pointer to Vertex */

	/* Clear VertexContext */
	memset(&BackVertexContext,0,sizeof(KMVERTEXCONTEXT));

	/* Setup VertexContext */
	BackVertexContext.RenderState	= KM_DEPTHMODE  		| KM_CULLINGMODE				/* ISP/TSP IW */
									| KM_SCREENCOORDINATION	| KM_SHADINGMODE
									| KM_MODIFIER 			| KM_ZWRITEDISABLE				/* TSP CW */
									| KM_SRCBLENDINGMODE
									| KM_SRCSELECT			| KM_DSTSELECT
									| KM_FOGMODE			| KM_USESPECULAR
									| KM_USEALPHA			| KM_IGNORETEXTUREALPHA
									| KM_FLIPUV 			| KM_CLAMPUV 
									| KM_FILTERMODE			| KM_SUPERSAMPLE
									| KM_MIPMAPDADJUST 		| KM_TEXTURESHADINGMODE
									| KM_PARAMTYPE 			| KM_LISTTYPE 					/* Param CW */
									| KM_COLORTYPE			| KM_USESPECULAR
									| KM_UVFORMAT;

	/* for ParameterControlWord  */
	BackVertexContext.ParamType				= KM_POLYGON;
	BackVertexContext.ListType				= KM_OPAQUE_POLYGON;
	BackVertexContext.ColorType				= KM_FLOATINGCOLOR;
	BackVertexContext.bUseSpecular			= FALSE;
	BackVertexContext.UVFormat				= KM_32BITUV;

	/* for ISP/TSP InstructionWord  */
	BackVertexContext.DepthMode				= KM_GREATER;
	BackVertexContext.CullingMode			= KM_NOCULLING;
	BackVertexContext.ScreenCoordination	= KM_SCREEN;
	BackVertexContext.ShadingMode			= KM_NOTEXTUREGOURAUD;
	BackVertexContext.SelectModifier		= KM_NOMODIFIER;
	BackVertexContext.bZWriteDisable		= FALSE;			/* not effective on ARC1 */

	/* for TSP ControlWord  */
	BackVertexContext.SRCBlendingMode		= KM_ONE;
/*--
//	BackVertexContext.DSTBlendingMode		= KM_ZERO;	// must not set this parameter on background plane
--*/
	BackVertexContext.bSRCSel				= FALSE;			/* not effective on ARC1 */
	BackVertexContext.bDSTSel				= FALSE;			/* not effective on ARC1 */
	BackVertexContext.FogMode				= FOGMODE;			/* 11 is reserved */
	BackVertexContext.bUseSpecular			= FALSE;
	BackVertexContext.bUseAlpha				= FALSE;
	BackVertexContext.ClampUV				= KM_NOCLAMP;
	BackVertexContext.FilterMode			= FILTERMODE;
	BackVertexContext.bSuperSample			= FALSE;
	BackVertexContext.MipMapAdjust			= 0x00000004;		/* D=1.00 */
	BackVertexContext.TextureShadingMode	= KM_MODULATE;
	
	/* for Texture ControlBit */

	/* No effect on ARC1 */
	BackVertexContext.bColorClamp			= FALSE;
	BackVertexContext.PaletteBank			= 0;

	/* for GlobalColorData */
	BackVertexContext.fFaceColorAlpha		= 1.0f;		/* Face Color Alpha */
	BackVertexContext.fFaceColorRed			= 1.0f;		/* Face Color Red */
	BackVertexContext.fFaceColorGreen		= 1.0f;		/* Face Color Green */
	BackVertexContext.fFaceColorBlue		= 1.0f;		/* Face Color Blue */
	BackVertexContext.fOffsetColorAlpha		= 1.0f;		/* Specular Color Alpha */
	BackVertexContext.fOffsetColorRed		= 1.0f;		/* Specular Color Red */
	BackVertexContext.fOffsetColorGreen		= 1.0f;		/* Specular Color Green */
	BackVertexContext.fOffsetColorBlue		= 1.0f;		/* Specular Color Blue */

	status = kmProcessVertexRenderState(&BackVertexContext);
	Check_Status(status, "kmProcessVertexRenderState");
	status = kmSetBackGroundRenderState(&BackVertexContext);
	Check_Status(status, "kmSetBackGroundRenderState");

	/*-----------------------------------------------------------------------------------*/
	/* set VERTEX DATA */

	/* Vertex #1 */
	BV[0].ParamControlWord	= KM_VERTEXPARAM_NORMAL;
	BV[0].fX				=  2.0f;
	BV[0].fY				= 260.0f;
#if defined(_STRICT_UNION_)
	BV[0].u.fZ				=  0.0001f;
#else
	BV[0].fZ				=  0.0001f;
#endif
	BV[0].fBaseAlpha		=  1.0f;
	BV[0].fBaseRed			=  0.0f;
	BV[0].fBaseGreen		=  0.0f;
	BV[0].fBaseBlue			=  0.5f;

	/* Vertex #2 */
	BV[1].ParamControlWord	= KM_VERTEXPARAM_NORMAL;
	BV[1].fX				= 150.0f;
	BV[1].fY				=  2.0f;
#if defined(_STRICT_UNION_)
	BV[1].u.fZ				=  0.0001f;
#else
	BV[1].fZ				=  0.0001f;
#endif
	BV[1].fBaseAlpha		=  1.0f;
	BV[1].fBaseRed			=  0.0f;
	BV[1].fBaseGreen		=  0.0f;
	BV[1].fBaseBlue			=  0.5f;

	/* Vertex #3 */
	BV[2].ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
	BV[2].fX				= 560.0f;
	BV[2].fY				= 260.0f;
#if defined(_STRICT_UNION_)
	BV[2].u.fZ				=  0.0001f;
#else
	BV[2].fZ				=  0.0001f;
#endif
	BV[2].fBaseAlpha		=  1.0f;
	BV[2].fBaseRed			=  0.0f;
	BV[2].fBaseGreen		=  0.0f;
	BV[2].fBaseBlue			=  0.5f;

	pBV[0] = &BV[0];
	pBV[1] = &BV[1];
	pBV[2] = &BV[2];

	/*-----------------------------------------------------------------------------------*/
	/* set VERTEX */
	status = kmSetBackGroundPlane(	pBV,					/* pVertex */
									KM_VERTEXTYPE_01,		/* VertexType */
									sizeof(KMVERTEX_01)		/* StructSize */
									);
	Check_Status(status, "kmSetBackGroundPlane");
}

/****************************************************************************/
/**	kmtri_quads  by T.Hirata ************************************************/
/****************************************************************************/
void 
kmtri_quads (	KMVERTEXBUFFDESC	BufferDesc,
				KMVERTEXCONTEXT		VertexContext,
				int  nNumFaces,
				int  pFaces[][4],
				PSGLVERTEX  pVertices )
{
	KMSTATUS	status;
	int			i;
	KMVERTEX_03	Ver;

	status = kmSetVertexRenderState(&VertexContext);
	Check_Status(status, "kmSetVertexRenderState");

	for(i = 0; i < nNumFaces; i++)
	{
		status = kmStartVertexStrip(&BufferDesc);
		Check_Status(status, "kmStartVertexStrip");

		Ver.ParamControlWord	= KM_VERTEXPARAM_NORMAL;
		Ver.fX					= pVertices[pFaces[i][0]].fX;
		Ver.fY					= pVertices[pFaces[i][0]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][0]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][0]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][0]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][0]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][0]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][0]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");

		Ver.ParamControlWord	= KM_VERTEXPARAM_NORMAL;
		Ver.fX					= pVertices[pFaces[i][1]].fX;
		Ver.fY					= pVertices[pFaces[i][1]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][1]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][1]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][1]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][1]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][1]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][1]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");

		Ver.ParamControlWord	= KM_VERTEXPARAM_NORMAL;
		Ver.fX					= pVertices[pFaces[i][3]].fX;
		Ver.fY					= pVertices[pFaces[i][3]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][3]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][3]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][3]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][3]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][3]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][3]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");

		Ver.ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
		Ver.fX					= pVertices[pFaces[i][2]].fX;
		Ver.fY					= pVertices[pFaces[i][2]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][2]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][2]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][2]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][2]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][2]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][2]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");
/* Display polygon coodinates */
/*--
PRINTOUT(("[1](X,Y) = (%7.3f , %7.3f)\n",pVertices[pFaces[i][0]].fX,pVertices[pFaces[i][0]].fY));
PRINTOUT(("[2](X,Y) = (%7.3f , %7.3f)\n",pVertices[pFaces[i][1]].fX,pVertices[pFaces[i][1]].fY));
PRINTOUT(("[3](X,Y) = (%7.3f , %7.3f)\n",pVertices[pFaces[i][3]].fX,pVertices[pFaces[i][3]].fY));
PRINTOUT(("[4](X,Y) = (%7.3f , %7.3f)\n",pVertices[pFaces[i][2]].fX,pVertices[pFaces[i][2]].fY));
--*/
	}
}

/****************************************************************************/
/**	kmtri_triangles  by T.Hirata ********************************************/
/****************************************************************************/
void 
kmtri_triangles ( KMVERTEXBUFFDESC		BufferDesc,
				  KMVERTEXCONTEXT		VertexContext,
				  int  					nNumFaces,
				  int  					pFaces[][3],
				  PSGLVERTEX  			pVertices )
{
	KMSTATUS	status;
	int			i;
	KMVERTEX_03	Ver;

	status = kmSetVertexRenderState(&VertexContext);
	Check_Status(status, "kmSetVertexRenderState");

	for(i = 0; i < nNumFaces; i++)
	{
		status = kmStartVertexStrip(&BufferDesc);
		Check_Status(status, "kmStartVertexStrip");

		Ver.ParamControlWord	= KM_VERTEXPARAM_NORMAL;
		Ver.fX					= pVertices[pFaces[i][0]].fX;
		Ver.fY					= pVertices[pFaces[i][0]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][0]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][0]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][0]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][0]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][0]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][0]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");

		Ver.ParamControlWord	= KM_VERTEXPARAM_NORMAL;
		Ver.fX					= pVertices[pFaces[i][1]].fX;
		Ver.fY					= pVertices[pFaces[i][1]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][1]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][1]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][1]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][1]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][1]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][1]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");

		Ver.ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
		Ver.fX					= pVertices[pFaces[i][2]].fX;
		Ver.fY					= pVertices[pFaces[i][2]].fY;
#if defined(_STRICT_UNION_)
		Ver.u.fZ				= pVertices[pFaces[i][2]].fInvW;
#else
		Ver.fZ					= pVertices[pFaces[i][2]].fInvW;
#endif
		Ver.fU					= pVertices[pFaces[i][2]].fUOverW;
		Ver.fV					= pVertices[pFaces[i][2]].fVOverW;
		Ver.uBaseRGB.dwPacked	= pVertices[pFaces[i][2]].u32Colour;
		Ver.uOffsetRGB.dwPacked	= pVertices[pFaces[i][2]].u32Specular;
		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_03,sizeof(KMVERTEX3) );
		Check_Status(status, "kmSetVertex");
	}
}

/****************************************************************************/
/**	Initialize Vertex Context ***********************************************/
/****************************************************************************/
void	InitVertexContext(PKMVERTEXCONTEXT pVertexContext)
{
	
	pVertexContext->RenderState	= KM_DEPTHMODE  		| KM_CULLINGMODE
								| KM_SCREENCOORDINATION	| KM_SHADINGMODE
								| KM_MODIFIER 			| KM_ZWRITEDISABLE
								| KM_SRCBLENDINGMODE	| KM_DSTBLENDINGMODE
								| KM_SRCSELECT			| KM_DSTSELECT
								| KM_FOGMODE			| KM_USESPECULAR
								| KM_USEALPHA			| KM_IGNORETEXTUREALPHA
								| KM_FLIPUV 			| KM_CLAMPUV 
								| KM_FILTERMODE			| KM_SUPERSAMPLE
								| KM_MIPMAPDADJUST 		| KM_TEXTURESHADINGMODE
								| KM_PARAMTYPE 			| KM_LISTTYPE
								| KM_COLORTYPE			| KM_USESPECULAR
								| KM_UVFORMAT;

	/* for ParameterControlWord */
	pVertexContext->ParamType			= KM_POLYGON;
	pVertexContext->ListType			= KM_OPAQUE_POLYGON;
	pVertexContext->ColorType			= KM_PACKEDCOLOR;
	pVertexContext->bUseSpecular		= FALSE;
	pVertexContext->UVFormat			= KM_32BITUV;

	/* for ISP/TSP InstructionWord */
	pVertexContext->DepthMode			= KM_GREATER;
	pVertexContext->CullingMode			= KM_NOCULLING;
	pVertexContext->ScreenCoordination	= KM_SCREEN;
/*--
//	pVertexContext->ScreenCoordination	= KM_PROJECTIVE;
--*/
	pVertexContext->ShadingMode			= KM_NOTEXTUREGOURAUD;
	pVertexContext->SelectModifier		= KM_NOMODIFIER;
	pVertexContext->bZWriteDisable		= FALSE;			

	/* for TSP ControlWord */
	pVertexContext->SRCBlendingMode		= KM_ONE;
	pVertexContext->DSTBlendingMode		= KM_ZERO;
	pVertexContext->bSRCSel				= FALSE;			
	pVertexContext->bDSTSel				= FALSE;			
	pVertexContext->FogMode				= FOGMODE;			
	pVertexContext->bUseSpecular		= FALSE;
	pVertexContext->bUseAlpha			= FALSE;
	pVertexContext->FlipUV				= KM_NOFLIP;
	pVertexContext->ClampUV				= KM_NOCLAMP;
	pVertexContext->FilterMode			= FILTERMODE;
	pVertexContext->bSuperSample		= FALSE;
	pVertexContext->MipMapAdjust		= 0x00000004;		/* D=1.00 */
	pVertexContext->TextureShadingMode	= KM_MODULATE;
	
	/* for Texture ControlBit */

	/* No effect on ARC1 */
	pVertexContext->bColorClamp		= FALSE;
	pVertexContext->PaletteBank		= 0;

	/* for GlobalColorData */
	pVertexContext->fFaceColorAlpha		= 1.0f;		/* Face Color Alpha */
	pVertexContext->fFaceColorRed		= 1.0f;		/* Face Color Red */
	pVertexContext->fFaceColorGreen		= 1.0f;		/* Face Color Green */
	pVertexContext->fFaceColorBlue		= 1.0f;		/* Face Color Blue */
	pVertexContext->fOffsetColorAlpha	= 1.0f;		/* Specular Color Alpha */
	pVertexContext->fOffsetColorRed		= 1.0f;		/* Specular Color Red */
	pVertexContext->fOffsetColorGreen	= 1.0f;		/* Specular Color Green */
	pVertexContext->fOffsetColorBlue	= 1.0f;		/* Specular Color Blue */

	kmProcessVertexRenderState(pVertexContext);
}

#if 0
/****************************************************************************/
/**	Load texture ************************************************************/
/****************************************************************************/
PKMDWORD LoadTextureFile(char *filename)
{
	int			hFile;
	long		filelen;
	PKMDWORD	pTexture;

	/* Open input file */
	hFile = _open(filename, _O_RDONLY | _O_BINARY);
	if(hFile != -1) {
		filelen = _filelength(hFile);			/* length of texture file */
		pTexture = (PKMDWORD)malloc(filelen);	/* allocate mainmemory */
		_read(hFile, pTexture, filelen);		/* read in texture file */
		_close(hFile);							/* file close */
		printf("LoadTextureFile: Texture file %s load OK.\n",filename);
	}
	else {
		printf("LoadTextureFile: ??ERROR Can not read texture file %s .\n",filename);
	}
	return pTexture;
}
#endif

/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   SetupScene                                                     */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   Error message or 0                                             */
/*  Globals Used    :   Device                                                         */
/*  Description     :   This routine is used to set SGL device and setup some values.  */
/*                      This routine is called from FRONTEND.C                         */
/*-------------------------------------------------------------------------------------*/
int SetupScene (void)
{
	KMPACKEDARGB   cBorder;
	int i;
	KMPACKEDARGB	fogcol;
	KMFLOAT			FogTable[128];

/*--
//	Device = sgl_create_screen_device (0, 640, 480, sgl_device_16bit, FALSE);
//	if (Device<0) return ERR_CREATE_SCREEN_DEVICE;
--*/

#if	defined(_X86_)
	srand ((unsigned)time(NULL));
#else
	srand ((unsigned)10);
#endif
/*--
//	 SetCursor (NULL);
--*/

	/*-----------------------------------------------------------------------------------*/
	/* Initialize Hardware */
#if NTSC
	sbInitSystem( NJD_RESOLUTION_640x480_NTSCNI, NJD_FRAMEBUFFER_MODE_RGB565, 1 );
#else
	sbInitSystem( NJD_RESOLUTION_VGA, NJD_FRAMEBUFFER_MODE_RGB565, 1 );
#endif

	/* Black Border */
	cBorder.dwPacked	=	0x00000000;
	kmSetBorderColor(cBorder);

	kmGetVersionInfo(&VersionInfo);
	PRINTOUT(("MajorVersion      0x0%08x\n",VersionInfo.kmMajorVersion));
	PRINTOUT(("LocalVersion      0x0%08x\n",VersionInfo.kmLocalVersion));
	PRINTOUT(("kmFrameBufferSize 0x0%08x\n",VersionInfo.kmFrameBufferSize));

	/*-----------------------------------------------------------------------------------*/
	/* Create primary frame buffer surface */
	status = kmCreateFrameBufferSurface(&PrimarySurfaceDesc,	/* pSurfaceDesc */
								640,	/* nWidth */
								480,	/* nHeight */
								FALSE,	/* bStripBuffer */
								FALSE	/* bBufferClear */
								);
	Check_Status(status, "kmCreateFrameBufferSurface(Primary)");

	/*-----------------------------------------------------------------------------------*/
	/* Create backbuffer frame buffer surface */
	status = kmCreateFrameBufferSurface(&BackSurfaceDesc,	/* pSurfaceDesc */
								640,	/* nWidth */
								480,	/* nHeight */
								FALSE,	/* bStripBuffer */
								FALSE	/* bBufferClear */
								);
	Check_Status(status, "kmCreateFrameBufferSurface(Back-buffer)");

	/*-----------------------------------------------------------------------------------*/
	/* Set Latency Model */
	kmChangeLatencyModel(KM_LATENCYMODEL_2V, KM_VERTEXBUFMODEL_NOBUF_OPAQUE); 

	/*-----------------------------------------------------------------------------------*/
	/* Create vertex buffer */
	status = kmCreateVertexBuffer(&VertexBufferDesc,		/* pBufferDesc */
									131072,					/* Opaque-Polygon 500KB */
									0,						/* Opaque-Modifier */
									131072,					/* Trans-Polygon 500KB */
									0						/* Trans-Modifier */
									);
	Check_Status(status, "kmCreateVertexBuffer");

	/*-----------------------------------------------------------------------------------*/
	/* Fog Setting */

	/* Fog Color */
	fogcol.byte.bBlue	= 0.6 * 255;
	fogcol.byte.bGreen	= 0.4 * 255;
	fogcol.byte.bRed	= 0.1 * 255;
	status = kmSetFogTableColor(fogcol);
	Check_Status(status, "kmSetFogTableColor");

	/* Fog Density */
	status = kmSetFogDensity(0xFF0C);
	Check_Status(status, "kmSetFogDensity");

	/* Fog Table */
	for(i = 0;i < 128; i++) {
/*--
//		// Linear Fog table ----------------------------------------------
//		FogTable[i] = 1.0f - ((float)i / 128.0f);
//		// PCX Fog table ----------------------------------------------
//		FogTable[i] = (float)PCXFogTable[i] / 256.0f;
//		// Slope Fog table ----------------------------------------------
--*/
#define	FOG_MIN		(-0.8f)
		FogTable[i] = 1.0f - (float)i * ((1.0f - FOG_MIN) / 128.0f);
		if(FogTable[i] < 0.0f) FogTable[i] = 0.0f;
	}
	status = kmSetFogTable(&FogTable[0]);
	Check_Status(status, "kmSetFogTable");

	/*-----------------------------------------------------------------------------------*/
	/* set display surface */
	status = kmActivateFrameBuffer(	&PrimarySurfaceDesc,	/* pSurfaceDesc */
									&BackSurfaceDesc,		/* pSurfaceDesc */
									FALSE,					/* bStripBuffer */
									TRUE					/* bWaitVSync */
									);
	Check_Status(status, "kmActivateFrameBuffer");

	/*-----------------------------------------------------------------------------------*/
	/* Initialize DisplayString routine */
	txt_InitDisplayString();

	/*-----------------------------------------------------------------------------------*/
	/* some initializes */

	SetupTextures ();
	SetupPrism    ();
	SetupContext  ();

	InitBackGround();		/* Setup background plane */

     for (i=0; i<NK; i++){
         LongK[i]  = 60;
         StateK[i] = i & 3;
         p1[i][2]  = p2[i][2]= -170.0f;
         NewAng[i] = (float)((char)(rand()))*(50.0f / 255.0f);
         NewPoint     (i);
         CreatePath   (i);
     }

	

	frame		= 0;

#if defined(_DISP_PERFORMANCE_)
	totalTime	= 0;

	pcount_f = QueryPerformanceFrequency((LARGE_INTEGER*)&freqi);	
	if(pcount_f) {	
		QueryPerformanceCounter((LARGE_INTEGER*)&Time3i);	
		freq = 1000.0f / (double)freqi;						
		OldTime3 = Time3 = (double)Time3i * freq;			
	}
	else {	
		Time3 = (double)timeGetTime();						
	}

	/* Get AP start time ---------------------------------------------*/
#if defined(_X86_)
	 time( &start_time );
#endif
#endif	/* defined(_DISP_PERFORMANCE_) */

	return 0;
}

/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   NextFrame                                                      */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   SGLContext, MovAngK, AngK, LongK, TimerK, StateK               */
/*  Description     :   Drawing everything and rendering.                              */
/*                      This routine is called from FRONTEND.C                         */
/*-------------------------------------------------------------------------------------*/
void NextFrame()
{
	register i;   
#if defined(_X86_)
	time_t		ltime;
#endif

/*--
//sgltri_startofframe (&SGLContext);
--*/

#if defined(_DISPLAY_TRANS_)
      DrawGround();
#endif
#if defined(_DISPLAY_SKY_)
      DrawSky   ();
#endif

      /* We have three diferent States: 0. Before jump (Only rotation)          */
      /*                                1. In the air. (Rotion and traslation)  */
      /*                                2. On the ground again (Only rotation)  */
      for (i=0; i<NK; i++){
         switch (StateK[i]){
               default:
               case 0: MovAngK[i]+=AngK[i]/LAP; LongK[i]+=3.3; DrawCyberK(0,i); 
                       if (TimerK[i]==LAP){TimerK[i]=-1; StateK[i]=1;}
                       break;
               case 1: MovAngK[i]-=(2.0*AngK[i])/NumMax[i]; LongK[i]=60; DrawCyberK(TimerK[i], i); 
                       if (TimerK[i]==NumMax[i]-1){TimerK[i]=-1; StateK[i]=2;}
                       break;
               case 2: MovAngK[i]+=AngK[i]/LAP; LongK[i]-=3.3;  DrawCyberK(NumMax[i]-1,i); 
                       if (TimerK[i]==LAP){TimerK[i]=-1; StateK[i]=0; NewPoint(i); CreatePath(i);}
                       break;
        }
     TimerK[i]++;
     }

/*--
//sgltri_render (&SGLContext);
--*/

	txt_SetCursor(0,4);
#if defined(_DISP_PERFORMANCE_)
	/* Write Date & Time on screen ---------------------------------------------*/
#if defined(_X86_)
	 time( &ltime );
    PRINTOUT(("START : %s", ctime( &start_time )));
    PRINTOUT(("NOW   : %s", ctime( &ltime )));
#endif
	/* Write FPS on screen -----------------------------------------------------*/
	PRINTOUT(("FRAME : %06d%06d  Now:%07.3fFPS, Ave:%07.3fFPS\n",frame_2, frame,nFPS,aFPS));
#else
	PRINTOUT(("FRAME : %06d%06d\n",frame_2, frame));
#endif	/* defined(_DISP_PERFORMANCE_) */

	/*-----------------------------------------------------------------------------------*/
	/* Rendering start */
#if defined(_DISPLAY_STRING_)
	txt_DispScreen(VertexBufferDesc);		/* Display screen */
#endif
	status = kmRender();
	Check_Status(status, "kmRender");

	/*-----------------------------------------------------------------------------------*/
	/* Flip screen */
	status = kmFlipFrameBuffer();
	Check_Status(status, "kmFlipFrameBuffer");

#if defined(_DISP_PERFORMANCE_)
	
	if(pcount_f) {
		QueryPerformanceCounter((LARGE_INTEGER*)&Time3i);	
		OldTime3 = Time3; Time3 = (double)Time3i * freq;
	}
	else {
		OldTime3 = Time3; Time3 = (double)timeGetTime();	
	}


	nowTime = Time3 - OldTime3;					
	if((nowTime > 1000.0f)||(nowTime < 1.0f)) nowTime = 20.0f;		
	if(nowTime > maxTime) maxTime = nowTime;	
	if(nowTime < minTime) minTime = nowTime;	

	totalTime += nowTime;										
	aveTime = totalTime / ((double)frame + 1.0f);		

	nFPS  = 1000.0f / (double)nowTime;
	aFPS  = 1000.0f / (double)aveTime;
	MxFPS = 1000.0f / (double)minTime;
	MnFPS = 1000.0f / (double)maxTime;
#endif	/* defined(_DISP_PERFORMANCE_) */

	frame++;
	Movement++; if (Movement == 400) Movement = 0;
	if(frame > 1000000) {	
		frame = 0;
#if defined(_DISP_PERFORMANCE_)
		totalTime = 0;
#endif	/* defined(_DISP_PERFORMANCE_) */
		frame_2++;
	}
}

/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   Finish                                                         */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   Device                                                         */
/*  Description     :   Free textures and close device.                                */
/*                      This routine is called from FRONTEND.C                         */
/*-------------------------------------------------------------------------------------*/
void Finish()
{
/*--
//	FreeAllBMPTextures ();
//	sgl_delete_device  (Device);	
--*/

	/*-----------------------------------------------------------------------------------*/
	/* Free Texture Surface */
	status = kmFreeTexture(&CyberKTex);
	Check_Status(status, "kmFreeTexture");
	status = kmFreeTexture(&GroundTex);
	Check_Status(status, "kmFreeTexture");
	status = kmFreeTexture(&SkyTex);
	Check_Status(status, "kmFreeTexture");

	/*-----------------------------------------------------------------------------------*/
	/* Free vertex buffer */
	status = kmDiscardVertexBuffer(&VertexBufferDesc);
	Check_Status(status, "kmDiscardVertexBuffer");

	/*-----------------------------------------------------------------------------------*/
	/* End display */
	status = kmStopDisplayFrameBuffer();
	Check_Status(status, "kmStopDisplayFrameBuffer");
}

/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   DrawGround                                                     */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   SGLContex                                                      */
/*  Description     :   Draw ground.                                                   */
/*-------------------------------------------------------------------------------------*/
void DrawGround()
{
SGLVERTEX	Vert[4];
int			Face[1][4] = {0, 1, 2, 3};
int			i;
float		Pos;
/* Four points to set a big quad. */
sgl_vector	Pnt[4] =  {{-5000.0f,  -0.0f, -100.0f},           
                      {-5000.0f,  -0.0f, 8000.0f},
                      { 6000.0f,  -0.0f, 8000.0f},
                      { 6000.0f,  -5.0f, -100.0f}};	


    for (i=0; i<4; i++){
        /* Translate from 3D to SGL-Direct coord. */
        Perspect (Pnt[i], &Vert[i]);                     
        /* Set the colour for each vertex. */
/*--
//		Vert[i].u32Colour   = RGBColour (255,255,255);
--*/
		Vert[i].u32Colour   = RGBA(255,255,255,160);
		Vert[i].u32Specular = RGBColour (255,255,255);
   }

    /* Here the continous fluency of the ground.  */
    /* Note that I just move texture's UV values. */
    /* I don't move the camera.                   */
    Pos = Movement / 50.0f;
    
    /* Set UV values for each textured vertex. */
    Vert[0].fUOverW = 0.0f;    Vert[0].fVOverW = Pos + 0.0f;
    Vert[1].fUOverW = 0.0f;    Vert[1].fVOverW = Pos + 30.0f;
    Vert[2].fUOverW = 35.0f;   Vert[2].fVOverW = Pos + 20.0f;
/*--
//    Vert[3].fUOverW = 0.0f;    Vert[3].fVOverW = Pos + 0.0f;
--*/
    Vert[3].fUOverW = 35.0f;    Vert[3].fVOverW = Pos + 0.0f;

    /* Set a sigle textured and transparent quad to create the ground. */
/*--
//	SGLContext.nTextureName   = GroundTex;    
//	SGLContext.u32Flags       = SGLTT_TEXTURE | SGLTT_GLOBALTRANS | SGLTT_BILINEAR;
//	SGLContext.u32GlobalTrans = 160;

//	sgltri_quads (&SGLContext, 1, Face, Vert);
--*/
kmtri_quads (	VertexBufferDesc,		/* KMVERTEXBUFFDESC		BufferDesc, */
				VertexContextGround,	/* KMVERTEXCONTEXT		VertexContext, */
				1,						/* int  nNumFaces, */
				Face,					/* int  pFaces[][4], */
				Vert					/* PSGLVERTEX  pVertices */
				);
}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   DrawSky                                                        */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   SGLContex                                                      */
/*  Description     :   Draw Sky. (The same as DrawGround)                             */
/*-------------------------------------------------------------------------------------*/
void DrawSky()
{
float		Pos=0;
SGLVERTEX	Vert[4];
int			Face[1][4] = {0,1,2,3};
int			i;
sgl_vector	Pnt[4] = {{-4000.0f,600.0f, -100.0f}, 
                     {-4000.0f,600.0f, 50000.0f},
                     { 8000.0f,600.0f, 50000.0f},
                     { 8000.0f,600.0f, -100.0f}};

    for (i=0; i<4; i++){ 
        Perspect (Pnt[i], &Vert[i]);
        Vert[i].u32Colour   = RGBColour (255,255,255);
        Vert[i].u32Specular = RGBColour (255,255,255);
    }
    
    /* Here the continous fluency of the sky.     */
    /* I just move texture's UV values.           */
    Pos = Movement/400.0; 

    Vert[0].fUOverW = 0.0;  Vert[0].fVOverW = Pos-0.0;  
/*--
//    Vert[1].fUOverW = 0.0;  Vert[1].fVOverW = Pos+20.0;
--*/
    Vert[1].fUOverW = 0.0;  Vert[1].fVOverW = Pos+5.0;
    Vert[2].fUOverW = 10.0; Vert[2].fVOverW = Pos+5.0;
    Vert[3].fUOverW = 10.0; Vert[3].fVOverW = Pos+00.0;


/*--
//	SGLContext.nTextureName = SkyTex;
//	sgltri_quads (&SGLContext, 1, Face, Vert);
--*/
	kmtri_quads (	VertexBufferDesc,	/* KMVERTEXBUFFDESC	BufferDesc, */
					VertexContextSky,	/* KMVERTEXCONTEXT		VertexContext, */
					1,					/* int  nNumFaces, */
					Face,				/* int  pFaces[][4], */
					Vert				/* PSGLVERTEX  pVertices */
					);

}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   CreatePath                                                     */
/*  Inputs          :   Num                                                            */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   PathK, p1, p2, RotVect, MovAngK, AngK                          */
/*  Description     :   Calculates a parabolic path (jump) for each CyberK             */
/*-------------------------------------------------------------------------------------*/
void CreatePath (int Num)
{
int		i = 0;
float	dist;
float	t = 0.0f;
float	A;
float	CosA, SinA, x, Vel, Lang;
sgl_vector End1, End2;

End1[0]=p1[Num][0];
End1[2]=p1[Num][2];
End2[0]=p2[Num][0];
End2[2]=p2[Num][2];

dist = sqrt ((End2[2]-End1[2])*(End2[2]-End1[2])+(End1[0]-End2[0])*(End1[0]-End2[0]));

RotVecK[Num][0] = (End2[2] - End1[2]);
RotVecK[Num][1] = 0.0f;
RotVecK[Num][2] = (End1[0] - End2[0]);

if (fabs(RotVecK[Num][2]) < 0.1f) RotVecK[Num][2] *= 10.0f;
 
A = -atan ( (End1[2]-End2[2])/(End1[0]-End2[0]) );
CosA = (End1[0]<End2[0]) ?  cos(A) : -cos(A);
SinA = (End1[0]<End2[0]) ? -sin(A) :  sin(A);

MovAngK[Num] = 0.0f;  Lang = atan (-4 * HIGH / dist);
AngK[Num]  = ((PI/2.0)+Lang)/1.2;
AngK[Num]  = (End1[0]<End2[0]) ? -AngK[Num]:AngK[Num];
Vel  = sqrt (GRV * dist / sin(2*Lang));

while (1){
      x = Vel * cos(Lang) * t;
      PathK[Num][i][1] = -Vel * sin (Lang) * t + GRV/2 * t*t;
      PathK[Num][i][0] = End1[0] + CosA*x;
      PathK[Num][i][2] = End1[2] + SinA*x;
      if (PathK[Num][i][1]<0.0 && i>1) break;
       t += TLP; i++;
      }

PathK[Num][i][0] = p2[Num][0];
PathK[Num][i][1] = p2[Num][1];
PathK[Num][i][2] = p2[Num][2];

NumMax[Num]=++i;
}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   NewPoint                                                       */
/*  Inputs          :   Num                                                            */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   NewAng, p1, p2                                                 */
/*  Description     :   Calculates two end points for creating a new path (jump).      */
/*-------------------------------------------------------------------------------------*/
void NewPoint (int Num)
{
    NewAng[Num]+=((float)((char)(rand())) / 255.0f) * ( 2.5f - Num * (2.0f / 50.0f));

    p1[Num][0] = p2[Num][0]; p1[Num][2] = p2[Num][2];

    p2[Num][0] = 50.0f * (Num /2.0f + 1.0f) * cos(NewAng[Num] / 2.0f);
    p2[Num][2] = 50.0f * (Num /2.0f + 1.0f) * sin(NewAng[Num] / 2.0f) + 500.0f + frame * 5.0f;
}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   SetupTextures                                                  */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   SeaTex, SealTex, GroundTex, SkyTex                             */
/*  Description     :   Loads all texture bitmaps.                                     */
/*-------------------------------------------------------------------------------------*/
void SetupTextures (void)
{
/*--
//	CyberKTex  = LoadBMPTexture ("CyberK.bmp", FALSE,  TRUE,  TRUE);
//	GroundTex  = LoadBMPTexture ("Ground.bmp", FALSE,  FALSE, TRUE);
//	SkyTex     = LoadBMPTexture ("Sky.bmp",    FALSE,  TRUE,  TRUE);
--*/
	PKMDWORD			pTexture01;				/* Pointer to texture */
	KMTEXTURETYPE		nTextureType;			/* texture type definition */

	/*-----------------------------------------------------------------------------------*/
	/* Create texture surface */
	nTextureType = KM_TEXTURE_TWIDDLED | KM_TEXTURE_RGB565;	/* Set texture type */
	status = kmCreateTextureSurface(
		&CyberKTex,				/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		128,					/*	IN	KMINT32			nWidth */
		128,					/*	IN	KMINT32			nHeight */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);
	Check_Status(status, "kmCreateTextureSurface(SeaTex)");

	nTextureType = KM_TEXTURE_TWIDDLED | KM_TEXTURE_RGB565;	/* Set texture type */
	status = kmCreateTextureSurface(
		&GroundTex,				/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		128,					/*	IN	KMINT32			nWidth */
		128,					/*	IN	KMINT32			nHeight */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);
	Check_Status(status, "kmCreateTextureSurface(GroundTex)");

	nTextureType = KM_TEXTURE_TWIDDLED | KM_TEXTURE_RGB565;	/* Set texture type */
	status = kmCreateTextureSurface(
		&SkyTex,				/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		128,					/*	IN	KMINT32			nWidth */
		128,					/*	IN	KMINT32			nHeight */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);
	Check_Status(status, "kmCreateTextureSurface(SkyTex)");

	/*-----------------------------------------------------------------------------------*/
	/* Load and set texture */
/*--
//	pTexture01 =  LoadTextureFile("CyberK.pvr");	// Load KAMUI texture
--*/
	pTexture01 = (unsigned long *)&cyberk;
	status = kmLoadTexture(&CyberKTex,				/* PKMSURFACEDESC pSurfaceDesc */
							pTexture01 + (16 / sizeof(KMDWORD)),			/* PKMDWORD pTexture */
							FALSE,				/* KMBOOLEAN bAutoMipMap */
							FALSE				/* KMBOOLEAN bDither */
							);
	Check_Status(status, "kmLoadTexture(CyberK.pvr)");
	free(pTexture01);

/*--
//	pTexture01 =  LoadTextureFile("CyGround.pvr");	// Load KAMUI texture
--*/
	pTexture01 = (unsigned long *)&cyground;
	status = kmLoadTexture(&GroundTex,				/* PKMSURFACEDESC pSurfaceDesc */
							pTexture01 + (16 / sizeof(KMDWORD)),			/* PKMDWORD pTexture */
							FALSE,				/* KMBOOLEAN bAutoMipMap */
							FALSE				/* KMBOOLEAN bDither */
							);
	Check_Status(status, "kmLoadTexture(Ground.pvr)");
	free(pTexture01);

/*--
//	pTexture01 =  LoadTextureFile("CySky.pvr");	// Load KAMUI texture
--*/
	pTexture01 = (unsigned long *)&cysky;
	status = kmLoadTexture(&SkyTex,				/* PKMSURFACEDESC pSurfaceDesc */
							pTexture01 + (16 / sizeof(KMDWORD)),			/* PKMDWORD pTexture */
							FALSE,				/* KMBOOLEAN bAutoMipMap */
							FALSE				/* KMBOOLEAN bDither */
							);
	Check_Status(status, "kmLoadTexture(Sky.pvr)");
	free(pTexture01);

}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   SetupContex                                                    */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   SGLContex                                                      */
/*  Description     :   Setup SGLContex values.                                        */
/*-------------------------------------------------------------------------------------*/
void SetupContext (void)
{
/*--
//	SGLContext.bFogOn               = TRUE;
//	SGLContext.fFogR                = 0.1f;
//	SGLContext.fFogG                = 0.4f;
//	SGLContext.fFogB                = 0.6f;
//	SGLContext.u32FogDensity        = 7;
//	SGLContext.bCullBackfacing      = FALSE;
//	SGLContext.u32Flags             = SGLTT_TEXTURE | SGLTT_GOURAUD | SGLTT_BILINEAR;
//	SGLContext.nTextureName         = 0;
//	SGLContext.bDoClipping          = TRUE;
//	SGLContext.cBackgroundColour[0] = 0.1f;
//	SGLContext.cBackgroundColour[1] = 0.5f;
//	SGLContext.cBackgroundColour[2] = 0.7f;
//	SGLContext.eShadowLightVolMode  = NO_SHADOWS_OR_LIGHTVOLS;
//	SGLContext.bFlipU               = FALSE;
//	SGLContext.bFlipV               = FALSE;
//	SGLContext.bDoUVTimesInvW       = TRUE;
//	SGLContext.eFilterType          = sgl_tf_bilinear;
--*/

	/*----------------------------------------------------------------------------------*/
	/* Initialize Vertex Context														*/
	/*----------------------------------------------------------------------------------*/
	/* Context for Ground */
	memset( &VertexContextGround, 0, sizeof(VertexContextGround));	/* Crear Context */
	InitVertexContext(&VertexContextGround);					/* Initialize context */
	/* Clear render state */
	VertexContextGround.RenderState	= 0;

	VertexContextGround.RenderState	|= KM_SRCBLENDINGMODE;
	VertexContextGround.SRCBlendingMode	= KM_SRCALPHA;

	VertexContextGround.RenderState	|= KM_DSTBLENDINGMODE;
	VertexContextGround.DSTBlendingMode	= KM_INVSRCALPHA;

	VertexContextGround.RenderState	|= KM_LISTTYPE;
	VertexContextGround.ListType  = KM_TRANS_POLYGON;

	VertexContextGround.RenderState	|= KM_TEXTURESHADINGMODE;
	VertexContextGround.TextureShadingMode	= KM_MODULATE_ALPHA;

	VertexContextGround.RenderState	|= KM_USEALPHA;
	VertexContextGround.bUseAlpha = TRUE;
	/* Set shading mode */
	VertexContextGround.RenderState	|= KM_SHADINGMODE;
	VertexContextGround.ShadingMode	= KM_TEXTUREGOURAUD;
	/* Set texture surface */
	VertexContextGround.pTextureSurfaceDesc	= &GroundTex;
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContextGround);
	Check_Status(status, "kmProcessVertexRenderState");
	/*--------------------------------------------------------------------------------*/
	/* Context for Sky */
	memset( &VertexContextSky, 0, sizeof(VertexContextSky));	/* Crear Context */
	InitVertexContext(&VertexContextSky);						/* Initialize context */
	/* Clear render state */
	VertexContextSky.RenderState	= 0;
	/* Set shading mode */
	VertexContextSky.RenderState	|= KM_SHADINGMODE;
	VertexContextSky.ShadingMode	= KM_TEXTUREGOURAUD;
	/* Set texture surface */
	VertexContextSky.pTextureSurfaceDesc	= &SkyTex;
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContextSky);
	Check_Status(status, "kmProcessVertexRenderState");
	/*--------------------------------------------------------------------------------*/
	/* Context for CyberK */
	memset( &VertexContextCyberK, 0, sizeof(VertexContextCyberK));	/* Crear Context */
	InitVertexContext(&VertexContextCyberK);						/* Initialize context */
	/* Clear render state */
	VertexContextCyberK.RenderState	= 0;
	/* Set shading mode */
	VertexContextCyberK.RenderState	|= KM_SHADINGMODE;
	VertexContextCyberK.ShadingMode	= KM_TEXTUREGOURAUD;
/*
	VertexContextCyberK.ShadingMode	= KM_TEXTUREFLAT;
*/
/*--
//	VertexContextSeal.ShadingMode	= KM_NOTEXTUREGOURAUD;
--*/
	/* Set texture surface */
	VertexContextCyberK.pTextureSurfaceDesc	= &CyberKTex;
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContextCyberK);
	Check_Status(status, "kmProcessVertexRenderState");

}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   Perspect                                                       */
/*  Inputs          :   Point3D                                                        */
/*  Outputs         :   Vert                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   None                                                           */
/*  Description     :   Calculates SGL-Direct coordenates from 3D coordenates.         */
/*-------------------------------------------------------------------------------------*/
void Perspect (const sgl_vector Point3D, SGLVERTEX *Vert)
{
const sgl_vector CamPos = { 0.0f, 40.0f, 150.0f};
float x, y, z;

    x    =  Point3D[0] + CamPos[0];
    y    = -Point3D[1] + CamPos[1];
    z    = (Point3D[2] + CamPos[2]) ;

    Vert->fX    =  (CamFocus * x) / z + 320;
    Vert->fY    =  (CamFocus * y) / z + 240;

    /* The render uses fInvW (1/z) to set the Z-buffer */
    /* In this case I use it to set the fog effect as well */
     Vert->fInvW =  1.8f / z;                   
}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   SetupPrisms                                                    */
/*  Inputs          :   None                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   Prism3DVert, PrismVert                                         */
/*  Description     :   Setup prisms vertex                                            */
/*-------------------------------------------------------------------------------------*/
void SetupPrism (void)
{
int Sh[] = {0, 150, 200, 255, 255, 200, 150, 85, 0, 0};
int ColR, ColG, ColB, ColRSh, ColGSh, ColBSh;
register i, j, k;
int cont = 0;

/* Here we set values for a default CyberK (3 prisms) */
for (j=0; j<2; j++){
   for (i=0; i<10; i++){
            for (k=0; k<3; k++) {
                Prism3DVect[k][cont][0]          = (2.0f + (float)k * 4.0f) * cos (((float)i * PI * 2.0f) / 9.0f);
                Prism3DVect[k][cont][1]          = (float)j * 20.0f;
                Prism3DVect[k][cont][2]          = (2.0f + (float)k * 4.0f) * sin (((float)i * PI * 2.0f) / 9.0f);
                PrismVect[k][cont].fUOverW       = (float)(i + 2) / 9.0f;
                PrismVect[k][cont].fVOverW       = (float)(j) / 0.95f;
                ReflectVect[k][cont].fUOverW     = (float)(i + 2) / 9.0f;
                ReflectVect[k][cont].fVOverW     = (float)(j) / 0.95f;
            }
       cont++;
   }
}

  /* Here we set the color and the shade for each vertex */
  for (i=0; i<NK; i++)
  {
    ColR = 50 + (int)(rand() & 0x00FF) * 200.0f / 255.0f;
    ColB = 50 + (int)(rand() & 0x00FF) * 200.0f / 255.0f;
    ColG = 50 + (int)(rand() & 0x00FF) * 200.0f / 255.0f;

    for (j=0; j<10; j++){
        ColRSh = (ColR * Sh[j]) / 200.0f; if (ColRSh > 255) ColRSh = 255;
        ColGSh = (ColG * Sh[j]) / 200.0f; if (ColGSh > 255) ColGSh = 255;
        ColBSh = (ColB * Sh[j]) / 200.0f; if (ColBSh > 255) ColBSh = 255;         
        PrismCol [i][j] = RGBColour (ColRSh, ColGSh, ColBSh);
    }
  }
}
/*-------------------------------------------------------------------------------------*/
/*  Function Name   :   DrawCyberK                                                     */
/*  Inputs          :   PNum                                                           */
/*  Outputs         :   None                                                           */
/*  Returns         :   None                                                           */
/*  Globals Used    :   Prism3DVert, PrismVert                                         */
/*  Description     :   Draw six prisms to build a CyberK and its reflection           */
/*-------------------------------------------------------------------------------------*/
void DrawCyberK (int Pos,int KNum)
{
register i, j, k, cont=0, Sign = TRUE;
float TempAng, xx, x, y, z;
sgl_vector TempVect;
float CosZ, SinZ, CosY, SinY, CurrentLong;

   if (PathK[KNum][Pos][2]-frame*5 < -210) return;

   TempAng = -atan ((RotVecK[KNum][0]/RotVecK[KNum][2]));

   if (RotVecK[KNum][0] < 0.0 || RotVecK[KNum][2] < 0.0) Sign = FALSE;

   CosZ = cos (MovAngK[KNum]);
   SinZ = sin (MovAngK[KNum]);
   CosY = cos (TempAng);
   SinY = sin (TempAng);
 
   for (k=0; k<3; k++)
   {
    CurrentLong =  k*((LongK[KNum])/3.0) - k*(60-LongK[KNum])/5.0;
    for (j=0; j<2; j++)
    {
      for (i=0; i<10; i++)
      {
         x =  Prism3DVect[k][cont][0];
         y =  Prism3DVect[k][cont][1];
         z =  Prism3DVect[k][cont][2];

         if (Sign) { x=-x;  z=-z;}
         
    /* VERTICAL TRANSLATION */
         y += CurrentLong;
    /* Z_AXIS ROTATION      */
         xx = x;
         x  = xx * CosZ - y  * SinZ;
         y  = y  * CosZ + xx * SinZ;
    /* Y_AXIS ROTATION      */
         xx = x;
         x  = xx * CosY - z  * SinY;
         z  = z  * CosY + xx * SinY;
    /* TRANSLATION          */
        TempVect[0] = x + PathK[KNum][Pos][0];
        TempVect[1] = y + PathK[KNum][Pos][1];
        TempVect[2] = z + PathK[KNum][Pos][2] - frame*5 + 100;

        Perspect (TempVect, &PrismVect[k][cont]);

        TempVect[1] = -TempVect[1];
        Perspect (TempVect, &ReflectVect[k][cont]);

    /* Setting smooth shading */
        PrismVect   [k][cont].u32Colour   = PrismCol[KNum][i];
        PrismVect   [k][cont].u32Specular = RGBColour (255, 255, 255);
        ReflectVect [k][cont].u32Colour   = PrismCol[KNum][i];
        ReflectVect [k][cont].u32Specular = RGBColour (255, 255, 255);;
   
       cont++;
       }
    }
    cont = 0;
/*--
//SGLContext.nTextureName  = CyberKTex;
//sgltri_quads   (&SGLContext, 14, &(PrismFaces[4]), PrismVect[k]);
//sgltri_quads   (&SGLContext, 14, &(PrismFaces[4]), ReflectVect[k]);
--*/
	 kmtri_quads (	VertexBufferDesc,	/* KMVERTEXBUFFDESC		BufferDesc, */
					VertexContextCyberK,/* KMVERTEXCONTEXT		VertexContext, */
					14,					/* int  nNumFaces, */
					&(PrismFaces[4]),	/* int  pFaces[][4], */
					PrismVect[k]		/* PSGLVERTEX  pVertices */
					);
	 kmtri_quads (	VertexBufferDesc,	/* KMVERTEXBUFFDESC	BufferDesc, */
					VertexContextCyberK,/* KMVERTEXCONTEXT		VertexContext, */
					14,					/* int  nNumFaces, */
					&(PrismFaces[4]),	/* int  pFaces[][4], */
					ReflectVect[k]		/* PSGLVERTEX  pVertices */
					);

    /* We change the colour for simulating the shade on the bottom face */ 
    for (i=0; i<20; i++) 
    {
        PrismVect[k][i].u32Colour     = RGBColour ( 60, 60, 60);
        ReflectVect[k][i].u32Colour   = RGBColour ( 60, 60, 60);
    }
/*--
//sgltri_quads   (&SGLContext, 4, &(PrismFaces[0]),   PrismVect[k]);
//sgltri_quads   (&SGLContext, 4, &(PrismFaces[0]), ReflectVect[k]);
--*/
	 kmtri_quads (	VertexBufferDesc,	/* KMVERTEXBUFFDESC	BufferDesc, */
					VertexContextCyberK,/* KMVERTEXCONTEXT		VertexContext, */
					4,					/* int  nNumFaces, */
					&(PrismFaces[0]),	/* int  pFaces[][4], */
					PrismVect[k]		/* PSGLVERTEX  pVertices */
					);
	 kmtri_quads (	VertexBufferDesc,	/* KMVERTEXBUFFDESC	BufferDesc, */
					VertexContextCyberK,/* KMVERTEXCONTEXT		VertexContext, */
					4,					/* int  nNumFaces, */
					&(PrismFaces[0]),	/* int  pFaces[][4], */
					ReflectVect[k]		/* PSGLVERTEX  pVertices */
					);
  } 
}
/*-------------------------------------------------------------------------------------*/
/*------------------------------------ End of File ------------------------------------*/
/****************************************************************************/
/**	main ********************************************************************/
/****************************************************************************/ 
int	main(void)
{
	txt_ClearScreen();	/* Clear text screen */
	PRINTOUT(("** CyberK 2VLatency Model(OPAQUE)**\n"));
    SetupScene ();	/* Initialize */
	PRINTOUT(("\n"));

/*--
//	for(count =0; count < FRAMES; count++) {
--*/
	while(1){
		NextFrame();	/* Rendering */
/*--
//		if((count % 50) == 0) {
//			PRINTOUT((" FRAME : %04d  Now:%07.3fFPS, Ave:%07.3fFPS, Max:%07.3fFPS, Min:%07.3fFPS\n",frame,nFPS,aFPS,MxFPS,MnFPS);
//		}
--*/
	}

	Finish();		/* End of render */
#if	defined(_X86_)
	Sleep(500);
#endif
	PRINTOUT(("** END CiberK **\n"));
	return 0;
}

/*--------------------------- End of File --------------------------------*/
