SceneManager场景管理器,管理啥呢?管理的就是Node,具体点是SceneNode
SceneNode继承自Node,Node只是个虚类,定义了很大一部分操作和接口
SceneNode和Node之间是代码重用关系,不是接口关系。(例如SceneNode提供了attachObject函数,而Node没有提供这个接口)。所以不要指望用Node的指针操作所有SceneNode的操作。应该直接用SceneNode的指针。Node存在的目的是减少代码的重复编写。这虽然是继承最普通的用法,但是在设计模式之帝Ogre里看到这种代码多少会迷糊点,我以为它又要用什么神奇的设计模式了。
那这样,就必须得先看Node了
OgreNode.h
定义了Node类,你可以把这个类理解成纯粹是一个树上的节点。这个类完成的功能主要包括:定义了节点之间的树结构,而且还实现了事件监听(例如添加个Node到树触发什么什么的)
关于属性(为啥我要以属性来分析功能,而不是以函数?很容易啊~~~又不是算法类,实体类的每个函数都是设置或者获取属性值的,只是方法不同而已,所以属性值基本可以清楚的代表一切了)
首先必须是树结构的信息:包括父节点和子节点集合,已经一些标志(标志啥?更新啊。本节点变化,所有子节点得跟着变化吧,父节点变化,都得变吧)
然后是节点的信息:
包括朝向、位置和放大:mOrientation:Quaternion,mPosistion:Vector3, mScale:Vector3。要注意的是,这里的朝向和位置都是相对于父节点的
包含从父节点继承的朝向、位置和放大
包含作为关键帧动画的起始朝向、位置和放大
也就这么点东西了。
然后是
OgreSceneNode.h
这个就主要和场景有关了。
场景上需要除了树之外的什么东西呢?
要能显示一个WireBoundingBox吧?不过不是必须的,但是Ogre提供了。mWireBoundingBox: WireBoundingBox
既然是场景里的,场景管理器SceneManager肯定要有个指针吧,毕竟是人家创造的。mCreator:SceneManager,还得有个bool判定是否加进了SceneManager里了
场景里就有碰撞检测的需求,那就要有AABB啦~~~mWorldAABB:AxisAlignedBox
另外,增强了点功能,例如Node里提供的yaw操作只能绕着y轴转,但是SceneNode里扩展到了可以绕任意轴
另外既然是可显示的节点,那就得能选择这个节点显示不显示。有个bool值
另外扩展了一个功能,就是一个节点可以根据另外一个节点自动的改变自己的位置和朝向。
下面要说操作,在这之前,必须要讲一个概念,就是Node里存放的节点位置和朝向都是相对于父节点的。那么他们的函数操作就分为相对于父节点坐标系、或者是自己本身的局部坐标系和世界坐标系两种。有个Enum定义了这三种坐标系,分别为TS_LOCAL, TS_PARENT, TS_WORLD
在Node的translate函数里,可以设置到底是哪种。
另外你想啊,你定义一个子节点,那个节点的坐标系会和父节点一样?这个确实很复杂。
既然子节点的Orientation是相对于父节点的。也就是说子节点的坐标系的方向就是父节点的朝向(通常用z轴限定)。那么可不可以更改子节点的坐标系朝向?当然可以啊,用setDirection函数,这样的话它的mOrientation参数就肯定得跟着变了,毕竟,虽然说子节点是相对于父节点的,那是说的坐标系。子节点存储的Orientation值还是相当于本节点的。那这样岂不是与父节点的朝向信息失去联系了?木有,别忘了Node里还有存放父节点朝向的地方呢~~~~其实,存放父节点朝向的信息是从父节点的父节点迭代计算下来的,其实最后就是相对于根节点的Orientation。
发现问题的关键了麽?如果你改了坐标系的朝向,但是节点在根节点的总坐标系中确仍然是根据父节点*mOriention计算出来的,也就是说,改坐标系的朝向就相当于改了那面是正面,哪面是反面。或者其他坐标轴。(比如改成了屁股是正面),就是用的setDirection函数,或者lookAt函数。