A闪的 BLOG 技术与人文
这部分内容会非常好玩,还记得第一章里那些枯燥无趣的数学概念和数学公式么。和大学一样,我们学了很多东西,去并不知道这些内容用什么卵用。现在我们将会把这些数学知识巧妙的组合到一起,让它们产生巨大的威力。
要想了解移动的操作,我们先需要了解位置的设置操作。
所谓单项位置设置,就是指每次位置设置操作针对x,y,z单独操作。
作者偷个懒,直接使用立方体做演示,为了保证最佳观看效果,摄像机固定在(0,-300,300)
的位置。
一切准备就绪后,我们现在创建立方体,代码可以参考上一节中的内容。然后设置立方体网格对象的x坐标。
this._view3D.camera3D.lookAt(new egret3d.Vector3D(0,-300,300),new egret3d.Vector3D(0,0,0));
var cube:egret3d.CubeGeometry = new egret3d.CubeGeometry();
var mat:egret3d.TextureMaterial = new egret3d.TextureMaterial();
this.model = new egret3d.Mesh(cube, mat);
this._view3D.addChild3D(this.model);
//this.model.x = 0; //第一次x设置为0
this.model.x = 100; //第二次x设置为100
查看两次运行后的效果:
摄像机的位置并没有变,变得只是立方体的位置。于此同理,你自己可以修改y轴和z轴来查看效果。
与单项位置设置,多项位置设置是使用一行代码同时设置x,y,z三个轴坐标。如果是多项移动,使用position
属性就可以达到我们想要的效果。
position
属性是一个类型为Vector3D
的可读可写变量。Vector3D
对象,包含x,y,z三个属性,恰巧与我们的三维坐标相符,使用也非常直观。和上面的Demo相同,我们改变x轴坐标为100的代码如下:
this.model.position = new egret3d.Vector3D(100,0,0,0);
效果大家可以自行coding查看。
前面讲的单项位置设置和多项位置设置我们可以理解为已知终点位置,直接设置数值。如果将其看成移动操作的化,我们可以将其称之为”绝对位置移动“。那么有没有”相对位置移动“呢?
答案是有!
按照前面的例子,我们可以描述为”x轴移动到100的位置“。如果是相对位置移动,则描述为”x轴向左移动100个距离“。好了,我们来看一下相对位置移动的写法。
this.model.x += 100;
代码不难理解,如果将其拆解,则完整表达式如下:
this.model.x = this.model.x + 100;
这是单项设置,如果是对象设置应该如何操作呢?
this.model.position = this.model.position.add(new egret3d.Vector3D(100,0,0,0));
这里需要注意的一点是,Vector3D的add方法会将两个向量的计算结果作为一个新Vector3D对象返回,而不是修改原有Vector3D对象数据,所以计算后需要一个赋值操作。
代码不难理解,我们对原有坐标进行一个向量加的操作。但是向量加为什么会有移动的效果呢?这里需要一个“几何解释”。
为了方便讲解,我们忽略y轴,把三维空间变成二维空间。虽然少了一个轴,但是原理是相同的。同时我们把Vector3D
变成“Vector2D”(Egret3D中并没有Vector2D这个类,这里仅是为了方便大家理解而估计创造出来的一个概念)。
假设我们在一个2D坐标系中,存在一个点,这个点的位置是(1,2)。
我们要将其移动到 (3, 1) 的位置。描述为,向右移动2个距离,向下移动1个距离。
如果是单项操作,伪代码如下:
point.x += 2;
point.y -= 1;
拆分成两步来看的化,我们的图像变化如下:
那么这次移动几何图形来表达就是如下图中带有箭头的虚线。
用数学表达法就是
结合刚才的几何解释,如果是写成数学公式的化,那么这个点的相对位置移动向量表达式如下:
如果你理解这2D空间中,使用二维向量进行相对位置移动操作的化,那么三维空间也不难理解,仅仅是增加一个z轴而已。对于前面的示例,我们可以将其总结为如下公式:
旋转操作与移动操作相似,也存在绝对角度旋转和相对角度旋转,其几何意义也相同。这里不再对几何意义进行赘述,我们更加深入的讨论与旋转操作的一些特定问题。
我们已然使用上一节中出现的立方体作为示例Demo,为了更好的观察旋转效果,我们将摄像机的位置放置于 (0,0,-300) 上。
Tip
Egret3D中旋转角度所使用的单位是度,旋转一周则为360度。
绝对单项旋转,你可以直接设置rotationX、rotationY和rotationZ属性。代码如下:
this.model.rotationX = 120;
this.model.rotationY = 70;
this.model.rotationZ = 190;
如果是旋转相对角度的话,代码如下:
this.model.rotationX += 120;
this.model.rotationY += 70;
this.model.rotationZ += 190;
运行效果如图:
多项角度旋转代码会简单很多,只需要设置其rotation
属性即可。不仅如此,和position
属性一样类型为Vector3D
。唯一不同的是,此时Vector3D
对象的x,y,z属性所代表的含义分别为绕x轴旋转角度,绕y轴旋转角度和绕z轴旋转角度。
如果我们想设置立方体x,y,z轴旋转角度分别为50,60,70,那么代码如下:
this.model.rotation = new egret3d.Vector3D(50,60,70);
如果旋转角度每次累加值为正数,我们称之为正向旋转,反之称之为反向旋转。那么正向旋转的方向是什么样的,下图可以很好的解释清楚。值得注意的是,Egret3D所使用的是左手坐标系,默认情况下,x轴向右侧无限延伸扩大。
Tip
另外一种更加简单的记忆方式,对于每个轴,如果把它的方向面冲你,那么正向旋转方向都是顺时针的。
Egret3D中没有对角度极限值做限制,你可以设置旋转角度为1200度。这样的好处在于可以通过角度计算出当前物体旋转了几周。但你需要避免旋转角度过大。当角度值超出JavaScript中Number极限值之后,显示效果将发生错误。
设置缩放每一个轴的缩放属性,其中z轴不进行缩放,其值为1。
this.model.scaleX = 2;
this.model.scaleY = 0.5;
this.model.scaleZ = 1;
运行后,效果如图:
同时缩放3个坐标轴,使用scale
属性,其类型为Vector3D
。
this.model.scale = new egret3d.Vector3D(2,0.5,1);
运行效果与上面相同。