天行健 君子当自强而不息

网格模型高级技术(16)

索引顶点混合

Direct3D通过索引顶点混合,扩展了使用多个混合矩阵对顶点进行混合的支持。在索引顶点混合中,混合矩阵被保存在矩阵调色板(可以看成一个矩阵数组)中,使用矩阵索引来引用特定的混合矩阵。矩阵索引使用8位无符号整数表示,由每个顶点提供,因为Direct3D中限定每个顶点最多受到4个混合矩阵的影响,所以每个顶点最多具有4个矩阵索引,每个顶点的矩阵索引被组合成一个DWORD类型的整数存储和表示。因为每个顶点最多受4个混合矩阵的影响,所以在渲染一个三角形时最多可能需要使用12个混合矩阵,在这种情况下,矩阵调色板中最少需要包含12个混合矩阵。

下图演示了一个顶点使用矩阵索引引用4个混合矩阵,图中的顶点通过矩阵索引引用矩阵调色板中索引为0、2、5、6的混合矩阵:

下图演示了渲染一个三角形时,如何通过矩阵索引引用矩阵调色板中的12个混合矩阵:

在渲染图形时,要想启用索引顶点混合,需要将渲染状态D3DRS_INDEXEDVERTEXBLENDENABLE设置为TRUE,如果启用了索引顶点混合,则在顶点数据中就需要包含矩阵索引数据。如果 将渲染状态D3DRS_INDEXEDVERTEXBLENDENABLE设置为FALSE则禁用索引顶点混合,但是又启用了图形混合功能,这时在顶点数据中就不需要包含矩阵索引数据,每个顶点的矩阵索引默认为0~3。

D3DRS_INDEXEDVERTEXBLENDENABLE
bool value that enables or disables indexed vertex blending. The default value is FALSE. When set to TRUE, indexed vertex blending is enabled. When set to FALSE, indexed vertex blending is disabled. If this render state is enabled, the user must pass matrix indices as a packed DWORDwith every vertex. When the render state is disabled and vertex blending is enabled through the D3DRS_VERTEXBLEND state, it is equivalent to having matrix indices 0, 1, 2, 3 in every vertex.

D3DCAPS结构体的成员变量MaxVertexBlendMatrixIndex表示当前设备对索引顶点混合的支持,如果MaxVertexBlendMatrixIndex的值为0,表示当前硬件设备不支持索引顶点混合。如果MaxVertexBlendMatrixIndex的值不为0,表示混合矩阵的最大索引为MaxVertexBlendMatrixIndex,也就是当前硬件设备支持的矩阵调色 板最大容量为MaxVertexBlendMatrixIndex+1,表示矩阵调色板最大可以容纳MaxVertexBlendMatrixIndex+1个混合矩阵。如果顶点中包含法线信息, 则也需要对法线数据进行混合,这时矩阵调色板中矩阵的最大数量为(MaxVertexBlendMatrixIndex+1)/ 2。如果使用软件顶点处理模式,则矩阵调色板的最大容量为256,不管是否需要对法线向量进行混合。

MaxVertexBlendMatrixIndex
DWORD value that specifies the maximum matrix index that can be indexed into using the per-vertex indices. The number of matrices is MaxVertexBlendMatrixIndex + 1, which is the size of the matrix palette. If normals are present in the vertex data that needs to be blended for lighting, then the number of matrices is half the number specified by this capability flag. If MaxVertexBlendMatrixIndex is set to zero, the driver does not support indexed vertex blending. If this value is not zero then the valid range of indices is zero through MaxVertexBlendMatrixIndex.

A zero value for MaxVertexBlendMatrixIndex indicates that the driver does not support indexed matrices.

When software vertex processing is used, 256 matrices could be used for indexed vertex blending, with or without normal blending.

For a given physical device, this capability may vary across Direct3D devices depending on the parameters supplied to IDirect3D9::CreateDevice.

综合上面图形混合和索引顶点混合的内容,对顶点混合可以总结如下:

(1)不管是否使用索引顶点混合,混合矩阵都是通过索引从矩阵调色板中引用。

(2)如果不使用索引顶点混合,则混合矩阵索引最大为3,而且在顶点数据中不需要包含矩阵索引,矩阵索引默认为0~3。

(3)如果使用索引顶点混合,矩阵索引最大为255,而且在顶点数据中需要指定影响该顶点混合矩阵的索引。

(4)使用图形混合之前,首先需要检查当前设备支持的调色板容量是否满足要求,因为使用软件顶点处理模式时,最大混合矩阵索引为255,肯定能满足要求,所以如果硬件顶点处理模式下矩阵调色板容量不能满足要求,只需简单转换为使用软件顶点处理模式即可。

 

蒙皮骨骼动画跟单纯的骨骼动画相比,只是使用了顶点混合技术,解决单纯的骨骼动画存在的问题。

首先我们需要定义包含顶点混合权重和法线向量的结构体,还需要定义两个混合矩阵:

struct sBlendVertex
{
D3DXVECTOR3 pos;
float blend;
D3DXVECTOR3 normal;
};
#define BLEND_VERTEX_FVF (D3DFVF_XYZB1 | D3DFVF_NORMAL)
CDXUTMesh*	g_dxut_mesh;
D3DXMATRIX g_blend_matrix_1;
D3DXMATRIX g_blend_matrix_2;

因为顶点所有骨骼权重之和是1,所以如果1个顶点受到n块骨骼的影响,那么为顶点指定n-1个权重即可,最后一个权重可以通过1减去n-1个权重之和得到。这里每个顶点只受两个骨骼矩阵的影响,所以在上面的顶点结构中只需提供一个顶点权重即可。

接着在回调函数ModifyDeviceSetttings()中用下列语句检查硬件是否支持索引顶点混合,如果当前硬件不支持索引顶点混合,则使用软件顶点处理模式:

if(pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
pDeviceSettings->BehaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
// if current device does not support vertex blending, use software device.
if(pCaps->MaxVertexBlendMatrices < 1)
pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

接下来在回调函数OnCreateDevice()中从.x文件中加载网格模型,因为该网格模型中并没有包含骨骼权重信息,所以首先调用CDXUTMesh:SetFVF()设置网格模型的顶点灵活格式,然后为该网格模型的每个顶点添加权重:

g_dxut_mesh = new CDXUTMesh();
V_RETURN(g_dxut_mesh->Create(pd3dDevice, L"mslogo.x"));
// add vertex blending weight and normal information
g_dxut_mesh->SetFVF(pd3dDevice, BLEND_VERTEX_FVF);
DWORD num_vertices = g_dxut_mesh->GetMesh()->GetNumVertices();
IDirect3DVertexBuffer9* vertex_buffer;
g_dxut_mesh->GetMesh()->GetVertexBuffer(&vertex_buffer);
sBlendVertex* blend_vertices;
vertex_buffer->Lock(0, 0, (void**)&blend_vertices, 0);
// count min and max x coordinate of all vertices for calculating vertex blending weight
float min_x =  1e10f;
float max_x = -1e10f;
for(DWORD i = 0; i < num_vertices; i++)
{
if(blend_vertices[i].pos.x < min_x)
min_x = blend_vertices[i].pos.x;
	if(blend_vertices[i].pos.x > max_x)
max_x = blend_vertices[i].pos.x;
}
// calculate for all vertices blending weight
for(DWORD i = 0; i < num_vertices; i++)
{
float scale = (blend_vertices[i].pos.x - min_x) / (max_x - min_x);
blend_vertices[i].blend = 1.0f - sinf(scale * D3DX_PI);
}
vertex_buffer->Unlock();
vertex_buffer->Release();

接下来在回调函数中OnFrameMove()中实时构造并设置骨骼变换矩阵:

float scale = (float) fTime;
// calculate blend matrix
D3DXVECTOR3 axis(2 + sinf(scale * 3.1f), 2 + sinf(scale * 3.3f), sinf(scale * 3.5f));
D3DXMatrixIdentity(&g_blend_matrix_1);
D3DXMatrixRotationAxis(&g_blend_matrix_2, &axis, sinf(3 * scale));
// set vertex blend method and blend matrix
pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);
pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(0), &g_blend_matrix_1);
pd3dDevice->SetTransform(D3DTS_WORLDMATRIX(1), &g_blend_matrix_2);

上面代码中的最后三行是相互对应的,缺一不可。首先将渲染状态D3DRS_VERTEXBLEND设置为D3DVBF_1WEIGHTS,渲染状态D3DRS_VERTEXBLEND用来指定进行顶点混合时所使用的矩阵的数目,这里将它设置为D3DVBF_1WEIGHTS,表示用宏D3DTS_WORLDMATRIX(index)设置两个骨骼矩阵进行顶点混合,而且这两个骨骼矩阵的索引号分别是0和1。

因为要进行顶点混合,所以函数SetTransform()将要设置的不再是普通的世界坐标变换矩阵,而是骨骼变换矩阵,所以它的第一个参数应该采用宏D3DTS_WORLDMATRIX(index)的格式,而不像以前一样使用标识符D3DTS_WORLD。宏D3DTS_WORLDMATRIX(index)的定义如下:

#define D3DTS_WORLDMATRIX(index) (D3DTRANSFORMSTATETYPE)(index + 256)

该宏负责将索引号index映射到相应的变换状态下。

在设置好各个骨骼矩阵之后,在回调函数OnFrameRender()中渲染网格模型:

g_dxut_mesh->Render(pd3dDevice);

 

运行截图:

 

主程序:

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

#pragma warning(disable : 
4127 4995)

struct sBlendVertex
{
    D3DXVECTOR3 pos;
    
float        blend;
    D3DXVECTOR3 normal;
};

#define BLEND_VERTEX_FVF (D3DFVF_XYZB1 | D3DFVF_NORMAL)

#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;
D3DXMATRIX                    g_blend_matrix_1;
D3DXMATRIX                    g_blend_matrix_2;

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

    
if(pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
        pDeviceSettings
->BehaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;

    
// if current device does not support vertex blending, use software device.
    if(pCaps->MaxVertexBlendMatrices < 1)
        pDeviceSettings
->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    
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);
    
    g_dxut_mesh 
= new CDXUTMesh();
    V_RETURN(g_dxut_mesh
->Create(pd3dDevice, L"mslogo.x"));

    
// add vertex blending weight and normal information
    g_dxut_mesh->SetFVF(pd3dDevice, BLEND_VERTEX_FVF);
    
    IDirect3DVertexBuffer9
* vertex_buffer;
    g_dxut_mesh
->GetMesh()->GetVertexBuffer(&vertex_buffer);

    sBlendVertex
* blend_vertices;
    vertex_buffer
->Lock(00, (void**)&blend_vertices, 0);

    
// count min and max x coordinate of all vertices for calculating vertex blending weight

    DWORD num_vertices 
= g_dxut_mesh->GetMesh()->GetNumVertices();

    
float min_x =  1e10f;
    
float max_x = -1e10f;    

    
for(DWORD i = 0; i < num_vertices; i++)
    {
        
if(blend_vertices[i].pos.x < min_x)
            min_x 
= blend_vertices[i].pos.x;

        
if(blend_vertices[i].pos.x > max_x)
            max_x 
= blend_vertices[i].pos.x;
    }

    
// calculate for all vertices blending weight
    for(DWORD i = 0; i < num_vertices; i++)
    {
        
float scale = (blend_vertices[i].pos.x - min_x) / (max_x - min_x);
        blend_vertices[i].blend 
= 1.0f - sinf(scale * D3DX_PI);
    }

    vertex_buffer
->Unlock();
    vertex_buffer
->Release();        

    
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,  -10.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);    

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

    material.Ambient.r 
= material.Diffuse.r = 1.0f;
    material.Ambient.g 
= material.Diffuse.g = 1.0f;
    material.Ambient.b 
= material.Diffuse.b = 1.0f;
    material.Ambient.a 
= material.Diffuse.a = 1.0f;

    pd3dDevice
->SetMaterial(&material);

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

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

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

    pd3dDevice
->SetRenderState(D3DRS_AMBIENT, 0x00404040);

    
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 )
{    
    
float scale = (float) fTime;

    
// calculate blend matrix
    D3DXVECTOR3 axis(2 + sinf(scale * 3.1f), 2 + sinf(scale * 3.3f), sinf(scale * 3.5f));
    D3DXMatrixIdentity(
&g_blend_matrix_1);
    D3DXMatrixRotationAxis(
&g_blend_matrix_2, &axis, sinf(3 * scale));

    
// set vertex blend method and blend matrix
    pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_1WEIGHTS);
    pd3dDevice
->SetTransform(D3DTS_WORLDMATRIX(0), &g_blend_matrix_1);
    pd3dDevice
->SetTransform(D3DTS_WORLDMATRIX(1), &g_blend_matrix_2);
}

//--------------------------------------------------------------------------------------
// 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 helper information
    
    
const D3DSURFACE_DESC* surface_desc = DXUTGetBackBufferSurfaceDesc();

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

    text_helper.End();
}

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

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

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

    
// Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {                    
        g_dxut_mesh
->Render(pd3dDevice);
        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 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"Vertex Blend" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, 
true640480, IsDeviceAcceptable, ModifyDeviceSettings );

    
// Start the render loop
    DXUTMainLoop();

    
// TODO: Perform any application-level cleanup here

    
return DXUTGetExitCode();
}

 

下载示例工程


posted on 2008-06-12 10:17 lovedday 阅读(2779) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论