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

            天行健 君子當自強而不息

            Using the .X File Format(10)

            Loading Meshes with Your .X Parser

            Just as I promised, it's time to check out how to merge the mesh−loading functions into your .X parser class. Since you're going to be accessing the mesh data objects directly, you need to use the D3DXLoadMeshFromXof function to load mesh data. That means you need to parse each data object, and look for Mesh objects as you go. Start by deriving a parser class with which to work.

            class cXMeshParser : public cXParser
            {
            public:
            ID3DXMesh *m_Mesh;
            public:
            cXMeshParser() { m_Mesh = NULL; }
            ~cXMeshParser() { if(m_Mesh) m_Mesh−>Release(); }
            	BOOL ParseObject(IDirectXFileData *pDataObj, 
            IDirectXFileData *pParentDataObj,
            DWORD Depth,
            void **Data,
            BOOL Reference);
            };

            As you can see from the class declaration, I'm only declaring one mesh object. If you want more, you need to create a linked list (or another type of list) to contain the mesh objects. I'll leave that up to you because for now I just want to demonstrate using the D3DXLoadMeshFromXof function.

            Override the ParseObject function, allowing it to scan for Mesh objects.

            BOOL cXMeshParser::ParseObject( 
            IDirectXFileData *pDataObj,
            IDirectXFileData *pParentDataObj,
            DWORD Depth,
            void **Data,
            BOOL Reference)
            {
            // Skip reference objects
            if(Reference == TRUE)
            return TRUE;
            	// Make sure object being parsed is Mesh
            if(*GetObjectGUID(pDataObj) == D3DRM_TIDMesh)
            {
            // It's a mesh, use D3DXLoadMeshFromXof to load it
            ID3DXBuffer *Materials;
            DWORD NumMaterials;
            		D3DXLoadMeshFromXof(pDataObj, 0, pDevice, NULL, &Materials, NULL, &NumMaterials, &m_Mesh);
            		// Finish by processing material information
            		// return FALSE to stop parsing
            return FALSE;
            }
            	// Parse child objects
            return ParseChildObjects(pDataObj,Depth,Data,Reference);
            }

            There you have it! With one quick call, you've loaded a mesh from a Mesh data object! If you think that's cool, I've got something new for you−skinned meshes. Read on to see how to load skinned mesh data from .X files.

             

            Loading Skinned Meshes

            A skinned mesh contains a hierarchy of bones (a skeletal structure) that you can use to deform the mesh to which the bones are attached.

            Loading skinned meshes from .X files is just like loading regular meshes. By enumerating the data objects, you can determine which ones to load skinned mesh data from and put the data into an ID3DXSkinMesh object.

            The surprising thing here is that a skinned mesh's data is contained in the same Mesh objects as a regular mesh! If it's the same data object, how could you possibly know the difference between a skinned mesh and a regular mesh?

            The only way to determine whether a Mesh data object contains skinned mesh data is to use the D3DXLoadSkinMeshFromXof function to load the mesh into an ID3DXSkinMesh object. After the mesh data is loaded, you can query the newly created skinned mesh object to see whether it contains bone information (which is contained in special data objects embedded within the Mesh object). If bone
            information exists, the mesh is skinned. If no bones exist, the mesh is regular and can be converted to an ID3DXMesh object.

            I'm starting to get ahead of myself, so jump back to the whole ID3DXSkinMesh and D3DXLoadSkinMeshFromXof thing.Much like regular meshes, you must instance an ID3DXSkinMesh object.

            ID3DXSkinMesh *SkinMesh = NULL;

            Inside your ParseObject function, you need to change the D3DXLoadSkinMeshFromXof call. Instead of calling D3DXLoadMeshFromXof this time, use D3DXLoadSkinMeshFromXof.

            Loads a skin mesh from a DirectX .x file data object.

            HRESULT D3DXLoadSkinMeshFromXof(
            LPD3DXFILEDATA pxofMesh,
            DWORD Options,
            LPDIRECT3DDEVICE9 pD3DDevice,
            LPD3DXBUFFER * ppAdjacency,
            LPD3DXBUFFER * ppMaterials,
            LPD3DXBUFFER * ppEffectInstances,
            DWORD * pMatOut,
            LPD3DXSKININFO * ppSkinInfo,
            LPD3DXMESH * ppMesh
            );

            Parameters

            pxofMesh
            [in] Pointer to an ID3DXFileData interface, representing the file data object to load.
            Options
            [in] Combination of one or more flags, from the D3DXMESH enumeration, specifying creation options for the mesh.
            pD3DDevice
            [in] Pointer to an IDirect3DDevice9 interface, the device object associated with the mesh.
            ppAdjacency
            [out] Address of a pointer to an ID3DXBuffer interface. When this method returns, this parameter is filled with an array of three DWORDs per face that specify the three neighbors for each face in the mesh.
            ppMaterials
            [out] Address of a pointer to an ID3DXBuffer interface. When the method returns, this parameter is filled with an array of D3DXMATERIAL structures.
            ppEffectInstances
            [out] Pointer to a buffer containing an array of effect instances, one per attribute group in the returned mesh. An effect instance is a particular instance of state information used to initialize an effect. See D3DXEFFECTINSTANCE. For more information about accessing the buffer, see ID3DXBuffer.
            pMatOut
            [out] Pointer to the number of D3DXMATERIAL structures in the ppMaterials array, when the method returns.
            ppSkinInfo
            [out] Address of a pointer to an ID3DXSkinInfo interface, which represents the skinning information.
            ppMesh
            [out] Address of a pointer to an ID3DXMesh interface, which represents the loaded mesh.

            Return Values

            If the function succeeds, the return value is D3D_OK. If the function fails, the return value can be one of the following: D3DERR_INVALIDCALL.

            D3DXERR_INVALIDDATA E_OUTOFMEMORY

            Remarks

            This method takes a pointer to an internal object in the .x file, enabling you to load the frame hierarchy.

            For mesh files that do not contain effect instance information, default effect instances will be generated from the material information in the .x file. A default effect instance will have default values that correspond to the members of the D3DMATERIAL9 structure.

            The default texture name is also filled in, but is handled differently. The name will be Texture0@Name, which corresponds to an effect variable by the name of "Texture0" with an annotation called "Name." This will contain the string file name for the texture.

            I know you've got to be saying that D3DXLoadSkinMeshFromXof looks almost exactly like D3DXLoadMeshFromXof, and you're right! Loading the skinned mesh using D3DXLoadSkinMeshFromXof looks something like this:

            D3DXLoadSkinMeshFromXof(pDataObj, 0, pDevice, NULL, &Materials, NULL, &NumMaterials, &SkinMesh);

            Once you have called D3DXLoadSkinMeshFromXof using a valid Mesh object, you'll have a cool new ID3DXSkinMesh object at your disposal.

             

            ParseMesh Demo

            ParseMesh contains a button (shown in Figure 3.3) that you click to locate and open an .X file.

            Figure 3.3: After locating and opening an .X file, you are shown some vital data on each mesh contained in that file.

            The ParseMesh demo lists information about the meshes it finds in the .X file you opened. This data includes the type of mesh (standard or skinned), the number of vertices, the number of faces, and (when applicable) the number of bones. You can use this handy demo program as an example for your own .X file, to make sure all the meshes contain the proper information.

            Because IDirectXFile interface has been deprecated, I translate this interface into ID3DXFile.

            XParser.h:

            #ifndef X_PARSER_H
            #define X_PARSER_H

            #include 
            <windows.h>
            #include 
            <dxfile.h>

            #pragma warning(disable : 
            4100)

            class cXParser
            {
            protected:
                
            // functions called when parsing begins and ends
                virtual bool begin_parse(void* data)    { return true; }
                
            virtual bool end_parse(void* data)        { return true; }

                
            // function called for every template found
                virtual bool parse_objects(ID3DXFileData* xfile_data,
                                           ID3DXFileData
            * parent_xfile_data,
                                           DWORD  depth,
                                           
            void** data,
                                           
            bool   force_ref)
                {
                    
            return parse_child_objects(xfile_data, depth, data, force_ref);
                }

                
            // function called to enumerate child objects
                bool parse_child_objects(ID3DXFileData* xfile_data,
                                         DWORD depth,
                                         
            void** data,
                                         
            bool   force_ref);

            public:
                
            // function to start parsing an .X file
                bool parse(const char* filename, void** data);

                
            // functions to help retrieve object information
                void  get_object_guid(ID3DXFileData* xfile_data, GUID* type);
                
            char* get_object_name(ID3DXFileData* xfile_data);
                
            };

            #endif


            XParser.cpp:
            #include <d3dx9xof.h>
            #include 
            <rmxfguid.h>
            #include 
            <rmxftmpl.h>
            #include 
            "XParser.h"

            #define release_com(x)    { if(x) { (x)->Release(); (x) = NULL; } }

            bool cXParser::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((LPVOID) filename, DXFILELOAD_FROMFILE, &xfile_enum)))
                {
                    xfile
            ->Release();
                    
            return false;
                }

                
            if(begin_parse(data))
                {
                    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);

                        
            bool parse_result = parse_objects(xfile_data, NULL, 0, data, false);
                        release_com(xfile_data);

                        
            if(parse_result == false)
                            
            break;
                    }    

                    end_parse(data);
                }

                release_com(xfile_enum);
                release_com(xfile);

                
            return true;
            }

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

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

                
            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;
                    
                    
            bool parse_result = parse_objects(child_xfile_data, xfile_data, depth+1, data, force_ref);
                    release_com(child_xfile_data);

                    
            if(parse_result == false)    // parsing failure
                        return false;
                }    

                
            return true;
            }

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

            void cXParser::get_object_guid(ID3DXFileData* xfile_data, GUID* type)
            {
                
            if(xfile_data == NULL)
                    type 
            = NULL;
                
            else
                    xfile_data
            ->GetType(type);  
            }

            char* cXParser::get_object_name(ID3DXFileData* xfile_data)
            {
                
            if(xfile_data == NULL)
                    
            return NULL;

                DWORD size 
            = 0;
                xfile_data
            ->GetName(NULL, &size);    

                
            char* name = NULL;

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

                
            return name;
            }


            WinMain.cpp:
            #include <stdio.h>
            #include 
            <windows.h>
            #include 
            <d3d9.h>
            #include 
            <d3dx9.h>
            #include 
            <rmxfguid.h>
            #include 
            "Direct3D.h"
            #include 
            "XParser.h"
            #include 
            "resource.h"

            #pragma warning(disable : 
            4996)

            extern unsigned char D3DRM_XTEMPLATES[];

            IDirect3D9
            *                g_d3d;
            IDirect3DDevice9
            *        g_device;
            D3DXMESHCONTAINER_EX
            *    g_root_mesh_container;

            const char g_class_name[] = "ParseMeshClass";
            const char g_caption[]      = ".X Mesh Parser 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();

            void add_mesh_to_list(D3DXMESHCONTAINER_EX* mesh_container, HWND list_handle);

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

            class cXMeshParser : public cXParser
            {
            protected:
                D3DXMESHCONTAINER_EX
            * m_root_mesh_container;

            protected:
                
            virtual bool parse_objects(ID3DXFileData* xfile_data,
                                           ID3DXFileData
            * parent_xfile_data,
                                           DWORD  depth,
                                           
            void** data,
                                           
            bool   force_ref)
                {
                    GUID type;
                    get_object_guid(xfile_data, 
            &type);

                    
            // make sure template being parsed is a mesh (non-referenced)
                    if(type == TID_D3DRMMesh && force_ref == false)
                    {
                        D3DXMESHCONTAINER_EX
            * mesh_container;

                        
            if(SUCCEEDED(load_mesh(&mesh_container, g_device, xfile_data, ".\\"00)))
                        {
                            
            if(mesh_container->Name == NULL)
                                mesh_container
            ->Name = strdup("NoNameMesh");

                            mesh_container
            ->pNextMeshContainer = m_root_mesh_container;
                            m_root_mesh_container 
            = mesh_container;
                            mesh_container 
            = NULL;
                        }
                    }

                    
            return parse_child_objects(xfile_data, depth, data, force_ref);
                }

            public:
                
            bool load(const char* filename, D3DXMESHCONTAINER_EX** ret_mesh_container)
                {
                    
            bool rv = false;
                    m_root_mesh_container 
            = NULL;

                    
            if(parse(filename, NULL))
                    {
                        
            *ret_mesh_container = m_root_mesh_container;
                        rv 
            = true;
                    }
                    
            else
                    {
                        
            *ret_mesh_container = NULL;
                    }

                    
            return rv;
                }
            };

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

            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_HREDRAW | CS_VREDRAW;
                win_class.lpfnWndProc   
            = window_proc;
                win_class.cbClsExtra    
            = 0;
                win_class.cbWndExtra    
            = DLGWINDOWEXTRA;
                win_class.hInstance     
            = inst;
                win_class.hIcon         
            = LoadIcon(NULL, IDI_APPLICATION);
                win_class.hCursor       
            = LoadCursor(NULL, IDC_ARROW);
                win_class.hbrBackground 
            = (HBRUSH)(COLOR_BTNFACE + 1);
                win_class.lpszMenuName  
            = NULL;
                win_class.lpszClassName 
            = g_class_name;
                win_class.hIconSm       
            = LoadIcon(NULL, IDI_APPLICATION);

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

                
            // create the dialog box window and show it
                HWND hwnd = CreateDialog(inst, MAKEINTRESOURCE(IDD_MESHVIEW), 0, NULL);

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

                
            // Call init function and enter message pump

                init_d3d(
            &g_d3d, &g_device, hwnd, truefalse);    

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

                release_com(g_device);
                release_com(g_d3d);

                UnregisterClass(g_class_name, inst);
                CoUninitialize();

                
            return 0;
            }

            LRESULT FAR PASCAL window_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
                OPENFILENAME ofn;
                
            char filename[MAX_PATH] = {0};
                
                
            // Only handle window destruction messages
                switch(msg) 
                {
                
            case WM_COMMAND:
                    
            switch(LOWORD(wParam))
                    {
                    
            case IDC_SELECT:
                        ZeroMemory(
            &ofn, sizeof(OPENFILENAME));

                        ofn.lStructSize        
            = sizeof(OPENFILENAME);
                        ofn.nMaxFile        
            = MAX_PATH;
                        ofn.nMaxFileTitle    
            = MAX_PATH;
                        ofn.Flags            
            = OFN_HIDEREADONLY | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT;
                        ofn.hwndOwner        
            = hwnd;
                        ofn.lpstrFile        
            = filename;
                        ofn.lpstrTitle        
            = "Load and Parse .x file";
                        ofn.lpstrFilter        
            = ".X Files (*.x)\0*.x\0All Files (*.*)\0*.*\0\0";
                        ofn.lpstrDefExt        
            = "x";

                        
            if(! GetOpenFileName(&ofn))
                            
            return 0;

                        
            // get rid of last loaded mesh list
                        delete g_root_mesh_container;
                        g_root_mesh_container 
            = NULL;

                        
            // parse .x file and display hierarchy

                        cXMeshParser mesh_parser;

                        
            if(mesh_parser.load(filename, &g_root_mesh_container))
                        {
                            SendMessage(GetDlgItem(hwnd, IDC_MESHLIST), LB_RESETCONTENT, 
            00);
                            add_mesh_to_list(g_root_mesh_container, GetDlgItem(hwnd, IDC_MESHLIST));
                        }

                        
            break;
                    }

                    
            break;
                
                
            case WM_DESTROY:
                    delete g_root_mesh_container;
                    g_root_mesh_container 
            = NULL;
                    PostQuitMessage(
            0);
                    
            break;

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

                    
            break;
                }

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

            void add_mesh_to_list(D3DXMESHCONTAINER_EX* mesh_container, HWND list_handle)
            {
                
            if(mesh_container == NULL)
                    
            return;

                
            // add siblings to list first
                if(mesh_container->pNextMeshContainer)
                    add_mesh_to_list((D3DXMESHCONTAINER_EX
            *) mesh_container->pNextMeshContainer, list_handle);

                
            // build text to add to list

                
            char text[1024];

                
            if(mesh_container->skin_mesh && mesh_container->pSkinInfo)
                {
                    sprintf(text, 
            "%s (SKINNED ) Verts: %lu, Faces: %lu, Bones: %lu",
                        mesh_container
            ->Name, mesh_container->MeshData.pMesh->GetNumVertices(),
                        mesh_container
            ->MeshData.pMesh->GetNumFaces(), mesh_container->pSkinInfo->GetNumBones());
                }
                
            else
                {
                    sprintf(text, 
            "%s (STANDARD) Verts: %lu, Faces: %lu"
                        mesh_container
            ->Name, mesh_container->MeshData.pMesh->GetNumVertices(), 
                        mesh_container
            ->MeshData.pMesh->GetNumFaces());
                }

                SendMessage(list_handle, LB_ADDSTRING, 
            0, (LPARAM) text);
            }
             

            download source file


            posted on 2008-04-18 12:16 lovedday 閱讀(947) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            亚洲伊人久久成综合人影院 | 久久丫忘忧草产品| 久久久久综合国产欧美一区二区| 亚洲国产精品久久66| 少妇久久久久久被弄到高潮| 青青草原精品99久久精品66| 久久99国产精品久久久| 一本大道久久香蕉成人网| 嫩草伊人久久精品少妇AV| 93精91精品国产综合久久香蕉| 一级女性全黄久久生活片免费 | 中文字幕无码久久久| 97精品国产91久久久久久| 久久久久噜噜噜亚洲熟女综合 | 秋霞久久国产精品电影院| 色8激情欧美成人久久综合电| 久久婷婷五月综合色高清| 伊人久久大香线蕉AV一区二区| 久久精品国产影库免费看| 久久AV无码精品人妻糸列| 久久久亚洲精品蜜桃臀| 色综合色天天久久婷婷基地| 久久精品国产99国产精品亚洲| 久久99精品国产麻豆不卡| 久久这里只有精品久久| 久久久噜噜噜www成人网| 久久亚洲日韩看片无码| 亚洲精品乱码久久久久久蜜桃| 国产亚洲美女精品久久久| 国产韩国精品一区二区三区久久 | 精品久久人妻av中文字幕| 国内精品伊人久久久久777| 精品久久人人妻人人做精品 | 久久精品国产亚洲av高清漫画| 久久综合亚洲色一区二区三区| 亚洲国产小视频精品久久久三级| 国产精品免费久久久久影院| 精品乱码久久久久久夜夜嗨| 欧美精品一本久久男人的天堂| 亚洲国产成人久久综合一| 国内精品久久久久久不卡影院|