Skip to content

137. API 查缺补漏:Euler

Published:

这节继续来过其他 api,这节来过一下 Euler

Euler 用三个角度(x, y, z)表示旋转

我们平时都是直接设置 mesh.rotation.x、y、z,其实 rotation 就是一个 Euler 对象:

image.png

之前我们都这样设置:

image.png

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

image.png

其实也可以这样:

image.png

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;

image.png

创建了三个立方体,改下第一个的角度。

第二个立方体这样设置:

image.png

const euler2 = new THREE.Euler(x, y, z, 'ZYX');
mesh2.setRotationFromEuler(euler2);

修改了下 XYZ 的顺序。

之前是先绕 X 轴旋转、再绕 Y 轴旋转,再绕 Z 轴旋转。

现在改为了 ZYX

image.png

可以看到,旋转结果是不一样的。

此外,还可以绕一个轴旋转:

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

image.png

可以看到效果就是绕 z 轴旋转 30 度的效果。

这可以可以换成绕任意的轴来旋转,旋转后设置到 eular 就好了。

eular 也是三元的,它自然可以通过 Vector3 设置:

image.png

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

image.png

只不过 eular 是特指旋转角度的三元数。

此外,还可以从四维矩阵 4*4 的矩阵来设置角度:

image.png

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 中表示旋转的核心类

Euler 还可以与 Quaternion、Matrix4、Vector3 相互转换,为不同场景提供灵活的旋转表示方式。

下节我们把 Quaternion、Matrix4 等 api 也过一下。

评论