在 Three.js 中,可以通过 rotation 或者 quaternion 属性来修改 Object3D 的旋转角度。
rotation 属性
object.rotation.x; // 围绕X轴的旋转角度 object.rotation.y; // 围绕Y轴的旋转角度 object.rotation.z; // 围绕Z轴的旋转角度
可以通过修改这些属性的值来改变物体的旋转状态。例如,通过设置
object.rotation.x = Math.PI / 2; // 绕X轴旋转90度
quaternion 属性
以下是一个简单的例子,演示如何创建一个绕 Y 轴旋转 45 度的四元数:
// 创建一个四元数表示旋转 var quaternion = new THREE.Quaternion(); // 绕Y轴旋转45度 quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 4); // 将四元数应用到Group的quaternion属性 object.quaternion.copy(quaternion);
rotation 和 quaternion 之间的转换
Three.js 中,rotation 和 quaternion 都可以修改当前 Object3D 的旋转,同时这两个值也可以相互转换。
rotation 转 quaternion:
// 绕 X 轴旋转 90 度 const euler = new THREE.Euler(Math.PI / 2, 0, 0, 'XYZ'); // 创建一个空的 Quaternion const quaternion = new THREE.Quaternion(); // 将 Euler 转换为 Quaternion quaternion.setFromEuler(euler);
quaternion 转 rotation:
const quaternion = new THREE.Quaternion(); // 示例:绕X轴旋转90度 quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 2); // 将 Quaternion 转换为 Euler const euler = new THREE.Euler().setFromQuaternion(quaternion);
Euler 和 Quaternion 转化的数值可能差异巨大
既然 Three.js 中可以使用 Euler 或者 Quaternion 来设置旋转,并且两者可以相互转换。那是否可以随意使用两个数值,并且相互转换得到另一个值呢?
这里可能会有一个坑:Euler 转 Quaternion,再转成 Euler 之后,转化前的 Euler 和转化后的 Euler 的数值可能差异巨大。
来看下面的例子:
// 绕 Y 轴旋转 -160° const euler = new THREE.Euler(0, -160 * (Math.PI / 180), 0, 'XYZ'); const quaternion = new THREE.Quaternion().setFromEuler(euler); const afterEuler = new THREE.Euler().setFromQuaternion(quaternion); console.log("euler ", euler.order); // 输出: // euler:order: "XYZ", x: 0, y: -2.792526803190927, z: 0 console.log("afterEuler:", afterEuler); // afterEuler:order: "XYZ", x: 3.141592653589793, y: -0.349065850398866, z: 3.141592653589793
Three.js 定义的 PI 为
#define PI 3.141592653589793
euler 转成 quaternion 之后,再转成 afterEuler 之后,euler 和 afterEuler 的数值相差巨大:
- euler: 表示绕 Y 轴旋转 -160°。
- afterEuler:表示绕 X 轴旋转 180°(PI),绕 y 轴旋转 -20°(-0.349065850398866 弧度),绕 z 轴旋转 180°(PI)。
euler 和 afterEuler 表示的旋转结果基本一致,但是 x,y, z 值相差巨大。
所以,当程序的一部分依靠 Euler 的单个绕轴旋转弧度,另一部分依靠 Quaternion 时,可能会出现差异。