//cGraphics header file
#include<windows.h>
#include<d3d9.h>
#include<d3dx9.h>
#include<stdio.h>
#include"CCamera.h"
#define CUSTOMVERTEX_FVF (D3DFVF_XYZ|D3DFVF_NORMAL)
#define DXERROR(function,type) if(FAILED(function)){MessageBox(NULL,type,"Error",MB_OK); return false;}
struct CUSTOMVERTEX
{
float x,y,z;
D3DXVECTOR3 vecNormal;
};
class CGraphics
{
public:
bool Initialize(HINSTANCE hInstance,HWND hWnd); //Set it up
bool Present(void); //Presents the scene
bool LoadHeightMap(void); //Loads and sets up the heightmap
void Cleanup(void); //Release all resources
void SetupMatrices(void); //Handles cameras
bool SetupLights(void); //Adds some light
void CalcTerrainNormals(void); //Calculates the normals of the goraud lighting
CGraphics(void); //Constructor
private:
IDirect3D9 *p_iD3D9;
IDirect3DDevice9 *p_iD3DDevice9;
IDirect3DIndexBuffer9 *p_iD3DIndexBuffer9;
IDirect3DVertexBuffer9 *p_iD3DVertexBuffer9;
CCamera cCamera;
};
bool CGraphics::Initialize(HINSTANCE hInstance,HWND hWnd)
{
p_iD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
DXERROR(p_iD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &p_iD3DDevice9), "Failed to create device");
p_iD3DDevice9->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
p_iD3DDevice9->SetRenderState(D3DRS_ZENABLE, TRUE);
if(LoadHeightMap()==false) //Load the .raw file and setup vertices/indices
{
MessageBox(NULL, "Failed to load heightmap", "Error", MB_OK);
return false;
}
//Initialize dinput camera
if(cCamera.Initialize(hInstance,hWnd)==false)
{
MessageBox(NULL,"Error in camera initialization","Error",MB_OK);
return false;
}
return true;
}
bool CGraphics::Present(void)
{
//Get keyboard state
if(cCamera.GetData()==false)
{
return false;
}
p_iD3DDevice9->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255),1.0f,0);
DXERROR(p_iD3DDevice9->BeginScene(),"Failed to begin scene rendering");
SetupMatrices(); //Setup camera
SetupLights();
// Set the location source of our vertex input stream
DXERROR(p_iD3DDevice9->SetStreamSource( 0, p_iD3DVertexBuffer9,0, sizeof(CUSTOMVERTEX)),"Failed to set streamsource");
// Set the location of our index information to our Index Buffer
DXERROR(p_iD3DDevice9->SetIndices( p_iD3DIndexBuffer9 ),"Failed to set indices")
DXERROR(p_iD3DDevice9->SetFVF(CUSTOMVERTEX_FVF),"Failed to set FVF");
DXERROR(p_iD3DDevice9->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0,
0,
1920*1920,
0,
1919*1919*2), "Failed to draw indexed primitive");
p_iD3DDevice9->EndScene();
RECT rRect;
rRect.left = 0;
rRect.top = 0;
rRect.right = 480;
rRect.bottom = 480;
//Render only from and to the given rect
DXERROR(p_iD3DDevice9->Present(&rRect,&rRect,NULL,NULL), "Failed to present scene")
return true;
}
bool CGraphics::LoadHeightMap(void)
{
FILE *pFile = NULL;
unsigned char iHeightMapArray[1920*1920];; //All the y values
pFile = fopen("Heightmaps\\hmap000.raw", "rb" );
fread(&iHeightMapArray, 1, 1920*1920, pFile );
fclose(pFile);
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
CUSTOMVERTEX vertices[1920*1920];
int dPosition = 0;
for(int i = 0; i<1920; ++i)
{
dPosition = 0;
for(int j = 0; j<1920; ++j)
{
vertices[1920*i+dPosition].x = (float)j;
vertices[1920*i+dPosition].y = (float)iHeightMapArray[i*1919+j]/5;
vertices[1920*i+dPosition].z = (float)i;
//Calculate the normals for vertices
if(i != 0 || i != 1919)//Check so not the first or last row are affected
{
if(dPosition != 0 || dPosition != 1919) //Check so the first and last vertex are not affected
{
//Get the vertex data for the left,right,up and down side vertices
D3DXVECTOR3 vecRight;
vecRight.x = vertices[128*i+dPosition+1].x;
vecRight.y = vertices[128*i+dPosition+1].y;
vecRight.z = vertices[128*i+dPosition+1].z;
D3DXVECTOR3 vecLeft;
vecLeft.x = vertices[128*i+dPosition-1].x;
vecLeft.y = vertices[128*i+dPosition-1].y;
vecLeft.z = vertices[128*i+dPosition-1].z;
D3DXVECTOR3 vecUp;
vecUp.x = vertices[128*i+dPosition+128].x;
vecUp.y = vertices[128*i+dPosition+128].y;
vecUp.z = vertices[128*i+dPosition+128].z;
D3DXVECTOR3 vecDown;
vecDown.x = vertices[128*i+dPosition-128].x;
vecDown.y = vertices[128*i+dPosition-128].y;
vecDown.z = vertices[128*i+dPosition-128].z;
D3DXVECTOR3 vecUpRightCross;
D3DXVECTOR3 vecUpLeftCross;
D3DXVECTOR3 vecDownRightCross;
D3DXVECTOR3 vecDownLeftCross;
D3DXVECTOR3 vecTempUpRightCross;
D3DXVECTOR3 vecTempUpLeftCross;
D3DXVECTOR3 vecTempDownRightCross;
D3DXVECTOR3 vecTempDownLeftCross;
//Add the vector data to get a cross product
vecTempUpRightCross.x = vecUp.x*vecRight.x;
vecTempUpRightCross.y = vecUp.y*vecRight.y;
vecTempUpRightCross.z = vecUp.z*vecRight.z;
vecTempDownRightCross.x = vecDown.x*vecRight.x;
vecTempDownRightCross.y = vecDown.y*vecRight.y;
vecTempDownRightCross.z = vecDown.z*vecRight.z;
vecTempUpLeftCross.x = vecUp.x*vecLeft.x;
vecTempUpLeftCross.y = vecUp.y*vecLeft.y;
vecTempUpLeftCross.z = vecUp.z*vecLeft.z;
vecTempDownLeftCross.x = vecDown.x*vecLeft.x;
vecTempDownLeftCross.y = vecDown.y*vecLeft.y;
vecTempDownLeftCross.z = vecDown.z*vecLeft.z;
//Normalize the cross product
D3DXVec3Normalize(&vecUpRightCross, &vecTempUpRightCross);
D3DXVec3Normalize(&vecUpLeftCross, &vecTempUpLeftCross);
D3DXVec3Normalize(&vecDownLeftCross, &vecTempDownLeftCross);
D3DXVec3Normalize(&vecDownRightCross, &vecTempDownRightCross);
//Fill the temp vector with the normal
D3DXVECTOR3 vecTemp;
D3DXVECTOR3 vecFinal;
vecTemp.x = vecUpRightCross.x+vecUpLeftCross.x+vecDownRightCross.x+vecDownLeftCross.x;
vecTemp.y = vecUpRightCross.y+vecUpLeftCross.y+vecDownRightCross.y+vecDownLeftCross.y;
vecTemp.z = vecUpRightCross.z+vecUpLeftCross.z+vecDownRightCross.z+vecDownLeftCross.z;
//And normalize to the final vector
D3DXVec3Normalize(&vecFinal, &vecTemp);
//Add normal data to the vertex
vertices[1920*i+dPosition].vecNormal.x = vecFinal.x;
vertices[1920*i+dPosition].vecNormal.y = vecFinal.y;
vertices[1920*i+dPosition].vecNormal.z = vecFinal.z;
}
}
dPosition++;
}
}
DXERROR(p_iD3DDevice9->CreateVertexBuffer((1920*1920)*sizeof(CUSTOMVERTEX),
0, CUSTOMVERTEX_FVF, D3DPOOL_DEFAULT,&p_iD3DVertexBuffer9,NULL), "Failed to create vertex buffer");
VOID* pVertices;
DXERROR(p_iD3DVertexBuffer9->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ),
"Failed to lock vertexbuffer");
memcpy( pVertices, vertices, sizeof(vertices) );
DXERROR(p_iD3DVertexBuffer9->Unlock(), "Failed to unlock vertex buffer");
//Now set up the index buffer
WORD dIndices[1919*1919*6];
ZeroMemory(&dIndices, sizeof(dIndices));
long dPos = 0;
for(int y = 0;y < 1919;++y)
{
dPos = 0;
for(int x = 0;x < 1919;++x)
{
dIndices[1919*y*6+dPos] = x + y * (1919 + 1);
dPos++; //Go next
dIndices[1919*y*6+dPos]= x + 1 + y * (1919 + 1); //v2
dPos++; //Go next
dIndices[1919*y*6+dPos] = x + 1 + (y + 1) * (1919 + 1); //v4
dPos++; //Go next
dIndices[1919*y*6+dPos] = x + y * (1919 + 1); //v1
dPos++; //Go next
dIndices[1919*y*6+dPos] = x + 1 + (y + 1) * (1919 + 1); //v4
dPos++; //Go next
dIndices[1919*y*6+dPos] = x + (y + 1) * (1919 + 1); //v3
dPos++;
}
}
DXERROR(p_iD3DDevice9->CreateIndexBuffer((1919*1919*2*3)*sizeof(WORD),0,D3DFMT_INDEX32,D3DPOOL_MANAGED,
&p_iD3DIndexBuffer9,NULL), "Failed to create index buffer");
VOID *p_vData;
DXERROR(p_iD3DIndexBuffer9->Lock(0,sizeof(dIndices),(VOID**)&p_vData,0),
"Failed to lock index buffer");
memcpy(p_vData,dIndices,sizeof(dIndices)); //copy data
DXERROR(p_iD3DIndexBuffer9->Unlock(), "Failed to unlock indexbuffer");
//Set all the pointer to NULL
p_vData = NULL;
pFile= NULL;
pVertices = NULL;
return true;
}
CGraphics::CGraphics(void)
{
p_iD3D9 = NULL;
p_iD3DDevice9= NULL;
p_iD3DIndexBuffer9= NULL;
p_iD3DVertexBuffer9= NULL;
}
void CGraphics::Cleanup(void)
{
cCamera.Release();
if(p_iD3DIndexBuffer9 != NULL)
{
p_iD3DIndexBuffer9->Release();
p_iD3DIndexBuffer9 = NULL;
}
if(p_iD3DVertexBuffer9 != NULL)
{
p_iD3DVertexBuffer9->Release();
p_iD3DVertexBuffer9 = NULL;
}
if(p_iD3DDevice9 != NULL)
{
p_iD3DDevice9->Release();
p_iD3DDevice9 = NULL;
}
if(p_iD3D9 != NULL)
{
p_iD3D9->Release();
p_iD3D9 = NULL;
}
}
void CGraphics::SetupMatrices(void)
{
D3DXMATRIX matWorld;
D3DXMatrixIdentity( &matWorld );
p_iD3DDevice9->SetTransform( D3DTS_WORLD, &matWorld );
//Set up the view. First struct is eye point, next is lookat point
//third is the direction of up, which here is set to the y axis.
D3DXVECTOR3 vecPos;
D3DXVECTOR3 vecLookAt;
cCamera.FillVectors(&vecPos,&vecLookAt);
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView,
&vecPos,
&vecLookAt,
&D3DXVECTOR3(0.0f, 1.0f, 0.0f ) );
p_iD3DDevice9->SetTransform( D3DTS_VIEW, &matView );
//Set up the projection so that I get a far clip at 100 and near
//at 1.
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
p_iD3DDevice9->SetTransform( D3DTS_PROJECTION, &matProj );
}
bool CGraphics::SetupLights(void)
{
D3DMATERIAL9 mtrlTerrain;
ZeroMemory(&mtrlTerrain, sizeof(mtrlTerrain));
mtrlTerrain.Diffuse.r = mtrlTerrain.Ambient.r = 0.0f;
mtrlTerrain.Diffuse.g = mtrlTerrain.Ambient.g = 1.0f;
mtrlTerrain.Diffuse.b = mtrlTerrain.Ambient.b = 0.0f;
mtrlTerrain.Diffuse.a = mtrlTerrain.Ambient.a = 1.0f;
DXERROR(p_iD3DDevice9->SetMaterial(&mtrlTerrain),"Failed to set material"); //Set the light
D3DXVECTOR3 vecLightDir; //Direction of the light
vecLightDir.x = -450.0f;
vecLightDir.y = -1.0f;
vecLightDir.z = -200.0f;
D3DLIGHT9 lghLight;
ZeroMemory(&lghLight, sizeof(lghLight));
lghLight.Type = D3DLIGHT_DIRECTIONAL;
//Diffuse light color
lghLight.Diffuse.r = 1.0f;
lghLight.Diffuse.g = 1.0f;
lghLight.Diffuse.b = 1.0f;
//Normalize the direction vector
D3DXVec3Normalize((D3DXVECTOR3*)&lghLight.Direction, &vecLightDir);
lghLight.Range = 1000.0f; //Wont affect directional lights
DXERROR(p_iD3DDevice9->SetLight(0,&lghLight),"Failed tp set lights"); //Use this light
DXERROR(p_iD3DDevice9->LightEnable(0,TRUE),"Failed to enable light");
p_iD3DDevice9->SetRenderState(D3DRS_LIGHTING,TRUE);
p_iD3DDevice9->SetRenderState(D3DRS_AMBIENT,0x00202020);
p_iD3DDevice9->SetRenderState(D3DRS_LIGHTING,TRUE);
p_iD3DDevice9->SetRenderState(D3DRS_AMBIENT,0x00202020);
return true;
}
This is the class that handles graphics. Gotta go to work so I can´t check it out at the moment. If anyone would notice something strange with the code, please reply.
Oh and ignore those 128:s at the normals calc. I changed them but it didn´t help
Bad Monkey Productions