Three.js中文网 Three.js中文网
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
Web3D系统课程视频
  • 1. 数学几何计算基础

  • 2.位移、速度、加速度(向量)

  • 3.向量点乘、叉乘

  • 4.四元数、欧拉角(角度姿态)

  • 5.矩阵

  • 6.射线

  • 7.包围盒

  • 8.第一、三人称漫游

  • 9.漫游-八叉树碰撞检测

    • 1. 八叉树Octree扩展库介绍
    • 2. 胶囊几何`Capsule.js`
    • 3. 八叉树与胶囊Capsule交叉计算
      • 4. 角色漫游(八叉树碰撞检测)
      • 5. 设置重力加速度(下坡、坠落)
      • 6. 简化碰撞体(提升八叉树计算性能)
    • 10.CannonJS物理引擎

    • Three.js进阶教程
    • 9.漫游-八叉树碰撞检测
    郭隆邦
    2025-03-24
    目录

    3. 八叉树与胶囊Capsule交叉计算

    # 八叉树与胶囊Capsule交叉计算

    通过前面两小节介绍,大家对八叉树Octree.js和胶囊Capsule.js扩展库都有一定了解。

    下面给大家讲解胶囊碰撞体Capsule与八叉树Octree交叉计算的应用场景。

    # 胶囊与地面重合的计算问题

    大家可以思考一个问题,假设场景中有一个胶囊网格Mesh,如何计算这个网格Mesh与地面地形的交叉重合问题?

    或者换个说法,如何把与平移胶囊Mesh,确保他与地面刚刚不重合,而是相切。

    胶囊与地面交叉重合

    胶囊与地面不交叉重合

    这就要用到前面两节课讲到的八叉树Octree.js和胶囊Capsule.js。

    用数学几何胶囊Capsule表示胶囊网格Mesh,用八叉树Octree表示胶囊周围的地面或物体Mesh。

    const worldOctree = new Octree();
    const gltf = await loader.loadAsync("../地形.glb");
    worldOctree.fromGraphNode(gltf.scene);
    
    const R = 0.4;//胶囊半径
    const H = 1.7;//胶囊总高度
    const start = new THREE.Vector3(0, 0, 0);//底部半球球心坐标
    const end = new THREE.Vector3(0, H - 2*R, 0);//顶部半球球心坐标
    const capsule = new Capsule(start, end, R);
    

    # 交叉计算

    1. 胶囊碰撞体Capsule:代表胶囊网格模型capsuleMesh
    2. 八叉树Octree:代表地形网格模型

    Octree.capsuleIntersect(capsule)可以计算Octree表示的3D模型与胶囊几何体capsule是否重合交叉,如果有重合交叉,返回交叉相关的信息,具体说就是在某个方向上交叉重合的深度是多少。

    // 碰撞检测:几何体交叉计算
    // Octree表示的3D模型和Capsule交叉计算
    const result = worldOctree.capsuleIntersect(capsule);
    console.log('碰撞检测结果', result);
    
    • .depth交叉重合的深度
    • .normal深度对应的方向

    计算原理:先与八叉树里面的包围盒子节点进行交叉计算,在与相交叉的包围盒包含的三角形进行交叉计算。借助八叉树,相比较,for循环所有模型所有三角形分别进行交叉计算,更节约时间。

    # 根据交叉碰撞数据,平移碰撞体

    根据交叉碰撞数据,平移碰撞体,让胶囊碰撞体不在于八叉树对应模型重合。

    • .depth交叉重合的深度
    • .normal深度对应的方向

    总结:.normal数据的特点就是让胶囊沿着.normal方向,平移.depth距离,就能刚好确保交叉重合深度为0

    //平移胶囊碰撞体Capsule,保证与八叉树对应网格没有交叉
    capsule.translate(result.normal.multiplyScalar(result.depth));
    
    // 获取胶囊碰撞体坐标,同步胶囊网格capsuleMesh
    capsuleMesh.position.copy(capsule.start);
    capsuleMesh.position.y -= R;
    

    # 测试:胶囊放在斜面上

    平移胶囊放在斜面上,查看交叉重合计算结果。

    // 平移胶囊与斜坡交叉重合
    capsule.translate(new THREE.Vector3(0, 0, -5))
    capsuleMesh.position.z -= 5;
    

    测试下面代码是否同样可以做到保证胶囊Mesh与八叉树对应的地形不交叉

    capsule.translate(result.normal.multiplyScalar(result.depth));
    capsuleMesh.position.copy(capsule.start);
    capsuleMesh.position.y -= R;
    

    # 测试:胶囊与楼梯交叉

    // 平移胶囊与楼梯交叉重合
    capsule.translate(new THREE.Vector3(0, 0, 6.5))
    capsuleMesh.position.z += 6.5;
    

    测试下面代码是否同样可以做到保证胶囊Mesh与八叉树对应的地形不交叉

    capsule.translate(result.normal.multiplyScalar(result.depth));
    capsuleMesh.position.copy(capsule.start);
    capsuleMesh.position.y -= R;
    

    # 胶囊向上平移,与地面没有接触,查看交叉计算结果

    胶囊向上平移,与地面没有接触

    // 平移胶囊与地形没有交叉重合
    capsule.translate(new THREE.Vector3(0, 2*R, 0))
    capsuleMesh.position.y += 2*R;
    

    交叉计算结果返回值false

    const result = worldOctree.capsuleIntersect(capsule);
    console.log('碰撞检测结果', result);
    
    2. 胶囊几何`Capsule.js`
    4. 角色漫游(八叉树碰撞检测)

    ← 2. 胶囊几何`Capsule.js` 4. 角色漫游(八叉树碰撞检测)→

    Theme by Vdoing | Copyright © 2016-2025 豫ICP备16004767号-2
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式