|
我自己写了一个CModeD3D的类(主要就是对ID3DXMesh的封装),里面主要涉及到顶点、索引缓冲区的填充,邻接数组的优化,子集的创建和顶点法线的生成。这个类单独使用创建一个模型的时候没有问题,但是被其他的类组合着来使用的时候就出现问题了,问题就出在所有与邻接数组有关的操作中,比如GenerateAdjacency、OptimizeInplace和D3DXComputeNormals,总要因为空的引用而中断,不知道为什么,单独使用的时候没有问题,被组合着用就出现问题了,但我就是找不出什么地方出现了空的引用,如果是代码问题那单独使用的时候应该也要报错才对。
我把这个类贴出来,希望高手能帮我解决一下,小弟是在不知道什么地方出错了。
头文件:
#ifndef MODE_H
#define MODE_H
#include <d3dx9.h>
#include <vector>
using std::vector;
class CModeD3D
{
private:
struct SModeMatTex
{
D3DMATERIAL9 m_material;
IDirect3DTexture9* m_pTexture;
};
private:
IDirect3DDevice9* m_pDevice;
vector<SModeMatTex*> m_vMatTex;
ID3DXMesh* m_pMesh;
DWORD m_dwFVF;
ID3DXBuffer* m_pAdjacency;
ID3DXBuffer* m_pMaterial;
int m_nMatNum;
public:
CModeD3D(IDirect3DDevice9* pDevice)
:m_pDevice(pDevice),m_dwFVF(NULL),m_pMesh(NULL),m_pAdjacency(NULL),m_pMaterial(NULL),m_nMatNum(0)
{};
~CModeD3D();
void InitMode(DWORD, void*, int, DWORD, DWORD, DWORD=D3DXMESH_MANAGED);
void InitMode(DWORD, void*, int, void*, int, DWORD, DWORD, DWORD=D3DXMESH_MANAGED);
void InitMode(DWORD, DWORD, DWORD, DWORD=D3DXMESH_MANAGED);
void InitVertex(void*, int);
void InitIndex(void*, int);
void AddSubset(D3DMATERIAL9, TCHAR*, int, int);
void AddSubset(D3DMATERIAL9, TCHAR*, int*, int);
void LoadMode(TCHAR*, DWORD=D3DXMESH_MANAGED);
void OptimizeMesh(DWORD=D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_COMPACT|D3DXMESHOPT_VERTEXCACHE);
void CreateNormal(bool=false);
ID3DXMesh* GetMesh(){ return m_pMesh; };
void DrawVertex();
void DrawIndex();
void DrawSubset();
};
#endif
实现文件:
#include "mode.h"
CModeD3D::~CModeD3D()
{
int nCount = m_vMatTex.size();
for (int i=0; i<nCount; i++) delete m_vMatTex;
}
void CModeD3D::InitMode(DWORD dwFVF, void* pData, int nBytes, DWORD dwFaceNum, DWORD dwVertexNum, DWORD dwOption)
{
m_dwFVF = dwFVF;
if (m_pMesh!=NULL) m_pMesh->Release();
D3DXCreateMeshFVF(dwFaceNum, dwVertexNum, dwOption, m_dwFVF, m_pDevice, &m_pMesh);
void* pBuffer;
m_pMesh->LockVertexBuffer(0, &pBuffer);
memcpy(pBuffer, pData, nBytes);
m_pMesh->UnlockVertexBuffer();
}
void CModeD3D::InitMode(DWORD dwFVF, void* pVertex, int nVertexBytes, void* pIndex, int nIndexBytes,
DWORD dwFaceNum, DWORD dwVertexNum, DWORD dwOption)
{
m_dwFVF = dwFVF;
if (m_pMesh!=NULL) m_pMesh->Release();
D3DXCreateMeshFVF(dwFaceNum, dwVertexNum, dwOption, m_dwFVF, m_pDevice, &m_pMesh);
void* pBuffer;
m_pMesh->LockVertexBuffer(0, &pBuffer);
memcpy(pBuffer, pVertex, nVertexBytes);
m_pMesh->UnlockVertexBuffer();
m_pMesh->LockIndexBuffer(0, &pBuffer);
memcpy(pBuffer, pIndex, nIndexBytes);
m_pMesh->UnlockIndexBuffer();
}
void CModeD3D::InitMode(DWORD dwFVF, DWORD dwFaceNum, DWORD dwVertexNum, DWORD dwOption)
{
m_dwFVF = dwFVF;
if (m_pMesh!=NULL) m_pMesh->Release();
D3DXCreateMeshFVF(dwFaceNum, dwVertexNum, dwOption, m_dwFVF, m_pDevice, &m_pMesh);
}
void CModeD3D::InitVertex(void* pVertex, int nBytes)
{
void* pBuffer;
m_pMesh->LockVertexBuffer(0, &pBuffer);
memcpy(pBuffer, pVertex, nBytes);
m_pMesh->UnlockVertexBuffer();
}
void CModeD3D::InitIndex(void* pIndex, int nBytes)
{
void* pBuffer;
m_pMesh->LockIndexBuffer(0, &pBuffer);
memcpy(pBuffer, pIndex, nBytes);
m_pMesh->UnlockIndexBuffer();
}
void CModeD3D::AddSubset(D3DMATERIAL9 material, TCHAR* szPath, int nStart, int nEnd)
{
SModeMatTex* pMT = new SModeMatTex;
pMT->m_material = material;
if (szPath==NULL) pMT->m_pTexture=NULL;
else D3DXCreateTextureFromFile(m_pDevice, szPath, &pMT->m_pTexture);
DWORD* pAttrib = new DWORD[m_pMesh->GetNumFaces()];
m_pMesh->LockAttributeBuffer(0, &pAttrib);
int nSubsetID = m_vMatTex.size();
for (int i=nStart; i<=nEnd; i++) pAttrib=nSubsetID;
m_pMesh->UnlockAttributeBuffer();
m_vMatTex.push_back(pMT);
}
void CModeD3D::AddSubset(D3DMATERIAL9 material, TCHAR* szPath, int* pIndex, int nSize)
{
SModeMatTex* pMT = new SModeMatTex;
pMT->m_material = material;
if (szPath==NULL) pMT->m_pTexture=NULL;
else D3DXCreateTextureFromFile(m_pDevice, szPath, &pMT->m_pTexture);
DWORD* pAttrib = new DWORD[m_pMesh->GetNumFaces()];
m_pMesh->LockAttributeBuffer(0, &pAttrib);
int nSubsetID = m_vMatTex.size();
for (int i=0; i<nSize; i++) pAttrib[pIndex]=nSubsetID;
m_pMesh->UnlockAttributeBuffer();
m_vMatTex.push_back(pMT);
}
void CModeD3D: oadMode(TCHAR* szPath, DWORD dwOption)
{
if (m_pAdjacency!=NULL) m_pAdjacency->Release();
if (m_pMaterial!=NULL) m_pMaterial->Release();
if (m_pMesh!=NULL) m_pMesh->Release();
D3DXLoadMeshFromX(szPath, dwOption, m_pDevice, &m_pAdjacency, &m_pMaterial, 0, (DWORD*)&m_nMatNum, &m_pMesh);
if (m_pMaterial==NULL || m_nMatNum==0) return;
D3DXMATERIAL* pMaterial = (D3DXMATERIAL*)m_pMaterial->GetBufferPointer();
for (int i=0; i<m_nMatNum; i++)
{
SModeMatTex* pMT = new SModeMatTex;
pMaterial.MatD3D.Ambient = (D3DXCOLOR)pMaterial.MatD3D.Diffuse*0.4f;
pMT->m_material = pMaterial.MatD3D;
if (pMaterial.pTextureFilename==NULL) pMT->m_pTexture=NULL;
else D3DXCreateTextureFromFile(m_pDevice, pMaterial.pTextureFilename, &pMT->m_pTexture);
m_vMatTex.push_back(pMT);
}
}
void CModeD3D::OptimizeMesh(DWORD dwOption)
{
if (m_pAdjacency!=NULL) m_pAdjacency->Release();
D3DXCreateBuffer(3*m_pMesh->GetNumFaces()*sizeof(DWORD), &m_pAdjacency);
m_pMesh->GenerateAdjacency(0, (DWORD*)m_pAdjacency->GetBufferPointer()); // 主要就在这个地方出错
m_pMesh->OptimizeInplace(dwOption, (DWORD*)m_pAdjacency->GetBufferPointer(), 0, 0, 0); // 如果上面的被注释掉了那这里就出错
m_pAdjacency->Release();
D3DXCreateBuffer(3*m_pMesh->GetNumFaces()*sizeof(DWORD), &m_pAdjacency);
m_pMesh->GenerateAdjacency(0, (DWORD*)m_pAdjacency->GetBufferPointer()); // 如果上面两个都被注释掉了那这里就报错
}
void CModeD3D::CreateNormal(bool bAdj)
{
if (!(m_pMesh->GetFVF() & D3DFVF_NORMAL))
{
ID3DXMesh* pTmpMesh = 0;
m_pMesh->CloneMeshFVF(D3DXMESH_MANAGED, m_pMesh->GetFVF()|D3DFVF_NORMAL, m_pDevice, &pTmpMesh);
if(bAdj) D3DXComputeNormals(pTmpMesh, (DWORD*)m_pAdjacency->GetBufferPointer());
else D3DXComputeNormals(pTmpMesh, 0);
m_pMesh->Release();
m_pMesh = pTmpMesh;
}
else
{
if(bAdj) D3DXComputeNormals(m_pMesh, (DWORD*)m_pAdjacency->GetBufferPointer());
else D3DXComputeNormals(m_pMesh, 0);
}
} // 如果直接不用OptimizeMesh方法那就直接在这里中断
void CModeD3D: rawVertex()
{
IDirect3DVertexBuffer9* pVB = 0;
m_pMesh->GetVertexBuffer(&pVB);
m_pDevice->SetStreamSource(0, pVB, 0, D3DXGetFVFVertexSize(m_dwFVF));
m_pDevice->SetFVF(m_dwFVF);
m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, m_pMesh->GetNumFaces());
}
void CModeD3D::DrawIndex()
{
int nCount = m_vMatTex.size();
for (int i=0; i<nCount; i++) m_pMesh->DrawSubset(i);
}
void CModeD3D::DrawSubset()
{
int nCount = m_vMatTex.size();
for (int i=0; i<nCount; i++)
{
m_pDevice->SetMaterial(&m_vMatTex->m_material);
m_pDevice->SetTexture(0, m_vMatTex->m_pTexture);
m_pMesh->DrawSubset(i);
}
}
PS:请大大们帮帮忙,小弟感激不尽!!!!
|
|