threejs - 包围盒和包围球

在Three.js中,包围盒(Bounding Box)和包围球(Bounding Sphere)是两种常见的用于简化碰撞检测和空间查询的几何体

包围盒

  1. 碰撞检测:包围盒是一个简单的几何空间,里面包含着复杂形状的物体。通过为物体添加包围盒,可以在进行精确的碰撞检测之前进行过滤,即当包围盒碰撞时,才进行精确的碰撞检测和处理。这样可以显著提高碰撞检测的效率。
  2. 场景边界判定:包围盒可以作为场景边界的判定值,用于确定物体是否在某个特定区域内。
  3. 体积和中心点计算:对于不规则物体,可以通过包围盒来近似计算其体积和中心点。

计算几何体的矩形包围

js 复制代码
gltfLoader.load(
  "./model/Duck.glb",
  (gltf)=>{
    console.log(gltf);
    // 把模型加入到场景中
    scene.add(gltf.scene)
    // 获取到几何体
    let duckMesh = gltf.scene.getObjectByName("LOD3spShape")
    let duckGeometry = duckMesh.geometry
    // 计算包围盒
    duckGeometry.computeBoundingBox()
    // 获取包围盒
    let duckBox = duckGeometry.boundingBox
    // 创建包围盒辅助器
    let boxHelper = new THREE.Box3Helper(duckBox, 0xffff00)
    // 更新世界矩阵
    duckMesh.updateWorldMatrix(true, true)
    // 更新包围盒
    duckBox.applyMatrix4(duckMesh.matrixWorld)
    // 添加到场景中
    scene.add(boxHelper)
  }
)

几何体居中

几何体.center()

js 复制代码
const gltfLoader = new GLTFLoader()
gltfLoader.load(
  "./model/Duck.glb",
  (gltf)=>{
    console.log(gltf);
    // 把模型加入到场景中
    scene.add(gltf.scene)
    // 获取到几何体
    let duckMesh = gltf.scene.getObjectByName("LOD3spShape")
    let duckGeometry = duckMesh.geometry
    // 设置居中
    duckGeometry.center()
    // 计算包围盒
    duckGeometry.computeBoundingBox()
    // 获取包围盒
    let duckBox = duckGeometry.boundingBox
    // 创建包围盒辅助器
    let boxHelper = new THREE.Box3Helper(duckBox, 0xffff00)
    // 更新世界矩阵
    duckMesh.updateWorldMatrix(true, true)
    // 更新包围盒
    duckBox.applyMatrix4(duckMesh.matrixWorld)
    // 添加到场景中
    scene.add(boxHelper)
  }
)
获取包围盒中心点
js 复制代码
// 获取包围盒中心点
    let center = duckBox.getCenter(new THREE.Vector3())

包围球

  1. 碰撞检测:与包围盒类似,包围球也可以用于碰撞检测。通过将物体封装到一个包围球中,可以简化碰撞检测的计算过程。
  2. 相机飞行参考值:在Three.js中,包围球还可以作为相机飞行的参考值,帮助确定相机的移动范围和视角。
js 复制代码
 // 获取包围球
let duckSphere = duckGeometry.boundingSphere
duckSphere.applyMatrix4(duckMesh.matrixWorld)
// 创建包围球辅助器
let sphereGeometry = new THREE.SphereGeometry(duckSphere.radius, 16, 16)
let sphereMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  wireframe: true
})
let sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial)
sphereMesh.position.copy(duckSphere.center)
scene.add(sphereMesh)

多个物体的包围盒

第一种方式

循环需要包围的盒子,用一个空盒子合并需要包围的盒子,然后创建父盒子的包围盒

js 复制代码
let box = new THREE.Box3()
let arrSphere = [sphere1, sphere2, sphere3]
for (let i = 0; i < arrSphere.length; i++) {
  // 计算当前物体的包围盒
  arrSphere[i].geometry.computeBoundingBox()
  // 获取包围盒
  let box3 = arrSphere[i].geometry.boundingBox
  // 更新世界矩阵
  arrSphere[i].updateWorldMatrix(true, true)
  // 将包围盒转换到世界坐标系
  box3.applyMatrix4(arrSphere[i].matrixWorld)
  // 合并包围盒
  box.union(box3)
}
// 创建包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 0xffff00)
scene.add(boxHelper)

第二种方式

使用setFromObject,计算包围盒的3D对象

js 复制代码
let box = new THREE.Box3()
let arrSphere = [sphere1, sphere2, sphere3]
for (let i = 0; i < arrSphere.length; i++) {
  let box3 = new THREE.Box3().setFromObject(arrSphere[i])
  // 合并包围盒
  box.union(box3)
}
// 创建包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 0xffff00)
scene.add(boxHelper)
相关推荐
小彭努力中9 小时前
138. CSS3DRenderer渲染HTML标签
前端·深度学习·3d·webgl·three.js
优雅永不过时·13 小时前
three.js实现地球 外部扫描的着色器
前端·javascript·webgl·three.js·着色器
阿铎前端4 天前
Three.js PBR材质
vue·three.js
二三ErSan6 天前
深入探索ES 3D Editor:一个基于ThreeJS + Vue 3 + Naive UI的三维编辑器
three.js
Sword998 天前
【ThreeJs原理解析】第2期 | 旋转、平移、缩放实现原理
前端·three.js·源码阅读
小白菜学前端8 天前
Threejs 材质贴图、光照和投影详解
前端·3d·three.js
破浪前行·吴9 天前
使用@react-three/fiber,@mkkellogg/gaussian-splats-3d加载.splat,.ply,.ksplat文件
前端·react.js·three.js
格瑞@_@16 天前
11.Three.js使用indexeddb前端缓存模型优化前端加载效率
前端·javascript·缓存·three.js·indexeddb缓存
谢小飞16 天前
我做了三把椅子原来纹理这样加载切换
前端·three.js
小白菜学前端17 天前
ThreeJS创建一个3D物体的基本流程
3d·three.js