先前想做个3D人物移动场景,那就必然会遇到碰撞检测的问题,那么今天就来浅谈一下Three.js的碰撞检测。

规则几何体

球体

在规则几何体,球体的碰撞检测是最好处理的,只要判断两点圆心之间的距离是否小于两球体半径之和便可判断是否发生碰撞。

1
2
3
4
function isCrashed() {
var dist = sphereL.position.clone().distanceTo(sphereR.position.clone());
return dist < 10;
}

效果如下:



矩形

如果矩形像球体一样处理,判断会不太精确。

如下图:



所幸,Three.js提供了一种方法让我们来进行碰撞检测,那既是射线(Raycaster)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function isCrashed() {
//获取到底部cube的中心点坐标
var originPoint = sphereR.position.clone();
for(var vertexIndex = 0; vertexIndex < sphereR.geometry.vertices.length; vertexIndex++){
//顶点原始坐标
var localVertex = sphereR.geometry.vertices[vertexIndex].clone();
//顶点经过变换后的坐标
var globaVertex = localVertex.applyMatrix4(sphereR.matrix);
//获得由中心指向顶点的向量
var directionVector = globaVertex.sub(sphereR.position);
//将方向向量初始化
var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
//检测射线与多个物体相交的情况
var collisionResults = ray.intersectObjects([sphereL]);
//如果返回结果不为空,且交点与射线起点的距离小于物体中心至顶点的距离,则发生碰撞
if(collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() + 1.2 ){
return true
}
}
return false
}

效果如下:



从效果可以看出,第二种方法会比第一种方法精确很多。

不规则几何体

对于不规则几何体,还是宜用射线,选取任意数量的顶点,以中心至顶点做射线,射线越密则越精确,但是效率却越低,为了提高运行效率,可只对运动的物体在其运动方向做射线,以此来判断物理是否碰撞上物体,而不必判断物体是否被碰撞,以此可提高一倍以上的性能。