You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

THREE.js旋转增量计算及四元数加减实现跟随旋转的技术问询

关于THREE.js中旋转增量计算与旋转跟随的实现

一、如何在THREE.js中计算旋转增量?

首先得明确:三维旋转不能像位置那样直接做分量加减,因为旋转是非线性的空间变换,直接操作欧拉角还容易碰到万向锁问题。所以更稳妥的方式是用**四元数(Quaternion)**来计算旋转增量。

思路是这样的:假设你有物体旋转前的旧四元数oldQuat,和旋转后的新四元数newQuat,那么从旧旋转到新旋转的增量四元数,其实是旧四元数的逆四元数乘以新四元数——逆四元数的作用是抵消旧旋转的影响,剩下的就是两次旋转之间的变换量。

代码示例:

// 假设已记录物体的旧四元数oldQuat,当前四元数是object.quaternion
const deltaQuat = oldQuat.inverse().multiply(object.quaternion);
// deltaQuat就是这次的旋转增量

如果非要用欧拉角计算(不推荐),可以直接对三个轴的角度做减法,但一定要注意万向锁的问题:

const oldEuler = new THREE.Euler().setFromQuaternion(oldQuat);
const newEuler = object.rotation.clone();
const deltaEuler = new THREE.Euler(
  newEuler.x - oldEuler.x,
  newEuler.y - oldEuler.y,
  newEuler.z - oldEuler.z,
  'XYZ' // 要和物体的欧拉角顺序保持一致
);

二、用四元数实现类似位置跟随的旋转跟随效果

你之前的位置跟随思路是对的,但旋转不能直接照搬“加减”的逻辑——THREE.js里Quaternion.sub()是分量级的减法,这不是旋转空间里的增量计算,直接用会导致四元数失去单位特性,旋转完全乱掉。

正确的做法是用四元数乘法来传递旋转增量,和位置跟随的逻辑对应起来:

  1. 拖拽开始时,记录objectA的旧四元数:const objectAOldRotation = objectA.quaternion.clone();
  2. 拖拽过程中,计算objectA的旋转增量(就是从旧旋转到当前旋转的变换)
  3. 把这个增量应用到objectB的当前旋转上,让它跟着objectA转相同的角度

对应你的位置代码,旋转跟随的代码应该是这样:

// 1. 计算objectA的旋转增量(注意是逆乘,不是减法!)
const rotationDelta = objectAOldRotation.inverse().multiply(objectA.quaternion);

// 2. 将增量应用到objectB的旋转上
objectB.quaternion.multiply(rotationDelta);

如果想和你位置代码的写法更贴近(先克隆再操作),也可以写成:

const rotationDelta = objectAOldRotation.inverse().multiply(objectA.quaternion);
const newRotation = objectB.quaternion.clone().multiply(rotationDelta);
objectB.quaternion = newRotation;

为什么这么做?因为四元数的乘法代表旋转的复合:objectB当前旋转 × 旋转增量,就相当于让objectB在自己当前的旋转基础上,再做一遍objectA刚才的旋转动作,完美实现“跟着转”的效果。

另外要注意:每次拖拽更新后,记得把objectAOldRotation更新为objectA当前的四元数,不然下一次计算的增量会累积错误。


内容的提问来源于stack exchange,提问作者user2132190

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:07:59