Kol*_*ban 7 javascript rotation three.js
更新:添加了一个jsfiddle来说明:
我有一个放置在场景中的对象(立方体).我的目标是提供3个角度,代表物体在现实世界中的方向.角度将根据实际的X,Y和Z轴进行测量.我失败(悲惨)是如何给对象这些角度,然后随着数据的变化,设置对象以接收新的三角形.我似乎发现的是,当我设置一组初始角度时,一切都很好,但是当我设置一组新角度时,它们似乎相对于局部对象空间方向而不是世界空间进行设置.我试图理解在这个领域提出的一些类似问题,但这些问题似乎是关于围绕轴旋转对象而不是明确地将对象的角度设置为世界轴.
当我的x,y或z角度的值发生变化时,我正在调用:
cube.rotation.set(x, y , z, 'XYZ');
Run Code Online (Sandbox Code Playgroud)
为了进一步说明,这里是我的立方体的屏幕截图...没有改变X或Y,我绕Z旋转90 ...看到之前和之后的两个图像
和
注意旋转是如何围绕紫色面的法线方向发生的,而不是围绕世界Z轴...
我很难过:-(
cube.rotation.set(),正如您已经发现的那样,沿着对象的局部轴创建一个旋转.在第一次旋转期间,例如,沿着X,世界坐标中的局部X轴恰好等于世界X轴.然而,在旋转之后,世界坐标中的局部Y轴和Z轴不再等于世界Y轴和Z轴.因此,沿着这些轴的后续旋转将不再像沿世界轴的旋转那样.如果更改旋转顺序,则只会在本地空间中发生第一次旋转,该空间偶然与世界空间相同.所有后续旋转将在不再相同的局部空间中计算.
您想要旋转对象三次:沿世界X轴一次,沿世界Y轴一次,沿世界Z轴一次.但我们现在知道所有轮换都发生在当地空间.在世界空间中进行旋转的关键是问一个问题:"这个世界轴在我的物体的局部空间中是什么样的?" 如果你可以采用世界轴,将其表示为对象局部空间中的向量,然后沿着该向量进行旋转,那么无论特定的局部空间如何,您都可以沿着世界向量自行旋转.
让我们将这个想法融入你的小提琴:
var x = toRadians($("#rotateX").slider("option", "value"));
var y = toRadians($("#rotateY").slider("option", "value"));
var z = toRadians($("#rotateZ").slider("option", "value"));
var rotation = new THREE.Matrix4();
rotation.multiply(new THREE.Matrix4().makeRotationX(x));
var worldYAxis = new THREE.Vector3(0, 1, 0).applyMatrix4(new THREE.Matrix4().getInverse(rotation));
var rotationWorldY = new THREE.Matrix4().makeRotationAxis(worldYAxis, y);
rotation.multiply(rotationWorldY);
var worldZAxis = new THREE.Vector3(0, 0, 1).applyMatrix4(new THREE.Matrix4().getInverse(rotation));
var rotationWorldZ = new THREE.Matrix4().makeRotationAxis(worldZAxis, z);
rotation.multiply(rotationWorldZ);
cube.matrixAutoUpdate = false;
cube.matrix = rotation;
Run Code Online (Sandbox Code Playgroud)
如果您尝试此代码,您会注意到当Y和Z旋转为零时X旋转沿世界X轴,当Z旋转为零且Z旋转始终沿Z轴时,Y旋转沿世界Y轴.
但是,如果在设置X,然后是Y,然后是Z旋转,我们再次转动X滑块怎么办?您会注意到旋转不再沿着世界X轴,而是沿着局部X轴.原因很简单,虽然解释原因可能并非如此.用一个词 - 轮换不通勤.你看,旋转X(a) * Y(b) * Z(c) * X(d)通常不等于X(a + d) * Y(b) * Z(c).也就是说,如果你沿着世界X旋转a,然后沿着世界Y by b,然后沿着世界Z by c,然后再沿着世界X by d旋转,那么结果与你旋转时所获得的旋转不同a + d从一开始就沿着世界X. 其原因在于变换开始时的"世界X"和变换结束时的"世界X"是两个不同的向量,其值取决于到此为止所做的所有变换.因此,它们代表局部空间中的不同旋转轴.
我将尝试预测下一个问题:"我怎么能这样做,无论我如何左右移动滑块,物体总是只沿着世界轴旋转?" 这个基于我们已经知道的关于围绕世界轴旋转的知识的答案 - 世界轴必须表示为局部空间中的向量,并且旋转必须围绕该向量进行.该想法的实现如下:
var prevX = 0, prevY = 0, prevZ = 0;
function doRotate() {
var x = toRadians($("#rotateX").slider("option", "value"));
var y = toRadians($("#rotateY").slider("option", "value"));
var z = toRadians($("#rotateZ").slider("option", "value"));
var inverse = new THREE.Matrix4().getInverse(cube.matrix);
var rotation = cube.matrix;
var worldXAxis = new THREE.Vector3(1, 0, 0).applyMatrix4(new THREE.Matrix4().getInverse(rotation));
var rotationWorldX = new THREE.Matrix4().makeRotationAxis(worldXAxis, x - prevX);
rotation.multiply(rotationWorldX);
var worldYAxis = new THREE.Vector3(0, 1, 0).applyMatrix4(new THREE.Matrix4().getInverse(rotation));
var rotationWorldY = new THREE.Matrix4().makeRotationAxis(worldYAxis, y - prevY);
rotation.multiply(rotationWorldY);
var worldZAxis = new THREE.Vector3(0, 0, 1).applyMatrix4(new THREE.Matrix4().getInverse(rotation));
var rotationWorldZ = new THREE.Matrix4().makeRotationAxis(worldZAxis, z - prevZ);
rotation.multiply(rotationWorldZ);
prevX = x;
prevY = y;
prevZ = z;
cube.matrixAutoUpdate = false;
cube.matrix = rotation;
}
Run Code Online (Sandbox Code Playgroud)
小提琴:https://jsfiddle.net/2whv0e8o/13/
上面的函数被绑定为slide所有滑块的事件处理程序:"slide": doRotate.现在,如果你试图旋转这两个,你会注意到无论盒子的当前方向如何,移动滑块总是会导致沿世界轴的旋转.但有一点需要注意:滑块的值不再代表围绕任何特定轴的实际旋转角度.您会注意到该doRotate函数仅沿世界轴应用增量旋转,因为它们当前以局部坐标表示.我们已经实现了能够应用始终沿世界轴进行的增量旋转的目标,但是我们已经失去了X,Y和Z滑块的绝对值的含义.但是,如果该值并不意味着什么,有什么可能被用来保存对象的当前旋转的的旋转?根据我的经验,最好只存储对象的转换矩阵批发.也就是说,不是试图保存三个特定的旋转角度,加上平移向量,加上可能的缩放参数,而是将整个矩阵保存为对象的一部分.
| 归档时间: |
|
| 查看次数: |
2605 次 |
| 最近记录: |