116 lines
2.8 KiB
Odin
116 lines
2.8 KiB
Odin
package bvh
|
|
|
|
import "base:runtime"
|
|
import "core:container/queue"
|
|
import "core:fmt"
|
|
import "core:log"
|
|
import lg "core:math/linalg"
|
|
import rl "vendor:raylib"
|
|
import "vendor:raylib/rlgl"
|
|
|
|
_ :: fmt
|
|
_ :: log
|
|
|
|
// Assuming rl.BeginMode3D was called before this
|
|
debug_draw_bvh_bounds :: proc(bvh: ^BVH, mesh: Mesh, pos: rl.Vector3, node_index: int) {
|
|
old_width := rlgl.GetLineWidth()
|
|
rlgl.SetLineWidth(4)
|
|
defer rlgl.SetLineWidth(old_width)
|
|
|
|
temp := runtime.default_temp_allocator_temp_begin()
|
|
defer runtime.default_temp_allocator_temp_end(temp)
|
|
|
|
Traversal :: struct {
|
|
node_idx: i32,
|
|
should_draw: bool,
|
|
}
|
|
nodes_to_process: queue.Queue(Traversal)
|
|
queue.init(&nodes_to_process, queue.DEFAULT_CAPACITY, context.temp_allocator)
|
|
|
|
queue.push_back(&nodes_to_process, Traversal{0, node_index == 0})
|
|
|
|
for queue.len(nodes_to_process) > 0 {
|
|
traversal := queue.pop_front(&nodes_to_process)
|
|
|
|
node_idx := traversal.node_idx
|
|
should_draw := traversal.should_draw || node_index == int(node_idx)
|
|
|
|
node := &bvh.nodes[node_idx]
|
|
|
|
if should_draw {
|
|
rl.DrawBoundingBox(
|
|
rl.BoundingBox{node.aabb.min + pos, node.aabb.max + pos},
|
|
debug_int_to_color(node_idx + 1),
|
|
)
|
|
}
|
|
|
|
if !is_leaf_node(node^) {
|
|
left_child := node.child_or_prim_start
|
|
queue.push_back_elems(
|
|
&nodes_to_process,
|
|
Traversal{left_child, should_draw},
|
|
Traversal{left_child + 1, should_draw},
|
|
)
|
|
} else if should_draw {
|
|
for i in node.child_or_prim_start ..< node.child_or_prim_start + node.prim_len {
|
|
tri := bvh.primitives[i]
|
|
i1, i2, i3 :=
|
|
mesh.indices[tri * 3], mesh.indices[tri * 3 + 1], mesh.indices[tri * 3 + 2]
|
|
v1, v2, v3 := mesh.vertices[i1], mesh.vertices[i2], mesh.vertices[i3]
|
|
|
|
centroid := (v1 + v2 + v3) * 0.33333333
|
|
|
|
aabb: AABB
|
|
aabb.min = Vec3 {
|
|
min(v1.x, v2.x, v3.x),
|
|
min(v1.y, v2.y, v3.y),
|
|
min(v1.z, v2.z, v3.z),
|
|
}
|
|
aabb.max = Vec3 {
|
|
max(v1.x, v2.x, v3.x),
|
|
max(v1.y, v2.y, v3.y),
|
|
max(v1.z, v2.z, v3.z),
|
|
}
|
|
|
|
size := lg.length(aabb.max - aabb.min)
|
|
rl.DrawTriangle3D(v1, v2, v3, debug_int_to_color(i32(tri) + 1))
|
|
rl.DrawBoundingBox(
|
|
rl.BoundingBox{aabb.min, aabb.max},
|
|
debug_int_to_color(i32(tri) + 2),
|
|
)
|
|
|
|
if size < 1 {
|
|
rl.DrawCubeWiresV(centroid, 0.05, debug_int_to_color(i32(tri) + 3))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
debug_int_to_color :: proc(num: i32) -> (color: rl.Color) {
|
|
x := debug_hash(num)
|
|
|
|
color.r = u8(x % 256)
|
|
color.g = u8((x / 256) % 256)
|
|
color.b = u8((x / 256 / 256) % 256)
|
|
color.a = 255
|
|
return
|
|
}
|
|
|
|
debug_hash :: proc(num: i32) -> u32 {
|
|
x := cast(u32)num
|
|
|
|
x = ((x >> 16) ~ x) * 0x45d9f3b
|
|
x = ((x >> 16) ~ x) * 0x45d9f3b
|
|
x = (x >> 16) ~ x
|
|
|
|
return x
|
|
}
|
|
|
|
bvh_mesh_from_rl_mesh :: proc(mesh: rl.Mesh) -> Mesh {
|
|
return Mesh {
|
|
vertices = (cast([^]Vec3)mesh.vertices)[:mesh.vertexCount],
|
|
indices = mesh.indices[:mesh.triangleCount * 3],
|
|
}
|
|
}
|