模型旋转Quaternion四元数使用,慎用getWorldQuaternion、getWorldDirection

 

使用getWorldQuaternion获取模型世界旋转四元数并转化为erluer角时,x、y、z分量可能皆不为0,这种情况下如果只取某个分量的值来进行旋转无法达到目标效果,

原因:欧拉角的x、y、z三个分量相互影响,且容易出现万象锁问题,因此获取世界旋转值时应慎重使用

 

普通用法:获取模型世界四元数、并获取对应的欧拉角

      //世界旋转
      this.object.parent.getWorldQuaternion(this.worldQuaternion);
      // 转换为欧拉角
      this.prevRotation.setFromQuaternion(this.worldQuaternion, 'XYZ');

这种情况下一定不要只取某个分量

正确做法:应计算获取在某个平面上的投影来获取单个正确的分量:

示例:场景下的模型B想只做y轴旋转与模型a的y轴旋转一致(模型a的y轴旋转受x、z影响

 

// 1. 获取模型a的世界四元数
const q_a = new THREE.Quaternion();
modelA.getWorldQuaternion(q_a);

// 2. 模型a的“前向量”(默认模型的正Z方向为前)
const forward = new THREE.Vector3(0, 0, 1);

// 用q_a旋转forward向量,得到世界空间中模型a的朝向向量
const worldForward = forward.clone().applyQuaternion(q_a);

// 3. 计算worldForward在XZ平面的投影
const projectedForward = new THREE.Vector3(worldForward.x, 0, worldForward.z).normalize();

// 4. 计算绕Y轴的旋转角(atan2方式)
const yRotationA = Math.atan2(projectedForward.x, projectedForward.z);

// 5. 赋值给模型b的Y轴旋转(保持b的X、Z旋转不变)
const eulerB = new THREE.Euler();
eulerB.copy(modelB.rotation);
eulerB.y = yRotationA;
modelB.rotation.copy(eulerB);

 

posted @ 2025-06-06 17:25  SimoonJia  阅读(17)  评论(0)    收藏  举报