Skip to content

Instantly share code, notes, and snippets.

@jakubtomsu
Created May 12, 2024 16:06
Show Gist options
  • Save jakubtomsu/995ddb0fe6343f08cdb452b5a2a4635e to your computer and use it in GitHub Desktop.
Save jakubtomsu/995ddb0fe6343f08cdb452b5a2a4635e to your computer and use it in GitHub Desktop.
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