这节继续来过其他 api,这节来过一下 Euler
Euler 用三个角度(x, y, z)表示旋转
我们平时都是直接设置 mesh.rotation.x、y、z,其实 rotation 就是一个 Euler 对象:

之前我们都这样设置:

mesh.rotation.x = Math.PI / 4;
mesh.rotation.y = Math.PI / 4;
mesh.rotation.z = Math.PI / 4;

其实也可以这样:

const euler = new THREE.Euler(Math.PI / 4, Math.PI / 4, Math.PI / 4);
mesh.setRotationFromEuler(euler);
后面我们就统一用这种方式了。
还可以和前面的 MathUtils 的 api 结合用:
const x = THREE.MathUtils.degToRad(45);
const y = THREE.MathUtils.degToRad(45);
const z = THREE.MathUtils.degToRad(45);
const euler = new THREE.Euler(x, y, z);
mesh.setRotationFromEuler(euler);
用 degToRad 把角度转弧度,再设置到 Euler
此外,你还可以调整不同方向旋转角度的顺序:
改下 mesh.js
import * as THREE from 'three';
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material1 = new THREE.MeshPhongMaterial({ color: 'orange' });
const material2 = new THREE.MeshPhongMaterial({ color: 'cyan' });
const material3 = new THREE.MeshPhongMaterial({ color: 'lime' });
const mesh1 = new THREE.Mesh(geometry, material1);
mesh1.position.set(-200, 0, 0);
const mesh2 = new THREE.Mesh(geometry, material2);
mesh2.position.set(0, 0, 0);
const mesh3 = new THREE.Mesh(geometry, material3);
mesh3.position.set(200, 0, 0);
const x = THREE.MathUtils.degToRad(90);
const y = THREE.MathUtils.degToRad(60);
const z = THREE.MathUtils.degToRad(30);
const euler1 = new THREE.Euler(x, y, z, 'XYZ');
mesh1.setRotationFromEuler(euler1);
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
group.add(mesh3);
export default group;

创建了三个立方体,改下第一个的角度。
第二个立方体这样设置:

const euler2 = new THREE.Euler(x, y, z, 'ZYX');
mesh2.setRotationFromEuler(euler2);
修改了下 XYZ 的顺序。
之前是先绕 X 轴旋转、再绕 Y 轴旋转,再绕 Z 轴旋转。
现在改为了 ZYX

可以看到,旋转结果是不一样的。
此外,还可以绕一个轴旋转:
const angle = THREE.MathUtils.degToRad(30);
const quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle(new THREE.Vector3(0, 0, 1), angle);
const euler = new THREE.Euler();
euler.setFromQuaternion(quaternion);
mesh3.setRotationFromEuler(euler);
Vector3 是三元的,多一个维度就是四元数,也就是 Quaternion
我们让它绕 0,0,1 这个向量旋转 30 度
这时候的角度用 setFromQuaternion 设置到 eular

可以看到效果就是绕 z 轴旋转 30 度的效果。
这可以可以换成绕任意的轴来旋转,旋转后设置到 eular 就好了。
eular 也是三元的,它自然可以通过 Vector3 设置:

const v = new THREE.Vector3(angle, 0, 0);
euler.setFromVector3(v);
mesh3.setRotationFromEuler(euler);

只不过 eular 是特指旋转角度的三元数。
此外,还可以从四维矩阵 4*4 的矩阵来设置角度:

const m = new THREE.Matrix4();
// 绕Z轴旋转60度 (cos60°=0.5, sin60°=√3/2≈0.8660)
m.elements = [
0.5, 0.8660, 0, 0, // 第一列
-0.8660, 0.5, 0, 0, // 第二列
0, 0, 1, 0, // 第三列
0, 0, 0, 1 // 第四列
];
euler.setFromRotationMatrix(m);
mesh3.setRotationFromEuler(euler);
当然,矩阵是很底层的知识,一般不这么用,但如果你有了矩阵数据,也可以用这个 Matrix4 接收,然后 euler.setFromRotationMatrix 设置为旋转角度。
案例代码上传了小册仓库
总结
这节我们过了一遍 Euler 的 api,它是 Three.js 中表示旋转的核心类
new Euler(x, y, z, order)- 创建欧拉角setRotationFromEuler(euler)- 设置网格的旋转order- 旋转顺序(‘XYZ’、‘YXZ’、‘ZXY’、‘ZYX’、‘YZX’、‘XZY’)setFromQuaternion(q)- 从四元数设置角度setFromRotationMatrix(m)- 从旋转矩阵设置角度setFromVector3(v)- 从 Vector3 设置角度
Euler 还可以与 Quaternion、Matrix4、Vector3 相互转换,为不同场景提供灵活的旋转表示方式。
下节我们把 Quaternion、Matrix4 等 api 也过一下。