Three.js中计算四元数使实例网格朝向目标方向与法线
Three.js 实例网格双轴对齐的四元数计算方法
要同时让立方体的X轴对齐dir、Z轴对齐normal,不能直接分两次旋转(会导致轴约束冲突),正确的做法是先构建目标空间的正交坐标系,再生成对应的旋转四元数,步骤如下:
步骤1:预处理输入向量
确保dir和normal是单位向量,且严格正交(如果输入向量不正交,需要先做正交化修正,避免后续计算偏差):
const targetX = dir.clone().normalize(); let targetZ = normal.clone().normalize(); // 正交化:让targetZ与targetX严格垂直 const temp = targetX.clone().multiplyScalar(targetZ.dot(targetX)); targetZ.sub(temp).normalize();
步骤2:构建目标正交坐标系的Y轴
根据Three.js右手坐标系规则,目标Y轴由Z轴叉乘X轴得到:
const targetY = targetZ.clone().cross(targetX).normalize();
步骤3:从正交轴生成旋转矩阵并转换为四元数
用三个目标轴构造旋转矩阵,再将矩阵转换为四元数:
const rotationMatrix = new THREE.Matrix4(); // 按列序填充矩阵:X、Y、Z轴分别作为矩阵的前三列 rotationMatrix.makeBasis(targetX, targetY, targetZ); const quaternion = new THREE.Quaternion(); quaternion.setFromRotationMatrix(rotationMatrix);
完整代码示例
// 立方体默认初始轴 const xAxis = new THREE.Vector3(1, 0, 0); const zAxis = new THREE.Vector3(0, 0, 1); // 自定义目标方向与法线 const dir = new THREE.Vector3(0.5, 0.2, 0.8); const normal = new THREE.Vector3(-0.2, 0.8, 0.5); // 计算双轴对齐的四元数 const targetX = dir.clone().normalize(); let targetZ = normal.clone().normalize(); // 处理浮点误差导致的非正交情况 const dotProduct = targetZ.dot(targetX); if (Math.abs(dotProduct) > 0.0001) { const temp = targetX.clone().multiplyScalar(dotProduct); targetZ.sub(temp).normalize(); } const targetY = targetZ.clone().cross(targetX).normalize(); const rotationMatrix = new THREE.Matrix4(); rotationMatrix.makeBasis(targetX, targetY, targetZ); const quaternion = new THREE.Quaternion(); quaternion.setFromRotationMatrix(rotationMatrix);
注意事项
直接分步旋转(先对齐X轴再调整Z轴)会在输入向量非正交时出现偏差,而构建正交基的方法能保证三个轴始终符合右手坐标系规则,结果更稳定可靠。
内容的提问来源于stack exchange,提问作者leonidasarch
相关产品推荐
相关产品推荐

