Skip to content

四元数、欧拉角

欧拉角 Euler

创建欧拉角表示特定旋转角度

js
const Euler = new THREE.Euler();
Euler.x = Math.PI / 3; //绕x轴旋转60度
Euler.y = Math.PI / 3; //绕y轴旋转60度
Euler.z = Math.PI / 3; //绕z轴旋转60度

改变物体角度

threejs 模型对象都包含rotation属性,.rotation的值其实就是欧拉角对象Euler

  • 直接修改.rotation

    js
    // 物体fly绕x轴旋转60度
    fly.rotation.x = Math.PI / 3;
  • copyEuler

    js
    const Euler = new THREE.Euler();
    Euler.x = Math.PI / 3;
    // 复制欧拉角的值,赋值给物体的.rotation属性
    fly.rotation.copy(Euler);

物体旋转顺序.order

物体先后绕 x、y、z 轴旋转,旋转的顺序不同,物体的姿态角度也可能不同。

  • 直接修改.rotation

    js
    // 直接修改fly.rotation
    fly.rotation.order = "YXZ";
    fly.rotation.x = Math.PI / 3;
    fly.rotation.y = Math.PI / 3;
  • 欧拉赋值

    js
    const Euler = new THREE.Euler();
    Euler.x = Math.PI / 3;
    Euler.y = Math.PI / 3;
    //先绕Y轴旋转,在绕X、Z轴旋转
    Euler.order = "YXZ";
    fly.rotation.copy(Euler);

四元数 Quaternion

四元数Quaternion和欧拉角Euler一样, 用来计算或表示物体在 3D 空间中的旋转姿态角度

实例化Quaternion

js
const quaternion = new THREE.Quaternion();

四元数方法.setFromAxisAngle()

生成一个四元数,绕任意轴,旋转任意角度

js
const quaternion = new THREE.Quaternion();
// 旋转轴new THREE.Vector3(0,0,1)
// 旋转角度Math.PI/2
// 绕z轴旋转90度
quaternion.setFromAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI / 2);

四元数旋转坐标

通过.applyQuaternion(quaternion)对坐标点进行旋转

js
const quaternion = new THREE.Quaternion();
// 绕z轴旋转90度
quaternion.setFromAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI / 2);
// 通过四元数旋转A点:把A点绕z轴旋转90度生成一个新的坐标点B
const B = A.clone().applyQuaternion(quaternion);

四元数表示物体姿态

Three.js 模型对象都有一个属性.quaternion, 可以通过物体.quaternion属性改变物体的姿态角度

js
const quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 2);
//quaternion表示旋转角度复制给物体.quaternion
fly.quaternion.copy(quaternion);

模型属性.rotation(角度)和.quaternion(四元数)

模型属性

二者都是用来表示物体姿态角度, 一个改变,另一个也会同步改变。

四元数乘法运算.multiply()

在物体原有角度姿态上进行旋转

js
// 在物体原来姿态基础上,进行旋转
const q1 = new THREE.Quaternion();
q1.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 2);
fly.quaternion.multiply(q1);
// 在物体上次旋转基础上,进行旋转
const q2 = new THREE.Quaternion();
q2.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
fly.quaternion.multiply(q2);

效果同上:

js
const q1 = new THREE.Quaternion();
q1.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI / 2);
const q2 = new THREE.Quaternion();
q2.setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI / 2);
const newQ = q1.clone().multiply(q2);
fly.quaternion.multiply(newQ);

注意

不满足交换律,执行顺序不同将影响物体最终姿态角度

.copy区别

A.multiply(B)表示 A 乘以 B,结果赋值给 A,在 A 的基础上旋转 B。

A.copy(B)表示用 B 的值替换 A 的值,A 表示的旋转会被 B 替换。

四元数表示两个向量旋转

一个向量向另外一个向量旋转,这个过程可以用一个四元数表示

js
//飞机初始姿态飞行方向a
const a = new THREE.Vector3(0, 0, -1);
// 飞机姿态绕自身坐标原点旋转到b指向的方向
const b = new THREE.Vector3(-1, -1, -1).normalize();
// a旋转到b构成的四元数
const quaternion = new THREE.Quaternion();
//注意两个参数的顺序
quaternion.setFromUnitVectors(a, b);
// quaternion表示的是变化过程,在原来基础上乘以quaternion即可
fly.quaternion.multiply(quaternion);