gaia引擎分析(二)场景管理
只是粗略的分析原理,大虾轻喷~~
Gaia引擎中没有场景管理器(scenemanager)这种东西,但是并不是没有场景管理,而是在cGameHost类中有一课场景树进行场景组织、一棵四叉树用来进行剪裁。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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,可挂接在四叉树节点上。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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:四叉树,用于剪裁掉不可见的物体,提高渲染效率
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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形成一个列表发送到渲染队列,这样就实现了裁剪。