如何将三维坐标表示的旋转转换为CannonJS四元数?
解决CannonJS中欧拉角转四元数的问题
核心问题:四元数乘法的顺序
四元数乘法不满足交换律,旋转顺序直接决定最终结果。你手动组合四元数时出错的原因是乘法顺序和你想要的旋转顺序不匹配。
手动组合四元数的正确方式
假设你的旋转顺序是「先绕X轴转rx,再绕Y轴转ry,最后绕Z轴转rz」,那么四元数需要按从右到左的顺序相乘(最右侧的四元数对应第一个执行的旋转):
const qX = new CANNON.Quaternion(); const qY = new CANNON.Quaternion(); const qZ = new CANNON.Quaternion(); qX.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), rx); qY.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), ry); qZ.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), rz); // 按 X → Y → Z 的旋转顺序组合 const combined = qZ.mult(qY.mult(qX)); combined.normalize(); // 赋值给物理物体 cannon_object.quaternion.copy(combined);
如果你的旋转顺序是其他类型(比如常见的Z→Y→X),则调整乘法顺序为qX.mult(qY.mult(qZ))。
更简单的方法:用CannonJS内置方法
CannonJS的Quaternion类提供了setFromEuler方法,可以直接将欧拉角转换为四元数,自动处理旋转顺序:
const targetQuat = new CANNON.Quaternion(); // 第四个参数指定旋转顺序,可选值:'XYZ'/'YZX'/'ZXY'/'XZY'/'YXZ'/'ZYX',默认是'ZYX' targetQuat.setFromEuler(rx, ry, rz, 'XYZ'); cannon_object.quaternion.copy(targetQuat);
修复Three.js辅助转换的NaN问题
你之前的代码错误在于rotation.set()的参数传递——这个方法接受三个数字,而非THREE.Vector3对象,修正后即可正常使用:
// 直接传入弧度制角度值(如果是角度需转弧度:THREE.MathUtils.degToRad(angle)) three_object.rotation.set(rx, ry, rz); // 显式更新四元数(避免延迟更新问题) three_object.updateQuaternion(); // 复制到CannonJS物体 cannon_object.quaternion.copy(three_object.quaternion);
注意:Three.js默认欧拉角顺序是XYZ,如果和你的需求不符,可以通过three_object.rotation.order = 'ZYX'修改。
内容的提问来源于stack exchange,提问作者Jason Roman
相关产品推荐
相关产品推荐

