In my libgdx game I have 3D BoundingBoxes and Spheres for map and player objects. I want to calculate whether they collide with each other in order to properly simulate the motion of these objects. What method can I use to calculate whether these objects collide/intersect?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
You can use the following method:
public static boolean intersectsWith(BoundingBox boundingBox, Sphere sphere) {
float dmin = 0;
Vector3 center = sphere.center;
Vector3 bmin = boundingBox.getMin();
Vector3 bmax = boundingBox.getMax();
if (center.x < bmin.x) {
dmin += Math.pow(center.x - bmin.x, 2);
} else if (center.x > bmax.x) {
dmin += Math.pow(center.x - bmax.x, 2);
}
if (center.y < bmin.y) {
dmin += Math.pow(center.y - bmin.y, 2);
} else if (center.y > bmax.y) {
dmin += Math.pow(center.y - bmax.y, 2);
}
if (center.z < bmin.z) {
dmin += Math.pow(center.z - bmin.z, 2);
} else if (center.z > bmax.z) {
dmin += Math.pow(center.z - bmax.z, 2);
}
return dmin <= Math.pow(sphere.radius, 2);
}
It's modeled after
A Simple Method for Box-Sphere Intersection Testing by Jim Arvo from "Graphics Gems", Academic Press, 1990
The sample C code for which can be found here: http://www.realtimerendering.com/resources/GraphicsGems/gems/BoxSphere.c
回答2:
The above answer is only good for AABB (Axis Aligned Bounding Box). The method though is concise and beautiful. So I have expanded it to include general Bounding Box. Bellow is the minimum code that provide the same algorithm as above. In the code bellow a bounding box is specified by a center and 3 direction vectors R, S, and T. Each represent the direction and length the main edges of the box.
struct OBBox{
vector3 center;
vector3 S; // representing side s.
vector3 R;
vector3 T;
/* s, r, and t take -1 or +1 representing a corner along side S, R, and T correspondingly. If one of s, r, or t is 0 then middle of corresponding edge of the non-zero side is returned. If 2 of them are 0, then middle of the plane of the corresponding side is returned. */
vector3 getCorner(int s, int r, int t)
{
return center + ( s*S + r*R + t*T)/2.0;
}
}
public static boolean intersectsWith(OBBox bbox, Sphere sphere){
float dmin = 0.;
vector3 center = sphere.center;
float centerS = center.S;
float centerR = center.R;
float centerT = center.T;
vector3 bminS = bbox.getCorner(-1, 0, 0);
vector3 bmaxS = bbox.getCorner(1, 0, 0);
vector3 bminR = bbox.getCorner(0, -1, 0);
vector3 bmaxR = bbox.getCorner(0, 1, 0);
vector3 bminT = bbox.getCorner(0, 0, -1);
vector3 bmaxT = bbox.getCorner(0, 0, 1);
if(centerS < bminS.S) {
dmin += (centerS-bminS).(centerS-minS); // . means 3d dot product.
else if(centerS > bmaxS)
dmin += (centerS-bmaxS).(centerS-bmaxS);
}
if(centerR < bminR.R) {
dmin += (centerR-bminR).(centerR-minR);
else if(centerR > bmaxR.R)
dmin += (centerR-bmaxR).(centerR-bmaxR);
}
if(centerT < bminT.T) {
dmin += (centerT-bminT).(centerT-minT);
else if(centerT > bmaxT)
dmin += (centerT-bmaxT).(centerT-bmaxT);
}
return dmin <= (sphere.radius).(sphere.radius);
}