Last active
October 27, 2023 03:00
-
-
Save BoyBaykiller/b2ee57415d0e10ce85c70fbfaa99c604 to your computer and use it in GitHub Desktop.
Box vs Triangle Intersection test GLSL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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