www.pudn.com > packmk2.rar > tessdemo.cpp


 
//----------------------------------------------------------------------------- 
// File: tessdemo.cpp 
// 
// Desc: Demo of the projective mesh concept 
// 
// Copyright (c) 2003 Claes Johanson 
//----------------------------------------------------------------------------- 
#include  
#include  
#include  
#include  
#include  
#include "dxmouse.h" 
#include "camera.h" 
#include "surface.h" 
 
#include "parameterhandler.h" 
#include "software_noisemaker.h" 
 
surface *sea; 
 
dxmouse *mouse; 
float mouseX=0, mouseY=0; 
float mspeed = 0.005; 
bool drag=false; 
bool text=true; 
 
struct duck 
{ 
	float x,y,z; 
	float y_vel; 
	float angle; 
}; 
 
duck duckie_pos; 
 
 
parameterhandler *prm; 
 
bool	keys[256];			// Array Used For The Keyboard Routine 
 
#define PI	3.1415926535898 
#define		n_cameras 2 
int			active_camera_view = 0, active_camera_mouse = 0; 
camera		*camera_mouse, *camera_view, *cameras[n_cameras]; 
 
#ifdef CPU_NORMALS 
int gridsize_x = 256, gridsize_y = 512;		 
#else 
int gridsize_x = 128, gridsize_y = 256;		 
#endif 
 
//----------------------------------------------------------------------------- 
// Global variables 
//----------------------------------------------------------------------------- 
LPDIRECT3D9             g_pD3D				= NULL; // Used to create the D3DDevice 
LPDIRECT3DDEVICE9       g_pd3dDevice		= NULL; // Our rendering device 
LPDIRECT3DVERTEXBUFFER9 g_pVB				= NULL; // Buffer to hold vertices 
LPDIRECT3DVERTEXBUFFER9 g_pVBproj			= NULL; // Buffer to hold vertices 
 
LPDIRECT3DVERTEXBUFFER9 g_referencePlaneVB	= NULL; 
LPD3DXFONT				g_pd3dxFont			= NULL; 
LPDIRECT3DSURFACE9		g_depthstencil		= NULL; 
LPDIRECT3DTEXTURE9		terrain_texture		= NULL; 
LPD3DXEFFECT			terrain_effect		= NULL; 
LPD3DXMESH				duckie				= NULL; 
LPD3DXMESH				island				= NULL; 
LPD3DXBUFFER duck_Adjacency, duck_Materials, duck_EffectInstances; 
LPD3DXBUFFER island_Adjacency, island_Materials, island_EffectInstances; 
D3DLIGHT9 sun; 
 
// declarations 
void createFont( void ); 
 
//----------------------------------------------------------------------------- 
// Name: InitD3D() 
// Desc: Initializes Direct3D 
//----------------------------------------------------------------------------- 
HRESULT InitD3D( HWND hWnd ) 
{ 
	HRESULT hr; 
	// Create the D3D object. 
	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) 
		return E_FAIL; 
 
	// Set up the structure used to create the D3DDevice 
	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory( &d3dpp, sizeof(d3dpp) ); 
	d3dpp.Windowed = TRUE; 
	//d3dpp.Windowed = FALSE; 
 
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 
	//d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; 
	//d3dpp.BackBufferFormat = D3DFMT_A2R10G10B10; 
	d3dpp.EnableAutoDepthStencil = TRUE; 
	d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; 
	//d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES; 
 
 
 
	// Create the D3DDevice 
	if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
		D3DCREATE_HARDWARE_VERTEXPROCESSING, 
		&d3dpp, &g_pd3dDevice ) ) ) 
	{ 
		return E_FAIL; 
	} 
 
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );		 
	g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); 
	g_pd3dDevice->GetDepthStencilSurface(&g_depthstencil); 
 
	// initialize camera objects 
	cameras[0] = new camera(D3DXVECTOR3(-27,8,0),0.3,450,0,45,1.33,0.3,5000.0); 
	cameras[1] = new camera(D3DXVECTOR3(-150,50,-100),-0.5,-1.3,0,45,1.33,0.1,10000.0); 
	camera_mouse = cameras[active_camera_mouse]; 
	camera_view = cameras[active_camera_view]; 
 
	// Create a font for statistics and help output 
	createFont(); 
 
	// create parameter handler 
	prm = new parameterhandler(); 
	prm->set_float( p_fStrength,	0.9f ); 
	prm->set_bool(	p_bDisplace,	true ); 
	prm->set_int(	p_iOctaves,		8 ); 
	prm->set_float( p_fScale,		0.38f ); 
	prm->set_float( p_fFalloff,		0.607f ); 
	prm->set_float( p_fAnimspeed,	1.4f ); 
	prm->set_float( p_fTimemulti,	1.27f ); 
	prm->set_bool(	p_bPaused,		false ); 
 
	prm->set_float(	p_fLODbias,		0.0f); 
	prm->set_bool(	p_bDisplayTargets, false ); 
	prm->set_float(	p_fElevation,	7.0f ); 
 
	//prm->set_float( p_fSunPosAlpha,		2.7f ); 
	//prm->set_float( p_fSunPosTheta,		0.1f ); 
	prm->set_float( p_fSunPosAlpha,		1.38f ); 
	prm->set_float( p_fSunPosTheta,		1.09f ); 
	prm->set_float( p_fSunShininess,	84.0f ); 
	prm->set_float( p_fSunStrength,		12.0f ); 
 
#ifdef CPU_NORMALS 
	prm->set_bool(	p_bSmooth,			false ); 
#else 
	prm->set_bool(	p_bSmooth,			true ); 
#endif 
	prm->set_float(	p_bReflRefrStrength,0.1f ); 
 
	prm->set_float( p_fWaterColourR,	0.17f ); 
	prm->set_float( p_fWaterColourG,	0.27f ); 
	prm->set_float( p_fWaterColourB,	0.26f ); 
 
	prm->set_bool(	p_bAsPoints,		false ); 
	prm->set_bool(	p_bDrawDuckie,		true ); 
	prm->set_bool(	p_bDrawIsland,		false ); 
	prm->set_bool(	p_bDiffuseRefl,		false ); 
 
	prm->set_active_parameter(p_fStrength); 
 
 
	// create sea object 
	sea = new surface(&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0),gridsize_x,gridsize_y,g_pd3dDevice,cameras[0], prm); 
 
	DWORD n_materials; 
	D3DXLoadMeshFromX( "duckie.x", D3DXMESH_MANAGED, g_pd3dDevice, &duck_Adjacency, &duck_Materials, &duck_EffectInstances, &n_materials, &duckie ); 
	D3DXLoadMeshFromX( "island.x", D3DXMESH_MANAGED, g_pd3dDevice, &island_Adjacency, &island_Materials, &island_EffectInstances, &n_materials, &island );	 
 
	// load terrain texture 
	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "textures/terrain.png", &terrain_texture ) ) ) 
	{ 
		MessageBox(NULL, "Could not find terrain texture", "lalala.exe", MB_OK);		 
	} 
	// load terrain underwater effect 
 
		char *errortext; 
	LPD3DXBUFFER errors; 
	D3DXHANDLE hTechnique; 
 
	D3DXCreateEffectFromFile(g_pd3dDevice, "terrain_underwater.fx",  
		NULL, NULL, 0, NULL, &terrain_effect, &errors ); 
 
	if (errors != NULL){ 
		errortext = (char*) errors->GetBufferPointer(); 
		MessageBox(NULL, errortext, "lalala.exe", MB_OK);		 
	} 
 
	terrain_effect->FindNextValidTechnique(NULL, &hTechnique);     
	terrain_effect->SetTechnique(hTechnique); 
 
 
 
	return S_OK; 
} 
 
void loadpreset(int n) 
{ 
	switch(n) 
	{ 
	case 1: 
		prm->set_float( p_fScale,		0.38f ); 
		prm->set_float( p_fStrength,	0.9f ); 
		prm->set_float( p_fFalloff,		0.607f ); 
		prm->set_float( p_fWaterColourR,	0.07f ); 
		prm->set_float( p_fWaterColourG,	0.11f ); 
		prm->set_float( p_fWaterColourB,	0.11f ); 
		prm->set_float(	p_fLODbias,		0.0f); 
		prm->set_bool(	p_bAsPoints,		false ); 
		prm->set_bool(	p_bDrawDuckie,		true ); 
		prm->set_bool(	p_bDrawIsland,		true ); 
		prm->set_bool(	p_bDiffuseRefl,		false ); 
		break; 
	case 2: 
		prm->set_float( p_fScale,		0.38f ); 
		prm->set_float( p_fStrength,	4.0f ); 
		prm->set_float( p_fFalloff,		0.47f ); 
		prm->set_float( p_fWaterColourR,	0.13f ); 
		prm->set_float( p_fWaterColourG,	0.19f ); 
		prm->set_float( p_fWaterColourB,	0.22f ); 
		prm->set_float(	p_fLODbias,		4.5f); 
		prm->set_bool(	p_bAsPoints,		false ); 
		prm->set_bool(	p_bDrawDuckie,		true ); 
		prm->set_bool(	p_bDrawIsland,		true ); 
		prm->set_bool(	p_bDiffuseRefl,		false ); 
		break; 
	case 3: 
		prm->set_float( p_fScale,		0.38f ); 
		prm->set_float( p_fStrength,	7.0f ); 
		prm->set_float( p_fFalloff,		0.53f ); 
		prm->set_float( p_fWaterColourR,	0.12f ); 
		prm->set_float( p_fWaterColourG,	0.22f ); 
		prm->set_float( p_fWaterColourB,	0.29f ); 
		prm->set_float(	p_fLODbias,		10.0f); 
		prm->set_bool(	p_bAsPoints,		false ); 
		prm->set_bool(	p_bDrawDuckie,		false ); 
		prm->set_bool(	p_bDrawIsland,		false ); 
		prm->set_bool(	p_bDiffuseRefl,		true ); 
		prm->set_float( p_fSunPosAlpha,		2.91f ); 
		prm->set_float( p_fSunPosTheta,		0.36f ); 
		prm->set_float( p_fSunShininess,	1263.0f ); 
		prm->set_float( p_fSunStrength,		208.0f ); 
		break; 
	case 4: 
		prm->set_float( p_fScale,		0.38f ); 
		prm->set_float( p_fStrength,	4.0f ); 
		prm->set_float( p_fFalloff,		0.47f ); 
		prm->set_float( p_fWaterColourR,	0.13f ); 
		prm->set_float( p_fWaterColourG,	0.19f ); 
		prm->set_float( p_fWaterColourB,	0.22f ); 
		prm->set_float(	p_fLODbias,		4.5f); 
		prm->set_bool(	p_bAsPoints,		true ); 
		prm->set_bool(	p_bDrawDuckie,		false ); 
		prm->set_bool(	p_bDrawIsland,		false ); 
		prm->set_bool(	p_bDiffuseRefl,		true ); 
		break; 
	case 5: 
		prm->set_float( p_fScale,		0.197f ); 
		prm->set_float( p_fStrength,	12.9f ); 
		prm->set_float( p_fFalloff,		0.467f ); 
		prm->set_float( p_fWaterColourR,	0.12f ); 
		prm->set_float( p_fWaterColourG,	0.20f ); 
		prm->set_float( p_fWaterColourB,	0.24f ); 
		prm->set_float(	p_fLODbias,			0.0f); 
		prm->set_bool(	p_bAsPoints,		false ); 
		prm->set_bool(	p_bDrawDuckie,		true ); 
		prm->set_bool(	p_bDrawIsland,		true ); 
		prm->set_float( p_fSunPosAlpha,		2.91f ); 
		prm->set_float( p_fSunPosTheta,		0.88f ); 
		prm->set_float( p_fSunShininess,	1263.0f ); 
		prm->set_float( p_fSunStrength,		5270.0f ); 
		prm->set_bool(	p_bDiffuseRefl,		true ); 
		break; 
	case 6: 
		prm->set_float( p_fScale,		0.38f ); 
		prm->set_float( p_fStrength,	11.3f ); 
		prm->set_float( p_fFalloff,		0.56f ); 
		prm->set_float( p_fWaterColourR,	0.17f ); 
		prm->set_float( p_fWaterColourG,	0.27f ); 
		prm->set_float( p_fWaterColourB,	0.26f ); 
		prm->set_float(	p_fLODbias,			0.0f); 
		prm->set_bool(	p_bAsPoints,		false ); 
		prm->set_bool(	p_bDrawDuckie,		true ); 
		prm->set_bool(	p_bDrawIsland,		true ); 
		prm->set_float( p_fSunPosAlpha,		2.91f ); 
		prm->set_float( p_fSunPosTheta,		0.256f ); 
		prm->set_float( p_fSunShininess,	700.0f ); 
		prm->set_float( p_fSunStrength,		200.85f ); 
		prm->set_bool(	p_bDiffuseRefl,		false ); 
		break; 
	} 
} 
 
 
//----------------------------------------------------------------------------- 
// Name: InitGeometry() 
// Desc: Creates the scene geometry 
//----------------------------------------------------------------------------- 
HRESULT InitGeometry() 
{ 
#define color1 0xff000000 
#define color2 0xffff7f7f 
#define color3 0xff007fff 
	// Initialize frustum box 
	CUSTOMVERTEX g_Vertices[] = 
	{ 
		// front 
		{ -1.0f,-1.0f, -1.0f, color1, }, 
		{ +1.0f,-1.0f, -1.0f, color1, }, 
		{ -1.0f,-1.0f, -1.0f, color1, }, 
		{ -1.0f,+1.0f, -1.0f, color1, }, 
		{ +1.0f,-1.0f, -1.0f, color1, }, 
		{ +1.0f,+1.0f, -1.0f, color1, }, 
		{ -1.0f,+1.0f, -1.0f, color1, }, 
		{ +1.0f,+1.0f, -1.0f, color1, }, 
		// back 
		{ -1.0f,-1.0f, +1.0f, color1, }, 
		{ +1.0f,-1.0f, +1.0f, color1, }, 
		{ -1.0f,-1.0f, +1.0f, color1, }, 
		{ -1.0f,+1.0f, +1.0f, color1, }, 
		{ +1.0f,-1.0f, +1.0f, color1, }, 
		{ +1.0f,+1.0f, +1.0f, color1, }, 
		{ -1.0f,+1.0f, +1.0f, color1, }, 
		{ +1.0f,+1.0f, +1.0f, color1, }, 
		// connects 
		{ -1.0f,-1.0f, -1.0f, color1, }, 
		{ -1.0f,-1.0f, +1.0f, color1, }, 
		{ +1.0f,-1.0f, -1.0f, color1, }, 
		{ +1.0f,-1.0f, +1.0f, color1, }, 
		{ -1.0f,+1.0f, -1.0f, color1, }, 
		{ -1.0f,+1.0f, +1.0f, color1, }, 
		{ +1.0f,+1.0f, -1.0f, color1, }, 
		{ +1.0f,+1.0f, +1.0f, color1, }, 
	}; 
		CUSTOMVERTEX g_Vertices2[] = 
	{ 
		// front 
		{ -1.0f,-1.0f, -1.0f, color2, }, 
		{ +1.0f,-1.0f, -1.0f, color2, }, 
		{ -1.0f,-1.0f, -1.0f, color2, }, 
		{ -1.0f,+1.0f, -1.0f, color2, }, 
		{ +1.0f,-1.0f, -1.0f, color2, }, 
		{ +1.0f,+1.0f, -1.0f, color2, }, 
		{ -1.0f,+1.0f, -1.0f, color2, }, 
		{ +1.0f,+1.0f, -1.0f, color2, }, 
		// back 
		{ -1.0f,-1.0f, +1.0f, color2, }, 
		{ +1.0f,-1.0f, +1.0f, color2, }, 
		{ -1.0f,-1.0f, +1.0f, color2, }, 
		{ -1.0f,+1.0f, +1.0f, color2, }, 
		{ +1.0f,-1.0f, +1.0f, color2, }, 
		{ +1.0f,+1.0f, +1.0f, color2, }, 
		{ -1.0f,+1.0f, +1.0f, color2, }, 
		{ +1.0f,+1.0f, +1.0f, color2, }, 
		// connects 
		{ -1.0f,-1.0f, -1.0f, color2, }, 
		{ -1.0f,-1.0f, +1.0f, color2, }, 
		{ +1.0f,-1.0f, -1.0f, color2, }, 
		{ +1.0f,-1.0f, +1.0f, color2, }, 
		{ -1.0f,+1.0f, -1.0f, color2, }, 
		{ -1.0f,+1.0f, +1.0f, color2, }, 
		{ +1.0f,+1.0f, -1.0f, color2, }, 
		{ +1.0f,+1.0f, +1.0f, color2, }, 
	}; 
 
	CUSTOMVERTEX g_plane[] = { 
		{ -200.0f, 0.0f, -200.0f, 0x7f00007f, }, 
		{ 200.0f, 0.0f, -200.0f, 0x7f00007f, }, 
		{ 200.0f, 0.0f, 200.0f, 0x7f00007f, }, 
		{ -200.0f, 0.0f, 200.0f, 0x7f00007f, }, 
	}; 
 
	// Create the vertex buffer. 
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( 24*sizeof(CUSTOMVERTEX), 
		0, D3DFVF_CUSTOMVERTEX, 
		D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) 
	{ 
		return E_FAIL; 
	} 
 
	// Fill the vertex buffer. 
	VOID* pVertices; 
	if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) ) 
		return E_FAIL; 
	memcpy( pVertices, g_Vertices, sizeof(g_Vertices) ); 
	g_pVB->Unlock(); 
 
	 
	// Create the vertex buffer. 
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( 24*sizeof(CUSTOMVERTEX), 
		0, D3DFVF_CUSTOMVERTEX, 
		D3DPOOL_DEFAULT, &g_pVBproj, NULL ) ) ) 
	{ 
		return E_FAIL; 
	} 
 
	// Fill the vertex buffer.	 
	if( FAILED( g_pVBproj->Lock( 0, sizeof(g_Vertices2), (void**)&pVertices, 0 ) ) ) 
		return E_FAIL; 
	memcpy( pVertices, g_Vertices2, sizeof(g_Vertices2) ); 
	g_pVBproj->Unlock(); 
 
	// Create the vertex buffer. 
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX), 
		0, D3DFVF_CUSTOMVERTEX, 
		D3DPOOL_DEFAULT, &g_referencePlaneVB, NULL ) ) ) 
	{ 
		return E_FAIL; 
	} 
 
	// Fill the vertex buffer. 
 
	if( FAILED( g_referencePlaneVB->Lock( 0, sizeof(g_plane), (void**)&pVertices, 0 ) ) ) 
		return E_FAIL; 
	memcpy( pVertices, g_plane, sizeof(g_plane) ); 
	g_referencePlaneVB->Unlock(); 
 
	return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Cleanup() 
// Desc: Releases all previously initialized objects 
//----------------------------------------------------------------------------- 
VOID Cleanup() 
{ 
	if( g_pVB != NULL ) 
		g_pVB->Release(); 
 
	if( g_pd3dDevice != NULL ) 
		g_pd3dDevice->Release(); 
 
	if( g_pD3D != NULL ) 
		g_pD3D->Release(); 
} 
 
 
 
//----------------------------------------------------------------------------- 
// Name: SetupMatrices() 
// Desc: Sets up the world, view, and projection transform matrices. 
//----------------------------------------------------------------------------- 
VOID SetupMatrices() 
{ 
	D3DXMATRIXA16 matWorld,matProj; 
	D3DXMatrixIdentity(&matWorld); 
	g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); 
	g_pd3dDevice->SetTransform( D3DTS_VIEW, &(camera_view->view) ); 
	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &(camera_view->proj) ); 
} 
 
 
 
float getheight(float x, float z) 
{ 
	//	return displacement*0.5*(1+sin(0.15*x)*sin(z)); 
	return 0; 
} 
 
set_clipplane_height(float height) 
{ 
	float plane[4]; 
 
	g_pd3dDevice->GetClipPlane(0,plane); 
 
	plane[3] = height; 
 
	g_pd3dDevice->SetClipPlane(0,plane); 
} 
 
enum rs_mode { 
	rsm_normal=0, 
	rsm_refraction, 
	rsm_reflection, 
	rsm_reflection_backface, 
}; 
 
void render_scene(int mode) 
{ 
	// if displaced==true, objects should be displaced according to the waveheight at their location, so the reflections will match 
 
	// set lightning 
	sun.Direction.x = -cos(prm->get_float(p_fSunPosTheta))*sin(prm->get_float(p_fSunPosAlpha)); 
	sun.Direction.y = -sin(prm->get_float(p_fSunPosTheta)); 
	sun.Direction.z = -cos(prm->get_float(p_fSunPosTheta))*cos(prm->get_float(p_fSunPosAlpha)); 
	if(mode==rsm_reflection) 
	{ 
		//sun.Direction.x = -sun.Direction.x; 
		sun.Direction.y = -sun.Direction.y; 
		//sun.Direction.z = -sun.Direction.z; 
	} 
	sun.Diffuse.r = 2.0f; 
	sun.Diffuse.g = 2.0f; 
	sun.Diffuse.b = 2.0f; 
	sun.Diffuse.a = 1.0f; 
	sun.Ambient.a = 1.0f; 
	sun.Ambient.r = 0.2f; 
	sun.Ambient.g = 0.3f; 
	sun.Ambient.b = 0.3f; 
	sun.Specular.r = 1.0f; 
	sun.Specular.g = 1.0f; 
	sun.Specular.b = 1.0f; 
	sun.Specular.a = 1.0f; 
 
	sun.Attenuation0 = 1.0f; 
	sun.Type = D3DLIGHT_DIRECTIONAL; 
	g_pd3dDevice->SetLight(0, &sun); 
	g_pd3dDevice->LightEnable( 0, true);		 
 
	// draw the badanka 
	if (mode!=rsm_refraction) 
	{ 
		D3DXMATRIXA16 store, offset, yrot,scale; 
		g_pd3dDevice->GetTransform(D3DTS_WORLD,&store); 
		float duckX = -15, duckZ = -5; 
		if (mode == rsm_normal) 
			D3DXMatrixTranslation( &offset, duckie_pos.x, duckie_pos.y, duckie_pos.z); 
		else if(mode == rsm_reflection) 
			D3DXMatrixTranslation( &offset, duckie_pos.x, -duckie_pos.y + sea->get_height_at(duckie_pos.x,duckie_pos.z), duckie_pos.z); 
		else 
			D3DXMatrixTranslation( &offset, duckie_pos.x, 1.33*duckie_pos.y, duckie_pos.z); 
 
		g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &offset ); 
		D3DXMatrixRotationY( &yrot, duckie_pos.angle); 
		g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &yrot ); 
		D3DXMatrixScaling( &scale, 3, 3, 3 ); 
		g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale ); 
 
		//g_pd3dDevice->SetMaterial((D3DMATERIAL9*)duck_Materials->GetBufferPointer()); 
		g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, true); 
 
		g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 ); 
		g_pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR1 ); 
		g_pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1 ); 
 
		set_clipplane_height(sea->get_height_at(duckX,duckZ) + 0.1); 
		if (prm->get_bool(p_bDrawDuckie)) duckie->DrawSubset(0);		 
 
 
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &store); 
	} 
	sun.Diffuse.r = 1.0f; 
	sun.Diffuse.g = 1.0f; 
	sun.Diffuse.b = 1.0f; 
	g_pd3dDevice->SetLight(0, &sun); 
	if (prm->get_bool(p_bDrawIsland))  
	{	 
		if (mode == rsm_refraction) 
		{ 
			//g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );	//lalal 
			 
			LPDIRECT3DVERTEXBUFFER9 vb; 
			LPDIRECT3DINDEXBUFFER9 ib; 
			island->GetVertexBuffer(&vb); 
			island->GetIndexBuffer(&ib);	 
			g_pd3dDevice->SetStreamSource(0, vb, 0, island->GetNumBytesPerVertex()); 
			g_pd3dDevice->SetIndices(ib); 
			g_pd3dDevice->SetFVF( island->GetFVF() ); 
 
			terrain_effect->Begin(NULL,NULL); 
			terrain_effect->Pass(0);			 
			terrain_effect->SetMatrix("mViewProj",&(camera_view->viewproj)); 
			terrain_effect->SetMatrix("mView",&(camera_view->view));			 
			float sa = prm->params[p_fSunPosAlpha].fData, st = prm->params[p_fSunPosTheta].fData; 
			terrain_effect->SetVector("sun_vec",&D3DXVECTOR4(cos(st)*sin(sa), sin(st), cos(st)*cos(sa),0)); 
			terrain_effect->SetFloat("sun_shininess", prm->params[p_fSunShininess].fData);			 
			terrain_effect->SetFloat("sun_strength", prm->params[p_fSunStrength].fData); 
			terrain_effect->SetVector("watercolour", &D3DXVECTOR4(prm->params[p_fWaterColourR].fData,prm->params[p_fWaterColourG].fData,prm->params[p_fWaterColourB].fData,1)); 
			terrain_effect->SetVector("view_position", &D3DXVECTOR4(camera_view->position.x,camera_view->position.y,camera_view->position.z,1)); 
			terrain_effect->SetTexture("texDiffuse",terrain_texture);						 
		 
			g_pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST, 0,	0, island->GetNumVertices(), 0, island->GetNumFaces() );				 
			terrain_effect->End(); 
		} else { 
 
			//g_pd3dDevice->SetMaterial((D3DMATERIAL9*)duck_Materials->GetBufferPointer()); 
			g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, true); 
 
			g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ); 
			g_pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL ); 
			g_pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL ); 
			g_pd3dDevice->SetTexture(0, terrain_texture); 
 
			/*D3DXATTRIBUTERANGE AttribTable; 
			DWORD AttribTableSize; 
			island->GetAttributeTable( &AttribTable, &AttribTableSize);*/ 
			//AttribTable 
			set_clipplane_height(0); 
			for(int i=0; i<7; i++) 
			{ 
				LPD3DXMATERIAL mat = (LPD3DXMATERIAL) island_Materials->GetBufferPointer();			 
				g_pd3dDevice->SetMaterial(&(mat->MatD3D)); 
				island->DrawSubset(i); 
			}					 
		} 
	}	 
 
	// restore stuff 
	g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false);		 
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  ); 
} 
 
void render_refracted_scene() 
{ 
	// set rendertarget 
	LPDIRECT3DSURFACE9 target,bb; 
	g_pd3dDevice->GetRenderTarget(0, &bb ); 
	sea->surf_refraction->GetSurfaceLevel( 0,&target ); 
	g_pd3dDevice->SetRenderTarget(0, target); 
 
	/*g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_ZBUFFER, 0, 1.0f, 0 ); 
	sea->render_cutter(); 
	g_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_GREATEREQUAL  );	*/ 
 
	g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB((int)(255*prm->params[p_fWaterColourR].fData),(int)(255*prm->params[p_fWaterColourG].fData),(int)(255*prm->params[p_fWaterColourB].fData)), 1.0f, 0 ); 
	D3DXMATRIXA16 store, scale;	 
	// squach the scene 
	g_pd3dDevice->GetTransform(D3DTS_WORLD,&store); 
	D3DXMatrixScaling( &scale, 1, 0.75, 1 ); 
	g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale ); 
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW  );	 
	// add a clip-plane as well	 
	float plane[4]; 
 
	plane[0] = 0; 
	plane[1] = -1; 
	plane[2] = 0; 
	plane[3] = 1.7*prm->params[p_fStrength].fData;	// a slight offset to avoid seams 
 
	g_pd3dDevice->SetClipPlane(0,plane); 
	//g_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 1); 
 
	render_scene(rsm_refraction); 
 
	// restore	 
	g_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); 
	g_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0); 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &store);	 
	g_pd3dDevice->SetRenderTarget(0, bb); 
} 
 
 
void render_actual_scene() 
{ 
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW  );	 
	g_pd3dDevice->SetDepthStencilSurface(g_depthstencil); 
	render_scene(rsm_normal); 
} 
 
void render_reflected_scene() 
{ 
	// set rendertarget 
	LPDIRECT3DSURFACE9 target,bb; 
	g_pd3dDevice->GetRenderTarget(0, &bb ); 
	sea->surf_reflection->GetSurfaceLevel( 0,&target ); 
	g_pd3dDevice->SetRenderTarget(0, target); 
	g_pd3dDevice->SetDepthStencilSurface( sea->depthstencil ); 
 
	// alpha & z must be cleared 
	g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0 ); 
 
	D3DXMATRIXA16 store, scale;	 
	// mirror the scene 
	g_pd3dDevice->GetTransform(D3DTS_WORLD,&store); 
	D3DXMatrixScaling( &scale, 1, -1, 1 ); 
	g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale ); 
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );		 
 
	// add a clip-plane as well	 
	float plane[4]; 
 
	plane[0] = 0; 
	plane[1] = -1; 
	plane[2] = 0; 
	plane[3] = 0; 
 
	g_pd3dDevice->SetClipPlane(0,plane); 
	g_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 1); 
	//g_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 1); 
 
	//g_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER ); 
 
	render_scene(rsm_reflection); 
 
	//g_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA ); 
	//g_pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, false); 
	/*D3DMATERIAL9 noalpha; 
	noalpha.Diffuse.g = 255; 
	noalpha.Diffuse.a = 0; 
	noalpha.Ambient.a = 0; 
	noalpha.Specular.a = 0; 
	g_pd3dDevice->SetMaterial(&noalpha); 
	g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL ); 
	g_pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL ); 
	g_pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL ); 
	sea->render_cutter(); 
	g_pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, true); 
	g_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F );*/ 
 
	// restore 
	g_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0); 
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &store);	 
	g_pd3dDevice->SetRenderTarget(0, bb); 
	g_pd3dDevice->SetDepthStencilSurface( g_depthstencil ); 
} 
 
//----------------------------------------------------------------------------- 
// Name: Render() 
// Desc: Draws everything 
//----------------------------------------------------------------------------- 
void Render() 
{	 
	static DWORD it=0; 
	static DWORD time_prepare, time_total, time_total_start; 
	it++; 
	// measure fps 
	if (it>63) 
	{ 
		time_total = timeGetTime() - time_total_start; 
		time_total_start = timeGetTime(); 
		it = 0; 
	} 
 
	// update mouse & kbd 
	mouse->Update(); 
	float movespeed; 
	if( GetAsyncKeyState(VK_LCONTROL) != 0) 
	{ 
		mspeed = 0.0001; 
		movespeed = 0.03f; 
	}  
	else if( GetAsyncKeyState(VK_LSHIFT) != 0) 
	{ 
		mspeed = 0.05; 
		movespeed = 5.0f; 
	}  
	else 
	{ 
		mspeed = 0.005; 
		movespeed = 0.3f; 
	} 
 
	// keys 
 
	if(keys['A']) 
		camera_mouse->position -= movespeed*camera_mouse->right; 
	if(keys['D']) 
		camera_mouse->position += movespeed*camera_mouse->right; 
	if(keys['W']) 
		camera_mouse->position += movespeed*camera_mouse->forward; 
	if(keys['S']) 
		camera_mouse->position -= movespeed*camera_mouse->forward; 
	if(keys['Q']) 
		camera_mouse->position += movespeed*camera_mouse->up; 
	if(keys['Z']) 
		camera_mouse->position -= movespeed*camera_mouse->up; 
	camera_mouse->update(); 
 
	if(mouse->mousedown(MOUSE_LEFT)){ 
		camera_mouse->roty -= 0.005 * mouse->x; 
		camera_mouse->rotx -= 0.005 * mouse->y; 
		camera_mouse->update(); 
	} else if(mouse->mousedown(MOUSE_RIGHT)){ 
		camera_mouse->position += 5 * mspeed * mouse->x * camera_mouse->right; 
		camera_mouse->position -= 5 * mspeed * mouse->y * camera_mouse->up; 
		camera_mouse->update(); 
	} else if(mouse->mousedown(MOUSE_MIDDLE)){ 
		camera_mouse->position -= 10*mspeed * mouse->y * camera_mouse->forward; 
		//camera_mouse->rotz -= mspeed * mouse->x;		 
		camera_mouse->update(); 
	}  
 
	DWORD time_prepare_start = timeGetTime(); 
	sea->prepare(camera_view); 
	time_prepare = timeGetTime() - time_prepare_start; 
 
	// move the duck 
	duckie_pos.angle += 0.001; 
	if (duckie_pos.angle > (2*PI)) duckie_pos.angle -= 2*PI; 
	duckie_pos.x = 20*cos(duckie_pos.angle); 
	duckie_pos.z = -20*sin(duckie_pos.angle); 
	float new_y = sea->get_height_at(duckie_pos.x,duckie_pos.z); 
	duckie_pos.y_vel = new_y - duckie_pos.y; 
	duckie_pos.y += 0.2*duckie_pos.y_vel; 
 
 
	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) 
	{			 
		// Setup the world, view, and projection matrices (this is used to render the frustum) 
		SetupMatrices(); 
 
		 
		// render reflections/refractions into textures 
//#ifdef REFRACTION 
		render_refracted_scene(); 
//#endif 
		 
		render_reflected_scene();		 
 
		if (prm->get_bool(p_bAsPoints)) 
			g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255,255), 1.0f, 0 ); 
		else 
			g_pd3dDevice->Clear( 0, NULL,D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, D3DCOLOR_XRGB((int)(255*prm->params[p_fWaterColourR].fData),(int)(255*prm->params[p_fWaterColourG].fData),(int)(255*prm->params[p_fWaterColourB].fData)), 1.0f, 0 );	 
		 
		// Begin the scene		 
 
		// set rendering states		 
		g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 
		g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true); 
		g_pd3dDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL); 
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,false);		 
 
		// render sea 
		if (!prm->get_bool(p_bAsPoints))	sea->render_skybox(); 
		sea->render();	 
 
		render_actual_scene();		 
 
		//D3DRS_BLENDOP 
		// Render the camera frustum		 
		if(active_camera_view == 1) 
		{ 
			{ 
				D3DXMATRIXA16 store; 
				g_pd3dDevice->GetTransform(D3DTS_WORLD,&store); 
				g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &(cameras[0]->invviewproj)); 
				g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); 
				g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); 
				g_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, 12 ); 
 
				g_pd3dDevice->SetTransform(D3DTS_WORLD, &store); 
			} 
			// Render the projector frustum		 
			{ 
				D3DXMATRIXA16 store; 
				g_pd3dDevice->GetTransform(D3DTS_WORLD,&store); 
				g_pd3dDevice->MultiplyTransform(D3DTS_WORLD, &(sea->projecting_camera->invviewproj)); 
				g_pd3dDevice->SetStreamSource( 0, g_pVBproj, 0, sizeof(CUSTOMVERTEX) ); 
				g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); 
				g_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, 12 ); 
 
				g_pd3dDevice->SetTransform(D3DTS_WORLD, &store); 
			} 
		} 
 
		// render the reference plane 
		/* 
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true); 
		g_pd3dDevice->SetStreamSource( 0, g_referencePlaneVB, 0, sizeof(CUSTOMVERTEX) ); 
		g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); 
		g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 ); 
		*/			 
 
 
		// Draw text		 
		if (text) 
		{ 
			//		g_pd3dxFont->Begin();		 
 
			RECT textpos; 
			char textString[900],activecamera[16],view[16]; 
			SetRect( &textpos, 5, 5, 0, 0 ); 
 
			if(camera_mouse==cameras[0]) 
				sprintf(activecamera,"tesselating"); 
			else if(camera_mouse==cameras[1]) 
				sprintf(activecamera,"observing"); 
 
			if(camera_view==cameras[0]) 
				sprintf(view,"primary"); 
			else if(camera_view==cameras[1]) 
				sprintf(view,"observer"); 
 
			sprintf( textString, "Mouse is currently controlling the %s camera (switch with TAB)\n",activecamera); 
			sprintf( textString, "%sefficiency: %.2f percent  \n",textString,100*sea->efficiency); 
			sprintf( textString, "%sdetail: %ix%i\n",textString,gridsize_x,gridsize_y); 
			sprintf( textString, "%sview(switch with 'c'): %s\n",textString,view); 
			//sprintf( textString, "%s\n%s",textString, sea->debugdata); 
			sprintf( textString, "%stime_prepare: %i\ntotal time: %f\nframerate: %f Hz\n",textString,time_prepare, (double)time_total/64.0f,64000.0f/((float)(time_total))); 
			//		sprintf( textString, "%sn_points: %i\n",textString,n_points); 
			//		sprintf( textString, "%sx_min: %f x_max: %f y_min: %f y_max: %f ",textString,x_min,x_max,y_min,y_max); 
 
			g_pd3dxFont->DrawText(NULL, textString,-1,&textpos,DT_NOCLIP,D3DXCOLOR( 0.0f, 0.0f, 0.0f, 1.0f )); 
 
			sprintf( textString, "%s\n", prm->get_display() ); 
			textpos.top = 200; 
			g_pd3dxFont->DrawText(NULL, textString,-1,&textpos,DT_NOCLIP,D3DXCOLOR( 1.0f, 0.5f, 0.5f, 1.0f )); 
			//		g_pd3dxFont->End(); 
		} 
 
		// End the scene 
		g_pd3dDevice->EndScene(); 
	} 
	// Present the backbuffer contents to the display 
 
 
	//LPDIRECT3DSWAPCHAIN9 SwapChain; 
	//g_pd3dDevice->GetSwapChain( 0,&SwapChain); 
	//SwapChain->Present( NULL, NULL, NULL, NULL, D3DPRESENT_LINEAR_CONTENT );			 
 
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL );	 
} 
 
 
 
//----------------------------------------------------------------------------- 
// Name: MsgProc() 
// Desc: The window's message handler 
//----------------------------------------------------------------------------- 
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) 
{ 
	switch( msg ) 
	{ 
	case WM_DESTROY: 
		Cleanup(); 
		PostQuitMessage( 0 ); 
		return 0; 
	case WM_KEYDOWN:							// Is A Key Being Held Down? 
		{			 
			keys[wParam] = TRUE;					// If So, Mark It As TRUE 
			// preset handling 
			if (keys['1']) 
			{ 
				loadpreset(1); 
				return 0; 
			} 
			if (keys['2']) 
			{ 
				loadpreset(2); 
				return 0; 
			} 
			if (keys['3']) 
			{ 
				loadpreset(3); 
				return 0; 
			} 
			if (keys['4']) 
			{ 
				loadpreset(4); 
				return 0; 
			} 
			if (keys['5']) 
			{ 
				loadpreset(5); 
				return 0; 
			} 
			if (keys['6']) 
			{ 
				loadpreset(6); 
				return 0; 
			} 
			if (keys['T']) 
			{ 
				text = !text; 
				return 0; 
			} 
			// other keys 
			if (keys[VK_TAB]) 
			{ 
				active_camera_mouse = (active_camera_mouse+1)%n_cameras; 
				camera_mouse = cameras[active_camera_mouse]; 
				return 0; 
			} 
			if (keys['C']) 
			{ 
				active_camera_view = (active_camera_view+1)%n_cameras; 
				camera_view = cameras[active_camera_view]; 
				return 0; 
			}  
			if (keys['E']) 
			{ 
				sea->calc_efficiency(); 
				return 0; 
			}  
			if (keys['0'])  
			{ 
				prm->value_reset(); 
				return 0; 
			} 
 
			if (keys[VK_PRIOR]){ 
				gridsize_x = gridsize_x<<1; 
				sea->set_grid_size(gridsize_x,gridsize_y); 
				return 0; 
			} 
			if (keys[VK_NEXT]){ 
				gridsize_x = gridsize_x>>1; 
				if (gridsize_x<2) gridsize_x = 2; 
				sea->set_grid_size(gridsize_x,gridsize_y); 
				return 0; 
			} 
			if (keys[VK_HOME]){ 
				gridsize_y = gridsize_y<<1; 
				sea->set_grid_size(gridsize_x,gridsize_y); 
				return 0; 
			} 
			if (keys[VK_END]){ 
				gridsize_y = gridsize_y>>1; 
				if (gridsize_y<2) gridsize_y = 2; 
				sea->set_grid_size(gridsize_x,gridsize_y); 
				return 0; 
			} 
			if (keys[VK_SUBTRACT]) 
			{ 
				prm->value_decrease(); 
				return 0; 
			} 
			if (keys[VK_ADD]) 
			{ 
				prm->value_increase();				 
				return 0; 
			} 
 
			if (keys[VK_LEFT]) 
			{ 
				prm->value_decreaseXL(); 
				return 0; 
			} 
			if (keys[VK_RIGHT]) 
			{ 
				prm->value_increaseXL(); 
				return 0; 
			} 
			if (keys[VK_UP]) 
			{ 
				prm->previous_parameter(); 
				return 0; 
			} 
			if (keys[VK_DOWN]) 
			{ 
				prm->next_parameter(); 
				return 0; 
			}			 
 
			return 0;								// Jump Back 
		} 
 
	case WM_KEYUP:								// Has A Key Been Released? 
		{ 
			keys[wParam] = FALSE;					// If So, Mark It As FALSE 
			return 0;								// Jump Back 
		} 
 
	} 
 
	return DefWindowProc( hWnd, msg, wParam, lParam ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: WinMain() 
// Desc: The application's entry point 
//----------------------------------------------------------------------------- 
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) 
{ 
	// Register the window class 
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL, 
		"D3D Tutorial", NULL }; 
	RegisterClassEx( &wc ); 
 
	// Create the application's window 
	HWND hWnd = CreateWindow( "D3D Tutorial", "Projected grid concept demo", 
		WS_OVERLAPPEDWINDOW, 100, 100, 1024, 768, 
		GetDesktopWindow(), NULL, wc.hInstance, NULL ); 
	// init mouse 
	mouse = new dxmouse(hWnd,hInst); 
	mouse->Init(); 
 
	// Initialize Direct3D 
	if( SUCCEEDED( InitD3D( hWnd ) ) ) 
	{ 
		// Create the scene geometry 
		if( SUCCEEDED( InitGeometry() ) ) 
		{ 
			// Show the window 
			ShowWindow( hWnd, SW_SHOWDEFAULT ); 
			UpdateWindow( hWnd ); 
 
			// Enter the message loop 
			MSG msg; 
			ZeroMemory( &msg, sizeof(msg) ); 
			while( msg.message!=WM_QUIT ) 
			{ 
				if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) 
				{ 
					TranslateMessage( &msg ); 
					DispatchMessage( &msg ); 
				} 
				else 
					Render(); 
			} 
		} 
	} 
 
	UnregisterClass( "D3D Tutorial", wc.hInstance ); 
	return 0; 
} 
 
 
 
//----------------------------------------------------------------------------- 
// Name: createFont() 
// Desc:  
//----------------------------------------------------------------------------- 
void createFont( void ) 
{ 
	// 
	// To create a Windows friendly font using only a point size, an  
	// application must calculate the logical height of the font. 
	//  
	// This is because functions like CreateFont() and CreateFontIndirect()  
	// only use logical units to specify height. 
	// 
	// Here's the formula to find the height in logical pixels: 
	// 
	//             -( point_size * LOGPIXELSY ) 
	//    height = ---------------------------- 
	//                          72 
	// 
 
	HRESULT hr; 
	HDC hDC; 
	HFONT hFont; 
	int nHeight; 
	int nPointSize = 7; 
	char strFontName[] = "Verdana"; 
 
	hDC = GetDC( NULL ); 
 
	nHeight = -( MulDiv( nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ) ); 
 
 
	hFont = CreateFont( nHeight,  
		0, 0, 0, 
		FW_DONTCARE, 
		false, false, false, 
		DEFAULT_CHARSET, 
		OUT_DEFAULT_PRECIS, 
		CLIP_DEFAULT_PRECIS, 
		DEFAULT_QUALITY, 
		DEFAULT_PITCH | FF_DONTCARE, 
		strFontName ); 
 
	if( hFont != NULL ) 
	{ 
 
		//if( FAILED( D3DXCreateFont( g_pd3dDevice, hFont, &g_pd3dxFont ) ) ) 
		if( FAILED( D3DXCreateFont( g_pd3dDevice,nHeight, 5, 1, 1, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, strFontName, &g_pd3dxFont ) ) ) 
		{ 
			MessageBox(NULL,"Call to D3DXCreateFont failed!", "ERROR",MB_OK|MB_ICONEXCLAMATION); 
		} 
 
 
		DeleteObject( hFont ); 
	} 
	else 
	{ 
		MessageBox(NULL,"Call to CreateFont failed!", "ERROR",MB_OK|MB_ICONEXCLAMATION); 
	} 
 
}