Created
May 12, 2024 16:06
-
-
Save jakubtomsu/995ddb0fe6343f08cdb452b5a2a4635e to your computer and use it in GitHub Desktop.
This file contains 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
Renderer_Frustum :: struct { | |
planes: [6]Vec4, | |
} | |
renderer_frustum_from_projection_mat4 :: proc(m: Mat4) -> (result: Renderer_Frustum) { | |
// https://iquilezles.org/articles/frustum/ | |
result.planes = { | |
{m[0, 3] - m[0, 0], m[1, 3] - m[1, 0], m[2, 3] - m[2, 0], m[3, 3] - m[3, 0]}, | |
{m[0, 3] + m[0, 0], m[1, 3] + m[1, 0], m[2, 3] + m[2, 0], m[3, 3] + m[3, 0]}, | |
{m[0, 3] + m[0, 1], m[1, 3] + m[1, 1], m[2, 3] + m[2, 1], m[3, 3] + m[3, 1]}, | |
{m[0, 3] - m[0, 1], m[1, 3] - m[1, 1], m[2, 3] - m[2, 1], m[3, 3] - m[3, 1]}, | |
{m[0, 3] - m[0, 2], m[1, 3] - m[1, 2], m[2, 3] - m[2, 2], m[3, 3] - m[3, 2]}, | |
{m[0, 3] + m[0, 2], m[1, 3] + m[1, 2], m[2, 3] + m[2, 2], m[3, 3] + m[3, 2]}, | |
} | |
for &p in result.planes { | |
p /= length(p.xyz) | |
} | |
return | |
} | |
// NOTE: doesn't work perfectly with large objects | |
// false if fully outside, true if inside or intersects | |
renderer_aabb_in_frustum :: proc(aabb: Aabb, planes: [6]Vec4) -> bool { | |
// https://iquilezles.org/articles/frustumcorrect/ | |
// check box outside/inside of frustum | |
for p in planes { | |
out := 0 | |
out += int(dot(p, Vec4{aabb.min.x, aabb.min.y, aabb.min.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.max.x, aabb.min.y, aabb.min.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.min.x, aabb.max.y, aabb.min.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.max.x, aabb.max.y, aabb.min.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.min.x, aabb.min.y, aabb.max.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.max.x, aabb.min.y, aabb.max.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.min.x, aabb.max.y, aabb.max.z, 1.0}) < 0.0) | |
out += int(dot(p, Vec4{aabb.max.x, aabb.max.y, aabb.max.z, 1.0}) < 0.0) | |
if out == 8 { | |
return false | |
} | |
} | |
return true | |
} | |
// More precise, handles large objects. | |
renderer_aabb_in_frustum_precise :: proc(aabb: Aabb, planes: [6]Vec4, corners: [5]Vec3) -> bool { | |
if !renderer_aabb_in_frustum(aabb, planes) do return false | |
// check frustum outside/inside box | |
out := 0 | |
out = 0;for c in corners do out += int(c.x > aabb.max.x);if out == 5 do return false | |
out = 0;for c in corners do out += int(c.x < aabb.min.x);if out == 5 do return false | |
out = 0;for c in corners do out += int(c.y > aabb.max.y);if out == 5 do return false | |
out = 0;for c in corners do out += int(c.y < aabb.min.y);if out == 5 do return false | |
out = 0;for c in corners do out += int(c.z > aabb.max.z);if out == 5 do return false | |
out = 0;for c in corners do out += int(c.z < aabb.min.z);if out == 5 do return false | |
return true | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment