You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Three.js + Rapier:带Y轴旋转的建筑碰撞盒错位问题

Three.js + Rapier:带Y轴旋转的建筑碰撞盒错位问题

看起来你遇到的是旋转变换顺序导致的坐标系不匹配问题,我来帮你拆解下原因和解决办法:

问题根源分析

你提到_center旋转后的AABB中心——这就是问题所在!Rapier的碰撞盒是基于刚体的本地坐标系定义的,但你用了旋转后的世界坐标系下的中心来计算碰撞盒位置,自然会和视觉上的模型错位。

当你给Building应用Y轴旋转后,模型的本地坐标系和世界坐标系已经发生了偏移,这时候用世界空间的AABB中心来做碰撞盒的相对位置,相当于在旋转后的空间里又叠加了一次偏移,肯定对不上。

具体解决办法

  • 改用本地坐标系的中心计算碰撞盒
    在基类Building中,一定要在应用旋转、位移等世界变换之前,计算模型的本地边界框中心:

    // 基类Building的初始化流程
    async loadModel() {
      // 1. 加载GLTF模型
      const gltf = await this.loadGLTF();
      this.model = gltf.scene;
    
      // 2. 先计算本地AABB和本地中心(关键:这时候还没加任何世界变换)
      this.model.geometry.computeBoundingBox();
      const localAABB = this.model.geometry.boundingBox;
      this._localCenter = localAABB.getCenter(new THREE.Vector3());
    
      // 3. 再应用旋转、位移等世界变换
      this.model.rotation.y = this.rotationY;
      this.model.position.set(this.posX, this.posY, this.posZ);
    
      // 4. 最后创建碰撞盒
      this._computeColliders();
    }
    

    然后在子类的_computeColliders里,用this._localCenter来定义碰撞盒的相对位置:

    // 子类的_computeColliders示例
    _computeColliders() {
      // 基于本地中心定义碰撞盒的本地偏移
      const wallCollider = RAPIER.ColliderDesc.cuboid(0.5, 3, 10)
        .setTranslation(
          this._localCenter.x + 2, // 相对于本地中心的X偏移
          this._localCenter.y + 1.5,
          this._localCenter.z
        );
      this.rigidBody.addCollider(wallCollider);
    }
    
  • 确保碰撞盒跟随刚体的世界变换
    Rapier的刚体(RigidBody)会自动继承你在Three.js中设置的旋转、位移,所以碰撞盒只需要定义相对于刚体本地坐标系的位置和大小,不需要再手动加世界旋转。如果你的刚体是和Building模型绑定的,刚体的变换要和模型保持一致:

    // 基类中创建刚体时同步变换
    this.rigidBody = this.world.createRigidBody(
      RAPIER.RigidBodyDesc.fixed()
        .setTranslation(this.model.position.x, this.model.position.y, this.model.position.z)
        .setRotation(this.model.quaternion)
    );
    
  • 避免变换顺序错误
    记住Three.js的变换优先级是缩放→旋转→位移(SRT),如果你的基类中变换顺序搞反了(比如先位移再旋转),也会导致坐标系混乱。严格按照「计算本地边界→应用变换→创建碰撞盒」的顺序来,就能避免大部分错位问题。

最后再提醒下

核心就是别把本地坐标系和世界坐标系搞混——Rapier碰撞盒认的是刚体的本地空间,而你之前误用了旋转后的世界空间坐标来定义,自然会和视觉模型错开。调整下计算中心的时机,换成本地坐标系的参考,应该就能完美对齐了!

火山引擎 最新活动