使用Quaternion旋转模型时如何防止模型侧滚?
解决Three.js模型旋转侧滚问题
要避免模型旋转时出现侧滚,核心是约束模型的额外旋转自由度——仅让模型的前方向(原Z轴)指向目标方向,同时固定模型的局部向上轴(原Y轴)的朝向,避免绕目标方向的扭转。
原代码中q.setFromUnitVectors(vB, vC)仅保证前方向对齐,但模型的其他轴旋转是自由的,这就是侧滚的原因。以下是两种可行的解决方案:
方法一:手动构造正交轴系(更可控)
通过构建正交的三个轴(右、上、前)来定义旋转,确保模型向上轴保持与原向上方向的正交投影一致:
//Box natural direction let vB = new THREE.Vector3(0, 0, 1); // 模型原始向上方向(原Y轴) let upB = new THREE.Vector3(0, 1, 0); //Cable direction let vC = new THREE.Vector3(1, 1, 0).normalize(); // 构造无侧滚的旋转轴系 const forward = vC.clone(); // 计算右轴:前方向叉乘原向上方向,确保正交 const right = new THREE.Vector3().crossVectors(forward, upB).normalize(); // 处理前方向与原向上方向平行的极端情况 if (right.lengthSq() < 0.0001) { right.set(1, 0, 0).cross(forward).normalize(); } // 计算正交的向上轴:右轴叉乘前方向 const up = new THREE.Vector3().crossVectors(right, forward).normalize(); // 从轴系生成旋转矩阵,再转成四元数 const rotationMatrix = new THREE.Matrix4().makeBasis(right, up, forward); let q = new THREE.Quaternion().setFromRotationMatrix(rotationMatrix); // 后续模型应用代码不变 const boxG = new THREE.BoxGeometry(4, 8, 10); const boxM = new THREE.Mesh(boxG, matSS); const conG = new THREE.CylinderGeometry(0.5, 0.5, 2, 16); conG.rotateX(Math.PI / 2); const conM = new THREE.Mesh(conG, matSS); conM.translateZ(5); boxM.applyQuaternion(q); boxM.add(conM); scene.add(boxM); //Cable to connect const cabG = new THREE.CylinderGeometry(0.25, 0.25, 100, 16); cabG.rotateX(Math.PI / 2); const cabM = new THREE.Mesh(cabG, matBL); const cabP = vC.clone().setLength(50); cabM.applyQuaternion(q); cabM.position.set(cabP.x,cabP.y,cabP.z); scene.add(cabM);
方法二:使用lookAt矩阵(更简洁)
利用Three.js的lookAt矩阵直接生成约束向上方向的旋转,本质和方法一逻辑一致:
//Box natural direction let vB = new THREE.Vector3(0, 0, 1); let upB = new THREE.Vector3(0, 1, 0); //Cable direction let vC = new THREE.Vector3(1, 1, 0).normalize(); // 用lookAt生成旋转:让模型Z轴指向vC,同时保持upB为向上方向 const lookAtMatrix = new THREE.Matrix4().lookAt( new THREE.Vector3(0,0,0), // 模型原点 vC, // 目标方向(作为点) upB // 约束的向上方向 ); let q = new THREE.Quaternion().setFromRotationMatrix(lookAtMatrix); // 后续模型代码与原代码一致
原理说明
两种方法都是通过固定模型的向上轴朝向,消除了绕目标方向(vC)的额外旋转自由度,从而避免侧滚。旋转后的模型不仅前方向对齐vC,局部Y轴也会保持在垂直于vC的平面内,且与原向上方向的投影一致。
内容的提问来源于stack exchange,提问作者MikeB
相关产品推荐
相关产品推荐

