青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

創(chuàng)建游戲內(nèi)核(14)

 

本篇是 創(chuàng)建游戲內(nèi)核(13)的續(xù)篇,其中涉及到的網(wǎng)格繪制知識請參閱D3D中網(wǎng)格模型的運用

 

使用.X樣式三維動畫

三維動畫與二維動畫相比較是一個全新的處理過程。不用再奢侈地繪制圖像,然后按順序顯示來創(chuàng)建動畫。在三維世界中,一個對象可以從任何方向進行觀察。

基本上,三維動畫改變那些在運行期間用于為網(wǎng)格模型指明方向的框架變換矩陣,進而產(chǎn)生出在框架中移動的各式各樣的網(wǎng)格模型,這個運動的網(wǎng)格模型就是動畫。可以使用任何方式平移、旋轉(zhuǎn)、甚至縮放網(wǎng)格模型。

在處理蒙皮網(wǎng)格模型時,框架變換的使用只不過是使網(wǎng)格模型產(chǎn)生動畫的一種方法。因為一個蒙皮網(wǎng)格模型就是一個單一的網(wǎng)格模型(并非由多個網(wǎng)格模型組成),需要改變框架比便進行頂點的變形。修改框架變換矩陣最簡單的方法就是使用一種稱之為關(guān)鍵楨(key frame)的技術(shù)。

 

關(guān)鍵楨技術(shù)

在計算機動畫中,關(guān)鍵楨描述了這樣一種技術(shù),它使用兩個完整的、單獨的方位(關(guān)鍵楨),以及兩者之間基于某一系數(shù)(例如時間)的插值。另一方面,通過使用兩個不同框架的方位(每個方位稱之為一個關(guān)鍵點key),就可以計算出那些關(guān)鍵點任何位置以及任何時間所在的方位。

如下所示,框架的方位,從開始時的方位到結(jié)束時的方位,隨時間變化進行插值計算。

關(guān)鍵幀的效率非常高,它確保了動畫能夠以相同的速度運行在所有的系統(tǒng)中。運行較慢的計算機會減少幀數(shù)(以動畫的跳躍為代價),而較快的計算機能夠產(chǎn)生出更多的幀,從而提供更平滑的動畫。

只需要在那些幀之間進行插值計算便可以產(chǎn)生平滑的動畫,插值(interpolating)是一種計算兩個數(shù)值之間,隨時間變化的過渡數(shù)值的方法。這里使用的關(guān)鍵楨形式是矩陣關(guān)鍵楨(matrix key framing),因為使用的是D3DX矩陣對象,所以使用這種格式的關(guān)鍵楨會十分容易。比如說,有兩個矩陣mat1和mat2,分別表示開始和結(jié)束的矩陣,他們之間的時間距離表示為time_length,同時當前的時間表示為time(其范圍從0到length),計算插值矩陣,就像下面代碼所示:

    D3DXMATRIX mat1, mat2;
    DWORD time_length, time;
    D3DXMATRIX mat_inter;   
// 最終的插值矩陣

    // 計算插值矩陣    
    mat_inter = mat1 + ((mat2 - mat1) / time_length) * time;
 

.X中的動畫

微軟公司在.X文件中提供了動畫數(shù)據(jù),該動畫數(shù)據(jù)位于一個特定數(shù)據(jù)對象的集合里,同時,也可以使用與加載蒙皮網(wǎng)格模型相同的技術(shù)去加載那些動畫對象的數(shù)據(jù)。特定的數(shù)據(jù)對象包含了在關(guān)鍵幀技術(shù)中所使用到的各種各樣的關(guān)鍵點,每個關(guān)鍵點代表了一種變換:旋轉(zhuǎn)、縮放、平移。為了使之更加容易,可以指定同時組合了所有變換的矩陣關(guān)鍵點。

每個關(guān)鍵點都有一個與之相關(guān)聯(lián)的激活時間。換句話說,在time=0的旋轉(zhuǎn)關(guān)鍵點意味著在時間為0時,關(guān)鍵點中的旋轉(zhuǎn)數(shù)值被使用。而第二個旋轉(zhuǎn)關(guān)鍵點在time=200時激活。當計時繼續(xù)時,位于第一個和第二個旋轉(zhuǎn)關(guān)鍵點之間某個位置的旋轉(zhuǎn)插值被計算出來。當時間到達200時,旋轉(zhuǎn)數(shù)值與第二個旋轉(zhuǎn)關(guān)鍵點相等。這種形式的插值計算可以被運用到所有的關(guān)鍵點類型中。

動畫以集合的形式出現(xiàn),同時每個集合被分配特定的框架,可以將多個關(guān)鍵點分配給相同的集合,以便使多個動畫關(guān)鍵點能夠同時影響到框架。舉例來說,一個框架可以同時被旋轉(zhuǎn)關(guān)鍵點和平移關(guān)鍵點的集合來修改,以便同時旋轉(zhuǎn)并平移框架。

 

使用OBJECT繪制對象

要繪制網(wǎng)格,必須在網(wǎng)格定義和顯示器之間搭設一道橋梁。為什么不使用MESH對象處理渲染呢?原因在于內(nèi)存使用(memory usage),如果要反復使用相同的網(wǎng)格,該怎么辦?解決的辦法就是使用OBJECT對象。

首先定義表示插值旋轉(zhuǎn)變換、平移變換、縮放、變換矩陣的數(shù)據(jù)結(jié)構(gòu):

struct S_ROTATE_KEY
{
    DWORD           time;
    D3DXQUATERNION  quat;
};

struct S_POSITION_KEY
{
    DWORD           time;
    D3DXVECTOR3     pos;
    D3DXVECTOR3     pos_inter;
};

struct S_SCALE_KEY
{
    DWORD       time;
    D3DXVECTOR3 scale;
    D3DXVECTOR3 scale_inter;
};

struct S_MATRIX_KEY
{
    DWORD       time;
    D3DXMATRIX  matrix;
    D3DXMATRIX  mat_inter;
};

其次定義一個叫做S_ANIATION的結(jié)構(gòu)體來封裝框架的變換矩陣。

struct S_ANIMATION
{
public:
    
char*           m_name;
    
char*           m_frame_name;
    S_FRAME*        m_frame;

    BOOL            m_is_loop;
    BOOL            m_is_linear;

    DWORD           m_num_position_keys;
    S_POSITION_KEY* m_position_keys;

    DWORD           m_num_rotate_keys;
    S_ROTATE_KEY*   m_rotate_keys;

    DWORD           m_num_scale_keys;
    S_SCALE_KEY*    m_scale_keys;

    DWORD           m_num_matrix_keys;
    S_MATRIX_KEY*   m_matrix_keys;

    S_ANIMATION*    m_next;

    
//--------------------------------------------------------------------
    // Constructor, initialize member data.
    //--------------------------------------------------------------------
    S_ANIMATION()
    {
        m_name              = NULL;
        m_frame_name        = NULL;
        m_frame             = NULL;

        m_is_loop           = FALSE;
        m_is_linear         = TRUE;

        m_num_position_keys = 0;
        m_num_rotate_keys   = 0;
        m_num_scale_keys    = 0;
        m_num_matrix_keys   = 0;

        m_position_keys     = NULL;
        m_rotate_keys       = NULL;
        m_scale_keys        = NULL;
        m_matrix_keys       = NULL;

        m_next              = NULL;
    }

    
//--------------------------------------------------------------------
    // Destructor, release resource.
    //--------------------------------------------------------------------
    ~S_ANIMATION()
    {
        delete[] m_name;            m_name          = NULL;
        delete[] m_frame_name;      m_frame_name    = NULL;
        delete[] m_position_keys;   m_position_keys = NULL;
        delete[] m_rotate_keys;     m_rotate_keys   = NULL;
        delete[] m_scale_keys;      m_scale_keys    = NULL;
        delete[] m_matrix_keys;     m_matrix_keys   = NULL;
        delete[] m_next;            m_next          = NULL;
    }

    
//--------------------------------------------------------------------
    // Update current frame's transformed matrix.
    //--------------------------------------------------------------------
    void Update(DWORD time, BOOL is_smooth)
    {
        unsigned 
long key_index;
        DWORD time_diff, time_inter;
        D3DXMATRIX  matrix, mat_temp;
        D3DXVECTOR3 vector;
        D3DXQUATERNION quat;

        
if(m_frame == NULL)
            
return;

        
// Update rotation, scale, and position keys.
        if(m_num_rotate_keys != 0 || m_num_scale_keys != 0 || m_num_position_keys != 0)
        {
            D3DXMatrixIdentity(&matrix);

            
// update rotation matrix
            if(m_num_rotate_keys != 0 && m_rotate_keys != NULL)
            {
                
// find the key that fits this time
                key_index = 0;

                
for(unsigned long i = 0; i < m_num_rotate_keys; i++)
                {
                    
if(m_rotate_keys[i].time <= time)
                        key_index = i;
                    
else
                        
break;
                }

                
// If it's the last key or non-smooth animation, then just set the key value.
                if(key_index == m_num_rotate_keys - 1 || is_smooth == FALSE)
                    quat = m_rotate_keys[key_index].quat;
                
else
                {
                    
// calculate the time difference and interpolate time
                    time_diff  = m_rotate_keys[key_index + 1].time - m_rotate_keys[key_index].time;
                    time_inter = time - m_rotate_keys[key_index].time;

                    
// Get the quarternion value
                    //
                    // Interpolates between two quaternions, using spherical linear interpolation.
                    D3DXQuaternionSlerp(&quat, &m_rotate_keys[key_index].quat, 
                        &m_rotate_keys[key_index+1].quat, (
float)time_inter / time_diff);
                }

                
// combine with the new matrix

                // builds a rotation matrix from a quaternion.
                D3DXMatrixRotationQuaternion(&mat_temp, &quat);

                D3DXMatrixMultiply(&matrix, &matrix, &mat_temp);
            }

            
// update scale matrix
            if(m_num_scale_keys != 0 && m_scale_keys != NULL)
            {
                
// find the key that fits this time
                key_index = 0;

                
for(unsigned long i = 0; i < m_num_scale_keys; i++)
                {
                    
if(m_scale_keys[i].time <= time)
                        key_index = i;
                    
else
                        
break;
                }

                
// If it's the last key or non-smooth animation, then just set the key value.
                if(key_index == m_num_scale_keys - 1 || is_smooth == FALSE)
                    vector = m_scale_keys[key_index].scale;
                
else
                {
                    
// calculate the time difference and interpolate time
                    time_inter = time - m_scale_keys[key_index].time;

                    
// get the interpolated vector value
                    vector = m_scale_keys[key_index].scale + 
                             m_scale_keys[key_index].scale_inter * (
float)time_inter;
                }

                
// combine with the new matrix
                D3DXMatrixScaling(&mat_temp, vector.x, vector.y, vector.z);
                D3DXMatrixMultiply(&matrix, &matrix, &mat_temp);
            }

            
// update translation matrix
            if(m_num_position_keys != 0 && m_position_keys != NULL)
            {
                
// find the key that fits this time
                key_index = 0;

                
for(unsigned long i = 0; i < m_num_position_keys; i++)
                {
                    
if(m_position_keys[i].time <= time)
                        key_index = i;
                    
else
                        
break;
                }

                
// If it's the last key or non-smooth animation, then just set the key value.
                if(key_index == m_num_position_keys - 1 || is_smooth == FALSE)
                    vector = m_position_keys[key_index].pos;
                
else
                {
                    
// calculate the time difference and interpolate time
                    time_inter = time - m_position_keys[key_index].time;

                    
// get the interpolated vector value
                    vector = m_position_keys[key_index].pos + 
                             m_position_keys[key_index].pos_inter * (
float)time_inter;
                }

                
// combine with the new matrix
                D3DXMatrixTranslation(&mat_temp, vector.x, vector.y, vector.z);

                D3DXMatrixMultiply(&matrix, &matrix, &mat_temp);
            }

            
// set the new matrix
            m_frame->m_mat_transformed = matrix;
        }
        
        
// update matrix keys
        if(m_num_matrix_keys != 0 && m_matrix_keys != NULL)
        {
            
// find the key that fits this time
            key_index = 0;

            
for(unsigned long i = 0; i < m_num_matrix_keys; i++)
            {
                
if(m_matrix_keys[i].time <= time)
                    key_index = i;
                
else
                    
break;
            }

            
// If it's the last key or non-smooth animation, then just set the matrix.
            if(key_index == m_num_matrix_keys - 1 || is_smooth == FALSE)
                m_frame->m_mat_transformed = m_matrix_keys[key_index].matrix;
            
else
            {
                
// calculate the time difference and interpolated time
                time_inter = time - m_matrix_keys[key_index].time;

                
// set the new interpolation matrix
                matrix = m_matrix_keys[key_index].mat_inter * (float) time_inter;
                m_frame->m_mat_transformed = m_matrix_keys[key_index].matrix + matrix;
            }
        }
    }
};
 
接著再定義一個結(jié)構(gòu)體S_ANIMATION_SET來封裝動畫集合。
 
struct S_ANIMATION_SET
{
public:
    
char*           m_name;
    S_ANIMATION*    m_animation;

    unsigned 
long   m_time_length;

    S_ANIMATION_SET*  m_next;

    
//-----------------------------------------------------------------------------
    // Constructor, initialize member data.
    //-----------------------------------------------------------------------------
    S_ANIMATION_SET()
    {
        m_name      = NULL;
        m_animation = NULL;
        m_next      = NULL;

        m_time_length    = 0;
    }

    
//-----------------------------------------------------------------------------
    // Destructor, release resource.
    //-----------------------------------------------------------------------------
    ~S_ANIMATION_SET()
    {
        delete[] m_name;    m_name = NULL;
        delete m_animation; m_animation = NULL;
        delete m_next;      m_next = NULL;
    }

    
//-----------------------------------------------------------------------------
    // Find animation set in animation set link list which match specified name.
    //-----------------------------------------------------------------------------
    S_ANIMATION_SET* Find_Set(char* name)
    {
        
// return first instance if name is NULL
        if(name == NULL)
            
return this;

        
// compare names and return if exact match
        if(m_name != NULL && !strcmp(name, m_name))
            
return this;

        
// search next in list
        if(m_next != NULL)
        {
            S_ANIMATION_SET* anim_set;

            
if((anim_set = m_next->Find_Set(name)) != NULL)
                
return anim_set;
        }

        
return NULL;
    }

    
//-----------------------------------------------------------------------------
    // Update all animations in current animation set.
    //-----------------------------------------------------------------------------
    void Update(DWORD time, BOOL is_smooth)
    {
        S_ANIMATION* anim = m_animation;

        
while(anim != NULL)
        {
            
if(m_time_length == 0)
            {
                
// If time length of the animation set is zero, just use first frame.
                anim->Update(0, FALSE);
            }
            
else if(time >= m_time_length && anim->m_is_loop == FALSE)
            {
                
// If time beyonds max time length of the animation set and is not loop animation, use last frame.
                anim->Update(time, FALSE);
            }
            
else
            {
                
// Now, update animation usually.
                anim->Update(time % m_time_length, is_smooth);
            }

            anim = anim->m_next;
        }
    }
};

在定義好以上數(shù)據(jù)結(jié)構(gòu)的方法的基礎上,我們定義一個叫做OBJECT的類來封裝網(wǎng)格對象的繪制:

class OBJECT
{
protected:
    GRAPHICS*           _graphics;
    MESH*               _mesh;
    S_ANIMATION_SET*    _animation_set;
    WORLD_POSITION      _pos;

    BOOL                _use_billboard;    
    unsigned 
long       _start_time;

    
void _Update_Frame(S_FRAME* frame, D3DXMATRIX* matrix);
    
void _Draw_Frame(S_FRAME* frame);

public:
    OBJECT();
    ~OBJECT();

    BOOL Create(GRAPHICS* graphics, MESH* mesh = NULL);
    
void Free();

    
void Enable_Billboard(BOOL enable = TRUE);
    
void Attach_To_Object(OBJECT* objectchar* frame_name = NULL);

    
void Move(float x_pos, float y_pos, float z_pos);
    
void Move_Rel(float x_add, float y_add, float z_add);

    
void Rotate(float x_rot, float y_rot, float z_rot);
    
void Rotate_Rel(float x_add, float y_add, float z_add);

    
void Scale(float x_scale, float y_scale, float z_scale);
    
void Scale_Rel(float x_add, float y_add, float z_add);

    D3DXMATRIX* Get_Matrix();

    
float Get_X_Pos();
    
float Get_Y_Pos();
    
float Get_Z_Pos();
    
float Get_X_Rotation();
    
float Get_Y_Rotation();
    
float Get_Z_Rotation();
    
float Get_X_Scale();
    
float Get_Y_Scale();
    
float Get_Z_Scale();

    BOOL Get_Bounds(
float* min_x, float* min_y, float* min_z, float* max_x, float* max_y, float* max_z, float* radius);

    
void  Set_Mesh(MESH* mesh);
    MESH* Get_Mesh();

    
void  Set_Animation(ANIMATION* animation, char* name = NULL, unsigned long start_time = 0);
    
char* Get_Animation_Name();
    
void  Reset_Animation(unsigned long start_time = 0);

    
void Update_Animation(unsigned long time, BOOL is_smooth = TRUE);
    BOOL Animation_Complete(unsigned 
long time);

    
void Update();
    BOOL Render();
};
 
接著是類OBJECT的實現(xiàn):

//-------------------------------------------------------------------
// Constructor, initialize member data.
//-------------------------------------------------------------------
OBJECT::OBJECT()
{
    _graphics       = NULL;
    _mesh           = NULL;
    _animation_set  = NULL;
}

//-------------------------------------------------------------------
// Destructor, release resource.
//-------------------------------------------------------------------
OBJECT::~OBJECT()
{
    Free();
}

//-------------------------------------------------------------------
// Create an object with specified mesh object.
//-------------------------------------------------------------------
BOOL OBJECT::Create(GRAPHICS* graphics, MESH* mesh)
{
    
if((_graphics = graphics) == NULL)
        
return FALSE;

    _mesh = mesh;

    Move(0.0f, 0.0f, 0.0f);
    Rotate(0.0f, 0.0f, 0.0f);
    Scale(1.0f, 1.0f, 1.0f);

    
return TRUE;
}

//-------------------------------------------------------------------
// Release resource.
//-------------------------------------------------------------------
void OBJECT::Free()
{
    _graphics       = NULL;
    _mesh           = NULL;
    _animation_set  = NULL;
}

//-------------------------------------------------------------------
// Enable or disable billboard.
//-------------------------------------------------------------------
void OBJECT::Enable_Billboard(BOOL enable)
{
    _pos.Enable_Billboard(enable);
}

//-------------------------------------------------------------------
// Attach another object's transformed matrix to current object.
//-------------------------------------------------------------------
void OBJECT::Attach_To_Object(OBJECT* objectchar* frame_name)
{
    
if(object == NULL || object->_mesh == NULL)
    {
        _pos.Set_Combine_Matrix_1(NULL);
        _pos.Set_Combine_Matrix_2(NULL);
    }
    
else
    {
        S_FRAME* frame = 
object->_mesh->Get_Frame(frame_name);

        
if(frame == NULL)
        {
            _pos.Set_Combine_Matrix_1(NULL);
            _pos.Set_Combine_Matrix_2(NULL);
        }
        
else
        {
            _pos.Set_Combine_Matrix_1(&frame->m_mat_combined);
            _pos.Set_Combine_Matrix_2(
object->_pos.Get_Matrix());
        }
    }
}

//-------------------------------------------------------------------
// Move object to new world position with specified relative value.
//-------------------------------------------------------------------
void OBJECT::Move(float x_pos, float y_pos, float z_pos)
{
    _pos.Move(x_pos, y_pos, z_pos);
}

//-------------------------------------------------------------------
// Move object to new world position which is specified by new relative
// value and current position.
//-------------------------------------------------------------------
void OBJECT::Move_Rel(float x_add, float y_add, float z_add)
{
    _pos.Move_Rel(x_add, y_add, z_add);
}

//-------------------------------------------------------------------
// Rotate around x, y, z, axis with specified degree.
//-------------------------------------------------------------------
void OBJECT::Rotate(float x_rot, float y_rot, float z_rot)
{
    _pos.Rotate(x_rot, y_rot, z_rot);
}

//-------------------------------------------------------------------
// Rotate around x, y, z, axis which is specified with new relative 
// degree and current rotation value.
//-------------------------------------------------------------------
void OBJECT::Rotate_Rel(float x_add, float y_add, float z_add)
{
    _pos.Rotate_Rel(x_add, y_add, z_add);
}

//-------------------------------------------------------------------
// Build scaling matrix.
//-------------------------------------------------------------------
void OBJECT::Scale(float x_scale, float y_scale, float z_scale)
{
    _pos.Scale(x_scale, y_scale, z_scale);
}

//-------------------------------------------------------------------
// Build scaling matrix with specified value and current scaling value.
//-------------------------------------------------------------------
void OBJECT::Scale_Rel(float x_add, float y_add, float z_add)
{
    _pos.Scale_Rel(x_add, y_add, z_add);
}

//-------------------------------------------------------------------
// Get current world transform matrix.
//-------------------------------------------------------------------
D3DXMATRIX* OBJECT::Get_Matrix()
{
    
return _pos.Get_Matrix();
}

//-------------------------------------------------------------------
// Set mesh to current object.
//-------------------------------------------------------------------
void OBJECT::Set_Mesh(MESH *mesh)
{
    _mesh = mesh;
}

//-------------------------------------------------------------------
// Get current object's mesh.
//-------------------------------------------------------------------
MESH* OBJECT::Get_Mesh()
{
    
return _mesh;
}

//-------------------------------------------------------------------
// Set animation set with specified name and start time.
//-------------------------------------------------------------------
void OBJECT::Set_Animation(ANIMATION* animation, char* name, unsigned long start_time)
{
    _start_time = start_time;

    
if(animation == NULL)
        _animation_set = NULL;
    
else
        _animation_set = animation->Get_Animation_Set(name);
}

//-------------------------------------------------------------------
// Get the name of animation set.
//-------------------------------------------------------------------
char* OBJECT::Get_Animation_Name()
{
    
if(_animation_set == NULL)
        
return NULL;

    
return _animation_set->m_name;
}

//-------------------------------------------------------------------
// Reset start time of animation set.
//-------------------------------------------------------------------
void OBJECT::Reset_Animation(unsigned long start_time)
{
    _start_time = start_time;
}

//-------------------------------------------------------------------
// Get x coordinate of current obejct.
//-------------------------------------------------------------------
float OBJECT::Get_X_Pos()
{
    
return _pos.Get_X_Pos();
}

//-------------------------------------------------------------------
// Get y coordinate of current obejct.
//-------------------------------------------------------------------
float OBJECT::Get_Y_Pos()
{
    
return _pos.Get_Y_Pos();
}

//-------------------------------------------------------------------
// Get z coordinate of current obejct.
//-------------------------------------------------------------------
float OBJECT::Get_Z_Pos()
{
    
return _pos.Get_Z_Pos();
}

//-------------------------------------------------------------------
// Get current rotation value which rotate around x axis.
//-------------------------------------------------------------------
float OBJECT::Get_X_Rotation()
{
    
return _pos.Get_X_Rotation();
}

//-------------------------------------------------------------------
// Get current rotation value which rotate around y axis.
//-------------------------------------------------------------------
float OBJECT::Get_Y_Rotation()
{
    
return _pos.Get_Y_Rotation();
}

//-------------------------------------------------------------------
// Get current rotation value which rotate around z axis.
//-------------------------------------------------------------------
float OBJECT::Get_Z_Rotation()
{
    
return _pos.Get_Z_Rotation();
}

//-------------------------------------------------------------------
// Get current scale value which around x axis.
//-------------------------------------------------------------------
float OBJECT::Get_X_Scale()
{
    
return _pos.Get_X_Scale();
}

//-------------------------------------------------------------------
// Get current scale value which around y axis.
//-------------------------------------------------------------------
float OBJECT::Get_Y_Scale()
{
    
return _pos.Get_Y_Scale();
}

//-------------------------------------------------------------------
// Get current scale value which around z axis.
//-------------------------------------------------------------------
float OBJECT::Get_Z_Scale()
{
    
return _pos.Get_Z_Scale();
}

//-------------------------------------------------------------------
// Get bound coordinate and radius after scale.
//-------------------------------------------------------------------
BOOL OBJECT::Get_Bounds(float *min_x, float *min_y, float *min_z, float *max_x, float *max_y, float *max_z, 
                        
float *radius)
{
    
if(_mesh == NULL)
        
return FALSE;

    
// Get bound box coordiante and radius.
    _mesh->Get_Bounds(min_x, min_y, min_z, max_x, max_y, max_z, radius);

    
// scale bounds
    float x_scale = _pos.Get_X_Scale();
    
float y_scale = _pos.Get_Y_Scale();
    
float z_scale = _pos.Get_Z_Scale();

    
if(min_x != NULL)   *min_x *= x_scale;
    
if(min_y != NULL)   *min_y *= y_scale;
    
if(min_z != NULL)   *min_z *= z_scale;

    
if(max_x != NULL)   *max_x *= x_scale;
    
if(max_y != NULL)   *max_y *= y_scale;
    
if(max_z != NULL)   *max_z *= z_scale;

    
if(radius != NULL)
    {
        
float length = (float) sqrt(x_scale * x_scale + y_scale * y_scale + z_scale * z_scale);
        (*radius) *= length;
    }

    
return TRUE;
}

//-------------------------------------------------------------------
// Update world tranform matrix.
//-------------------------------------------------------------------
void OBJECT::Update()
{
    _pos.Update(_graphics);
}

//-----------------------------------------------------------------------------
// Update all animations in current animation set.
//-----------------------------------------------------------------------------
void OBJECT::Update_Animation(unsigned long time, BOOL is_smooth)
{
    
if(_animation_set)
    {
        
// reset all frames's transformed matrices to original matrices
        _mesh->Get_Root_Frame()->Reset_Matrices();

        
// update all animations in current animation set
        _animation_set->Update(time - _start_time, is_smooth);
    }
}

//-----------------------------------------------------------------------------
// Judge whether animation has completed.
//-----------------------------------------------------------------------------
BOOL OBJECT::Animation_Complete(unsigned long time)
{
    
if(_animation_set == NULL)
        
return TRUE;

    
if((time - _start_time) >= _animation_set->m_time_length)
        
return TRUE;

    
return FALSE;
}

//-----------------------------------------------------------------------------
// Render all meshes in this object.
//-----------------------------------------------------------------------------
BOOL OBJECT::Render()
{
    D3DXMATRIX matrix;

    
// error checking
    if(_graphics == NULL || _mesh == NULL || _mesh->Get_Root_Frame() == NULL || _mesh->Get_Root_Mesh() == NULL)
        
return FALSE;

    
// update the object matrix
    Update();

    
// update the frame matrices
    D3DXMatrixIdentity(&matrix);
    _Update_Frame(_mesh->Get_Root_Frame(), &matrix);

    
// copy frame matrices to bone matrices
    _mesh->Get_Root_Mesh()->Copy_Frame_To_Bone_Matrices();

    
// draw all frame meshes
    _Draw_Frame(_mesh->Get_Root_Frame());

    
return TRUE;
}

//-----------------------------------------------------------------------------
// Update transformation matrix of all frames, call recursively.
//-----------------------------------------------------------------------------
void OBJECT::_Update_Frame(S_FRAME *frame, D3DXMATRIX *matrix)
{
    
// return if no more frames
    if(frame == NULL)
        
return;

    
// calculate frame matrix based on animation or not
    if(_animation_set == NULL)
        D3DXMatrixMultiply(&frame->m_mat_combined, &frame->m_mat_original, matrix);
    
else
        D3DXMatrixMultiply(&frame->m_mat_combined, &frame->m_mat_transformed, matrix);

    
// update child frames
    _Update_Frame(frame->m_child, &frame->m_mat_combined);

    
// update sibling frames
    _Update_Frame(frame->m_sibling, matrix);
}

//-----------------------------------------------------------------------------
// Draw all meshes in frames which under current specified frame, call recursively.
//-----------------------------------------------------------------------------
void OBJECT::_Draw_Frame(S_FRAME *frame)
{
    S_MESH_LIST*    list;
    S_MESH*         mesh;
    D3DXMATRIX      mat_world;

    
if(frame == NULL)
        
return;

    
if((list = frame->m_mesh_list) != NULL)
    {
        
// draw all meshes in this frame
        while(list != NULL)
        {
            
// see if there's a mesh to draw
            if((mesh = list->m_mesh) != NULL)
            {
                
// generate the mesh if using bones and set world matrix
                if(mesh->m_num_bones && mesh->m_skin_mesh)
                {
                    
void* src_ptr;
                    
void* dest_ptr;

                    
// lock the source and destination vertex buffers
                    mesh->m_mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**) &src_ptr);
                    mesh->m_skin_mesh->LockVertexBuffer(0, (
void**) &dest_ptr);

                    
// perfrom skinned mesh update
                    mesh->m_skin_info->UpdateSkinnedMesh(mesh->m_matrices, NULL, src_ptr, dest_ptr);

                    
// unlock vertex buffers
                    mesh->m_skin_mesh->UnlockVertexBuffer();
                    mesh->m_mesh->UnlockVertexBuffer();

                    
// set object world transformation
                    _graphics->Get_Device_COM()->SetTransform(D3DTS_WORLD, _pos.Get_Matrix());
                }
                
else
                {
                    
// set the world transformation matrix for this frame
                    D3DXMatrixMultiply(&mat_world, &frame->m_mat_combined, _pos.Get_Matrix());
                    _graphics->Get_Device_COM()->SetTransform(D3DTS_WORLD, &mat_world);
                }

                
// loop through materials and draw the mesh
                for(DWORD i = 0; i < mesh->m_num_materials; i++)
                {
                    
// don't draw materials with no alpha (0.0)
                    if(mesh->m_materials[i].Diffuse.a != 0.0f)
                    {
                        _graphics->Get_Device_COM()->SetMaterial(&mesh->m_materials[i]);
                        _graphics->Get_Device_COM()->SetTexture(0, mesh->m_textures[i]);

                        
// enabled alpha blending based on material alpha
                        if(mesh->m_materials[i].Diffuse.a != 1.0f)
                            _graphics->Enable_Alpha_Blending(TRUE, D3DBLEND_SRCCOLOR, D3DBLEND_ONE);

                        
// draw mesh or skinned mehs
                        if(mesh->m_skin_mesh != NULL)
                            mesh->m_skin_mesh->DrawSubset(i);
                        
else
                            mesh->m_mesh->DrawSubset(i);

                        
// disable alpha blending based on material alpha
                        if(mesh->m_materials[i].Diffuse.a != 1.0f)
                            _graphics->Enable_Alpha_Blending(FALSE);
                    }
                }
            }

            
// next mesh in lsit
            list = list->m_next;
        }
    }

    
// draw child frames and sibling frames
    _Draw_Frame(frame->m_child);
    _Draw_Frame(frame->m_sibling);
}

其中涉及到網(wǎng)格動畫組件類ANIMATION,其簡要定義如下:

class ANIMATION
{
protected:
    
long                _num_animations;
    S_ANIMATION_SET*    _animation_set;

public:
    ANIMATION();
    ~ANIMATION();

    S_ANIMATION_SET* Get_Animation_Set(
char* name = NULL);

    
void Free();
};

//-------------------------------------------------------------------
// Constructor, initialize member data.
//-------------------------------------------------------------------
ANIMATION::ANIMATION()
{
    _num_animations = 0;
    _animation_set  = NULL;
}

//-------------------------------------------------------------------
// Destructor, free resource.
//-------------------------------------------------------------------
ANIMATION::~ANIMATION()
{
    Free();
}

//-------------------------------------------------------------------
// Free resource.
//-------------------------------------------------------------------
void ANIMATION::Free()
{
    delete _animation_set;
    _animation_set = NULL;

    _num_animations = 0;
}

//-------------------------------------------------------------------
// Get animation set which match specified name.
//-------------------------------------------------------------------
S_ANIMATION_SET* ANIMATION::Get_Animation_Set(char* name)
{
    
if(_animation_set == NULL)
        
return NULL;

    
return _animation_set->Find_Set(name);
}

接著,我們編寫測試代碼來測試類OBJECT:

點擊下載源碼和工程

/*****************************************************************************
PURPOSE:
    Test for class OBJECT.
*****************************************************************************/


#include "Core_Global.h"

#pragma warning(disable : 4996)

//===========================================================================
// Defines class APP which public inherits from class APPLICATION.
//===========================================================================
class APP : public APPLICATION
{
private:
    GRAPHICS        _graphics;
    MESH            _mesh;
    OBJECT          _object;
    
public:    
    BOOL Init();
    BOOL Shutdown();
    BOOL Frame();
};

//-----------------------------------------------------------------------------
// Initialize graphics, set display mode, set vertex buffer, load texture file.
//-----------------------------------------------------------------------------
BOOL APP::Init()
{    
    D3DXMATRIX mat_view;

    
// initialize graphics
    if (! _graphics.Init())
        
return FALSE;    

    
// set display mode for graphics
    if(! _graphics.Set_Mode(Get_Hwnd(), TRUE, FALSE, 400, 400, 16))
        
return FALSE;

    
// disable D3D lighting
    _graphics.Enable_Lighting(FALSE);

    
// set perspective projection transform matrix.
    _graphics.Set_Perspective(D3DX_PI/4.0f, 1.33333f, 1.0f, 1000.0f);

    
// 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));

    _graphics.Get_Device_COM()->SetTransform(D3DTS_VIEW, &mat_view);

    
// load mesh
    if(! _mesh.Load(&_graphics, "warrior.x"))
        
return FALSE;

    
// create object to draw
    if(! _object.Create(&_graphics, &_mesh))
        
return FALSE;

    
return TRUE;
}

//-----------------------------------------------------------------------------
// Release all d3d resource.
//-----------------------------------------------------------------------------
BOOL APP::Shutdown()
{
    
return TRUE;
}

//-----------------------------------------------------------------------------
// Render a frame.
//-----------------------------------------------------------------------------
BOOL APP::Frame()
{
    D3DXMATRIX mat_world;

    
// clear display with specified color
    _graphics.Clear_Display(D3DCOLOR_RGBA(0, 128, 0, 255));

    
// begin scene
    if(_graphics.Begin_Scene())
    {
        
// rotate object along x-axis, y-axis.       
        _object.Rotate((float) (timeGetTime() / 2000.0), (float) (timeGetTime() / 1000.0), 0);

        
// draw object
        _object.Render();
        
        
// end the scene
        _graphics.End_Scene();       
    }

    
// display video buffer
    _graphics.Display();
    
    
return TRUE;
}

int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    APP app;

    
return app.Run();
}

運行截圖:

posted on 2007-09-14 20:54 lovedday 閱讀(603) 評論(0)  編輯 收藏 引用

公告

導航

統(tǒng)計

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美视频一区二区三区| 精品不卡在线| 一区二区高清在线| 亚洲精品免费在线播放| 免费在线观看日韩欧美| 亚洲精品一区在线| 亚洲视频电影在线| 好吊色欧美一区二区三区四区| 久久久伊人欧美| 欧美jizzhd精品欧美喷水| 亚洲精品日韩在线| 在线视频免费在线观看一区二区| 国产乱子伦一区二区三区国色天香| 久久不见久久见免费视频1| 久久久999精品| 日韩午夜在线观看视频| 一区二区三区毛片| 黄色成人片子| 99精品99| 在线成人亚洲| 宅男噜噜噜66一区二区 | 亚洲精品在线免费| 国产精品女人久久久久久| 久久夜色精品国产亚洲aⅴ| 欧美大秀在线观看| 久久大逼视频| 欧美另类高清视频在线| 久久久久久9| 欧美日韩国产三级| 久久艳片www.17c.com| 欧美日韩大陆在线| 美国成人直播| 国产伦精品一区二区三区视频孕妇| 久久综合99re88久久爱| 国产精品vip| 欧美激情91| 国户精品久久久久久久久久久不卡| 亚洲娇小video精品| 国产亚洲综合在线| 亚洲色图综合久久| 亚洲另类在线一区| 久久亚洲捆绑美女| 久久国产精品亚洲77777| 欧美激情精品久久久久久久变态 | 亚洲免费小视频| 欧美成人第一页| 久久综合伊人77777尤物| 国产精品一区二区你懂得 | 麻豆精品在线视频| 国产无一区二区| 亚洲视频你懂的| av不卡在线| 欧美高清在线一区| 欧美a级一区二区| 国产真实乱偷精品视频免| 中日韩高清电影网| 亚洲一区二区三区在线看| 欧美一区二区三区成人| 欧美日韩ab| 亚洲第一二三四五区| 狠狠色丁香婷婷综合影院 | 久久久亚洲午夜电影| 国产色产综合色产在线视频| 亚洲天堂av在线免费| 亚洲性视频网址| 欧美亚日韩国产aⅴ精品中极品| 91久久精品国产91性色| 亚洲人成在线观看| 欧美二区在线观看| 亚洲品质自拍| 一本综合精品| 国产精品国产三级国产aⅴ无密码| 亚洲精品国产欧美| 亚洲午夜极品| 国产精品推荐精品| 欧美制服丝袜第一页| 久久夜色精品亚洲噜噜国产mv| 国产一区二区三区四区老人| 久久精品91久久久久久再现| 久久久一区二区| 亚洲黄色免费电影| 欧美日韩成人综合| 国产精品99久久不卡二区| 欧美一区二区三区日韩| 国产一区二区三区精品久久久| 久久av红桃一区二区小说| 老司机67194精品线观看| 91久久黄色| 国产精品国产三级国产专区53| 欧美亚洲在线播放| 欧美高清影院| 亚洲欧美成人一区二区三区| 国产一区二区三区日韩欧美| 鲁大师影院一区二区三区| 亚洲精品国产无天堂网2021| 欧美在线视频免费观看| 在线精品国产欧美| 欧美日韩一区二区三区在线观看免| 亚洲一区视频| 欧美激情视频网站| 欧美伊人久久久久久午夜久久久久 | 久久久久国产一区二区| 亚洲国产日日夜夜| 欧美一区免费| 亚洲美女中出| 黄色成人在线网址| 欧美日韩妖精视频| 欧美主播一区二区三区美女 久久精品人 | 亚洲男人的天堂在线观看| 美国十次了思思久久精品导航| 999亚洲国产精| 国内精品视频666| 国产精品成人免费精品自在线观看| 久久国产精品久久久久久久久久| 亚洲日本理论电影| 久久综合九色综合久99| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲成色最大综合在线| 国产视频自拍一区| 欧美日韩直播| 欧美成人国产一区二区| 久久精品道一区二区三区| 亚洲一区欧美| 日韩亚洲不卡在线| 亚洲国产小视频在线观看| 久久视频国产精品免费视频在线| 亚洲一本大道在线| 99re66热这里只有精品3直播 | 国产亚洲精品美女| 国产精品久久毛片a| 久久亚洲春色中文字幕| 亚洲一区视频| 这里只有精品视频在线| 亚洲精品中文字| 91久久精品日日躁夜夜躁国产| 国产亚洲欧美一区在线观看| 国产精品色午夜在线观看| 欧美无乱码久久久免费午夜一区| 欧美日本乱大交xxxxx| 欧美成人精品| 欧美激情第三页| 欧美精品一区二区三区四区| 欧美/亚洲一区| 欧美大片一区二区三区| 免费亚洲一区| 欧美日韩国产黄| 欧美视频一区在线| 国产精品久久9| 国产精品人成在线观看免费| 国产精品区一区二区三| 国产伦精品一区二区三区在线观看 | 久久国产日本精品| 久久精品在线视频| 久久人人精品| 欧美成人福利视频| 亚洲欧洲视频在线| 亚洲无线视频| 久久不见久久见免费视频1| 欧美中文在线观看国产| 久久久久欧美精品| 欧美 日韩 国产在线| 欧美日韩国产色视频| 国产精品综合不卡av| 伊甸园精品99久久久久久| 亚洲精品乱码久久久久久日本蜜臀| 99re热精品| 欧美夜福利tv在线| 欧美大胆人体视频| 9久草视频在线视频精品| 亚洲综合二区| 麻豆国产va免费精品高清在线| 欧美精品日韩综合在线| 国产欧美精品日韩区二区麻豆天美| 激情伊人五月天久久综合| 亚洲人www| 欧美一区二区成人| 亚洲风情亚aⅴ在线发布| 99精品视频一区| 久久久九九九九| 欧美日本中文字幕| 国产丝袜美腿一区二区三区| 亚洲三级色网| 久久国产精品免费一区| 91久久黄色| 欧美中文在线观看| 欧美色中文字幕| 激情国产一区二区| 亚洲综合好骚| 亚洲国产小视频| 久久久午夜视频| 国产精品乱码妇女bbbb| 亚洲美女网站| 免费成人av资源网| 性做久久久久久久久| 欧美日韩成人综合天天影院| 伊人久久亚洲美女图片| 欧美另类69精品久久久久9999| 国产欧美日韩精品丝袜高跟鞋| 一本久久知道综合久久| 奶水喷射视频一区|