topical media & game development
graphic-directx-game-15-Solar-System-Demo-d3dUtil.cpp / cpp
//=============================================================================
// d3dUtil.cpp by Frank Luna (C) 2005 All Rights Reserved.
//=============================================================================
include <d3dUtil.h>
include <Vertex.h>
void GenTriGrid(int numVertRows, int numVertCols,
float dx, float dz,
const D3DXVECTOR3& center,
std::vector<D3DXVECTOR3>& verts,
std::vector<DWORD>& indices)
{
int numVertices = numVertRows*numVertCols;
int numCellRows = numVertRows-1;
int numCellCols = numVertCols-1;
int numTris = numCellRows*numCellCols*2;
float width = (float)numCellCols * dx;
float depth = (float)numCellRows * dz;
//===========================================
// Build vertices.
// We first build the grid geometry centered about the origin and on
// the xz-plane, row-by-row and in a top-down fashion. We then translate
// the grid vertices so that they are centered about the specified
// parameter 'center'.
verts.resize( numVertices );
// Offsets to translate grid from quadrant 4 to center of
// coordinate system.
float xOffset = -width * 0.5f;
float zOffset = depth * 0.5f;
int k = 0;
for(float i = 0; i < numVertRows; ++i)
{
for(float j = 0; j < numVertCols; ++j)
{
// Negate the depth coordinate to put in quadrant four.
// Then offset to center about coordinate system.
verts[k].x = j * dx + xOffset;
verts[k].z = -i * dz + zOffset;
verts[k].y = 0.0f;
// Translate so that the center of the grid is at the
// specified 'center' parameter.
D3DXMATRIX T;
D3DXMatrixTranslation(&T, center.x, center.y, center.z);
D3DXVec3TransformCoord(&verts[k], &verts[k], &T);
++k; // Next vertex
}
}
//===========================================
// Build indices.
indices.resize(numTris * 3);
// Generate indices for each quad.
k = 0;
for(DWORD i = 0; i < (DWORD)numCellRows; ++i)
{
for(DWORD j = 0; j < (DWORD)numCellCols; ++j)
{
indices[k] = i * numVertCols + j;
indices[k + 1] = i * numVertCols + j + 1;
indices[k + 2] = (i+1) * numVertCols + j;
indices[k + 3] = (i+1) * numVertCols + j;
indices[k + 4] = i * numVertCols + j + 1;
indices[k + 5] = (i+1) * numVertCols + j + 1;
// next quad
k += 6;
}
}
}
void LoadXFile(
const std::string& filename,
ID3DXMesh** meshOut,
std::vector<Mtrl>& mtrls,
std::vector<IDirect3DTexture9*>& texs)
{
// Step 1: Load the .x file from file into a system memory mesh.
ID3DXMesh* meshSys = 0;
ID3DXBuffer* adjBuffer = 0;
ID3DXBuffer* mtrlBuffer = 0;
DWORD numMtrls = 0;
HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, gd3dDevice,
&adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys));
// Step 2: Find out if the mesh already has normal info?
D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE];
HR(meshSys->GetDeclaration(elems));
bool hasNormals = false;
D3DVERTEXELEMENT9 term = D3DDECL_END();
for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
{
// Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}?
if(elems[i].Stream == 0xff )
break;
if( elems[i].Type == D3DDECLTYPE_FLOAT3 &&
elems[i].Usage == D3DDECLUSAGE_NORMAL &&
elems[i].UsageIndex == 0 )
{
hasNormals = true;
break;
}
}
// Step 3: Change vertex format to VertexPNT.
D3DVERTEXELEMENT9 elements[64];
UINT numElements = 0;
VertexPNT::Decl->GetDeclaration(elements, &numElements);
ID3DXMesh* temp = 0;
HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM,
elements, gd3dDevice, &temp));
ReleaseCOM(meshSys);
meshSys = temp;
// Step 4: If the mesh did not have normals, generate them.
if( hasNormals == false)
HR(D3DXComputeNormals(meshSys, 0));
// Step 5: Optimize the mesh.
HR(meshSys->Optimize(D3DXMESH_MANAGED |
D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut));
ReleaseCOM(meshSys); // Done w/ system mesh.
ReleaseCOM(adjBuffer); // Done with buffer.
// Step 6: Extract the materials and load the textures.
if( mtrlBuffer != 0 && numMtrls != 0 )
{
D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
for(DWORD i = 0; i < numMtrls; ++i)
{
// Save the ith material. Note that the MatD3D property does not have an ambient
// value set when its loaded, so just set it to the diffuse value.
Mtrl m;
m.ambient = d3dxmtrls[i].MatD3D.Diffuse;
m.diffuse = d3dxmtrls[i].MatD3D.Diffuse;
m.spec = d3dxmtrls[i].MatD3D.Specular;
m.specPower = d3dxmtrls[i].MatD3D.Power;
mtrls.push_back( m );
// Check if the ith material has an associative texture
if( d3dxmtrls[i].pTextureFilename != 0 )
{
// Yes, load the texture for the ith subset
IDirect3DTexture9* tex = 0;
char* texFN = d3dxmtrls[i].pTextureFilename;
HR(D3DXCreateTextureFromFile(gd3dDevice, texFN, &tex));
// Save the loaded texture
texs.push_back( tex );
}
else
{
// No texture for the ith subset
texs.push_back( 0 );
}
}
}
ReleaseCOM(mtrlBuffer); // done w/ buffer
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.