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

            天行健 君子當(dāng)自強(qiáng)而不息

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

             

            本篇是 創(chuàng)建游戲內(nèi)核(14)的續(xù)篇。


            使用ANIMATION移動網(wǎng)格


            ANIMATION類是網(wǎng)格動畫組件,也是圖形內(nèi)核的最后一個類。使用ANIMATION,就能夠從.X文件加載一連串動畫集,把它同OBJECT結(jié)合起來創(chuàng)建網(wǎng)格動畫。ANIMATION類很小,類似 于MESH,它也有一些用于保存動畫數(shù)據(jù)鏈表的結(jié)構(gòu)體。

            首先定義一些結(jié)構(gòu)體來存儲.X文件里的旋轉(zhuǎn)關(guān)鍵點(diǎn)、縮放關(guān)鍵點(diǎn)、平移關(guān)鍵點(diǎn)、矩陣關(guān)鍵點(diǎn)信息。

            struct S_XFILE_ROTATE_KEY
            {
                DWORD time;
                DWORD floats;
                
            float w;
                
            float x;
                
            float y;
                
            float z;
            };

            struct S_XFILE_SCALE_KEY
            {
                DWORD       time;
                DWORD       floats;
                D3DXVECTOR3 scale;
            };

            struct S_XFILE_POSITION_KEY
            {
                DWORD       time;
                DWORD       floats;
                D3DXVECTOR3 pos;
            };

            struct S_XFILE_MATRIX_KEY
            {
                DWORD       time;
                DWORD       floats;
                D3DXMATRIX  matrix;
            };

            接著我們定義類ANIMATION:

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

                
            void _Parse_XFile_Data(ID3DXFileData* xfile_data, S_ANIMATION_SET* anim_set_to_parse, S_ANIMATION* anim_to_parse);

            public:
                ANIMATION();
                ~ANIMATION();

                BOOL Is_Loaded();

                
            long Get_Num_Animations();             
                S_ANIMATION_SET* Get_Animation_Set(
            char* name = NULL);
                unsigned 
            long Get_Time_Length(char* name = NULL);

                BOOL Load(
            const char* filename, MESH* map_mesh = NULL);
                
            void Free();

                BOOL Map_To_Mesh(MESH* mesh);

                BOOL Set_Loop(BOOL is_loop, 
            char* name = NULL);
            };

            以下是類ANIMATION的實(shí)現(xiàn):

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

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

            //-------------------------------------------------------------------
            // Load animation information from specified file and map mesh.
            //-------------------------------------------------------------------
            BOOL ANIMATION::Load(const char *filename, MESH *map_mesh)
            {
                ID3DXFile*              xfile = NULL;
                ID3DXFileEnumObject*    xfile_enum = NULL;
                ID3DXFileData*          xfile_data = NULL;

                
            // free a prior animation
                Free();

                
            // error checking
                if(filename == NULL)
                    
            return FALSE;

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

                
            // create an enumeration object
                if(FAILED(xfile->CreateEnumObject((LPVOID) filename, DXFILELOAD_FROMFILE, &xfile_enum)))
                {
                    xfile->Release();
                    
            return FALSE;
                }

                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 animation
                for(SIZE_T i = 0; i < num_child; i++)
                {
                    
            if(FAILED(xfile_enum->GetChild(i, &xfile_data)))
                        
            return FALSE;

                    
            // parse xfile data
                    _Parse_XFile_Data(xfile_data, NULL, NULL);

                    Release_COM(xfile_data);
                }

                Release_COM(xfile_enum);
                Release_COM(xfile);

                
            // map the animation to the supplied mesh (if any)
                if(map_mesh != NULL)
                    Map_To_Mesh(map_mesh);

                
            return TRUE;
            }

            //-------------------------------------------------------------------
            // Parse xfile data object which type is animation or animation set,
            // call recursively.
            //-------------------------------------------------------------------
            void ANIMATION::_Parse_XFile_Data(ID3DXFileData* xfile_data, 
                                              S_ANIMATION_SET* anim_set_to_parse, S_ANIMATION* anim_to_parse)
            {
                GUID    type;
                DWORD   size;
                
            char*   name = NULL;

                
            // get the template type
                if(FAILED(xfile_data->GetType(&type)))
                    
            return;

                
            // get the template name (if any)
                if(FAILED(xfile_data->GetName(NULL, &size)))
                    
            return;

                
            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 animation set and current animation
                S_ANIMATION_SET*    cur_anim_set = anim_set_to_parse;
                S_ANIMATION*        cur_anim = anim_to_parse;

                
            // process the templates

                S_ANIMATION*        new_anim = NULL;
                S_ANIMATION_SET*    new_anim_set = NULL;

                PBYTE*  data_ptr;
                DWORD   time;

                S_XFILE_ROTATE_KEY*     rot_key;
                S_XFILE_SCALE_KEY*      scale_key;
                S_XFILE_POSITION_KEY*   pos_key;
                S_XFILE_MATRIX_KEY*     mat_key;

                
            if(type == TID_D3DRMAnimationSet)   // process an animation set
                {
                    
            // create an animation set structure
                    if((new_anim_set = new S_ANIMATION_SET()) == NULL)
                        
            return;

                    
            // set the name
                    new_anim_set->m_name = name;
                    name = NULL;

                    
            // link into the animation set list
                    new_anim_set->m_next = _animation_set;
                    _animation_set = new_anim_set;

                    
            // set new animation set as current animation set
                    cur_anim_set = new_anim_set;
                }
                
            else if(type == TID_D3DRMAnimation && cur_anim_set != NULL) // process an animtion
                {
                    
            // create an animation structure
                    if((new_anim = new S_ANIMATION()) == NULL)
                        
            return;

                    
            // set the name
                    new_anim->m_name = name;
                    name = NULL;

                    
            // link into the animaton set
                    new_anim->m_next = cur_anim_set->m_animation;
                    cur_anim_set->m_animation = new_anim;

                    cur_anim = new_anim;
                }
                
            else if(type == TID_D3DRMAnimationKey && cur_anim != NULL)  // process an animation key
                {
                    
            // load in this animation's key data
                    if(FAILED(xfile_data->Lock(&size, (LPCVOID*) &data_ptr)))
                        
            return;

                    DWORD key_type = ((DWORD*) data_ptr)[0];
                    DWORD num_keys = ((DWORD*) data_ptr)[1];

                    
            switch(key_type)
                    {
                    
            case 0:     // rotate key type
                        delete[] cur_anim->m_rotate_keys;
                        
                        
            if((cur_anim->m_rotate_keys = new S_ROTATE_KEY[num_keys]) == NULL)
                            
            return;

                        cur_anim->m_num_rotate_keys = num_keys;
                        rot_key = (S_XFILE_ROTATE_KEY*) ((
            char*) data_ptr + sizeof(DWORD) * 2);

                        
            // translate rotate key information from xfile to animation
                        for(DWORD i = 0; i < num_keys; i++)
                        {
                            cur_anim->m_rotate_keys[i].time = rot_key->time;

                            cur_anim->m_rotate_keys[i].quat.x = -rot_key->x;
                            cur_anim->m_rotate_keys[i].quat.y = -rot_key->y;
                            cur_anim->m_rotate_keys[i].quat.z = -rot_key->z;
                            cur_anim->m_rotate_keys[i].quat.w = -rot_key->w;

                            
            if(rot_key->time > cur_anim_set->m_time_length)
                                cur_anim_set->m_time_length = rot_key->time;

                            rot_key += 1;
                        }

                        
            break;

                    
            case 1:     // scale key type
                        delete[] cur_anim->m_scale_keys;

                        
            if((cur_anim->m_scale_keys = new S_SCALE_KEY[num_keys]) == NULL)
                            
            return;

                        cur_anim->m_num_scale_keys = num_keys;
                        scale_key = (S_XFILE_SCALE_KEY*) ((
            char*) data_ptr + sizeof(DWORD) * 2);

                        
            // translate scale key information from xfile to animtion
                        for(DWORD i = 0; i < num_keys; i++)
                        {
                            cur_anim->m_scale_keys[i].time  = scale_key->time;
                            cur_anim->m_scale_keys[i].scale = scale_key->scale;

                            
            if(scale_key->time > cur_anim_set->m_time_length)
                                cur_anim_set->m_time_length = scale_key->time;

                            scale_key += 1;
                        }
                    
                        
            // calculate the interpolation values
                        if(num_keys > 1)
                        {
                            
            for(DWORD i = 0; i < num_keys -1; i++)
                            {
                                time = cur_anim->m_scale_keys[i+1].time - cur_anim->m_scale_keys[i].time;

                                
            if(time == 0)
                                    time = 1;

                                cur_anim->m_scale_keys[i].scale_inter = 
                                    (cur_anim->m_scale_keys[i+1].scale - cur_anim->m_scale_keys[i].scale) / (
            float)time;
                            }
                        }

                        
            break;

                    
            case 2:     // position key type
                        delete[] cur_anim->m_position_keys;

                        
            if((cur_anim->m_position_keys = new S_POSITION_KEY[num_keys]) == NULL)
                            
            return;

                        cur_anim->m_num_position_keys = num_keys;
                        pos_key = (S_XFILE_POSITION_KEY*) ((
            char*) data_ptr + sizeof(DWORD) * 2);

                        
            // translate position key informaton from xfile to animtion
                        for(DWORD i = 0; i < num_keys; i++)
                        {
                            cur_anim->m_position_keys[i].time = pos_key->time;
                            cur_anim->m_position_keys[i].pos  = pos_key->pos;

                            
            if(pos_key->time > cur_anim_set->m_time_length)
                                cur_anim_set->m_time_length = pos_key->time;

                            pos_key += 1;
                        }

                        
            // calculate the interpolation values
                        if(num_keys > 1)
                        {
                            
            for(DWORD i = 0;i < num_keys - 1; i++)
                            {
                                time = cur_anim->m_position_keys[i+1].time - cur_anim->m_position_keys[i].time;

                                
            if(time == 0)
                                    time = 1;

                                cur_anim->m_position_keys[i].pos_inter = 
                                    (cur_anim->m_position_keys[i+1].pos - cur_anim->m_position_keys[i].pos) / (
            float)time;
                            }
                        }

                        
            break;

                    
            case 4:     // matrix key type
                        delete[] cur_anim->m_matrix_keys;

                        
            if((cur_anim->m_matrix_keys = new S_MATRIX_KEY[num_keys]) == NULL)
                            
            return;

                        cur_anim->m_num_matrix_keys = num_keys;
                        mat_key = (S_XFILE_MATRIX_KEY*) ((
            char*) data_ptr + sizeof(DWORD) * 2);

                        
            // translate matrix key information from xfile to animation
                        for(DWORD i = 0; i < num_keys; i++)
                        {
                            cur_anim->m_matrix_keys[i].time   = mat_key->time;
                            cur_anim->m_matrix_keys[i].matrix = mat_key->matrix;

                            
            if(mat_key->time > cur_anim_set->m_time_length)
                                cur_anim_set->m_time_length = mat_key->time;

                            mat_key += 1;
                        }

                        
            // calculate the interpolation matrices
                        if(num_keys > 1)
                        {
                            
            for(DWORD i = 0; i < num_keys - 1; i++)
                            {
                                time = cur_anim->m_matrix_keys[i+1].time - cur_anim->m_matrix_keys[i].time;

                                
            if(time == 0)
                                    time = 1;

                                cur_anim->m_matrix_keys[i].mat_inter =
                                    (cur_anim->m_matrix_keys[i+1].matrix - cur_anim->m_matrix_keys[i].matrix) / (
            float)time;
                            }
                        }

                        
            break;
                    }

                    xfile_data->Unlock();
                }
                
            else if(type == TID_D3DRMAnimationOptions && cur_anim != NULL)  // process animation options
                {
                    
            // load in this animation's options
                    if(FAILED(xfile_data->Lock(&size, (LPCVOID*) &data_ptr)))
                        
            return;

                    
            // process looping information
                    if(((DWORD*) data_ptr)[0] == 0)
                        cur_anim->m_is_loop = TRUE;
                    
            else
                        cur_anim->m_is_loop = FALSE;

                    
            // process linear information
                    if(((DWORD*) data_ptr)[1] == 0)
                        cur_anim->m_is_linear = FALSE;
                    
            else
                        cur_anim->m_is_linear = TRUE;

                    xfile_data->Unlock();
                }
                
            else if(type == TID_D3DRMFrame && cur_anim != NULL)     // process a frame reference
                {
                    cur_anim->m_frame_name = name;
                    name = NULL;

                    
            // don't enumerate child templates
                    return;
                }

                
            // release name buffer
                delete[] name;

                SIZE_T num_child;
                ID3DXFileData* child_xfile_data = NULL;

                xfile_data->GetChildren(&num_child);

                
            // scan for embeded templates
                for(SIZE_T i = 0; i < num_child; i++)
                {
                    xfile_data->GetChild(i, &child_xfile_data);

                    
            // parse child xfile data
                    _Parse_XFile_Data(child_xfile_data, cur_anim_set, cur_anim);

                    Release_COM(child_xfile_data);
                }
            }

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

                _num_animations = 0;
            }

            //-------------------------------------------------------------------
            // Judge whether animation set has beed loaded.
            //-------------------------------------------------------------------
            BOOL ANIMATION::Is_Loaded()
            {
                
            return (_animation_set != NULL);
            }

            //-------------------------------------------------------------------
            // Map all frames in the animation sets to mesh's frames. 
            //-------------------------------------------------------------------
            BOOL ANIMATION::Map_To_Mesh(MESH* mesh)
            {
                S_ANIMATION_SET*    anim_set;
                S_ANIMATION*        anim;

                
            // make sure there is a mesh to work with
                if(mesh == NULL)
                    
            return FALSE;

                
            // assign links to frames by name

                
            if((anim_set = _animation_set) == NULL)
                    
            return FALSE;

                
            // scan through all animation sets
                while(anim_set != NULL)
                {
                    
            // scan through all animations in current animation set

                    anim = anim_set->m_animation;

                    
            while(anim != NULL)
                    {
                        
            // find the matching frame from mesh
                        anim->m_frame = mesh->Get_Frame(anim->m_frame_name);

                        anim = anim->m_next;
                    }

                    anim_set = anim_set->m_next;
                }

                
            return TRUE;
            }

            //-------------------------------------------------------------------
            // Get number of animations.
            //-------------------------------------------------------------------
            long ANIMATION::Get_Num_Animations()
            {
                
            return _num_animations;
            }

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

            //-------------------------------------------------------------------
            // Set loop flag of all animations in the animation set which match
            // specified name.
            //-------------------------------------------------------------------
            BOOL ANIMATION::Set_Loop(BOOL is_loop, char *name)
            {
                S_ANIMATION_SET* anim_set;

                
            if((anim_set = Get_Animation_Set(name)) == NULL)
                    
            return FALSE;

                S_ANIMATION* anim = anim_set->m_animation;

                
            while(anim != NULL)
                {
                    anim->m_is_loop = is_loop;
                    anim = anim->m_next;
                }

                
            return TRUE;
            }

            //-------------------------------------------------------------------
            // Get time length of animation set which match specified name.
            //-------------------------------------------------------------------
            unsigned long ANIMATION::Get_Time_Length(char* name)
            {
                S_ANIMATION_SET* anim_set;

                
            if((anim_set = Get_Animation_Set(name)) == NULL)
                    
            return 0;

                
            return anim_set->m_time_length;
            }

            對于ANIMATION類,一般只調(diào)用4個常用的函數(shù):Load,F(xiàn)ree,Map_To_Mesh和Set_Loop。要確保動畫類能夠找到需要修改的網(wǎng)格矩陣,有必要將動畫映射到網(wǎng)格。對于Set_Loop函數(shù),要注意name參數(shù),name指出了要設(shè)置重復(fù)循環(huán)的動畫名稱。

            像框架和網(wǎng)格一樣,動畫也能夠在.X文件內(nèi)進(jìn)行命名。這樣就可以將多個動畫打包到.X文件中,并通過名字對它們們進(jìn)行引用。舉例來說,如果.X文件包含一個名稱為Walk的動畫集,就能夠?qū)⒆址?Walk"作為name傳遞給Set_Loop函數(shù)。給name指定一個NULL值就指定使用鏈表中最上面的動畫。

            其他需要注意的地方就是OBJECT類中的start_time參數(shù),start_time參數(shù)提供了初始參考值,動畫使用此值對動畫進(jìn)行定時。因此,如果動畫基于時間(使用諸如timeGetTime的函數(shù)),就要將StartTime設(shè)置成開始播放動畫的時間。播放動畫時,時間可以是任意的,可以用秒、毫秒、幀等等來表示時間 ,必須選擇并一直使用一個時間度量單位。

            接下來調(diào)用OBJECT::Update_Animation,使用的是所提供時間與start_time之間的差值,這樣就給出了一個清除定時機(jī)構(gòu)的思路(換句話說,準(zhǔn)確的定時是基于0秒的開始播放時間,而不是任意的時間值)。

            我們編寫一段代碼來測試類ANIMATION:

            點(diǎn)擊下載源碼和工程

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


            #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;
                ANIMATION       _animation;    

                DWORD           _last_anim_time;
                BOOL            _is_first_render;

            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, 640, 480, 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);

                
            const char* xfilename = "Walk.x";

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

                
            // load animation
                if(! _animation.Load(xfilename, &_mesh))
                    
            return FALSE;

                
            // play loop
                _animation.Set_Loop(TRUE, NULL);

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

                
            // attach animation to object
                _object.Set_Animation(&_animation, NULL, timeGetTime());   

                _last_anim_time  = timeGetTime();
                _is_first_render = TRUE;

                
            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, 0, 0, 255));

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

                    
            if(timeGetTime() - _last_anim_time > 300 || _is_first_render)
                    {
                        
            // update animation
                        _object.Update_Animation(timeGetTime(), TRUE);

                        
            // update last animation time
                        _last_anim_time = timeGetTime();

                        _is_first_render = FALSE;
                    }        

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

            運(yùn)行截圖:


            posted on 2007-09-15 18:09 lovedday 閱讀(530) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            久久91精品国产91| 亚洲精品午夜国产VA久久成人| 香港aa三级久久三级老师2021国产三级精品三级在 | 午夜精品久久久久久久无码| 久久亚洲精品中文字幕三区| 日韩av无码久久精品免费| 久久成人国产精品免费软件| 欧美日韩精品久久久免费观看| 久久久久综合中文字幕| 久久久久久国产精品无码下载| 久久国产综合精品五月天| 亚洲精品国产成人99久久| 97超级碰碰碰碰久久久久| 精品久久久久一区二区三区 | 久久国产乱子伦精品免费强| 色综合久久88色综合天天| 97久久精品无码一区二区| 99精品久久精品一区二区| 久久综合中文字幕| 久久国产成人午夜aⅴ影院| 综合久久精品色| 久久久久人妻一区精品色| 久久久久综合网久久| 精品欧美一区二区三区久久久| 中文字幕无码久久人妻| 国内精品人妻无码久久久影院| 国产精品久久久久久影院| 97精品伊人久久久大香线蕉| 亚洲&#228;v永久无码精品天堂久久| 无码人妻少妇久久中文字幕| 久久久一本精品99久久精品88| 99久久精品免费国产大片| 久久精品成人欧美大片| 久久久久久久久久久久久久| 久久久久四虎国产精品| 一级做a爰片久久毛片毛片| …久久精品99久久香蕉国产| 久久久久久久综合综合狠狠| 久久人人爽人人爽人人AV| 久久AAAA片一区二区| 国产亚洲精品自在久久|