NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
GRID.CPP
Go to the documentation of this file.
00001 
00012 #include <stdio.h>
00013 #include <math.h>
00014 #include <windows.h>
00015 #include <d3d9.h>
00016 #include <d3dx9tex.h>
00017 #include <Dxerr.h>
00018 #include <string>
00019 
00020 #include "grid.h"
00021 
00022 Grid::Grid(
00023     const MAP& map,
00024     D3DXVECTOR3 *v0P,
00025     D3DXVECTOR3 *v1P,
00026     D3DXVECTOR3 *v2P,
00027     D3DXVECTOR3 *v3P
00028     ) {
00029   this->widthVertices = map.width;
00030   this->heightVertices = map.height;
00031 
00032   this->numVertices = this->widthVertices * this->heightVertices;
00033   this->widthFaces = this->widthVertices - 1;
00034   this->heightFaces = this->heightVertices - 1;
00035   this->numFaces = this->widthFaces * this->heightFaces * 2; // 2 triangles in each grid cell
00036   this->v0 = *v0P;
00037   this->v1 = *v1P;
00038   this->v2 = *v2P;
00039   this->v3 = *v3P;
00040   this->dv = this->v2 - this->v0;
00041   this->dv.x /= float(this->widthVertices - 1);
00042   this->dv.y /= 1;
00043   this->dv.z /= float(this->heightVertices - 1);
00044 
00045   this->scale = 1.0f;
00046   this->vOffset = 0.0f;
00047   this->uOffset = 0.0f;
00048   
00049   this->vertices = NULL;
00050   this->mesh = NULL;
00051 
00052   int i, j, k;
00053 
00054   // set up the vertex and normal and texture data
00055   this->vertices = new GRIDVERTEX[this->numVertices];
00056   
00057   D3DXVECTOR3 a, b;
00058   
00059   for (j = 0, k = 0; j < this->heightVertices; j++) {
00060     for (i = 0; i < this->widthVertices; i++, k++) {
00061       // Set vertex position
00062       vertices[k].position.x = this->v0.x + float(i) * this->dv.x;
00063       vertices[k].position.y = this->v0.y + map.array[k] * this->dv.y;
00064       vertices[k].position.z = this->v0.z + float(j) * this->dv.z;
00065       
00066       // Calculate vertex normal (*TODO: should compute normal over a larger patch (3x3 vertices) for smoother features)
00067       a.x = 1.0f;
00068       a.y = 0.0f;
00069       a.z = (map.array[k] - map.array[k + 1]) * this->dv.y;
00070       
00071       b.x = 0.0f;
00072       b.y = 1.0f;
00073       b.z = (map.array[k] - map.array[k + this->widthVertices]) * this->dv.y;
00074       
00075       D3DXVec3Normalize(&this->vertices[k].normal, D3DXVec3Cross(&this->vertices[k].normal, &a, &b));
00076       
00077       // Set vertex color
00078       this->vertices[k].color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
00079     }
00080   }
00081 
00082   UpdateUVs();
00083 
00084   // set up the index data
00085   indexData = new WORD[numFaces * 3];
00086 
00087   // note direct x uses a CW winding order
00088   // vertices 0, 1, 2, 3 in the following configuration
00089   // 2        3
00090   //  
00091   //   
00092   // 0        1
00093   for (j = 0, k = 0; j < this->heightFaces; j++) {
00094     for (i = 0; i < this->widthFaces; i++) {
00095       indexData[k++] = j * this->widthVertices + i; // vertex 0
00096       indexData[k++] = (j + 1) * this->widthVertices + i + 1; // vertex 3
00097       indexData[k++] = j * this->widthVertices + i + 1; // vertex 1
00098 
00099       indexData[k++] = j * this->widthVertices + i; // vertex 0
00100       indexData[k++] = (j + 1) * this->widthVertices + i; // vertex 2
00101       indexData[k++] = (j + 1) * this->widthVertices + i + 1; // vertex 3
00102     }
00103   }
00104 }
00105 
00106 void Grid::UpdateUVs() {
00107   int i, j, k;
00108   for (j = 0, k = 0; j < this->heightVertices; j++) {
00109     for (i = 0; i < this->widthVertices; i++, k++) {
00110       this->vertices[k].u = this->scale * ((float) i + this->uOffset);
00111       this->vertices[k].v = this->scale * ((float) j + this->vOffset);
00112     }
00113   }
00114 }
00115 
00116 void Grid::GetGridPoint(
00117     D3DXVECTOR3 *pt,
00118     int i, // row (from bottom to top)
00119     int j // column (from left to right)
00120     ) {
00121   *pt = this->vertices[j * this->heightVertices * i].position;
00122 }
00123 
00124 void Grid::GetGridNormal(
00125     D3DXVECTOR3 *normal,
00126     int i,
00127     int j
00128     ) {
00129   unsigned int k = i + j * this->widthVertices;
00130   
00131   normal->x = this->vertices[k].normal.x;
00132   normal->y = this->vertices[k].normal.y;
00133   normal->z = this->vertices[k].normal.z;
00134 }
00135 
00136 void Grid::CreateDirectXMesh(
00137     LPDIRECT3DDEVICE9 pd3dDevice
00138     ) {
00139   HRESULT hr;
00140   VOID* pData;
00141   hr = D3DXCreateMeshFVF(this->numFaces, this->numVertices, D3DXMESH_DYNAMIC /* | D3DXMESH_32BIT */, D3DFVF_GRIDVERTEX, pd3dDevice, &this->mesh);
00142   //*NOTE: the 32 bit mesh causes the DrawSubset method to have an access violation on my machine....
00143   if (FAILED(hr)) {
00144 #ifdef DEBUG
00145     char buf[2048];
00146     sprintf_s(buf, 2048, "Grid Create Mesh Error: %s error description: %s\n", DXGetErrorString(hr), DXGetErrorDescription(hr));
00147     OutputDebugString(buf);
00148 #endif
00149     return;
00150   }
00151 
00152   hr = this->mesh->LockVertexBuffer(D3DLOCK_DISCARD, (void**) &pData);
00153   if (FAILED(hr)) {
00154 #ifdef DEBUG
00155     char buf[2048];
00156     sprintf_s(buf, 2048, "Grid Lock Vertex Buffer Error: %s error description: %s\n", DXGetErrorString(hr), DXGetErrorDescription(hr));
00157     OutputDebugString(buf);
00158 #endif
00159     return;
00160   }
00161 
00162   // copy the vertices into the buffer
00163   memcpy(pData, this->vertices, this->numVertices * sizeof(GRIDVERTEX));
00164 
00165   // unlock the vertex buffer
00166   this->mesh->UnlockVertexBuffer();
00167 
00168   this->mesh->LockIndexBuffer(0, &pData);
00169 
00170   memcpy(pData, this->indexData, this->numFaces * 3 * sizeof(WORD));
00171 
00172   this->mesh->UnlockIndexBuffer();
00173 }
00174 
00175 void Grid::DrawDirectXMesh(
00176     LPDIRECT3DDEVICE9 pd3dDevice
00177     ) {
00178   HRESULT hr;
00179   if (this->mesh != NULL) {
00180     pd3dDevice->SetFVF(this->mesh->GetFVF());
00181     hr = this->mesh->DrawSubset(0);
00182     
00183     if (FAILED(hr)) {
00184 #ifdef DEBUG
00185       char buf[2048];
00186       sprintf_s(buf, 2048, "Grid Draw Error: %s error description: %s\n", DXGetErrorString(hr), DXGetErrorDescription(hr));
00187       OutputDebugString(buf);
00188 #endif
00189     }
00190   }
00191 }