Skip to content

Instantly share code, notes, and snippets.

@BoyBaykiller
Last active October 27, 2023 03:00
Show Gist options
  • Select an option

  • Save BoyBaykiller/b2ee57415d0e10ce85c70fbfaa99c604 to your computer and use it in GitHub Desktop.

Select an option

Save BoyBaykiller/b2ee57415d0e10ce85c70fbfaa99c604 to your computer and use it in GitHub Desktop.
Box vs Triangle Intersection test GLSL
float Min3(float a, float b, float c)
{
return min(a, min(b, c));
}
float Max3(float a, float b, float c)
{
return max(a, max(b, c));
}
bool BoxTriangleIntersect(vec3 boxMin, vec3 boxMax, vec3 triP0, vec3 triP1, vec3 triP2)
{
vec3 boxCenter = (boxMax + boxMin) * 0.5;
vec3 boxHalfSize = (boxMax - boxMin) * 0.5;
// Translate triangle as conceptually moving Box to origin
vec3 v0 = (triP0 - boxCenter);
vec3 v1 = (triP1 - boxCenter);
vec3 v2 = (triP2 - boxCenter);
// Compute edge vectors for triangle
vec3 f0 = (v1 - v0);
vec3 f1 = (v2 - v1);
vec3 f2 = (v0 - v2);
/// Region: Test axes a00..a22 (category 3)
// Test axis a00
vec3 a00 = vec3(0.0, -f0.z, f0.y);
float p0 = dot(v0, a00);
float p1 = dot(v1, a00);
float p2 = dot(v2, a00);
vec3 halfSize = boxHalfSize;
float r = halfSize.y * abs(f0.z) + halfSize.z * abs(f0.y);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a01
vec3 a01 = vec3(0.0, -f1.z, f1.y);
p0 = dot(v0, a01);
p1 = dot(v1, a01);
p2 = dot(v2, a01);
r = halfSize.y * abs(f1.z) + halfSize.z * abs(f1.y);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a02
vec3 a02 = vec3(0, -f2.z, f2.y);
p0 = dot(v0, a02);
p1 = dot(v1, a02);
p2 = dot(v2, a02);
r = halfSize.y * abs(f2.z) + halfSize.z * abs(f2.y);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a10
vec3 a10 = vec3(f0.z, 0, -f0.x);
p0 = dot(v0, a10);
p1 = dot(v1, a10);
p2 = dot(v2, a10);
r = halfSize.x * abs(f0.z) + halfSize.z * abs(f0.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a11
vec3 a11 = vec3(f1.z, 0.0, -f1.x);
p0 = dot(v0, a11);
p1 = dot(v1, a11);
p2 = dot(v2, a11);
r = halfSize.x * abs(f1.z) + halfSize.z * abs(f1.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a12
vec3 a12 = vec3(f2.z, 0.0, -f2.x);
p0 = dot(v0, a12);
p1 = dot(v1, a12);
p2 = dot(v2, a12);
r = halfSize.x * abs(f2.z) + halfSize.z * abs(f2.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a20
vec3 a20 = vec3(-f0.y, f0.x, 0.0);
p0 = dot(v0, a20);
p1 = dot(v1, a20);
p2 = dot(v2, a20);
r = halfSize.x * abs(f0.y) + halfSize.y * abs(f0.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a21
vec3 a21 = vec3(-f1.y, f1.x, 0.0);
p0 = dot(v0, a21);
p1 = dot(v1, a21);
p2 = dot(v2, a21);
r = halfSize.x * abs(f1.y) + halfSize.y * abs(f1.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
// Test axis a22
vec3 a22 = vec3(-f2.y, f2.x, 0.0);
p0 = dot(v0, a22);
p1 = dot(v1, a22);
p2 = dot(v2, a22);
r = halfSize.x * abs(f2.y) + halfSize.y * abs(f2.x);
if (max(-Max3(p0, p1, p2), Min3(p0, p1, p2)) > r)
{
return false;
}
/// Region: Test the three axes corresponding to the face normals of Box b (category 1)
// Exit if...
// ... [-extents.x, extents.x] and [min(v0.x,v1.x,v2.x), max(v0.x,v1.x,v2.x)] do not overlap
if (Max3(v0.x, v1.x, v2.x) < -halfSize.x || Min3(v0.x, v1.x, v2.x) > halfSize.x)
{
return false;
}
// ... [-extents.y, extents.y] and [min(v0.y,v1.y,v2.y), max(v0.y,v1.y,v2.y)] do not overlap
if (Max3(v0.y, v1.y, v2.y) < -halfSize.y || Min3(v0.y, v1.y, v2.y) > halfSize.y)
{
return false;
}
// ... [-extents.z, extents.z] and [min(v0.z,v1.z,v2.z), max(v0.z,v1.z,v2.z)] do not overlap
if (Max3(v0.z, v1.z, v2.z) < -halfSize.z || Min3(v0.z, v1.z, v2.z) > halfSize.z)
{
return false;
}
/// Region: Test separating axis corresponding to triangle face normal (category 2)
vec3 planeNormal = cross(f0, f1);
float planeDistance = dot(planeNormal, v0);
// Compute the projection interval radius of b onto L(t) = b.c + t * p.n
r = halfSize.x * abs(planeNormal.x) + halfSize.y * abs(planeNormal.y) + halfSize.z * abs(planeNormal.z);
// Intersection occurs when plane distance falls within [-r,+r] interval
if (planeDistance > r)
{
return false;
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment