You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:23:17