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

Three.js加载OBJ模型实现爆炸/聚合效果的方向计算求助

解决Three.js OBJ模型爆炸/聚合效果的方案

嘿,作为Three.js新手,你已经能获取到模型部件并修改位置,这已经迈出了关键一步!你的核心问题是不知道部件该朝哪个方向运动,其实思路很简单:让每个部件沿着远离(爆炸)或靠近(聚合)模型中心的方向移动,下面我给你一步步拆解实现方法:

核心思路

OBJ加载后每个部件都是独立的Mesh,我们不需要操作顶点(那是单个几何体的爆炸方式),直接控制每个Mesh的位置即可:

  1. 先保存每个部件的初始位置,方便聚合时回到原位
  2. 确定一个爆炸中心点(比如模型的几何中心)
  3. 计算每个部件到爆炸中心的方向向量,爆炸时沿这个方向向外移动,聚合时反向移动

具体实现代码

第一步:加载模型后初始化数据

加载完OBJ模型后,先收集所有Mesh部件,保存它们的初始位置,并计算爆炸方向:

// 假设object是你加载的OBJ模型对象
const parts = [];
// 遍历模型,收集所有Mesh部件(避免嵌套层级漏掉)
object.traverse(child => {
  if (child.isMesh) {
    parts.push(child);
    // 保存部件的初始局部位置
    child.userData.initialPosition = child.position.clone();
  }
});

// 计算模型的几何中心作为爆炸点(比固定(0,0,0)更自然)
const boundingBox = new THREE.Box3().setFromObject(object);
const explosionCenter = boundingBox.getCenter(new THREE.Vector3());

// 给每个部件计算爆炸方向
parts.forEach(part => {
  // 计算从爆炸中心指向部件初始位置的方向向量,归一化后确保移动速度一致
  const direction = part.userData.initialPosition.clone().sub(explosionCenter).normalize();
  part.userData.explodeDirection = direction;
  // 给每个部件加随机速度,避免所有部件移动节奏完全一致
  part.userData.velocity = Math.random() * 0.5 + 0.2;
});

第二步:在动画循环中实现爆炸/聚合动画

用一个进度变量控制爆炸的程度,0是初始状态,1是完全爆炸,通过切换进度的增减来实现爆炸和聚合的切换:

// 爆炸进度:0=初始状态,1=完全爆炸
let explodeProgress = 0;
// 控制当前是爆炸还是聚合
let isExploding = true;
// 最大爆炸距离,可根据你的模型大小调整
const maxExplodeDistance = 150;

function animate() {
  requestAnimationFrame(animate);

  // 更新爆炸进度
  if (isExploding) {
    // 爆炸:进度增加到1后停止
    explodeProgress = Math.min(explodeProgress + 0.01, 1);
  } else {
    // 聚合:进度减少到0后停止
    explodeProgress = Math.max(explodeProgress - 0.01, 0);
  }

  // 更新每个部件的位置
  parts.forEach(part => {
    const initialPos = part.userData.initialPosition;
    const direction = part.userData.explodeDirection;
    const velocity = part.userData.velocity;

    // 计算当前进度下的位置偏移量
    const offset = direction.multiplyScalar(explodeProgress * maxExplodeDistance * velocity);
    // 设置部件新位置:初始位置 + 偏移量
    part.position.copy(initialPos).add(offset);
  });

  renderer.render(scene, camera);
}
animate();

第三步:添加交互切换爆炸/聚合(可选)

你可以加个点击事件来切换爆炸和聚合状态,比如:

window.addEventListener('click', () => {
  isExploding = !isExploding;
});

为什么和参考示例不同?

你找到的参考示例是对单个几何体的顶点做爆炸,而你的场景是多个独立的Mesh部件,所以不需要操作顶点数组,直接控制每个Mesh的position就可以,逻辑更简单。

内容的提问来源于stack exchange,提问作者Nguyễn Minh Vương

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:32:04