本篇是创建游戏内核(12)【OO改良版】的续篇,关于该内核的细节说明请参阅创建游戏内核(13)。
接口:
//================================================================================
// Defines for structure MESH_INFO.
//================================================================================
typedef struct MESH_INFO
{
//------------------------------------------------------------------------------------
// Constructor, initialize all member data.
//------------------------------------------------------------------------------------
MESH_INFO()
{
memset(this, 0, sizeof(*this));
}
//------------------------------------------------------------------------------------
// Destructor, release all resouce.
//------------------------------------------------------------------------------------
~MESH_INFO()
{
release_com(m_d3d_mesh);
release_com(m_d3d_skin_mesh);
release_com(m_d3d_skin_info);
delete[] m_name;
delete[] m_d3d_materials;
if(m_d3d_textures)
{
for(DWORD i = 0; i < m_num_materials; i++)
release_com(m_d3d_textures[i]);
delete[] m_d3d_textures;
}
delete[] m_matrices;
delete[] m_frame_matrices;
delete m_next;
}
//------------------------------------------------------------------------------------
// Find mesh object with specified name.
//------------------------------------------------------------------------------------
MESH_INFO* find_mesh_info(const char* name)
{
// return first instance if name is NULL
if(name == NULL)
return this;
// compare names and return if exact match
if(m_name && STREQ(name, m_name))
return this;
// search next in list
if(m_next != NULL)
{
MESH_INFO* _mesh_info;
// recursively call
if((_mesh_info = m_next->find_mesh_info(name)) != NULL)
return _mesh_info;
}
return NULL;
}
//------------------------------------------------------------------------------------
// Get number of materials.
//------------------------------------------------------------------------------------
DWORD get_num_materials()
{
return m_num_materials;
}
//------------------------------------------------------------------------------------
// Get material object.
//------------------------------------------------------------------------------------
D3DMATERIAL9* get_d3d_material(DWORD index)
{
if(index >= m_num_materials || m_d3d_materials == NULL)
return NULL;
return &m_d3d_materials[index];
}
//------------------------------------------------------------------------------------
// Get texture object.
//------------------------------------------------------------------------------------
IDirect3DTexture9* get_d3d_texture(DWORD index)
{
if(index >= m_num_materials || m_d3d_textures == NULL)
return NULL;
return m_d3d_textures[index];
}
//------------------------------------------------------------------------------------
// create frame transform matrices, recursively call.
//------------------------------------------------------------------------------------
void create_frame_transform_matrices()
{
DWORD _num_bones = get_num_bones();
if(_num_bones != 0 && m_matrices && m_frame_matrices)
{
for(DWORD i = 0; i < _num_bones; i++)
{
if(m_frame_matrices[i])
// gets the bone offset matrix and multiply it with frame transformed matrix
D3DXMatrixMultiply(&m_matrices[i], m_d3d_skin_info->GetBoneOffsetMatrix(i), m_frame_matrices[i]);
else
D3DXMatrixIdentity(&m_matrices[i]);
}
}
// process next in list (recursively call)
if(m_next)
m_next->create_frame_transform_matrices();
}
//------------------------------------------------------------------------------------
// Return number of bone in skin mesh information.
//------------------------------------------------------------------------------------
DWORD get_num_bones()
{
return m_d3d_skin_info->GetNumBones();
}
public:
char* m_name; // name of mesh
ID3DXMesh* m_d3d_mesh; // mesh object
ID3DXMesh* m_d3d_skin_mesh; // skin mesh object
ID3DXSkinInfo* m_d3d_skin_info; // skin mesh information
DWORD m_num_materials; // number of materials in mesh
D3DMATERIAL9* m_d3d_materials; // array of materials
IDirect3DTexture9** m_d3d_textures; // array of textures
D3DXMATRIX* m_matrices; // bone matrices
D3DXMATRIX** m_frame_matrices; // pointers to frame matrices
D3DXVECTOR3 m_bound_min, m_bound_max; // bounding box
float m_bound_radius; // bounding sphere radius
MESH_INFO* m_next; // next mesh in list
} *MESH_INFO_PTR;
//================================================================================
// Defines for structure FRAME_INFO.
//================================================================================
typedef struct FRAME_INFO
{
public:
//------------------------------------------------------------------------------------
// Constructor, initialize member data.
//------------------------------------------------------------------------------------
FRAME_INFO()
{
memset(this, 0, sizeof(*this));
D3DXMatrixIdentity(&m_mat_combined);
D3DXMatrixIdentity(&m_mat_transformed);
D3DXMatrixIdentity(&m_mat_original);
}
//------------------------------------------------------------------------------------
// Destructor, release all resource.
//------------------------------------------------------------------------------------
~FRAME_INFO()
{
delete m_name;
delete m_child;
delete m_sibling;
}
//------------------------------------------------------------------------------------
// Find frame information with specified name, call recursively.
//------------------------------------------------------------------------------------
FRAME_INFO* find_frame_info(const char* name)
{
// return this instances if name is NULL
if(name == NULL)
return this;
// compare names and return if exact match
if(m_name && STREQ(name, m_name))
return this;
FRAME_INFO* _frame_info;
// search child lists, recursively call.
if(m_child)
{
if((_frame_info = m_child->find_frame_info(name)) != NULL)
return _frame_info;
}
// search sibling lists, recursively call.
if(m_sibling)
{
if((_frame_info = m_sibling->find_frame_info(name)) != NULL)
return _frame_info;
}
return NULL;
}
//------------------------------------------------------------------------------------
// Reset transformed matrices to original matrices, recursively call.
//------------------------------------------------------------------------------------
void reset_matrices()
{
m_mat_transformed = m_mat_original;
if(m_child)
m_child->reset_matrices();
if(m_sibling)
m_sibling->reset_matrices();
}
//------------------------------------------------------------------------------------
// Add mesh information into mesh list.
//------------------------------------------------------------------------------------
void add_mesh_info(MESH_INFO* mesh_info)
{
mesh_info->m_next = m_mesh_info;
m_mesh_info = mesh_info;
}
public:
char* m_name;
MESH_INFO_PTR m_mesh_info; // list of meshes attached to this frame
D3DXMATRIX m_mat_combined; // combined trasnformation matrix
D3DXMATRIX m_mat_transformed; // currently transformed matrix
D3DXMATRIX m_mat_original; // original .x File matrix
FRAME_INFO* m_parent; // parent frame
FRAME_INFO* m_child; // child frame
FRAME_INFO* m_sibling; // silbling frame
} *FRAME_INFO_PTR;
//================================================================================
// Defines for class MESH.
//================================================================================
typedef class MESH
{
public:
MESH();
~MESH();
BOOL is_loaded();
long get_num_frames();
FRAME_INFO_PTR get_root_frame_info();
FRAME_INFO_PTR get_frame_info(const char* name);
long get_num_meshes();
MESH_INFO_PTR get_root_mesh_info();
MESH_INFO_PTR get_mesh_info(const char* name);
void get_bounds(float* min_x, float* min_y, float* min_z,
float* max_x, float* max_y, float* max_z,
float* radius);
BOOL load(const char* filename, const char* texture_path);
void free();
private:
void _parse_xfile_data(ID3DXFileData* _xfile_data, FRAME_INFO_PTR parent_frame_info, const char* texture_path);
void _map_frame_matrix_to_bone(FRAME_INFO_PTR frame_info);
private:
long m_num_meshes; // number of meshes
MESH_INFO_PTR m_mesh_info; // mesh information list
long m_num_frames; // number of frames
FRAME_INFO_PTR m_frame_info; // frame information list
D3DXVECTOR3 m_bound_min; // the lower-left corner of the bounding box
D3DXVECTOR3 m_bound_max; // the upper-right corner of the bounding box
float m_bound_radius; // bounding box radius
} *MESH_PTR;
实现:
//-------------------------------------------------------------------
// Constructor, initialize member data.
//-------------------------------------------------------------------
MESH::MESH()
{
memset(this, 0, sizeof(*this));
}
//-------------------------------------------------------------------
// Destructor, release all resources.
//-------------------------------------------------------------------
MESH::~MESH()
{
free();
}
//-------------------------------------------------------------------
// Release all resources.
//-------------------------------------------------------------------
void MESH::free()
{
delete m_mesh_info;
m_mesh_info = NULL;
delete m_frame_info;
m_frame_info = NULL;
}
//-------------------------------------------------------------------
// load .x File from specified filename.
//-------------------------------------------------------------------
BOOL MESH::load(const char* filename, const char* texture_path)
{
// free prior mesh object data
free();
// error checking
if(g_d3d_device == NULL || filename == NULL)
return FALSE;
ID3DXFile* _xfile = NULL;
// create the file object
if(FAILED(D3DXFileCreate(&_xfile)))
return FALSE;
// register the templates
if(FAILED(_xfile->RegisterTemplates((LPVOID) D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
{
_xfile->Release();
return FALSE;
}
ID3DXFileEnumObject* _xfile_enum = NULL;
// create an enumeration object
if(FAILED(_xfile->CreateEnumObject((LPVOID) filename, DXFILELOAD_FROMFILE, &_xfile_enum)))
{
_xfile->Release();
return FALSE;
}
// create a frame information object
FRAME_INFO_PTR _frame_info = new FRAME_INFO();
ID3DXFileData* _xfile_data = NULL;
SIZE_T _num_child;
// retrieve the number of children in this file data object
_xfile_enum->GetChildren(&_num_child);
// loop through all objects looking for the frames and meshes
for(SIZE_T i = 0; i < _num_child; i++)
{
if(FAILED(_xfile_enum->GetChild(i, &_xfile_data)))
return FALSE;
_parse_xfile_data(_xfile_data, _frame_info, texture_path);
release_com(_xfile_data);
}
// release used COM objects
release_com(_xfile_enum);
release_com(_xfile);
// see if we should keep the frame information as root
if(_frame_info->m_mesh_info != NULL)
{
m_frame_info = _frame_info;
m_frame_info->m_name = new char[7];
strcpy(m_frame_info->m_name, "%ROOT%");
}
else
{
// Ok, now there is no any mesh in this frame, assign child frame as the root frame and release this frame.
m_frame_info = _frame_info->m_child;
FRAME_INFO_PTR _frame_info_ptr = m_frame_info;
// reset all child frames information of this frame, only under one level.
while(_frame_info_ptr != NULL)
{
_frame_info_ptr->m_parent = NULL;
_frame_info_ptr = _frame_info_ptr->m_sibling;
}
_frame_info->m_child = NULL;
delete _frame_info;
}
// map transformed matrix frames to bones
_map_frame_matrix_to_bone(m_frame_info);
MESH_INFO_PTR _mesh_info;
// calculate bounding box and sphere
if((_mesh_info = m_mesh_info) != NULL)
{
while(_mesh_info)
{
// set the lower-left corner of the bounding box as the most lower-left corner
// of all meshes's bounding box
m_bound_min.x = min(m_bound_min.x, _mesh_info->m_bound_min.x);
m_bound_min.y = min(m_bound_min.y, _mesh_info->m_bound_min.y);
m_bound_min.z = min(m_bound_min.z, _mesh_info->m_bound_min.z);
// set the upper-right corner of the bounding box as the most upper-right corner
// of all meshes's bounding box
m_bound_max.x = max(m_bound_max.x, _mesh_info->m_bound_max.x);
m_bound_max.y = max(m_bound_max.y, _mesh_info->m_bound_max.y);
m_bound_max.z = max(m_bound_max.z, _mesh_info->m_bound_max.z);
// set bounding box radius as max radius of all meshes
m_bound_radius = max(m_bound_radius, _mesh_info->m_bound_radius);
_mesh_info = _mesh_info->m_next;
}
}
return TRUE;
}
//-------------------------------------------------------------------
// Parse specified xfile data, recursive function.
//-------------------------------------------------------------------
void MESH::_parse_xfile_data(ID3DXFileData* xfile_data, FRAME_INFO_PTR parent_frame_info, const char* texture_path)
{
// get the template type
GUID _type;
// retrieve the globally unique identifier (GUID) of the object's template
if(FAILED(xfile_data->GetType(&_type)))
return;
// get the template name (if any)
DWORD _size;
if(FAILED(xfile_data->GetName(NULL, &_size)))
return;
char* _name = NULL;
if(_size != 0)
{
if((_name = new char[_size]) != NULL)
xfile_data->GetName(_name, &_size);
}
// give template a default name if none found
if(_name == NULL)
{
if((_name = new char[9]) == NULL)
return;
strcpy(_name, "$NoName$");
}
// set current frame information pointer
FRAME_INFO_PTR _current_frame_info = parent_frame_info;
// process the templates
if(_type == TID_D3DRMFrame) // it's a frame
{
// create a new frame information structure
FRAME_INFO_PTR _frame_info = new FRAME_INFO();
// store the name
_frame_info->m_name = _name;
_name = NULL;
// link to parent frame
_frame_info->m_parent = parent_frame_info;
_frame_info->m_sibling = parent_frame_info->m_child;
parent_frame_info->m_child = _frame_info;
// increase frame count
m_num_frames++;
// set current frame as new frame
_current_frame_info = _frame_info;
}
else if(_type == TID_D3DRMFrameTransformMatrix) // it's a frame transformation matrix
{
D3DXMATRIX* _frame_matrix = NULL;
// get frame transformation matrix
if(FAILED(xfile_data->Lock(&_size, (LPCVOID*) &_frame_matrix)))
return;
// set original matrix
parent_frame_info->m_mat_original = *_frame_matrix;
xfile_data->Unlock();
}
else if(_type == TID_D3DRMMesh) // it's a mesh
{
ID3DXBuffer* _material_buffer = NULL;
ID3DXBuffer* _adjacency = NULL;
MESH_INFO* _mesh_info = NULL;
// see if mesh already loaded
if(m_mesh_info == NULL || m_mesh_info->find_mesh_info(_name) == NULL)
{
// create a new mesh information structure
_mesh_info = new MESH_INFO();
// store the name
_mesh_info->m_name = _name;
_name = NULL;
// load mesh data
if(FAILED(D3DXLoadSkinMeshFromXof(xfile_data, 0, g_d3d_device, &_adjacency, &_material_buffer, NULL,
&_mesh_info->m_num_materials, &_mesh_info->m_d3d_skin_info, &_mesh_info->m_d3d_mesh)))
{
delete[] _name;
delete _mesh_info;
return;
}
BYTE* _ptr;
ID3DXMesh* _d3d_mesh = _mesh_info->m_d3d_mesh;
// calculate the bounding box and sphere
if(SUCCEEDED(_d3d_mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**) &_ptr)))
{
// computes a coordinate-axis oriented bounding box
D3DXComputeBoundingBox((D3DXVECTOR3*) _ptr, _d3d_mesh->GetNumVertices(),
_d3d_mesh->GetNumBytesPerVertex(), &_mesh_info->m_bound_min, &_mesh_info->m_bound_max);
// computes a bounding sphere for the mesh
D3DXComputeBoundingSphere((D3DXVECTOR3*) _ptr,
_d3d_mesh->GetNumVertices(),_d3d_mesh->GetNumBytesPerVertex(),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), &_mesh_info->m_bound_radius);
_d3d_mesh->UnlockVertexBuffer();
}
// create a matching skinned mesh if bone exist
if(_mesh_info->m_d3d_skin_info && _mesh_info->get_num_bones() != 0)
{
DWORD _num_bones = _mesh_info->get_num_bones();
// clones a mesh using a flexible vertex format (FVF) code
if(FAILED(_d3d_mesh->CloneMeshFVF(0, _d3d_mesh->GetFVF(), g_d3d_device, &_mesh_info->m_d3d_skin_mesh)))
{
release_com(_mesh_info->m_d3d_skin_info);
}
else // create an array of matrices to store bone transformations
{
// create the bone matrix array and clear it out
_mesh_info->m_matrices = new D3DXMATRIX[_num_bones];
for(DWORD i = 0; i < _num_bones; i++)
D3DXMatrixIdentity(&_mesh_info->m_matrices[i]);
// create the frame matrix pointer array and clear out
_mesh_info->m_frame_matrices = new D3DXMATRIX*[_num_bones];
for(DWORD i = 0; i < _num_bones; i++)
_mesh_info->m_frame_matrices[i] = NULL;
}
}
// load materials or create a default one if none
if(_mesh_info->m_num_materials == 0)
{
// create a default one
_mesh_info->m_d3d_materials = new D3DMATERIAL9[1];
_mesh_info->m_d3d_textures = new LPDIRECT3DTEXTURE9[1];
ZeroMemory(_mesh_info->m_d3d_materials, sizeof(D3DMATERIAL9));
_mesh_info->m_d3d_materials[0].Diffuse.r = 1.0f;
_mesh_info->m_d3d_materials[0].Diffuse.g = 1.0f;
_mesh_info->m_d3d_materials[0].Diffuse.b = 1.0f;
_mesh_info->m_d3d_materials[0].Diffuse.a = 1.0f;
_mesh_info->m_d3d_materials[0].Ambient = _mesh_info->m_d3d_materials[0].Diffuse;
_mesh_info->m_d3d_materials[0].Specular = _mesh_info->m_d3d_materials[0].Diffuse;
_mesh_info->m_d3d_textures[0] = NULL;
_mesh_info->m_num_materials = 1;
}
else
{
// load the materials
D3DXMATERIAL* _x_materials = (D3DXMATERIAL*) _material_buffer->GetBufferPointer();
_mesh_info->m_d3d_materials = new D3DMATERIAL9[_mesh_info->m_num_materials];
_mesh_info->m_d3d_textures = new LPDIRECT3DTEXTURE9[_mesh_info->m_num_materials];
char _path[MAX_PATH];
for(DWORD i = 0; i < _mesh_info->m_num_materials; i++)
{
_mesh_info->m_d3d_materials[i] = _x_materials[i].MatD3D;
_mesh_info->m_d3d_materials[i].Ambient = _mesh_info->m_d3d_materials[i].Diffuse;
// build a texture _path and load it
sprintf(_path, "%s%s", texture_path, _x_materials[i].pTextureFilename);
if(FAILED(D3DXCreateTextureFromFile(g_d3d_device, _path, &_mesh_info->m_d3d_textures[i])))
_mesh_info->m_d3d_textures[i] = NULL;
}
}
release_com(_material_buffer);
release_com(_adjacency);
// link to mesh
_mesh_info->m_next = m_mesh_info;
m_mesh_info = _mesh_info;
m_num_meshes++;
}
else
// Find mesh in list
_mesh_info = m_mesh_info->find_mesh_info(_name);
// add mesh information into frame
if(_mesh_info != NULL)
_current_frame_info->add_mesh_info(_mesh_info);
} // end if(_type == TID_D3DRMMesh)
else if(_type == TID_D3DRMAnimationSet || _type == TID_D3DRMAnimation || _type == TID_D3DRMAnimationKey)
{
// skip animation sets and animations
delete[] _name;
return;
}
// release _name buffer
delete[] _name;
ID3DXFileData* _child_xfile_data = NULL;
SIZE_T _num_child;
xfile_data->GetChildren(&_num_child);
// scan for embedded templates
for(SIZE_T i = 0; i < _num_child; i++)
{
xfile_data->GetChild(i, &_child_xfile_data);
// parse child _xfile data object
_parse_xfile_data(_child_xfile_data, _current_frame_info, texture_path);
release_com(_child_xfile_data);
}
}
//-------------------------------------------------------------------
// Map frame transformation matrix to match bone, recursively call.
//-------------------------------------------------------------------
void MESH::_map_frame_matrix_to_bone(FRAME_INFO_PTR frame_info)
{
// return if no more frames to map
if(frame_info == NULL || frame_info->m_name == NULL)
return;
// scan through meshes looking for bone matches
MESH_INFO_PTR _mesh_info = m_mesh_info;
while(_mesh_info != NULL)
{
DWORD _num_bones = _mesh_info->get_num_bones();
if(_mesh_info->m_d3d_skin_info && _num_bones && _mesh_info->m_frame_matrices)
{
for(DWORD i = 0; i < _num_bones; i++)
{
if(STREQ(frame_info->m_name, _mesh_info->m_d3d_skin_info->GetBoneName(i)))
{
// pointer mesh's frame transform matrix to frame combined matrix
_mesh_info->m_frame_matrices[i] = &frame_info->m_mat_combined;
break;
}
}
}
_mesh_info = _mesh_info->m_next;
}
// scan through child frames
_map_frame_matrix_to_bone(frame_info->m_child);
// scan throuogh sibling frames
_map_frame_matrix_to_bone(frame_info->m_sibling);
}
//-------------------------------------------------------------------
// Judge whether the mesh has been loaded successfully.
//-------------------------------------------------------------------
BOOL MESH::is_loaded()
{
return (m_mesh_info != NULL && m_frame_info != NULL);
}
//-------------------------------------------------------------------
// Get number of frame.
//-------------------------------------------------------------------
long MESH::get_num_frames()
{
return m_num_frames;
}
//-------------------------------------------------------------------
// Get root frame information.
//-------------------------------------------------------------------
FRAME_INFO_PTR MESH::get_root_frame_info()
{
return m_frame_info;
}
//-------------------------------------------------------------------
// Find frame information with specified name.
//-------------------------------------------------------------------
FRAME_INFO_PTR MESH::get_frame_info(const char* name)
{
if(m_frame_info == NULL)
return NULL;
return m_frame_info->find_frame_info(name);
}
//-------------------------------------------------------------------
// Get number of mesh.
//-------------------------------------------------------------------
long MESH::get_num_meshes()
{
return m_num_meshes;
}
//-------------------------------------------------------------------
// Return root mesh information.
//-------------------------------------------------------------------
MESH_INFO_PTR MESH::get_root_mesh_info()
{
return m_mesh_info;
}
//-------------------------------------------------------------------
// Get mesh information whih spefied name.
//-------------------------------------------------------------------
MESH_INFO_PTR MESH::get_mesh_info(const char* name)
{
if(m_mesh_info == NULL)
return NULL;
return m_mesh_info->find_mesh_info(name);
}
//-------------------------------------------------------------------
// Get bound box coordinate and radius.
//-------------------------------------------------------------------
void MESH::get_bounds(float* min_x, float* min_y, float* min_z,
float* max_x, float* max_y, float* max_z,
float* radius)
{
if(min_x != NULL) *min_x = m_bound_min.x;
if(min_y != NULL) *min_y = m_bound_min.y;
if(min_z != NULL) *min_z = m_bound_min.z;
if(max_x != NULL) *max_x = m_bound_max.x;
if(max_y != NULL) *max_y = m_bound_max.y;
if(max_z != NULL) *max_z = m_bound_max.z;
if(radius != NULL) *radius = m_bound_radius;
}
测试代码:
/***********************************************************************************
PURPOSE:
Test for mesh class.
***********************************************************************************/
#include "core_common.h"
#include "core_framework.h"
#include "core_graphics.h"
class APP : public FRAMEWORK
{
public:
BOOL init()
{
// Create Direct3D and Direct3DDevice object
if(! create_display(g_hwnd, get_client_width(g_hwnd), get_client_height(g_hwnd), 16, TRUE, FALSE))
return FALSE;
// set perspective projection transform matrix
set_perspective(D3DX_PI/4.0f, 1.33333f, 1.0f, 1000.0f);
D3DXMATRIX _mat_view;
// create and set the view matrix
D3DXMatrixLookAtLH(&_mat_view,
&D3DXVECTOR3(0.0, 50.0, -150.0),
&D3DXVECTOR3(0.0, 50.0, 0.0),
&D3DXVECTOR3(0.0, 1.0, 0.0));
g_d3d_device->SetTransform(D3DTS_VIEW, &_mat_view);
if(! m_mesh.load("warrior.x", ".\\"))
return FALSE;
return TRUE;
}
BOOL frame()
{
clear_display_buffer(D3DCOLOR_RGBA(0, 0, 0, 255));
if(SUCCEEDED(g_d3d_device->BeginScene()))
{
D3DXMATRIX _mat_world;
// create and set the world transformation matrix
// rotate object along z-axis
D3DXMatrixRotationY(&_mat_world, (float) (timeGetTime() / 1000.0));
g_d3d_device->SetTransform(D3DTS_WORLD, &_mat_world);
FRAME_INFO_PTR _frame_info = m_mesh.get_root_frame_info();
_draw_mesh(_frame_info);
g_d3d_device->EndScene();
}
present_display();
return TRUE;
}
BOOL shutdown()
{
release_com(g_d3d_device);
release_com(g_d3d);
return TRUE;
}
private:
BOOL _draw_mesh(FRAME_INFO_PTR frame_info)
{
D3DXMATRIX* _matrices = NULL;
ID3DXMesh* _d3d_mesh_to_draw;
MESH_INFO_PTR _mesh_info;
if(frame_info == NULL)
return FALSE;
// draw meshes if any in frame
if((_mesh_info = frame_info->m_mesh_info) != NULL)
{
// setup pointer to d3d mesh to draw
_d3d_mesh_to_draw = _mesh_info->m_d3d_mesh;
ID3DXMesh* _d3d_mesh = _mesh_info->m_d3d_mesh;
ID3DXMesh* _d3d_skin_mesh = _mesh_info->m_d3d_skin_mesh;
ID3DXSkinInfo* _d3d_skin_info = _mesh_info->m_d3d_skin_info;
// generate mesh from skinned mesh to draw with
if(_d3d_skin_mesh && _d3d_skin_info)
{
DWORD _num_bones = _d3d_skin_info->GetNumBones();
// allocate an array of _matrices to orient bones
_matrices = new D3DXMATRIX[_num_bones];
// set all bones orientation to identity
for(DWORD i = 0; i < _num_bones; i++)
D3DXMatrixIdentity(&_matrices[i]);
// lock _source_vertices and destination vertex buffers
void* _source_vertices = NULL;
void* _dest_vertices = NULL;
// locks a vertex buffer and obtains a pointer to the vertex buffer memory
_d3d_mesh->LockVertexBuffer(0, &_source_vertices);
_d3d_skin_mesh->LockVertexBuffer(0, &_dest_vertices);
// Update skinned mesh, applies software skinning to the target vertices based on the current matrices.
_d3d_skin_info->UpdateSkinnedMesh(_matrices, NULL, _source_vertices, _dest_vertices);
// unlock buffers
_d3d_mesh->UnlockVertexBuffer();
_d3d_skin_mesh->UnlockVertexBuffer();
// pointer to skin _mesh_info to draw
_d3d_mesh_to_draw = _d3d_skin_mesh;
}
// render the d3d mesh
for(DWORD i = 0; i < _mesh_info->get_num_materials(); i++)
{
// set the materials properties for the device
g_d3d_device->SetMaterial(&_mesh_info->m_d3d_materials[i]);
// assign a texture to a stage for a device
g_d3d_device->SetTexture(0, _mesh_info->m_d3d_textures[i]);
// draw a subset of a _mesh_info
_d3d_mesh_to_draw->DrawSubset(i);
}
// free array of _matrices
delete[] _matrices;
_matrices = NULL;
}
// draw child frames, recursively call.
_draw_mesh(frame_info->m_child);
return TRUE;
}
private:
MESH m_mesh;
};
int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
APP app;
if(! build_window(inst, "MainClass", "MainWindow", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480))
return -1;
app.run();
return 0;
}