113 Three.js的obb (OrientedboundingBox)方向包围盒的使用

本文详细介绍了包围盒在碰撞检测中的作用,包括AABB和OBB的特性及应用场景。在Three.js中,通过Box3和OBB.js库可以轻松获取模型的包围盒,用于高效的碰撞检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、包围盒简介:

包围盒是一个简单的几何空间,里面包含着复杂形状的物体。为物体添加包围体的目的是快速的进行碰撞检测或者进行精确的碰撞检测之前进行过滤(即当包围体碰撞,才进行精确碰撞检测和处理)。包围体类型包括球体、轴对齐包围盒(AABB)、有向包围盒(OBB)、8-DOP以及凸壳。

包围盒广泛地应用于碰撞检测,比如射击、点击、相撞等,每一个物体都有自己的包围盒。因为包围盒一般为规则物体,因此用它来代替物体本身进行计算,会比直接用物体本身更加高效和简单。

在这里插入图片描述
目前广泛应用的是AABB和OBB包围盒,其中AABB包围盒更常见。因为它的生成方法很简单,因它与坐标轴是对齐的。但它也有不足,它不随物体旋转,可以看出当图中的老虎沿着Z轴方向站立时,AABB包围盒还和老虎比较贴合,但当老虎转了一个角度后,AABB包围盒便增加了较大的空隙,对于较精确的碰撞检测效果不太好。这时就需要OBB包围盒,它始终沿着物体的主成分方向生成最小的一个矩形包围盒,可以随物体旋转,可用于较精确的碰撞检测。

以上摘自:https://blog.youkuaiyun.com/qing101hua/article/details/53100112

二、 Three.js中的包围盒使用

在three.js中,获取一个模型的包围盒有很多种方法,下面我列一下,我个人经常使用的:
第一种方法,也是最无脑的方法:
实例化一个THREE.Box3,然后用.expandByObject 直接可以获取到此模型的包围盒,而且还能包含它的子对象,官方注释(扩展此包围盒的边界,使得对象及其子对象在包围盒内,包括对象和子对象的世界坐标的变换。)
第二种方法,获取单个几何体的模型的方法:
首先获取到模型的geometry的boundingbox,然后把这个boundingbox乘以模型的世界变换矩阵,就可以实现包围盒的获取。
以上两种,都是获取AABB类型的包围盒,使用简单,理解简单,也好用。

针对于OBB包围盒,今天发现three.js也有相应的封装,文件地址在/examples/jsm/math/OBB.js
官方有demo,可以在我网站上翻一翻,地址:http://wjceo.com/three.js/examples/?q=obb#webgl_math_obb
在这里插入图片描述

你也可以自己打开一个官方的demo搜一下OBB,来查看一下,demo效果就是,如果两个盒子发生了碰撞,就会变成红色,仅此而已。

针对于这个OBB包围盒对象使用,我们需要手动设置其初始的包围盒尺寸,官方的demo没有在初始化的时候直接传值,而是,实例化后,直接设置的尺寸,而且还需要设置包围盒子尺寸的一半,不知道为啥要这么设置:

var obb = new OBB();
obb.halfSize.copy(new THREE.Vector(x, y, z)).multiplyScalar(0.5);

我们可以直接复制一下size的值,然后让每个值乘以0.5,就是一半的盒子。
每个对象都设置了一个OBB对象,那么怎么实现的碰撞检测。官方demo里面是在每一帧的render里面,因为demo里面的模型的几何体都是用的一个默认的几何体盒子,所以,在每一帧里面,模型都先copy了一下几何体的OBB对象,然后再乘以模型的世界矩阵,获取到了模型的OBB包围盒。
我们查看这个OBB.js文件,会发现里面有很多的内置方法,什么和点检测的,面检测碰撞的,和球的,所以,我们只需要调用相应的api即可。
官方demo在render里面,显示更新每个模型的OBB包围盒,然后拿着其中的一个和其它所有的OBB包围盒,通过intersectsOBB方法来检测是否碰撞,如果检测碰撞,直接设置颜色为红色。

### Three.js 中实现 OBB (定向包围盒)Three.js 中,标准库并不直接支持 OBB 的创建和操作。然而,可以通过自定义几何体并应用变换矩阵来模拟 OBB 行为。下面是一个简单的例子,展示了如何构建一个基本的 OBB 并将其应用于场景中的物体。 #### 创建 OBB 几何体 为了更好地理解这个过程,先考虑使用 `BoxGeometry` 来代表 OBB 形状的基础结构: ```javascript // 导入必要的模块 import * as THREE from 'three'; function createOBB(width, height, depth, position, rotation) { const geometry = new THREE.BoxGeometry(width, height, depth); // 应用旋转和平移转换到几何体上 const matrix = new THREE.Matrix4(); matrix.makeRotationFromEuler(rotation); // 设置旋转角度 geometry.applyMatrix4(matrix); const obbMesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0x00ff00 })); obbMesh.position.copy(position); // 移动位置 return obbMesh; } ``` 此函数接受宽度、高度、深度参数用于指定盒子尺寸;position 和 rotation 参数则用来调整其空间定位与方向[^1]。 #### 将 OBB 添加至场景 一旦有了上述辅助函数,就可以轻松地将 OBB 对象加入到 Three.js 场景中了: ```javascript const scene = new THREE.Scene(); // 定义 OBB 属性 const width = 2; // 长度 const height = 3; // 宽度 const depth = 4; // 高度 const pos = new THREE.Vector3(5, 6, 7); // 坐标位置 const rot = new THREE.Euler(Math.PI / 8, Math.PI / 4, 0); // 旋转角 // 创建并添加 OBB 到场景里 scene.add(createOBB(width, height, depth, pos, rot)); ``` 这段代码片段说明了怎样初始化一个新的场景,并通过调用之前定义好的 `createOBB()` 方法向其中插入了一个具有特定大小、方位及坐标的 OBB 物件。 请注意,这只是一个基础示例,实际项目可能还需要处理碰撞检测等功能,这时就需要更复杂的逻辑和技术手段了。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值