围绕世界轴(外部Euler角度)依次旋转threejs对象



我正在创建外部Euler角度旋转的可视化,我想要一个立方体根据用户输入绕世界轴旋转的动画。我有一个数据。带有x、y和z旋转角度控件的GUI控件。请参阅此屏幕截图。

到目前为止,我已经能够实现内在旋转,只需使用cube_axes.rotation.x(和.y.z(并设置立方体旋转。我的GUI代码如下:

gui.add(params, 'x_rot').name('X rotation').min(-180).max(180).step(5).onChange(() => {
cube_axes.rotation.x = toRadians(params.x_rot)
})
gui.add(params, 'y_rot').name('Y rotation').min(-180).max(180).step(5).onChange(() => {
cube_axes.rotation.y = toRadians(params.y_rot)
})
gui.add(params, 'z_rot').name('Z rotation').min(-180).max(180).step(5).onChange(() => {
cube_axes.rotation.z = toRadians(params.z_rot)
})

当用户移动x旋转控件时,立方体将围绕其局部x轴旋转指定的度数。然后,当用户移动y旋转控件时,已旋转的立方体将围绕其局部y轴旋转。

然而,我在外部旋转中遇到的问题是,立方体会擦除以前的旋转(本质上是重置自身(,并简单地旋转正在更改的控件。因此,立方体永远不会在上一次旋转的基础上旋转。这是我的代码:

gui.add(params, 'x_rot').name('X rotation').min(-180).max(180).step(5).onChange(() => {
//cube_axes.setRotationFromAxisAngle(x_vector, toRadians(params.x_rot))
let quaternion = new THREE.Quaternion().setFromAxisAngle(x_vector, toRadians(params.x_rot));
cube_axes.rotation.setFromQuaternion(quaternion);
})
gui.add(params, 'y_rot').name('Y rotation').min(-180).max(180).step(5).onChange(() => {
//cube_axes.setRotationFromAxisAngle(y_vector, toRadians(params.y_rot))
let quaternion = new THREE.Quaternion().setFromAxisAngle(y_vector, toRadians(params.y_rot));
cube_axes.rotation.setFromQuaternion(quaternion);
})
gui.add(params, 'z_rot').name('Z rotation').min(-180).max(180).step(5).onChange(() => {
//cube_axes.setRotationFromAxisAngle(z_vector, toRadians(params.z_rot))
let quaternion = new THREE.Quaternion().setFromAxisAngle(z_vector, toRadians(params.z_rot));
cube_axes.rotation.setFromQuaternion(quaternion);
})

我尝试过使用.setFromQuaternion(来自这个问题(和.setRotationFromAxisAngle(注释行(,但这两种方法都有相同的问题。我不知道这里发生了什么。是因为我使用的是.rotation而不是特定的旋转轴(.rotation.x.rotation.y.rotation.z(吗?

谢谢。

我想通了!使用.applyQuaternion而不是.setFromQuaternion。根据我的理解,这在已经存在的基础上进行了旋转,而不是完全重置。这是我的代码:

gui.add(params, 'x_rot').name('X rotation').min(-180).max(180).step(5).onChange(() => {
let quaternion = new THREE.Quaternion().setFromAxisAngle(x_vector, toRadians(params.x_rot));
cube_axes.applyQuaternion(quaternion);
})
gui.add(params, 'y_rot').name('Y rotation').min(-180).max(180).step(5).onChange(() => {
let quaternion = new THREE.Quaternion().setFromAxisAngle(y_vector, toRadians(params.y_rot));
cube_axes.applyQuaternion(quaternion);
})
gui.add(params, 'z_rot').name('Z rotation').min(-180).max(180).step(5).onChange(() => {
let quaternion = new THREE.Quaternion().setFromAxisAngle(z_vector, toRadians(params.z_rot));
cube_axes.applyQuaternion(quaternion);
})

请注意,此实现不使用THREE对象的rotation属性。

编辑:对于那些试图做同样事情的人,你还需要一个额外的变量来跟踪以前的参数,这样你就可以应用正确的角度。否则,最终会出现不正确的旋转(只要控件发生更改,就会继续添加另一个角度(。请参阅以下代码:

let prev_params = {
x_rot: 0,
y_rot: 0,
z_rot: 0,
}

然后这个代码在GUI onChange函数中(我只包含了x的代码(:

let angle = toRadians(params.x_rot)
if (prev_params.x_rot) {
angle = angle - toRadians(prev_params.x_rot)
}
let quaternion = new THREE.Quaternion().setFromAxisAngle(x_vector, angle)
cube_axes.applyQuaternion(quaternion)
prev_params.x_rot = params.x_rot

最新更新