Three.js中文网 Three.js中文网
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Threejs进阶课程
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • Threejs文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Threejs进阶课程
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • Threejs文章
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交叉计算
    • 10.CannonJS物理引擎

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

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

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

    Capsule表示胶囊形状的几何体,具体说就是上面一个半球、中间一个圆柱、下面一个半球拼接构成的胶囊形状几何体。

    下面给大家讲解胶囊形状几何体apsule与八叉树表示的3D模型进行交叉计算,你可以类比以前的射线交叉计算,虽然不同,都是都是交叉相关的计算。

    # 项目引入胶囊碰撞体Capsule.js

    Three.js在目录/examples/jsm/math/下提供了一个胶囊形状的几何体Capsule.js。

    npm安装threejs情况下,Capsule.js扩展库引入路径。

    // 引入/examples/jsm/math/目录下胶囊扩展库Capsule.js
    import { Capsule } from 'three/examples/jsm/math/Capsule.js';
    

    本课程案例源码.html里面自定义了新的路径。

    import { Capsule } from 'three/addons/math/Capsule.js';
    

    # 创建胶囊几何体

    创建胶囊几何体:让胶囊底部半球与y=0的平面刚好相切即可。

    const R = 0.4;//胶囊半径
    const H = 1.7;//胶囊总高度
    const start = new THREE.Vector3(0, R, 0);//底部半球球心坐标
    const end = new THREE.Vector3(0, H - R, 0);//顶部半球球心坐标
    const capsule = new Capsule(start, end, R);
    console.log('capsule', capsule);
    

    # 练习:Mesh可视化上面胶囊几何体

    // 可视化胶囊几何体
    const capsuleHelper = CapsuleHelper(R, H);
    model.add(capsuleHelper);
    
    function CapsuleHelper(R, H) {
        const group = new THREE.Group();
        const material = new THREE.MeshLambertMaterial({
            color: 0x00ffff,
            transparent: true,
            opacity: 0.5,
        });
        // 底部半球
        const geometry = new THREE.SphereGeometry(R, 25, 25, 0, 2 * Math.PI, 0, Math.PI / 2);
        geometry.rotateX(Math.PI);
        const mesh = new THREE.Mesh(geometry, material);
        mesh.position.y = R;
        group.add(mesh)
        // 顶部半球
        const geometry2 = new THREE.SphereGeometry(R, 25, 25, 0, 2 * Math.PI, 0, Math.PI / 2);
        const mesh2 = new THREE.Mesh(geometry2, material);
        mesh2.position.set(0, H - R, 0)
        group.add(mesh2)
        // 中间圆柱
        const h = H - 2 * R
        const geometry3 = new THREE.CylinderGeometry(R, R, h,32,1,true);
        geometry3.translate(0, h / 2+R,0)
        const mesh3 = new THREE.Mesh(geometry3, material);
        group.add(mesh3)
        return group;
    }
    

    # 平移胶囊几何体

    平移胶囊碰撞体,使底部半球位于y=0的平面以下。

    capsule.translate(new THREE.Vector3(0, -R, 0));
    

    可视化胶囊的模型对象同步平移

    capsuleHelper.position.y += -R;
    

    换一种平移方式

    capsuleHelper.position.copy(capsule.start)
    capsuleHelper.position.y -= R;
    

    # 交叉计算

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

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

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

    # 胶囊放在斜面上

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

    capsule.translate(new THREE.Vector3(0, 0, -3*H));
    capsuleHelper.position.z += -3 * H;
    

    你可以看到交叉方向不再是垂直于平面

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

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

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

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

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

    // 根据碰撞结果平移胶囊碰撞体,使交叉重合深度为0
    capsule.translate(result.normal.multiplyScalar(result.depth));
    capsuleHelper.position.copy(capsule.start);
    capsuleHelper.position.y -= R;
    

    # 胶囊与楼梯交叉

    // 根据碰撞结果平移胶囊碰撞体,使交叉重合深度为0
    capsule.translate(result.normal.multiplyScalar(result.depth));
    capsuleHelper.position.copy(capsule.start);
    capsuleHelper.position.y -= R;
    

    平移后,不在于楼梯交叉,上升偏离地面了(如果运动起来,这个特点可以让胶囊产生上楼梯的效果,下节课会讲解)

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

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

    // 胶囊向上平移,与地面不交叉情况,查看计算结果
    capsule.translate(new THREE.Vector3(0, R, 0));
    capsuleHelper.position.y += R;
    

    交叉计算结果返回值false

    const result = worldOctree.capsuleIntersect(capsule);
    console.log('碰撞检测结果', result);
    
    1. 八叉树Octree扩展库介绍
    1. 物理引擎CannonJS简介和引入

    ← 1. 八叉树Octree扩展库介绍 1. 物理引擎CannonJS简介和引入→

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