Three.js 精密地形碰撞

Posted

技术标签:

【中文标题】Three.js 精密地形碰撞【英文标题】:Three.js Precision Terrain Collision 【发布时间】:2013-04-11 06:13:25 【问题描述】:

一直在使用 WebGL 库 Three.js 开发游戏引擎。我有基本的地形碰撞工作到我可以找到用户站立的脸的地步。使用面顶点的平均或最大 Y 位置是不够的。

我可以使用什么公式来找到对象相对于“站立”的地形面的确切 Y 位置?假设我知道面的四个顶点位置和对象矢量位置。

平面是由高度图增强的 THREE.PlaneGeometry(2000,2000,128,128)。上图是它的一张脸。

【问题讨论】:

有一个geometry.computeCentroids() 函数可以使用,然后使用人脸的质心。 我已经完成了 geo.computeCentroids() 但问题是角色并不总是站在脸的中心。 既然你在做碰撞,你已经在发送光线(我假设)。当您成功找到一张脸时,为什么不进行射线平面相交以找到确切的位置。不知道three.js是否有这个构建。 我正在使用另一种方法来查找人脸。射线投影性能不如我希望的那么好。不管怎样,我只能找到一张脸。我需要知道我站立的那部分面部的精确 y 位置。由于这张脸内没有顶点(仅在拐角处),因此只能使用我不知道的某种数学来推断这些数据。 【参考方案1】:

我无法将代码放在评论中,所以我把它放在这里。 你不需要做数学。让three.js 为您完成。您可以执行以下操作:

var plane = new THREE.Plane();
plane.setFromCoplanarPoints (v1, v2, v3);

// x, y, z: position of your object
var ray = new THREE.Ray (new THREE.Vector3(x, y, z), new THREE.Vector3(0, 1, 0));
var where = ray.intersectPlane (plane);

从 Vector3 的“位置”,您可以使用 y 组件来更改对象的位置。

【讨论】:

嗯,这不适用于我的飞机(这是一个 THREE.PlaneGeometry(2000,2000,128,128)),它已被高度图增强。 ray.intersectPlane (mesh) 给出错误“无法调用未定义的方法‘点’”。将几何传递给 intersectPlane 函数时也会发生同样的事情。那么,这个函数返回一个向量而不是一个人脸?如果它返回真正的相交向量(不是平面几何的最近顶点),我会改变我的地形代码以适应。我正在使用 r58。 v1, v2, v3 对应于图像中的顶点。代码中的“平面”与平面几何无关。并且 ray.intersectPlane 不采用网格。请看说明书。 我很犹豫是否要重新编写代码以使用 THREE.Plane 对象,但我不确定在此方法中创建的平面可以被高度图细分和置换,例如 THREE.PlaneGeometry 可以,并且使用 planeIntercept() 返回精确交点的向量,而不仅仅是来自它所击中的平面的几何数据。我知道 interceptObjects() 返回网格、几何数据、距离和其他一些信息,但不是确切的交点,因为用户可能(并且经常是)在顶点之间。 您将只为交叉点创建平面。而已。一旦你有了 v1、v2、v3 向量,创建它,做交集然后丢弃它。 好的,我不是每帧都创建平面,而是为每次检测重用同一个平面并重新定位它。现在移动需要 1 毫秒而不是 0 毫秒,我可以忍受。这种方法并不完美,但要好得多。我的角色不再漂浮在最大顶点位置的面上 =] 有时,当我移动时,我的脚会在陡峭的斜坡/下降时沉入水面以下,但仍然感谢。投票。【参考方案2】:

你可以很容易地找到你的对象站立的脸的高度

const down = new THREE.Vector3(0, -1, 0);
const raycaster = new THREE.Raycaster();

raycaster.set(obj.position, down);
const collisionResults = raycaster.intersectObject(terrain);

if (collisionResults.length > 0 && collisionResults[0].distance > 0)
   const pointHeight = collisionResults[0].point.y;

此时只需从对象的 y 坐标中减去 pointHeight,即可得到相对高度。

const relativeHeight = obj.position.y - pointHeight;

【讨论】:

虽然这绝对是最简单的方法,但有一个警告。例如,我的地形大约是 30K 多边形,使用这种方法比 Gaitat 的答案慢得多。

以上是关于Three.js 精密地形碰撞的主要内容,如果未能解决你的问题,请参考以下文章

Three.js重建真实地形教程

Three.js 进阶之旅:物理效果-碰撞和声音 💥

Three.js 用于碰撞检测的光线投射

Three.js实现高程数据加载

Three.JS程序化建模入门

Three.JS程序化建模入门