Simple Oriented Bounding Box OBB collision detection explaining(简单定向包围盒OBB冲突检测说明)
本文介绍了简单定向包围盒OBB冲突检测说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我可以实现AABB方法来检测碰撞它既简单又便宜,但我想实现OBB以获得更高的精度,所以我用模型初始化创建了边界框它由8个边界顶点和中心组成,每一帧我用变换矩阵变换所有的顶点以适应定向边界框但我不能理解检测两个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();
推荐答案
用于两个3D OBB之间的简单碰撞检测的分离轴定理的C++代码实现如下:
#include <iostream>
// define the operations to be used in our 3D vertices
struct vec3
{
float x, y, z;
vec3 operator- (const vec3 & rhs) const { return{ x - rhs.x, y - rhs.y, z - rhs.z }; }
float operator* (const vec3 & rhs) const { return{ x * rhs.x + y * rhs.y + z * rhs.z }; } // DOT PRODUCT
vec3 operator^ (const vec3 & rhs) const { return{ y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x }; } // CROSS PRODUCT
vec3 operator* (const float& rhs)const { return vec3{ x * rhs, y * rhs, z * rhs }; }
};
// set the relevant elements of our oriented bounding box
struct OBB
{
vec3 Pos, AxisX, AxisY, AxisZ, Half_size;
};
// check if there's a separating plane in between the selected axes
bool getSeparatingPlane(const vec3& RPos, const vec3& Plane, const OBB& box1, const OBB&box2)
{
return (fabs(RPos*Plane) >
(fabs((box1.AxisX*box1.Half_size.x)*Plane) +
fabs((box1.AxisY*box1.Half_size.y)*Plane) +
fabs((box1.AxisZ*box1.Half_size.z)*Plane) +
fabs((box2.AxisX*box2.Half_size.x)*Plane) +
fabs((box2.AxisY*box2.Half_size.y)*Plane) +
fabs((box2.AxisZ*box2.Half_size.z)*Plane)));
}
// test for separating planes in all 15 axes
bool getCollision(const OBB& box1, const OBB&box2)
{
static vec3 RPos;
RPos = box2.Pos - box1.Pos;
return !(getSeparatingPlane(RPos, box1.AxisX, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisY, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisZ, box1, box2) ||
getSeparatingPlane(RPos, box2.AxisX, box1, box2) ||
getSeparatingPlane(RPos, box2.AxisY, box1, box2) ||
getSeparatingPlane(RPos, box2.AxisZ, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisX^box2.AxisX, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisX^box2.AxisY, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisX^box2.AxisZ, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisY^box2.AxisX, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisY^box2.AxisY, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisY^box2.AxisZ, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisZ^box2.AxisX, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisZ^box2.AxisY, box1, box2) ||
getSeparatingPlane(RPos, box1.AxisZ^box2.AxisZ, box1, box2));
}
// a quick test to see the code working
int _tmain(int argc, _TCHAR* argv[])
{
// create two obbs
OBB A, B;
// set the first obb's properties
A.Pos = { 0.f, 0.f, 0.f }; // set its center position
// set the half size
A.Half_size.x = 10.f;
A.Half_size.y = 1.f;
A.Half_size.z = 1.f;
// set the axes orientation
A.AxisX = { 1.f, 0.f, 0.f };
A.AxisY = { 0.f, 1.f, 0.f };
A.AxisZ = { 0.f, 0.f, 1.f };
// set the second obb's properties
B.Pos = { 20.f, 0.f, 0.f }; // set its center position
// set the half size
B.Half_size.x = 10.f;
B.Half_size.y = 1.f;
B.Half_size.z = 1.f;
// set the axes orientation
B.AxisX = { 1.f, 0.f, 0.f };
B.AxisY = { 0.f, 1.f, 0.f };
B.AxisZ = { 0.f, 0.f, 1.f };
// run the code and get the result as a message
if (getCollision(A, B)) std::cout << "Collision!!!" << std::endl;
else std::cout << "No collision." << std::endl;
// pause and quit
std::cout << std::endl;
system("pause");
return 0;
}
这篇关于简单定向包围盒OBB冲突检测说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:简单定向包围盒OBB冲突检测说明
基础教程推荐
猜你喜欢
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- C++,'if' 表达式中的变量声明 2021-01-01
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- 设计字符串本地化的最佳方法 2022-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01