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

THREE.JS中如何实现物体绕各世界轴独立旋转

解决THREE.js中绕固定世界轴旋转3D物体的问题

你的问题出在用绝对角度生成四元数并按固定顺序相乘,这种方式本质是在物体的局部空间叠加旋转,导致轴会随物体姿态变化。要实现绕世界空间固定轴旋转,需要基于旋转增量直接在世界空间应用旋转,而非累积绝对角度。

核心思路

  • 放弃累积xRot/yRot/zRot这类绝对角度值,改用鼠标移动的增量值生成单次旋转的四元数
  • 绕世界轴旋转时,要将增量四元数左乘到物体当前的四元数上(THREE.js中四元数乘法顺序是最终姿态 = 新旋转 * 当前姿态,左乘相当于在世界空间叠加旋转)

修改后的代码

// 不需要预先定义xQuat/yQuat/zQuat,每次生成临时增量四元数即可
rotate(e, axis) {
  // 计算旋转增量,dy是鼠标移动量,除以100控制旋转速度
  const delta = e.movementY / 100;
  let incrementQuat = new THREE.Quaternion();
  const worldAxis = new THREE.Vector3();

  // 确定要旋转的世界空间轴
  switch(axis) {
    case 'x':
      worldAxis.set(1, 0, 0);
      break;
    case 'y':
      worldAxis.set(0, 1, 0);
      break;
    case 'z':
      worldAxis.set(0, 0, 1);
      break;
  }

  // 生成绕世界轴的增量旋转四元数
  incrementQuat.setFromAxisAngle(worldAxis, delta);
  // 左乘增量四元数,实现世界空间旋转
  this.target.quaternion.premultiply(incrementQuat);
}

关键细节解释

  • premultiply方法:等价于this.target.quaternion = incrementQuat.multiply(this.target.quaternion),确保新的旋转是在世界空间上叠加,而不是物体的局部空间
  • 直接使用世界轴向量:new THREE.Vector3(1,0,0)这类向量本身就是世界空间的轴,不需要做任何转换
  • 增量式旋转:每次只处理当前鼠标移动带来的旋转量,避免绝对角度累积导致的轴混乱

如果需要保留初始姿态的重置功能,可以额外存储一个初始四元数,重置时直接赋值:

// 初始化时保存初始姿态
this.initialQuat = this.target.quaternion.clone();

// 重置方法
resetRotation() {
  this.target.quaternion.copy(this.initialQuat);
}

内容的提问来源于stack exchange,提问作者BigChungus443

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:52:46