[OGRE]基础教程来二发:来谈一谈坐标系统

上一回我们讲到,屏幕出现了一个机器人。

不过为毛这个机器人没有面对着我们呢?这是因为机器人模型预设的方向就是正对X正方向的。

我们先来了解一下 OGRE 的坐标和向量。

与其它图形引擎一样,OGRE 使用 XZ 面作为其水平面,Y 轴作为纵轴。

当你面对着屏幕时,从左至右的方向为 X 轴正方向,从下至上为 Y 轴正方向,屏幕从里至外为 Z 轴的正方向(指着你)。


现在我们已经了解了 OGRE 中的方位了,让我们再次回到上次的代码部分,可以发现在代码中并没有指定机器人的方向,怪不得人家不鸟你。

实际上在 OGRE 中大量的函数都有自己默认的参数值,

例如SceneNode::createChildSceneNode成员函数有三个参数:场景节点的名称、位置及方向,该成员的位置默认值为(0,0,0)

让我们创建另一个场景节点,这次我们指定它的位置方位信息

#include "ExampleApplication.h"
class TutorialApplication : public ExampleApplication
{
public:
	TutorialApplication()
	{
	}
	~TutorialApplication() 
	{
	}
protected:
	void createScene(void)
	{
		//设置背景灯光
		mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );

		//第一个机器人
		Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
		SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
		node1->attachObject( ent1 );

		//第二个机器人
		Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
		SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode2", Vector3( 50, 0, 0 ) );
		node2->attachObject( ent2 );
	}
};

这些代码除了两个地方不同之外,其它部分与以前的代码都一样。

首先我们创建的实体及场景节点的名称有细微的不同,

其次创建场景节点时指定了节点的方位信息,我们让实体向 X 的正方向偏移了50单位。

这是相对与场景中的根节点而言,而所有的节点的位置都是相对于其父节点而言的。

编译并运行,你会发现屏幕上现在有两个机器人:

[OGRE]基础教程来二发:来谈一谈坐标系统_第1张图片


下面我们再来谈谈OGRE的实体系统,主要给大家介绍几个函数。

第一个是Entity::setVisibleEntity::isVisible

利用这个函数,你可以设置任何一个实体为可见或不可见。

当你想暂时隐藏一个实体时,与其销毁这个实体然后再在用的时候重新创建,不如简单的调用一下这个函数把实体隐藏。

注意:并不需要省着用这些实体,任何一个对象的材质和贴图只会被载入到内存里一次,这样做唯一省掉的只不过是实体创建和毁灭的时间。


还有两个函数很常用,一个是getName函数,用来返回实体的名称;另一个是getParentSceneNode函数,返回这个实体绑定的节点。



再来谈谈场景节点的问题。

这个问题说来话长,我们简单介绍一下常用的内容。

第一条:移动。你可以利用getPositionsetPosition得到或者设定场景节点的位置(总是和父节点相对的)。你可以利用translate函数来移动对象。

第二条:缩放。场景节点不仅仅决定一个对象的位置,它还可以控制一个对象的缩放比例和旋转角度。你可以用scale函数来设置一个对象的缩放比例。

第三条:旋转。可以用yaw, roll, pitch函数来旋转对象。

你可以用resetOrientation来还原你对对象进行的所有旋转,也还可以用setOrientation, getOrientationrotate函数对对象进行高级旋转。

注意:所有的移动都是相对于父节点的,所以可以很容易的使两个节点一起移动。

我们用前面的两个机器人做实验,原始代码如下:

#include "ExampleApplication.h"
class TutorialApplication : public ExampleApplication
{
public:
	TutorialApplication()
	{
	}
	~TutorialApplication() 
	{
	}
protected:
	void createScene(void)
	{
		//设置背景灯光
		mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );

		//第一个机器人
		Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
		SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
		node1->attachObject( ent1 );

		//第二个机器人
		Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
		SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode2", Vector3( 50, 0, 0 ) );
		node2->attachObject( ent2 );
	}
};

假如我们在添加第二个机器人的地方稍做手脚:

       SceneNode *node2 = node1->createChildSceneNode( "RobotNode2", Vector3( 50, 0, 0 ) );


这样一来RobotNode2就变成了RobotNode的子节点。移动node1会使node2跟着移动,移动node2却不会影响node1

下面的代码就只会移动RobotNode2

node2->translate( Vector3( 10, 0, 10 ) );

下面的代码会移动RobotNode,既然RobotNode2是RobotNode的子节点,RobotNode2会跟着移动:

       node1->translate( Vector3( 25, 0, 0 ) );


最后说一下,你可以使用场景管理器的成员函数getSceneNodegetEntity来获取场景节点和实体,这样你就不用保留你创建他们时使用的指针了。

但你仍然应该保留很常用的实体的指针。


下面我们来做两个小实验,首先是缩放。将头文件的代码修改如下:

#include "ExampleApplication.h"
class TutorialApplication : public ExampleApplication
{
public:
	TutorialApplication()
	{
	}
	~TutorialApplication() 
	{
	}
protected:
	void createScene(void)
	{
		//设置背景灯光
		mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );

		//第一个机器人
		Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
		SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" );
		node1->attachObject( ent1 );
		node1->scale( .5, 1, 2 ); 



		//第二个机器人
		Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
		SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode2", Vector3( 50, 0, 0 ) );
		node2->attachObject( ent2 );
		node2->scale( 1, 2, 1 ); 
	}
};

可以看到两个机器人均进行了缩放:

[OGRE]基础教程来二发:来谈一谈坐标系统_第2张图片


接下来就是旋转的问题啦,可以用yaw, pitch, roll来旋转对象。

YawY轴的旋转,PitchX轴,RollZ轴。

我们把代码作如下修改:

#include "ExampleApplication.h"
class TutorialApplication : public ExampleApplication
{
public:
	TutorialApplication()
	{
	}
	~TutorialApplication() 
	{
	}
protected:
	void createScene(void)
	{
		//设置背景灯光
		mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );

		//第一个机器人
		Entity *ent1 = mSceneMgr->createEntity( "Robot", "robot.mesh" );
		SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode( "RobotNode" ,Vector3( -100, 0, 0 ) );
		node1->attachObject( ent1 );
		node1->yaw( Degree( -90 ) );
		
		//第二个机器人
		Entity *ent2 = mSceneMgr->createEntity( "Robot2", "robot.mesh" );
		SceneNode *node2 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode2", Vector3( 0, 0, 0 ) );
		node2->attachObject( ent2 );
		node2->pitch( Degree( -90 ) );
				
		//第三个机器人
		Entity *ent3 = mSceneMgr->createEntity( "Robot3", "robot.mesh" );
		SceneNode *node3 = mSceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode3", Vector3( 100, 0, 0 ) );
		node3->attachObject( ent3 );
		node3->roll( Degree( -90 ) );
	}
};

运行可以看见三个体位各异的机器人:

[OGRE]基础教程来二发:来谈一谈坐标系统_第3张图片


至此,基本内容的介绍就告一段落咯。



你可能感兴趣的:(OGRE)