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

            天行健 君子當自強而不息

            Working with skeletal animation(8)

            As shown in Figure 4.5, the SkeletalAnim mesh demonstrates what you learned in this chapter by loading a skinned mesh (the Tiny.x mesh provided in the DirectX SDK samples) and rendering it to the display.

            Figure 4.5: Meet Tiny, Microsoft's woman of skeletal meshes. She is constructed from a single mesh and an underlying hierarchy of invisible bones.

            source added into Direct3D.cpp:

            //-------------------------------------------------------------------------------------------
            // Declare an internal .X file parser class for loading meshes and frames.
            //-------------------------------------------------------------------------------------------
            class cXInternalParser
            {
            public:
                
            // information passed from calling function
                IDirect3DDevice9*        m_device;
                
            const char*                m_texture_path;
                DWORD                    m_new_fvf;
                DWORD                    m_load_flags;

                DWORD                    m_flags;    
            // flags for which data to load: 1 = mesh, 2 = frames, 3 = both.

                
            // hierarchies used during loading
                D3DXMESHCONTAINER_EX*    m_root_mesh_container;
                D3DXFRAME_EX
            *            m_root_frame;

            protected:
                
            void parse_object(ID3DXFileData* xfile_data,
                                  ID3DXFileData
            * parent_xfile_data,
                                  DWORD   depth,
                                  
            void**  data,
                                  
            bool      force_ref);

                
            void parse_child_object(ID3DXFileData* xfile_data, DWORD depth, void** data, bool force_ref);

            public:
                cXInternalParser();
                
            ~cXInternalParser();

                
            bool  parse(const char* filename, void** data);
                
            char* get_name(ID3DXFileData* xfile_data);
            };

            //==============================================================================================
            // Generic .X parser class code
            //==============================================================================================

            cXInternalParser::cXInternalParser()
            {
                ZeroMemory(
            thissizeof(*this));
            }

            cXInternalParser::
            ~cXInternalParser()
            {
                delete m_root_mesh_container;    m_root_mesh_container 
            = NULL;
                delete m_root_frame;            m_root_frame 
            = NULL;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            bool cXInternalParser::parse(const char* filename, void** data)
            {
                
            if(filename == NULL)
                    
            return false;

                ID3DXFile
            * xfile;

                
            if(FAILED(D3DXFileCreate(&xfile)))
                    
            return false;

                
            // register standard templates
                if(FAILED(xfile->RegisterTemplates((LPVOID) D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES)))
                {
                    xfile
            ->Release();
                    
            return false;
                }

                ID3DXFileEnumObject
            * xfile_enum;

                
            if(FAILED(xfile->CreateEnumObject(filename, DXFILELOAD_FROMFILE, &xfile_enum)))
                {
                    xfile
            ->Release();
                    
            return false;
                }

                SIZE_T num_child;
                xfile_enum
            ->GetChildren(&num_child);

                
            // loop through all top-level objects, breaking on errors.
                for(SIZE_T i = 0; i < num_child; i++)
                {
                    ID3DXFileData
            * xfile_data;
                    xfile_enum
            ->GetChild(i, &xfile_data);

                    parse_object(xfile_data, NULL, 
            0, data, false);
                    release_com(xfile_data);
                }

                release_com(xfile_enum);
                release_com(xfile);

                
            return true;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            void cXInternalParser::parse_object(ID3DXFileData* xfile_data, 
                                                ID3DXFileData
            * parent_xfile_data, 
                                                DWORD depth, 
            void** data, bool force_ref)
            {
                GUID type;
                xfile_data
            ->GetType(&type);

                
            // process templates based on their type
                if(type == TID_D3DRMFrame && (m_flags & PARSE_FRAME) && force_ref == false)
                {
                    D3DXFRAME_EX
            * frame = new D3DXFRAME_EX;
                    frame
            ->Name = get_name(xfile_data);

                    
            // link frame into hierarchy
                    if(data == NULL)
                    {
                        
            // link as sibling of root
                        frame->pFrameSibling = m_root_frame;
                        m_root_frame 
            = frame;
                        frame 
            = NULL;

                        data 
            = (void**&m_root_frame;
                    }
                    
            else
                    {
                        
            // link as child of supplied frame
                        D3DXFRAME_EX* frame_ptr        = (D3DXFRAME_EX*)*data;
                        frame
            ->pFrameSibling        = frame_ptr->pFrameFirstChild;
                        frame_ptr
            ->pFrameFirstChild = frame;
                        frame 
            = NULL;

                        data 
            = (void**)&frame_ptr->pFrameFirstChild;
                    }
                }
                
            else if(type == TID_D3DRMFrameTransformMatrix && (m_flags & PARSE_FRAME) && data && force_ref == false)
                {
                    D3DXFRAME_EX
            * frame = (D3DXFRAME_EX*)*data;

                    
            if(frame)
                    {
                        SIZE_T size;
                        
            const void* tran_matrix;

                        xfile_data
            ->Lock(&size, &tran_matrix);

                        frame
            ->TransformationMatrix = *((const D3DXMATRIX*) tran_matrix);
                        frame
            ->mat_original            = frame->TransformationMatrix;

                        xfile_data
            ->Unlock();
                    }
                }
                
            else if(type == TID_D3DRMMesh && (m_flags & PARSE_MESH))    // load a mesh (skinned or regular)
                {
                    
            if(force_ref == false)
                    {
                        D3DXMESHCONTAINER_EX
            * mesh_container;
                        load_mesh(
            &mesh_container, m_device, xfile_data, m_texture_path, m_new_fvf, m_load_flags);

                        
            // link mesh to head of list of meshes0
                        if(mesh_container)
                        {
                            mesh_container
            ->pNextMeshContainer = m_root_mesh_container;
                            m_root_mesh_container 
            = mesh_container;
                            mesh_container 
            = NULL;

                            
            // link mesh to frame if needed
                            if(data)
                            {
                                D3DXFRAME_EX
            * frame = (D3DXFRAME_EX**data;

                                
            if((m_flags & PARSE_FRAME) && frame)
                                    frame
            ->pMeshContainer = m_root_mesh_container;
                            }
                        }
                    }
                    
            else    // referenced, then check if wanting to link to frame.
                    {
                        
            if(data)
                        {
                            D3DXFRAME_EX
            * frame = (D3DXFRAME_EX**data;

                            
            if((m_flags & PARSE_FRAME) && m_root_mesh_container && frame)
                            {
                                
            char* name = get_name(xfile_data);

                                
            if(name)
                                {
                                    frame
            ->pMeshContainer = m_root_mesh_container->find(name);

                                    delete[] name;
                                    name 
            = NULL;
                                }
                            }
                        }
                    }
                }
                
                parse_child_object(xfile_data, depth, data, force_ref);
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            void cXInternalParser::parse_child_object(ID3DXFileData* xfile_data, 
                                                      DWORD depth, 
            void** data, bool force_ref)
            {
                SIZE_T num_child;
                xfile_data
            ->GetChildren(&num_child);

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

                    
            if(child_xfile_data->IsReference())
                        force_ref 
            = true;

                    parse_object(child_xfile_data, xfile_data, depth
            +1, data, force_ref);
                    release_com(child_xfile_data);
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            char* cXInternalParser::get_name(ID3DXFileData* xfile_data)
            {
                
            if(xfile_data == NULL)
                    
            return NULL;

                DWORD size;

                
            if(FAILED(xfile_data->GetName(NULL, &size)))
                    
            return NULL;

                
            char* name = NULL;

                
            if(size > 1)
                {
                    name 
            = new char[size];
                    xfile_data
            ->GetName(name, &size);
                }

                
            return name;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            HRESULT load_mesh(D3DXMESHCONTAINER_EX
            ** ret_mesh_container,
                              D3DXFRAME_EX
            ** ret_frame,
                              IDirect3DDevice9
            * device,
                              
            const char* filename,
                              
            const char* texture_path,
                              DWORD new_fvf,
                              DWORD load_flags)
            {
                
            // error checking
                if(device == NULL || filename == NULL || texture_path == NULL)
                    
            return E_FAIL;

                cXInternalParser parser;

                
            // set parser data
                parser.m_device            = device;
                parser.m_texture_path    
            = texture_path;
                parser.m_new_fvf        
            = new_fvf;
                parser.m_load_flags        
            = load_flags;
                parser.m_flags            
            = ((ret_mesh_container == NULL) ? PARSE_NONE : PARSE_MESH) |
                                          ((ret_frame 
            == NULL) ? PARSE_NONE : PARSE_FRAME);

                
            // clear mesh and frame pointers
                parser.m_root_frame = NULL;
                parser.m_root_mesh_container 
            = NULL;

                
            if(! parser.parse(filename, NULL))
                    
            return E_FAIL;

                
            // Map the matrices to the frames and create an array of bone matrices,
                
            // but only if user passed pointers to receive and the loader found some meshes and frames.
                if(ret_mesh_container && ret_frame && parser.m_root_mesh_container && parser.m_root_frame)
                {
                    
            // scan through all meshes

                    D3DXMESHCONTAINER_EX
            * mesh_container = parser.m_root_mesh_container;

                    
            while(mesh_container)
                    {
                        
            // does this mesh use skinning?
                        if(mesh_container->pSkinInfo)
                        {
                            DWORD num_bones 
            = mesh_container->pSkinInfo->GetNumBones();

                            
            // allocate the matrix pointers and bone matrices
                            mesh_container->frame_combined_matrices = new D3DXMATRIX*[num_bones];
                            mesh_container
            ->bone_trans_matrices        = new D3DXMATRIX[num_bones];

                            
            // match matrix poiners to frames
                            for(DWORD i = 0; i < num_bones; i++)
                            {
                                
            const char* bone_name = mesh_container->pSkinInfo->GetBoneName(i);
                                D3DXFRAME_EX
            * frame   = parser.m_root_frame->find(bone_name);

                                
            // match frame to bone
                                if(frame)
                                    mesh_container
            ->frame_combined_matrices[i] = &frame->mat_combined;
                                
            else
                                    mesh_container
            ->frame_combined_matrices[i] = NULL;
                            }
                        }

                        
            // go to next mesh
                        mesh_container = (D3DXMESHCONTAINER_EX*) mesh_container->pNextMeshContainer;
                    }
                }

                
            if(ret_mesh_container)
                {
                    
            // copy the pointer into passed variables
                    *ret_mesh_container = parser.m_root_mesh_container;
                    parser.m_root_mesh_container 
            = NULL;
                }
                
            else
                {
                    
            // delete list of meshes in case any were not needed.
                    delete parser.m_root_mesh_container;
                    parser.m_root_mesh_container 
            = NULL;
                }

                
            if(ret_frame)
                {
                    
            // assign frame hierarchy pointer
                    *ret_frame = parser.m_root_frame;
                    parser.m_root_frame 
            = NULL;
                }
                
            else
                {
                    
            // delete frame hierarchy in case it was loaded and it was not needed.
                    delete parser.m_root_frame;
                    parser.m_root_frame 
            = NULL;
                }

                
            return S_OK;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            HRESULT update_skin_mesh(D3DXMESHCONTAINER_EX
            * mesh_container)
            {
                
            if(mesh_container == NULL)
                    
            return E_FAIL;

                
            if(mesh_container->MeshData.pMesh == NULL || mesh_container->skin_mesh == NULL || mesh_container->pSkinInfo == NULL)
                    
            return E_FAIL;

                
            if(mesh_container->bone_trans_matrices == NULL || mesh_container->frame_combined_matrices == NULL)
                    
            return E_FAIL;

                
            // copy the bone matrices over (must have been combined before call draw_mesh)
                for(DWORD i = 0; i < mesh_container->pSkinInfo->GetNumBones(); i++)
                {
                    
            // start with bone offset matrix
                    mesh_container->bone_trans_matrices[i] = *(mesh_container->pSkinInfo->GetBoneOffsetMatrix(i));

                    
            // apply frame transformation
                    if(mesh_container->frame_combined_matrices[i])
                        mesh_container
            ->bone_trans_matrices[i] *= (*mesh_container->frame_combined_matrices[i]);
                }

                
            void* src_vertices;
                
            void* dest_vertices;

                mesh_container
            ->MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&src_vertices);
                mesh_container
            ->skin_mesh->LockVertexBuffer(0, (void**)&dest_vertices);

                
            // update the skinned mesh using provided transformations
                mesh_container->pSkinInfo->UpdateSkinnedMesh(mesh_container->bone_trans_matrices, NULL, src_vertices, dest_vertices);

                mesh_container
            ->MeshData.pMesh->UnlockVertexBuffer();
                mesh_container
            ->skin_mesh->UnlockVertexBuffer();    

                
            return S_OK;
            }

             

            WinMain.cpp:

            #include <windows.h>
            #include 
            <d3d9.h>
            #include 
            <d3dx9.h>
            #include 
            "Direct3D.h"

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            D3DXMESHCONTAINER_EX
            *    g_mesh_container;
            D3DXFRAME_EX
            *            g_frame;

            float g_mesh_radius = 0.0f;    // bounding radius of mesh

            const char CLASS_NAME[] = "SkeletalClass";
            const char CAPTION[]    = "Skeletal Demo";

            ////////////////////////////////////////////////////////////////////////////////////////////////

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

            bool do_init(HWND hwnd);
            void do_shutdown();
            void do_frame();


            //////////////////////////////////////////////////////////////////////////////////////////////

            int PASCAL WinMain(HINSTANCE inst, HINSTANCE, LPSTR, int cmd_show)
            {      
                CoInitialize(NULL);    
            // Initialize the COM system

                
            // Create the window class here and register it

                WNDCLASSEX win_class;  

                win_class.cbSize        
            = sizeof(win_class);
                win_class.style         
            = CS_CLASSDC;
                win_class.lpfnWndProc   
            = window_proc;
                win_class.cbClsExtra    
            = 0;
                win_class.cbWndExtra    
            = 0;
                win_class.hInstance     
            = inst;
                win_class.hIcon         
            = LoadIcon(NULL, IDI_APPLICATION);
                win_class.hCursor       
            = LoadCursor(NULL, IDC_ARROW);
                win_class.hbrBackground 
            = NULL;
                win_class.lpszMenuName  
            = NULL;
                win_class.lpszClassName 
            = CLASS_NAME;
                win_class.hIconSm       
            = LoadIcon(NULL, IDI_APPLICATION);

                
            if(!RegisterClassEx(&win_class))
                    
            return -1;

                
            // Create the main window
                HWND hwnd = CreateWindow(CLASS_NAME, CAPTION, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                                         
            00640480, NULL, NULL, inst, NULL);

                
            if(hwnd == NULL)
                    
            return -1;

                ShowWindow(hwnd, cmd_show);
                UpdateWindow(hwnd);

                
            // Call init function and enter message pump
                if(do_init(hwnd)) 
                {
                    MSG msg;    
                    ZeroMemory(
            &msg, sizeof(MSG));

                    
            // Start message pump, waiting for user to exit
                    while(msg.message != WM_QUIT) 
                    {
                        
            if(PeekMessage(&msg, NULL, 00, PM_REMOVE)) 
                        {
                            TranslateMessage(
            &msg);
                            DispatchMessage(
            &msg);
                        }
                        
                        do_frame();    
            // Render a single frame
                    }
                }
              
                do_shutdown();
                UnregisterClass(CLASS_NAME, inst);
                CoUninitialize();

                
            return 0;
            }

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                
            // Only handle window destruction messages
                switch(msg) 
                {
                
            case WM_DESTROY:
                    PostQuitMessage(
            0);
                    
            break;

                
            case WM_KEYDOWN:
                    
            if(wParam == VK_ESCAPE)
                        DestroyWindow(hwnd);

                    
            break;
                }

                
            return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            bool do_init(HWND hwnd)
            {
                init_d3d(
            &g_d3d, &g_device, hwnd, falsefalse);

                
            if(FAILED(load_mesh(&g_mesh_container, &g_frame, g_device, "..\\Data\\tiny.x""..\\Data\\"00)))
                    
            return false;

                
            // get the bounding radius of the object

                g_mesh_radius 
            = 0.0f;

                D3DXMESHCONTAINER_EX
            * mesh_container = g_mesh_container;

                
            while(mesh_container)
                {
                    ID3DXMesh
            * mesh = mesh_container->MeshData.pMesh;

                    
            if(mesh)
                    {
                        
            // lock the vertex buffer, get its radius, and unlock buffer.

                        D3DXVECTOR3
            * vertices;
                        D3DXVECTOR3  center;
                        
            float         radius;

                        mesh
            ->LockVertexBuffer(D3DLOCK_READONLY, (void**)&vertices);

                        D3DXComputeBoundingSphere(vertices, mesh
            ->GetNumVertices(), D3DXGetFVFVertexSize(mesh->GetFVF()),
                                                  
            &center, &radius);
                        
                        mesh
            ->UnlockVertexBuffer();

                        
            // update radius
                        if(radius > g_mesh_radius)
                            g_mesh_radius 
            = radius;
                    }

                    
            // goto next mesh
                    mesh_container = (D3DXMESHCONTAINER_EX*) mesh_container->pNextMeshContainer;
                }

                
            return true;
            }

            void do_shutdown()
            {
                
            // free mesh data
                delete g_mesh_container;    g_mesh_container = NULL;
                delete g_frame;                g_frame 
            = NULL;
                
                
            // release D3D objects
                release_com(g_device);
                release_com(g_d3d);
            }

            void do_frame()
            {
                
            // calculate a view transformation matrix using the mesh's bounding radius to position the viewer

                
            float distance = g_mesh_radius * 3.0f;
                
            float angle       = timeGetTime() / 2000.0f;        

                D3DXMATRIX  mat_view;
                D3DXVECTOR3 eye(cos(angle) 
            * distance, g_mesh_radius, sin(angle) * distance);
                D3DXVECTOR3 at(
            0.0f0.0f0.0f);
                D3DXVECTOR3 up(
            0.0f1.0f0.0f);

                D3DXMatrixLookAtLH(
            &mat_view, &eye, &at, &up);
                g_device
            ->SetTransform(D3DTS_VIEW, &mat_view);

                
            // rebuild the frame hierarchy transformations
                if(g_frame)
                    g_frame
            ->update_hierarchy(NULL);

                
            // rebuild the mesh
                update_skin_mesh(g_mesh_container);

                
            // clear the device and start drawing the scene

                g_device
            ->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0064255), 1.0f0);

                g_device
            ->BeginScene();

                D3DXMATRIX mat_world;
                D3DXMatrixIdentity(
            &mat_world);
                g_device
            ->SetTransform(D3DTS_WORLD, &mat_world);

                draw_mesh(g_mesh_container);

                g_device
            ->EndScene();

                g_device
            ->Present(NULL, NULL, NULL, NULL);
            }

             

            download source file


            posted on 2008-04-23 20:24 lovedday 閱讀(653) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            人妻少妇久久中文字幕 | 久久婷婷激情综合色综合俺也去 | 久久精品国产亚洲av麻豆小说 | 日韩va亚洲va欧美va久久| 欧美噜噜久久久XXX| 色婷婷综合久久久中文字幕| 狠狠色丁香婷婷久久综合五月| 久久精品这里只有精99品| 三级片免费观看久久| 伊人 久久 精品| 日韩精品久久久久久久电影| 亚洲国产精品成人久久蜜臀| 狠狠色丁香婷婷久久综合| 亚洲午夜久久久久久噜噜噜| 久久亚洲精品无码AV红樱桃| 久久久久人妻一区精品色| 狠狠狠色丁香婷婷综合久久五月 | 无码人妻久久久一区二区三区| 99精品久久精品一区二区| 久久精品国产亚洲av影院| 久久久久久久久无码精品亚洲日韩 | 久久九九免费高清视频| 青青草原综合久久大伊人导航| 久久综合久久综合亚洲| 久久亚洲春色中文字幕久久久| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 麻豆精品久久久久久久99蜜桃| 亚洲国产精品久久久天堂| 精品久久久久久久| 蜜桃麻豆www久久国产精品| 一本久久a久久精品vr综合| 精品熟女少妇a∨免费久久| 久久久精品人妻无码专区不卡 | 久久久久国产精品人妻| 久久99国产精一区二区三区| 久久人人爽人爽人人爽av| 99久久精品免费看国产一区二区三区| 成人久久久观看免费毛片| 亚洲国产成人久久综合区| 久久精品国产91久久麻豆自制| 精品伊人久久久|