• <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>

            天行健 君子當自強而不息

            創建游戲內核(14)

             

            本篇是 創建游戲內核(13)的續篇,其中涉及到的網格繪制知識請參閱D3D中網格模型的運用

             

            使用.X樣式三維動畫

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

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

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

             

            關鍵楨技術

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

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

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

            只需要在那些幀之間進行插值計算便可以產生平滑的動畫,插值(interpolating)是一種計算兩個數值之間,隨時間變化的過渡數值的方法。這里使用的關鍵楨形式是矩陣關鍵楨(matrix key framing),因為使用的是D3DX矩陣對象,所以使用這種格式的關鍵楨會十分容易。比如說,有兩個矩陣mat1和mat2,分別表示開始和結束的矩陣,他們之間的時間距離表示為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文件中提供了動畫數據,該動畫數據位于一個特定數據對象的集合里,同時,也可以使用與加載蒙皮網格模型相同的技術去加載那些動畫對象的數據。特定的數據對象包含了在關鍵幀技術中所使用到的各種各樣的關鍵點,每個關鍵點代表了一種變換:旋轉、縮放、平移。為了使之更加容易,可以指定同時組合了所有變換的矩陣關鍵點。

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

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

             

            使用OBJECT繪制對象

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

            首先定義表示插值旋轉變換、平移變換、縮放、變換矩陣的數據結構:

            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的結構體來封裝框架的變換矩陣。

            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;
                        }
                    }
                }
            };
             
            接著再定義一個結構體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;
                    }
                }
            };

            在定義好以上數據結構的方法的基礎上,我們定義一個叫做OBJECT的類來封裝網格對象的繪制:

            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的實現:

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

            其中涉及到網格動畫組件類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 閱讀(594) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            三级三级久久三级久久| 国产亚洲精午夜久久久久久| 精品无码久久久久久久动漫| 国产精品久久久久久久久鸭| 久久无码AV一区二区三区| 天天做夜夜做久久做狠狠| 亚洲精品国产成人99久久| 狠色狠色狠狠色综合久久| 久久66热人妻偷产精品9| 久久久国产精品亚洲一区| 久久久亚洲欧洲日产国码二区| 一本一本久久a久久综合精品蜜桃| 伊人情人综合成人久久网小说| 免费精品久久久久久中文字幕| 久久九九免费高清视频| 欧美国产成人久久精品| 奇米影视7777久久精品人人爽 | 久久婷婷色香五月综合激情| 亚洲午夜福利精品久久| 久久精品aⅴ无码中文字字幕不卡| 亚洲va久久久噜噜噜久久狠狠| 久久99国产综合精品免费| 女人香蕉久久**毛片精品| 久久夜色精品国产亚洲av| 99久久综合国产精品免费| 国产亚洲综合久久系列| 精品多毛少妇人妻AV免费久久| 久久99热这里只有精品66| 久久精品无码一区二区无码| 国产精品99久久精品爆乳| 2021国产精品午夜久久| 久久青草国产精品一区| 亚洲v国产v天堂a无码久久| 国产精品禁18久久久夂久| 久久久久国产日韩精品网站| 麻豆成人久久精品二区三区免费| 91精品国产高清久久久久久国产嫩草| 欧美久久久久久精选9999| 久久精品国产亚洲AV麻豆网站| 伊人久久大香线蕉综合网站| 日本福利片国产午夜久久|