新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 网格模型高级技术(2) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 25197 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 网格模型高级技术(2) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 网格模型高级技术(2)

    层次细节网格模型(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 bufferLPD3DXBUFFER     pD3DXMtrlBuffer  = NULL; // material bufferLPD3DXMESH       pMesh            = NULL; // mesh objectDWORD            m_dwNumMaterials;        // number of materialsD3DXWELDEPSILONS Epsilons;                // structure with epsilon valuesDWORD            *pFaceRemap[65536];      // face remapping arrayDWORD            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));

    运行效果图:

    按此在新窗口浏览图片


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:46:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    主程序:


    #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, 18, 0, 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 - 170, 0);
        g_button_dlg.SetSize(170, 170);

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

        // setup view matrix

        D3DXMATRIX mat_view;
        D3DXVECTOR3 eye(0.0f, 0.0f, -4.0f);
        D3DXVECTOR3  at(0.0f, 0.0f,  0.0f);
        D3DXVECTOR3  up(0.0f, 1.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.0f, 100.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.7f, 0);
        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(5, 5);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 0.475f, 0.0f, 1.0f) );
        text_helper.DrawTextLine( DXUTGetFrameStats(true) );
        text_helper.DrawTextLine( DXUTGetDeviceStats() );

        // show other simple information
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.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.0f, 0.475f, 0.0f, 1.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.0f, 1.0f, 1.0f, 1.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(0, 0, 0, 0), 1.0f, 0) );

        // 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 event, int 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, 10, 36, 200, 16, 4, 4, 4);
    }

    //--------------------------------------------------------------------------------------
    // 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( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
        DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
        DXUTCreateWindow( L"ProgressMesh" );
        DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

        // Start the render loop
        DXUTMainLoop();

        // TODO: Perform any application-level cleanup here

        return DXUTGetExitCode();
    }

    [B][URL=http://www.cppblog.com/Files/changingnow/ProgressMesh.rar]下载示例工程[/URL][/B](仅包含工程文件和源码,不包含资源文件,资源请从示例程序OptimizedMesh中提取)

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:47:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客3
    发贴心情 
    增强网格模型是运行镶嵌技术将原始网格模型的三角形面进行细分,形成更加精细(三角形面更多)的网格模型,这对于逐顶点进行的光照效果会更好。网格模型镶嵌技术主要用在层次细节场景中当模型距离观察者较近时,使模型的显示更精细。

    增强网格模型可以通过对原始网格模型进行镶嵌细分模型得到,Direct3D提供了功能函数D3DXTessellateNPatches()来完成这一工作。该函数根据指定的参数,由显卡的镶嵌器(tessellator)对网格模型中的多边形进行细分,从而使原来的三维物体表面变得更加光滑细致。该函数声明如下:

    Tessellates the given mesh using the N-patch tessellation scheme.

    HRESULT D3DXTessellateNPatches(  LPD3DXMESH pMeshIn,  CONST DWORD * pAdjacencyIn,  FLOAT NumSegs,  BOOL QuadraticInterpNormals,  LPD3DXMESH * ppMeshOut,  LPD3DXBUFFER * ppAdjacencyOut);
    Parameters
    pMeshIn
    [in] Pointer to an ID3DXMesh interface, representing the mesh to tessellate.
    pAdjacencyIn
    [in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the source mesh. This parameter may be NULL.
    NumSegs
    [in] Number of segments per edge to tessellate.
    QuadraticInterpNormals
    [in] Set to TRUE to use quadratic interpolation for normals; set to FALSE for linear interpolation.
    ppMeshOut
    [out] Address of a pointer to an ID3DXMesh interface, representing the returned tessellated mesh.
    ppAdjacencyOut
    [out] Address of a pointer to an ID3DXBuffer interface. If the value of this parameter is not set to NULL, this buffer will contain an array of three DWORDs per face that specify the three neighbors for each face in the output mesh. This parameter may be NULL.
    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 values: D3DERR_INVALIDCALL, D3DXERR_INVALIDDATA, E_OUTOFMEMORY.

    Remarks
    This function tessellates by using the N-patch algorithm.

    在示例程序EnhancedMesh中,生成增强网格模型的代码如下:

    //--------------------------------------------------------------------------------------// Generate enhanced mesh from original mesh//--------------------------------------------------------------------------------------HRESULT GenerateEnhancedMesh(IDirect3DDevice9* device, UINT num_segs){ ID3DXMesh* enhanced_mesh; ID3DXMesh* cloned_mesh; HRESULT  hr;
     // use 32 bit index to avoid vertex indices buffer overflow V_RETURN(g_mesh->CloneMeshFVF(D3DXMESH_MANAGED | D3DXMESH_32BIT, g_mesh->GetFVF(), device, &cloned_mesh));
     V_RETURN(D3DXTessellateNPatches(cloned_mesh, (DWORD*) g_adj_buffer->GetBufferPointer(), (float) num_segs,         FALSE, &enhanced_mesh, NULL));
     release_com(cloned_mesh); release_com(g_enhanced_mesh); // release already used global enhanced mesh
     g_enhanced_mesh = enhanced_mesh;
     return S_OK;}
    在上面的代码中,首先调用函数CloneMeshFVF()在原网格模型基础上进行克隆,这是因为后面将要生成的增强网格模型的顶点和多边形数量相当大,16位索引可能很难满足需求,为了防止意外,使用标志D3DXMESH_32BIT克隆出使用32位索引的新网格模型。接下来调用函数D3DXTessellateNPatches()生成增强网格模型。

    运行效果图:

    按此在新窗口浏览图片

    细分前

    按此在新窗口浏览图片

    每边细分为2

    按此在新窗口浏览图片

    每边细分为10

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:48:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客4
    发贴心情 
    主程序:


    #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_SEGMENT                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;

    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;
    ID3DXMesh*                    g_enhanced_mesh;
    UINT                        g_num_segs = 1;

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

    //--------------------------------------------------------------------------------------
    // Generate enhanced mesh from original mesh
    //--------------------------------------------------------------------------------------
    HRESULT GenerateEnhancedMesh(IDirect3DDevice9* device, UINT num_segs)
    {
        ID3DXMesh*    enhanced_mesh;
        ID3DXMesh*    cloned_mesh;
        HRESULT        hr;

        // use 32 bit index to avoid vertex indices buffer overflow
        V_RETURN(g_mesh->CloneMeshFVF(D3DXMESH_MANAGED | D3DXMESH_32BIT, g_mesh->GetFVF(), device, &cloned_mesh));

        V_RETURN(D3DXTessellateNPatches(cloned_mesh, (DWORD*) g_adj_buffer->GetBufferPointer(), (float) num_segs,
                                        FALSE, &enhanced_mesh, NULL));

        release_com(cloned_mesh);
        release_com(g_enhanced_mesh);    // release already used global enhanced mesh

        g_enhanced_mesh = enhanced_mesh;

        return S_OK;
    }

    //--------------------------------------------------------------------------------------
    // 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, 18, 0, 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"cube.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();

        V_RETURN(GenerateEnhancedMesh(pd3dDevice, g_num_segs));

        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 - 170, 0);
        g_button_dlg.SetSize(170, 170);

        g_ui_dlg.SetLocation(0, pBackBufferSurfaceDesc->Height - 60);
        g_ui_dlg.SetSize(pBackBufferSurfaceDesc->Width, 50);
        g_ui_dlg.GetControl(IDC_SEGMENT)->SetSize(pBackBufferSurfaceDesc->Width - 20, 16);

        // setup view matrix

        D3DXMATRIX mat_view;
        D3DXVECTOR3 eye(0.0f, 0.0f,  6.0f);
        D3DXVECTOR3  at(0.0f, 0.0f,  0.0f);
        D3DXVECTOR3  up(0.0f, 1.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.0f, 100.0f);
        pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

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

    //--------------------------------------------------------------------------------------
    // Handle updates to the scene
    //--------------------------------------------------------------------------------------
    void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
        D3DXMATRIX mat_world;
        float time = timeGetTime() / 1000.0f;
        D3DXMatrixRotationYawPitchRoll(&mat_world, time, time, time);

        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(5, 5);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 0.475f, 0.0f, 1.0f) );
        text_helper.DrawTextLine( DXUTGetFrameStats(true) );
        text_helper.DrawTextLine( DXUTGetDeviceStats() );

        // show other simple information
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f) );
        text_helper.DrawFormattedTextLine(L"Divide every edge of original mesh into part: %d\n", g_num_segs);
        text_helper.DrawFormattedTextLine(L"Enhanced mesh's faces number: %d\n", g_enhanced_mesh->GetNumFaces());
        text_helper.DrawFormattedTextLine(L"Enhanced mesh's vertices number: %d\n", g_enhanced_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.0f, 0.475f, 0.0f, 1.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.0f, 1.0f, 1.0f, 1.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(0, 0, 92, 92), 1.0f, 0) );

        // 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_enhanced_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 event, int 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_SEGMENT:
            g_num_segs = ((CDXUTSlider*) control)->GetValue();
            GenerateEnhancedMesh(DXUTGetD3DDevice(), g_num_segs);
            break;
        }
    }

    //--------------------------------------------------------------------------------------
    // 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_SEGMENT, 10, 36, 150, 24, 1, 10, 1);
    }

    //--------------------------------------------------------------------------------------
    // 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( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
        DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
        DXUTCreateWindow( L"EnhancedMesh" );
        DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

        // Start the render loop
        DXUTMainLoop();

        // TODO: Perform any application-level cleanup here

        return DXUTGetExitCode();
    }

    [B][URL=http://www.cppblog.com/Files/changingnow/EnhancedMesh.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:48:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客5
    发贴心情 
    渐变(tweening)网格模型是Direct3D中实现模型动画最简单的方式和途径,它的原理也非常简单。例如对于场景内的某个网格模型,最初只记录t0时刻和t1时刻该网格模型的状态(即这两个时刻网格模型中所有顶点的位置),对于t0到t1这段时间内的任意时刻t_current,根据该时刻距离t0和t1时刻的远近,实时地分配给这两个网格模型不同的权重,然后按照这两个网格模型中顶点的不同位置和它们各自的权重进行插值,计算出t_current时刻整个网格模型中所有顶点的位置,从而实现动画效果。

    通常将t0时刻的网格模型称为源网格模型,将t1时刻的网格模型称为目标网格模型,将最后拟合得到的网格模型称为结果网格模型。当然初始条件还可以是3个或更多时刻网格模型的状态,再根据时间的推移对这些网格模型进行插值而实时得到当前时刻网格模型的状态。

    事实上,渐变网格模型就是对一系列已知的网格模型进行插值得到最终的网格模型。

    首先,我们需要从.x文件加载源网格模型和目标网格模型:

    V_RETURN(D3DXLoadMeshFromXW(L"source.x", D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, &g_num_materials,        &g_source_mesh));
    V_RETURN(D3DXLoadMeshFromXW(L"target.x", D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, &g_num_materials,        &g_target_mesh));
    由于我们仅对两个网格模型中的顶点位置坐标和法向量进行插值,所以在创建好源网格模型和目标网格模型后,需要按照指定的顶点格式克隆源网格模型、目标网格模型和结果网格模型,使这时的源网格模型、目标网格模型和结果网格模型仅包含顶点位置和法向量:

    ID3DXMesh* cloned_mesh;
    // clone source mesh with specified vertex formatg_source_mesh->CloneMeshFVF(g_source_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &cloned_mesh);release_com(g_source_mesh);g_source_mesh = cloned_mesh;
    // clone target mesh with specified vertex formatg_target_mesh->CloneMeshFVF(g_target_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &cloned_mesh);release_com(g_target_mesh);g_target_mesh = cloned_mesh;
    // clone result mesh with specified vertex format from target meshg_target_mesh->CloneMeshFVF(g_target_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &g_result_mesh);
    g_source_mesh->GetVertexBuffer(&g_source_vb);g_target_mesh->GetVertexBuffer(&g_target_vb);g_result_mesh->GetVertexBuffer(&g_result_vb);

    其中源网格模型的状态如下图所示:

    按此在新窗口浏览图片

    目标网格模型的状态如下图所示:

    按此在新窗口浏览图片

    最后我们根据程序当前运行时间,分别计算源网格模型和目标网格模型的权重,利用计算出的权重对源网格模型和目标网格模型的顶点坐标和法向量进行插值,得到当前时刻的结果网格模型:

    sVertex* source_vertices;sVertex* target_vertices;sVertex* result_vertices;
    g_source_vb->Lock(0, 0, (void**) &source_vertices, 0);g_target_vb->Lock(0, 0, (void**) &target_vertices, 0);g_result_vb->Lock(0, 0, (void**) &result_vertices, 0);
    float time_factor = (float)(timeGetTime() % 2000) / 1000.0f;float scalar   = (time_factor <= 1.0f) ? time_factor : (2.0f - time_factor);
    for(DWORD i = 0; i < g_result_mesh->GetNumVertices(); i++){ result_vertices[i].x = source_vertices[i].x * (1.0f - scalar) + target_vertices[i].x * scalar; result_vertices[i].y = source_vertices[i].y * (1.0f - scalar) + target_vertices[i].y * scalar; result_vertices[i].z = source_vertices[i].z * (1.0f - scalar) + target_vertices[i].z * scalar;
     result_vertices[i].nx = source_vertices[i].nx * (1.0f - scalar) + target_vertices[i].nx * scalar; result_vertices[i].ny = source_vertices[i].ny * (1.0f - scalar) + target_vertices[i].ny * scalar; result_vertices[i].nz = source_vertices[i].nz * (1.0f - scalar) + target_vertices[i].nz * scalar;}
    g_source_vb->Unlock();g_target_vb->Unlock();g_result_vb->Unlock();
    为了让海豚动起来,我们还必须修改世界坐标矩阵:

    // move dolphin around circle
    float kick_freq = float(2.0f * fTime);float phas       = float(fTime) / 3.0f;
    D3DXMATRIX mat_dolphin, mat_trans, mat_rot_y, mat_rot_z;
    D3DXMatrixScaling(&mat_dolphin, 0.01f, 0.01f, 0.01f);D3DXMatrixRotationZ(&mat_rot_z, -cosf(kick_freq) / 6);D3DXMatrixRotationY(&mat_rot_y, phase);D3DXMatrixTranslation(&mat_trans, -5 * sinf(phase), sinf(kick_freq)/2, 10 - 10 * cosf(phase));
    mat_dolphin = mat_dolphin * mat_rot_z * mat_rot_y * mat_trans;;
    pd3dDevice->SetTransform(D3DTS_WORLD, &mat_dolphin);

    运行效果图:

    按此在新窗口浏览图片

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:48:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客6
    发贴心情 
    主程序:


    #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

    struct sVertex
    {
        float x, y, z;
        float nx, ny, nz;
    };

    const DWORD CUSTOM_VERTEX_FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

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

    ID3DXFont*                    g_font;
    ID3DXSprite*                g_text_sprite;
    bool                        g_show_help;

    CDXUTDialogResourceManager    g_dlg_resource_manager;
    CD3DSettingsDlg                g_settings_dlg;
    CDXUTDialog                    g_button_dlg;

    ID3DXMesh*                    g_source_mesh;
    ID3DXMesh*                    g_target_mesh;
    ID3DXMesh*                    g_result_mesh;

    IDirect3DVertexBuffer9*        g_source_vb;
    IDirect3DVertexBuffer9*        g_target_vb;
    IDirect3DVertexBuffer9*        g_result_vb;

    DWORD                        g_num_materials;


    //--------------------------------------------------------------------------------------
    // 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, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                       DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_font);

        V_RETURN(D3DXLoadMeshFromXW(L"source.x", D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, &g_num_materials,
                                    &g_source_mesh));

        V_RETURN(D3DXLoadMeshFromXW(L"target.x", D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, &g_num_materials,
                                    &g_target_mesh));

        ID3DXMesh* cloned_mesh;

        // clone source mesh with specified vertex format
        g_source_mesh->CloneMeshFVF(g_source_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &cloned_mesh);
        release_com(g_source_mesh);
        g_source_mesh = cloned_mesh;

        // clone target mesh with specified vertex format
        g_target_mesh->CloneMeshFVF(g_target_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &cloned_mesh);
        release_com(g_target_mesh);
        g_target_mesh = cloned_mesh;

        // clone result mesh with specified vertex format from target mesh
        g_target_mesh->CloneMeshFVF(g_target_mesh->GetOptions(), CUSTOM_VERTEX_FVF, pd3dDevice, &g_result_mesh);

        g_source_mesh->GetVertexBuffer(&g_source_vb);
        g_target_mesh->GetVertexBuffer(&g_target_vb);
        g_result_mesh->GetVertexBuffer(&g_result_vb);

        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 - 170, 0);
        g_button_dlg.SetSize(170, 170);    

        // setup view matrix

        D3DXMATRIX mat_view;
        D3DXVECTOR3 eye(0.0f, 0.0f,  -8.0f);
        D3DXVECTOR3  at(0.0f, 0.0f,  0.0f);
        D3DXVECTOR3  up(0.0f, 1.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.0f, 100.0f);
        pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

        // setup material

        D3DMATERIAL9 material;
        ZeroMemory(&material, sizeof(D3DMATERIAL9));

        material.Diffuse.r = 0.5f;
        material.Diffuse.g = 0.5f;
        material.Diffuse.b = 0.8f;
        material.Diffuse.a = 1.0f;

        material.Ambient.r = 0.5f;
        material.Ambient.g = 0.5f;
        material.Ambient.b = 0.8f;
        material.Ambient.a = 1.0f;

        pd3dDevice->SetMaterial(&material);

        // setup light

        D3DLIGHT9 light;
        ZeroMemory(&light, sizeof(D3DLIGHT9));

        light.Type       = D3DLIGHT_DIRECTIONAL;

        light.Diffuse.r  = 0.1f;
        light.Diffuse.g  = 0.1f;
        light.Diffuse.b  = 0.3f;
        light.Diffuse.a  = 1.0f;

        light.Ambient.r  = 0.1f;
        light.Ambient.g  = 0.1f;
        light.Ambient.b  = 0.3f;
        light.Ambient.a  = 1.0f;

        D3DXVECTOR3 light_dir = D3DXVECTOR3(-1, -1, 1);
        D3DXVec3Normalize((D3DXVECTOR3*) &light.Direction, &light_dir);
        pd3dDevice->SetLight(0, &light);
        pd3dDevice->LightEnable(0, TRUE);
        pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

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

        release_com(g_font);

        release_com(g_source_mesh);
        release_com(g_target_mesh);    
        release_com(g_result_mesh);    

        release_com(g_source_vb);
        release_com(g_target_vb);
        release_com(g_result_vb);
    }

    //--------------------------------------------------------------------------------------
    // Handle updates to the scene
    //--------------------------------------------------------------------------------------
    void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
    {
        sVertex* source_vertices;
        sVertex* target_vertices;
        sVertex* result_vertices;

        g_source_vb->Lock(0, 0, (void**) &source_vertices, 0);
        g_target_vb->Lock(0, 0, (void**) &target_vertices, 0);
        g_result_vb->Lock(0, 0, (void**) &result_vertices, 0);

        float time_factor = (float)(timeGetTime() % 2000) / 1000.0f;
        float scalar      = (time_factor <= 1.0f) ? time_factor : (2.0f - time_factor);

        for(DWORD i = 0; i < g_result_mesh->GetNumVertices(); i++)
        {
            result_vertices[i].x = source_vertices[i].x * (1.0f - scalar) + target_vertices[i].x * scalar;
            result_vertices[i].y = source_vertices[i].y * (1.0f - scalar) + target_vertices[i].y * scalar;
            result_vertices[i].z = source_vertices[i].z * (1.0f - scalar) + target_vertices[i].z * scalar;

            result_vertices[i].nx = source_vertices[i].nx * (1.0f - scalar) + target_vertices[i].nx * scalar;
            result_vertices[i].ny = source_vertices[i].ny * (1.0f - scalar) + target_vertices[i].ny * scalar;
            result_vertices[i].nz = source_vertices[i].nz * (1.0f - scalar) + target_vertices[i].nz * scalar;
        }

        g_source_vb->Unlock();
        g_target_vb->Unlock();
        g_result_vb->Unlock();

        // move dolphin around circle

        float kick_freq = float(2.0f * fTime);
        float phase        = float(fTime) / 3.0f;

        D3DXMATRIX mat_dolphin, mat_trans, mat_rot_y, mat_rot_z;

        D3DXMatrixScaling(&mat_dolphin, 0.01f, 0.01f, 0.01f);
        D3DXMatrixRotationZ(&mat_rot_z, -cosf(kick_freq) / 6);
        D3DXMatrixRotationY(&mat_rot_y, phase);
        D3DXMatrixTranslation(&mat_trans, -5 * sinf(phase), sinf(kick_freq)/2, 10 - 10 * cosf(phase));

        mat_dolphin = mat_dolphin * mat_rot_z * mat_rot_y * mat_trans;;

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

    //--------------------------------------------------------------------------------------
    // 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(5, 5);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 0.475f, 0.0f, 1.0f) );
        text_helper.DrawTextLine( DXUTGetFrameStats(true) );
        text_helper.DrawTextLine( DXUTGetDeviceStats() );

        // 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.0f, 0.475f, 0.0f, 1.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.0f, 1.0f, 1.0f, 1.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(0, 32, 64, 128), 1.0f, 0) );

        // Render the scene
        if( SUCCEEDED( pd3dDevice->BeginScene() ) )
        {
            for(DWORD i = 0; i < g_num_materials; i++)
                g_result_mesh->DrawSubset(i);

            RenderText();
            V(g_button_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;
        
        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 event, int 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;
        }
    }

    //--------------------------------------------------------------------------------------
    // Initialize dialogs
    //--------------------------------------------------------------------------------------
    void InitDialogs()
    {
        g_settings_dlg.Init(&g_dlg_resource_manager);
        g_button_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);
    }

    //--------------------------------------------------------------------------------------
    // 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( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
        DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
        DXUTCreateWindow( L"Tweening" );
        DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

        // Start the render loop
        DXUTMainLoop();

        // TODO: Perform any application-level cleanup here

        return DXUTGetExitCode();
    }

    [B][URL=http://www.cppblog.com/Files/changingnow/Tweening.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:49:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客7
    发贴心情 
    类CDXUTMesh的详细说明请参阅DXUT源码分析 ---- 类CDXUTMesh

    使用CDXUTMesh进行网格模型的绘制

    首先在OnCreate()函数中创建CDXUTMesh对象:

    g_dxut_mesh = new CDXUTMesh();
    g_dxut_mesh->Create(pd3dDevice, L"airplane.x");

    接着在OnFrameRender()中绘制(先绘制不透明的网格,再绘制半透明的网格):

    // Render the sceneif( SUCCEEDED( pd3dDevice->BeginScene() ) ){      pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
     g_dxut_mesh->Render(pd3dDevice, true, false);
     pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA); pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
     g_dxut_mesh->Render(pd3dDevice, false, true);
     // restore alpha belnd state to disabled pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
     RenderText(); V(g_button_dlg.OnRender(fElapsedTime));
        V( pd3dDevice->EndScene() );}

    示例截图:

    按此在新窗口浏览图片

    主程序:

    #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 release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    ID3DXFont*                    g_font;
    ID3DXSprite*                g_text_sprite;
    bool                        g_show_help;

    CDXUTDialogResourceManager    g_dlg_resource_manager;
    CD3DSettingsDlg                g_settings_dlg;
    CDXUTDialog                    g_button_dlg;

    CDXUTMesh*                    g_dxut_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, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                       DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_font);
        
        g_dxut_mesh = new CDXUTMesh();
        g_dxut_mesh->Create(pd3dDevice, L"airplane.x");

        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 - 170, 0);
        g_button_dlg.SetSize(170, 170);

        // setup view matrix

        D3DXMATRIX mat_view;
        D3DXVECTOR3 eye(0.0f, 10.0f, -20.0f);
        D3DXVECTOR3  at(0.0f, 0.0f,    0.0f);
        D3DXVECTOR3  up(0.0f, 1.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.0f, 100.0f);
        pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

        // setup light
        
        D3DLIGHT9 light;
        ZeroMemory(&light, sizeof(D3DLIGHT9));

        light.Type       = D3DLIGHT_DIRECTIONAL;
        light.Diffuse.r  = 1.0f;
        light.Diffuse.g  = 1.0f;
        light.Diffuse.b  = 1.0f;

        D3DXVECTOR3 light_dir(0.0f, -1.0f, 1.0f);    
        D3DXVec3Normalize((D3DXVECTOR3*) &light.Direction, &light_dir);
        pd3dDevice->SetLight(0, &light);
        pd3dDevice->LightEnable(0, TRUE);
        pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);

        pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00FFFF80);

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

        release_com(g_font);
        SAFE_DELETE(g_dxut_mesh);
    }

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

        D3DXMatrixRotationY(&mat_rot_y, (float)fTime);
        D3DXMatrixTranslation(&mat_trans, 0.0f, 0.0f, 30.0f - 30.0f * cos((float)fTime));

        mat_world =  mat_rot_y * mat_trans;
        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(5, 5);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 0.475f, 0.0f, 1.0f) );
        text_helper.DrawTextLine( DXUTGetFrameStats(true) );
        text_helper.DrawTextLine( DXUTGetDeviceStats() );

        // 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.0f, 0.475f, 0.0f, 1.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.0f, 1.0f, 1.0f, 1.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(0, 64, 16, 16), 1.0f, 0) );

        // Render the scene
        if( SUCCEEDED( pd3dDevice->BeginScene() ) )
        {                    
            pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

            g_dxut_mesh->Render(pd3dDevice, true, false);

            pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
            pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

            g_dxut_mesh->Render(pd3dDevice, false, true);

            // restore alpha belnd state to disabled
            pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

            RenderText();
            V(g_button_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;

        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 event, int 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;
        }
    }

    //--------------------------------------------------------------------------------------
    // Initialize dialogs
    //--------------------------------------------------------------------------------------
    void InitDialogs()
    {
        g_settings_dlg.Init(&g_dlg_resource_manager);
        g_button_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);    
    }

    //--------------------------------------------------------------------------------------
    // 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( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
        DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
        DXUTCreateWindow( L"Use DXUT Mesh Class" );
        DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

        // Start the render loop
        DXUTMainLoop();

        // TODO: Perform any application-level cleanup here

        return DXUTGetExitCode();
    }


    下载示例工程

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/18 9:51:00
     
     秋十三 帅哥哟,离线,有人找我吗?
      
      
      等级:大三(要不要学学XML呢?)
      文章:124
      积分:593
      门派:XML.ORG.CN
      注册:2008/11/12

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给秋十三发送一个短消息 把秋十三加入好友 查看秋十三的个人资料 搜索秋十三在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看秋十三的博客8
    发贴心情 
    好啊
    我收藏了啊
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/1/2 20:01:00
     
     秋十三 帅哥哟,离线,有人找我吗?
      
      
      等级:大三(要不要学学XML呢?)
      文章:124
      积分:593
      门派:XML.ORG.CN
      注册:2008/11/12

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给秋十三发送一个短消息 把秋十三加入好友 查看秋十三的个人资料 搜索秋十三在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看秋十三的博客9
    发贴心情 
    好啊
    我收藏了啊
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/1/2 20:03:00
     
     dungeonsnd 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:1
      积分:54
      门派:XML.ORG.CN
      注册:2009/3/10

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给dungeonsnd发送一个短消息 把dungeonsnd加入好友 查看dungeonsnd的个人资料 搜索dungeonsnd在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看dungeonsnd的博客10
    发贴心情 啥也不说了,眼泪哗哗的,太好了,学习的极好资料。
    太详细的学习网格的资料!~~ 感谢!
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/3/10 17:29:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/26 7:56:25

    本主题贴数10,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    375.000ms