2023年6月22日发(作者:)
OGRE源码分析:场景树模块引擎名称:OGRE 版本:1.11.5分析模块:场景树模块(Node,SceneNode,Bone,OctreeNode,TagPoint)引擎模块介绍本次分析是场景管理的⼀部分内容,及场景的组织⽅式(场景树),该模块的功能是将场景中所需要⽤到的对象存储起来,以节点、⾻骼、⼋叉树等不同组织⽅式进⾏描述场景树。场景结构图如下:根节点的位置往往在场景的中⼼。每个节点对象都⽤数据成员保存相对于⽗节点的相对位移和相对旋转量(这⼀点很重要)。节点类提供节点的移动和旋转函数。这样当节点1发⽣移动和旋转的时候,其全部⼦节点及它们挂接的场景元素也将被动地移动和旋转。引擎模块主要类介绍这是有关场景树的UML图。作为场景中可以渲染 object 的⽗类,场景树中的每个节点都是可渲染的,所以都是从 Renderable 中集成⽽来。同场景树相关的类主要是 Node、SceneNode。Node类:⼀个虚类,定义了⼤部分操作和接⼝。Node为场景图的节点基类,定义公共属性⚫ 有指向多个⼦节点的指针表⚫ 有指向多个⽗节点的指针表⚫ 增加、删除、修改节点操作⚫ 包围体和变换计算等操作⚫ Node派⽣类为各类场景节点,如可移动对象类、静态场景类、⾓⾊类等场景图的公共基类(Node抽象类),派⽣两个场景节点类:普通场景节点类(SceneNode)和⾓⾊⾻骼节点类(Bone)SceneNode类:重写了⼤部分Node的函数,此类主要和场景有关。对Node类进⾏扩展和补充,例如Node类只定义了yaw绕y轴旋转,⽽SceneNode定义了可以绕任何轴旋转的函数。树的普通节点,包含该节点以下⼦树的变换信息和包围体信息,⽤attachObject()操作将可移动对象“挂到”该节点中。OctreeNode类:定义了⼋叉树节点的操作。Bone类:⾓⾊⾻骼节点类,定义了以⾻骼节点为单位各种变换操作。TagPoint类:继承于Bone类,是对悬挂在⾻骼上⼀些素材的操作,例如缩放、平移等。类的成员函数描述·Node类:继承图(关系图):类型定义:typedef std::vector ChildNodeMap;typedef VectorIterator ChildNodeIterator;typedef ConstVectorIterator ConstChildNodeIterator;Node类功能(成员函数):Node::Node(const String& name)构造函数产⽣⼀个string类型的节点名称,并且初始化节点变量(定义在OgreNode.h)以下是Node类⾥跟⼦节点有关的成员函数:Node* Node::createChild(const Vector3& inTranslate, const Quaternion& inRotate)Node* Node::createChild(const String& name, const Vector3& inTranslate, const Quaternion& inRotate)void Node::addChild(Node* child)Node* Node::getChild(unsigned short index) constNode* Node::removeChild(unsigned short index)Node* Node::removeChild(Node* child)void Node::removeAllChildren(void)Node* Node::getChild(const String& name) constNode* Node::removeChild(const String& name)Node::ChildNodeIterator Node::getChildIterator(void)Node::ConstChildNodeIterator Node::getChildIterator(void) const其中创建⼦节点的时候,有两个成员函数,⼀个是创建未命名的⼦节点,另⼀个是创建未命名的⼦节点。上述函数⽀撑起了创建⼦节点,根据索引或节点名字得到⼀个⼦节点,删除特定位置或名字的⼦节点的功能,最后两个函数是返回此节点的迭代器,可⽤于遍历此节点的⼦节点,速度⽐较快。以下是Node类和位置有关的函数 :void Node::setPosition(const Vector3& pos)void Node::setPosition(Real x, Real y, Real z)Vector3 Node::convertWorldToLocalPosition( const Vector3 &worldPos )Vector3 Node::convertLocalToWorldPosition( const Vector3 &localPos )Vector3 Node::convertWorldToLocalDirection( const Vector3 &worldDir, bool useScale )Vector3 Node::convertLocalToWorldDirection( const Vector3 &localDir, bool useScale )Quaternion Node::convertWorldToLocalOrientation( const Quaternion &worldOrientation )Quaternion Node::convertLocalToWorldOrientation( const Quaternion &localOrientation )设置位置坐标是设置相对于⽗节点的坐标,可以通过重载函数来接收两种不同的参数,还可以获取世界坐标和⽅向或本地坐标和⽅向。还可以通过函数名带有Derived的函数来设置节点的最终坐标和⽅向。下⾯是变换有关的函数:void Node::setScale(const Vector3& inScale)void Node::setScale(Real x, Real y, Real z)void Node::scale(const Vector3& inScale)void Node::scale(Real x, Real y, Real z)Matrix3 Node::getLocalAxes(void) constvoid Node::translate(const Vector3& d, TransformSpace relativeTo)void Node::translate(Real x, Real y, Real z, TransformSpace relativeTo)void Node::translate(const Matrix3& axes, const Vector3& move, TransformSpace relativeTo)void Node::translate(const Matrix3& axes, Real x, Real y, Real z, TransformSpace relativeTo)void Node::roll(const Radian& angle, TransformSpace relativeTo)void Node::pitch(const Radian& angle, TransformSpace relativeTo)void Node::yaw(const Radian& angle, TransformSpace relativeTo)void Node::rotate(const Vector3& axis, const Radian& angle, TransformSpace relativeTo)void Node::rotate(const Quaternion& q, TransformSpace relativeTo)void Node::setInitialState(void)设置节点的缩放因⼦时,要注意与其他变换不同,缩放因⼦并不总是由⼦节点继承。 缩放是否影响⼦节点的⼤⼩取决于⼦节点的setInheritScale选项。 在某些情况下,您希望⽗节点的缩放因⼦应⽤于⼦节点(例如,⼦节点是同⼀对象的⼀部分,因此您希望它基于⽗节点的⼤⼩具有相同的相对⼤⼩),但是 在其他情况下(例如,⼦节点仅⽤于定位另⼀个对象,您希望它保持⾃⼰的⼤⼩)。 默认设置是继承与其他转换⼀样。像旋转⼀样,缩放围绕节点的原点定向。缩放有两种,⼀种是根据缩放⽐例与缩放因⼦结合进⾏缩放,另⼀种是直接对坐标进⾏操作。平移有沿着世界笛卡尔轴,即沿着世界x,y,z,通过所提供的⽮量移动节点,还有通过相对于⾃定义轴组的向量转换节点。Roll旋转是绕着z轴进⾏旋转,pitch旋转是绕着x轴进⾏旋转,yaw旋转是绕着y轴进⾏旋转。·SceneNode类:继承(关系)图:从代码中可以看出 SceneNode 类似于 Scene 中的⼀个 Cell,想象⼀下在 OctreeScene Manager 中的⼀个划分和 BSP 中的 cell。所以 SceneNode 可以认为是⼀个容器,可以存放 Movable Object。⽽存放在同⼀个 SceneNode 中的 object 应该有⼀定的共性。⾸先来看构造函数:SceneNode::SceneNode(SceneManager* creator)SceneNode::SceneNode(SceneManager* creator, const String& name)构造函数,仅由创建者SceneManager调⽤。创建具有⽣成名称的节点或者特定名称的节点。下⾯是和object有关的函数:void SceneNode::attachObject(MovableObject* obj)unsigned short SceneNode::numAttachedObjects(void) constMovableObject* SceneNode::getAttachedObject(unsigned short index)MovableObject* SceneNode::getAttachedObject(const String& name)MovableObject* SceneNode::detachObject(unsigned short index)MovableObject* SceneNode::detachObject(const String& name)void SceneNode::detachObject(MovableObject* obj)void SceneNode::detachAllObjects(void)AttachObject函数将场景对象的实例添加到此节点。场景对象可以包括实体对象,相机对象,灯光对象,粒⼦系统对象等。来⾃MovableObject的⼦类。还可以通过调⽤numAttachedObjects函数获取附加到此节点的对象数。可以通过索引或者对象的名称来获取附加的对象的指针。另外可以通过索引或名称或者指向对象的指针来分离⼀个附加的对象。最后,可以调⽤detachAllObjects把该节点上的所有对象分离。void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue,VisibleObjectsBoundsInfo* visibleBounds, bool includeChildren,bool displayNodes, bool onlyShadowCasters)这是⼀个内部⽅法,⽤于定位附加到此节点的任何可见对象,并将它们添加到传⼊的队列中。只应由SceneManager实现调⽤,并且只有在调⽤_updat⽅法后才能确保转换和世界范围是最新的。参数cam是个活动的相机,queue是SceneManager的渲染队列,visibleBounds动态创建的边界信息,包含摄像机的所有可见对象,includeChildren如果为true,则会⾃动将调⽤级联到所有⼦节点。displayNodes如果为true,则节点本⾝将呈现为⼀组3个轴以及正在呈现的对象。 ⽤于调试⽬的。⼦节点有关的函数:Node* SceneNode::createChildImpl(void)Node* SceneNode::createChildImpl(const String& name)void SceneNode::removeAndDestroyChild(const String& name)void SceneNode::removeAndDestroyChild(unsigned short index)void SceneNode::removeAndDestroyChild(SceneNode* child)void SceneNode::removeAndDestroyAllChildren(void)SceneNode* SceneNode::createChildSceneNode(const Vector3& inTranslate,const Quaternion& inRotate)SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& inTranslate,const Quaternion& inRotate)上述函数实现了创建⼀个带有名称的⼦节点,根据索引或名称移除并且销毁⼀个⼦节点,删除附加到此节点的所有⼦节点。 不删除节点,只是将它们与此⽗节点分离,可能会重新附加到其他位置的功能。下⾯是⼀些操作函数:void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo,const Vector3& localDirectionVector)void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo,const Vector3& localDirectionVector)void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo,const Vector3& localDirectionVector)void SceneNode::_autoTrack(void)SceneNode* SceneNode::getParentSceneNode(void) constvoid SceneNode::setVisible(bool visible, bool cascade)void SceneNode::flipVisibility(bool cascade)SetDirection函数设置了节点的⽅向向量,参数x,y,z是各⾃⽅向的分量,relativeTo表⽰此⽅向向量的空间,localDirectionVector通常描述节点⾃然⽅向的向量,通常为-Z。Lookat函数是将该节点的本地-Z⽅向指向空间中的某个点,targetPoint是看向的点的向量relativeTo点所在的空间(TS_WORLD、TS_PARENT、TS_LOCAL)localDirectionVector通常描述节点⾃然⽅向的向量,通常为-Z。_autotrack是⽤于更新⾃动跟踪摄像头的内部⽅法。setVisible使得悬挂在这个节点上的对象变得可见/不可见,第⼀个参数是设置可见性,第⼆个参数是设置是否级联到⼦节点。FlipVisibility函数是反转所有悬挂对象的可见性,参数是设置是否级联到⼦节点。·OctreeNode类:继承(关系)图:在三维空间分割,把场景分成很多更⼩的部分,并⽤层次树结构组织这些被分割的部分。⼋叉树就是把空间分成⼋等份,如果被分的部分填满了场景内容,或被分的部分没有场景内容,则不再分割;否则,继续分割这部分,直到终⽌条件满⾜。被分割的空间可以组成⼋叉树。⾸先来看构造函数:OctreeNode::OctreeNode( SceneManager* creator ) : SceneNode( creator )OctreeNode::OctreeNode( SceneManager* creator, const String& name )初始化mOctant,mOctant是被悬挂的节点。下⾯是对移除⼦节点的函数:void OctreeNode::_removeNodeAndChildren( )Node * OctreeNode::removeChild( unsigned short index )Node * OctreeNode::removeChild( Node* child )void OctreeNode::removeAllChildren()Node * OctreeNode::removeChild( const String & name )removeAllChildren函数是从Node中重写,删除对mOctant所有的引⽤。删除⼦节点的引⽤可以通过三种⽅式,通过索引,通过名称,通过指针。这些删除相关的函数都是从Node⾥重写⽽来的。OctreeNode类中其他操作函数:bool OctreeNode::_isIn( AxisAlignedBox &box )void OctreeNode::_updateBounds( void )void OctreeNode::_addToRenderQueue( Camera* cam, RenderQueue
queue,bool onlyShadowCasters, VisibleObjectsBoundsInfo visibleBounds )void OctreeNode::getRenderOperation( RenderOperation& rend )isIn函数判断此节点是否在给定的参数box⾥。_addToRenderQueue函数将所有悬挂的sceneNode添加到渲染队列当中,其中函数内调⽤processVisibleObject函数需要参数(Camera* cam, RenderQueue
queue, bool onlyShadowCasters, VisibleObjectsBoundsInfovisibleBounds )。getRenderOperation函数设置LegacyRenderOperation以将此场景节点渲染为⼏何体。·Bone类:继承(关系)图:Bone类和SceneNode类都是继承于Node,Bone类主要是存放对象⾻骼信息。其中Bone类的⼤部分成员函数在Mesh类中⼤量重写,在此主要分析原Bone类中的成员函数。构造函数:Bone::Bone(unsigned short handle, Skeleton* creator)Bone::Bone(const String& name, unsigned short handle, Skeleton* creator)构造函数,不能直接使⽤(使⽤Bone :: createChild或Skeleton :: createBone)createChild函数在下⾯介绍。创建有关的函数:Bone* Bone::createChild(unsigned short handle, const Vector3& inTranslate,const Quaternion& inRotate)Node* Bone::createChildImpl(void)Node* Bone::createChildImpl(const String& name)createChild函数是创建⼀个新的⾻骼作为此⾻骼的⼦项。要注意的是此⽅法创建⼀个新⾻骼,该⾻骼将继承此⾻骼的变换,并指定句柄(Bone* retBone = mCreator->createBone(handle))。参数handle提供新⾻骼的数字句柄; 在Skeleton中必须是唯⼀的。InTranslate是⼦节点相对于⽗母的初始平移偏差,inRotate是相对于⽗级的初始旋转。CreateChild函数可以被两个createChildImpl函数调⽤,创建⼀个带或者不带有名称的⾻骼。下⾯是对⾻骼设置有关的函数:void Bone::setBindingPose(void)void Bone::reset(void)void Bone::setManuallyControlled(bool manuallyControlled)bool Bone::isManuallyControlled() constunsigned short Bone::getHandle(void) constsetBindingPose函数将当前位置/⽅向设置为“绑定姿势”,即⾻骼最初绑定到⽹格的布局。Reset函数是将此⾻骼的位置和⽅向重置为原始绑定位置。调⽤的是Node类⾥⾯的resetToInitialState⽅法。setManuallyControlled函数设置是否⼿动控制此⾻骼。同样isManuallyControlled函数是判断此⾻骼是不是⼿动控制的。getHandle函数获取此⾻骼的数字句柄(在Skeleton中是唯⼀的)。·TagPoint类:继承(关系)图:TagPoint::TagPoint(unsigned short handle, Skeleton* creator)构造函数,初始化句柄和⾻架中的构造器。设置有关的函数:void TagPoint::setParentEntity(Entity *pEntity)void TagPoint::setChildObject(MovableObject *pObject)void TagPoint::setInheritParentEntityOrientation(bool inherit)void TagPoint::setInheritParentEntityScale(bool inherit)上述函数实现了设置⽗节点的实体和设置⼦节点的对象,分别调⽤Entity类和MovableObject类中的成员变量。并且通过参数inherit设置了是否继承⽗节点的⽅向和缩放因⼦。获取信息相关的函数:Entity
TagPoint::getParentEntity(void) constMovableObject TagPoint::getChildObject(void) constbool TagPoint::getInheritParentEntityOrientation(void) constbool TagPoint::getInheritParentEntityScale(void) constconst Affine3& TagPoint::_getFullLocalTransform(void) constconst Affine3& TagPoint::getParentEntityTransform(void) constconst LightList& TagPoint::getLights(void) const上述函数实现了获取⽗级实体和⼦级对象的功能,同样是返回⼀个Entity和MovableObject类的参数变量。同样能够判断是否继承了⽗级的⽅向、缩放因⼦、平移量,返回⼀个bool值。GetLights函数获取灯光列表,列表按照它们与此可渲染器的接近程度排序。
发布者:admin,转转请注明出处:http://www.yc00.com/news/1687386018a6192.html
评论列表(0条)