/********************************************************************************/
/* Name     : kmnefert.c														*/
/* Title    : KAMUI test program "Nefertt" from VL								*/
/* Author   : VideoLogic / Takeshi Muto : NEC									*/
/* Created  : 30/01/1997  by VideoLogic											*/
/* Modified : 17/09/1997  by Takeshi Muto for KAMUI								*/
/*            12 May 1998 by Takeshi Muto for CLX/SET5							*/
/* Description :																*/
/********************************************************************************/
/*
#define		_X86_
*/
/* _X86_ flag for win95 : SET2 */

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

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

/* Set Display Mode */
#define NTSC 1

#define		SPEED			(1.0f)					/* pet move speed ( 1 to n ) */

#define		TITLE			"Nefertt for KAMUI"		/* ウインドウ・タイトル */
#define		TEX1_FNAME		".\\Rivets.pvr"			/* 「顔」のテクスチャファイル名 */
#define		TEX1_U			(128)					/* Texture width */
#define		TEX1_V			(128)					/* Texture height */
#define		TEX2_FNAME		".\\pvrlogo.pvr"		/* 「顔」のテクスチャファイル名 */
#define		TEX2_U			(256)					/* Texture width */
#define		TEX2_V			(256)					/* Texture height */
#define		FRAMES			(100000)				/* rendering frame number */

#include	<math.h>				/* for atan */
#include	<stdio.h>
#include	<stdlib.h>
#include	<float.h>

#include	<shinobi.h>

#if 0
#include	<io.h>					/* for _filelength */
#include	<FCNTL.H>				/* for _open switches */
#endif

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

#include	"kamui.h"				/* for Kamui Call */
#include	"transfor.h"
#include	"nefertt.h"				/* nefertity model data */
/*#include	"nec.h"				 */	/* nec logo model data */
#include	"dispstr.h"				/* for DisplayString */

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

/* Textures */
extern const unsigned char pvrlogo[];
extern const unsigned char Rivets[];

#define		PI					(3.141592654f)
#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		ONEOVERTWOPI		(1.0f/(2.0f*PI))

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

/* SGL互換TYPE */
typedef float	km_2d_vec[2];	/* type of sgl_2d_vec */
/* --------- */
/* 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		TexSurfaceDesc1;		/* texture surface */
	KMSURFACEDESC		TexSurfaceDesc2;		/* texture surface */
	KMVERTEXBUFFDESC	VertexBufferDesc;		/* Vertex-buffer */
	KMVERTEXCONTEXT		VertexContext01;		/* Vertex context(Normal Object) */
	KMVERTEXCONTEXT		VertexContext02;		/* Vertex context(Two parameter Object #1) */
	KMVERTEXCONTEXT		VertexContext03;		/* Vertex context(Two parameter Object #2) */
	KMVERTEXCONTEXT		ModifireContextFirst;	/* Vertex context */
	KMVERTEXCONTEXT		ModifireContextNormal;	/* Vertex context */
	KMVERTEXCONTEXT		ModifireContextLast;	/* Vertex context */
	PKMDWORD			pTexture01;				/* Pointer to texture */
	KMTEXTURETYPE		nTextureType;			/* texture type definition */

/***************************************************************************/
/**	グローバル変数 *********************************************************/
/***************************************************************************/

/* SGL互換変数 */
static km_vector km_x_axis = {1.0f, 0.0f, 0.0f};	/* sgl_x_axis */
static km_vector km_y_axis = {0.0f, 1.0f, 0.0f};	/* sgl_y_axis */
static km_vector km_z_axis = {0.0f, 0.0f, 1.0f};	/* sgl_z_axis */

/* 性能測定用変数 */
	int			frame;				/* 画面フレーム */
	int			frame_2 = 0;		/* 画面フレーム上位 */
#if defined(_DISP_PERFORMANCE_)
	int			pcount_f;			/* Hight-resolution counter supported? */
	double		nFPS;				/* 現在の性能(Frame/Second) */
	double		aFPS;				/* 性能の平均値 */
	double		MxFPS;				/* 最高性能 */
	double		MnFPS;				/* 最低性能 */
	__int64 	Time3i;				/* render API 完了時刻 */
	__int64		freqi;				/* カウンタの精度 */
	double		freq;				/* カウンタの精度 */
	double		Time3;				/* render API 完了時刻 */
	double		maxTime = 0.00001;	/* 最高描画時間(msec) */
	double		minTime = 99999;	/* 最低描画時間(msec) */
	double		OldTime3;			/* １フレーム前のrender直後の時間(msec) */
	double		nowTime;			/* 現在の描画時間(msec) */
	double		totalTime	= 0;	/* 累積render時間(msec) */
	double		aveTime;			/* 平均描画時間(msec) */
#if defined(_X86_)
	time_t		start_time;			/* APの開始時間 */
#endif
#endif

/* モード設定フラグ */
	int		move_object		= 1;	/* 物体を自動的に回転する */
/*	int		wait_render_f	= 1;	// レンダリングの終了を待つ */
/*	int		use_cull_f		= 0;	// CULL modeを使用する */
/*	int		use_fog_f		= 0;	// フォグを使用する */
/*	int		use_clipping_f	= 1;	// クリッピングを使用する */
/*	int		fog_red			= 50;	// Fog coclor(Red) (%) */
/*	int		fog_green		= 50;	// Fog coclor(Green) (%) */
/*	int		fog_blue		= 50;	// Fog coclor(Blue) (%) */
/*	int		fog_density		= 18;	// Fog density */
/*	int		bg_red			= 50;	// Background color(Red) (%) */
/*	int		bg_green		= 30;	// Background(Green) (%) */
/*	int		bg_blue			= 0;	// Background(Blue) (%) */
	int		tex_map_type	= 2;	/* Texture mapping type 1=Spherical 2=Cylindrical */
	int		shadow_vol_type	= 2;	/* shadow volume 1:No 2:Shadow 3:Light */
/*	int		shadow_vol_type	= 1;	// shadow volume 1:No 2:Shadow 3:Light */
	int		disp_shadow_vol	= 0;	/* Display shadow/light volume object */
	int		polygons		= NUM_FACES;	/* 表示するポリゴンの数 */
/*	int		fShadowBrightness = 70;	// fShadowBrightness */
/*	int		LightVolRed		= 70;	// Light Volume Color(Red) */
/*	int		LightVolGreen	= 50;	// Light Volume Color(Green) */
/*	int		LightVolBlue	= 20;	// Light Volume Color(Blue) */
	int		LightRed		= 100;	/* Light Color(Red) */
	int		LightGreen		= 100;	/* Light Color(Green) */
	int		LightBlue		= 100;	/* Light Color(Blue) */
/*	int		smooth_f		= 1;	// スムースシェーディングを行う */
/*	int		render_all		= 1;	// すべてのリージョンをレンダリングする */
/*	int		flipu_f			= 1;	// Ｕ軸方向テクスチャ繰り返し */
/*	int		flipv_f			= 1;	// Ｖ軸方向テクスチャ繰り返し */
/*	int		invw_f			= 1;	// Do UV Times inv W */
/*	int		globaltrans		= 100;	// Global translucent */
/*	int		mipmapoffset	= 2;	// mipmap offset */
/*	int		trans_tex		= 0;	// αテクスチャ使用 */
/*	int		screen_top_x	= 0;	// 描画座標（左上） */
/*	int		screen_top_y	= 0;	// 描画座標（左上） */
/*	int		screen_bottom_x	= 639;	// 描画座標（右下） */
/*	int		screen_bottom_y	= 479;	// 描画座標（右下） */
/*	int		disp_fps		= 1;	// Display FPS */

/* 物体の移動に関する変数 */
	float	rx = 0.0f;	/* X軸周りの回転量(ユーザー入力) */
	float	ry = 0.0f;	/* Y軸周りの回転量(ユーザー入力) */
	float	rz = 0.0f;	/* Z軸周りの回転量(ユーザー入力) */

	float 				OxDash, OyDash, SxDash, SyDash;
	float				ZoomFactor, ZoomFactorD;
	float				CamXsize, CamXsizeD, CamYsize, CamYsizeD;
	float 				f1OverLength;
	static SGLVERTEX 	SGLVertices[NUM_VERTICES];
	static km_2d_vec	UVs[NUM_VERTICES];
	km_vector			Tra, Sca, Rot;
	float				Theta;
	TRANSFORM			T;
	km_vector			LightLocal;
	km_vector			LightDir = {0.6667f, 0.6667f, -0.6667f}; 

/***************************************************************************/
/**	サブルーチン ***********************************************************/
/***************************************************************************/

/***************************************************************************/
/**	Sphereテクスチャマッピング *********************************************/
/***************************************************************************/
void DoSphericalTextureMapping (int nVertices, km_vector Vertices[], km_2d_vec UVs[], km_vector Centre, float fU, float fV)
{
	int k;

	for (k = 0; k < nVertices; ++k)
	{
		float fX = Vertices[k][0] - Centre[0];

		UVs[k][0] = (((float) atan2 (Vertices[k][2] - Centre[2], fX) + PI) * ONEOVERTWOPI) * fU;
		UVs[k][1] = (((float) atan2 (Vertices[k][1] - Centre[1], fX) + PI) * ONEOVERTWOPI) * fV;
	}
}

/***************************************************************************/
/**	Cylindricalテクスチャマッピング ****************************************/
/***************************************************************************/
void DoCylindricalTextureMapping (int nVertices, km_vector Vertices[], km_2d_vec UVs[], km_vector Centre, km_2d_vec CVec, float fU, float fV)
{
	int k;

	for (k = 0; k < nVertices; ++k)
	{
		float fX = Vertices[k][0] - Centre[0];
		float fY = Vertices[k][1] - Centre[1];
		float fZ = Vertices[k][2] - Centre[2];

		UVs[k][0] = (((float) atan2 (fZ, fX) + PI) * ONEOVERTWOPI) * fU;
		UVs[k][1] = fY * fV;
	}
}

/****************************************************************************/
/**	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;
	}
}

/****************************************************************************/
/**	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	Ver03;

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

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

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

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

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

/****************************************************************************/
/**	kmtri_triangles for 2 parameter : modifier volume variant ***************/
/****************************************************************************/
void 
kmtri_triangles2( KMVERTEXBUFFDESC		BufferDesc,
				  KMVERTEXCONTEXT		VertexContext01,	/* Main */
				  KMVERTEXCONTEXT		VertexContext02,	/* shadow */
				  int  					nNumFaces,
				  int  					pFaces[][3],
				  PSGLVERTEX  			pVertices )
{
	KMSTATUS		status;
	int				i;
	KMVERTEX_11		Ver;

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

	status = kmSetModifierRenderState(&VertexContext02);
	Check_Status(status, "kmSetModifierRenderState");

	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.fU0m					= pVertices[pFaces[i][0]].fUOverW;
		Ver.fV0m					= pVertices[pFaces[i][0]].fVOverW;
		Ver.fU1m					= pVertices[pFaces[i][0]].fUOverW;
		Ver.fV1m					= pVertices[pFaces[i][0]].fVOverW;
		Ver.uBaseRGB0m.dwPacked		= pVertices[pFaces[i][0]].u32Colour;
		Ver.uBaseRGB1m.dwPacked		= pVertices[pFaces[i][0]].u32Colour;
		Ver.uOffsetRGB0m.dwPacked	= pVertices[pFaces[i][0]].u32Specular;
		Ver.uOffsetRGB1m.dwPacked	= pVertices[pFaces[i][0]].u32Specular;

		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_11,sizeof(KMVERTEX_11) );
		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.fU0m					= pVertices[pFaces[i][1]].fUOverW;
		Ver.fV0m					= pVertices[pFaces[i][1]].fVOverW;
		Ver.fU1m					= pVertices[pFaces[i][1]].fUOverW;
		Ver.fV1m					= pVertices[pFaces[i][1]].fVOverW;
		Ver.uBaseRGB0m.dwPacked		= pVertices[pFaces[i][1]].u32Colour;
		Ver.uBaseRGB1m.dwPacked		= pVertices[pFaces[i][1]].u32Colour;
		Ver.uOffsetRGB0m.dwPacked	= pVertices[pFaces[i][1]].u32Specular;
		Ver.uOffsetRGB1m.dwPacked	= pVertices[pFaces[i][1]].u32Specular;

		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_11,sizeof(KMVERTEX_11) );
		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.fU0m					= pVertices[pFaces[i][2]].fUOverW;
		Ver.fV0m					= pVertices[pFaces[i][2]].fVOverW;
		Ver.fU1m					= pVertices[pFaces[i][2]].fUOverW;
		Ver.fV1m					= pVertices[pFaces[i][2]].fVOverW;
		Ver.uBaseRGB0m.dwPacked		= pVertices[pFaces[i][2]].u32Colour;
		Ver.uBaseRGB1m.dwPacked		= pVertices[pFaces[i][2]].u32Colour;
		Ver.uOffsetRGB0m.dwPacked	= pVertices[pFaces[i][2]].u32Specular;
		Ver.uOffsetRGB1m.dwPacked	= pVertices[pFaces[i][2]].u32Specular;

		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_11,sizeof(KMVERTEX_11) );
		Check_Status(status, "kmSetVertex");
	}
}

/****************************************************************************/
/**	kmtri_shadow ************************************************************/
/****************************************************************************/
void 
kmtri_shadow (	KMVERTEXBUFFDESC		BufferDesc,
				KMVERTEXCONTEXT			VertexContextFirst,
				KMVERTEXCONTEXT			VertexContextNormal,
				KMVERTEXCONTEXT			VertexContextLast,
				int						nNumFaces,
				int						pFaces[][3],
				PSGLVERTEX				pVertices )
{
	KMSTATUS	status;
	int			i;
	KMVERTEX_17	Ver;	/* Shadow Volume */

	/*---------------------------------------------------- First Polygon */
	status = kmSetVertexRenderState(&VertexContextFirst);
	Check_Status(status, "kmSetVertexRenderState");

	status = kmStartVertexStrip(&VertexBufferDesc);
	Check_Status(status, "kmStartVertexStrip");

	Ver.ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
	Ver.fAX					= pVertices[pFaces[0][0]].fX;
	Ver.fAY					= pVertices[pFaces[0][0]].fY;
#if defined(_STRICT_UNION_)
	Ver.uA.fAZ				= pVertices[pFaces[0][0]].fInvW;
#else
	Ver.fAZ					= pVertices[pFaces[0][0]].fInvW;
#endif
	Ver.fBX					= pVertices[pFaces[0][1]].fX;
	Ver.fBY					= pVertices[pFaces[0][1]].fY;
#if defined(_STRICT_UNION_)
	Ver.uB.fBZ				= pVertices[pFaces[0][1]].fInvW;
#else
	Ver.fBZ					= pVertices[pFaces[0][1]].fInvW;
#endif
	Ver.fCX					= pVertices[pFaces[0][2]].fX;
	Ver.fCY					= pVertices[pFaces[0][2]].fY;
#if defined(_STRICT_UNION_)
	Ver.uC.fCZ				= pVertices[pFaces[0][2]].fInvW;
#else
	Ver.fCZ					= pVertices[pFaces[0][2]].fInvW;
#endif

	status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_17,sizeof(KMVERTEX17) );
	Check_Status(status, "kmSetVertex");

	/*---------------------------------------------------- Normal Polygon */
	status = kmSetVertexRenderState(&VertexContextNormal);
	Check_Status(status, "kmSetVertexRenderState");

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

		Ver.ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
		Ver.fAX					= pVertices[pFaces[i][0]].fX;
		Ver.fAY					= pVertices[pFaces[i][0]].fY;
#if defined(_STRICT_UNION_)
		Ver.uA.fAZ				= pVertices[pFaces[i][0]].fInvW;
#else
		Ver.fAZ					= pVertices[pFaces[i][0]].fInvW;
#endif
		Ver.fBX					= pVertices[pFaces[i][1]].fX;
		Ver.fBY					= pVertices[pFaces[i][1]].fY;
#if defined(_STRICT_UNION_)
		Ver.uB.fBZ				= pVertices[pFaces[i][1]].fInvW;
#else
		Ver.fBZ					= pVertices[pFaces[i][1]].fInvW;
#endif
		Ver.fCX					= pVertices[pFaces[i][2]].fX;
		Ver.fCY					= pVertices[pFaces[i][2]].fY;
#if defined(_STRICT_UNION_)
		Ver.uC.fCZ				= pVertices[pFaces[i][2]].fInvW;
#else
		Ver.fCZ					= pVertices[pFaces[i][2]].fInvW;
#endif

		status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_17,sizeof(KMVERTEX17) );
		Check_Status(status, "kmSetVertex");
	}

	/*---------------------------------------------------- Last Polygon */
	status = kmSetVertexRenderState(&VertexContextLast);
	Check_Status(status, "kmSetVertexRenderState");

	status = kmStartVertexStrip(&VertexBufferDesc);
	Check_Status(status, "kmStartVertexStrip");

	Ver.ParamControlWord	= KM_VERTEXPARAM_ENDOFSTRIP;
	Ver.fAX					= pVertices[pFaces[(nNumFaces - 1)][0]].fX;
	Ver.fAY					= pVertices[pFaces[(nNumFaces - 1)][0]].fY;
#if defined(_STRICT_UNION_)
	Ver.uA.fAZ				= pVertices[pFaces[(nNumFaces - 1)][0]].fInvW;
#else
	Ver.fAZ					= pVertices[pFaces[(nNumFaces - 1)][0]].fInvW;
#endif
	Ver.fBX					= pVertices[pFaces[(nNumFaces - 1)][1]].fX;
	Ver.fBY					= pVertices[pFaces[(nNumFaces - 1)][1]].fY;
#if defined(_STRICT_UNION_)
	Ver.uB.fBZ				= pVertices[pFaces[(nNumFaces - 1)][1]].fInvW;
#else
	Ver.fBZ					= pVertices[pFaces[(nNumFaces - 1)][1]].fInvW;
#endif
	Ver.fCX					= pVertices[pFaces[(nNumFaces - 1)][2]].fX;
	Ver.fCY					= pVertices[pFaces[(nNumFaces - 1)][2]].fY;
#if defined(_STRICT_UNION_)
	Ver.uC.fCZ				= pVertices[pFaces[(nNumFaces - 1)][2]].fInvW;
#else
	Ver.fCZ					= pVertices[pFaces[(nNumFaces - 1)][2]].fInvW;
#endif

	status = kmSetVertex(&BufferDesc,&Ver,KM_VERTEXTYPE_17,sizeof(KMVERTEX17) );
	Check_Status(status, "kmSetVertex");
}

/****************************************************************************/
/**	Initialize Vertex Context ***********************************************/
/****************************************************************************/
void	InitVertexContext(PKMVERTEXCONTEXT pVertexContext)
{
	/* 頂点CONTEXTの生成 */
	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->ShadingMode			= KM_NOTEXTUREGOURAUD;
	pVertexContext->SelectModifier		= KM_NOMODIFIER;
	pVertexContext->bZWriteDisable		= FALSE;			/* ARC1にはない */

	/* for TSP ControlWord  */
	pVertexContext->SRCBlendingMode		= KM_ONE;
	pVertexContext->DSTBlendingMode		= KM_ZERO;
	pVertexContext->bSRCSel				= FALSE;			/* ARC1にはない */
	pVertexContext->bDSTSel				= FALSE;			/* ARC1にはない */
	pVertexContext->FogMode				= KM_NOFOG;			/* 11はリザーブ */
	pVertexContext->bUseSpecular		= FALSE;
	pVertexContext->bUseAlpha			= FALSE;
	pVertexContext->FlipUV				= KM_NOFLIP;
	pVertexContext->ClampUV				= KM_NOCLAMP;
	pVertexContext->FilterMode			= KM_POINT_SAMPLE;
	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);
}

/****************************************************************************/
/**	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				= KM_NOFOG;			/* 11 is reserved */
	BackVertexContext.bUseSpecular			= FALSE;
	BackVertexContext.bUseAlpha				= FALSE;
	BackVertexContext.ClampUV				= KM_NOCLAMP;
	BackVertexContext.FilterMode			= KM_POINT_SAMPLE;
	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				=   0.0f;
	BV[0].fY				= 479.0f;
#if defined(_STRICT_UNION_)
	BV[0].u.fZ				=  0.2f;
#else
	BV[0].fZ				=  0.2f;
#endif
	BV[0].fBaseAlpha		=   1.0f;
	BV[0].fBaseRed			=   1.0f;
	BV[0].fBaseGreen		=   1.0f;
	BV[0].fBaseBlue			=   0.0f;

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

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

	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");
}

#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

/***************************************************************************/
/** シーンの初期化 : Initialize scene **************************************/
/***************************************************************************/

void	InitScene(void)
{
	int	k;

	static int		SGLFaces[NUM_FACES][3];
	static float	fDot[NUM_VERTICES];
	km_vector  		MeshCentre = {0.0f, -2.0f, 4.0f};
	km_2d_vec  		MeshCVec = {0.0f, 0.0f};

	/*----------------------------------------------------------------------------------- */
	/* 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

	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_MODIFIER); 

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

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

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

/****************************************************************************/
/**	変数の初期化 ************************************************************/
/****************************************************************************/

		Tra[0] = 0.0f;			/* Translate X */
		Tra[1] = 200.0f;		/* Translate Y */
		Tra[2] = 1600.0f;		/* Translate Z */

		Sca[0] = 60.0f;			/* Scale X */
		Sca[1] = 60.0f;			/* Scale Y */
		Sca[2] = 60.0f;			/* Scale Z */
/*		Sca[0] = 2.0f;			// Scale X */
/*		Sca[1] = 2.0f;			// Scale Y */
/*		Sca[2] = 2.0f;			// Scale Z */

		Rot[0] = 0.333f;		/* Rotate X */
		Rot[1] = 1.0f;			/* Rotate Y */
		Rot[2] = 0.667f;		/* Rotate Z */

		Theta = 0.35f;			/* Ｙ軸方向の現在の回転角度 */

		OxDash = 320.0f;		/* Camera X Centre */
		OyDash = 240.0f;		/* Camera Y Centre */

		ZoomFactor	= 4.0f;
		ZoomFactorD	= 0.01f;
		CamXsize	= 0.3f;
		CamXsizeD	= 0.001f;
		CamYsize	= 0.3f;
		CamYsizeD	= 0.001f;

		/*-------------------------------------------------------------------------------- */
		/* 性能測定用各種変数の初期化 */

		frame		= 0;

#if defined(_DISP_PERFORMANCE_)
	totalTime	= 0;

	pcount_f = QueryPerformanceFrequency((LARGE_INTEGER*)&freqi);	/* カウンタの単位の読み出し */
	if(pcount_f) {	/*	QueryPerformanceCounterがサポートされている */
		QueryPerformanceCounter((LARGE_INTEGER*)&Time3i);	/* ダミー値による初期化 */
		freq = 1000.0f / (double)freqi;						/* msec変換用係数の生成 */
		OldTime3 = Time3 = (double)Time3i * freq;			/* countからmsecへ変換 */
	}
	else {	/* QueryPerformanceCounterがサポートされていない */
		Time3 = (double)timeGetTime();						/* ダミー値による初期化 */
	}
#endif	/* defined(_DISP_PERFORMANCE_) */

/****************************************************************************/
/**	？？？？？ **************************************************************/
/****************************************************************************/
		for (k = 0; k < NUM_VERTICES; ++k)
		{
			f1OverLength =  1.0f / (float) sqrt (Normals[k][0] * Normals[k][0] + 
												 Normals[k][1] * Normals[k][1] + 
												 Normals[k][2] * Normals[k][2] );
			Normals[k][0] *= f1OverLength;
			Normals[k][1] *= f1OverLength;
			Normals[k][2] *= f1OverLength;
		}

/****************************************************************************/
/**	テクスチャマッピング ****************************************************/
/****************************************************************************/
	/*----------------------------------------------------------------------------------- */
	/* Create texture surface */
	nTextureType = KM_TEXTURE_TWIDDLED | KM_TEXTURE_RGB565;	/* Set texture type */
	status = kmCreateTextureSurface(
		&TexSurfaceDesc1,		/* OUT	PKMSURFACEDESC	pSurfaceDesc */
		TEX1_U,					/*	IN	KMINT32			nWidth  */
		TEX1_V,					/*	IN	KMINT32			nHeight  */
		nTextureType			/*	IN	KMTEXTURETYPE	nTextureType */
	);
	Check_Status(status, "kmCreateTextureSurface");

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

	/*----------------------------------------------------------------------------------- */
	/* Load and set texture */
/*--
	pTexture01 =  LoadTextureFile(TEX1_FNAME);
--*/
	pTexture01 = (unsigned long *)&Rivets;
	status = kmLoadTexture(&TexSurfaceDesc1,	/* PKMSURFACEDESC pSurfaceDesc */
							pTexture01 + (16 / sizeof(KMDWORD)),			/* PKMDWORD pTexture */
							FALSE,				/* KMBOOLEAN bAutoMipMap */
							FALSE				/* KMBOOLEAN bDither */
							);
	Check_Status(status, "kmLoadTexture");
/*--
	free(pTexture01);
--*/

/*--
	pTexture01 =  LoadTextureFile(TEX2_FNAME);
--*/
	pTexture01 = (unsigned long *)&pvrlogo;
	status = kmLoadTexture(&TexSurfaceDesc2,	/* PKMSURFACEDESC pSurfaceDesc */
							pTexture01 + (16 / sizeof(KMDWORD)),			/* PKMDWORD pTexture */
							FALSE,				/* KMBOOLEAN bAutoMipMap */
							FALSE				/* KMBOOLEAN bDither */
							);
	Check_Status(status, "kmLoadTexture");
/*--
	free(pTexture01);
--*/

	switch(tex_map_type) {
	default:
	case 1:	DoSphericalTextureMapping (NUM_VERTICES, Vertices, UVs, MeshCentre, 10.0f, 0.5f); break;
	case 2:	DoCylindricalTextureMapping (NUM_VERTICES, Vertices, UVs, MeshCentre, MeshCVec, 10.0f, 0.5f); break;
	case 3: break;
	}

/****************************************************************************/
/**	VERTEX Contextの初期化 **************************************************/
/****************************************************************************/
	/* for Normal object -----------------------------------------------------  */
	memset( &VertexContext01, 0, sizeof(VertexContext01));	/* Crear Context */
	InitVertexContext(&VertexContext01);					/* Initialize context */

	/* Clear render state */
	VertexContext01.RenderState	= 0;
	/* Set shading mode */
	VertexContext01.RenderState	|= KM_SHADINGMODE;
	VertexContext01.ShadingMode	= KM_TEXTUREGOURAUD;
	/* Set texture surface */
	VertexContext01.pTextureSurfaceDesc	= &TexSurfaceDesc1;
	/* Set select color type */
	VertexContext01.RenderState	|= KM_COLORTYPE;
	VertexContext01.ColorType	= KM_PACKEDCOLOR;
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContext01);
	Check_Status(status, "kmProcessVertexRenderState");

	/* for 2 parameter object (main) -------------------------------------------  */
	memset( &VertexContext02, 0, sizeof(VertexContext02));	/* Crear Context */
	InitVertexContext(&VertexContext02);					/* Initialize context */

	/* Clear render state */
	VertexContext02.RenderState	= 0;
	/* Set shading mode */
	VertexContext02.RenderState	|= KM_SHADINGMODE;
	VertexContext02.ShadingMode	= KM_TEXTUREGOURAUD;
	/* Set texture surface */
	VertexContext02.pTextureSurfaceDesc	= &TexSurfaceDesc1;
	/* Set select modifier mode */
	VertexContext02.RenderState	|= KM_MODIFIER;
	VertexContext02.SelectModifier	= KM_MODIFIER_A;
	/* Set select color type */
	VertexContext02.RenderState	|= KM_COLORTYPE;
	VertexContext02.ColorType	= KM_PACKEDCOLOR;
#if 0
	/* Set specular mode */
	VertexContext02.RenderState	|= KM_USESPECULAR;
	VertexContext02.bUseSpecular	= TRUE;
#endif
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContext02);
	Check_Status(status, "kmProcessVertexRenderState");

	/* for 2 parameter object (shadow) -------------------------------------------  */
	memset( &VertexContext03, 0, sizeof(VertexContext03));	/* Crear Context */
	InitVertexContext(&VertexContext03);					/* Initialize context */

	/* Clear render state */
	VertexContext03.RenderState	= 0;
	/* Set shading mode */
	VertexContext03.RenderState	|= KM_SHADINGMODE;
	VertexContext03.ShadingMode	= KM_TEXTUREGOURAUD;
	/* Set texture surface */
	VertexContext03.pTextureSurfaceDesc	= &TexSurfaceDesc2;
	/* Process & Set Texture */
	status = kmProcessVertexRenderState(&VertexContext03);
	Check_Status(status, "kmProcessVertexRenderState");

/****************************************************************************/
/**	Background Plane setting ************************************************/
/****************************************************************************/
	/*----------------------------------------------------------------------------------- */
	/* set background plane */
	InitBackGround();

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

/****************************************************************************/
/**	アニメーション **********************************************************/
/****************************************************************************/
void	SceneLoop(void)
{
#if defined(_X86_)
		time_t		ltime;
#endif

		int 		k;
		float		*pV;
		SGLVERTEX	*pSV;
		float		fFogRescale = 1.05f;	/* 大きいほど、霧の影響を強く受ける */
	#if TWO_PASSES
		int 		nFaces;
	#endif

	/*---------------------------------------- Camera */
	/* Change Zoom factor */
	ZoomFactor += ZoomFactorD;
	if((ZoomFactor < 1.0f)||(ZoomFactor > 9.0f)) ZoomFactorD = -ZoomFactorD;
#if 0
	/* Change Camera X size */
	CamXsize += CamXsizeD;
	if((CamXsize < 0.01f)||(CamXsize > 0.9f)) CamXsizeD = -CamXsizeD;
#endif

	SxDash =  ZoomFactor * 0.5f * CamXsize;	/*   zoom factor * 0.5 * CamXSize */
	SyDash = -ZoomFactor * 0.5f * CamYsize;	/* - zoom factor * 0.5 * CamYSize */
	PRINTOUT(("Zoom factor : %8.4f\n", ZoomFactor));
	PRINTOUT(("Cam  X size : %8.4f\n", CamXsize));
	PRINTOUT(("Cam  Y size : %8.4f\n", CamYsize));

	/*---------------------------------------- 行列式によるアフィン変換 */
	Theta += (0.05f / SPEED);				/* Ｙ軸方向回転角の増加 */
	MatrixIdentity(&T);						/* 行列式の初期化 */
	MatrixTranslate(&T, Tra);				/* 平行移動 */
	MatrixScale(&T, Sca);					/* 拡大・縮小 */
	if(move_object) {
		MatrixRotate(&T, km_y_axis, Theta);	/* Y軸回転 */
	}
	else {
		MatrixRotate(&T, km_x_axis, rx);	/* X軸回転 */
		MatrixRotate(&T, km_y_axis, ry);	/* Y軸回転 */
		MatrixRotate(&T, km_z_axis, rz);	/* Z軸回転 */
	}

	/*---------------------------------------- ライトの処理 */
	LightLocal[0] = LightDir[0]*T.Inverse[0][0] + LightDir[1]*T.Inverse[0][1] + LightDir[2]*T.Inverse[0][2];
	LightLocal[1] = LightDir[0]*T.Inverse[1][0] + LightDir[1]*T.Inverse[1][1] + LightDir[2]*T.Inverse[1][2];
	LightLocal[2] = LightDir[0]*T.Inverse[2][0] + LightDir[1]*T.Inverse[2][1] + LightDir[2]*T.Inverse[2][2];
	f1OverLength =  1.0f / (float) sqrt (LightLocal[0]*LightLocal[0] + 
										 LightLocal[1]*LightLocal[1] + 
										 LightLocal[2]*LightLocal[2]);
	LightLocal[0] *= f1OverLength;
	LightLocal[1] *= f1OverLength;
	LightLocal[2] *= f1OverLength;

	pSV = SGLVertices;					/* pSV = SGLVERTEX型構造体へのポインタ */
	pV = (float *) Vertices;			/* pV  = 物体の頂点座標の構造体へのポインタ */

	/*********************************************************** 各頂点の投影変換:SGLVERTEX構造体の生成 */
	for (k = 0; k < NUM_VERTICES; ++k, pV += 3, ++pSV)
	{
		float fXws;
		float fYws;
		float fZws;
		float f1OverZ;
		float fI;
		unsigned char u8Col[3];

		/*------------------------------------------------------ 頂点座標の投影 */
		#if TWO_PASSES
			fDot[k] = 	T.Inverse[0][2] * Normals[k][0] + 
						T.Inverse[1][2] * Normals[k][1] + 
						T.Inverse[2][2] * Normals[k][2];
		#endif
		fXws = (pV[0] * T.Matrix[0][0] + pV[1] * T.Matrix[0][1] + pV[2] * T.Matrix[0][2] + T.Matrix[0][3]) * fFogRescale;
		fYws = (pV[0] * T.Matrix[1][0] + pV[1] * T.Matrix[1][1] + pV[2] * T.Matrix[1][2] + T.Matrix[1][3]) * fFogRescale;
		fZws = (pV[0] * T.Matrix[2][0] + pV[1] * T.Matrix[2][1] + pV[2] * T.Matrix[2][2] + T.Matrix[2][3]) * fFogRescale;

		fZws *= 1.0f / 2000.0f;
		f1OverZ = 1.0f / fZws;

		pSV->fX = (SxDash * fXws * f1OverZ) + OxDash;		/* 投影面上のＸ座標 */
		pSV->fY = (SyDash * fYws * f1OverZ) + OyDash;		/* 投影面上のＹ座標 */
		pSV->fZ = fZws;										/* Dummy奥行き座標 */
		pSV->fInvW = SxDash * f1OverZ;						/* 奥行き情報 */

		/*------------------------------------------------------ 頂点の色の計算 */
		fI = Normals[k][0] * LightLocal[0] + Normals[k][1] * LightLocal[1] + Normals[k][2] * LightLocal[2];
		if (fI < 0.0f)	fI = -fI;
		if (fI > 1.0f)	fI = 1.0f;
		fI *= 0.75f;
		fI += 0.25f;

		u8Col[0] = (unsigned char) (fI * (LightRed   * 0.01f) * 255.0f);
		u8Col[1] = (unsigned char) (fI * (LightGreen * 0.01f) * 255.0f);
		u8Col[2] = (unsigned char) (fI * (LightBlue  * 0.01f) * 255.0f);

		/*------------------------------------------------------- 頂点の透明度の決定 */
		{
			BYTE u8Alpha;
			float f;
			f = (float) cos ((frame * 0.1) + (fYws * 0.02)) + 1.0f;
			u8Alpha = (BYTE) (f * 127.5);
			pSV->u32Colour		= RGBA (u8Col[0], u8Col[1], u8Col[2], u8Alpha);
			pSV->u32Specular	= RGBColour (u8Alpha, u8Alpha, u8Alpha);
		}
		pSV->fUOverW = UVs[k][0]; /* * pSV->fInvW; */
		pSV->fVOverW = UVs[k][1]; /* * pSV->fInvW; */
	}	/* End of for */

	/*----------------------------------------------------------- ？？？？？？？？ */
	#if TWO_PASSES
		nFaces = 0;
		for (k = 0; k < polygons; ++k)
		{
			if ((fDot[Faces[k][0]] + fDot[Faces[k][1]] + fDot[Faces[k][2]]) <= 0.0f)
			{
				SGLFaces[nFaces][0] = Faces[k][0];
				SGLFaces[nFaces][1] = Faces[k][1];
				SGLFaces[nFaces][2] = Faces[k][2];
				nFaces++;
			}
		}

		if (nFaces)
		{
/*			SGLContext.fTranslucentPassDepth = 1.0f; */
/*			sgltri_triangles (&SGLContext, nFaces, SGLFaces, SGLVertices); */
			kmtri_triangles2 (	VertexBufferDesc,	/*	KMVERTEXBUFFDESC	BufferDesc */
								VertexContext02,	/*	KMVERTEXCONTEXT		VertexContext */
								VertexContext03,	/*	KMVERTEXCONTEXT		VertexContext */
								nFaces,				/*	int					nNumFaces */
								SGLFaces,			/*	int					pFaces[][3] */
								SGLVertices			/*	PSGLVERTEX			pVertices */
								);
		}
		nFaces = 0;

		for (k = 0; k < polygons; ++k)
		{
			if ((fDot[Faces[k][0]] + fDot[Faces[k][1]] + fDot[Faces[k][2]]) > 0.0f)
			{
				SGLFaces[nFaces][0] = Faces[k][0];
				SGLFaces[nFaces][1] = Faces[k][1];
				SGLFaces[nFaces][2] = Faces[k][2];
				nFaces++;
			}
		}
		if (nFaces)
		{
/*			SGLContext.fTranslucentPassDepth = 0.0f; */
/*			sgltri_triangles (&SGLContext, nFaces, SGLFaces, SGLVertices); */
			kmtri_triangles2 (	VertexBufferDesc,	/*	KMVERTEXBUFFDESC	BufferDesc */
								VertexContext02,	/*	KMVERTEXCONTEXT		VertexContext */
								VertexContext03,	/*	KMVERTEXCONTEXT		VertexContext */
								nFaces,				/*	int					nNumFaces */
								SGLFaces,			/*	int					pFaces[][3] */
								SGLVertices			/*	PSGLVERTEX			pVertices */
								);
	}
	#else
/*		sgltri_triangles (&SGLContext, polygons, Faces, SGLVertices); */
#if 1	/* 2 parameter */
		kmtri_triangles2 (	VertexBufferDesc,	/*	KMVERTEXBUFFDESC	BufferDesc */
							VertexContext02,	/*	KMVERTEXCONTEXT		VertexContext */
							VertexContext03,	/*	KMVERTEXCONTEXT		VertexContext */
							polygons,			/*	int					nNumFaces */
							Faces,				/*	int					pFaces[][3] */
							SGLVertices			/*	PSGLVERTEX			pVertices */
							);
#endif
#if 0	/* Not 2 parameter */
		kmtri_triangles (	VertexBufferDesc,	/*	KMVERTEXBUFFDESC	BufferDesc */
							VertexContext01,	/*	KMVERTEXCONTEXT		VertexContext */
							polygons,			/*	int					nNumFaces */
							Faces,				/*	int					pFaces[][3] */
							SGLVertices			/*	PSGLVERTEX			pVertices */
							);
#endif
	#endif

/****************************************************************************/
/**	影となる空間の設定 ******************************************************/
/****************************************************************************/
if(shadow_vol_type > 1) {
{
	/*-------------------------------- 影となる空間を定義する頂点座標 */
	float SV[8][3] =
	{
		{-1.0f,	-1.0f,	-1.0f},		/* Vertex 0        5------6   */
		{-1.0f,	-1.0f,   1.0f},		/* Vertex 1       /      /    */
		{ 1.0f,	-1.0f,	 1.0f},		/* Vertex 2      /      / |   */
		{ 1.0f,	-1.0f,	-1.0f},		/* Vertex 3     4------7  |   */
		{-1.0f,	 1.0f,	-1.0f},		/* Vertex 4     |   1  | / 2  */
		{-1.0f,	 1.0f,	 1.0f},		/* Vertex 5     |      |/     */
		{ 1.0f,	 1.0f,	 1.0f},		/* Vertex 6     0------3      */
		{ 1.0f,	 1.0f,	-1.0f}		/* Vertex 7                   */
	};
	/*-------------------------------- 影となる空間を定義する頂点の組み合わせ */
	static int SF[12][3] =
	{
		{0, 5, 4},		/* Face  0  : Left   1 */
		{0, 1, 5},		/* Face  1  : Left   2 */
		{1, 6, 5},		/* Face  2  : Back   1 */
		{1, 2, 6},		/* Face  3  : Back   2 */
		{2, 7, 6},		/* Face  4  : Right  1 */
		{2, 3, 7},		/* Face  5  : Right  2 */
		{3, 4, 7},		/* Face  6  : Front  1 */
		{3, 0, 4},		/* Face  7  : Front  2 */
		{4, 6, 7},		/* Face  8  : Top    1 */
		{4, 5, 6},		/* Face  9  : Top    2 */
		{3, 1, 0},		/* Face 10  : Bottom 1 */
		{3, 2, 1}		/* Face 11  : Bottom 2 */
	};
	/*-------------------------------- 影となる空間に対するジオメトリ演算 */
	SGLVERTEX 	ShadowVertices[8];
	km_vector	SSca = {100.0f, 100.0f,  100.0f};	/* Scaling   : 拡大・縮小量 */
	km_vector	STra = {  0.0f,   0.0f, 1600.0f};	/* Transform : 平行移動量 */
	km_vector	SRot = {  0.5f,   0.5f,    0.5f};	/* Rotation  : 回転軸 */

	MatrixIdentity(&T);								/* 行列式の初期化 */
	MatrixTranslate(&T, STra);						/* 平行移動 */
	MatrixScale(&T, SSca);							/* 拡大・縮小 */
	MatrixRotate(&T, SRot, Theta);					/* 回転 */
	for (k = 0; k < 8; ++k)
	{
		float f1OverZ, fX, fY, fZ;
		fX = (SV[k][0] * T.Matrix[0][0] + 
			  SV[k][1] * T.Matrix[0][1] + 
			  SV[k][2] * T.Matrix[0][2] + T.Matrix[0][3]) * fFogRescale;
		fY = (SV[k][0] * T.Matrix[1][0] + 
			  SV[k][1] * T.Matrix[1][1] + 
			  SV[k][2] * T.Matrix[1][2] + T.Matrix[1][3]) * fFogRescale;
		fZ = (SV[k][0] * T.Matrix[2][0] + 
			  SV[k][1] * T.Matrix[2][1] + 
			  SV[k][2] * T.Matrix[2][2] + T.Matrix[2][3]) * fFogRescale;
		fZ *= (1.0f / 2000.0f);
		f1OverZ = 1.0f / fZ;
		ShadowVertices[k].fX = (SxDash * fX * f1OverZ) + OxDash;
		ShadowVertices[k].fY = (SyDash * fY * f1OverZ) + OyDash;
		ShadowVertices[k].fZ = fZ;
		ShadowVertices[k].fInvW = SxDash * f1OverZ;
	}
	/*----------------------------------------------------------------------------------- */
	/*------ Shadow volume のContextの初期化 */
	/* (1) for First polygon ----------------------------------------------------------- */
	memset( &ModifireContextFirst, 0, sizeof(ModifireContextFirst));	/* Crear Context */
	InitVertexContext(&ModifireContextFirst);	/* Initialize context */

	ModifireContextFirst.RenderState	= 0;
	/* Set param type */
	ModifireContextFirst.RenderState	|= KM_PARAMTYPE;
	ModifireContextFirst.ParamType		= KM_MODIFIERVOLUME;
	/* Set list type */
	ModifireContextFirst.RenderState	|= KM_LISTTYPE;
	ModifireContextFirst.ListType	= KM_OPAQUE_MODIFIER;

	/* Shadow & BBOX */
	ModifireContextFirst.ModifierInstruction = KM_MODIFIER_INCLUDE_FIRST_POLY;
	ModifireContextFirst.fBoundingBoxXmin =   0.0f;
	ModifireContextFirst.fBoundingBoxYmin =   0.0f;
	ModifireContextFirst.fBoundingBoxXmax = 639.0f;
	ModifireContextFirst.fBoundingBoxYmax = 479.0f;
	
	/* Process & Set */
	status = kmProcessVertexRenderState(&ModifireContextFirst);
	Check_Status(status, "ModifireContextFirst");

	/* (2) for Normal polygon ----------------------------------------------------------- */
	memset( &ModifireContextNormal, 0, sizeof(ModifireContextNormal));	/* Crear Context */
	InitVertexContext(&ModifireContextNormal);	/* Initialize context */

	ModifireContextNormal.RenderState	= 0;
	/* Set param type */
	ModifireContextNormal.RenderState	|= KM_PARAMTYPE;
	ModifireContextNormal.ParamType		= KM_MODIFIERVOLUME;
	/* Set list type */
	ModifireContextNormal.RenderState	|= KM_LISTTYPE;
	ModifireContextNormal.ListType	= KM_OPAQUE_MODIFIER;

	/* Shadow & BBOX */
	ModifireContextNormal.ModifierInstruction = KM_MODIFIER_NORMAL_POLY;
	ModifireContextNormal.fBoundingBoxXmin =   0.0f;
	ModifireContextNormal.fBoundingBoxYmin =   0.0f;
	ModifireContextNormal.fBoundingBoxXmax = 639.0f;
	ModifireContextNormal.fBoundingBoxYmax = 479.0f;
	
	/* Process & Set */
	status = kmProcessVertexRenderState(&ModifireContextNormal);
	Check_Status(status, "ModifireContextNormal");

	/* (3) for Last polygon ----------------------------------------------------------- */
	memset( &ModifireContextLast, 0, sizeof(ModifireContextLast));	/* Crear Context */
	InitVertexContext(&ModifireContextLast);	/* Initialize context */

	ModifireContextLast.RenderState	= 0;
	/* Set param type */
	ModifireContextLast.RenderState	|= KM_PARAMTYPE;
	ModifireContextLast.ParamType		= KM_MODIFIERVOLUME;
	/* Set list type */
	ModifireContextLast.RenderState	|= KM_LISTTYPE;
	ModifireContextLast.ListType	= KM_OPAQUE_MODIFIER;

	/* Shadow & BBOX */
	ModifireContextLast.ModifierInstruction = KM_MODIFIER_INCLUDE_LAST_POLY;
	ModifireContextLast.fBoundingBoxXmin =   0.0f;
	ModifireContextLast.fBoundingBoxYmin =   0.0f;
	ModifireContextLast.fBoundingBoxXmax = 639.0f;
	ModifireContextLast.fBoundingBoxYmax = 479.0f;
	
	/* Process & Set */
	status = kmProcessVertexRenderState(&ModifireContextLast);
	Check_Status(status, "ModifireContextLast");

	/*----------------------------------------------------------------------------------- */
	/*------ Shadow volume のVertexの設定  */
	if(disp_shadow_vol)
/*		sgltri_triangles (&SGLContext, 6, SF, ShadowVertices );		// 影となる／照明の当たる空間の設定 */
		kmtri_triangles (	VertexBufferDesc,	/*	KMVERTEXBUFFDESC	BufferDesc */
							VertexContext01,	/*	KMVERTEXCONTEXT		VertexContext */
							12,					/*	int					nNumFaces */
							SF,					/*	int					pFaces[][3] */
							ShadowVertices		/*	PSGLVERTEX			pVertices */
							);
	else
/*		sgltri_shadow (&SGLContext, 6, SF, ShadowVertices, NULL);	// 影となる／照明の当たる空間の設定 */
		kmtri_shadow (	VertexBufferDesc,		/*	KMVERTEXBUFFDESC	BufferDesc */
						ModifireContextFirst,	/*	KMVERTEXCONTEXT		VertexContext(First) */
						ModifireContextNormal,	/*	KMVERTEXCONTEXT		VertexContext(Normal) */
						ModifireContextLast,	/*	KMVERTEXCONTEXT		VertexContext(Last) */
						12,						/*	int					nNumFaces */
						SF,						/*	int					pFaces[][3] */
						ShadowVertices			/*	PSGLVERTEX			pVertices */
						);
}
} /* end of if(gen_shadow_vol) */

/****************************************************************************/
/**	画面描画 ****************************************************************/
/****************************************************************************/

	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_)
	/* render終了の時刻 -----------------------------------------------------------------*/
	if(pcount_f) {
		QueryPerformanceCounter((LARGE_INTEGER*)&Time3i);	/* sgltri_render終了の時刻 */
		OldTime3 = Time3; Time3 = (double)Time3i * freq;
	}
	else {
		OldTime3 = Time3; Time3 = (double)timeGetTime();	/* sgltri_render終了の時刻 */
	}

/* 性能計算 ------------------------------------------------------------------*/
	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++;
	if(frame > 1000000) {	/* フレームのリセット */
		frame = 0;
#if defined(_DISP_PERFORMANCE_)
		totalTime = 0;
#endif	/* defined(_DISP_PERFORMANCE_) */
		frame_2++;
	}
}

/****************************************************************************/
/**	ディスプレィ・デバイスの消去と終了 **************************************/
/****************************************************************************/ 
void	Finish(void)
{
/*	if(!finished) */
/*	{ */

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

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

/*	finished = 1; */
/*	} */
 }

/****************************************************************************/
/**	main ********************************************************************/
/****************************************************************************/ 
int	main(void)
{

#ifdef __GNUC__
	shinobi_workaround();
#endif

	txt_ClearScreen();	/* Clear text screen */
	PRINTOUT(("** Nefertity 2V Latency Opq Modifire Direct**\n"));
	InitScene();	/* Initialize */

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

	Finish();		/* End of render */
	PRINTOUT(("** END Nefertt **\n"));
	return 0;
}

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