Matrix Three.js设置绝对局部旋转

Matrix Three.js设置绝对局部旋转,matrix,three.js,rotation,quaternions,Matrix,Three.js,Rotation,Quaternions,我有一个基于串行输入旋转立方体的程序。串行输入提供立方体应处于的绝对旋转(例如20度)。我对立方体的旋转有限制,比如X从-45度到45度 我当前正在存储X、Y、Z的当前旋转,计算当前旋转和新旋转之间的差异,然后使用.rotateX().rotateY()和.rotateZ()根据立方体的局部位置旋转立方体 curX = 0; // Global variable function updateCubeRotation(newX) { // Limit X if(newX <

我有一个基于串行输入旋转立方体的程序。串行输入提供立方体应处于的绝对旋转(例如20度)。我对立方体的旋转有限制,比如X从-45度到45度

我当前正在存储X、Y、Z的当前旋转,计算当前旋转和新旋转之间的差异,然后使用.rotateX().rotateY()和.rotateZ()根据立方体的局部位置旋转立方体

curX = 0; // Global variable

function updateCubeRotation(newX) {
    // Limit X
    if(newX < 45 && newX > -45) {
        cube.rotateX(THREE.Math.degToRad(newX - curX));
        curX = newX;
    }
}
我猜这是可能的四元计算,但我不确定的数学需要发生的这一点

.quaternion : Quaternion
Object's local rotation as a Quaternion.
我最初使用的是cube.rotation.x=45,但它在世界空间中旋转。与Unity相比,它们有cube.localRotation.x属性,这正是我试图模仿的


更新

我看到文档上说,旋转是局部的,但我仍然感到困惑,因为我可以通过世界坐标来判断它的旋转。rotateX和rotation.x有什么区别

记录rotateX和rotation.x我可以看到rotateX更改了rotation.x、rotation.y和rotation.z,以便在局部轴上正确旋转。因为超过1个轴必须更改,这意味着它相对于世界轴,这与文档冲突

以下是rotateX和rotation.x的示例:

rotateX所需的旋转,但只取最后位置和新位置之间的差值,而不是绝对值

 console.log(cube.rotation.x)

 x       y       z
 0.1011 -0.6073 -0.5624
-0.0143 -0.5418 -0.6252
-0.1162 -0.4741 -0.6748
-0.2075 -0.4053 -0.7137
-0.2875 -0.3387 -0.7428
-0.3572 -0.2764 -0.7640
-0.4148 -0.2221 -0.7782
-0.4616 -0.1764 -0.7875
-0.4983 -0.1398 -0.7932
-0.5289 -0.1088 -0.7970

旋转.x-不希望的旋转

 console.log(cube.rotation.x)

 x       y       z
 0.6109 -0.0298 -0.7854
 0.6051 -0.0298 -0.7854
 0.4279 -0.0298 -0.7854
 0.2683 -0.0298 -0.7854
 0.1125 -0.0298 -0.7854
-0.0346 -0.0298 -0.7854
-0.1684 -0.0298 -0.7854
-0.3198 -0.0298 -0.7854
-0.5058 -0.0298 -0.7854
-0.6109 -0.0298 -0.7854


如果.rotation实际上是局部的,那么将x设置为degToRad(45)是否会导致旋转与第一个示例类似,而只需要更改x轴


JS小提琴示例


您可以轻松使用
cube.rotation.x
属性设置绝对值(而不是更改值)

//设置绝对旋转
设置旋转(newRot){
//夹紧值,使其不超过+/-45
var clampedRot=3.Math.clamp(newRot,-45,45);
//以弧度为单位指定新旋转
cube.rotation.x=3.Math.degToRad(clampedRot);
}
我最初使用的是cube.rotation.x=45,但它在世界空间中旋转


我不相信这是真的。我认为问题在于,如果您使用
cube.rotation.x=45
,您将得到不想要的结果,因为旋转是以弧度计算的,而不是以度计算的。使用literal
45
可以让你旋转7圈,你应该使用
3.Math.degToRad(45)

对我来说,它就像立方体。旋转。x是它的世界空间旋转,尽管文档说它是局部的。我在我的问题中添加了一个更新,也许你可以解释一下我的困惑。啊,你的更新显著地使原始问题复杂化,因为你将三个旋转加在一起,这似乎导致了一些问题。这是使用Euler旋转时非常常见的问题,在3D和游戏开发中经常发生。您可能需要切换到,而不是设置Euler旋转。你能把你的例子添加到一个JSFIDLE中去看看这是否是问题所在吗?我在文章的末尾添加了一个JSFIDLE。我确实认为在查看rotateX()的源代码时需要切换到四元数,它使用四元数。所以理想情况下,我会找到一种类似于rotateX()的方法,只需要一个绝对的旋转值,而不是速度虽然是我的串行控制器可以返回非常大的数字,如果我告诉它从15000,0,0这样的旋转返回到0,0,0,我想一些小数位精度会丢失,因为立方体最终会旋转几度,即使它报告0度。能够将其强制到特定角度会更好。我认为您需要了解这一点:
 console.log(cube.rotation.x)

 x       y       z
 0.6109 -0.0298 -0.7854
 0.6051 -0.0298 -0.7854
 0.4279 -0.0298 -0.7854
 0.2683 -0.0298 -0.7854
 0.1125 -0.0298 -0.7854
-0.0346 -0.0298 -0.7854
-0.1684 -0.0298 -0.7854
-0.3198 -0.0298 -0.7854
-0.5058 -0.0298 -0.7854
-0.6109 -0.0298 -0.7854
cube.rotation.x = THREE.Math.degToRad(45);