简单定向边界框OBB碰撞检测解释

我可以实现AABB方法来检测碰撞,它很容易且便宜,但是我想实现OBB以获得更高的精度,所以我创建了包含8个边界的模型初始化的边界框顶点和中心,每帧我转换所有的顶点与变换矩阵,以适应定向包围盒,但我不明白的方法来检测两个OBB之间的碰撞,我找不到一个简单和清晰的教程,解释算法与代码观点不是数学,因为我不是数学家。简单定向边界框OBB碰撞检测解释

,如果我有

struct Box { 

glm::vec3 vertices[8];

Box() {

for (int i = 0; i < 8; i++) {

vertices[i] = glm::vec3(0);

}

}

glm::vec3 max;

glm::vec3 min;

glm::vec3 origin;

void reCompute() {

max = vertices[0];

min = vertices[0];

for (int i = 1; i < 8; i++) {

max.x = max.x > vertices[i].x ? max.x : vertices[i].x;

max.y = max.y > vertices[i].y ? max.y : vertices[i].y;

max.z = max.z > vertices[i].z ? max.z : vertices[i].z;

min.x = min.x < vertices[i].x ? min.x : vertices[i].x;

min.y = min.y < vertices[i].y ? min.y : vertices[i].y;

min.z = min.z < vertices[i].z ? min.z : vertices[i].z;

}

origin = glm::vec3((max.x + min.x)/2.0f, (max.y + min.y)/2.0f, (max.z + min.z)/2.0f);

}

//AABB intersection

bool intersects(const Box &b) const {

return (min.x < b.max.x) && (max.x > b.min.x) && (min.y < b.max.y) && (max.y > b.min.y) && (min.z < b.max.z) && (max.z > b.min.z) && *this != b;

}

bool operator==(const Box& b) const {

return (max.x == b.max.x && max.y == b.max.y && max.z == b.max.z && min.x == b.min.x && min.y == b.min.y && min.z == b.min.z);

}

bool operator!=(const Box& b) const {

return (max.x != b.max.x) || (max.y != b.max.y) || (max.z != b.max.z) || (min.x != b.min.x) || (min.y != b.min.y) || (min.z != b.min.z);

}

};

在模型初始化创建盒子

box.vertices[0] = glm::vec3(meshMinX, meshMinY, meshMinZ); 

box.vertices[1] = glm::vec3(meshMaxX, meshMinY, meshMinZ);

box.vertices[2] = glm::vec3(meshMinX, meshMaxY, meshMinZ);

box.vertices[3] = glm::vec3(meshMaxX, meshMaxY, meshMinZ);

box.vertices[4] = glm::vec3(meshMinX, meshMinY, meshMaxZ);

box.vertices[5] = glm::vec3(meshMaxX, meshMinY, meshMaxZ);

box.vertices[6] = glm::vec3(meshMinX, meshMaxY, meshMaxZ);

box.vertices[7] = glm::vec3(meshMaxX, meshMaxY, meshMaxZ);

,每帧

我重新计算与模型

for (int n = 0; n < 8; n++) { 

boxs[j].vertices[n] = glm::vec3(matrix * glm::vec4(box.vertices[n], 1));

}

boxs[j].reCompute();

回答:

的变换矩阵箱知道两个OBB碰撞你使用SAT(分离轴定理):你必须投影这两个点的所有点在两个形状的每个法线上形状。然后你会看到两个形状的投影是否重叠在每个法线上都有碰撞。如果至少有一个没有重叠的法线,它们不会相互碰撞。所有这一切,你需要一种方法来做一个矢量在另一个上的正交投影,并返回一个标量,并且用一个方法来检查两个区间是否重叠。 我有一些代码,但它的Java:

/** 

* Vec u is projected on Vec v

* @param u 2d point

* @param v 2d axe

* @return the orthogonal projection

*/

public static float orthagonalProjectionOf(Vector2f u, Vector2f v){

float norme_u = u.lenght();

float norme_v = v.lenght();

float dot_u_v = dot(u, v);

float buffer = (dot_u_v/(norme_u*norme_v))*norme_u;

if(Float.isNaN(buffer))return 0;//If the vector u is null, then is orthogonal projection is 0, not a NaN

else return buffer;

}

重叠两类区间的:

/** 

* Get the overlapping of two interval on an axis.

* @param minA

* @param maxA

* @param minB

* @param maxB

* @return true overlapping. false if there is no overlapping

*/

public static boolean isOverlapping(float minA, float maxA, float minB, float maxB) {

float minOverlap = Float.NaN;

float maxOverlap = Float.NaN;

//If B contain in A

if(minA <= minB && minB <= maxA) {

if(Float.isNaN(minOverlap) || minB < minOverlap)minOverlap = minB;

}

if(minA <= maxB && maxB <= maxA) {

if(Float.isNaN(maxOverlap) || maxB > minOverlap)maxOverlap = maxB;

}

//If A contain in B

if(minB <= minA && minA <= maxB) {

if(Float.isNaN(minOverlap) || minA < minOverlap)minOverlap = minA;

}

if(minB <= maxA && maxA <= maxB) {

if(Float.isNaN(maxOverlap) || maxA > minOverlap)maxOverlap = maxA;

}

if(Float.isNaN(minOverlap) || Float.isNaN(maxOverlap))return false; //Pas d'intersection

else return true;//Intersection

}

随着你都能够做到的方法来测试的U开V

Orthagonal投影两个OBB之间的碰撞:

public boolean OBBwOBB(RigidBody bodyA, RigidBody bodyB) { 

Shape shapeA = bodyA.getObb().getShape();

Shape shapeB = bodyB.getObb().getShape();

short overlapCompt = 0;

//We test for each normal the projection of the two shape

//Shape A :

for(int i = 0; i < shapeA.getNbrOfNormals(); i++) {

Vector2f normal = shapeA.getNormal(i, bodyA.getAngle());

boolean overlap = overlapOnThisNormal(bodyA, bodyB, normal);

if(overlap) {

overlapCompt++;

}

}

//Shape B :

for(int i = 0; i < shapeB.getNbrOfNormals(); i++) {

Vector2f normal = shapeB.getNormal(i, bodyB.getAngle());

boolean overlap = overlapOnThisNormal(bodyA, bodyB, normal);

if(overlap){

overlapCompt++;

}

}

//Now we see if there is a collision

short howManyNormals = (short) (shapeA.getNbrOfNormals() + shapeB.getNbrOfNormals());

if(overlapCompt == howManyNormals){//If the number of overlap equal the number of normal in both shape :

return true;

}

else return false;

}

而且您将需要它t为两个形式投影在向量的投影的最小值和最大值:

/** 

* Test if the orthogonal projection of two shape on a vector overlap.

* @param bodyA

* @param bodyB

* @param normal

* @return null if no overlap, else Vector2f(minOverlaping, maxOverlaping).

*/

public static boolean overlapOnThisNormal(RigidBody bodyA, RigidBody bodyB, Vector2f normal) {

Shape shapeA = bodyA.getObb().getShape();

Shape shapeB = bodyB.getObb().getShape();

//We test each vertex of A

float minA = Float.NaN;

float maxA = Float.NaN;

for(short j = 0; j < shapeA.getNbrOfPoint(); j++){

Vector2f vertex = shapeA.getVertex(j, bodyA.getScale().x, bodyA.getScale().y, bodyA.getPosition().x, bodyA.getPosition().y, bodyA.getAngle());

float bufferA = Vector2f.orthagonalProjectionOf(vertex, normal);

if(Float.isNaN(minA) || bufferA < minA)minA = bufferA;//Set min interval

if(Float.isNaN(maxA) || bufferA > maxA)maxA = bufferA;//Set max interval

}

//We test each vertex of B

float minB = Float.NaN;

float maxB = Float.NaN;

for(short j = 0; j < shapeB.getNbrOfPoint(); j++){

Vector2f vertex = shapeB.getVertex(j, bodyB.getScale().x, bodyB.getScale().y, bodyB.getPosition().x, bodyB.getPosition().y, bodyB.getAngle());

float bufferB = Vector2f.orthagonalProjectionOf(vertex, normal);

if(Float.isNaN(minB) || bufferB < minB)minB = bufferB;//Set min interval

if(Float.isNaN(maxB) || bufferB > maxB)maxB = bufferB;//Set max interval

}

//We test if there overlap

boolean overlap = isOverlapping(minA, maxA, minB, maxB);

return overlap;

}

我希望这个帮你;)

以上是 简单定向边界框OBB碰撞检测解释 的全部内容, 来源链接: utcz.com/qa/262563.html

回到顶部