我试图为定向包围框(OBB)和轴对齐边界框(AABB)编写一些交叉代码。我有OBB-OBB交集,使用分离轴定理(SAT),我正在试图找出如何将这段代码改进到我所知道的比较OBB和AABB的具体情况。
这是我的函数代码:
bool Collider::isColliding(OBB * one, OBB * other)
{
TestManager::collisionTests++;
glm::vec3 oneCenter = one->m_gameObject->getWorldPosition(); // object's pos = collider center
glm::mat4 oneTransform = glm::scale(one->m_gameObject->getTransform(), one->m_halfSize); // scaling for halfsize
glm::vec3 otherCenter = other->m_gameObject->getWorldPosition();
glm::mat4 otherTransform = glm::scale(other->m_gameObject->getTransform(), other->m_halfSize);
for (int a = 0; a < 3; a++) {
glm::vec3 l = glm::vec3(oneTransform[a]); // one axis to project on
float tl = std::abs(glm::dot(l, otherCenter) - glm::dot(l, oneCenter)); // center distance
float ra = std::abs(glm::dot(l, glm::vec3(oneTransform[0]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[1]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[2])));
float rb = std::abs(glm::dot(l, glm::vec3(otherTransform[0]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[1]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[2])));
float penetration = (ra + rb) - tl;
if (penetration <= 0) { // no overlap
return false;
}
}
for (int b = 0; b < 3; b++) {
glm::vec3 l = glm::vec3(otherTransform[b]); // other axis to project on
float tl = std::abs(glm::dot(l, otherCenter) - glm::dot(l, oneCenter)); // center distance
float ra = std::abs(glm::dot(l, glm::vec3(oneTransform[0]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[1]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[2])));
float rb = std::abs(glm::dot(l, glm::vec3(otherTransform[0]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[1]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[2])));
float penetration = (ra + rb) - tl;
if (penetration <= 0) { // no overlap
return false;
}
}
for (int a = 0; a < 3; a++) {
glm::vec3 aAxis = glm::vec3(oneTransform[a]);
for (int b = 0; b < 3; b++) {
glm::vec3 bAxis = glm::vec3(otherTransform[b]);
if (aAxis != bAxis) {
glm::vec3 l = glm::cross(aAxis, bAxis); // has flaw when axis are same, result in (0,0,0), solved by if
float tl = std::abs(glm::dot(l, otherCenter) - glm::dot(l, oneCenter)); // center distance
float ra = std::abs(glm::dot(l, glm::vec3(oneTransform[0]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[1]))) + std::abs(glm::dot(l, glm::vec3(oneTransform[2])));
float rb = std::abs(glm::dot(l, glm::vec3(otherTransform[0]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[1]))) + std::abs(glm::dot(l, glm::vec3(otherTransform[2])));
float penetration = (ra + rb) - tl;
if (penetration <= 0) { // no overlap
return false;
}
}
}
}
return true;
}希望你能帮我。
发布于 2018-04-23 19:45:38
看起来你是用这个来进行所谓的宽相位碰撞检测。这是碰撞检测中的步骤,用于确定执行实际碰撞检测(快速总结)的狭窄阶段的候选对。
因为这是一个边框文本(特别是如果您涉及到AABB),看起来您只是想看看是否要通过这两个形状的实际交叉口路线。如果你能坚持AABB在一般情况下,数学变得容易得多,因此更快。此外,您还可以使用AABB-树(它们是空间部分树)来为一个对象查找所有的交叉点候选对象,而不是对一个对象进行配对检查。
发布于 2018-04-23 18:03:55
脑垃圾场:
tl、ra和rb。他们最好分别担任centerDistance、oneProjectedDistance和otherProjectedDistance。(也许也可以考虑radiusOne和radiusOther )。关于这一点:a可能就是axis最后但同样重要的是,我想知道你为什么不在着色器里这样做.
在我(公认的业余)理解着色器基本上是为了快速执行浮点数学,很少分支在GPU上。
这也可能使代码看起来不那么笨重。考虑:
for (int axis = 0; axis < 3; axis++)
{
vec3 projectionAxis = oneTransform[axis].xyz;
float distance = abs(projectionAxis.dot(otherCenter) - projectionAxis.dot(oneCenter));
float radius_a = abs(projectionAxis.dot(oneTransform[0].xyz))
+ abs(projectionAxis.dot(oneTransform[1].xyz))
+ abs(projectionAxis.dot(oneTransform[2].xyz));
// ...对我来说,这读起来要清晰一些,因为parens更容易理解,并且在一看就可以更容易地掌握所涉及的坐标。
现在,至少我可以更清楚地了解到底发生了什么,我不禁想知道,这是否可以用如下方式来表达:
(免责声明:我只对wolframalpha做了一些快速检查,以确定尺寸是否匹配)
vec3 radius_a_vec = abs(transpose(oneTransform) * projectionAxis);
float radius_a = radius_a_vec.x + radius_a_vec.y + radius_a_vec.z;这使得数学更难理解,但它极大地简化了对代码的研究。
https://codereview.stackexchange.com/questions/192753
复制相似问题