最近在看《Real Time 3D Terrain Engines Using C++And DirectX 9》,不過是看網上翻譯的版本叫《實時地形引擎》,看英文實在蛋疼,還好有翻譯版的,要多多感謝承天一大哥!這本書講解了地形制作的一些技術,更吸引人的是實現了一個小型的渲染引擎,對於我這樣的游戲引擎初學者很適合。gaia正是書中構建的引擎的名字。這里來寫寫一些簡單的分析,作為學習筆記。
(一)資源管理
1、 data_pool.h
cPoolGroup:模板類,池組,顧名思義,就是裝載一組數據的對象
template <class T>
class cPoolGroup
{
public:
cPoolGroup(uint16 maxCount);
~cPoolGroup(){};
void create();
void destroy();
uint16 addMember(const T& member);
uint16 nextMember();
void release(uint16 index);
uint16 totalOpen()const;
uint16 totalUsed()const;
uint16 firstOpen()const;
bool isOpen(uint16 index)const;
T& member(uint16 index);
const T& member(uint16 index)const;
T* memberPtr(uint16 index);
const T* memberPtr(uint16 index)const;
private:
uint16 m_totalOpen;
uint16 m_firstOpen;
uint16 m_maxCount;
uint16* m_nextOpenList;
T* m_memberList;//數據對象鏈表
};
cDataPoolInterface:數據池接口,抽象類
class cDataPoolInterface
{
public:
typedef void (*MEMBER_CALLBACK)(cDataPoolInterface* pPool, cPoolHandle handle, void* member);
cDataPoolInterface():m_initialized(false){};
virtual ~cDataPoolInterface(){};
virtual void initialize(uint16 growSize)=0;;
virtual void destroy()=0;;
virtual void clear()=0;
virtual cPoolHandle nextHandle()=0;
virtual void release(cPoolHandle* pHandle)=0;
virtual void forEach(MEMBER_CALLBACK function)=0;
virtual void* getGenericPtr(cPoolHandle index)=0;
bool isInitialized()const {return m_initialized;}
protected:
bool m_initialized;
};
cDataPool:模板類,繼承自cDataPoolInterface,數據池,它包括了若干個cPoolGroup
template <class T>
class cDataPool : public cDataPoolInterface
{
public:
// Data Types & Constants...
typedef T DATA_TYPE;
typedef cPoolGroup<T> MemberGroup;
typedef std::list<MemberGroup*> MemberGroupList;
typedef cDataPoolInterface::MEMBER_CALLBACK MEMBER_CALLBACK;
// Creators...
cDataPool();
~cDataPool();
void initialize(uint16 growSize);
void destroy();
const T& operator[](cPoolHandle handle)const {return get(handle);}
T& operator[](cPoolHandle handle) {return get(handle);}
// Mutators...
cPoolHandle add(const T& member);
void clear();
cPoolHandle nextHandle();
void release(cPoolHandle* pHandle);
void forEach(MEMBER_CALLBACK function);
// Accessors...
bool isHandleValid(cPoolHandle index)const;
const T& get(cPoolHandle index)const;
T* getPtr(cPoolHandle index);
void* getGenericPtr(cPoolHandle index);
uint16 totalMembers()const {return m_totalMembers;}
uint16 totalOpen()const {return m_totalOpen;}
uint16 totalUsed()const {return m_totalMembers-m_totalOpen;}
private:
// Private Data...
MemberGroupList m_groupList;// cPoolGroup鏈表
uint16 m_totalMembers;
uint16 m_totalOpen;
uint16 m_groupCount;
uint32 m_indexMask;
int m_indexShift;
// Private Functions...
explicit cDataPool(const cDataPool& Src);
cDataPool& operator=(const cDataPool& Src);
cPoolGroup<T>* addGroup();
cPoolGroup<T>* findOpenGroup(unsigned* groupNumber);
cPoolGroup<T>* getGroup(unsigned index);
const cPoolGroup<T>* getGroup(unsigned index)const;
int getGroupNumber(cPoolHandle handle)const;
int getItemIndex(cPoolHandle handle)const;
cPoolHandle buildHandle(int group, int index)const;
};
2、 resource_pool.h
cResourcePoolInterface:資源池接口,抽象類
class cResourcePoolInterface
{
public:
union FILE_EXTENSION
{
char ext[4];
uint32 fourcc;
};
typedef std::map<cString, cPoolHandle> NAME_LOOKUP_MAP;
cResourcePoolInterface();
virtual ~cResourcePoolInterface(){};
// these functions must be proviided in the derived class (cResourceType)
virtual void initialize(uint16 growSize)=0;
virtual void destroy()=0;
virtual bool isInitialized()const=0;
virtual void destroyAll()=0;
virtual void disableAll()=0;
virtual void restoreAll()=0;
virtual void clean()=0;
cResourcePoolItem* createResource(const cString& resourceName);
cResourcePoolItem* loadResource(const cString& filename);
cResourcePoolItem* getResource(cPoolHandle handle);
cResourcePoolItem* findResource(const cString& Name);
void destroyResource(cResourcePoolItem* pResource);
bool saveResource(cResourcePoolItem* pResource);
cPoolHandle findResourceHandle(const cString& Name);
const cString* findResourceName(cPoolHandle handle)const;
void setResourceName(cPoolHandle handle, const tchar* name);
void registerResourcePool(cResourceCode code);
void unregisterResourcePool();
cResourceCode registrationCode()const;
protected:
cResourceCode m_registrationCode;
NAME_LOOKUP_MAP m_nameMap;
private:
// Private Functions...
virtual cPoolHandle internalCreateResource(const cString& resourceName)=0;
virtual void internalDestroyResource(cPoolHandle handle)=0;
virtual cResourcePoolItem* internalGetResource(cPoolHandle handle)=0;
};
cResourcePool:模板類,資源池,繼承自cResourcePoolInterface,成員中有一個DataPool可以看做是DataPool的擴充。
template <class T>
class cResourcePool : public cResourcePoolInterface
{
public:
typedef T DataType;
typedef cDataPool<T> DataPool;
// Creators...
cResourcePool(){};
~cResourcePool(){};
// Base Class Overrides...
void initialize(uint16 growSize);
void destroy();
bool isInitialized()const;
void destroyAll();
void disableAll();
void restoreAll();
void clean(); // delete items no longer referenced
DataType* createResource(const cString& resourceName);
DataType* loadResource(const cString& filename);
DataType* getResource(cPoolHandle handle);
DataType* findResource(const cString& Name);
// static data pool callbacks
static void callbackDestroy(cDataPoolInterface* pPool, cPoolHandle handle, void* resource);
static void callbackRestore(cDataPoolInterface* pPool, cPoolHandle handle, void* resource);
static void callbackDisable(cDataPoolInterface* pPool, cPoolHandle handle, void* resource);
static void callbackClean(cDataPoolInterface* pPool, cPoolHandle handle, void* resource);
private:
// Data...
DataPool m_dataPool;
// Private Functions...
cPoolHandle internalCreateResource(const cString& resourceName);
void internalDestroyResource(cPoolHandle handle);
cResourcePoolItem* internalGetResource(cPoolHandle handle);
// Nonexistant Functions...
cResourcePool( const cResourcePool& Src);
cResourcePool& operator=( const cResourcePool& Src);
};
cResourcePoolItem:資源池對象繼承自cReferenceCounter
關於cReferenceCounter上一段英文:
/* cResourcePoolItem
------------------------------------------------------------------------------------------
A cResourcePoolItem is a simple base class for a shared resource such as a texture,
animation or vertex buffer.
Note that cResourcePoolItem is derived from cReferenceCounter. The cResourcePoolManager uses
the value of the cReferenceCounter to decide when objects are no longer in use and can
be destroyed during the cResourcePoolManager::clean() function. This means the application
must update the reference count of the cResourcePoolItem whenever links between objects
are created or removed between objects. The cReferenceCounter base class provides the
functionality to manipulate the reference count.
------------------------------------------------------------------------------------------
*/
class cResourcePoolItem : public cReferenceCounter
{
public:
// Data Types & Constants...
enum
{
nCreated=0, // the resource has been created
nLoaded, // the resource is filled with data and ready for use
nDisabled, // the resource is currently disabled for use
nAltered, // the resource has been altered since loaded
nTotalResourceFlags
};
// Creators...
cResourcePoolItem();
virtual ~cResourcePoolItem();
// User Functions
// These function prototypes are to be used by resources that use volatile or system-specific resources.
// Examples would be video-memory resident textures or hardware vertex buffers.
virtual bool createResource()=0; // innitialize the resource (called once)
virtual bool destroyResource()=0; // destroy the resource
virtual bool disableResource()=0; // purge the resource from volatile memory
virtual bool restoreResource()=0; // restore the resource to volatile memory
virtual bool loadResource(const tchar* filename=0)=0; // load the resource from a file (or NULL to use the resource name)
virtual bool saveResource(const tchar* filename=0)=0; // save the resource to a file (or NULL to use the resource name)
// Accessors...
cResourceCode resourceCode()const;
cResourcePoolInterface* resourcePool()const;
cPoolHandle resourceHandle()const;
u32Flags resourceFlags()const;
bool isResourceCreated()const;
bool isResourceDisabled()const;
bool isResourceLoaded()const;
const cString* findResourceName()const;
void setResourceName(const tchar* name);
void setAlteredFlag(bool onOff);
bool alteredFlag()const;
// mimic COM interfaces
virtual int32 Release();
protected:
// only derrived classes are permitted to modify internal members
void setResourceCode(cResourceCode code);
void setResourcePool(cResourcePoolInterface* interfaePtr);
void setResourceHandle(cPoolHandle handle);
void setResourceFlag(int flagBit, bool Setting);
void notifyCreated();
void notifyDisabled();
void notifyLoaded();
void notifyUnloaded();
void notifyRestored();
void notifyDestroyed();
void notifySaved();
private:
// Data...
cResourceCode m_resourceCode;
cResourcePoolInterface* m_resourcePool;
cPoolHandle m_resourceHandle;
u32Flags m_resourceFlags;
// Private Functions...
// Nonexistant Functions...
cResourcePoolItem( const cResourcePoolItem& Src);
cResourcePoolItem& operator=( const cResourcePoolItem& Src);
friend cResourcePoolInterface;
};
cReferenceCounter:。。(我沒太理解它的作用,望大蝦指點。。)
/* cReferenceCounter
-----------------------------------------------------------------
A cReferenceCounter is a base class which allows the program
to count open instances.
-----------------------------------------------------------------
*/
class cReferenceCounter
{
public:
// Construction and Destruction...
cReferenceCounter()
{
m_nReferenceCount = 0;
}
cReferenceCounter( const cReferenceCounter& Src)
{
// Reference counts are tied to a specific instance
// i.e. they are never copied
m_nReferenceCount = 0;
}
virtual ~cReferenceCounter()
{
// assert if this object is still in use
assert(m_nReferenceCount == 0);
}
// Operators...
cReferenceCounter& operator=(const cReferenceCounter& Src)
{
// this function is provided in order to allow
// derived classes to provide copy operators.
// the reference count itself is never copied.
return *this;
}
// Mutators...
virtual int32 AddRef()
{
assert(m_nReferenceCount != MAX_INT32);
++m_nReferenceCount;
return(m_nReferenceCount);
};
virtual int32 Release()
{
assert(m_nReferenceCount > 0);
--m_nReferenceCount;
return(m_nReferenceCount);
}
// Accessors...
int32 referenceCount()const {return m_nReferenceCount;}
private:
// the internal reference count, stored in 32bits
int32 m_nReferenceCount;
};
cResourcePoolManager:單件類,資源管理器,負責申請資源池,找到資源等資源管理功能。
class cResourcePoolManager : public cSingleton<cResourcePoolManager>
{
public:
typedef std::map<cResourceCode, cResourcePoolInterface*> ResourcePoolTypeMap;
typedef std::list<cResourcePoolInterface*> ResourcePoolFamilyList;
// Creators...
cResourcePoolManager();
~cResourcePoolManager(){};
// registration of resource manager interfaces
void registerResourcePool(cResourceCode code, cResourcePoolInterface* pInterface);
cResourcePoolInterface* unregisterResourcePool(cResourceCode code);
// operations for all resource types
void destroyAll();
void disableAll();
void restoreAll();
void clean(); // delete items no longer referenced
// operations on specific resource types
void destroyResourceFamily(int family);
void disableResourceFamily(int family);
void restoreResourceFamily(int family);
void cleanResourceFamily(int family);
void destroyResourceType(cResourceCode code);
void disableResourceType(cResourceCode code);
void restoreResourceType(cResourceCode code);
void cleanResourceType(cResourceCode code);
cResourcePoolInterface* findResourcePool(cResourceCode code)const;
cPoolHandle findResourceHandle(cResourceCode code, const cString& Name)const;
cResourcePoolItem* findResource(cResourceCode code, const cString& Name)const;
cResourcePoolItem* findResource(cResourceCode code, cPoolHandle handle)const;
private:
ResourcePoolFamilyList m_resourceFamilyList[k_nTotalResourceFamilies];
ResourcePoolTypeMap m_resourceTypeMap;
};
引擎中所有的資源都派生自cResourcePoolItem,也可以說是對D3D資源類的封裝。例如:texture.h里的cTexture:
class cTexture : public cResourcePoolItem
{
public:
// Data Types & Constants...
enum eTextureFlags
{
k_cubeMap=0,
k_dynamicTexture,
k_renderTarget,
k_paletized,
k_mipMaps,
};
enum eForcedFormatFlags
{
k_forceMipLevels=0,
k_forceFormat,
k_forceSize,
};
// Creators...
cTexture();
~cTexture();
// base resource overrides
bool createResource(); // innitialize the resource (called once)
bool destroyResource(); // destroy the resource
bool disableResource(); // purge the resource from volatile memory
bool restoreResource(); // prepare the resource for use (create any volatile memory objects needed)
bool loadResource(const tchar* filename=0); // load the resource from a file (or NULL to use the resource name)
bool saveResource(const tchar* filename=0); // save the resource to a file (or NULL to use the resource name)
bool createTexture(uint32 width, uint32 height, uint32 mipLevels, uint32 usage, D3DFORMAT Format, D3DPOOL pool);
bool createCubeTexture(uint32 size, uint32 mipLevels, uint32 usage, D3DFORMAT Format, D3DPOOL pool);
void generateMidpointNoise(float falloff);
void generatePerlinNoise(float scale, int octaves, float falloff);
bool generateNormalMap(LPDIRECT3DTEXTURE9 heightMap, uint32 channel, uint32 flags, float amplitude);
bool generateNormalizationCubeMap();
bool maskWithImage(cImage* pImage);
void releaseTexture();
bool convertToNormalMap(
uint32 channel,
uint32 flags,
float amplitude);
// Accessors...
LPDIRECT3DTEXTURE9 getTexture()const;
bool uploadImage(const cImage* pImage, bool copyAll = true);
bool uploadCubeFace(const cImage* pImage, D3DCUBEMAP_FACES face, bool copyAll = true);
uint32 width()const{return m_width;}
uint32 height()const{return m_height;}
uint32 mipLevels()const{return m_mipLevels;}
uint32 d3dUsage()const{return m_d3dUsage;}
D3DFORMAT d3dFormat()const{return m_d3dFormat;}
D3DPOOL d3dPool()const{return m_d3dPool;}
bool getSurfaceLevel(int level, LPDIRECT3DSURFACE9* ppSurface);
private:
// Data...
uint32 m_width;
uint32 m_height;
uint32 m_mipLevels;
uint32 m_d3dUsage;
D3DFORMAT m_d3dFormat;
D3DPOOL m_d3dPool;
DWORD m_d3dFilter;
DWORD m_d3dMipFilter;
D3DCOLOR m_d3dColorKey;
D3DXIMAGE_INFO m_d3dImageInfo;
PALETTEENTRY* m_pPalette;
LPDIRECT3DTEXTURE9 m_pTexture;
LPDIRECT3DCUBETEXTURE9 m_pCubeTexture;
bool loadFromResourceFile(cFile& InputFile);
bool configureImageSettings();
bool checkTextureRequirements();
bool checkCubeTextureRequirements();
bool loadTextureFromImageFile(const tchar* filename);
bool loadTextureFromMemory(uint8* memory, uint32 size);
bool loadCubeTextureFromImageFile(const tchar* filename);
bool loadCubeTextureFromMemory(uint8* memory, uint32 size);
// Nonexistant Functions...
cTexture( const cTexture& Src);
cTexture& operator=( const cTexture& Src);
};
typedef cResourcePool<cTexture> cTextureManager;
此外還有vertex_buffer.h中的cVertexBuffer和model_resource.h中的cModelResource
P56有資源的使用示例
類關系圖:
由cResourcePoolManager統一管理。
書的第四章gaia引擎總覽有提到資源管理相關的內容,但是並沒用對源碼進行過多的解釋,這部分還是要自己硬着頭皮看啊。。。
不過看了這些基本理解了資源管理的原理和整個模塊的結構,受益匪淺。。
UML:
ps:突然發現一個奇怪的問題,gaia中雖然定義了cResourcePoolManager,但是自己的程序里面並沒有使用,而是在displayManager里面直接有幾個cResourcePool對資源進行管理。。
如下:
class cDisplayManager
{
。。。。。。
protected:
// Private Data...
bool m_bEnabled;
bool m_bClearEachFrame; // true to clear each frame to black before rendering
// device-bound resource pools
cTextureManager m_texturePool;
cSurfaceMaterialManager m_surfaceMaterialPool;
cEffectFileManager m_effectFilePool;
cRenderMethodManager m_renderMethodPool;
cVertexBufferManager m_vertexBufferPool;
cIndexBufferManager m_indexBufferPool;
cModelManager m_modelPool;
cImageManager m_imagePool;
。。。。。。
};