天行健 君子当自强而不息

创建游戏内核(13)【OO改良版】

 

本篇是创建游戏内核(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;
}

posted on 2007-10-07 19:23 lovedday 阅读(349) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论