82 lines
2.7 KiB
C++
82 lines
2.7 KiB
C++
#include "IntersectTests.h"
|
|
|
|
//************************************
|
|
// Check if AABB and triangle intersect using the separating axis theorem
|
|
//************************************
|
|
bool IntersectTests::BoxTriangleIntersection(glm::vec3 minPosition, glm::vec3 maxPosition, glm::vec3 triangle[3]) {
|
|
|
|
// Box center and half vector
|
|
glm::vec3 c = .5f * (minPosition + maxPosition);
|
|
glm::vec3 h = maxPosition - c;
|
|
|
|
// Translate triangle to center box at origin
|
|
glm::vec3 v0 = triangle[0] - c;
|
|
glm::vec3 v1 = triangle[1] - c;
|
|
glm::vec3 v2 = triangle[2] - c;
|
|
|
|
// Crossproduct(edge from tri, {x,y,z}-directin), this gives 3x3=9 more tests
|
|
glm::vec2 hx = glm::vec2(h.y, h.z);
|
|
glm::vec2 hy = glm::vec2(h.x, h.z);
|
|
glm::vec2 hz = glm::vec2(h.x, h.y);
|
|
|
|
glm::vec2 v0x = glm::vec2(v0.y, v0.z);
|
|
glm::vec2 v0y = glm::vec2(v0.x, v0.z);
|
|
glm::vec2 v0z = glm::vec2(v0.x, v0.y);
|
|
glm::vec2 v1x = glm::vec2(v1.y, v1.z);
|
|
glm::vec2 v1y = glm::vec2(v1.x, v1.z);
|
|
glm::vec2 v1z = glm::vec2(v1.x, v1.y);
|
|
glm::vec2 v2x = glm::vec2(v2.y, v2.z);
|
|
glm::vec2 v2y = glm::vec2(v2.x, v2.z);
|
|
glm::vec2 v2z = glm::vec2(v2.x, v2.y);
|
|
|
|
// Triangle edges and normal
|
|
glm::vec3 e0 = glm::vec3(v1 - v0);
|
|
glm::vec3 fe0 = glm::abs(e0);
|
|
if (AxisTest(e0.z, e0.y, fe0.z, fe0.y, v0x, v2x, hx) ||
|
|
AxisTest(e0.z, e0.x, fe0.z, fe0.x, v0y, v2y, hy) ||
|
|
AxisTest(e0.y, e0.x, fe0.y, fe0.x, v1z, v2z, hz))
|
|
return false;
|
|
|
|
glm::vec3 e1 = glm::vec3(v2 - v1);
|
|
glm::vec3 fe1 = glm::abs(e1);
|
|
if (AxisTest(e1.z, e1.y, fe1.z, fe1.y, v0x, v2x, hx) ||
|
|
AxisTest(e1.z, e1.x, fe1.z, fe1.x, v0y, v2y, hy) ||
|
|
AxisTest(e1.y, e1.x, fe1.y, fe1.x, v0z, v1z, hz))
|
|
return false;
|
|
|
|
glm::vec3 e2 = glm::vec3(v0 - v2);
|
|
glm::vec3 fe2 = glm::abs(e2);
|
|
if (AxisTest(e2.z, e2.y, fe2.z, fe2.y, v0x, v1x, hx) ||
|
|
AxisTest(e2.z, e2.x, fe2.z, fe2.x, v0y, v1y, hy) ||
|
|
AxisTest(e2.y, e2.x, fe2.y, fe2.x, v1z, v2z, hz))
|
|
return false;
|
|
|
|
// Test box against minimal AABB around triangle
|
|
glm::vec3 vMin = glm::min(v0, v1);
|
|
vMin = glm::min(vMin, v2);
|
|
glm::vec3 vMax = glm::max(v0, v1);
|
|
vMax = glm::max(vMax, v2);
|
|
|
|
if (glm::any(glm::greaterThan(vMin, h)) || glm::any(glm::lessThan(vMax, -h)))
|
|
return false;
|
|
|
|
// Test box against triangle plane
|
|
glm::vec3 n = glm::cross(e0, e1);
|
|
vMin = -glm::sign(n) * h - v0;
|
|
vMax = glm::sign(n) * h - v0;
|
|
if (glm::dot(n, vMin) > 0.f || glm::dot(n, vMax) < 0.f)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//************************************
|
|
// Help method
|
|
//************************************
|
|
bool IntersectTests::AxisTest(float a, float b, float fa, float fb, glm::vec2 v0, glm::vec2 v1, glm::vec2 h) {
|
|
float p0 = a*v0.x - b*v0.y;
|
|
float p1 = a*v1.x - b*v1.y;
|
|
float rad = fa * h.x + fb * h.y;
|
|
return glm::min(p0, p1) > rad || glm::max(p0, p1) < -rad;
|
|
}
|