只是粗略的分析原理,大蝦輕噴~~
Gaia引擎中沒有場景管理器(scenemanager)這種東西,但是并不是沒有場景管理,而是在cGameHost類中有一課場景樹進行場景組織、一棵四叉樹用來進行剪裁。


class cGameHost : public CD3DApplication, public cSingleton<cGameHost>
{
。。。。。。
cSceneNode m_rootNode;//場景樹根節點
cCamera m_defaultCamera;
cCamera* m_pActiveCamera;
cQuadTree m_quadTree;//四叉樹
cRect3d m_worldExtents;
tchar m_rootPath[MAX_PATH];
bool m_frameReady;
// Invalid Functions...
cGameHost(const cGameHost& Src);
cGameHost& operator=(const cGameHost& Src);
};
cSceneNode類:場景節點,可形成樹狀結構組織場景,形成一種空間變換的層次結構。
?
?cSceneObject類:渲染基石,繼承自cSceneNode,所有可渲染對象都繼承自cSceneObject,可掛接在四叉樹節點上。


class cSceneObject : public cSceneNode
{
。。。。。。
void attachToQuadTree(cQuadTree* parentTree);//掛接到四叉樹
cQuadTreeNode* quadTreeNode()const;
u32Flags zMask()const;
cSceneObject* forwardTreeLink()const;
cSceneObject* rearTreeLink()const;
const cRect3d& localBounds()const;
const cRect3d& worldBounds()const;
//
// temporary functions
//
void setWorldBounds(const cRect3d& box)
{
m_worldBounds = box;
}
private:
// bounding box information
u32Flags m_objectFlags;
cRect3d m_localBounds;
cRect3d m_worldBounds;
// world QuadTree membership information
cQuadTree* m_pQuadTree;
cQuadTreeNode* m_pQuadTreeNode;
u32Flags m_quadTreeZMask;
cSceneObject* m_pForwardTreeLink;
cSceneObject* m_pRearTreeLink;
// QuadTree search result links
cSceneObject* m_pForwardSearchLink;
cSceneObject* m_pRearSearchLink;
// private functions
void setForwardSearchLink(cSceneObject* pForwardLink);
void setRearSearchLink(cSceneObject* pForwardLink);
virtual void refreshQuadTreeMembership();
friend cQuadTreeNode;
void setQuadTreeData(cQuadTreeNode* parentNode, u32Flags zMask);
void setForwardTreeLink(cSceneObject* link);
void setRearTreeLink(cSceneObject* link);
};
?
cQuadTree:四叉樹,用于剪裁掉不可見的物體,提高渲染效率


class cQuadTree
{
public:
// Data Types & Constants...
enum eConstants
{
k_minimumTreeDepth = 1,
k_maximumTreeDepth = 9, // must be a value between 1 and 9
};
// Public Data...
// Creators...
cQuadTree();
~cQuadTree();
void create(const cRect3d& worldExtents, int depth);
void destroy();
// Operators...
// Mutators...
cSceneObject* buildSearchResults(
const cRect3d& worldRect,
const cFrustum* pOptionalFrustum=0); //四叉樹搜索,即剪裁,可以選用視錐體和包圍盒
u32Flags addOrUpdateSceneObject(cSceneObject* newNode);
// Accessors...
bool isReady()const;
private:
// Private Data...
cQuadTreeNode* m_levelNodes[k_maximumTreeDepth];//四叉樹節點2維數組
cVector3 m_worldExtents;
cVector3 m_worldScale;
cVector3 m_worldOffset;
int m_depth;
uint32 m_memorySize;
// Private Functions...
void findTreeNodeInfo(const cQuadTreeRect& worldByteRect, int& level, int& levelX, int& levelY);
cQuadTreeNode* findTreeNode(const cQuadTreeRect& worldByteRect);
cQuadTreeNode* getNodeFromLevelXY(int level, int x, int y);
void buildByteRect(const cRect3d& worldRect, cQuadTreeRect& worldByteRect);
};
cQuadTreeNode:四叉樹節點,上面可以掛接cSceneObject


class cQuadTreeNode
{
public:
cQuadTreeNode();
~cQuadTreeNode();
uint32 addOrUpdateMember(cSceneObject* member, const cQuadTreeRect& rect);
void removeMember(cSceneObject* member);
void testLocalMembersForSearchResults(
cSceneObject** pResultList,
cSceneObject** pResultListTail,
u32Flags zMask,
float zMin,
float zMax,
const cFrustum* pOptionalFrustum=0);
void testLocalMembersForSearchResults(
cSceneObject** pResultList,
cSceneObject** pResultListTail,
u32Flags zMask,
const cRect3d& trueRect,
const cFrustum* pOptionalFrustum=0);
bool empty()const;
u32Flags zMask()const;
u32Flags zLocalMask()const;
private:
// Private Data...
cQuadTreeNode* m_pChildNode[4];//子節點
cQuadTreeNode* m_pParentNode;
cSceneObject* m_pFirstMember;//掛接的cSceneObject列表
u32Flags m_zLocalMask;
u32Flags m_zMask;
// Private Functions...
void descendantMemberAdded(u32Flags zMask);
void descendantMemberRemoved();
void rebuildLocalZMask();
void rebuildZMask();
// functions available to the quad tree
friend cQuadTree;
void setup(cQuadTreeNode* parent, cQuadTreeNode* child0, cQuadTreeNode* child1, cQuadTreeNode* child2, cQuadTreeNode* child3);//在四叉樹上配置節點
};
?
?UML:
由于我的uml建模工具貌似不支持自身關聯所以樹的結構就畫不出來了,腦補吧。。嘿嘿
?總結:
gaia的場景管理當中有兩棵樹:
一棵是場景樹,用來組織場景中物體的空間邏輯關系,即子節點依附在父節點上,在父節點的坐標系中活動,有點像骨骼動畫的原理。
一棵是四叉樹,用于剪裁。gaia中為了簡單,使用的是滿四叉樹。這些節點就是上面說過的cQuadTreeNode,四叉樹節點。
游戲中的cSceneObject根據自身的位置和包圍盒大小被放置到這棵四叉樹合適的四叉樹節點上。需要渲染時根據輸入的視錐體或者包圍盒遍歷整棵樹,將在包圍盒或視錐體中的cSceneObject形成一個列表發送到渲染隊列,這樣就實現了裁剪。