写点什么

使用 THREE.js 进行边界体积碰撞检测

作者:3D建模设计
  • 2023-08-31
    湖北
  • 本文字数:2558 字

    阅读完需:约 8 分钟

使用 THREE.js 进行边界体积碰撞检测

推荐:使用NSDT场景编辑器快速搭建 3D 应用场景

使用 Box3 和 Sphere

三.js 具有表示数学体积和形状的对象 - 对于 3D AABB 和边界球体,我们可以使用Box3Sphere对象。实例化后,它们具有可用于针对其他卷进行交集测试的方法。

实例化盒子

要创建 Box3 实例,我们需要提供盒子的下限和上限。通常,我们希望这个 AABB 被“链接”到我们 3D 世界中的对象(如角色)。在 Three.js 中,实例具有对象的属性和边界。请记住,为了定义此属性,您需要事先手动调用。GeometryboundingBoxminmaxGeometry.computeBoundingBox

.JS 复制到剪贴板

const knot = new THREE.Mesh(  new THREE.TorusKnotGeometry(0.5, 0.1),  new MeshNormalMaterial({}),);
knot.geometry.computeBoundingBox();const knotBBox = new Box3( knot.geometry.boundingBox.min, knot.geometry.boundingBox.max,);
复制代码

注意:该属性将自身作为引用,而不是 .因此,在计算计算框时,应用于 的任何转换(例如比例、位置等)都将被忽略。boundingBoxGeometryMeshMesh

解决上一个问题的更简单的替代方法是稍后使用 设置这些边界,这将计算尺寸,同时考虑 3D 实体的变换任何子网格Box3.setFromObject

.JS 复制到剪贴板

const knot = new THREE.Mesh(  new THREE.TorusKnotGeometry(0.5, 0.1),  new MeshNormalMaterial({}),);
const knotBBox = new Box3(new THREE.Vector3(), new THREE.Vector3());knotBBox.setFromObject(knot);
复制代码

实例化球体

实例化 Sphere 对象与此类似。我们需要提供球体的中心和半径,可以将其添加到 中可用的属性中。boundingSphereGeometry

.JS 复制到剪贴板

const knot = new THREE.Mesh(  new THREE.TorusKnotGeometry(0.5, 0.1),  new MeshNormalMaterial({}),);
const knotBSphere = new Sphere( knot.position, knot.geometry.boundingSphere.radius,);
复制代码

遗憾的是,没有等效的 Sphere 实例。因此,如果我们应用变换或更改位置 ,我们需要手动更新边界球体。例如:Box3.setFromObjectMesh

.JS 复制到剪贴板

knot.scale.set(2, 2, 2);knotBSphere.radius = knot.geometry.radius * 2;
复制代码

交叉测试

点与Box3 / Sphere

两者都有一个包含点方法来执行此测试。Box3Sphere

.JS 复制到剪贴板

const point = new THREE.Vector3(2, 4, 7);knotBBox.containsPoint(point);
复制代码

Box3Box3

Box3.intersectsBox 方法可用于执行此测试。

.JS 复制到剪贴板

knotBbox.intersectsBox(otherBox);
复制代码

注意:这与检查 Box3 是否完全包装另一个的方法不同。Box3.containsBox

SphereSphere

与以前类似的方式,有一个 Sphere.intersectsSphere 方法来执行此测试。

.JS 复制到剪贴板

knotBSphere.intersectsSphere(otherSphere);
复制代码

SphereBox3

不幸的是,这个测试没有在 Three.js 中实现,但我们可以修补 Sphere 以实现 Sphere 与 AABB 交集算法。

.JS 复制到剪贴板

// expand THREE.js Sphere to support collision tests vs. Box3// we are creating a vector outside the method scope to// avoid spawning a new instance of Vector3 on every check
THREE.Sphere.__closest = new THREE.Vector3();THREE.Sphere.prototype.intersectsBox = function (box) { // get box closest point to sphere center by clamping THREE.Sphere.__closest.set(this.center.x, this.center.y, this.center.z); THREE.Sphere.__closest.clamp(box.min, box.max);
const distance = this.center.distanceToSquared(THREE.Sphere.__closest); return distance < this.radius * this.radius;};
复制代码

演示

我们准备了一些现场演示来演示这些技术,并提供了要检查的源代码。

使用 BoxHelper

作为使用 raw 和 object 的替代方法,Three.js 有一个有用的对象,可以更轻松地处理边界框:BoxHelper(以前已弃用)。此帮助程序获取并为其计算边界框体积(包括其子网格)。这将生成一个表示边界框的新框,该框显示边界框的形状,并且可以传递给前面看到的方法,以便使边界框与 .Box3SphereBoundingBoxHelperMeshMeshsetFromObjectMesh

BoxHelper是处理 Three.js 中边界体积的 3D 碰撞的推荐方法。你会错过球体测试,但权衡是非常值得的。

使用此帮助程序的优点是:

  • 它有一个方法,如果链接的网格旋转或更改其尺寸,它将调整其边界框网格的大小,并更新其位置update()

  • 它在计算边界框的大小时会考虑子网格,因此原始网格及其所有子网格都已包装。

  • 我们可以通过渲染创建的 es 来轻松调试碰撞。默认情况下,它们是使用材质(用于绘制线框样式几何图形的三.js 材质)创建的。MeshBoxHelperLineBasicMaterial

主要缺点是它只创建框边界体积,所以如果你需要球体与 AABB 测试,你需要创建自己的对象。Sphere

要使用它,我们需要创建一个新实例并提供几何体和(可选)将用于线框材料的颜色。我们还需要将新创建的对象添加到场景中才能渲染它。我们假设我们的场景变量被调用。BoxHelperthree.jsscene

.JS 复制到剪贴板

const knot = new THREE.Mesh(  new THREE.TorusKnotGeometry(0.5, 0.1),  new THREE.MeshNormalMaterial({}),);const knotBoxHelper = new THREE.BoxHelper(knot, 0x00ff00);scene.add(knotBoxHelper);
复制代码

为了也拥有我们的实际边界框,我们创建了一个新对象并使其具有 的形状和位置。Box3Box3BoxHelper

.JS 复制到剪贴板

const box3 = new THREE.Box3();box3.setFromObject(knotBoxHelper);
复制代码

如果我们更改位置、旋转、缩放等,我们需要调用该方法,以便实例与其链接匹配。我们还需要再次调用才能使 .Meshupdate()BoxHelperMeshsetFromObjectBox3Mesh

.JS 复制到剪贴板

knot.position.set(-3, 2, 1);knot.rotation.x = -Math.PI / 4;// update the bounding box so it stills wraps the knotknotBoxHelper.update();box3.setFromObject(knotBoxHelper);
复制代码

执行碰撞测试的方式与上一节中解释的方式相同 — 我们使用 Box3 对象的方式与上述相同。

.JS 复制到剪贴板

// box vs. boxbox3.intersectsBox(otherBox3);// box vs. pointbox3.containsPoint(point.position);
复制代码

演示

您可以在我们的现场演示页面上查看两个演示。第一个展示了使用 .第二个执行盒与盒测试。BoxHelper


原文链接:使用 THREE.js 进行边界体积碰撞检测 (mvrlink.com)

发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2023-04-14 加入

还未添加个人简介

评论

发布
暂无评论
使用 THREE.js 进行边界体积碰撞检测_three.js_3D建模设计_InfoQ写作社区