📄 direct3d.cpp
字号:
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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -