cAutomap::cAutomap and cAutomap::~cAutomap
The constructor and destructor
of the cAutomap class ensure that all data is placed
within a known state and that all used resources are released. The constructor
does
nothing more than clear some variables and orient a camera to point downward.
You later use that camera to render the map. The destructor calls on the Free
function to release all used resources.
cAutomap::create and cAutoMap::free
All right, take a deep breath
for this part. The create function is the biggest of the
bunch. It loads an .X file and converts each mesh within into a separate vertex
buffer. Starting with its variable declarations, examine the variable in pieces
to
better understand what’s going on:
bool cAutoMap::create(pcstr filename, long color)
{
free();
cMesh mesh;
if(! mesh.load(filename, ".\\"))
return false;
// get number of map section, create section visible flag array, vertex buffer array.
m_num_sections = mesh.get_num_meshes();
if(m_num_sections == 0)
{
mesh.free();
return false;
}
m_visible = new bool[m_num_sections];
ZeroMemory(m_visible, m_num_sections);
m_map_vb = new DIRECT3DVERTEXBUFFER9_PTR[m_num_sections];
long num = m_num_sections - 1;
// get a bounding radius to scale by
float radius;
mesh.get_bounds(NULL, NULL, NULL, NULL, NULL, NULL, &radius);
m_scale = 128.0f / radius;
// go through each mesh in the cMesh object and construct a matching vertex buffer.
// make sure to start with last section in map to compensate for linked list ordering of mesh in cMesh.
for(sMeshInfo* mesh_info = mesh.get_root_mesh(); mesh_info != NULL; mesh_info = mesh_info->m_next)
{
static long per_vertex_size = D3DXGetFVFVertexSize(mesh_info->m_d3d_mesh->GetFVF());
ID3DXMesh* d3d_mesh = mesh_info->m_d3d_mesh;
ushort* index_ptr;
char* vert_ptr;
d3d_mesh->LockIndexBuffer(D3DLOCK_READONLY, (void**) &index_ptr);
d3d_mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**) &vert_ptr);
long num_faces = d3d_mesh->GetNumFaces();
create_vertex_buffer(&m_map_vb[num], num_faces * 3, sizeof(sMapVertex), AUTO_MAP_FVF);
sMapVertex* map_vb_ptr;
m_map_vb[num]->Lock(0, 0, (void**) &map_vb_ptr, 0);
// pull out vertices and construct map vertex list, then fill into map vertex buffer.
for(long i = 0; i < num_faces; i++)
{
for(long j = 0; j < 3; j++)
{
ushort vert_index = *index_ptr;
index_ptr++;
sVertex* vert = (sVertex*) &vert_ptr[per_vertex_size * vert_index];
sMapVertex map_vert;
map_vert.x = vert->x * m_scale;
map_vert.y = 0.0f;
map_vert.z = vert->z * m_scale;
map_vert.diffuse = color;
memcpy(map_vb_ptr, &map_vert, sizeof(sMapVertex));
map_vb_ptr++;
}
}
m_map_vb[num]->Unlock();
d3d_mesh->UnlockVertexBuffer();
d3d_mesh->UnlockIndexBuffer();
num--;
}
mesh.free();
// create a character arrow vertex buffer and fill in it
sMapVertex arrow_verts[3] =
{
{ 0.0f, 0.0f, 10.0f, D3DCOLOR_RGBA(128, 64, 0, 255) },
{ 5.0f, 0.0f, -10.0f, D3DCOLOR_RGBA(128, 64, 0, 255) },
{ -5.0f, 0.0f, -10.0f, D3DCOLOR_RGBA(128, 64, 0, 255) }
};
create_vertex_buffer(&m_arrow_vb, 3, sizeof(sMapVertex), AUTO_MAP_FVF);
fill_in_vertex_buffer(m_arrow_vb, 0, 3, arrow_verts);
return true;
}
At this point, some variables are
declared, a prior auto map is freed (via a call to
free), and some error checking is being performed. Notice that the variable
declarations
include the vertex definitions for the pointer vertex buffer.
Now move on, starting with the
code that loads the map mesh that is used to create
the vertex buffers.
The first order of business is
to load the actual .X file from disc. The first sMesh
structure is grabbed from the cMesh object (remember from the Graphics Core that
the cMesh class stores meshes in a linked list of sMeshInfo structures).
Next, you calculate the size of
the vertex structure used by the .X file and calculate
the scaling factor to alter the meshes being loaded. Finally, you store the
number
of map sections in a class variable. Notice that the number of map sections
happens
to be the number of meshes in the .X file.
Moving on, you allocate an
array of bool variables, with each element in the array
representing whether a map section is visible. Each map section has a matching
element in the array. You also create an array of vertex buffers.
These vertex
buffers will be used to store the map
sections.
Remember that the meshes are
contained with a linked list of structures. Now is
the time to iterate through each structure in the linked list and query each
structure
for the pointer to the actual Direct3D ID3DXMesh object that contains the mesh
information for a single map section.
Next, you lock the index and
vertex buffers and start pulling out the vertex data.
A vertex buffer is being
created to match the number of polygon faces in the source
mesh. The vertex buffer is being locked and a pointer is being retrieved to
start storing
the vertices.
Two loops now go through every
polygon face in the source mesh, and three vertices
for each face are copied over to the map vertex buffers. Notice that you use
only the
X- and Z-coordinates, although the Y-coordinate is set to 0 (again to flatten
the map).
Last, you set the diffuse color to the color value provided (used to render the
map).
You wrap up the process by
unlocking the index and vertex buffers of the source
mesh and then proceeding to the next map section mesh in the linked list of
meshes loaded from the .X file. Notice that the num variable is tracking the
vertex
buffer that is being created, and the preceding code decrements it with each
mesh
being processed.
You decrement rather than
increment the num variable because the meshes in the
cMesh object are stored in reverse order (to make loading faster), so you must
compensate
to make sure that each map section is numbered sequentially to match the
order those meshes are stored in the .X file.
The create function finishes up
by creating the pointer vertex buffer and copying
over the vertex definition data defined earlier. The source mesh is freed and
control
returns to the caller.
In order to free the map
sections from memory, you provide a free function that
releases all the allocated resources and prepares the class to load another map
class.