Three JS中如何沿世界固定轴旋转骨骼 不受父骨骼变换影响
解决方法
你遇到的问题本质是目标四元数处于世界空间,而骨骼的quaternion属性只对应父节点局部空间的朝向,你只需要把目标世界四元数转换为骨骼父节点的局部空间再赋值即可,有两种常用实现方案:
方案1:直接计算局部空间四元数(性能最优)
通过父节点的世界逆四元数做空间转换,不需要修改节点层级,适合高频调用的场景:
// 先确保所有节点的世界矩阵是最新状态 scene.updateMatrixWorld(true); // 处理上臂 const armParentQuat = leftArm.parent.getWorldQuaternion(new THREE.Quaternion()).invert(); leftArm.quaternion.copy(armParentQuat).multiply(arrowHelperArm.quaternion); // 处理前臂 const foreArmParentQuat = leftForeArm.parent.getWorldQuaternion(new THREE.Quaternion()).invert(); leftForeArm.quaternion.copy(foreArmParentQuat).multiply(arrowHelperForeArm.quaternion);
如果上述计算后朝向仍有偏移,说明需要抵消骨骼绑定姿态的影响,补充乘上骨骼绑定矩阵的逆四元数即可:
// 以leftForeArm为例 const bindQuat = new THREE.Quaternion().setFromRotationMatrix(leftForeArm.bindMatrixInverse); leftForeArm.quaternion.premultiply(bindQuat);
方案2:临时修改节点父级(逻辑直观,不易出错)
Three.js的attach方法会自动保留节点的世界空间变换,临时把骨骼挂到场景根节点(局部空间等价于世界空间)后直接赋值,再挂回原父节点即可:
scene.updateMatrixWorld(true); // 处理上臂 const armParent = leftArm.parent; scene.attach(leftArm); leftArm.applyQuaternion(arrowHelperArm.quaternion); armParent.attach(leftArm); // 处理前臂 const foreArmParent = leftForeArm.parent; scene.attach(leftForeArm); leftForeArm.applyQuaternion(arrowHelperForeArm.quaternion); foreArmParent.attach(leftForeArm);
内容的提问来源于stack exchange,提问作者Deepanshu Sharma
相关产品推荐
相关产品推荐

