模型节点的缓存
2011-06-03 13:55
211 查看
在游戏中,像树,石头等物体在地图上通常要渲染很多个,如果每个模型都是加载 新资源,这样加载时间会非常长,占用内存也会非常多。所以我们利用缓存来解决这个问题。如果是新资源就加载,如果加载过就读取缓存中的。
我们封装一个类来保存节点的缓存,其中包括Lod的层级模型,文件名(.x),材质层数,材质指针,以及其他的功能的函数:
typedef
class
CDXMeshNode
{
public:
CDXMeshNode(LPDIRECT3DDEVICE9
DVC,void* Parent );
~CDXMeshNode();
LPD3DXMESH
GenMesh;
LPD3DXMESH
LODMeshs[MAXLODLEVEL];
int Index;
D3DMATERIAL9 *mMat;
DWORD mAttCount;
char* mName;
HRESULT QCreate(char* sName);
void QUsing();
void QRelease();
void Render(short
iLOD,bool
UserSelfMat,LPDIRECT3DTEXTURE9* Face);
HRESULT MakeMeshLOD(DWORD* pAdj);
private:
void *mParent;
LPDIRECT3DDEVICE9
mDVC;
int
mRef;
HRESULT LoadFromFile();
}*LPMESHNODE;
我们曾经类CDXMeshBuffer来管理节点类(方便对节点的获取和析构),把节点类存储在一个EasyList中。
class
CDXMeshBuffer
{
public:
CDXMeshBuffer(void){};
public:
~CDXMeshBuffer(void){};
void Init(LPDIRECT3DDEVICE9
DVC);
LPMESHNODE
QCreateMesh(char* sFile);
HRESULT
QReleaseMesh(char* sFile);
DWORD
GetMeshCount();
HRESULT ReleaseAll();
HRESULT DeleteMesh(char* sFile);
private:
LPDIRECT3DDEVICE9
mDVC;
CEasyList
mMeshes;
LPMESHNODE
GetMeshNodeByName(char* sFile);
};
extern
CDXMeshBuffer
gMeshBuffer;
两个类的实现:
CDXMeshNode::CDXMeshNode( LPDIRECT3DDEVICE9
DVC ,void* Parent )
{
mMat=NULL;
Index=-1;
mAttCount=0;;
mName=NULL;
mDVC=DVC;
mParent=Parent;
GenMesh=NULL;
ZeroMemory(LODMeshs,MAXLODLEVEL*sizeof(LPD3DXMESH));
mRef=0;
}
HRESULT
CDXMeshNode::QCreate( char* sName )
{
mName=new
char[strlen(sName)+1];
strcpy(mName,sName);
HRESULT
hr= LoadFromFile();
if (!FAILED(hr))
{
mRef++;
}
return
hr;
}
void
CDXMeshNode::QUsing( )
{
mRef++;
}
void
CDXMeshNode::QRelease()
{
mRef--;
if (mRef<1)
{
if (mParent)
{
((CDXMeshBuffer*)mParent)->DeleteMesh(mName);
}
}
}
CDXMeshNode::~CDXMeshNode( void )
{
if(mRef>0) return ;
if (GenMesh)
{
SAFE_RELEASE(GenMesh);
}
for (int
i=0;i<MAXLODLEVEL;i++)
{
if (LODMeshs[i])
{
SAFE_RELEASE(LODMeshs[i]);
}
}
if (mMat)
{
delete
mMat;
}
if (mName)
{
delete []mName;
mName=NULL;
}
}
HRESULT
CDXMeshNode::LoadFromFile( )
{
HRESULT
hr;
LPD3DXMESH
pMesh;
LPD3DXBUFFER
pAdj;
LPD3DXBUFFER
pMat;
hr=D3DXLoadMeshFromXA(mName,
D3DXMESH_MANAGED, mDVC, &pAdj,
&pMat, NULL, &mAttCount, &pMesh) ;
if (FAILED(hr)) return
hr;
GenMesh=pMesh;
hr=MakeMeshLOD((DWORD*)pAdj->GetBufferPointer());
mMat=new
D3DMATERIAL9[mAttCount];
ZeroMemory(mMat,mAttCount*sizeof(D3DMATERIAL9));
D3DXMATERIAL *pMatList;
pMatList=(D3DXMATERIAL *)pMat->GetBufferPointer();
for (int
i=0;i<mAttCount;i++)
{
mMat[i]=pMatList[i].MatD3D;
mMat[i].Ambient.a=0.3;
mMat[i].Ambient.r=0.3;
mMat[i].Ambient.g=0.3;
mMat[i].Ambient.b=0.3;
}
SAFE_RELEASE(pAdj);
SAFE_RELEASE(pMat);
if (FAILED(hr)) return
hr;
return
S_OK;
}
void
CDXMeshNode::Render( short
iLOD,bool
UserSelfMat,LPDIRECT3DTEXTURE9* Face )
{
for (int
i=0;i<mAttCount;i++)
{
if (!LODMeshs[i])
{
continue;
}
if (UserSelfMat)
{
mDVC->SetMaterial(&mMat[i]);
}
if (Face)
{
mDVC->SetTexture(0,Face[i]);
}
LODMeshs[i]->DrawSubset(i);
}
}
HRESULT
CDXMeshNode::MakeMeshLOD( DWORD* pAdj )
{
HRESULT
hr;
if ((GenMesh==NULL) || (pAdj==NULL) )
{
return
S_FALSE;
}
LPD3DXMESH
pTempMesh =NULL; //临时网格模型变量
//清理
hr = D3DXCleanMesh( D3DXCLEAN_SIMPLIFICATION, GenMesh,pAdj,&pTempMesh,pAdj, NULL ) ;
if (FAILED(hr)) return
hr;
GenMesh->Release();
GenMesh = pTempMesh;
//焊接
D3DXWELDEPSILONS
Epsilons;
ZeroMemory( &Epsilons, sizeof(D3DXWELDEPSILONS) );
Epsilons.Normal=0.01;
Epsilons.Position=0.1;
hr = D3DXWeldVertices( GenMesh,D3DXWELDEPSILONS_WELDPARTIALMATCHES,
&Epsilons,pAdj,pAdj, NULL, NULL );
if (FAILED(hr)) return
hr;
//检查对原始网格模型进行整理、简化之后,还需要检查处理后的网格模型是否有效
hr = D3DXValidMesh( GenMesh, pAdj, NULL );
if (FAILED(hr)) return
hr;
DWORD
MaxVetex=GenMesh->GetNumVertices();
LPD3DXPMESH
ppMesh=NULL;
hr = D3DXGeneratePMesh( GenMesh, pAdj,NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &ppMesh );
if (FAILED(hr)) return
hr;
MaxVetex=GenMesh->GetNumVertices();
for (int
i=0;i<MAXLODLEVEL;i++)
{
ppMesh->SetNumVertices(MaxVetex*0.8);
hr=ppMesh->CloneMeshFVF(ppMesh->GetOptions(),ppMesh->GetFVF(),mDVC,&LODMeshs[i]);
if (FAILED(hr)) return
hr;
MaxVetex=LODMeshs[i]->GetNumVertices();
MaxVetex=ppMesh->GetNumVertices();
if( !(LODMeshs[i]->GetFVF() & D3DFVF_NORMAL) )
{
ID3DXMesh* pTempMesh;
hr=LODMeshs[i]->CloneMeshFVF( LODMeshs[i]->GetOptions(),
LODMeshs[i]->GetFVF() | D3DFVF_NORMAL,
mDVC, &pTempMesh ) ;
SAFE_RELEASE( LODMeshs[i] );
LODMeshs[i] = pTempMesh;
}
hr=D3DXComputeNormals( LODMeshs[i], NULL ) ;
}
SAFE_RELEASE(ppMesh);
return
S_OK;
}
LPMESHNODE
CDXMeshBuffer::QCreateMesh( char* sFile )
{
LPMESHNODE
pMeshNode=NULL;
pMeshNode=GetMeshNodeByName(sFile);
if (!pMeshNode)
{
pMeshNode =new
CDXMeshNode(mDVC,this);
pMeshNode->QCreate(sFile);
mMeshes.Add(pMeshNode);
}else
{
pMeshNode->QUsing();
}
return
pMeshNode;
}
LPMESHNODE
CDXMeshBuffer::GetMeshNodeByName( char* sFile )
{
LPMESHNODE
pMeshNode=NULL;
CListCursor
Cursor;
Cursor.Create(&mMeshes);
pMeshNode=(LPMESHNODE)(Cursor.First());
int
i=0;
while(pMeshNode)
{
if (strcmp(pMeshNode->mName,sFile)==0)
{
pMeshNode->Index=i;
return
pMeshNode;
}
i++;
pMeshNode=(LPMESHNODE)(Cursor.Next());
}
return
NULL;
}
HRESULT
CDXMeshBuffer::QReleaseMesh( char* sFile )
{
return
S_OK;
}
DWORD
CDXMeshBuffer::GetMeshCount()
{
return
mMeshes.Count();
}
HRESULT
CDXMeshBuffer::ReleaseAll()
{
return
S_OK;
}
void
CDXMeshBuffer::Init( LPDIRECT3DDEVICE9
DVC )
{
mDVC=DVC;
}
HRESULT
CDXMeshBuffer::DeleteMesh( char* sFile )
{
LPMESHNODE
pNode=(LPMESHNODE)(GetMeshNodeByName(sFile));
if (pNode>=0)
{
if (pNode->Index>=0)
{
mMeshes.Delete(pNode->Index);
}
delete
pNode;
}
return
S_OK;
}
CDXMeshBuffer
gMeshBuffer;
我们封装一个类来保存节点的缓存,其中包括Lod的层级模型,文件名(.x),材质层数,材质指针,以及其他的功能的函数:
typedef
class
CDXMeshNode
{
public:
CDXMeshNode(LPDIRECT3DDEVICE9
DVC,void* Parent );
~CDXMeshNode();
LPD3DXMESH
GenMesh;
LPD3DXMESH
LODMeshs[MAXLODLEVEL];
int Index;
D3DMATERIAL9 *mMat;
DWORD mAttCount;
char* mName;
HRESULT QCreate(char* sName);
void QUsing();
void QRelease();
void Render(short
iLOD,bool
UserSelfMat,LPDIRECT3DTEXTURE9* Face);
HRESULT MakeMeshLOD(DWORD* pAdj);
private:
void *mParent;
LPDIRECT3DDEVICE9
mDVC;
int
mRef;
HRESULT LoadFromFile();
}*LPMESHNODE;
我们曾经类CDXMeshBuffer来管理节点类(方便对节点的获取和析构),把节点类存储在一个EasyList中。
class
CDXMeshBuffer
{
public:
CDXMeshBuffer(void){};
public:
~CDXMeshBuffer(void){};
void Init(LPDIRECT3DDEVICE9
DVC);
LPMESHNODE
QCreateMesh(char* sFile);
HRESULT
QReleaseMesh(char* sFile);
DWORD
GetMeshCount();
HRESULT ReleaseAll();
HRESULT DeleteMesh(char* sFile);
private:
LPDIRECT3DDEVICE9
mDVC;
CEasyList
mMeshes;
LPMESHNODE
GetMeshNodeByName(char* sFile);
};
extern
CDXMeshBuffer
gMeshBuffer;
两个类的实现:
CDXMeshNode::CDXMeshNode( LPDIRECT3DDEVICE9
DVC ,void* Parent )
{
mMat=NULL;
Index=-1;
mAttCount=0;;
mName=NULL;
mDVC=DVC;
mParent=Parent;
GenMesh=NULL;
ZeroMemory(LODMeshs,MAXLODLEVEL*sizeof(LPD3DXMESH));
mRef=0;
}
HRESULT
CDXMeshNode::QCreate( char* sName )
{
mName=new
char[strlen(sName)+1];
strcpy(mName,sName);
HRESULT
hr= LoadFromFile();
if (!FAILED(hr))
{
mRef++;
}
return
hr;
}
void
CDXMeshNode::QUsing( )
{
mRef++;
}
void
CDXMeshNode::QRelease()
{
mRef--;
if (mRef<1)
{
if (mParent)
{
((CDXMeshBuffer*)mParent)->DeleteMesh(mName);
}
}
}
CDXMeshNode::~CDXMeshNode( void )
{
if(mRef>0) return ;
if (GenMesh)
{
SAFE_RELEASE(GenMesh);
}
for (int
i=0;i<MAXLODLEVEL;i++)
{
if (LODMeshs[i])
{
SAFE_RELEASE(LODMeshs[i]);
}
}
if (mMat)
{
delete
mMat;
}
if (mName)
{
delete []mName;
mName=NULL;
}
}
HRESULT
CDXMeshNode::LoadFromFile( )
{
HRESULT
hr;
LPD3DXMESH
pMesh;
LPD3DXBUFFER
pAdj;
LPD3DXBUFFER
pMat;
hr=D3DXLoadMeshFromXA(mName,
D3DXMESH_MANAGED, mDVC, &pAdj,
&pMat, NULL, &mAttCount, &pMesh) ;
if (FAILED(hr)) return
hr;
GenMesh=pMesh;
hr=MakeMeshLOD((DWORD*)pAdj->GetBufferPointer());
mMat=new
D3DMATERIAL9[mAttCount];
ZeroMemory(mMat,mAttCount*sizeof(D3DMATERIAL9));
D3DXMATERIAL *pMatList;
pMatList=(D3DXMATERIAL *)pMat->GetBufferPointer();
for (int
i=0;i<mAttCount;i++)
{
mMat[i]=pMatList[i].MatD3D;
mMat[i].Ambient.a=0.3;
mMat[i].Ambient.r=0.3;
mMat[i].Ambient.g=0.3;
mMat[i].Ambient.b=0.3;
}
SAFE_RELEASE(pAdj);
SAFE_RELEASE(pMat);
if (FAILED(hr)) return
hr;
return
S_OK;
}
void
CDXMeshNode::Render( short
iLOD,bool
UserSelfMat,LPDIRECT3DTEXTURE9* Face )
{
for (int
i=0;i<mAttCount;i++)
{
if (!LODMeshs[i])
{
continue;
}
if (UserSelfMat)
{
mDVC->SetMaterial(&mMat[i]);
}
if (Face)
{
mDVC->SetTexture(0,Face[i]);
}
LODMeshs[i]->DrawSubset(i);
}
}
HRESULT
CDXMeshNode::MakeMeshLOD( DWORD* pAdj )
{
HRESULT
hr;
if ((GenMesh==NULL) || (pAdj==NULL) )
{
return
S_FALSE;
}
LPD3DXMESH
pTempMesh =NULL; //临时网格模型变量
//清理
hr = D3DXCleanMesh( D3DXCLEAN_SIMPLIFICATION, GenMesh,pAdj,&pTempMesh,pAdj, NULL ) ;
if (FAILED(hr)) return
hr;
GenMesh->Release();
GenMesh = pTempMesh;
//焊接
D3DXWELDEPSILONS
Epsilons;
ZeroMemory( &Epsilons, sizeof(D3DXWELDEPSILONS) );
Epsilons.Normal=0.01;
Epsilons.Position=0.1;
hr = D3DXWeldVertices( GenMesh,D3DXWELDEPSILONS_WELDPARTIALMATCHES,
&Epsilons,pAdj,pAdj, NULL, NULL );
if (FAILED(hr)) return
hr;
//检查对原始网格模型进行整理、简化之后,还需要检查处理后的网格模型是否有效
hr = D3DXValidMesh( GenMesh, pAdj, NULL );
if (FAILED(hr)) return
hr;
DWORD
MaxVetex=GenMesh->GetNumVertices();
LPD3DXPMESH
ppMesh=NULL;
hr = D3DXGeneratePMesh( GenMesh, pAdj,NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &ppMesh );
if (FAILED(hr)) return
hr;
MaxVetex=GenMesh->GetNumVertices();
for (int
i=0;i<MAXLODLEVEL;i++)
{
ppMesh->SetNumVertices(MaxVetex*0.8);
hr=ppMesh->CloneMeshFVF(ppMesh->GetOptions(),ppMesh->GetFVF(),mDVC,&LODMeshs[i]);
if (FAILED(hr)) return
hr;
MaxVetex=LODMeshs[i]->GetNumVertices();
MaxVetex=ppMesh->GetNumVertices();
if( !(LODMeshs[i]->GetFVF() & D3DFVF_NORMAL) )
{
ID3DXMesh* pTempMesh;
hr=LODMeshs[i]->CloneMeshFVF( LODMeshs[i]->GetOptions(),
LODMeshs[i]->GetFVF() | D3DFVF_NORMAL,
mDVC, &pTempMesh ) ;
SAFE_RELEASE( LODMeshs[i] );
LODMeshs[i] = pTempMesh;
}
hr=D3DXComputeNormals( LODMeshs[i], NULL ) ;
}
SAFE_RELEASE(ppMesh);
return
S_OK;
}
LPMESHNODE
CDXMeshBuffer::QCreateMesh( char* sFile )
{
LPMESHNODE
pMeshNode=NULL;
pMeshNode=GetMeshNodeByName(sFile);
if (!pMeshNode)
{
pMeshNode =new
CDXMeshNode(mDVC,this);
pMeshNode->QCreate(sFile);
mMeshes.Add(pMeshNode);
}else
{
pMeshNode->QUsing();
}
return
pMeshNode;
}
LPMESHNODE
CDXMeshBuffer::GetMeshNodeByName( char* sFile )
{
LPMESHNODE
pMeshNode=NULL;
CListCursor
Cursor;
Cursor.Create(&mMeshes);
pMeshNode=(LPMESHNODE)(Cursor.First());
int
i=0;
while(pMeshNode)
{
if (strcmp(pMeshNode->mName,sFile)==0)
{
pMeshNode->Index=i;
return
pMeshNode;
}
i++;
pMeshNode=(LPMESHNODE)(Cursor.Next());
}
return
NULL;
}
HRESULT
CDXMeshBuffer::QReleaseMesh( char* sFile )
{
return
S_OK;
}
DWORD
CDXMeshBuffer::GetMeshCount()
{
return
mMeshes.Count();
}
HRESULT
CDXMeshBuffer::ReleaseAll()
{
return
S_OK;
}
void
CDXMeshBuffer::Init( LPDIRECT3DDEVICE9
DVC )
{
mDVC=DVC;
}
HRESULT
CDXMeshBuffer::DeleteMesh( char* sFile )
{
LPMESHNODE
pNode=(LPMESHNODE)(GetMeshNodeByName(sFile));
if (pNode>=0)
{
if (pNode->Index>=0)
{
mMeshes.Delete(pNode->Index);
}
delete
pNode;
}
return
S_OK;
}
CDXMeshBuffer
gMeshBuffer;
相关文章推荐
- 清空FPS摄像机和摄像机的子节点模型动作的缓存的函数方法
- [编程思想]领域模型和缓存应用【一】
- 采用DOM模型时创建一个Select节点后,要删除option项的解决方法
- ehcache jgroups同步,节点重启初始化缓存bug.
- memcache client缓存节点分配机制和连接读取缓存机制
- JavaScript实现TwoQueues缓存模型
- 多节点CDN缓存加速系统wdcdn1.5版本发布
- 内存In-memory模型 缓存Cache
- 分布式缓存技术redis学习系列(二)——详细讲解redis数据结构(内存模型)以及常用命令
- 数据库(1):配置数据的缓存建立方法,独立数据表模型
- 节点(个体)级SIS模型python代码
- JS(六)DOM模型之节点
- 树模型的类节点
- dom 节点(文档对象模型)详细介绍
- Zookeeper系列(4)--ZK概述,数据模型,节点特性,Watcher机制、ACL及数据存储
- session-缓存-分布式会话session共享、多节点部署session共享解决方案
- 2 weekend110的zookeeper的原理、特性、数据模型、节点、角色、顺序号、读写机制、保证、API接口、ACL、选举、 + 应用场景:统一命名服务、配置管理、集群管理、共享锁、队列管理
- [编程思想]领域模型和缓存应用【二】
- Tubes类(利用顶点缓存生成圆柱体,主要应用地下管网等模型)
- 多节点CDN缓存加速系统wdcdn2.2版本发布(20111115)