四、位置、旋转、尺寸缩放
BabylonJs的3D场景中通过特定的方法传入数值来调整物体的位置、旋转与尺寸缩放。
无论使用什么方法,它们都需要一个参照系,一种描述位置、旋转或缩放的方法以及帮助可视化应用这些效果的东西。可视化可以帮助使用者建立一个不对称的形状。
参考框架
BabylonJs一般使用世界坐标系(World axes)和局部坐标系(Local axes)两种坐标系作为参考框架,其中世界坐标的轴心位置不会发生改变。
在所有图表和场景里上,X轴是红色的,Y轴是绿色的,Z轴是蓝色的。
当物体网格(meshes)被创建时,它们的中心点被放置在世界坐标的原点,它们的位置总是相对于世界坐标的。
局部坐标会跟随物体网格移动。无论物体网格的位置在哪,局部坐标的原点总是在物体网格的创建中心。一个物体网格的旋转和放大的中心在局部坐标轴原点,然而它们是可以通过TransformNode或通过矩阵来设置一个支点改变它们的中心。
向量(Vectors)
所有的位置、旋转和尺寸大小都由三维向量来描述,可以使用 new BABYLON.Vector3(x,y,z) 来分别设置它们。
试验
下图中的试验物体中心在世界坐标的原点,所有轴的旋转为0,尺寸大小为1,世界坐标系和试验物体的局部坐标系重合了。
位置(Position)
试验物体使用向量Vector(x,y,z)来描述它的位置,它的局部坐标随着物体本身移动。
pilot.position = new BABYLON.Vector3(2, 3, 4);
//或者单独赋值
pilot.position.x = 2;
pilot.position.y = 3;
pilot.position.z = 4;
试验物体的局部坐标保存原有的方向。
旋转(Rotation)
在3D空间中的旋转总是很复杂的,你需要知道物体旋转的顺序以及它是如何被应用于的物体旋转,同时你也需要知道该次旋转是对应哪个坐标系而产生改变的。在三维建模中应用旋转还有许多不同的约定。
在BabylonJs中,物体的旋转的使用方式如下:
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
//或者单独赋值
pilot.rotation.x = alpha; //绕x轴旋转
pilot.rotation.y = beta; //绕y轴旋转
pilot.rotation.z = gamma; //绕z轴旋转
其中α,β和γ是表示弧度的角度。
在这里三个旋转给出了三个不同的轴,你可能会有疑问——“它适用于哪一个参照系?它是以什么样的顺序来描述的?以及它在哪个方向?”。
在BabylonJs中,以下两个公约被使用时会被认为该旋转导致了相同的结果。
公约1 - 局部坐标轴(Local Axes)
对于使用局部坐标轴旋转物体时,是先以Y、X、Z轴的顺序旋转网格物体的,旋转的顺序是逆时针。
下面的图像显示的起始位置的按局部坐标轴的Y轴逆时针旋转π/ 2,然后按局部坐标轴的X轴逆时针旋转π/ 2,最后按局部坐标轴的Z轴逆时针旋转π/ 2。
较小的轴代表世界轴心的方向。
(这里其实乍一看比较难看懂,我自己是这么理解的首先是看y轴从下往上看即以y轴正方向查看,然后进行旋转,可以看出是逆时针旋转,其它轴也一样,从原点到箭头的方向看去再来理解如何旋转)
公约2 - 世界坐标轴(World Axes)
与公约1相比,旋转中心及旋转轴都没有改变。
对于使用世界坐标轴旋转物体时,是先以Z、X、Y轴的顺序旋转网格物体的,旋转的顺序是逆时针。
下面的图像显示的起始位置的按世界坐标轴的Z轴逆时针旋转π/ 2,然后按世界坐标轴的X轴逆时针旋转π/ 2,最后按世界坐标轴的Y轴逆时针旋转π/ 2。
总结
不管你怎么想旋转,结果都是一样的,下面的结果都是一样的。
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
pilot.rotation.x = alpha;
pilot.rotation.y = beta;
pilot.rotation.z = gamma;
pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
pilot.rotation.y = beta;
pilot.rotation.y = beta;
pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
旋转的先后顺序
现在的问题是,如果你想要进行首先是关于x轴,然后是y轴,然后是z轴的一系列的旋转,该怎么办呢?
对世界坐标轴和局部坐标轴而言,BabylonJs都有对应的rotate和addRotation方法 。
你可以连续地轮换使用addRotation。此方法提供一个轴的一个旋转值,一系列可以从第一个到最后一个应用,如下示例所示:
mesh.addRotation(Math.PI/2, 0, 0).addRotation(0, Math.PI/2, 0).addRotation(0, 0, Math.PI/2);
由下图可以看到,物体网格是从初始位置绕局部坐标的X轴逆时针旋转π/ 2,然后绕局部坐标的Y轴逆时针旋转π/ 2,最后绕局部坐标的Z轴逆时针旋转π/ 2。
较小的轴代表世界轴心的方向。
在一般的网格里,使用addRotation(alpha, beta, gamma)进行旋转,通常都有其中两个属性为0。
尺寸缩放(Scaling)
尺寸是物体在沿其局部坐标缩放的时候使用的。
mesh.scaling = new BABYLON.Vector3(scale_x, scale_y, scale_z);
//或者单独赋值
mesh.scaling.y = 5;
下图显示了一个单位立方体,围绕Z轴旋转π/2后,沿着局部坐标轴的Y轴缩放。