您的位置:首页 > 其它

关于DirectX高级动画书中使用的9.0bsdk的升级说明

2014-02-26 19:34 453 查看
/article/8597015.html

在《Advanced.Animation.with.DirectX》DirectX开发游戏高级动画书中的代码例子都使用了9.0B版本的sdk,现如今的新入行的程序员很少有人再去使用vc6.0 ,大部分人都使用的是9.0c版本的sdk,所以导致编译出现错误:

error C2664: 'D3DXLoadSkinMeshFromXof' : cannot convert parameter 1 from 'IDirectXFileData *' to 'LPD3DXFILEDATA'

要想使用vs2005和9.0c

那么需要修改几个地方:

1、搜索所有的IDirectXFileData 替换成ID3DXFileData,添加D3dx9xof.h

替换所有的

IDirectXFile成ID3DXFile

IDirectXFileEnumObject -- ID3DXFileEnumObject

DirectXFileCreate D3DXFileCreate

但是ID3DXFileData 没有GetData,GetNextObject,AddDataReference等方法.

判断是否引用的改成了IsReference方法.

而获取子信息由原来的一个函数换成了这两个GetChild,GetChildren

下面是我经过改动之后代码......帮那些正在学的人少走一条湾路......

#ifndef _DIRECT3D_H_

#define _DIRECT3D_H_

#include <stdio.h>

#include <windows.h>

#include "d3d9.h"

#include "d3dx9.h"

#include "dxfile.h"

#include "XFile.h"

#include "D3dx9xof.h"

#define ReleaseCOM(x) { if(x!=NULL) x->Release(); x=NULL; }

// Declare an extended version of D3DXFRAME

// that contains a constructor and destructor

// as well as a combined transformation matrix

struct D3DXFRAME_EX : D3DXFRAME

{

D3DXMATRIX matCombined; // Combined matrix

D3DXMATRIX matOriginal; // Original transformation from .X

D3DXFRAME_EX()

{

Name = NULL;

pMeshContainer = NULL;

pFrameSibling = pFrameFirstChild = NULL;

D3DXMatrixIdentity(&matCombined);

D3DXMatrixIdentity(&matOriginal);

D3DXMatrixIdentity(&TransformationMatrix);

}

~D3DXFRAME_EX()

{

delete [] Name; Name = NULL;

delete pFrameSibling; pFrameSibling = NULL;

delete pFrameFirstChild; pFrameFirstChild = NULL;

}

// Function to scan hierarchy for matching frame name

D3DXFRAME_EX *Find(const char *FrameName)

{

D3DXFRAME_EX *pFrame, *pFramePtr;

// Return this frame instance if name matched

if(Name && FrameName && !strcmp(FrameName, Name))

return this;

// Scan siblings

if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling)) {

if((pFrame = pFramePtr->Find(FrameName)))

return pFrame;

}

// Scan children

if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild)) {

if((pFrame = pFramePtr->Find(FrameName)))

return pFrame;

}

// Return none found

return NULL;

}

// Reset transformation matrices to originals

void Reset()

{

// Copy original matrix

TransformationMatrix = matOriginal;

// Reset sibling frames

D3DXFRAME_EX *pFramePtr;

if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))

pFramePtr->Reset();

// Reset child frames

if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))

pFramePtr->Reset();

}

// Function to combine matrices in frame hiearchy

void UpdateHierarchy(D3DXMATRIX *matTransformation = NULL)

{

D3DXFRAME_EX *pFramePtr;

D3DXMATRIX matIdentity;

// Use an identity matrix if none passed

if(!matTransformation) {

D3DXMatrixIdentity(&matIdentity);

matTransformation = &matIdentity;

}

// Combine matrices w/supplied transformation matrix

matCombined = TransformationMatrix * (*matTransformation);

// Combine w/sibling frames

if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))

pFramePtr->UpdateHierarchy(matTransformation);

// Combine w/child frames

if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))

pFramePtr->UpdateHierarchy(&matCombined);

}

void Count(DWORD *Num)

{

// Error checking

if(!Num)

return;

// Increase count of frames

(*Num)+=1;

// Process sibling frames

D3DXFRAME_EX *pFrame;

if((pFrame=(D3DXFRAME_EX*)pFrameSibling))

pFrame->Count(Num);

// Process child frames

if((pFrame=(D3DXFRAME_EX*)pFrameFirstChild))

pFrame->Count(Num);

}

};

// Declare an extended version of D3DXMESHCONTAINER

// that contains a constructor and destructor

// as well as an array of textures, a mesh object

// that contains the generated skin mesh, and

// matrices that map to the frame hierarchy's and

// for updating bones.

struct D3DXMESHCONTAINER_EX : D3DXMESHCONTAINER

{

IDirect3DTexture9 **pTextures;

ID3DXMesh *pSkinMesh;

D3DXMATRIX **ppFrameMatrices;

D3DXMATRIX *pBoneMatrices;

D3DXMESHCONTAINER_EX()

{

Name = NULL;

MeshData.pMesh = NULL;

pMaterials = NULL;

pEffects = NULL;

NumMaterials = 0;

pAdjacency = NULL;

pSkinInfo = NULL;

pNextMeshContainer = NULL;

pTextures = NULL;

pSkinMesh = NULL;

ppFrameMatrices = NULL;

pBoneMatrices = NULL;

}

~D3DXMESHCONTAINER_EX()

{

if(pTextures && NumMaterials) {

for(DWORD i=0;i<NumMaterials;i++)

ReleaseCOM(pTextures[i]);

}

delete [] pTextures; pTextures = NULL;

NumMaterials = 0;

delete [] Name; Name = NULL;

delete [] pMaterials; pMaterials = NULL;

delete pEffects; pEffects = NULL;

delete [] pAdjacency; pAdjacency = NULL;

delete [] ppFrameMatrices; ppFrameMatrices = NULL;

delete [] pBoneMatrices; pBoneMatrices = NULL;

ReleaseCOM(MeshData.pMesh);

ReleaseCOM(pSkinInfo);

ReleaseCOM(pSkinMesh);

delete pNextMeshContainer; pNextMeshContainer = NULL;

}

D3DXMESHCONTAINER_EX *Find(char *MeshName)

{

D3DXMESHCONTAINER_EX *pMesh, *pMeshPtr;

// Return this mesh instance if name matched

if(Name && MeshName && !strcmp(MeshName, Name))

return this;

// Scan next in list

if((pMeshPtr = (D3DXMESHCONTAINER_EX*)pNextMeshContainer)) {

if((pMesh = pMeshPtr->Find(MeshName)))

return pMesh;

}

// Return none found

return NULL;

}

};

// Declare an internal .X file parser class for loading meshes and frames

class cXInternalParser

{

public:

// Information passed from calling function

IDirect3DDevice9 *m_pD3DDevice;

char *m_TexturePath;

DWORD m_NewFVF;

DWORD m_LoadFlags;

// Flags for which data to load

// 1 = mesh, 2 = frames, 3= both

DWORD m_Flags;

// Hierarchies used during loading

D3DXMESHCONTAINER_EX *m_RootMesh;

D3DXFRAME_EX *m_RootFrame;

protected:

// Function called for every template found

BOOL ParseObject(ID3DXFileData *pDataObj,

ID3DXFileData *pParentDataObj,

DWORD Depth,

void **Data, BOOL Reference);

// Function called to enumerate child templates

BOOL ParseChildObjects(ID3DXFileData *pDataObj,

DWORD Depth, void **Data,

BOOL ForceReference = FALSE);

public:

// Constructor and destructor

cXInternalParser();

~cXInternalParser();

// Function to start parsing an .X file

BOOL Parse(char *Filename, void **Data = NULL);

// Functions to help retrieve template information

const GUID *GetObjectGUID(ID3DXFileData *pDataObj);

char *GetObjectName(ID3DXFileData *pDataObj);

void *GetObjectData(ID3DXFileData *pDataObj, DWORD *Size);

};

// Initialize D3D

HRESULT InitD3D(IDirect3D9 **ppD3D,

IDirect3DDevice9 **ppD3DDevice,

HWND hWnd, BOOL ForceWindowed = FALSE,

BOOL MultiThreaded = FALSE);

// Load a vertex shader

HRESULT LoadVertexShader(IDirect3DVertexShader9 **ppShader,

IDirect3DDevice9 *pDevice,

char *Filename,

D3DVERTEXELEMENT9 *pElements = NULL,

IDirect3DVertexDeclaration9 **ppDecl = NULL);

// Load a single mesh from an .X file (compact multiple meshes into one)

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

IDirect3DDevice9 *pDevice,

char *Filename,

char *TexturePath = ".//",

DWORD NewFVF = 0,

DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Load a single mesh (regular or skinned) from a mesh template

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

IDirect3DDevice9 *pDevice,

ID3DXFileData *pDataObj,

char *TexturePath = ".//",

DWORD NewFVF = 0,

DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Load all meshes and frames from an .X file

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

D3DXFRAME_EX **ppFrame,

IDirect3DDevice9 *pDevice,

char *Filename,

char *TexturePath = ".//",

DWORD NewFVF = 0,

DWORD LoadFlags = D3DXMESH_SYSTEMMEM);

// Update a skinned mesh

HRESULT UpdateMesh(D3DXMESHCONTAINER_EX *pMesh);

// Draw the first mesh in a linked list of objects

HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh);

// Draw the first mesh in a linked list of objects

// using the specified vertex shader and declaration

HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh,

IDirect3DVertexShader9 *pShader,

IDirect3DVertexDeclaration9 *pDecl);

// Draw all meshes in a linked list of objects

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh);

// Draw all meshes in a linked list of objects

// using the specified vertex shader and declaration

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh,

IDirect3DVertexShader9 *pShader,

IDirect3DVertexDeclaration9 *pDecl);

#endif

#include "Direct3D.h"

///////////////////////////////////////////////////////////

//

// Initialize Direct3D function

//

///////////////////////////////////////////////////////////

HRESULT InitD3D(IDirect3D9 **ppD3D,

IDirect3DDevice9 **ppD3DDevice,

HWND hWnd,

BOOL ForceWindowed,

BOOL MultiThreaded)

{

IDirect3D9 *pD3D = NULL;

IDirect3DDevice9 *pD3DDevice = NULL;

HRESULT hr;

// Error checking

if(!ppD3D || !ppD3DDevice || !hWnd)

return E_FAIL;

// Initialize Direct3D

if((pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)

return E_FAIL;

*ppD3D = pD3D;

// Ask if user wants to run windowed or fullscreen

// or force windowed if flagged to do such

int Mode;

if(ForceWindowed == TRUE)

Mode = IDNO;

else

Mode = MessageBox(hWnd, "Use fullscreen mode? (640x480x16)", "Initialize D3D", MB_YESNO | MB_ICONQUESTION);

// Set the video (depending on windowed mode or fullscreen)

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory(&d3dpp, sizeof(d3dpp));

// Setup video settings based on choice of fullscreen or not

if(Mode == IDYES) {

//////////////////////////////////////////////////////////

// Setup fullscreen format (set to your own if you prefer)

//////////////////////////////////////////////////////////

DWORD Width = 640;

DWORD Height = 480;

D3DFORMAT Format = D3DFMT_R5G6B5;

// Set the presentation parameters (use fullscreen)

d3dpp.BackBufferWidth = Width;

d3dpp.BackBufferHeight = Height;

d3dpp.BackBufferFormat = Format;

d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;

d3dpp.Windowed = FALSE;

d3dpp.EnableAutoDepthStencil = TRUE;

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

} else {

//////////////////////////////////////////////////////////

// Setup windowed format (set to your own dimensions below)

//////////////////////////////////////////////////////////

// Get the client and window dimensions

RECT ClientRect, WndRect;

GetClientRect(hWnd, &ClientRect);

GetWindowRect(hWnd, &WndRect);

// Set the width and height (set your dimensions here)

DWORD DesiredWidth = 640;

DWORD DesiredHeight = 480;

DWORD Width = (WndRect.right - WndRect.left) + (DesiredWidth - ClientRect.right);

DWORD Height = (WndRect.bottom - WndRect.top) + (DesiredHeight - ClientRect.bottom);

// Set the window's dimensions

MoveWindow(hWnd, WndRect.left, WndRect.top, Width, Height, TRUE);

// Get the desktop format

D3DDISPLAYMODE d3ddm;

pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

// Set the presentation parameters (use windowed)

d3dpp.BackBufferWidth = DesiredWidth;

d3dpp.BackBufferHeight = DesiredHeight;

d3dpp.BackBufferFormat = d3ddm.Format;

d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

d3dpp.Windowed = TRUE;

d3dpp.EnableAutoDepthStencil = TRUE;

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

}

// Create the 3-D device

DWORD Flags= D3DCREATE_MIXED_VERTEXPROCESSING;

// DWORD Flags= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

if(MultiThreaded == TRUE)

Flags |= D3DCREATE_MULTITHREADED;

if(FAILED(hr = pD3D->CreateDevice(

D3DADAPTER_DEFAULT,

D3DDEVTYPE_HAL, hWnd, Flags,

&d3dpp, &pD3DDevice)))

return hr;

// Store the 3-D device object pointer

*ppD3DDevice = pD3DDevice;

// Set the perspective projection

float Aspect = (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight;

D3DXMATRIX matProjection;

D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4.0f, Aspect, 1.0f, 10000.0f);

pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection);

// Set the default render states

pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

// Set the default texture stage states

pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

// Set the default texture filters

pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

return S_OK;

}

///////////////////////////////////////////////////////////

//

// Load a vertex shader function

//

///////////////////////////////////////////////////////////

HRESULT LoadVertexShader(IDirect3DVertexShader9 **ppShader,

IDirect3DDevice9 *pDevice,

char *Filename,

D3DVERTEXELEMENT9 *pElements,

IDirect3DVertexDeclaration9 **ppDecl)

{

HRESULT hr;

// Error checking

if(!ppShader || !pDevice || !Filename)

return E_FAIL;

// Load and assemble the shader

ID3DXBuffer *pCode;

if(FAILED(hr=D3DXAssembleShaderFromFile(Filename, NULL, NULL, 0, &pCode, NULL)))

return hr;

if(FAILED(hr=pDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(), ppShader)))

return hr;

pCode->Release();

// Create the declaration interface if needed

if(pElements && ppDecl)

pDevice->CreateVertexDeclaration(pElements, ppDecl);

// Return success

return S_OK;

}

///////////////////////////////////////////////////////////

//

// Load mesh functions

//

///////////////////////////////////////////////////////////

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

IDirect3DDevice9 *pDevice,

char *Filename,

char *TexturePath,

DWORD NewFVF,

DWORD LoadFlags)

{

ID3DXMesh *pLoadMesh = NULL;

HRESULT hr;

// Error checking

if(!ppMesh || !pDevice || !Filename || !TexturePath)

return E_FAIL;

// Use system memory if converting FVF

DWORD TempLoadFlags = LoadFlags;

if(NewFVF)

TempLoadFlags = D3DXMESH_SYSTEMMEM;

// Load the mesh using D3DX routines

ID3DXBuffer *MaterialBuffer = NULL, *AdjacencyBuffer = NULL;

DWORD NumMaterials;

if(FAILED(hr=D3DXLoadMeshFromX(Filename, TempLoadFlags,

pDevice, &AdjacencyBuffer,

&MaterialBuffer, NULL,

&NumMaterials, &pLoadMesh)))

return hr;

// Convert to new FVF first as needed

if(NewFVF) {

ID3DXMesh *pTempMesh;

// Use CloneMeshFVF to convert mesh

if(FAILED(hr=pLoadMesh->CloneMeshFVF(LoadFlags, NewFVF, pDevice, &pTempMesh))) {

ReleaseCOM(AdjacencyBuffer);

ReleaseCOM(MaterialBuffer);

ReleaseCOM(pLoadMesh);

return hr;

}

// Free prior mesh and store new pointer

ReleaseCOM(pLoadMesh);

pLoadMesh = pTempMesh; pTempMesh = NULL;

}

// Allocate a D3DXMESHCONTAINER_EX structure

D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX();

*ppMesh = pMesh;

// Store mesh name (filename), type, and mesh pointer

pMesh->Name = strdup(Filename);

pMesh->MeshData.Type = D3DXMESHTYPE_MESH;

pMesh->MeshData.pMesh = pLoadMesh; pLoadMesh = NULL;

// Store adjacency buffer

DWORD AdjSize = AdjacencyBuffer->GetBufferSize();

if(AdjSize) {

pMesh->pAdjacency = new DWORD[AdjSize];

memcpy(pMesh->pAdjacency, AdjacencyBuffer->GetBufferPointer(), AdjSize);

}

ReleaseCOM(AdjacencyBuffer);

// Build material list

if(!(pMesh->NumMaterials = NumMaterials)) {

// Create a default material

pMesh->NumMaterials = 1;

pMesh->pMaterials = new D3DXMATERIAL[1];

pMesh->pTextures = new IDirect3DTexture9*[1];

ZeroMemory(pMesh->pMaterials, sizeof(D3DXMATERIAL));

pMesh->pMaterials[0].MatD3D.Diffuse.r = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.g = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.b = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.a = 1.0f;

pMesh->pMaterials[0].MatD3D.Ambient = pMesh->pMaterials[0].MatD3D.Diffuse;

pMesh->pMaterials[0].MatD3D.Specular = pMesh->pMaterials[0].MatD3D.Diffuse;

pMesh->pMaterials[0].pTextureFilename = NULL;

pMesh->pTextures[0] = NULL;

} else {

// Load the materials

D3DXMATERIAL *Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer();

pMesh->pMaterials = new D3DXMATERIAL[pMesh->NumMaterials];

pMesh->pTextures = new IDirect3DTexture9*[pMesh->NumMaterials];

for(DWORD i=0;i<pMesh->NumMaterials;i++) {

pMesh->pMaterials[i].MatD3D = Materials[i].MatD3D;

pMesh->pMaterials[i].MatD3D.Ambient = pMesh->pMaterials[i].MatD3D.Diffuse;

// Load the texture if one exists

pMesh->pTextures[i] = NULL;

if(Materials[i].pTextureFilename) {

char TextureFile[MAX_PATH];

sprintf(TextureFile, "%s%s", TexturePath,

Materials[i].pTextureFilename);

D3DXCreateTextureFromFile(pDevice,

TextureFile,

&pMesh->pTextures[i]);

}

}

}

ReleaseCOM(MaterialBuffer);

// Optimize the mesh for better attribute access

pMesh->MeshData.pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);

// Clear pMesh pointer just in case

pMesh = NULL;

return S_OK;

}

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

IDirect3DDevice9 *pDevice,

ID3DXFileData *pDataObj,

char *TexturePath,

DWORD NewFVF,

DWORD LoadFlags)

{

ID3DXMesh *pLoadMesh = NULL;

ID3DXSkinInfo *pSkin = NULL;

HRESULT hr;

// Error checking

if(!ppMesh || !pDevice || !pDataObj || !TexturePath)

return E_FAIL;

// Use system memory if converting FVF

DWORD TempLoadFlags = LoadFlags;

if(NewFVF)

TempLoadFlags = D3DXMESH_SYSTEMMEM;

// Load the mesh using the D3DX skinned mesh interface

ID3DXBuffer *MaterialBuffer = NULL, *AdjacencyBuffer = NULL;

DWORD NumMaterials;

if(FAILED(hr=D3DXLoadSkinMeshFromXof(pDataObj, TempLoadFlags,

pDevice, &AdjacencyBuffer,

&MaterialBuffer, NULL,

&NumMaterials, &pSkin,

&pLoadMesh)))

return hr;

// Free skin info if no bones

if(pSkin && !pSkin->GetNumBones())

ReleaseCOM(pSkin);

// Convert to new FVF first as needed (not w/skinned models)

if(NewFVF) {

ID3DXMesh *pTempMesh = NULL;

// Use CloneMeshFVF to convert mesh

if(FAILED(hr=pLoadMesh->CloneMeshFVF(LoadFlags, NewFVF, pDevice, &pTempMesh))) {

ReleaseCOM(pLoadMesh);

ReleaseCOM(pSkin);

ReleaseCOM(MaterialBuffer);

ReleaseCOM(AdjacencyBuffer);

return hr;

}

// Free prior mesh and store new pointer

ReleaseCOM(pLoadMesh);

pLoadMesh = pTempMesh; pTempMesh = NULL;

}

// Allocate a D3DXMESHCONTAINER_EX structure

D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX();

*ppMesh = pMesh;

// Store mesh template name, type, and mesh pointers

DWORD Size;

pDataObj->GetName(NULL, &Size);

if(Size) {

pMesh->Name = new char[Size];

pDataObj->GetName(pMesh->Name, &Size);

}

pMesh->MeshData.Type = D3DXMESHTYPE_MESH;

pMesh->MeshData.pMesh = pLoadMesh; pLoadMesh = NULL;

pMesh->pSkinInfo = pSkin; pSkin = NULL;

// Store adjacency buffer

DWORD AdjSize = AdjacencyBuffer->GetBufferSize();

if(AdjSize) {

pMesh->pAdjacency = (DWORD*)new char[AdjSize];

memcpy(pMesh->pAdjacency, AdjacencyBuffer->GetBufferPointer(), AdjSize);

}

ReleaseCOM(AdjacencyBuffer);

// Create a duplicate mesh in case skinning is used

if(pMesh->pSkinInfo)

pMesh->MeshData.pMesh->CloneMeshFVF(0, //D3DXMESH_MANAGED,

pMesh->MeshData.pMesh->GetFVF(),

pDevice, &pMesh->pSkinMesh);

// Build material list

if(!(pMesh->NumMaterials = NumMaterials)) {

// Create a default material

pMesh->NumMaterials = 1;

pMesh->pMaterials = new D3DXMATERIAL[1];

pMesh->pTextures = new IDirect3DTexture9*[1];

ZeroMemory(&pMesh->pMaterials[0], sizeof(D3DXMATERIAL));

pMesh->pMaterials[0].MatD3D.Diffuse.r = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.g = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.b = 1.0f;

pMesh->pMaterials[0].MatD3D.Diffuse.a = 1.0f;

pMesh->pMaterials[0].MatD3D.Ambient = pMesh->pMaterials[0].MatD3D.Diffuse;

pMesh->pMaterials[0].MatD3D.Specular = pMesh->pMaterials[0].MatD3D.Diffuse;

pMesh->pMaterials[0].pTextureFilename = NULL;

pMesh->pTextures[0] = NULL;

} else {

// Load the materials

D3DXMATERIAL *Materials = (D3DXMATERIAL*)MaterialBuffer->GetBufferPointer();

pMesh->pMaterials = new D3DXMATERIAL[pMesh->NumMaterials];

pMesh->pTextures = new IDirect3DTexture9*[pMesh->NumMaterials];

for(DWORD i=0;i<pMesh->NumMaterials;i++) {

pMesh->pMaterials[i].MatD3D = Materials[i].MatD3D;

pMesh->pMaterials[i].MatD3D.Ambient = pMesh->pMaterials[i].MatD3D.Diffuse;

// Load the texture if one exists

pMesh->pTextures[i] = NULL;

if(Materials[i].pTextureFilename) {

char TextureFile[MAX_PATH];

sprintf(TextureFile, "%s%s", TexturePath,

Materials[i].pTextureFilename);

D3DXCreateTextureFromFile(pDevice,

TextureFile,

&pMesh->pTextures[i]);

}

}

}

ReleaseCOM(MaterialBuffer);

// Optimize the mesh for better attribute access

pMesh->MeshData.pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);

// Clear pMesh pointer just in case

pMesh = NULL;

return S_OK;

}

HRESULT LoadMesh(D3DXMESHCONTAINER_EX **ppMesh,

D3DXFRAME_EX **ppFrame,

IDirect3DDevice9 *pDevice,

char *Filename,

char *TexturePath,

DWORD NewFVF,

DWORD LoadFlags)

{

cXInternalParser Parser;

// Error checking

if(!pDevice || !Filename || !TexturePath)

return E_FAIL;

// Set parser data

Parser.m_pD3DDevice = pDevice;

Parser.m_TexturePath = TexturePath;

Parser.m_NewFVF = NewFVF;

Parser.m_LoadFlags = LoadFlags;

Parser.m_Flags = ((!ppMesh)?0:1) | ((!ppFrame)?0:2);

// Clear mesh and frame pointers

Parser.m_RootFrame = NULL;

Parser.m_RootMesh = NULL;

// Parse the file

Parser.Parse(Filename);

// Map the matrices to the frames and create an array of bone

// matrices, but only if user passed pointers to receive and

// the loader found some meshes and frames.

if(ppMesh && ppFrame && Parser.m_RootMesh && Parser.m_RootFrame) {

// Scan through all meshes

D3DXMESHCONTAINER_EX *pMesh = Parser.m_RootMesh;

while(pMesh) {

// Does this mesh use skinning?

if(pMesh->pSkinInfo) {

// Get the number of bones

DWORD NumBones = pMesh->pSkinInfo->GetNumBones();

// Allocate the matrix pointers and bone matrices

pMesh->ppFrameMatrices = new D3DXMATRIX*[NumBones];

pMesh->pBoneMatrices = new D3DXMATRIX[NumBones];

// Match matrix pointers to frames

for(DWORD i=0;i<NumBones;i++) {

// Get bone name

const char *BoneName = pMesh->pSkinInfo->GetBoneName(i);

// Find matching name in frames

D3DXFRAME_EX *pFrame = Parser.m_RootFrame->Find(BoneName);

// Match frame to bone

if(pFrame)

pMesh->ppFrameMatrices[i] = &pFrame->matCombined;

else

pMesh->ppFrameMatrices[i] = NULL;

}

}

// Go to next mesh

pMesh = (D3DXMESHCONTAINER_EX*)pMesh->pNextMeshContainer;

}

}

// Copy the pointers into passed variables

if(ppMesh) {

// Assign mesh list pointer

*ppMesh = Parser.m_RootMesh;

Parser.m_RootMesh = NULL;

} else {

// Delete list of meshes in case any were loaded

// and were not needed.

delete Parser.m_RootMesh;

Parser.m_RootMesh = NULL;

}

if(ppFrame) {

// Assign frame hierarchy pointer

*ppFrame = Parser.m_RootFrame;

Parser.m_RootFrame = NULL;

} else {

// Delete frame hierarchy in case it was loaded

// and it was not needed.

delete Parser.m_RootFrame;

Parser.m_RootFrame = NULL;

}

return S_OK;

}

///////////////////////////////////////////////////////////

//

// Update a skinned mesh

//

///////////////////////////////////////////////////////////

HRESULT UpdateMesh(D3DXMESHCONTAINER_EX *pMesh)

{

// Error checking

if(!pMesh)

return E_FAIL;

if(!pMesh->MeshData.pMesh || !pMesh->pSkinMesh || !pMesh->pSkinInfo)

return E_FAIL;

if(!pMesh->pBoneMatrices || !pMesh->ppFrameMatrices)

return E_FAIL;

// Copy the bone matrices over (must have been combined before call DrawMesh)

for(DWORD i=0;i<pMesh->pSkinInfo->GetNumBones();i++) {

// Start with bone offset matrix

pMesh->pBoneMatrices[i] = (*pMesh->pSkinInfo->GetBoneOffsetMatrix(i));

// Apply frame transformation

if(pMesh->ppFrameMatrices[i])

pMesh->pBoneMatrices[i] *= (*pMesh->ppFrameMatrices[i]);

}

// Lock the meshes' vertex buffers

void *SrcPtr, *DestPtr;

pMesh->MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&SrcPtr);

pMesh->pSkinMesh->LockVertexBuffer(0, (void**)&DestPtr);

// Update the skinned mesh using provided transformations

pMesh->pSkinInfo->UpdateSkinnedMesh(pMesh->pBoneMatrices, NULL, SrcPtr, DestPtr);

// Unlock the meshes vertex buffers

pMesh->pSkinMesh->UnlockVertexBuffer();

pMesh->MeshData.pMesh->UnlockVertexBuffer();

// Return success

return S_OK;

}

///////////////////////////////////////////////////////////

//

// Draw mesh functions

//

///////////////////////////////////////////////////////////

HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh)

{

IDirect3DDevice9 *pD3DDevice;

DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;

// Error checking

if(!pMesh)

return E_FAIL;

if(!pMesh->MeshData.pMesh)

return E_FAIL;

if(!pMesh->NumMaterials || !pMesh->pMaterials)

return E_FAIL;

// Get the device interface

pMesh->MeshData.pMesh->GetDevice(&pD3DDevice);

// Release vertex shader if being used

pD3DDevice->SetVertexShader(NULL);

pD3DDevice->SetVertexDeclaration(NULL);

// Save render states

pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &OldAlphaState);

pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &OldSrcBlend);

pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &OldDestBlend);

LastState = OldAlphaState;

// Setup pointer for mesh to draw, either regular or skinned

ID3DXMesh *pDrawMesh = (!pMesh->pSkinMesh)?pMesh->MeshData.pMesh:pMesh->pSkinMesh;

// Look through all subsets

for(DWORD i=0;i<pMesh->NumMaterials;i++) {

// Set material and texture

pD3DDevice->SetMaterial(&pMesh->pMaterials[i].MatD3D);

pD3DDevice->SetTexture(0, pMesh->pTextures[i]);

// Enable or disable alpha blending per material

if(pMesh->pMaterials[i].MatD3D.Diffuse.a != 1.0f) {

if(LastState != TRUE) {

LastState = TRUE;

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCCOLOR);

pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);

}

} else {

if(LastState != FALSE) {

LastState = FALSE;

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

}

}

// Draw the mesh subset

pDrawMesh->DrawSubset(i);

}

// Restore alpha blending states

if(LastState != OldAlphaState) {

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, OldAlphaState);

pD3DDevice->SetRenderState(D3DRS_SRCBLEND, OldSrcBlend);

pD3DDevice->SetRenderState(D3DRS_DESTBLEND, OldDestBlend);

}

// Make sure to release the device object!

pD3DDevice->Release();

// Return success

return S_OK;

}

HRESULT DrawMesh(D3DXMESHCONTAINER_EX *pMesh,

IDirect3DVertexShader9 *pShader,

IDirect3DVertexDeclaration9 *pDecl)

{

IDirect3DDevice9 *pD3DDevice;

DWORD LastState, OldAlphaState, OldSrcBlend, OldDestBlend;

// Error checking

if(!pMesh || !pShader || !pDecl)

return E_FAIL;

if(!pMesh->MeshData.pMesh)

return E_FAIL;

if(!pMesh->NumMaterials || !pMesh->pMaterials)

return E_FAIL;

// Get the device interface

pMesh->MeshData.pMesh->GetDevice(&pD3DDevice);

// Save render states

pD3DDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &OldAlphaState);

pD3DDevice->GetRenderState(D3DRS_SRCBLEND, &OldSrcBlend);

pD3DDevice->GetRenderState(D3DRS_DESTBLEND, &OldDestBlend);

LastState = OldAlphaState;

// Get mesh buffer pointers

IDirect3DVertexBuffer9 *pVB = NULL;

IDirect3DIndexBuffer9 *pIB = NULL;

pMesh->MeshData.pMesh->GetVertexBuffer(&pVB);

pMesh->MeshData.pMesh->GetIndexBuffer(&pIB);

// Get attribute table

DWORD NumAttributes;

D3DXATTRIBUTERANGE *pAttributes = NULL;

pMesh->MeshData.pMesh->GetAttributeTable(NULL, &NumAttributes);

pAttributes = new D3DXATTRIBUTERANGE[NumAttributes];

pMesh->MeshData.pMesh->GetAttributeTable(pAttributes, &NumAttributes);

// Use the vertex shader interface passed

pD3DDevice->SetFVF(NULL);

pD3DDevice->SetVertexShader(pShader);

pD3DDevice->SetVertexDeclaration(pDecl);

// Set stream sources

pD3DDevice->SetStreamSource(0, pVB, 0, D3DXGetFVFVertexSize(pMesh->MeshData.pMesh->GetFVF()));

pD3DDevice->SetIndices(pIB);

// Go through each attribute group and render

for(DWORD i=0;i<NumAttributes;i++) {

if(pAttributes[i].FaceCount) {

// Get material number

DWORD MatNum = pAttributes[i].AttribId;

// Set texture

pD3DDevice->SetTexture(0, pMesh->pTextures[MatNum]);

// Enable or disable alpha blending per material

if(pMesh->pMaterials[i].MatD3D.Diffuse.a != 1.0f) {

if(LastState != TRUE) {

LastState = TRUE;

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);//SRCCOLOR);

pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);

}

} else {

if(LastState != FALSE) {

LastState = FALSE;

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

}

}

// Draw the mesh subset

pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,

pAttributes[i].VertexStart,

pAttributes[i].VertexCount,

pAttributes[i].FaceStart * 3,

pAttributes[i].FaceCount);

}

}

// Clear stream uses

pD3DDevice->SetStreamSource(0, NULL, 0, 0);

pD3DDevice->SetIndices(NULL);

// Free resources

ReleaseCOM(pVB);

ReleaseCOM(pIB);

delete [] pAttributes;

// Restore alpha blending states

if(LastState != OldAlphaState) {

pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, OldAlphaState);

pD3DDevice->SetRenderState(D3DRS_SRCBLEND, OldSrcBlend);

pD3DDevice->SetRenderState(D3DRS_DESTBLEND, OldDestBlend);

}

// Make sure to release the device object!

pD3DDevice->Release();

// Release vertex shader and declaration mapping

pD3DDevice->SetVertexShader(NULL);

pD3DDevice->SetVertexDeclaration(NULL);

return S_OK;

}

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh)

{

D3DXMESHCONTAINER_EX *MeshPtr = pMesh;

// Loop through all meshes in list

while(MeshPtr) {

// Draw mesh, returning on error

HRESULT hr = DrawMesh(MeshPtr);

if(FAILED(hr))

return hr;

// Go to next mesh

MeshPtr = (D3DXMESHCONTAINER_EX*)MeshPtr->pNextMeshContainer;

}

// Return success

return S_OK;

}

HRESULT DrawMeshes(D3DXMESHCONTAINER_EX *pMesh,

IDirect3DVertexShader9 *pShader,

IDirect3DVertexDeclaration9 *pDecl)

{

D3DXMESHCONTAINER_EX *MeshPtr = pMesh;

// Loop through all meshes in list

while(MeshPtr) {

// Draw mesh, returning on error

HRESULT hr = DrawMesh(MeshPtr, pShader, pDecl);

if(FAILED(hr))

return hr;

// Go to next mesh

MeshPtr = (D3DXMESHCONTAINER_EX*)MeshPtr->pNextMeshContainer;

}

// Return success

return S_OK;

}

///////////////////////////////////////////////////////////

//

// Generic .X parser class code

//

///////////////////////////////////////////////////////////

cXInternalParser::cXInternalParser()

{

m_pD3DDevice = NULL;

m_TexturePath = NULL;

m_Flags = 0;

m_RootMesh = NULL;

m_RootFrame = NULL;

}

cXInternalParser::~cXInternalParser()

{

delete m_RootMesh; m_RootMesh = NULL;

delete m_RootFrame; m_RootFrame = NULL;

}

BOOL cXInternalParser::Parse(char *Filename, void **Data)

{

ID3DXFile *pDXFile = NULL;

ID3DXFileEnumObject *pDXEnum = NULL;

ID3DXFileData *pDXData = NULL;

// Error checking

if(Filename == NULL)

return FALSE;

// Create the file object

if(FAILED(D3DXFileCreate(&pDXFile)))

return FALSE;

// Register the common templates

if(FAILED(pDXFile->RegisterTemplates( /

(LPVOID)D3DRM_XTEMPLATES, /

D3DRM_XTEMPLATE_BYTES))) {

pDXFile->Release();

return FALSE;

}

// Create an enumeration object

if(FAILED(pDXFile->CreateEnumObject((LPVOID)Filename, /

DXFILELOAD_FROMFILE, /

&pDXEnum))) {

pDXFile->Release();

return FALSE;

}

// Loop through all top-level objects, breaking on errors

//BOOL ParseResult;

//while(SUCCEEDED(pDXEnum->GetNextDataObject(&pDXData))) {

// ParseResult = ParseObject(pDXData, NULL, 0, Data, FALSE);

// ReleaseCOM(pDXData);

// if(ParseResult == FALSE)

// break;

//}

SIZE_T num_child;

pDXEnum->GetChildren(&num_child);

BOOL ParseResult;

for(SIZE_T i = 0; i < num_child; i++)

{

if(FAILED(pDXEnum->GetChild(i, &pDXData)))

return NULL;

ParseResult = ParseObject(pDXData, NULL,0,Data,FALSE);

ReleaseCOM(pDXData);

if(ParseResult == FALSE)

break;

}

// Release used COM objects

ReleaseCOM(pDXEnum);

ReleaseCOM(pDXFile);

return TRUE;

}

BOOL cXInternalParser::ParseObject(ID3DXFileData *pDataObj,

ID3DXFileData *pParentDataObj,

DWORD Depth,

void **Data, BOOL Reference)

{

const GUID *Type = GetObjectGUID(pDataObj);

// Process templates based on their type

// Build on to frame hierarchy (ony non-referenced frames)

if(*Type == TID_D3DRMFrame && Reference == FALSE && m_Flags & 2) {

// Allocate a frame

D3DXFRAME_EX *pFrame = new D3DXFRAME_EX();

// Get the frame's name (if any)

pFrame->Name = GetObjectName(pDataObj);

// Link frame into hierarchy

if(Data == NULL) {

// Link as sibling of root

pFrame->pFrameSibling = m_RootFrame;

m_RootFrame = pFrame; pFrame = NULL;

Data = (void**)&m_RootFrame;

} else {

// Link as child of supplied frame

D3DXFRAME_EX *pFramePtr = (D3DXFRAME_EX*)*Data;

pFrame->pFrameSibling = pFramePtr->pFrameFirstChild;

pFramePtr->pFrameFirstChild = pFrame; pFrame = NULL;

Data = (void**)&pFramePtr->pFrameFirstChild;

}

}

// Set a frame transformation matrix

if(*Type == TID_D3DRMFrameTransformMatrix && Reference == FALSE && m_Flags & 2 && Data) {

D3DXFRAME_EX *Frame = (D3DXFRAME_EX*)*Data;

if(Frame) {

Frame->TransformationMatrix = *(D3DXMATRIX*)GetObjectData(pDataObj, NULL);

Frame->matOriginal = Frame->TransformationMatrix;

}

}

// Load a mesh (skinned or regular)

if(*Type == TID_D3DRMMesh && m_Flags & 1) {

// Only load non-referenced skin meshes into memory

if(Reference == FALSE) {

// Load the mesh using the data object load method

D3DXMESHCONTAINER_EX *pMesh = NULL;

LoadMesh(&pMesh, m_pD3DDevice, pDataObj, m_TexturePath, m_NewFVF, m_LoadFlags);

// Link mesh to head of list of meshes

if(pMesh) {

pMesh->pNextMeshContainer = m_RootMesh;

m_RootMesh = pMesh; pMesh = NULL;

// Link mesh to frame if needed

if(Data) {

D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)*Data;

if(m_Flags & 2 && pFrame)

pFrame->pMeshContainer = m_RootMesh;

}

}

} else {

// If referenced, then check if wanting to link to frame

if(Data) {

D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)*Data;

if(m_Flags & 2 && m_RootMesh && pFrame) {

// Get name of mesh reference to link to

char *Name = GetObjectName(pDataObj);

if(Name) {

// Find matching mesh by name and store result

pFrame->pMeshContainer = m_RootMesh->Find(Name);

// Clear name

delete [] Name; Name = NULL;

}

}

}

}

}

// Parse child templates

return ParseChildObjects(pDataObj, Depth, Data, Reference);

}

BOOL cXInternalParser::ParseChildObjects(ID3DXFileData *pDataObj,

DWORD Depth, void **Data,

BOOL ForceReference)

{

ID3DXFileData *pSubObj = NULL;

SIZE_T num_child;

BOOL ParseResult = TRUE;

pDataObj->GetChildren(&num_child);

for(SIZE_T j = 0; j < num_child; j++)

{

pDataObj->GetChild(j, &pSubObj);

if(pSubObj->IsReference()){

ForceReference = true;

}

ParseResult = ParseObject(pSubObj,pDataObj,Depth+1, Data,ForceReference);

ReleaseCOM(pSubObj);

// Return on parsing failure

if(ParseResult == FALSE)

return FALSE;

}

////IDirectXFileObject *pSubObj = NULL;

////ID3DXFileData *pSubData = NULL;

////IDirectXFileDataReference *pDataRef = NULL;

////BOOL ParseResult = TRUE;

////// Scan for embedded templates

////while(SUCCEEDED(pDataObj->GetNextObject(&pSubObj))) {

//// // Process embedded references

//// if(SUCCEEDED(pSubObj->QueryInterface(

//// IID_IDirectXFileDataReference,

//// (void**)&pDataRef))) {

//// // Resolve the data object

//// if(SUCCEEDED(pDataRef->Resolve(&pSubData))) {

//// // Parse the object, remembering the return code

//// ParseResult = ParseObject(pSubData, pDataObj, Depth+1, Data, TRUE);

//// ReleaseCOM(pSubData);

//// }

//// ReleaseCOM(pDataRef);

//// // Return on parsing failure

//// if(ParseResult == FALSE)

//// return FALSE;

//// } else

//// // Process non-referenced embedded templates

//// if(SUCCEEDED(pSubObj->QueryInterface(

//// IID_IDirectXFileData,

//// (void**)&pSubData))) {

//// // Parse the object, remembering the return code

//// ParseResult = ParseObject(pSubData, pDataObj, Depth+1, Data, ForceReference);

//// ReleaseCOM(pSubData);

//// }

//// // Release the data object

//// ReleaseCOM(pSubObj);

//// // Return on parsing failure

//// if(ParseResult == FALSE)

//// return FALSE;

////}

return TRUE;

}

const GUID *cXInternalParser::GetObjectGUID(ID3DXFileData *pDataObj)

{

GUID* Type = new GUID;

// Error checking

if(pDataObj == NULL)

return NULL;

// Get the template type

if(FAILED(pDataObj->GetType(Type)))

return NULL;

return Type;

}

char *cXInternalParser::GetObjectName(ID3DXFileData *pDataObj)

{

char *Name = NULL;

DWORD Size = 0;

// Error checking

if(pDataObj == NULL)

return NULL;

// Get the template name (if any)

if(FAILED(pDataObj->GetName(NULL, &Size)))

return NULL;

// Allocate a name buffer and retrieve name

if(Size) {

if((Name = new char[Size]) != NULL)

pDataObj->GetName(Name, &Size);

}

return Name;

}

void *cXInternalParser::GetObjectData(ID3DXFileData *pDataObj,

DWORD *Size)

{

void *TemplateData;

SIZE_T TemplateSize=0;

// Error checking

if(pDataObj == NULL)

return NULL;

// Get a data pointer to template

//pDataObj->GetData(NULL, &TemplateSize, (PVOID*)&TemplateData);

pDataObj->Lock(&TemplateSize,(LPCVOID*)(VOID **)&TemplateData);

if (NULL==TemplateData)

{

return NULL;

}

// Save size if needed

if(Size != NULL)

*Size = TemplateSize;

return TemplateData;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: