青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

網格模型高級技術(5)

Direct3D對加載到內存中的網格模型提供了優化功能,通過網格模型優化可以明顯提高三維模型的渲染速度,這對渲染速度要求較高的三維圖形程序和游戲具有非常重要的現實意義。

對于程序員而言,對網格模型進行優化是比較簡單的,只需調用接口ID3DXMesh的方法Optimize(),該函數的聲明如下:

Generates a new mesh with reordered faces and vertices to optimize drawing performance.

HRESULT Optimize(
DWORD Flags,
CONST DWORD * pAdjacencyIn,
DWORD * pAdjacencyOut,
DWORD * pFaceRemap,
LPD3DXBUFFER * ppVertexRemap,
LPD3DXMESH * ppOptMesh
);

Parameters

Flags
[in] Specifies the type of optimization to perform. This parameter can be set to a combination of one or more flags from D3DXMESHOPT and D3DXMESH (except D3DXMESH_32BIT, D3DXMESH_IB_WRITEONLY, and D3DXMESH_WRITEONLY).
pAdjacencyIn
[in] Pointer to an array of three DWORDs per face that specifies the three neighbors for each face in the source mesh. If the edge has no adjacent faces, the value is 0xffffffff. See Remarks.
pAdjacencyOut
[in, out] Pointer to an array of three DWORDs per face that specifies the three neighbors for each face in the optimized mesh. If the edge has no adjacent faces, the value is 0xffffffff.
pFaceRemap
[in, out] An array of DWORDs, one per face, that identifies the original mesh face that corresponds to each face in the optimized mesh. If the value supplied for this argument is NULL, face remap data is not returned.
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.
ppOptMesh
[out] Address of a pointer to an ID3DXMesh interface, representing the optimized mesh.

Return Values

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

Remarks

This method generates a new mesh. Before running Optimize, an application must generate an adjacency buffer by calling ID3DXBaseMesh::GenerateAdjacency. The adjacency buffer contains adjacency data, such as a list of edges and the faces that are adjacent to each other.

This method is very similar to the ID3DXBaseMesh::CloneMesh method, except that it can perform optimization while generating the new clone of the mesh. The output mesh inherits all of the creation parameters of the input mesh.

Direct3D提供了7種網格模型優化方式,由枚舉常量D3DXMESHOPT定義:

Specifies the type of mesh optimization to be performed.

typedef enum D3DXMESHOPT
{
D3DXMESHOPT_COMPACT = 0x01000000,
D3DXMESHOPT_ATTRSORT = 0x02000000,
D3DXMESHOPT_VERTEXCACHE = 0x04000000,
D3DXMESHOPT_STRIPREORDER = 0x08000000,
D3DXMESHOPT_IGNOREVERTS = 0x10000000,
D3DXMESHOPT_DONOTSPLIT = 0x20000000,
D3DXMESHOPT_DEVICEINDEPENDENT = 0x40000000,
} D3DXMESHOPT, *LPD3DXMESHOPT;

Constants

D3DXMESHOPT_COMPACT
Reorders faces to remove unused vertices and faces.
D3DXMESHOPT_ATTRSORT
Reorders faces to optimize for fewer attribute bundle state changes and enhanced ID3DXBaseMesh::DrawSubset performance.
D3DXMESHOPT_VERTEXCACHE
Reorders faces to increase the cache hit rate of vertex caches.
D3DXMESHOPT_STRIPREORDER
Reorders faces to maximize length of adjacent triangles.
D3DXMESHOPT_IGNOREVERTS
Optimize the faces only; do not optimize the vertices.
D3DXMESHOPT_DONOTSPLIT
While attribute sorting, do not split vertices that are shared between attribute groups.
D3DXMESHOPT_DEVICEINDEPENDENT
Affects the vertex cache size. Using this flag specifies a default vertex cache size that works well on legacy hardware.

Remarks

The D3DXMESHOPT_STRIPREORDER and D3DXMESHOPT_VERTEXCACHE optimization flags are mutually exclusive.

The D3DXMESHOPT_SHAREVB flag has been removed from this enumeration. Use D3DXMESH_VB_SHARE instead, in D3DXMESH.

D3DXMESH

Flags used to specify creation options for a mesh.

typedef enum D3DXMESH
{
D3DXMESH_32BIT = 0x001,
D3DXMESH_DONOTCLIP = 0x002,
D3DXMESH_POINTS = 0x004,
D3DXMESH_RTPATCHES = 0x008,
D3DXMESH_NPATCHES = 0x4000,
D3DXMESH_VB_SYSTEMMEM = 0x010,
D3DXMESH_VB_MANAGED = 0x020,
D3DXMESH_VB_WRITEONLY = 0x040,
D3DXMESH_VB_DYNAMIC = 0x080,
D3DXMESH_VB_SOFTWAREPROCESSING = 0x8000,
D3DXMESH_IB_SYSTEMMEM = 0x100,
D3DXMESH_IB_MANAGED = 0x200,
D3DXMESH_IB_WRITEONLY = 0x400,
D3DXMESH_IB_DYNAMIC = 0x800,
D3DXMESH_IB_SOFTWAREPROCESSING = 0x10000,
D3DXMESH_VB_SHARE = 0x1000,
D3DXMESH_USEHWONLY = 0x2000,
D3DXMESH_SYSTEMMEM = 0x110,
D3DXMESH_MANAGED = 0x220,
D3DXMESH_WRITEONLY = 0x440,
D3DXMESH_DYNAMIC = 0x880,
D3DXMESH_SOFTWAREPROCESSING = 0x18000,
} D3DXMESH, *LPD3DXMESH;

Constants

D3DXMESH_32BIT
The mesh has 32-bit indices instead of 16-bit indices. See Remarks.
D3DXMESH_DONOTCLIP
Use the D3DUSAGE_DONOTCLIP usage flag for vertex and index buffers.
D3DXMESH_POINTS
Use the D3DUSAGE_POINTS usage flag for vertex and index buffers.
D3DXMESH_RTPATCHES
Use the D3DUSAGE_RTPATCHES usage flag for vertex and index buffers.
D3DXMESH_NPATCHES
Specifying this flag causes the vertex and index buffer of the mesh to be created with D3DUSAGE_NPATCHES flag. This is required if the mesh object is to be rendered using N-patch enhancement using Direct3D.
D3DXMESH_VB_SYSTEMMEM
Use the D3DPOOL_SYSTEMMEM usage flag for vertex buffers.
D3DXMESH_VB_MANAGED
Use the D3DPOOL_MANAGED usage flag for vertex buffers.
D3DXMESH_VB_WRITEONLY
Use the D3DUSAGE_WRITEONLY usage flag for vertex buffers.
D3DXMESH_VB_DYNAMIC
Use the D3DUSAGE_DYNAMIC usage flag for vertex buffers.
D3DXMESH_VB_SOFTWAREPROCESSING
Use the D3DUSAGE_SOFTWAREPROCESSING usage flag for vertex buffers.
D3DXMESH_IB_SYSTEMMEM
Use the D3DPOOL_SYSTEMMEM usage flag for index buffers.
D3DXMESH_IB_MANAGED
Use the D3DPOOL_MANAGED usage flag for index buffers.
D3DXMESH_IB_WRITEONLY
Use the D3DUSAGE_WRITEONLY usage flag for index buffers.
D3DXMESH_IB_DYNAMIC
Use the D3DUSAGE_DYNAMIC usage flag for index buffers.
D3DXMESH_IB_SOFTWAREPROCESSING
Use the D3DUSAGE_SOFTWAREPROCESSING usage flag for index buffers.
D3DXMESH_VB_SHARE
Forces the cloned meshes to share vertex buffers.
D3DXMESH_USEHWONLY
Use hardware processing only. For mixed-mode device, this flag will cause the system to use hardware (if supported in hardware) or will default to software processing.
D3DXMESH_SYSTEMMEM
Equivalent to specifying both D3DXMESH_VB_SYSTEMMEM and D3DXMESH_IB_SYSTEMMEM.
D3DXMESH_MANAGED
Equivalent to specifying both D3DXMESH_VB_MANAGED and D3DXMESH_IB_MANAGED.
D3DXMESH_WRITEONLY
Equivalent to specifying both D3DXMESH_VB_WRITEONLY and D3DXMESH_IB_WRITEONLY.
D3DXMESH_DYNAMIC
Equivalent to specifying both D3DXMESH_VB_DYNAMIC and D3DXMESH_IB_DYNAMIC.
D3DXMESH_SOFTWAREPROCESSING
Equivalent to specifying both D3DXMESH_VB_SOFTWAREPROCESSING and D3DXMESH_IB_SOFTWAREPROCESSING.

Remarks

A 32-bit mesh (D3DXMESH_32BIT) can theoretically support (2^32)-1 faces and vertices. However, allocating memory for a mesh that large on a 32-bit operating system is not practical.

因為調用ID3DXMesh::Optimize()函數對網格模型進行優化時,需要用到網格模型中每個面的三個鄰接信息,該信息在加載網格模型時得到:

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

接著我們以三種方式對原始網格模型進行了優化:

DWORD* adj_in = (DWORD*) g_adj_buffer->GetBufferPointer();
V_RETURN(g_mesh->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
&g_mesh_attr_sort));
V_RETURN(g_mesh->Optimize(D3DXMESHOPT_STRIPREORDER | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
&g_mesh_strip_reorder));
V_RETURN(g_mesh->Optimize(D3DXMESHOPT_VERTEXCACHE | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
&g_mesh_vertex_cache));

渲染優化后的網格模型與未優化的網格模型相比沒有任何區別:

// 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]);
		switch(g_render_flag)
{
case OPT_NONE:
g_mesh->DrawSubset(i);
break;
		case OPT_ATTR_SORT:
g_mesh_attr_sort->DrawSubset(i);
break;
		case OPT_STRIP_REORDER:
g_mesh_strip_reorder->DrawSubset(i);
break;
		case OPT_VERTEX_CACHE:
g_mesh_vertex_cache->DrawSubset(i);
break;
}
}
	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 OPT_NONE                0
#define OPT_ATTR_SORT            1
#define OPT_STRIP_REORDER        2
#define OPT_VERTEX_CACHE        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 = true;

CDXUTDialogResourceManager    g_dlg_resource_manager;
CD3DSettingsDlg                g_settings_dlg;
CDXUTDialog                    g_button_dlg;

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

ID3DXMesh
*                    g_mesh_attr_sort;
ID3DXMesh
*                    g_mesh_strip_reorder;
ID3DXMesh
*                    g_mesh_vertex_cache;
WCHAR                        g_opt_info[
256];
int                            g_render_flag = OPT_NONE;

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

    IDirect3D9
* pD3D = DXUTGetD3DObject(); 

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

    
return true;
}


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

    
static bool is_first_time = true;

    
if(is_first_time)
    {
        is_first_time 
= false;

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

    
return true;
}

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

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

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


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

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

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

    ID3DXBuffer
* material_buffer;

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

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

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

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

        g_mesh_textures[i] 
= NULL;

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

    lstrcpy(g_opt_info, L
"optimize method: none");

    DWORD
* adj_in = (DWORD*) g_adj_buffer->GetBufferPointer();

    V_RETURN(g_mesh
->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
                     
&g_mesh_attr_sort));

    V_RETURN(g_mesh
->Optimize(D3DXMESHOPT_STRIPREORDER | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
                     
&g_mesh_strip_reorder));
        
    V_RETURN(g_mesh
->Optimize(D3DXMESHOPT_VERTEXCACHE | D3DXMESH_MANAGED, adj_in, NULL, NULL, NULL,
                     
&g_mesh_vertex_cache));

    
return S_OK;
}


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

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

    
// set dialog position and size

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

    
// setup view matrix

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

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

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

    pd3dDevice
->SetRenderState(D3DRS_AMBIENT, 0xFFFFFFFF);

    
return S_OK;
}

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

    release_com(g_text_sprite);
}


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

    delete[] g_mesh_materials;
    g_mesh_materials 
= NULL;

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

        delete[] g_mesh_textures;
        g_mesh_textures 
= NULL;
    }

    release_com(g_font);
    release_com(g_adj_buffer);
    release_com(g_mesh);
    release_com(g_mesh_attr_sort);
    release_com(g_mesh_strip_reorder);
    release_com(g_mesh_vertex_cache);
}

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

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

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

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

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

    
// show other simple information
    text_helper.SetForegroundColor( D3DXCOLOR(1.0f1.0f1.0f1.0f) );
    text_helper.DrawTextLine(g_opt_info);

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

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

        text_helper.SetInsertionPos(
40, surface_desc->Height - 15 * 3);
        text_helper.DrawTextLine(L
"0, 1, 2, 3: switch optimize method");
    }
    
else
    {
        text_helper.SetInsertionPos(
10, surface_desc->Height - 15 * 4);
        text_helper.SetForegroundColor( D3DXCOLOR(
1.0f1.0f1.0f1.0f) );
        text_helper.DrawTextLine(L
"Press F1 for help");
    }

    text_helper.End();
}

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

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

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

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

            
switch(g_render_flag)
            {
            
case OPT_NONE:
                g_mesh
->DrawSubset(i);
                
break;

            
case OPT_ATTR_SORT:
                g_mesh_attr_sort
->DrawSubset(i);
                
break;

            
case OPT_STRIP_REORDER:
                g_mesh_strip_reorder
->DrawSubset(i);
                
break;

            
case OPT_VERTEX_CACHE:
                g_mesh_vertex_cache
->DrawSubset(i);
                
break;
            }
        }        

        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;

        
case 48:    // press key "0"
            g_render_flag = OPT_NONE;
            lstrcpy(g_opt_info, L
"optimize method: none");
            
break;

        
case 49:    // press key "1"
            g_render_flag = OPT_ATTR_SORT;
            lstrcpy(g_opt_info, L
"optimize method: D3DXMESHOPT_ATTRSORT");
            
break;

        
case 50:    // press key "2"
            g_render_flag = OPT_STRIP_REORDER;
            lstrcpy(g_opt_info, L
"optimize method: D3DXMESHOPT_STRIPREORDER");
            
break;

        
case 51:    // press key "3"
            g_render_flag = OPT_VERTEX_CACHE;
            lstrcpy(g_opt_info, L
"optimize method: D3DXMESHOPT_VERTEXCACHE");
            
break;
        }
    }
}

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

    
case IDC_TOGGLE_REF:
        DXUTToggleREF();
        
break;

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

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

    
// Start the render loop
    DXUTMainLoop();

    
// TODO: Perform any application-level cleanup here

    
return DXUTGetExitCode();
}

 

下載示例工程


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


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产在线精品成人一区二区三区| 久久精品国产99精品国产亚洲性色| 亚洲免费在线| 亚洲人午夜精品| 欧美专区福利在线| 亚洲一区二区三区乱码aⅴ| 久久夜色精品国产| 欧美在线免费看| 国产精品久久久久久久免费软件| 亚洲国产乱码最新视频| 国产一区二区三区四区五区美女| 中文一区二区| 一本色道久久综合亚洲二区三区| 蜜臀av一级做a爰片久久| 欧美亚洲网站| 国产精品爽黄69| 一区二区三区精品视频在线观看| 亚洲免费观看视频| 欧美ed2k| 亚洲欧洲一区二区三区久久| 亚洲精品乱码久久久久久日本蜜臀 | 亚洲理伦在线| 男人的天堂亚洲在线| 裸体丰满少妇做受久久99精品| 国产亚洲精品高潮| 亚洲欧美一区二区原创| 亚欧成人在线| 国内精品免费在线观看| 久久精品国产欧美激情| 久久综合激情| 亚洲高清在线播放| 欧美韩国日本综合| 亚洲精品一区在线观看香蕉| 99伊人成综合| 欧美日韩一级片在线观看| 夜夜嗨一区二区| 亚洲欧美日韩在线综合| 国产日韩精品一区| 久久久久网址| 亚洲欧洲三级电影| 亚洲无线观看| 国产偷国产偷亚洲高清97cao| 欧美一区二区三区的| 久久久中精品2020中文| 亚洲国产精品va在线看黑人| 欧美精品系列| 亚洲午夜一级| 美女任你摸久久| 99精品视频免费观看| 国产精品久久久久久久电影 | 精品二区久久| 女生裸体视频一区二区三区| 亚洲精品一区在线观看| 新狼窝色av性久久久久久| 精品999在线播放| 欧美另类视频在线| 午夜精品久久久久久99热| 欧美国产欧美亚州国产日韩mv天天看完整 | 韩日精品中文字幕| 欧美国产日韩亚洲一区| 亚洲一区二区三区四区五区黄| 久久综合九色九九| 亚洲美女视频网| 国产日韩欧美中文| 欧美国产精品专区| 欧美一级淫片播放口| 亚洲国产精品一区二区www在线| 亚洲视频www| 好看的日韩视频| 国产精品www色诱视频| 久久国产日韩欧美| 中日韩男男gay无套| 欧美成人一区二区| 午夜精品久久久久久久99黑人| 一区二区亚洲欧洲国产日韩| 欧美三级网址| 免费成人av在线| 久久成人这里只有精品| 亚洲三级毛片| 欧美大胆a视频| 久久免费高清视频| 亚洲伊人观看| 亚洲乱码视频| 亚洲国产成人久久综合一区| 国产精品视频网站| 欧美人成在线视频| 蜜乳av另类精品一区二区| 午夜精品久久久久久| 日韩午夜在线观看视频| 亚洲丰满少妇videoshd| 久久久综合香蕉尹人综合网| 午夜视频一区二区| 一本一本久久| 99精品欧美一区| 亚洲精品永久免费精品| 亚洲大片在线| 136国产福利精品导航网址| 国产欧美日韩专区发布| 国产精品久久久久久久午夜 | 国产一区二区在线免费观看| 欧美四级在线| 欧美视频不卡中文| 欧美日韩高清在线播放| 欧美经典一区二区三区| 欧美电影免费观看高清| 免费不卡欧美自拍视频| 免费日韩一区二区| 免费永久网站黄欧美| 免费一级欧美在线大片| 美女视频黄 久久| 欧美不卡三区| 欧美日韩国产影院| 欧美日韩ab片| 欧美日韩中文精品| 国产精品久久久| 国产精品一区在线观看| 国产亚洲亚洲| 在线观看日韩国产| 亚洲黄色成人久久久| 亚洲精品乱码久久久久久黑人| 亚洲精选视频在线| 中文一区字幕| 欧美一区二区三区日韩| 久久久久久一区二区| 欧美成人在线影院| 亚洲精品久久久久| 在线亚洲一区观看| 欧美一区二区三区四区高清| 久久久久99| 欧美久久精品午夜青青大伊人| 欧美日韩一区二区欧美激情| 国产精品女同互慰在线看| 国产亚洲一区二区三区| 亚洲国产高清一区二区三区| 日韩视频在线永久播放| 亚洲图片欧美一区| 久久久久久久久久码影片| 欧美激情亚洲自拍| 在线亚洲国产精品网站| 久久精品视频在线观看| 欧美精品一区二区三区视频| 国产乱肥老妇国产一区二| 伊人久久亚洲影院| 亚洲午夜一区二区三区| 久久综合一区二区三区| 日韩亚洲欧美高清| 久久精品国产2020观看福利| 欧美区一区二区三区| 国产精品视频| 日韩视频一区二区三区在线播放免费观看 | 国自产拍偷拍福利精品免费一| 亚洲黄色在线观看| 亚洲欧美99| 欧美激情第六页| 亚洲欧美999| 欧美激情bt| 狠狠色伊人亚洲综合成人| 亚洲色诱最新| 欧美激情一区二区三区| 亚洲欧美国产77777| 欧美精品一区二区三区蜜臀| 国产一区二区三区在线观看免费视频| 日韩午夜av在线| 麻豆亚洲精品| 亚洲欧美国产精品va在线观看| 欧美大片在线观看| 狠狠色狠狠色综合系列| 欧美亚洲一区三区| 亚洲精品一区二区三区四区高清 | 久久伊人亚洲| 国产欧美一区二区视频| 亚洲视频观看| 亚洲人成在线播放| 蜜乳av另类精品一区二区| 国产一区二区三区奇米久涩 | 欧美特黄视频| 亚洲伦理网站| 欧美风情在线观看| 久久久久久久999| 国内揄拍国内精品久久| 午夜精品理论片| 亚洲午夜精品在线| 欧美日韩精品久久| 99在线热播精品免费| 亚洲高清不卡av| 欧美成人在线影院| 91久久亚洲| 亚洲国产天堂久久国产91| 狂野欧美一区| 亚洲精品小视频在线观看| 欧美激情视频网站| 欧美va亚洲va香蕉在线| 亚洲日本欧美在线| 亚洲国产一区二区精品专区| 蜜臀av一级做a爰片久久| 亚洲国产精品小视频| 欧美激情一区二区三区全黄| 免费久久99精品国产自| 亚洲精品欧美激情| 亚洲精品人人|