ogre3d 1.7beginner's guide 第二章 Ogre之场景绘图

 原文出处: http://www.igamett.com/show.php?contentid=797

2 The Ogre Scene Graph
【 第二章 Ogre之场景绘图】

This chapter will introduce us to the concept of a scene graph and how we can use its functions to create complex scenes
【 这章将会介绍给我们场景绘图的一些概念和如何使用函数创造一个复杂的场景。 】

In this chapter, we will:
 Learn the three basic operations in 3D space
 How a scene graph is organized
 The different 3D spaces we can operate in
 let's get on with it.

【 在这章,我们将会:
 学习在3D空间中三个基本的操作。
 一个场景绘图是如何被组织的。
 我们可以操作的不同的3D空间。
那么,就让我们开始吧。 】


Creating a scene node
【 创建一个场景结点。 】

In the last chapter, Chapter 1, Installing Ogre 3D, we loaded a 3D model and attached it to our scene. Now we will learn how to create a new scene node and attach our 3D model to it.
【 在上一章中(第一章 创建Ogre 3D),,我们加载了一个3D模型并且把它绑定到我们的场景上。现在我们将会学习如何创建一个新的场景结点并且把我们的3D模型绑定到结点上。 】

Time for action – creating a scene node with Ogre 3D
【 实践时刻 — 用Ogre3D创建一个场景结点 】

We are going to use the code from Chapter 1, Installing Ogre 3D modify it to create a new scene node, and attach it to the scene. We will follow these steps:
【 我们将会使用第一章的代码,修改第一章的代码以创建一个新的场景结点,并且把他绑定到一个场景结点上。我们将会做以下步骤:】

1.In the old version of our code, we had the following two lines in the createScene() function:
【 在我们老版本的代码中,我们在createScene() 函数中存在以下两行。】
Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.mesh");
mSceneMgr->getRootSceneNode()->attachObject(ent);

2. Replace the last line with the following:
【 用以下代码替换函数中的最后一行。 】
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");

3. Then add the following two lines; the order of those two lines is irrelevant for
the resulting scene:
【 然后添加以下两行;这两行代码的添加顺序对场景的效果没有影响。 】
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

4. Compile and start the application.
【 编译并且运行应用程序。 】

5. You should see the same screen you get when starting the application from
Chapter 1.
【 当你运行应用程序,你应会看到和你第一章一样的场景。】

What just happened?
【 刚刚发生了什么?】
We created a new scene node named Node1. Then we added the scene node to the root
scene node. After this, we attached our previously created 3D model to the newly created
scene node so it would be visible.
【 我们创建了一个新的命名为Node1的场景结点。然后我们添加这个场景结点到根结点。在这之后,我们绑定之前的3D模型到我们新创建的结点上面,这样就可以看到效果了。 】

How to work with the RootSceneNode
【 如何使用场景根结点 】

The call mSceneMgr->getRootSceneNode() returns the root scene node. This scene node is a member variable of the scene manager. When we want something to be visible, we need to attach it to the root scene node or a node which is a child or a descendent in any way. In short, there needs to be a chain of child relations from the root node to the node; otherwise it won't be rendered. As the name suggests, the root scene node is the root of the scene.  So the entire scene will be, in some way, attached to the root scene node. Ogre 3D uses a so-called scene graph to organize the scene.
【 调用mSceneMgr->getRootSceneNode() 函数将会返回场景的根结点。这个场景结点是场景管理器的一个成员变量。当我们想要什么显示的时候,我们需要以一种方式把它绑定到场景根结点上或者一个派生类或子类的结点上。简而言之,子结点需要和根结点保持结点与结点之间的联系,否则的话,子结点上的模型就得不到渲染。就像变量名所暗示的那样,场景根结点是场景的根。因此整个场景将会以某种方式绑定到场景的根结点上。Ogre 3D使用了所谓的场景绘图的方式来组织场景。 】

This graph is like a tree,
it has one root, the root scene node, and each node can have children. We already have used this characteristc when we called mSceneMgr->getRootSceneNode()->addChild(node);. There we added the created scene node as a child to the root. Directly afterwards, we added another kind of child to the scene node with node->attachObject(ent);. Here, we added an entity to the scene node. We have two different kinds of objects we can add to a scene node. Firstly, we have other scene nodes, which can be added as children and have children themselves. Secondly, we have entity that we want rendered. Entity aren't children and can't have children themselves. They are data objects which are associated with the node and can be thought of as leaves of the tree. There are a lot of other things we can add to a scene, like lights, particle systems, and so on. We will later learn what these things are and how to use them. Right now, we only need entity. Our current scene graph looks like the following:
【 这个绘图的方式就好像一棵树一样。它只有一个根(也就是场景根结点),并且每个结点都可以有子结点。我们已经使用了这一特性当我们调用mSceneMgr->getRootSceneNode()->addChild(node) 的时候。我们把创建好的场景结点当做场景根结点的子结点。在这之后,我们添加了node->attachObject(ent) 使另一种类型添加到场景结点。这里,我们添加一个实体到场景结点。我们现在有两种不同的可以添加到场景结点的对象。首先,创建可以被添加为子结点或者可以继续为自己添加子结点的结点。然后,我们我们创建我们想要渲染的实体。实体不是子结点,它们也不可能有子结点。它们有数据对象可以被关联上结点也可以被认为是树上的叶子。我们稍晚将会学习它们到底是什么和如何使用它们。现在,我们只需要实体。我们当前的场景绘图方式就好像下图一样。】

 

The first thing we need to understand is what a scene graph is and what it does. A scene graph is used to represent how different parts of a scene are related to each other in 3D space.
【 首先我们需要理解的是什么是场景结点并且他们是干什么的。一个场景绘图就是用来代替在3D空间中不同部分的场景是如何相互关联在一起的。 】

3D space
Ogre 3D is a 3D rendering engine, so we need to understand some basic 3D concepts. The
most basic construct in 3D is a vector, which is represented by an ordered triple (x,y,z)
【 Ogre 3D是一个3D渲染引擎,所以我们需要一些基本的3D概念。在3D上最基础的结构就是向量,这个向量中有次序的包含着(x,y,z)。 】

 

Each position in a 3D space can be represented by such a triple using the Euclidean coordination system for three dimensions. It is important to know that there are different kinds of coordinate systems in 3D space. The only difference between the systems is the orientation of the axis and the positive rotation direction. There are two systems that are widely used, namely, the left-handed and the right-handed versions. In the following image, we see both systems—on the left side, we see the left-handed version; and on the right side, we see the right-handed one.
【 在3D空间的每个位置都可以被欧几里德三维坐标系的一个三维坐标表示。我们要强调一下在3D表示方面有不同的坐标体系。而这些体系之间的不同就是主轴的方向和选装的正方向。现在主流的有两种体系,左手坐标系和右手坐标系。在下面的图中,我们看到两种体系— 在左边我们看到的是左手坐标系;在右边我们看到的是右手坐标系。 】

      

Source: http://en.wikipedia.org/wiki/File:Cartesian_coordinate_system_handedness.svg

The names left-and right-handed are based on the fact that the orientation of the axis can be reconstructed using the left and right hand. The thumb is the x-axis, the index finger the y-axis, and the middle finger the z-axis. We need to hold our hands so that we have a ninety-degree angle between thumb and index finger and also between middle and index finger. When using the right hand, we get a right-handed coordination system. When using the left hand, we get the left-handed version.
【 左手和右手坐标系名字的由来是基于他们主轴方向的不同,方向是左手和右手来决定创建的。大拇指是X轴,食指是Y轴,而中指是Z轴。我们需要张开手使大拇指,食指和中指之间保持90度角。当使用右手时,我们就可以得到一个右手坐标系。当使用左手时,我们就可以得到一个右手坐标系】

Ogre uses the right-handed system, but rotates it so that the positive part of the x-axis is pointing right and the negative part of the x-axis points to the left. The y-axis is pointing up and the z-axis is pointing out of the screen and it is known as the y-up convention. This sounds irritating at first, but we will soon learn to think in this coordinate system. The Website http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html contains a rather good picture-based explanation of the different coordination systems and how they relate to each other.
【 Ogre 使用的是右手坐标系,但是旋转坐标系使X轴的正半轴指向右并且X轴的负半轴指向左。Y轴(正半轴)指向上,Z轴(正半轴)垂直于屏幕向外,这被称为y-up convention。这开始会使我们很不适应。但是我们不久将会在这样的坐标系下学习研究Ogre。这个网址http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html 有能更好展示不同坐标系之间的不同和联系的图片解释。 】

Scene graph
【场景绘图】

A scene graph is one of the most used concepts in graphics programming. Simply put, it's a way to store information about a scene. We already discussed that a scene graph has a root and is organized like a tree. But we didn't touch on the most important function of a scene graph. Each node of a scene graph has a list of its children as well as a transformation in the 3D space. The transformation is composed of three aspects, namely, the position, the rotation, and the scale. The position is a triple (x,y,z), which obviously describes the position of the node in the scene. The rotation is stored using a quaternion, a mathematical concept for storing rotations in 3D space, but we can think of rotations as a single floating point value for each axis, describing how the node is rotated using radians as units. Scaling is quite easy; again, it uses a triple (x,y,z), and each part of the triple is simply the factor to scale the axis with.
【 场景绘图是在图形化编程领域最被广泛使用的概念之一。简单的说,这是存储场景信息的一种方式。我们已经讨论过场景绘图必须有一个根结点而且是树形结构的。但是我们还没有涉及场景绘图中最重要的函数。每个场景结点既可有子结点也可以在3D空间变换的函数。这些变换可以说由三方面组成,就是—— 位置变换(position),旋转变换(rotation)和缩放(scale)变换。坐标点的(x,y,z),明确的描述了结点在场景中的位置。旋转是使用四元数来储存的,四元数是3D空间存贮旋转的一个数学概念,但是我们可以认为旋转就是每个坐标轴一个的浮点数,描述了结点以弧度为单位的旋转。缩放就比较简单了,同样的,就是它使用了一个(x,y,z)的数组,并且数组的每一部分就是对应坐标轴的缩放比例。 】

The important thing about a scene graph is that the transformation is relative to the parent
of the node. If we modify the orientation of the parent, the children will also be affected
by this change. When we move the parent 10 units along the x-axis, all children will also be
moved by 10 units along the x-axis. The final orientation of each child is computed using the
orientation of all parents. This fact will become clearer with the next diagram.
【 关于场景绘图很重要的一件事是相对于父结点的变换。如果我们修改了父结点的方向,子结点也会受其影响发生改变。当我们把父结点沿X轴移动十个单位,所有的子结点也将会沿X轴移动十个单位。最后子结点的方向会根据所有父结点的方向而计算出来。这个概念将会在下面的图标中展示的更加清楚。 】

 

The position of MyEntity in this scene will be (10,0,0) and MyEntity2 will be at (10,10,20).
Let's try this in Ogre 3D.
【 MyEntity的在场景中的位置将会是(10,0,0)并且MyEntity2将会在位置(10,10,20)。然后让我们在Ogre 3D中尝试一下这个实验。 】

Pop quiz – finding the position of scene nodes
【 简单测试——找到场景结点的位置】

1.  Look at the following tree and determine the end positions of MyEntity
and MyEntity2:
a.  MyEntity(60,60,60) and MyEntity2(0,0,0)
b.  MyEntity(70,50,60) and MyEntity2(10,-10,0)
c.  MyEntity(60,60,60) and MyEntity2(10,10,10)

1.观察下面的树形结构并且判定MyEntity和MyEntity2的最终位置
a.  MyEntity(60,60,60) and MyEntity2(0,0,0)
b.  MyEntity(70,50,60) and MyEntity2(10,-10,0)
c.  MyEntity(60,60,60) and MyEntity2(10,10,10) 

 

Setting the position of a scene node
【 设置场景结点的位置 】
Now, we will try to create the setup of the scene from the diagram before the
previous image.
【 现在,对比上幅图片我们将会尝试创建如图表中描述的场景。 】

Time for action – setting the position of a scene node
【 实践时刻—— 设置场景结点的位置 】

1. Add this new line after the creation of the scene node:
【 在创建场景结点后添加以下一行代码: 】
node->setPosition(10,0,0);

2. To create a second entity, add this line at the end of the createScene() function:
【 在createScene()函数结尾中添加下面一行代码以创建第二个实体。 】
Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.
mesh");

3. Then create a second scene node:
【 然后创建第二个场景结点。 】
Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");

4.  Add the second node to the first one:
【 把第二个结点添加到第二个结点上 】
node->addChild(node2);

4. Set the position of the second node:
【 设置第二个结点的位置 】
node2->setPosition(0,10,20);

5. Attach the second entity to the second node:
【 把第二个实体关联到第二个结点上面:】
node2->attachObject(ent2);

6. Compile the program and you should see two instances of Sinbad:
编译这个程序然后你就会看到两个Sinbad 实例了

 

What just happened?
【 刚刚发生了什么?】

We created a scene which matches the preceding diagram. The frist new function we used
was at step 1. Easily guessed, the function setPosition(x,y,z) sets the position of the
node to the given triple. Keep in mind that this position is relative to the parent. We wanted
MyEntity2 to be at (10,10,20), because we added node2, which holds MyEntity2, to a
scene node which already was at the position (10,0,0). We only needed to set the position
of node2 to (0,10,20). When both positions combine, MyEntity2 will be at (10,10,20).
【 我们创建了一个和之前图解中相匹配的场景。我们在第一步使用的首个新函数。能够很容易的猜到,setPosition(x,y,z)函数是根据数组来设置结点位置的。记住这个位置是相对于父结点的位置。我们想要MyEntity2 在位置(10,10,20),因为我们添加了关联MyEntity2的node2结点,并且node2的父结点已经在位置(10,0,0)了。我们只需要设置node2的位置到(0,10,20)。当两个位置结合到一起,MyEntity2就在(10,10,20)了。 】

Pop quiz – playing with scene nodes
【 简单测试 —— 】

1.  We have the scene node node1 at (0,20,0) and we have a child scene node node2,
which has an entity attached to it. If we want the entity to be rendered 
at (10,10,10), at which position would we need to set node2?
a.  (10,10,10)
b.  (10,-10,10)
c.  (-10,10,-10)
【 我们现在有场景结点node1在(0,20,0)并且我们有个场景子结点在node2并且已经有一个提示关联上去了。如果我们想要实体在(10,10,10)位置被渲染,那么我们应该把node2设置在什么位置?
a.  (10,10,10)
b.  (10,-10,10)
c.  (-10,10,-10)

Have a go hero – adding a Sinbad
【 让英雄动起来 —— 添加一个Sinbad】

Add a third instance of Sinbad and let it be rendered at the position (10,10,30).
【 添加Sinbad的第三个实例兵器让他在位置(10,10,30)受渲染 】

Rotating a scene node
【 旋转一个场景结点】

We already know how to set the position of a scene node. Now, we will learn how to rotate a
scene node and another way to modify the position of a scene node.
【 我们已经知道如何设置一个场景结点的位置。现在,我们将会学习如何去旋转一个场景结点并且如何以另一种方式去修改一个场景结点。 】

Time for action – rotating a scene node
【 实践时刻 —— 旋转一个场景结点】

We will use the previous code, but create completely new code for the createScene()
function.
【 我们将会使用之前的代码,但是为createScene()函数创建全新的代码。 】

1.  Remove all code from the createScene() function.
【 移走createScene()函数中的所有代码。 】

2.  First create an instance of Sinbad.mesh and then create a new scene node.
Set the position of the scene node to (10,10,0), at the end attach the entity
to the node, and add the node to the root scene node as a child:
【 首先创建一个Sinbad.mesh 的实例并且然后创建一个新的场景结点。设置场景结点的位置到(10,10,0),在最后关联实体到结点,并且添加一个结点为场景根结点的子结点。 】

Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.
mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
node->setPosition(10,10,0);
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

3.  Again, create a new instance of the model, also a new scene node, and set the
position to (10,0,0):
【 同样的,创建一个新的实例模型,然后是一个新的场景结点,并且设置点到(10,0,0) 】

Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.
mesh");
Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");
node->addChild(node2);
node2->setPosition(10,0,0);

4.  Now add the following two lines to rotate the model and attach the entity to the
scene node:
【 现在添加以下两行到旋转模型并且关联实体到场景结点 】

node2->pitch(Ogre::Radian(Ogre::Math::HALF_PI));
node2->attachObject(ent2);

5.  Do the same again, but this time use the function instead of the function pitch
and the translate function instead of the setPosition function:
【 同样的,但是这次使用yaw函数代替pitch函数并且使用translate函数代替setPosition函数 】

Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad.
mesh");
Ogre::SceneNode* node3 = mSceneMgr->createSceneNode("Node3",);
node->addChild(node3);
node3->translate(20,0,0);
node3->yaw(Ogre::Degree(90.0f));
node3->attachObject(ent3);

7. And the same again with roll instead of yaw or pitch:
【 同样再次代替yaw()和pitch()函数使用roll()函数旋转 】

Ogre::Entity* ent4 = mSceneMgr->createEntity("MyEntity4","Sinbad.
mesh");
Ogre::SceneNode* node4 = mSceneMgr->createSceneNode("Node4");
node->addChild(node4);
node4->setPosition(30,0,0);
node4->roll(Ogre::Radian(Ogre::Math::HALF_PI));
node4->attachObject(ent4);
8. Compile and run the program, and you should see the following screenshot:
【 编译并且运行程序,并且你将会看到下面的截图 】

 

What just happened?
【 刚刚发生了什么? 】

We repeated the code we had before four times and always changed some small details. 
The first repeat is nothing special. It is just the code we had before and this instance of the
model will be our reference model to see what happens to the other three instances we
made afterwards. In step 4, we added one following additional line:
node2->pitch(Ogre::Radian(Ogre::Math::HALF_PI));The function pitch (Ogre::Radian(Ogre::Math::HALF_PI)) rotates a scene node around the x-axis. As said before, this function expects a radian as parameter and we used half of pi, which means a rotation of ninety degrees.
【 我们几乎重复了4遍我们的代码并且总是改变一些小细节。第一次的代码没有什么特别的。它仅是我们之前写过的一样的代码,但是这个实例会作为我们的参照物,用来对于其他三个实例在改变之后发生了什么。在第四步中,我们添加了下面一行代码:函数pitch (Ogre::Radian(Ogre::Math::HALF_PI)) 用来绕X轴旋转结点。就如我们之前所说的一样,这个函数接受一个弧度单位作为参数并且我们使用 π/2 ,也就是旋转90度。 】

In step 5, we replaced the function call setPosition(x,y,z) with translate(x,y,z). The difference between setPosition(x,y,z) and translate(x,y,z) is that setPosition sets the position—no surprises here. translate adds the given values to the position of the scene node, so it moves the node relatively to its current position. If a scene node has the position (10,20,30) and we call setPosition(30,20,10), the node will then have the position (30,20,10). On the other hand, if we call translate(30,20,10), the node will have the position (40,40,40). It's a small, but important, difference. Both functions can be useful if used in the correct circumstances, like when we want to position in a scene, we would use the setPosition(x,y,z) function. However, when we want to move a node already positioned in the scene, we would use translate(x,y,z).
【 在第五步中,我们代替setPosition(x,y,z) 函数调用了 translate(x,y,z) 函数。setPosition(x,y,z) 和translate(x,y,z)函数之间的不同setPosition()函数仅是设置点,没什么可说。Translate() 以给定的值设置点的位置,但是它是相对于现在的位置变换。如果一个场景结点在位置(10,20,30)并我们调用setPosition(30,20,10),那个结点在就在世界空间的位置(30,20,10)。另一方面,如果我们调用translate(30,20,10),结点就会在位置(40,40,40)。这点区别虽小,但是相当重要。如果我们在正确的环境中使用这两个函数他们都是有效的,比如当我们想要设置结点在场景中的位置,我们将会使用setPosition(x,y,z)函数。然而,当我们想要移动一个已经在场景中设置好的结点,我们将会使用translate(x,y,z). 】

Also, we replaced pitch(Ogre::Radian(Ogre::Math::HALF_PI))with yaw(Ogre::Degree(90.0f)). The yaw() function rotates the scene node around the y-axis. Instead of Ogre::Radian(), we used Ogre::Degree(). Of course, Pitch and yaw still need a radian to be used. However, Ogre 3D offers the class Degree(), which has a cast operator so the compiler can automatically cast into a Radian(). Therefore, the programmer is free to use a radian or degree to rotate scene nodes. The mandatory use of the classes makes sure that it's always clear which is used, to prevent confusion and possible error sources.

同样的,我们用yaw(Ogre::Degree(90.0f)) 代替 pitch(Ogre::Radian(Ogre::Math::HALF_PI))
函数。yaw() 函数绕Y轴旋转场景结点。我们使用Ogre::Degree() 来代替Ogre::Radian(),当然,Pitch和yaw仍然需要一个使用弧度参数。然而,Ogre 3D提供了一个可以使编译器自动转换角度到弧度的操作的Degree()类。因此,程序员可以随心所欲使用一个弧度或角度单位来旋转场景结点了。不同的类命令确保类的使用是清楚的,这样防止使用混淆或者可能出错的资源。

Step 6 introduces the last of the three different rotate function a scene node has, namely,
roll(). This function rotates the scene node around the z-axis. Again, we could use
roll(Ogre::Degree(90.0f)) instead of roll(Ogre::Radian(Ogre::Math::HALF_PI)).The program when run shows a non-rotated model and all three possible rotations. The left model isn't rotated, the model to the right of the left model is rotated around the x-axis, the model to the left of the right model is rotated around the y-axis, and the right model is rotated around the z-axis. Each of these instances shows the effect of a different rotate function. In short, pitch() rotates around the x-axis, yaw()  around the y-axis, and roll() around the z-axis. We can either use Ogre::Degree(degree) or Ogre::Radian(radian) to specify how much we want to rotate.
【 第六步介绍了三个不同旋转结点函数的最后一个函数,即是roll()函数。这个函数绕Z轴旋转场景结点。同样的,我们可以使用roll(Ogre::Degree(90.0f))来代替  roll(Ogre::Radian(Ogre::Math::HALF_PI))。当程序运行我们可以一个不同和三个已经旋转过了的模型。最左边的模型没有转动,左边模型的右边那个是绕X轴转动过的,最右边的模型左边的那个模型是绕Y轴旋转过的,最右边的模型是绕Z轴旋转过的。三个实例都显示了不同旋转函数的效果。简而言之,pitch()函数绕X轴旋转,yaw()函数绕Y轴旋转,roll()函数绕Z轴旋转。我们可以使用Ogre::Degree(degree) 或者Ogre::Radian(radian)其中一个来明确指明我们想要旋转的程度。 】

Pop quiz – rotating a scene node
【 简单测试—— 旋转一个场景结点 】

1.  Which are the three functions to rotate a scene node?
a.  pitch, yawn, roll
b.  pitch, yaw, roll
c.  pitching, yaw, roll

1. 哪个是旋转结点的三个函数?
a.  pitch, yawn, roll
b.  pitch, yaw, roll
c.  pitching, yaw, roll

Have a go hero – using Ogre::Degree
【 让英雄动起来 —— 使用Ogre::Degree 】

Remodel the code we wrote for the previous section in such a way that each occurrence of
Ogre::Radian is replaced with an Ogre::Degree and vice versa, and the rotation is still
the same.
【 修改我们之前输入的代码段,替换现有的Ogre::Radian为Ogre::Degree或反之亦然,旋转将会保持不变 】

Scaling a scene node
【 缩放一个场景结点 】
We already have covered two of the three basic operations we can use to manipulate our
scene graph. Now it's time for the last one, namely, scaling.
【 我们已经】
Time for action – scaling a scene node
【 实践时刻 —— 缩放一个场景结点 】

Once again, we start with the same code block we used before.
【 再一次,以我们之前用过的程序段作为我们的开始】
 
1.  Remove all the code from the createScene() function and insert the following
code block:
【 1. 移走createScene() 函数中所有代码并插入以下代码段 】

Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.
mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
node->setPosition(10,10,0);
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

2. Again, create a new entity:
【 2. 同样的,创建一个新实体:】

Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.

3.  Now we use a function that creates the scene node and adds it automatically as a
child. Then we do the same thing we did before:
【 3. 现在我们使用一个函数创建一个场景结点并且把它添加为一个子结点。然后同样我们照原来所做。】

Ogre::SceneNode* node2 = node->createChildSceneNode("node2");
node2->setPosition(10,0,0);
node2->attachObject(ent2);

3. Now, after the setPosition() function, call the following line to scale the model:
【 3. 现在,在setPosition() 函数之后,调用下面的一行来缩放模型:】

node2->scale(2.0f,2.0f,2.0f);

5.  Create a new entity:
【 创建一个新的实体:】

Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad.mesh");

6. Now we call the same function as in step 3, but with an additional parameter:
【 6. 现在我们调用第三步中同样的函数,但是添加一个新增的参数 】

Ogre::SceneNode* node3 = node->createChildSceneNode("node3",Ogre::
Vector3(20,0,0));

7. After the function call, insert this line to scale the model:
【 7. 在调用完函数之后,插入这一行以缩放模型:】

node3->scale(0.2f,0.2f,0.2f);

9. Compile the program and run it, and you should see the following image:
【 编译程序并运行,然后就就看到下面的图片了:】

 

What just happened?
【 刚刚发生了什么?】

We created a scene with scaled models. Nothing special happened until step 3. Then we
used a new function, namely, node->createChildSceneNode("node2"). This function
is a member function of a scene node and creates a new node with the given name and adds
it directly as a child to the node which called the function. In this case, node2 is added as a
child to the node.
【 我们创建一个有缩放模型的场景。在第三步之前没有什么特别的发生。然后我们使用了一个新函数,即是—— node->createChildSceneNode("node2")。这个函数是场景结点的一个成员函数并且用给定的名字创建新的场景结点,并且当调用函数时,直接添加新结点到指定的父结点。因此,node2被添加为node的子结点。 】

In step 4, we used the scale() function of the scene node. This function takes a triple (x,y,z),
which indicated how the scene node should be scaled. x, y, and z are factors. (0.5,1.0,2.0)
means that the scene node should be halved on the x-axis, kept the same on the y-axis, and
doubled on the z-axis. Of course, in a really strict sense, the scene node can't be scaled; it only
holds metadata which isn't rendered. It would be more precise to say that each renderable
object attached to this node would be scaled instead of the scene node itself. The node is only
a holder or reference frame for all attached children and renderable objects.
【 在第四步中,我们对场景结点使用了scale() 函数。函数使用数组(x,y,z)来表示场景结点是如何缩放的。想,x,y,z轴都是参数因子,如(0.5,1.0,2.0)表示场景结点应该在X轴上缩小一半,在Y轴保持不变,在Z轴放大一倍。当然,从严格意义上说,场景结点是不能缩放的,它只保存着不被渲染元数据。更严格的说每个渲染的对象将会代替原有结点造成缩放。所以说,结点只是一个关联子结点和渲染对象的容器和参考框架。 】

In step 6, we used the createChildSceneNode() function again, but this time with more
parameters. The second parameter that this function takes is a triple (x,y,z) which is so often
used. Ogre 3D has its own class for it called Ogre::Vector3. Besides storing the triple, this
class offers functions which implement the basic operations. They can be done with three
dimensional vectors in linear algebra. This vector describes the translate which should be
used when the scene node is created. createChildSceneNode() can be used to replace
the following lines of code:
【 在第六步中,我们又使用了createChildSceneNode()函数,但是这次有更多的参数。在这个函数中的第二个参数接收一个我们常用的数组(x,y,z)。Ogre3D也有自己调用(x,y,z)的类Ogre::Vector3。除了储存数组,这个类提供了实现基础操作的函数。使它们可以使用线代中的三维向量。这个向量描述了当场景结点被创建起来时,结点的变换。createChildSceneNode()函数使用代替了以下代码:】

Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");
node->addChild(node2);

or even
【或者甚至是】

Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");
   node->addChild(node2);
   node2->setPosition(20,0,0);

The last piece of code can be replaced with
【 在最后的一段代码可以被替换成 】

Ogre::SceneNode* node2 = node->createChildSceneNode("Node2",Ogre::Vector3(20,0,0));

If we leave out the Vector3 parameter, we can replace the first piece of code. There are
more versions of this function, which we will use later. If you can't wait, take a look at the
documentation of Ogre 3D at http://www.ogre3d.org/docs/api/html/index.html.
Besides scale(), there is also setScale(). The difference between these functions is
the same as between setPosition() and translate().
【 如果我们省略Vector3参数,我们替换第一段代码。这个函数还有很多版本,我们将会稍后展示。如果您有点迫不及待了,请浏览Ogre3D的网上文档http://www.ogre3d.org/docs/api/html/index.html.。除了scale() 函数,也有一个setScale() 函数。这两个函数之间的不同就好像setPosition()和translate()函数一样。

Pop quiz – creating child scene nodes
【 简单测试 —— 创建一个场景子结点 】

1.  Name two different ways of calling createChildSceneNode().
【 说出调用createChildSceneNode() 函数的两种不同方式 】

2. How could the following line be replaced without using createChildSceneNode()?
【 一下这行如果不用createChildSceneNode() 用何代码来代替?】

Ogre::SceneNode* node2 = node->createChildSceneNode("node1",Ogre::
Vector3(10,20,30));

This line could be replaced with three lines. The first creates the scene node, the second one translates it, and the third attaches it to the node.
【 这行代码可以用三行代码来代替。第一行是创建场景结点,第二行是变换结点,第三行是把它绑定到node结点上。】

Ogre::SceneNode* node2 = mSceneMgr->createSceneNode("Node2");
node2->translate(Ogre::Vector3(10,20,30));
node->addChild(node2);
Have a go hero – using createChildSceneNode()
【 让英雄动起来 —— 使用createChildSceneNode() 函数 】

Refactor all the code you wrote in this chapter to use createChildSceneNode().
【 使用createChildSceneNode() 函数来重构这章你写的所有代码。 】

Using a scene graph the clever way
【 用聪明的方式使用场景绘图 】

In this section, we will learn how we can use the characteristics of a scene graph to make
some tasks easier. This will also expand our knowledge about a scene graph.
【 在这部分,我们将会学习如何使用场景绘图的一些特性使得场景绘图更加简单。这也将会扩展我们关于场景绘图的认识。】

Time for action – building a tree using scene nodes
【 实践时刻 —— 使用场景结点创建树。 】

This time, we are going to use another model besides Sinbad: the ninja.
【 这次,我们将会使用除Sinbad的另一个模型。 】

1.  Remove all the code from the createScene() function.
【 移去createScene() 函数中的所有代码。 】
2.  Create Sinbad like we always do:
【 用我们之前的方法创建一个Sinbad。 】
Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.
mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
node->setPosition(10,10,0);
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

3. Now create a ninja, which will follow Sinbad everywhere he goes:
【 现在创建一个可以到处跟着Sinbad移动的ninja。(译者注:Sinbad 是天方夜谭中的水手辛巴达,ninja是日本忍者。)】
Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntitysNinja","ninja.mesh");
Ogre::SceneNode* node2 = node->createChildSceneNode("node2");
node2->setPosition(10,0,0);
node2->setScale(0.02f,0.02f,0.02f);
node2->attachObject(ent2);
4.  Compile and run the application. When you take a closer look at Sinbad, you
will see a green ninja at his left arm.
【 编译并且运行应用程序。当你靠近看Sinbad的时候,你将会看到一个绿色的ninja的在他的左手边。】
 
4. Now change the position to (40,10,0):
【 现在改变位置到(40,10,0)。 】
node->setPosition(40,10,0);

5. And rotate the model 180 degree around the x-axis:
【 把模型绕X轴旋转180度。】
node->yaw(Ogre::Degree(180.0f));

7.  Compile and run the application.
【 编译并运行应用程序。 】

8.  You should see that the ninja is still at the left-hand of Sinbad and Sinbad is rotated.
【 你将会看到ninja任然在Sinbad的左手边并且Sinbad被旋转了 】

 

What just happened?
【 刚刚发生了什么?】

We created a sneaky ninja who follows each step of Sinbad. We made this possible because
we added the node the ninja model is attached to as a child to the scene node Sinbad is
attached to. When we moved Sinbad, we used his scene node, so each transform we did is
also done to the ninja, because this scene node is the child of the node we modify, and as
said before, the transformation of a parent is passed to all its children. This fact about scene
nodes is extremely helpful to create the following models or complex scenes. Say, if we
wanted to create a truck which carries a complete house, we could create the house using
a lot of different models and scene nodes. At the end, we would have a scene node where
the whole house and its interior are added as children too. Now when we want to move
the house, we simply attach the house node to the truck or anything else, and if the truck
moves, the complete house moves with it.
【 我们创建了一个鬼鬼祟祟跟随Sinbad的ninja。我们可以实现是因为我们把ninja模型关联为Sinbad场景结点的一个子结点。当Sinbad移动的时候,我们使用了他的场景结点,所以每步他的变换也会给ninja,因为他的场景结点是我们设置的Sinbad的子结点,并且如我们之间所说,一个父结点的变换将会传递给它所有的子结点。关于场景这一点对创建附加模型和复杂场景极其有用。如是说,如果我们想要创建一个装有房子的卡车,我们会使用多种不同的模型和场景结点。最终,我们将会有一个房子的场景结点和房子内部的东西作为它的子结点。现在我们想要移动房子,我们只需要简单关联房子结点到卡车结点或者别的什么,并且如果卡车移动了,整个房子也将会一起移动。】

 

The arrows show the direction the transformations are propagated along the scene graph.
【 箭头符号显示出场景绘图方向的变换是沿箭头方向一直传下去的。】
Pop quiz – even more about the scene graph
【 简单测试 ——  关于场景绘图 】

1.  How is transformation information passed in a scene graph?
【 在一个场景绘图中变换是如何传递的?】

a.  From the leaves to the root
b.  From the root to the leaves
【 a   从叶子结点到根结点。
   b  从根结点到叶子结点。

Have a go hero – adding a following ninja
【 让英雄动起来 —— 添加一个跟随着的ninja 】

Add a second ninja to the scene, which follows the first ninja.
【 添加第二个跟随着第一个日本忍者的忍者到场景之中。】

Different spaces in a scene
【 在场景中的不同空间。】
In this part, we will learn that there are different spaces in a scene and how we can use
these spaces.
【 在这部分,我们将会学习场景中的不同空间并且如何使用这些空间。 】

Time for action – translating in World space
【 实践时刻 —— 变换世界空间 】

We are going to move an object in a different way from what we are used to.
【 我们将会移动用一种与往常不同的方式移动对象。】

1.  Again, start with an empty createScene() function; so delete every code you
have in this function.
【 1. 同样,我们以一个空的createScene()函数开始;所以在使用前清空函数中的所有代码。】
2. Create a reference object:
【 2.创建一个引用模型。】

Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad.
mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
node->setPosition(0,0,400);
node->yaw(Ogre::Degree(180.0f));
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

3. Create two new instances of the model and translate each one with (0,0,10):
【 3.创建两个新的模型实例并且变换每个实例用相对位移(0,0,10)。】
Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad.
mesh");
Ogre::SceneNode* node2 = node->createChildSceneNode("node2");
node2->setPosition(10,0,0);
node2->translate(0,0,10);
node2->attachObject(ent2);
Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad.
mesh");
Ogre::SceneNode* node3 = node->createChildSceneNode("node3");
node3->setPosition(20,0,0);
node3->translate(0,0,10);
node3->attachObject(ent3);

4.  Compile and run the application. Navigate the camera until you see the previous
models like the following:
【 4.编译并且运行应用程序,操纵你的摄像机直到你看到前面的模型得到下面的效果。】

 

5.Replace the line:node3->translate(0,0,10);with
node3->translate(0,0,10,Ogre::Node::TS_WORLD);
【 换node3->translate(0,0,10)这行代码为node3->translate(0,0,10,Ogre::Node::TS_WORLD);】
6. Again, compile and run the application and navigate the camera like before.
【 同样的,编译并且运行应用程序并且像以前一样操控摄像机。】
 
   

What just happened?
【 刚刚发生了什么?】

We used a new parameter of the translate() function. The result was that the left model
in the scene moved in a different direction to the middle model.
【 我们使用了translate() 函数的一个新的参数。这造成了场景中左边的模型相对与中间的模型移动了不同的方向。 】

Different spaces in a 3D scene
【 在3D场景中不同的空间。 】

The reason why the model moved differently is because with Ogre::Node::TS_WORLD, we
told the translate() function that the translate should happen in world space and not in
parent space, where it is normal. There are three kinds of spaces we have in a 3D scene—
world space, parent space, and local space. Local space is where the model itself is defined.
A cube consists of eight points and can be described as in the following diagram:
【 模型移动方向的不同的因为使用了Ogre::Node::TS_WORLD ,我们告诉translate() 函数变换是发生在世界空间的而非一般的父空间。我们在3D场景中有三种空间——世界空间,父空间和局部空间。局部空间是模型本身定义的。如一个立方体有8个点并且可以用以下的图来说明:】
 
The black point is the null point of local space. Each point of the cube is described as a
translate from the null point. When the scene is rendered, the cube needs to be in world
space. To get the cube in world space, all transformations of these parents in the scene graph
are applied to these points. Let's say the cube is attach to a scene node which is added to
the root scene node with a translate of (10,0,0). Then the world space with the cube would
look like this:
【 黑色的点是立方体的原点。立方体的每个点都是相对于原点来表示的。当场景被渲染的时候,这个立方体就需要在世界空间中。为了获得在世界空间的立方体的坐标,在场景绘图中立方体中所有结点的应变换适用于世界空间坐标。比方说立方体关联上一个已经关联到场景根结点的结点上面,并且使用变换了(10,0,0)。然后在世界空间中这个立方体就变为了这样:】
 

The difference between the two cubes is that the null point has shifted its position, or to 
be more precise, the cube has been moved away from the null point.
【 两个立方体的不同之处在于原点的变换了位置,或者更准确的说,这个立方体远离了原点。】

When we call the translate() function, the cube is moved in parent space if the space to use is not defined, like we did in step 5. When no parent of the cube is rotated, translate() behaves the same way with world space as it would when used with parent or local space. This is true because only the position of the null point changes and not the orientation of the axes. When we, say, move the cube (0,0,10) units, it doesn't matter where the null point is—as long as the axes of the coordination system are orientated the same, it won't change the outcome of the translate process. However, when a parent is rotated, this is no longer true. When the parent is rotated, this also rotates the axis of the null point, which changes the meaning of translate(0,0,10).
【 当我们调用translate() 函数,如果没有定义使用的空间的话,立方体就相对于父空间移动,就如第五步所做的一样。当没有父结点的立方体被旋转,使用父空间或者局部空间translate() 函数表现为和世界空间为同一种方式。这是因只有原点的位置改变了并且主轴的方向并没有改变。当我们说移动立方体(0,0,10),原点在哪无关紧要—— 只要坐标系的主轴的方向是正确的,变换后的结果不会改变。然而,当一个父结点被旋转后,这个观点就不再正确了。当父结点旋转的时候,原点的轴也会旋转,同时也会改变translate(0,0,10) 的意义。】

 

The left coordination system is not rotated and (0,0,10) means moving the cube 10 units
nearer to the viewer. This is because the z-axis is pointing out of the screen. With the 180
degree rotation, (0,0,10) means moving the cube 10 units away from the viewer because 
the z-axis is pointing into the screen.
【 左边的坐标系并没有旋转并且(0,0,10)表示移动立方体让观察者感觉到拉近了10个单位。这使因为z轴是代表着指向屏幕外的方向。当坐标轴旋转180度,(0,0,10)就表示立方体远离观察者10个单位,因为Z轴已经指向了屏幕里面。】

We see that it is important in what space we describe the translate() function to get the
desired effect. World space always has the same orientation of axis. To be precise, world
spaces uses the left coordination system. Parent space uses a coordination system where all
rotations from the parent upwards are applied. Local space includes all rotations, from the
scene node itself to all parents. The default setting of translate() is to use parent space.
This enables us to rotate the node itself without changing the direction a node moves when
using translate().
【 我们可以看到达到既定效果,translate() 函数是调用在哪个空间是十分重要的。世界空间主轴的方向总是相同的。更准确的说,世界空间使用了左边的坐标系。父空间的所有旋转使用了上一个父结点自身的坐标系。局部的坐标系包含了全部的旋转,不论是场景结点本身还是所有的父结点。translate()的默认设置时使用父空间。当结点移动使用translate() 函数,使我们可以旋转场景结点时不需要改变结点的方向。】
But there are cases when we want to translate in a space different
to parent space. In such cases, we can use the second parameter from translate(). The
second parameter specifies the space we want the translate to happen in. In our code, we
used Ogre::Node::TS_WORLD to move the model in world space, which inverted the
direction the model used because we rotated the node around 180 degrees, and with this,
flipped the direction of the x-and z-axis. Again, look at the image to see the effect.
【 但是在某些情况下当我们想要在不同的空间发生变换而非在一个父空间。在这些情况下,我们使用translate()函数的第二个参数。第二个参数定义了我们想要变换发生的空间。在我们代码中,我们使用Ogre::Node::TS_WORLD 使模型在世界空间中移动,这就变为模型反向旋转,因为我们的模型之前已经旋转过180度,这样,X轴和Z轴的方向都改变了。再一次的观察图片查看效果。】


Translating in local space
【 在局部空间中变换】
We've already seen the effect of translating in parent and world space. Now we will translate in local and parent space to see the difference and get a deeper understanding of the differences between the spaces.
【 我们已经看到在父空间和时间空间的变换。现在我们将会在局部和父空间变换以区别两者的不同并且对空间之间的不同有个更深的认识。】
Time for action – translating in local and parent space
【 实践时刻—— 在局部和父空间中变换 】
1. Clear the createScene() function once again.
【 再次清空createScene()函数】
2. Insert a reference model; this time we will move it nearer to our camera so we don't have to move the camera so much:
【 插入一个参考模型。这次我们将会移动模型离我们的摄像器更近,所以我们就不用移动摄像机了。】
Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","Sinbad. mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
node->setPosition(0,0,400);
node->yaw(Ogre::Degree(180.0f));
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);
3. Add a second model and rotate it by 45 degrees around the y-axis and translate it (0,0,20) units in parent space:
 【 添加第二个模型并且绕Y轴旋转45度并且在父空间中移动(0,0,20) 】
Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","Sinbad. mesh");
Ogre::SceneNode* node2 = node->createChildSceneNode("node2");
node2->yaw(Ogre::Degree(45));
node2->translate(0,0,20);
node2->attachObject(ent2);

4. Add a third model and also rotate it 45 degrees around the y-axis and translate it (0,0,20) units in local space:
 【 添加第三个模型,同样绕Y轴旋转45度并且在局部空间中移动(0,0,20) 】
Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad. mesh");
Ogre::SceneNode* node3 = node->createChildSceneNode("node3");
node3->yaw(Ogre::Degree(45));
node3->translate(0,0,20,Ogre::Node::TS_LOCAL);
node3->attachObject(ent3);
4. Compile and run the application. Then navigate the camera again so that you see the model from above.
【 编译并运行应用程序。然后再次操控摄像机你就可以从上面看到模型了.】

 

What just happened?
【 刚刚发生了什么? 】

We created our reference model and then added two models which were rotated 45 degrees
around the y-axis. Then we translated both with (0,0,20), one model in parent space, the
default setting, and the other model in local space. The model we translated in parent space
moved in a straight line on the z-axis. But because we rotated the models around the y-axis,
the model we translated in local space moved with this rotation and ended up moving up
and left in the image. Let's repeat this. When we translate, the default setting is parent
space, meaning that all rotations, except the rotation of the scene node we translate, are
used while translating. When using world space, no rotation is taken into consideration.
When translating, the world coordination system is used. When translating in local space,
every rotation, even the rotation from the node we translate, is used for the translation.
【 我们创建了一个参考模型并且然后添加了两个绕Y轴旋转45度的模型。然后我们两个都移动(0,0,20),一个模型在默认的父空间,另一个在局部空间。在父空间的移动过的模型是直接朝Z轴移动的。但是因为我们绕Y轴旋转了模型,在局部空间中的移动模型,它将会以面向这个角度移动并且最终停在了途中的左上。让我们重复一下。
当我们移动的使用,默认的的设置是父空间,这意味着所有除了旋转过的场景结点都是使用父空间移动的。
当使用世界空间时,旋转是不被考虑进去的。当我们移动的时候,使用的就是就是世界坐标系。
当在局部空间移动的时候,每个旋转,甚至是我们移动过的结点的旋转,都会被用于移动变换。】

Pop quiz – Ogre 3D and spaces
【 简单测试——Ogre3D和空间】

Name three different spaces that Ogre 3D knows.
【 指出在Ogre3D中不同的3个空间】

Have a go hero – adding symmetry
【 让英雄移动起来—— 添加对称】

Change the rotation and translation of the MyEntity2 to make the image symmetric. Make
sure you use the right space; otherwise, it's difficult to create a symmetric image. Here is
how it should look afterwards:
【 改变MyEntity2的旋转和移动使效果图对称。确定你使用了正确的空间。否则,创建一个对称的效果图是十分困难的。这就是之后的效果图。】

 

Time for action – rotating in different spaces
【 实践时刻—— 在不同的空间中旋转 】

This time, we are going to rotate using different spaces, as follows:
【 这次,我们将会使用不同的空间旋转,如下所述】

1. And again, we will start with a clean createScene() function, so delete all code
inside this function.
【 同样的,我们将会以一个干干净净的createScene() 函数作为开始,所以删除这个函数内的所有代码。】

2. Add the reference model:
【 添加参照模型:】

Ogre::Entity* ent = mSceneMgr->createEntity("MyEntity","sinbad.
mesh");
Ogre::SceneNode* node = mSceneMgr->createSceneNode("Node1");
mSceneMgr->getRootSceneNode()->addChild(node);
node->attachObject(ent);

3. Add a second model and rotate it the normal way:
【 添加第二个模型并且以一般的方式旋转它:】

Ogre::Entity* ent2 = mSceneMgr->createEntity("MyEntity2","sinbad.
mesh");
Ogre::SceneNode* node2 = mSceneMgr->getRootSceneNode()-
>createChildSceneNode("Node2");
node2->setPosition(10,0,0);
node2->yaw(Ogre::Degree(90));
node2->roll(Ogre::Degree(90));
node2->attachObject(ent2);

4. Add a third model using world space:
【 使用时间空间添加第三个模型:】

Ogre::Entity* ent3 = mSceneMgr->createEntity("MyEntity3","Sinbad.
mesh");
Ogre::SceneNode* node3 = node->createChildSceneNode("node3");
node3->setPosition(20,0,0);
node3->yaw(Ogre::Degree(90),Ogre::Node::TS_WORLD);
node3->roll(Ogre::Degree(90),Ogre::Node::TS_WORLD);
node3->attachObject(ent3);

5. Compile and run the application.
【 编译并运行程序 】
 

What just happened?
【 刚刚发生了什么? 】

Like always, we created our reference model, which is the left one in the picture. We
rotated the second model—first around the y-axis and then around the z-axis. Rotation 
uses the default space as the local space. This implies that after we rotated the first model 90
degrees around the y-axis, the orientation of z-axis is changed. The second model used the
world coordination system and there the orientation of the z-axis stays the same, even when
we rotated a scene node.
【 如往常一样,我们创建我们的图中左侧的那个参考模型。我们旋转第二个模型—— 首先绕Y轴旋转并且然后绕Z轴旋转。旋转使用默认的空间作为局部的空间。这意味着我们把第一个模型绕Y轴旋转90度,Z轴的方向就改变了。第二个模型使用了世界坐标系并且Z轴的方向总是保持不变,甚至当我们已经旋转过场景结点。 】

 

The model under number 1 is the original coordination system we had. Under number 2, we
see the coordination system after we rotated 90 degrees around the y-axis. Under number 3,
we rotated 90 degrees around the z-axis. Now let's look at the same rotations when we use
world space instead of local space.
【 在一号模型中的坐标系是我们原始的坐标系。在二号中,我们看到经绕Y轴旋转90度之后的坐标系,在三号中,我们沿Z轴旋转90度。现在我们将会看代替局部空间使用世界空间后的变换。 】

 

Here we are doing the same rotations, but because we always used world space, we didn't
use the changed coordination system, and therefore we got a different result.
【 虽然我们做同样的旋转,但是因为总是使用世界空间,我们不使用改变了的坐标系,那样会得到一个不同的结果。】

Scaling in different spaces
【 在不同空间的缩放比例 】

Scaling is always done to the initial model, so there aren't different spaces for scaling. It
wouldn't make much sense to scale in different spaces because there isn't really any need 
to do it.
【 缩放比例在模型建立之初就完成了,因此在不同空间的缩放是相同的。在每个空间设置缩放比例是没有必要的,因为我们没有必要去做这件事。 】

Summary
【 概要】

We learned a lot in this chapter about the scene graph Ogre 3D uses and how to work with it
to create complex scenes.
【 我们在这章学习了很多关于使用Ogre3D绘图和用它去创建复杂的场景的知识。 】

Specifically, we covered the following:
  What a scene graph is and how it works
  Different ways for changing the position, rotation, and scaling of scene nodes
  What different kinds of spaces we have for rotations and translation
  How we can cleverly use the scene graph's properties to create complex scenes
 
【具体有以下几点:
1. 为什么是场景绘图并且它的如何起作用的。
2. 改变位置,方向和结点缩放比例的不同方法。
3. 我们用于旋转和变换的不同坐标系我们如何灵活的使用场景绘图的特性去创建复杂的场景。】


After being able to create complex scenes in the next chapter, we are going to add light,
shadows, and create our own camera.
【 之后,在下一章我们将会创建更加复杂的场景,我们将会添加灯光,阴影,并且创建我们自己的摄像机。 】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值