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

            天行健 君子當自強而不息

            網格模型高級技術(6)

            層次細節網格模型(progress mesh)是一種特殊的網格模型,它的頂點數據以樹狀形式組織,可以隨意增加或降低模型的復雜程度,從而比普通的網格模型具有更大的靈活性,層次細節網格模型對于層次細節場景的渲染非常理想。當模型距離觀察者較遠時可以降低模型的復雜程度,提高渲染速度。而當模型距離觀察者較近時可以使用復雜的模型,從而提高視覺效果。Direct3D用ID3DXPMesh來表示層次細節網格模型對象,而不是ID3DXMesh。

            層次細節網格模型是根據原始普通網格模型生成的,在生成層次細節網格模型之前,首先需要對原始網格模型進行相關處理,包括整理、頂點融合、檢查3個步驟。

            在調用函數D3DXLoadMeshFromX()生成網格模型后,調用Direct3D功能函數D3DXCleanMesh()對初始網格模型進行整理,其聲明如下:

            Cleans a mesh, preparing it for simplification.

            HRESULT D3DXCleanMesh(
            D3DXCLEANTYPE CleanType,
            LPD3DXMESH pMeshIn,
            CONST DWORD * pAdjacencyIn,
            LPD3DXMESH * ppMeshOut,
            DWORD * pAdjacencyOut,
            LPD3DXBUFFER * ppErrorsAndWarnings
            );

            Parameters

            CleanType
            [in] Vertex operations to perform in preparation for mesh cleaning.
            pMeshIn
            [in] Pointer to an ID3DXMesh interface, representing the mesh to be cleaned.
            pAdjacencyIn
            [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the mesh to be cleaned.
            ppMeshOut
            [out] Address of a pointer to an ID3DXMesh interface, representing the returned cleaned mesh. The same mesh is returned that was passed in if no cleaning was necessary.
            pAdjacencyOut
            [out] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the output mesh.
            ppErrorsAndWarnings
            [out] Returns a buffer containing a string of errors and warnings, which explain the problems found in the 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, E_OUTOFMEMORY.

            Remarks

            This function cleans a mesh using the cleaning method and options specified in the CleanType parameter. See the D3DXCLEANTYPE enumeration for a description of the available options.

            枚舉常量D3DXCLEANTYPE的定義如下:

            Defines operations to perform on vertices in preparation for mesh cleaning.

            typedef enum D3DXCLEANTYPE
            {
            D3DXCLEAN_BACKFACING = 1,
            D3DXCLEAN_BOWTIES = 2,
            D3DXCLEAN_SKINNING = D3DXCLEAN_BACKFACING,
            D3DXCLEAN_OPTIMIZATION = D3DXCLEAN_BACKFACING,
            D3DXCLEAN_SIMPLIFICATION = D3DXCLEAN_BACKFACING | D3DXCLEAN_BOWTIES,
            } D3DXCLEANTYPE, *LPD3DXCLEANTYPE;

            Constants

            D3DXCLEAN_BACKFACING
            Merge triangles that share the same vertex indices but have face normals pointing in opposite directions (back-facing triangles). Unless the triangles are not split by adding a replicated vertex, mesh adjacency data from the two triangles may conflict.
            D3DXCLEAN_BOWTIES
            If a vertex is the apex of two triangle fans (a bowtie) and mesh operations will affect one of the fans, then split the shared vertex into two new vertices. Bowties can cause problems for operations such as mesh simplification that remove vertices, because removing one vertex affects two distinct sets of triangles.
            D3DXCLEAN_SKINNING
            Use this flag to prevent infinite loops during skinning setup mesh operations.
            D3DXCLEAN_OPTIMIZATION
            Use this flag to prevent infinite loops during mesh optimization operations.
            D3DXCLEAN_SIMPLIFICATION
            Use this flag to prevent infinite loops during mesh simplification operations.

            通常選擇D3DXCLEAN_SIMPLIFICATION,這樣既可以將共享相同頂點且面法向量不在同一方向的三角形進行合并,同時還可以避免在簡化網格的操作中陷入死循環。

            在整理好網格模型后,調用函數D3DXWeldVertices()將網格模型中屬性相同的重復頂點溶合到一起,從而簡化網格模型,其聲明如下:

            Welds together replicated vertices that have equal attributes. This method uses specified epsilon values for equality comparisons.

            HRESULT D3DXWeldVertices(
            LPD3DXMESH pMesh,
            DWORD Flags,
            CONST D3DXWeldEpsilons * pEpsilons,
            CONST DWORD * pAdjacencyIn,
            DWORD * pAdjacencyOut,
            DWORD * pFaceRemap,
            LPD3DXBUFFER * ppVertexRemap
            );

            Parameters

            pMesh
            [in] Pointer to an ID3DXMesh object, the mesh from which to weld vertices.
            Flags
            [in] Combination of one or more flags from D3DXWeldEpsilonsFLAGS.
            pEpsilons
            [in] Pointer to a D3DXWeldEpsilons structure, specifying the epsilon values to be used for this method. Use NULL to initialize all structure members to a default value of 1.0e-6f.
            pAdjacencyIn
            [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the source mesh. If the edge has no adjacent faces, the value is 0xffffffff. If this parameter is set to NULL, ID3DXBaseMesh::GenerateAdjacency will be called to create logical adjacency information.
            pAdjacencyOut
            [in, out] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the optimized mesh. If the edge has no adjacent faces, the value is 0xffffffff.
            pFaceRemap
            [out] An array of DWORDs, one per face, that identifies the original mesh face that corresponds to each face in the welded mesh.
            ppVertexRemap
            [out] Address of a pointer to an ID3DXBuffer interface, which contains a DWORD for each vertex that specifies how the new vertices map to the old vertices. This remap is useful if you need to alter external data based on the new vertex mapping.

            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, E_OUTOFMEMORY.

            Remarks

            This function uses supplied adjacency information to determine the points that are replicated. Vertices are merged based on an epsilon comparison. Vertices with equal position must already have been calculated and represented by point-representative data.

            This function combines logically-welded vertices that have similar components, such as normals or texture coordinates within pEpsilons.

            The following example code calls this function with welding enabled. Vertices are compared using epsilon values for normal vector and vertex position. A pointer is returned to a face remapping array (pFaceRemap).

            TCHAR            strMediaPath[512];       // X-file path 
            LPD3DXBUFFER pAdjacencyBuffer = NULL; // adjacency data buffer
            LPD3DXBUFFER pD3DXMtrlBuffer = NULL; // material buffer
            LPD3DXMESH pMesh = NULL; // mesh object
            DWORD m_dwNumMaterials; // number of materials
            D3DXWELDEPSILONS Epsilons; // structure with epsilon values
            DWORD *pFaceRemap[65536]; // face remapping array
            DWORD i; // internal variable

            // Load the mesh from the specified file
            hr = D3DXLoadMeshFromX ( strMediaPath,
            D3DXMESH_MANAGED,
            m_pd3dDevice,
            &pAdjacencyBuffer,
            &pD3DXMtrlBuffer,
            NULL,
            &m_dwNumMaterials,
            &pMesh ) )

            if( FAILED( hr ) )
            goto End; // Go to error handling

            // Set epsilon values
            Epsilons.Normal = 0.001;
            Epsilons.Position = 0.1;

            // Weld the vertices
            for( i=0; i < 65536; i++ )
            {
            pFaceRemap[i] = 0;
            }

            hr = D3DXWeldVertices ( pMesh,
            D3DXWELDEPSILONS_WELDPARTIALMATCHES,
            &Epsilons,
            (DWORD*)pAdjacencyBuffer->GetBufferPointer(),
            (DWORD*)pAdjacencyBuffer->GetBufferPointer(),
            (DWORD*)pFaceRemap,
            NULL )

            if( FAILED( hr ) )
            goto End; // Go to error handling

            D3DXWeldEpsilonsFLAGS的定義如下:

            Options for welding together vertices.

            typedef enum D3DXWeldEpsilonsFLAGS
            {
            D3DXWeldEpsilons_WELDALL = 1,
            D3DXWeldEpsilons_WELDPARTIALMATCHES = 2,
            D3DXWeldEpsilons_DONOTREMOVEVERTICES = 4,
            D3DXWeldEpsilons_DONOTSPLIT = 8,
            } D3DXWeldEpsilonsFLAGS, *LPD3DXWeldEpsilonsFLAGS;

            Constants

            D3DXWeldEpsilons_WELDALL
            Weld together all vertices that are at the same location. Using this flag avoids an epsilon comparison between vertex components.
            D3DXWeldEpsilons_WELDPARTIALMATCHES
            If a given vertex component is within epsilon, modify partially matched vertices so that both components are identical. If all components are equal, remove one of the vertices.
            D3DXWeldEpsilons_DONOTREMOVEVERTICES
            Instructs the weld to allow only modifications to vertices and not removal. This flag is valid only if D3DXWeldEpsilons_WELDPARTIALMATCHES is set. It is useful to modify vertices to be equal, but not to allow vertices to be removed.
            D3DXWeldEpsilons_DONOTSPLIT
            Instructs the weld not to split vertices that are in separate attribute groups. When the ID3DXMesh::Optimize, ID3DXPMesh::Optimize, or ID3DXPMesh::OptimizeBaseLOD methods are called with the D3DXMESHOPT_ATTRSORT flag, then the D3DXMESHOPT_DONOTSPLIT flag will also be set. Setting this flag can slow down software vertex processing.

            D3DXWeldEpsilons的定義如下:

            Specifies tolerance values for each vertex component when comparing vertices to determine if they are similar enough to be welded together.

            typedef struct D3DXWeldEpsilons {
            FLOAT Position;
            FLOAT BlendWeights;
            FLOAT Normal;
            FLOAT PSize;
            FLOAT Specular;
            FLOAT Diffuse;
            FLOAT Texcoord[8];
            FLOAT Tangent;
            FLOAT Binormal;
            FLOAT Tess Factor;
            } D3DXWeldEpsilons, *LPD3DXWeldEpsilons;

            Members

            Position
            Position
            BlendWeights
            Blend weight
            Normal
            Normal
            PSize
            Point size value
            Specular
            Specular lighting value
            Diffuse
            Diffuse lighting value
            Texcoord
            Eight texture coordinates
            Tangent
            Tangent
            Binormal
            Binormal
            Tess Factor
            Tessellation factor

            Remarks

            The LPD3DXWeldEpsilons type is defined as a pointer to the D3DXWeldEpsilons structure.

            typedef D3DXWELDEPSILONS *LPD3DXWELDEPSILONS;

            對原始網格模型進行整理、簡化之后,還需要檢查處理后的網格模型是否有效,檢查工作由函數D3DXValidMesh()完成,其聲明如下:

            Validates a mesh.

            HRESULT D3DXValidMesh(
            LPD3DXMESH pMeshIn,
            CONST DWORD * pAdjacency,
            LPD3DXBUFFER * ppErrorsAndWarnings
            );

            Parameters

            pMeshIn
            [in] Pointer to an ID3DXMesh interface, representing the mesh to be tested.
            pAdjacency
            [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the mesh to be tested.
            ppErrorsAndWarnings
            [out] Returns a buffer containing a string of errors and warnings, which explain the problems found in the 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: D3DXERR_INVALIDMESH, D3DERR_INVALIDCALL, E_OUTOFMEMORY.

            Remarks

            This method validates the mesh by checking for invalid indices. Error information is available from the debugger output.

            在上面的準備工作完成后,可以調用函數D3DXGeneratePMesh()根據初始網格模型生成層次細節網格模型,其聲明如下:

            Generates a progressive mesh.

            HRESULT D3DXGeneratePMesh(
            LPD3DXMESH pMesh,
            CONST DWORD * pAdjacency,
            CONST D3DXATTRIBUTEWEIGHTS * pVertexAttributeWeights,
            CONST FLOAT * pVertexWeights,
            DWORD MinValue,
            DWORD Options,
            LPD3DXPMESH * ppPMesh
            );

            Parameters

            pMesh
            [in] Pointer to an ID3DXMesh interface, representing the source mesh.
            pAdjacency
            [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the created progressive mesh.
            pVertexAttributeWeights
            [in] Pointer to a D3DXATTRIBUTEWEIGHTS structure, containing the weight for each vertex component. If this parameter is set to NULL, a default structure is used. See Remarks.
            pVertexWeights
            [in] Pointer to an array of vertex weights. If this parameter is set to NULL, all vertex weights are set to 1.0. Note that the higher the vertex weight for a given vertex, the less likely it is to be simplified away.
            MinValue
            [in] Number of vertices or faces, depending on the flag set in the Options parameter, by which to simplify the source mesh.
            Options
            [in] Specifies simplification options for the mesh. One flag from the D3DXMESHSIMP enumeration can be set.
            ppPMesh
            [out] Address of a pointer to an ID3DXPMesh interface, representing the created progressive 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: D3DXERR_CANNOTATTRSORT, D3DERR_INVALIDCALL, E_OUTOFMEMORY.

            Remarks

            This function generates a mesh where the level of detail (LOD) can be adjusted from the current value to the MinValue.

            If the simplification process cannot reduce the mesh to MinValue, the call still succeeds because MinValue is a desired minimum, not an absolute minimum.

            If pVertexAttributeWeights is set to NULL, the following values are assigned to the default D3DXATTRIBUTEWEIGHTS structure.

            D3DXATTRIBUTEWEIGHTS AttributeWeights;

            AttributeWeights.Position = 1.0;
            AttributeWeights.Boundary = 1.0;
            AttributeWeights.Normal = 1.0;
            AttributeWeights.Diffuse = 0.0;
            AttributeWeights.Specular = 0.0;
            AttributeWeights.Tex[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

            This default structure is what most applications should use because it considers only geometric and normal adjustment. Only in special cases will the other member fields need to be modified.

            D3DXMESHSIMP的定義如下:

            Specifies simplification options for a mesh.

            typedef enum D3DXMESHSIMP
            {
            D3DXMESHSIMP_VERTEX = 1,
            D3DXMESHSIMP_FACE = 2,
            } D3DXMESHSIMP, *LPD3DXMESHSIMP;

            Constants

            D3DXMESHSIMP_VERTEX
            The mesh will be simplified by the number of vertices specified in the MinValue parameter.
            D3DXMESHSIMP_FACE
            The mesh will be simplified by the number of faces specified in the MinValue parameter.

            參數MinValue設置的最小頂點數只是一個期望值,實際生成的層次細節網格模型的最小頂點數量可能大于設置的最小頂點數量。

             

            示例程序ProgressMesh的具體實現

            示例程序演示了層次細節網格模型的生成和渲染,其中加載原始網格模型、簡化熔合原始網格并生成層次細節網格模型的代碼如下:

            ID3DXBuffer* material_buffer;
            V_RETURN(D3DXLoadMeshFromXW(L"Dwarf.x", D3DXMESH_MANAGED, pd3dDevice, &g_adj_buffer, &material_buffer, NULL,
            &g_num_materials, &g_mesh));
            D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();
            g_mesh_materials = new D3DMATERIAL9[g_num_materials];
            g_mesh_textures = new IDirect3DTexture9*[g_num_materials];
            for(DWORD i = 0; i < g_num_materials; i++)
            {
            g_mesh_materials[i] = xmaterials[i].MatD3D;
            g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;
            	WCHAR wfilename[256];
            RemovePathFromFileName(xmaterials[i].pTextureFilename, wfilename);
            	g_mesh_textures[i] = NULL;
            	if(xmaterials[i].pTextureFilename != NULL && lstrlen(wfilename) > 0)
            {
            V_RETURN(D3DXCreateTextureFromFileW(pd3dDevice, wfilename, &g_mesh_textures[i]));
            }
            }
            material_buffer->Release();
            ID3DXMesh* cleaned_mesh;
            DWORD* adj = (DWORD*) g_adj_buffer->GetBufferPointer();
            V_RETURN(D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, g_mesh, adj, &cleaned_mesh, adj, NULL));
            release_com(g_mesh);
            g_mesh = cleaned_mesh;
            D3DXWELDEPSILONS weld_epsilons;
            ZeroMemory(&weld_epsilons, sizeof(D3DXWELDEPSILONS));
            V_RETURN(D3DXWeldVertices(g_mesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, &weld_epsilons, adj, adj, NULL, NULL));
            V_RETURN(D3DXValidMesh(g_mesh, adj, NULL));
            V_RETURN(D3DXGeneratePMesh(g_mesh, adj, NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &g_progress_mesh));

             

            運行效果圖:

             

            主程序:

            #include "dxstdafx.h"
            #include 
            "resource.h"

            #pragma warning(disable : 
            4127 4995)

            #define IDC_TOGGLE_FULLSCREEN    1
            #define IDC_TOGGLE_REF            2
            #define IDC_CHANGE_DEVICE        3
            #define IDC_DETAIL                4

            #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

            ID3DXFont
            *                    g_font;
            ID3DXSprite
            *                g_text_sprite;
            bool                        g_show_help = true;

            CDXUTDialogResourceManager    g_dlg_resource_manager;
            CD3DSettingsDlg                g_settings_dlg;
            CDXUTDialog                    g_button_dlg;
            CDXUTDialog                    g_ui_dlg;

            ID3DXMesh
            *                    g_mesh;
            D3DMATERIAL9
            *                g_mesh_materials;
            IDirect3DTexture9
            **            g_mesh_textures;
            DWORD                        g_num_materials;
            ID3DXBuffer
            *                g_adj_buffer;
            ID3DXPMesh
            *                    g_progress_mesh;

            //--------------------------------------------------------------------------------------
            // Rejects any devices that aren't acceptable by returning false
            //--------------------------------------------------------------------------------------
            bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
                                              D3DFORMAT BackBufferFormat, 
            bool bWindowed, void* pUserContext )
            {
                
            // Typically want to skip backbuffer formats that don't support alpha blending

                IDirect3D9
            * pD3D = DXUTGetD3DObject(); 

                
            if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, 
                                D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
                    
            return false;

                
            return true;
            }


            //--------------------------------------------------------------------------------------
            // Before a device is created, modify the device settings as needed.
            //--------------------------------------------------------------------------------------
            bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )
            {
                
            // If video card does not support hardware vertex processing, then uses sofaware vertex processing.
                if((pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0)
                    pDeviceSettings
            ->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

                
            static bool is_first_time = true;

                
            if(is_first_time)
                {
                    is_first_time 
            = false;

                    
            // if using reference device, then pop a warning message box.
                    if(pDeviceSettings->DeviceType == D3DDEVTYPE_REF)
                        DXUTDisplaySwitchingToREFWarning();
                }

                
            return true;
            }

            //--------------------------------------------------------------------------------------
            // Remove path from fullname, and convert filename from multibyte to wchar.
            //--------------------------------------------------------------------------------------
            void RemovePathFromFileName(LPSTR fullname, LPWSTR wfilename)
            {
                WCHAR wbuf[MAX_PATH]  
            = {0};
                MultiByteToWideChar(CP_ACP, 
            0, fullname, -1, wbuf, MAX_PATH);

                LPWSTR w_last_back_slash 
            = wcsrchr(wbuf, '\\');

                
            if(w_last_back_slash)
                    lstrcpy(wfilename, 
            ++w_last_back_slash);
                
            else
                    lstrcpy(wfilename, wbuf);
            }


            //--------------------------------------------------------------------------------------
            // Create any D3DPOOL_MANAGED resources here 
            //--------------------------------------------------------------------------------------
            HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, 
                                             
            const D3DSURFACE_DESC* pBackBufferSurfaceDesc, 
                                             
            void* pUserContext )
            {
                HRESULT    hr;

                V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice));
                V_RETURN(g_settings_dlg.OnCreateDevice(pd3dDevice));

                D3DXCreateFont(pd3dDevice, 
            180, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                               DEFAULT_PITCH 
            | FF_DONTCARE, L"Arial"&g_font);

                ID3DXBuffer
            * material_buffer;

                V_RETURN(D3DXLoadMeshFromXW(L
            "Dwarf.x", D3DXMESH_MANAGED, pd3dDevice, &g_adj_buffer, &material_buffer, NULL,
                                            
            &g_num_materials, &g_mesh));

                D3DXMATERIAL
            * xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();
                g_mesh_materials 
            = new D3DMATERIAL9[g_num_materials];
                g_mesh_textures  
            = new IDirect3DTexture9*[g_num_materials];

                
            for(DWORD i = 0; i < g_num_materials; i++)
                {
                    g_mesh_materials[i] 
            = xmaterials[i].MatD3D;
                    g_mesh_materials[i].Ambient 
            = g_mesh_materials[i].Diffuse;

                    WCHAR wfilename[
            256];
                    RemovePathFromFileName(xmaterials[i].pTextureFilename, wfilename);

                    g_mesh_textures[i] 
            = NULL;

                    
            if(xmaterials[i].pTextureFilename != NULL && lstrlen(wfilename) > 0)
                    {
                        V_RETURN(D3DXCreateTextureFromFileW(pd3dDevice, wfilename, 
            &g_mesh_textures[i]));
                    }
                }
                
                material_buffer
            ->Release();
                
                ID3DXMesh
            * cleaned_mesh;
                DWORD
            * adj = (DWORD*) g_adj_buffer->GetBufferPointer();

                V_RETURN(D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, g_mesh, adj, 
            &cleaned_mesh, adj, NULL));
                release_com(g_mesh);

                g_mesh 
            = cleaned_mesh;

                D3DXWELDEPSILONS weld_epsilons;
                ZeroMemory(
            &weld_epsilons, sizeof(D3DXWELDEPSILONS));
                V_RETURN(D3DXWeldVertices(g_mesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, 
            &weld_epsilons, adj, adj, NULL, NULL));

                V_RETURN(D3DXValidMesh(g_mesh, adj, NULL));
                V_RETURN(D3DXGeneratePMesh(g_mesh, adj, NULL, NULL, 
            1, D3DXMESHSIMP_VERTEX, &g_progress_mesh));

                DWORD min_vertices 
            = g_progress_mesh->GetMinVertices();
                DWORD max_vertices 
            = g_progress_mesh->GetMaxVertices();

                g_ui_dlg.GetSlider(IDC_DETAIL)
            ->SetRange(min_vertices, max_vertices);
                g_ui_dlg.GetSlider(IDC_DETAIL)
            ->SetValue(max_vertices);
                g_progress_mesh
            ->SetNumVertices(max_vertices);

                
            return S_OK;
            }


            //--------------------------------------------------------------------------------------
            // Create any D3DPOOL_DEFAULT resources here 
            //--------------------------------------------------------------------------------------
            HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
                                            
            const D3DSURFACE_DESC* pBackBufferSurfaceDesc, 
                                            
            void* pUserContext )
            {
                HRESULT hr;

                V_RETURN(g_dlg_resource_manager.OnResetDevice());
                V_RETURN(g_settings_dlg.OnResetDevice());
                V_RETURN(g_font
            ->OnResetDevice());
                V_RETURN(D3DXCreateSprite(pd3dDevice, 
            &g_text_sprite));

                
            // set dialog position and size

                g_button_dlg.SetLocation(pBackBufferSurfaceDesc
            ->Width - 1700);
                g_button_dlg.SetSize(
            170170);

                g_ui_dlg.SetLocation(
            0, pBackBufferSurfaceDesc->Height - 60);
                g_ui_dlg.SetSize(pBackBufferSurfaceDesc
            ->Width, 50);
                g_ui_dlg.GetControl(IDC_DETAIL)
            ->SetSize(pBackBufferSurfaceDesc->Width - 2016);

                
            // setup view matrix

                D3DXMATRIX mat_view;
                D3DXVECTOR3 eye(
            0.0f0.0f-4.0f);
                D3DXVECTOR3  at(
            0.0f0.0f,  0.0f);
                D3DXVECTOR3  up(
            0.0f1.0f,  0.0f);

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

                
            // set projection matrix
                D3DXMATRIX mat_proj;
                
            float aspect = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
                D3DXMatrixPerspectiveFovLH(
            &mat_proj, D3DX_PI/4, aspect, 1.0f100.0f);
                pd3dDevice
            ->SetTransform(D3DTS_PROJECTION, &mat_proj);

                pd3dDevice
            ->SetRenderState(D3DRS_AMBIENT, 0xFFFFFFFF);

                
            return S_OK;
            }

            //--------------------------------------------------------------------------------------
            // Release resources created in the OnResetDevice callback here 
            //--------------------------------------------------------------------------------------
            void CALLBACK OnLostDevice( void* pUserContext )
            {
                g_dlg_resource_manager.OnLostDevice();
                g_settings_dlg.OnLostDevice();
                g_font
            ->OnLostDevice();

                release_com(g_text_sprite);
            }


            //--------------------------------------------------------------------------------------
            // Release resources created in the OnCreateDevice callback here
            //--------------------------------------------------------------------------------------
            void CALLBACK OnDestroyDevice( void* pUserContext )
            {
                g_dlg_resource_manager.OnDestroyDevice();
                g_settings_dlg.OnDestroyDevice();        

                delete[] g_mesh_materials;
                g_mesh_materials 
            = NULL;

                
            if(g_mesh_textures)
                {
                    
            for(DWORD i = 0; i < g_num_materials; i++)
                        release_com(g_mesh_textures[i]);

                    delete[] g_mesh_textures;
                    g_mesh_textures 
            = NULL;
                }

                release_com(g_font);
                release_com(g_adj_buffer);
                release_com(g_mesh);
                release_com(g_progress_mesh);    
            }

            //--------------------------------------------------------------------------------------
            // Handle updates to the scene
            //--------------------------------------------------------------------------------------
            void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
            {
                D3DXMATRIX mat_world, mat_translation, mat_rotation;

                D3DXMatrixTranslation(
            &mat_translation, 0-0.7f0);
                D3DXMatrixRotationY(
            &mat_rotation, timeGetTime() / 1000.0f);
                mat_world 
            = mat_translation * mat_rotation;

                pd3dDevice
            ->SetTransform(D3DTS_WORLD, &mat_world);
            }

            //--------------------------------------------------------------------------------------
            // Render the helper information
            //--------------------------------------------------------------------------------------
            void RenderText()
            {
                CDXUTTextHelper text_helper(g_font, g_text_sprite, 
            20);
                
                text_helper.Begin();

                
            // show frame and device states
                text_helper.SetInsertionPos(55);
                text_helper.SetForegroundColor( D3DXCOLOR(
            1.0f0.475f0.0f1.0f) );
                text_helper.DrawTextLine( DXUTGetFrameStats(
            true) );
                text_helper.DrawTextLine( DXUTGetDeviceStats() );

                
            // show other simple information
                text_helper.SetForegroundColor( D3DXCOLOR(1.0f1.0f1.0f1.0f) );
                text_helper.DrawFormattedTextLine(L
            "Vertices Range: %u ~ %u\nCurrent Vertices Number: %u\n",
                                                  g_progress_mesh
            ->GetMinVertices(),
                                                  g_progress_mesh
            ->GetMaxVertices(),
                                                  g_progress_mesh
            ->GetNumVertices());

                
            // show helper information
                
                
            const D3DSURFACE_DESC* surface_desc = DXUTGetBackBufferSurfaceDesc();

                
            if(g_show_help)
                {
                    text_helper.SetInsertionPos(
            10, surface_desc->Height - 15 * 6);
                    text_helper.SetForegroundColor( D3DXCOLOR(
            1.0f0.475f0.0f1.0f) );
                    text_helper.DrawTextLine(L
            "Controls (F1 to hide):");
                    
                    text_helper.SetInsertionPos(
            40, surface_desc->Height - 15 * 4);
                    text_helper.DrawTextLine(L
            "Quit: ESC");
                }
                
            else
                {
                    text_helper.SetInsertionPos(
            10, surface_desc->Height - 15 * 4);
                    text_helper.SetForegroundColor( D3DXCOLOR(
            1.0f1.0f1.0f1.0f) );
                    text_helper.DrawTextLine(L
            "Press F1 for help");
                }

                text_helper.End();
            }

            //--------------------------------------------------------------------------------------
            // Render the scene 
            //--------------------------------------------------------------------------------------
            void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
            {
                HRESULT hr;

                
            if(g_settings_dlg.IsActive())
                {
                    g_settings_dlg.OnRender(fElapsedTime);
                    
            return;
                }

                
            // Clear the render target and the zbuffer 
                V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0000), 1.0f0) );

                
            // Render the scene
                if( SUCCEEDED( pd3dDevice->BeginScene() ) )
                {
                    
            for(DWORD i = 0; i < g_num_materials; i++)
                    {
                        pd3dDevice
            ->SetMaterial(&g_mesh_materials[i]);
                        pd3dDevice
            ->SetTexture(0, g_mesh_textures[i]);
                        g_progress_mesh
            ->DrawSubset(i);
                    }        

                    RenderText();
                    V(g_button_dlg.OnRender(fElapsedTime));
                    V(g_ui_dlg.OnRender(fElapsedTime));

                    V( pd3dDevice
            ->EndScene() );
                }
            }


            //--------------------------------------------------------------------------------------
            // Handle messages to the application 
            //--------------------------------------------------------------------------------------
            LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 
                                      
            bool* pbNoFurtherProcessing, void* pUserContext )
            {
                
            *pbNoFurtherProcessing = g_dlg_resource_manager.MsgProc(hWnd, uMsg, wParam, lParam);
                
            if(*pbNoFurtherProcessing)
                    
            return 0;

                
            if(g_settings_dlg.IsActive())
                {
                    g_settings_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
                    
            return 0;
                }

                
            *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
                
            if(*pbNoFurtherProcessing)
                    
            return 0;

                
            *pbNoFurtherProcessing = g_ui_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
                
            if(*pbNoFurtherProcessing)
                    
            return 0;

                
            return 0;
            }


            //--------------------------------------------------------------------------------------
            // Handle keybaord event
            //--------------------------------------------------------------------------------------
            void CALLBACK OnKeyboardProc(UINT charater, bool is_key_down, bool is_alt_down, void* user_context)
            {
                
            if(is_key_down)
                {
                    
            switch(charater)
                    {
                    
            case VK_F1:
                        g_show_help 
            = !g_show_help;
                        
            break;
                    }
                }
            }

            //--------------------------------------------------------------------------------------
            // Handle events for controls
            //--------------------------------------------------------------------------------------
            void CALLBACK OnGUIEvent(UINT eventint control_id, CDXUTControl* control, void* user_context)
            {
                
            switch(control_id)
                {
                
            case IDC_TOGGLE_FULLSCREEN:
                    DXUTToggleFullScreen();
                    
            break;

                
            case IDC_TOGGLE_REF:
                    DXUTToggleREF();
                    
            break;

                
            case IDC_CHANGE_DEVICE:
                    g_settings_dlg.SetActive(
            true);
                    
            break;

                
            case IDC_DETAIL:
                    g_progress_mesh
            ->SetNumVertices( ((CDXUTSlider*) control)->GetValue() );
                }
            }

            //--------------------------------------------------------------------------------------
            // Initialize dialogs
            //--------------------------------------------------------------------------------------
            void InitDialogs()
            {
                g_settings_dlg.Init(
            &g_dlg_resource_manager);
                g_button_dlg.Init(
            &g_dlg_resource_manager);
                g_ui_dlg.Init(
            &g_dlg_resource_manager);

                g_button_dlg.SetCallback(OnGUIEvent);

                
            int x = 35, y = 10, width = 125, height = 22;

                g_button_dlg.AddButton(IDC_TOGGLE_FULLSCREEN, L
            "Toggle full screen", x, y,         width, height);
                g_button_dlg.AddButton(IDC_TOGGLE_REF,          L
            "Toggle REF (F3)",     x, y += 24, width, height);
                g_button_dlg.AddButton(IDC_CHANGE_DEVICE,      L
            "Change device (F2)", x, y += 24, width, height, VK_F2);

                g_ui_dlg.SetCallback(OnGUIEvent);
                g_ui_dlg.AddSlider(IDC_DETAIL, 
            103620016444);
            }

            //--------------------------------------------------------------------------------------
            // Initialize everything and go into a render loop
            //--------------------------------------------------------------------------------------
            INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
            {
                
            // Enable run-time memory check for debug builds.
            #if defined(DEBUG) | defined(_DEBUG)
                _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF 
            | _CRTDBG_LEAK_CHECK_DF );
            #endif

                
            // Set the callback functions
                DXUTSetCallbackDeviceCreated( OnCreateDevice );
                DXUTSetCallbackDeviceReset( OnResetDevice );
                DXUTSetCallbackDeviceLost( OnLostDevice );
                DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
                DXUTSetCallbackMsgProc( MsgProc );
                DXUTSetCallbackFrameRender( OnFrameRender );
                DXUTSetCallbackFrameMove( OnFrameMove );
                DXUTSetCallbackKeyboard(OnKeyboardProc);
               
                
            // TODO: Perform any application-level initialization here
                InitDialogs();

                
            // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
                DXUTInit( truetruetrue ); // Parse the command line, handle the default hotkeys, and show msgboxes
                DXUTSetCursorSettings( truetrue ); // Show the cursor and clip it when in full screen
                DXUTCreateWindow( L"ProgressMesh" );
                DXUTCreateDevice( D3DADAPTER_DEFAULT, 
            true640480, IsDeviceAcceptable, ModifyDeviceSettings );

                
            // Start the render loop
                DXUTMainLoop();

                
            // TODO: Perform any application-level cleanup here

                
            return DXUTGetExitCode();
            }

             

            下載示例工程(僅包含工程文件和源碼,不包含資源文件,資源請從示例程序OptimizedMesh中提取)


            posted on 2008-05-27 20:16 lovedday 閱讀(2115) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久国产午夜精品一区二区三区| 久久这里只有精品首页| 久久精品国产清自在天天线| 久久精品女人天堂AV麻| 亚洲第一极品精品无码久久| 久久亚洲AV成人无码电影| 久久久国产精品福利免费| 一极黄色视频久久网站| 久久综合香蕉国产蜜臀AV| 久久久久国产一区二区| 伊人色综合久久天天人手人婷 | 精品久久久久久国产三级| 久久精品中文无码资源站| 亚洲精品国产成人99久久| 久久无码中文字幕东京热| 久久久久国产视频电影| 日本久久久久久中文字幕| 久久久久久伊人高潮影院| 久久av免费天堂小草播放| 久久99国产精品99久久| 人妻无码中文久久久久专区| 亚洲国产视频久久| 久久精品无码免费不卡| 久久美女网站免费| 国产婷婷成人久久Av免费高清| 精品久久久久久久久免费影院| 精品免费久久久久国产一区| 东京热TOKYO综合久久精品| 久久久久久九九99精品| 亚洲国产精品无码久久一区二区| 亚洲婷婷国产精品电影人久久| 国产精品亚洲美女久久久| 国产精品一区二区久久精品无码| 久久99精品国产麻豆宅宅| .精品久久久麻豆国产精品| 国产精品对白刺激久久久| 99久久人妻无码精品系列蜜桃| 亚洲国产精品一区二区久久hs| 亚洲中文字幕无码久久精品1| 伊人久久无码中文字幕| 久久久久久久人妻无码中文字幕爆 |