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

天行健 君子當自強而不息

XFile網(wǎng)格的應(yīng)用(3)


本篇是XFile網(wǎng)格的應(yīng)用(2)的續(xù)篇。

上篇介紹了.X文件網(wǎng)格的渲染方法,如果需要創(chuàng)建自己的網(wǎng)格文件,并將它渲染出來,那么可以考慮創(chuàng)建一個空的網(wǎng)格,然后讀取網(wǎng)格文件內(nèi)容,將頂點,材質(zhì)和紋理數(shù)據(jù)寫入以上的網(wǎng)格相關(guān)緩沖區(qū)中。

創(chuàng)建一個自定義頂點格式的空Mesh網(wǎng)格可由 D3DXCreateMeshFVF來實現(xiàn),來看看它的具體信息說明:

Creates a mesh object using a flexible vertex format (FVF) code.

 HRESULT D3DXCreateMeshFVF( 
DWORD NumFaces ,
DWORD NumVertices ,
DWORD Options ,
DWORD FVF ,
LPDIRECT3DDEVICE9 pD3DDevice ,
LPD3DXMESH * ppMesh
);

Parameters

NumFaces
[in] Number of faces for the mesh. The valid range for this number is greater than 0, and one less than the max DWORD value, typically 232 - 1, because the last index is reserved.
NumVertices
[in] Number of vertices for the mesh. This parameter must be greater than 0.
Options
[in] Combination of one or more flags from the D3DXMESH enumeration, specifying creation options for the mesh.
FVF
[in] Combination of D3DFVF that describes the vertex format for the returned mesh. This function does not support D3DFVF_XYZRHW.
pD3DDevice
[in] Pointer to an IDirect3DDevice9 interface, the device object to be associated with the mesh.
ppMesh
[out] Address of a pointer to an ID3DXMesh interface, representing the created mesh object.

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.


空網(wǎng)格創(chuàng)建出來后,用ID3DXMesh接口的LockVertexBuffer函數(shù)取得頂點緩沖區(qū)的指針,這樣就可以將文件的頂點數(shù)據(jù)寫入已鎖定的緩沖區(qū)內(nèi),最后還要調(diào)用UnlockVertexBuffer來進行解鎖。

來看看 LockVertexBuffer函數(shù)的具體信息說明:

Locks a vertex buffer and obtains a pointer to the vertex buffer memory.

 HRESULT LockVertexBuffer( 
DWORD Flags ,
LPVOID * ppData
);

Parameters

Flags

Combination of zero or more locking flags that describe the type of lock to perform. For this method, the valid flags are:

  • D3DLOCK_DISCARD
  • D3DLOCK_NO_DIRTY_UPDATE
  • D3DLOCK_NOSYSLOCK
  • D3DLOCK_READONLY
  • D3DLOCK_NOOVERWRITE
[in] For a description of the flags, see D3DLOCK.

 

ppData
[out, retval] VOID* pointer to a buffer containing the vertex data.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

When working with vertex buffers, you are allowed to make multiple lock calls; however, you must ensure that the number of lock calls match the number of unlock calls. DrawPrimitive calls will not succeed with any outstanding lock count on any currently set vertex buffer.


來看看參數(shù)Flags可以使用的D3DLOCK的具體定義:

A combination of zero or more locking options that describe the type of lock to perform.

#define Description
D3DLOCK_DISCARD The application discards all memory within the locked region. For vertex and index buffers, the entire buffer will be discarded. This option is only valid when the resource is created with dynamic usage (see D3DUSAGE).
D3DLOCK_DONOTWAIT Allows an application to gain back CPU cycles if the driver cannot lock the surface immediately. If this flag is set and the driver cannot lock the surface immediately, the lock call will return D3DERR_WASSTILLDRAWING. This flag can only be used when locking a surface created using IDirect3DDevice9::CreateOffscreenPlainSurface, IDirect3DDevice9::CreateRenderTarget, or IDirect3DDevice9::CreateDepthStencilSurface. This flag can also be used with a back buffer.
D3DLOCK_NO_DIRTY_UPDATE By default, a lock on a resource adds a dirty region to that resource. This option prevents any changes to the dirty state of the resource. Applications should use this option when they have additional information about the set of regions changed during the lock operation.
D3DLOCK_NOOVERWRITE Indicates that memory that was referred to in a drawing call since the last lock without this flag will not be modified during the lock. This can enable optimizations when the application is appending data to a resource. Specifying this flag enables the driver to return immediately if the resource is in use, otherwise, the driver must finish using the resource before returning from locking.
D3DLOCK_NOSYSLOCK The default behavior of a video memory lock is to reserve a system-wide critical section, guaranteeing that no display mode changes will occur for the duration of the lock. This option causes the system-wide critical section not to be held for the duration of the lock.

The lock operation is time consuming, but can enable the system to perform other duties, such as moving the mouse cursor. This option is useful for long-duration locks, such as the lock of the back buffer for software rendering that would otherwise adversely affect system responsiveness.

D3DLOCK_READONLY The application will not write to the buffer. This enables resources stored in non-native formats to save the recompression step when unlocking.


再來看看UnlockVertexBuffer函數(shù)的具體信息說明:

Unlocks a vertex buffer.

 HRESULT UnlockVertexBuffer(); 

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.


同樣,利用ID3DXMesh接口的LockIndexBuffer和UnlockIndexBuffer函數(shù),可鎖定頂點索引緩沖區(qū),并寫入三角形面的頂點索引值,然后解鎖。

LockIndexBuffer的具體使用信息如下所示:

Locks an index buffer and obtains a pointer to the index buffer memory.

 HRESULT LockIndexBuffer( 
DWORD Flags ,
LPVOID * ppData
);

Parameters

Flags

Combination of zero or more locking flags that describe the type of lock to perform. For this method, the valid flags are:

  • D3DLOCK_DISCARD
  • D3DLOCK_NO_DIRTY_UPDATE
  • D3DLOCK_NOSYSLOCK
  • D3DLOCK_READONLY
[in] For a description of the flags, see D3DLOCK.

 

ppData
[out, retval] VOID* pointer to a buffer containing the index data. The count of indices in this buffer will be equal to ID3DXBaseMesh::GetNumFaces * 3.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

When working with index buffers, you are allowed to make multiple lock calls. However, you must ensure that the number of lock calls match the number of unlock calls. DrawPrimitive calls will not succeed with any outstanding lock count on any currently set index buffer.


該函數(shù)使用信息說明中提到的GetNumFaces用來獲取該網(wǎng)格包含的三角形面數(shù),信息說明如下所示:

Retrieves the number of faces in the mesh.

 DWORD GetNumFaces(); 

Parameters

None.

Return Values

Returns the number of faces in the mesh.


再來看看
UnlockIndexBuffer的使用說明:

Unlocks an index buffer.

 HRESULT UnlockIndexBuffer(); 

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.


接著我們可以利用ID3DXMesh接口的LockAttributeBuffer函數(shù)鎖定屬性緩沖區(qū),并取得緩沖區(qū)的指針,然后將每個三角形面的子集號寫入,最后調(diào)用該接口的UnlockAttributeBuffer函數(shù)將緩沖區(qū)解鎖。

來看看LockAttributeBuffer的使用說明:

Locks the mesh buffer that contains the mesh attribute data, and returns a pointer to it.

 HRESULT LockAttributeBuffer( 
DWORD Flags ,
DWORD ** ppData
);

Parameters

Flags

Combination of zero or more locking flags that describe the type of lock to perform. For this method, the valid flags are:

  • D3DLOCK_DISCARD
  • D3DLOCK_NO_DIRTY_UPDATE
  • D3DLOCK_NOSYSLOCK
  • D3DLOCK_READONLY
[in] For a description of the flags, see D3DLOCK.

 

ppData
[out] Address of a pointer to a buffer containing a DWORD for each face in the mesh.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

If ID3DXMesh::Optimize has been called, the mesh will also have an attribute table that can be accessed using the ID3DXBaseMesh::GetAttributeTable method.


再來看看UnlockAttributeBuffer的使用說明:

Unlocks an attribute buffer.

 HRESULT UnlockAttributeBuffer(); 

Parameters

None.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.


如果網(wǎng)格沒有提供各頂點的法向量坐標數(shù)據(jù),可使用ID3DXMesh接口的CloneMeshFVF函數(shù)復制生成一個包含法向量的網(wǎng)格,然后調(diào)用D3DXComputeNormals計算各頂點的法向量。

來看看CloneMeshFVF的使用說明:

Clones a mesh using a flexible vertex format (FVF) code.

 HRESULT CloneMeshFVF( 
DWORD Options ,
DWORD FVF ,
LPDIRECT3DDEVICE9 pDevice ,
LPD3DXMESH * ppCloneMesh
);

Parameters

Options
[in] A combination of one or more D3DXMESH flags specifying creation options for the mesh.
FVF
[in] Combination of FVF codes, which specifies the vertex format for the vertices in the output mesh. For the values of the codes, see D3DFVF.
pDevice
[in] Pointer to an IDirect3DDevice9 interface representing the device object associated with the mesh.
ppCloneMesh
[out, retval] Address of a pointer to an ID3DXMesh interface, representing the cloned 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

ID3DXBaseMesh::CloneMeshFVF is used to reformat and change the vertex data layout. This is done by creating a new mesh object. For example, use it to to add space for normals, texture coordinates, colors, weights, etc. that were not present before.

ID3DXBaseMesh::UpdateSemantics updates the vertex declaration with different semantic information without changing the layout of the vertex buffer. This method does not modify the contents of the vertex buffer. For example, use it to relabel a 3D texture coordinate as a binormal or tangent or vice versa.


以及D3DXComputeNormals的使用說明:

Computes unit normals for each vertex in a mesh. Provided to support legacy applications. Use D3DXComputeTangentFrameEx for better results.

 HRESULT D3DXComputeNormals( 
LPD3DXBASEMESH pMesh ,
CONST DWORD * pAdjacency
);

Parameters

pMesh
[in, out] Pointer to an ID3DXBaseMesh interface, representing the normalized mesh object. This function may not take an ID3DXPMesh progressive mesh as input.
pAdjacency
[in] Pointer to an array of three DWORDs per face that specify the three neighbors for each face in the created progressive mesh. This parameter is optional and should be set to NULL if it is unused.

Return Values

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

Remarks

The input mesh must have the D3DFVF_NORMAL flag specified in its flexible vertex format (FVF).

A normal for a vertex is generated by averaging the normals of all faces that share that vertex.

If adjacency is provided, replicated vertices are ignored and "smoothed" over. If adjacency is not provided, replicated vertices will have normals averaged in from only the faces explicitly referencing them.

This function simply calls D3DXComputeTangentFrameEx with the following input parameters:

D3DXComputeTangentFrameEx( pMesh,
D3DX_DEFAULT,
0,
D3DX_DEFAULT,
0,
D3DX_DEFAULT,
0,
D3DDECLUSAGE_NORMAL,
0,
D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS,
pAdjacency,
-1.01f,
-0.01f,
-1.01f,
NULL,
NULL);

下面的代碼通過復制的方法生成了一個具有頂點法向量信息的網(wǎng)格:

LPD3DXMESH mesh;
LPD3DXMESH mesh_clone = NULL;

mesh->CloneMeshFVF(mesh->GetOptions(), mesh->GetFVF() | D3DFVF_NORMAL, _d3d_device, &mesh_clone);

D3DXComputeNormals(mesh_clone, NULL);


Mesh數(shù)據(jù)的優(yōu)化

.X文件的網(wǎng)格數(shù)據(jù)裝入緩沖區(qū)后,每個網(wǎng)格子集的數(shù)據(jù)可以進行優(yōu)化,以提高子集渲染速度。對于頂點緩沖區(qū)來說,可以把位于同一個子集的頂點進行連續(xù)排放,減少三角形面的索引,也可以對鄰接的頂點進行壓縮,節(jié)省內(nèi)存消耗和提高頂點的命中率。對于頂點索引緩沖區(qū)來說,該緩沖區(qū)提供了網(wǎng)格的所有三角形面的構(gòu)成信息,如果把位于同一個子集的三角形面集中連續(xù)排放,就可以使屬性緩沖區(qū)的子集編號按序排列。

ID3DXMesh接口提供了OptimizeInplace 函數(shù)進行網(wǎng)格數(shù)據(jù)各種類型的優(yōu)化,它的使用說明如下所示:

Generates a mesh with reordered faces and vertices to optimize drawing performance. This method reorders the existing mesh.

 HRESULT OptimizeInplace( 
DWORD Flags ,
CONST DWORD * pAdjacencyIn ,
DWORD * pAdjacencyOut ,
DWORD * pFaceRemap ,
LPD3DXBUFFER * ppVertexRemap
);

Parameters

Flags
[in] Combination of one or more D3DXMESHOPT flags, specifying the type of optimization to perform.
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.
pAdjacencyOut
[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. If the value supplied for this argument is NULL, adjacency data is not returned.
pFaceRemap
[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. If the value supplied for this argument is NULL, vertex remap data is not returned.

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

Remarks

Before running ID3DXMesh::OptimizeInplace, 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.

Note     This method will fail if the mesh is sharing its vertex buffer with another mesh, unless the D3DXMESHOPT_IGNOREVERTS is set in Flags.


下面來看看參數(shù)Flags可以使用的網(wǎng)格優(yōu)化類型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.


D3DXLoadMeshFromX函數(shù)裝入.X文件時,會自動為網(wǎng)格填充一個三角形面的鄰接數(shù)組緩沖區(qū),也可以利用 ID3DXMesh接口提供的GenerateAdjacency函數(shù)來生成,下面是該函數(shù)的具體使用說明:

Generate a list of mesh edges, as well as a list of faces that share each edge.

 HRESULT GenerateAdjacency( 
FLOAT Epsilon ,
DWORD * pAdjacency
);

Parameters

Epsilon
[in] Specifies that vertices that differ in position by less than epsilon should be treated as coincident.
pAdjacency
[in] Pointer to an array of three DWORDs per face to be filled with the indices of adjacent faces. The number of bytes in this array must be at least 3 * ID3DXBaseMesh::GetNumFaces * sizeof(DWORD).

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

After an application generates adjacency information for a mesh, the mesh data can be optimized for better drawing performance.

The order of the entries in the adjacency buffer is determined by the order of the vertex indices in the index buffer. The adjacent triangle 0 always corresponds to the edge between the indices of the corners 0 and 1. The adjacent triangle 1 always corresponds to the edge between the indices of the corners 1 and 2 while the adjacent triangle 2 corresponds to the edge between the indices of the corners 2 and 0.


下面的代碼段給出了利用OptimizeInplace進行優(yōu)化的示例:

    // Generates a mesh with reordered faces and vertices to optimize drawing performance. 
    // This method reorders the existing mesh.
    _mesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
        (DWORD*) _adjacency_buffer->GetBufferPointer(), NULL, NULL, NULL);

值得一提的是,進行D3DXMESHOPT_ATTRSORT優(yōu)化操作后,將生成一個Attribute Table,它是一個D3DXATTRIBUTERANGE類型的數(shù)組,反映了優(yōu)化后的子集的三角形面的劃分和頂點的劃分。 D3DXATTRIBUTERANGE的具體定義如下所示:

Stores an attribute table entry.

typedef struct D3DXATTRIBUTERANGE {
DWORD AttribId;
DWORD FaceStart;
DWORD FaceCount;
DWORD VertexStart;
DWORD VertexCount;
} D3DXATTRIBUTERANGE, *LPD3DXATTRIBUTERANGE;

Members

AttribId
Attribute table identifier.
FaceStart
Starting face.
FaceCount
Face count.
VertexStart
Starting vertex.
VertexCount
Vertex count.

Remarks

An attribute table is used to identify areas of the mesh that need to be drawn with different textures, render states, materials, and so on. In addition, the application can use the attribute table to hide portions of a mesh by not drawing a given attribute identifier (AttribId) when drawing the frame.

The LPD3DXATTRIBUTERANGE type is defined as a pointer to the D3DXATTRIBUTERANGE structure.

typedef D3DXATTRIBUTERANGE* LPD3DXATTRIBUTERANGE;

可以調(diào)用ID3DXMesh接口的GetAttribute方法來獲得指向?qū)傩员淼闹羔樅蛯傩员淼拇笮。摵瘮?shù)具體說明如下:

Retrieves either an attribute table for a mesh, or the number of entries stored in an attribute table for a mesh.

 HRESULT GetAttributeTable( 
D3DXATTRIBUTERANGE * pAttribTable ,
DWORD * pAttribTableSize
);

Parameters

pAttribTable
[in, out] Pointer to an array of D3DXATTRIBUTERANGE structures, representing the entries in the mesh's attribute table. Specify NULL to retrieve the value for pAttribTableSize.
pAttribTableSize
[in, out] Pointer to either the number of entries stored in pAttribTable or a value to be filled in with the number of entries stored in the attribute table for the mesh.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

An attribute table is created by ID3DXMesh::Optimize and passing D3DXMESHOPT_ATTRSORT for the Flags parameter.

An attribute table is used to identify areas of the mesh that need to be drawn with different textures, render states, materials, and so on. In addition, the application can use the attribute table to hide portions of a mesh by not drawing a given attribute identifier when drawing the frame.



好了,現(xiàn)在來看一個例子。

需要在工程中設(shè)置鏈接d3dx9.lib d3d9.lib dinput8.lib dxguid.lib winmm.lib。
由于文件中用到了GE_APP和GE_INPUT這兩個類,它的具體使用說明請參閱 主窗口和DirectInput的封裝。
文件中同時還用到了GE_TIMER這個類,它的具體使用說明請參閱 游戲中時間的封裝

源碼與素材下載

來看看XFileLoad.h的定義:
/*************************************************************************************
 [Include File]

 PURPOSE: 
    Load .X file.
************************************************************************************
*/

#ifndef BASIC_XFILE_H
#define BASIC_XFILE_H

class BASIC_XFILE
{
private:
    IDirect3D9
*         _d3d;
    IDirect3DDevice9
*   _d3d_device;
    ID3DXBuffer
*        _adjacency_buffer;
    ID3DXBuffer
*        _material_buffer;
    D3DMATERIAL9
*       _material_array;
    IDirect3DTexture9
** _texture_array;

    DWORD               _num_materials;
    ID3DXMesh
*          _mesh;
    D3DXVECTOR3         _eye_point;

public:
    BASIC_XFILE();
    
~BASIC_XFILE();

    
bool Create_D3D_Device(HWND hwnd, bool full_screen = true);
    
bool Load_XFile(char* x_filename);
    
void Render();
    
void Set_Camera();
    
void Set_Projection();
    
void Rotate(float angle);
    
void Release_Direct3D();
};

#endif

再來看看XFileLoad.cpp的定義:

  
/*************************************************************************************
 [Implement File]

 PURPOSE: 
    Load .X file.
************************************************************************************
*/

#include 
"GE_COMMON.h"
#include 
"XFileLoad.h"

//------------------------------------------------------------------------------------
// Constrcutor, initialize data member.
//------------------------------------------------------------------------------------
BASIC_XFILE::BASIC_XFILE()
{
    _d3d_device         
= NULL;
    _adjacency_buffer   
= NULL;
    _material_buffer    
= NULL;
    _material_array     
= NULL;
    _texture_array      
= NULL;
    _mesh               
= NULL;

    _num_materials      
= 0;

   _eye_point 
= D3DXVECTOR3(3.0f0.0f-3.0f);
}

//------------------------------------------------------------------------------------
// Destructor, release all Direct3D resource has allocated.
//------------------------------------------------------------------------------------
BASIC_XFILE::~BASIC_XFILE()
{
    Release_Direct3D();
}

//------------------------------------------------------------------------------------
// Create direct3D interface and direct3D device.
//------------------------------------------------------------------------------------
bool BASIC_XFILE::Create_D3D_Device(HWND hwnd, bool full_screen)
{
    
// Create a IDirect3D9 object and returns an interace to it.
    _d3d = Direct3DCreate9(D3D_SDK_VERSION);
    
if(_d3d == NULL)
        
return false;

    
// retrieve adapter capability
    D3DCAPS9 d3d_caps;    
    _d3d
->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d_caps);
    
    
bool hardware_process_enable = (d3d_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? true : false);

    
// Retrieves the current display mode of the adapter.
    D3DDISPLAYMODE display_mode;
    
if(FAILED(_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &display_mode)))
        
return false;

    
// set present parameter for direct3D device
    D3DPRESENT_PARAMETERS present_param;

    ZeroMemory(
&present_param, sizeof(present_param));

    present_param.BackBufferWidth        
= WINDOW_WIDTH;
    present_param.BackBufferHeight       
= WINDOW_HEIGHT;
    present_param.BackBufferFormat       
= display_mode.Format;
    present_param.BackBufferCount        
= 1;
    present_param.hDeviceWindow          
= hwnd;
    present_param.Windowed               
= !full_screen;
    present_param.SwapEffect             
= D3DSWAPEFFECT_FLIP;
    present_param.PresentationInterval   
= D3DPRESENT_INTERVAL_DEFAULT;
    present_param.EnableAutoDepthStencil 
= TRUE;
    present_param.AutoDepthStencilFormat 
= D3DFMT_D16;

    
// Creates a device to represent the display adapter.
    DWORD behavior_flags;

    behavior_flags 
= hardware_process_enable ? D3DCREATE_HARDWARE_VERTEXPROCESSING : 
                                           D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    
if(FAILED(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, behavior_flags, 
                                 
&present_param, &_d3d_device)))
    {
        
return false;
    }
    
    
// create successfully
    return true;
}

//------------------------------------------------------------------------------------
// Load .X file
//------------------------------------------------------------------------------------
bool BASIC_XFILE::Load_XFile(char* x_filename)
{
    
// Loads a mesh from a DirectX .x file
    if(FAILED(D3DXLoadMeshFromX(
        x_filename,             
// Pointer to a string that specifies the filename
        D3DXMESH_MANAGED,       // specifies creation options for the mesh
        _d3d_device,            // Pointer to an IDirect3DDevice9 interface
        &_adjacency_buffer,     // Pointer to a buffer that contains adjacency data
        &_material_buffer,      // Pointer to a buffer containing materials data
        NULL,                   // Pointer to a buffer containing an array of effect instances
        &_num_materials,        // Pointer to the number of D3DXMATERIAL structures 
        &_mesh)))               // Address of a pointer to an ID3DXMesh interface
    {
        MessageBox(NULL, 
"Load .X file failed.""ERROR", MB_OK);
        
return false;
    }

    
// invalid data
    if(_material_buffer == NULL || _num_materials == 0)
        
return false;

    
// retrieves a pointer to the data in the buffer
    D3DXMATERIAL* material = (D3DXMATERIAL*) _material_buffer->GetBufferPointer();

    
if(material != NULL)
    {
        
// allocate memory for material array and texture array
        _material_array = new D3DMATERIAL9[_num_materials];
        _texture_array  
= new IDirect3DTexture9*[_num_materials];    

        
for(DWORD i = 0; i < _num_materials; i++)
        {
            
// assign material to array
            _material_array[i] = material[i].MatD3D;

            
if(material[i].pTextureFilename != NULL)
            {
                
if(FAILED(D3DXCreateTextureFromFile(_d3d_device, material[i].pTextureFilename, &_texture_array[i])))
                    _texture_array[i] 
= NULL;
            }
        }
    }

    
// Generates a mesh with reordered faces and vertices to optimize drawing performance. 
    
// This method reorders the existing mesh.
    _mesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
        (DWORD
*) _adjacency_buffer->GetBufferPointer(), NULL, NULL, NULL);

    _material_buffer
->Release();
    _adjacency_buffer
->Release();

    
return true;
}

//------------------------------------------------------------------------------------
// Render mesh.
//------------------------------------------------------------------------------------
void BASIC_XFILE::Render()
{
    
// Clear a render target and the depth buffer
    _d3d_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(000), 1.0f0);

    _d3d_device
->BeginScene();

    
// draw all face in the mesh
    for(DWORD i = 0; i < _num_materials; i++)
    {
        
// Sets the material properties for the device
        _d3d_device->SetMaterial(&_material_array[i]);

        
// Assigns a texture to a stage for a device
        _d3d_device->SetTexture(0, _texture_array[i]);

        
// Draws a subset of a mesh
        _mesh->DrawSubset(i);
    }

    _d3d_device
->EndScene();

    
// Presents the contents of the next buffer in the sequence of back buffers owned by the device
    _d3d_device->Present(NULL, NULL, NULL, NULL);
}

//------------------------------------------------------------------------------------
// Set camera's view transformation matrix
//------------------------------------------------------------------------------------
void BASIC_XFILE::Set_Camera()
{
    D3DXVECTOR3 at(
0.0f0.0f0.0f);
    D3DXVECTOR3 up(
0.0f1.0f0.0f);

    D3DXMATRIX view_matrix;

    
// get transformation matrix to transform world coordinate into view coordinate
    D3DXMatrixLookAtLH(&view_matrix, &_eye_point, &at, &up);

    
// set view transformation matrix to D3D device
    _d3d_device->SetTransform(D3DTS_VIEW, &view_matrix);
}

//------------------------------------------------------------------------------------
// Set projection matrix for D3D device.
//------------------------------------------------------------------------------------
void BASIC_XFILE::Set_Projection()
{
    D3DXMATRIX proj_matrix;

    
// build a perspective matrix using left hand 
    D3DXMatrixPerspectiveFovLH(&proj_matrix, D3DX_PI/2, WINDOW_WIDTH/WINDOW_HEIGHT, 1.0f1000.0f);

    
// set projection matrix to D3D device
    _d3d_device->SetTransform(D3DTS_PROJECTION, &proj_matrix);

    
// enable automatic normalization of vertex normals
    _d3d_device->SetRenderState(D3DRS_NORMALIZENORMALS, true);

    
// set magnification filter with linear mode
    _d3d_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

    
// set minification filter with linear mode
    _d3d_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

    
// set mipmap filter with point mode
    _d3d_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

    
// disable lighting
    _d3d_device->SetRenderState(D3DRS_LIGHTING, false);
}

//------------------------------------------------------------------------------------
// Rotate eye point with specified angle around y axis.
//------------------------------------------------------------------------------------
void BASIC_XFILE::Rotate(float angle)
{
    D3DXMATRIX mat_rotate;

    
// Builds a matrix that rotates around the y-axis
    D3DXMatrixRotationY(&mat_rotate, angle);

    
// Transforms a 3D vector by a given matrix, projecting the result back into w = 1.
    D3DXVec3TransformCoord(&_eye_point, &_eye_point, &mat_rotate);
}

//------------------------------------------------------------------------------------
// Release all Direct3D object.
//------------------------------------------------------------------------------------
void BASIC_XFILE::Release_Direct3D()
{
    
for(DWORD i = 0; i < _num_materials; i++)
        Safe_Release(_texture_array[i]);

    Safe_Release(_mesh);
    Safe_Release(_d3d_device);    
}

最后看看測試文件main.cpp的實現(xiàn):

  
/*************************************************************************************
 [Implement File]

 PURPOSE: 
    Test for loading .X file.
************************************************************************************
*/

#define DIRECTINPUT_VERSION 0x0800

#include 
"GE_COMMON.h"
#include 
"GE_APP.h"
#include 
"GE_INPUT.h"
#include 
"GE_TIMER.h"
#include 
"XFileLoad.h"

#pragma warning(disable : 
4305 4996)

const float ROTATE_ANGLE = 0.05;

int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    GE_APP ge_app;
    GE_INPUT ge_input;
    GE_TIMER ge_timer;

    BASIC_XFILE x_file;

    MSG msg 
= {0};

    
// create window
    if(! ge_app.Create_Window("Transparent blending test", instance, cmd_show))
        
return false;

    ge_timer.Init_Game_Time();

    HWND hwnd 
= ge_app.Get_Window_Handle();    

    SetWindowPos(hwnd, 
00,0,0,0, SWP_NOSIZE);
    SetCursorPos(
00);    

    
// create direct input
    ge_input.Create_Input(instance, hwnd);    
    
    
// Create direct3D interface and direct3D device.
    if(! x_file.Create_D3D_Device(hwnd, false))
        
return false;

    
if(x_file.Load_XFile("tiger.x"))
    {
        x_file.Set_Camera();
        x_file.Set_Projection();
        x_file.Render();
    }
    
    
float last_render_time = ge_timer.Get_Game_Play_Time();

    
while(msg.message != WM_QUIT)
    {
        
if(PeekMessage(&msg, NULL, 0,0 , PM_REMOVE))
        {
            TranslateMessage(
&msg);
            DispatchMessage(
&msg);
        }
        
else
        {
            
// get keyboard input
            if(ge_input.Read_Keyboard())
            {
                
if(ge_input.Is_Key_Pressed(DIK_ESCAPE))
                    PostQuitMessage(
0);

                
// if it is time to render again
                if(ge_timer.Get_Game_Play_Time() > last_render_time + 30)
                {
                    
// rotate camera
                    x_file.Rotate(ROTATE_ANGLE);

                    
// reset camera
                    x_file.Set_Camera();

                    x_file.Render();

                    
// update last render time
                    last_render_time = ge_timer.Get_Game_Play_Time();
                }
            }
        }
    }    

    UnregisterClass(WINDOW_CLASS_NAME, instance);

    
return true;
}


運行效果:



 

posted on 2007-05-18 22:55 lovedday 閱讀(2884) 評論(9)  編輯 收藏 引用

評論

# re: XFile網(wǎng)格的應(yīng)用(3) 2008-08-31 20:43 xxx

你很喜歡復制粘貼啊?這種東西值錢嗎?  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2008-08-31 21:06 lovedday

復制黏貼,你說說這些文章原出處在哪?這些文章我是寫給自己看的,再說,我沒逼你看。文章有沒有價值也用不著你來評價,發(fā)表文章是我的自由。我寫這些東西一不指望成名,二不指望賺錢,我在自己的博客上寫點東西怎么呢?難道我在自己的博客上寫點文章還要經(jīng)過你的許可?什么人啊,整一精神不正常。  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2008-09-17 14:57 黑夜又白粥

頂下博主,看了XFILE系列文章,很有幫助,多謝啊,不用管無理取鬧的家伙!  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2008-12-16 21:01 看博的人

頂樓上的,說得一點都沒有錯。不用管那種沒事找事的家伙。  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2009-01-14 17:01 arun

很好,謝過~  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2009-07-08 09:22 blueesoft

我支持博主,加油!!  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2009-09-05 00:41 lyra

xxx缺心眼,簽定完畢。博主很好,費時費力弄了這么多,幫助了N多人。  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2009-09-16 17:47 神仙

非常感謝博主,很有幫助,多謝!XXX估計是嫉妒  回復  更多評論   

# re: XFile網(wǎng)格的應(yīng)用(3) 2011-08-15 19:42 scarlettlee

@lovedday
看博主的文章很舒服,就像品味一杯奶茶。樓主應(yīng)該是一個很淡定的人,遇到樓上這種“沒有調(diào)查更沒有發(fā)言權(quán)”的人,淡定就好了,O(∩_∩)O~  回復  更多評論   


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


公告

導航

統(tǒng)計

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久视频在线看| 美女日韩在线中文字幕| 国产精品日韩专区| 欧美一二三视频| 久久综合色婷婷| 亚洲欧洲精品一区二区| 欧美日韩高清免费| 亚洲欧美综合国产精品一区| 久久一区二区三区av| 91久久久久久国产精品| 欧美日韩国产小视频在线观看| 亚洲网址在线| 美女精品一区| 一本色道婷婷久久欧美| 国产精品入口夜色视频大尺度| 久久精品视频在线| 亚洲美女视频在线观看| 欧美一区二区三区精品| 亚洲国产另类久久久精品极度 | 麻豆91精品| 日韩亚洲精品在线| 久久免费少妇高潮久久精品99| 亚洲激情偷拍| 国产日韩av高清| 欧美日韩国产不卡在线看| 亚洲欧美日韩中文视频| 亚洲国产一二三| 午夜免费电影一区在线观看| 在线成人激情| 国产美女精品免费电影| 欧美激情网友自拍| 久久精品国产免费看久久精品| 亚洲乱码国产乱码精品精天堂| 久久深夜福利免费观看| 亚洲视频综合| 亚洲三级免费电影| 国内精品视频在线观看| 国产精品免费观看在线| 欧美成人免费在线观看| 久久国产毛片| 亚洲欧美成人综合| 亚洲巨乳在线| 亚洲盗摄视频| 你懂的网址国产 欧美| 久久成人av少妇免费| 一区二区三区免费网站| 亚洲国内自拍| 国内一区二区三区在线视频| 国产精品久久久久久久久搜平片 | 媚黑女一区二区| 欧美自拍偷拍| 亚久久调教视频| 亚洲欧美国产77777| 一区二区三区高清视频在线观看| 亚洲第一网站| 欧美激情一区三区| 欧美mv日韩mv国产网站| 久久漫画官网| 久久久噜噜噜久久久| 久久国产精品毛片| 欧美在线91| 欧美在线高清| 久久精品国产99精品国产亚洲性色| 亚洲免费在线| 亚洲欧美成人网| 在线一区二区日韩| 一区二区三区四区国产| 一本色道久久综合精品竹菊| 99在线精品视频| 在线亚洲精品福利网址导航| 夜夜爽99久久国产综合精品女不卡| 亚洲欧洲一区二区三区久久| 亚洲日本理论电影| 一本色道久久精品| 亚洲制服丝袜在线| 性欧美xxxx大乳国产app| 欧美在线一级视频| 久久亚洲视频| 欧美激情第4页| 亚洲精品国产精品久久清纯直播| 亚洲区第一页| 在线午夜精品| 先锋影音久久久| 久久精品国产一区二区三区| 久久久蜜臀国产一区二区| 久久久一区二区三区| 欧美大胆a视频| 欧美三级日韩三级国产三级| 国产精品家庭影院| 国产亚洲制服色| 亚洲国产精品视频一区| 日韩一区二区免费高清| 亚洲在线黄色| 久久精品国产一区二区电影| 免费久久99精品国产自在现线| 欧美激情bt| 夜夜嗨一区二区| 欧美亚洲一区三区| 美女精品在线观看| 欧美日韩一区二区在线观看| 国产伦精品免费视频 | 91久久黄色| 99视频精品全部免费在线| 亚洲欧美一区二区精品久久久| 欧美一站二站| 欧美激情精品久久久久久大尺度| 欧美午夜精品一区二区三区| 国产在线精品一区二区中文 | 一区二区免费在线视频| 久久国产主播| 欧美久久久久中文字幕| 国产欧美综合一区二区三区| 亚洲电影免费| 亚洲欧美日韩另类| 欧美77777| 亚洲视频欧美在线| 久久亚洲精品网站| 国产精品色网| 亚洲乱码国产乱码精品精可以看| 欧美在线免费观看| 亚洲精品国产精品乱码不99按摩 | 午夜天堂精品久久久久| 美女黄毛**国产精品啪啪| 亚洲免费久久| 久久久久久久久久码影片| 国产精品户外野外| 亚洲啪啪91| 久久只有精品| 中日韩视频在线观看| 欧美国产日本在线| 精品动漫3d一区二区三区免费版 | 最新精品在线| 久久精品国产亚洲高清剧情介绍| 欧美日韩性生活视频| 亚洲国产精品va在线看黑人动漫| 午夜一级在线看亚洲| 亚洲每日更新| 牛人盗摄一区二区三区视频| 国产亚洲制服色| 翔田千里一区二区| 日韩小视频在线观看专区| 欧美本精品男人aⅴ天堂| 激情成人综合网| 久久久久国色av免费观看性色| 99精品国产高清一区二区| 欧美 日韩 国产一区二区在线视频 | 极品少妇一区二区| 欧美一区国产一区| 亚洲视频综合| 欧美性猛交xxxx乱大交退制版| 亚洲精品国产精品国自产在线 | 欧美在线一二三| 国产欧美日本在线| 香蕉久久一区二区不卡无毒影院| 99国产一区二区三精品乱码| 欧美伦理在线观看| 亚洲精品在线三区| 亚洲人成77777在线观看网| 猫咪成人在线观看| 亚洲国产精品成人一区二区| 乱人伦精品视频在线观看| 久久av一区二区三区漫画| 国产色产综合色产在线视频| 欧美一区二区在线免费播放| 亚洲一区二区视频在线观看| 国产欧美91| 久久九九热re6这里有精品| 欧美在线|欧美| 亚洲第一精品久久忘忧草社区| 麻豆国产va免费精品高清在线| 久久久999精品免费| 极品少妇一区二区三区精品视频| 久久久最新网址| 久久中文字幕一区| 亚洲人成亚洲人成在线观看| 亚洲国产精品悠悠久久琪琪| 欧美老女人xx| 午夜精品理论片| 欧美亚洲一区在线| 亚洲国产成人久久| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美精品色网| 亚洲欧美大片| 欧美在线二区| 亚洲精品国产欧美| 一本一本久久| 狠狠久久亚洲欧美专区| 欧美激情视频网站| 欧美亚州一区二区三区| 久久久99国产精品免费| 美女被久久久| 西西裸体人体做爰大胆久久久| 久久久久久久久久久一区| 亚洲免费精品| 欧美淫片网站| 在线一区二区视频| 久久久久久香蕉网| 中文精品视频| 久久天天狠狠| 欧美一区二区三区四区在线观看|