您的位置:首页 > 其它

模型节点的缓存

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