working bvh raytrace of the unity model
This commit is contained in:
parent
d68f740c10
commit
d875d1130b
12582
assets/unity.tri
Normal file
12582
assets/unity.tri
Normal file
File diff suppressed because it is too large
Load Diff
112
src/main.odin
112
src/main.odin
@ -2,11 +2,12 @@ package main
|
|||||||
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
import "core:math"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
WINDOW_WIDTH :: 1280
|
WINDOW_WIDTH :: 1280
|
||||||
WINDOW_HEIGHT :: 720
|
WINDOW_HEIGHT : i32
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -16,24 +17,38 @@ rl_window_loop :: proc() {
|
|||||||
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Rayt");
|
rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Rayt");
|
||||||
defer rl.CloseWindow()
|
defer rl.CloseWindow()
|
||||||
|
|
||||||
|
do_debug_elements := false
|
||||||
|
do_debug_model := false
|
||||||
|
|
||||||
rl_image := rl.Image {
|
rl_image := rl.Image {
|
||||||
data = raw_data(pixelbuffer_rgb),
|
data = raw_data(pixelbuffer_rgb),
|
||||||
width = cast(i32)image.width,
|
width = cast(i32)image.width,
|
||||||
height = cast(i32)image.height,
|
height = cast(i32)image.height,
|
||||||
mipmaps = 1,
|
mipmaps = 1,
|
||||||
format = .UNCOMPRESSED_R8G8B8
|
format = .UNCOMPRESSED_R8G8B8
|
||||||
}
|
}
|
||||||
defer rl.UnloadImage(rl_image)
|
defer rl.UnloadImage(rl_image)
|
||||||
fmt.println("Created raylib image from rgb data")
|
fmt.println("Created raylib image from rgb data")
|
||||||
|
|
||||||
|
|
||||||
texture := rl.LoadTextureFromImage(rl_image)
|
|
||||||
defer rl.UnloadTexture(texture)
|
texture := rl.LoadTextureFromImage(rl_image)
|
||||||
fmt.println("Loaded texture from image")
|
defer rl.UnloadTexture(texture)
|
||||||
//rl_window_loop(texture)
|
fmt.println("Loaded texture from image")
|
||||||
|
|
||||||
|
|
||||||
|
rl_camera := rl.Camera3D {
|
||||||
|
position = {-2.0, 0.0, 6.0},
|
||||||
|
target = {0.0, 0.0, 0.0},
|
||||||
|
up = {0.0, 1.0, 0.0},
|
||||||
|
fovy = 45,
|
||||||
|
projection = .PERSPECTIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh : rl.Mesh
|
||||||
|
model : rl.Model
|
||||||
|
if do_debug_model {
|
||||||
|
mesh = create_mesh_from_triangles()
|
||||||
|
model = rl.LoadModelFromMesh(mesh)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
for !rl.WindowShouldClose() {
|
||||||
@ -42,20 +57,33 @@ rl_window_loop :: proc() {
|
|||||||
rl.BeginDrawing()
|
rl.BeginDrawing()
|
||||||
rl.ClearBackground(rl.BLUE)
|
rl.ClearBackground(rl.BLUE)
|
||||||
|
|
||||||
|
// Display raytraced image
|
||||||
rl.DrawTexture(texture, 0, 0, rl.WHITE)
|
rl.DrawTexture(texture, 0, 0, rl.WHITE)
|
||||||
|
|
||||||
rl.DrawCircle(400, 300, 50, rl.GREEN)
|
// Debug draw model
|
||||||
rl.DrawLine(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, rl.BLUE)
|
if do_debug_model {
|
||||||
|
rl.BeginMode3D(rl_camera)
|
||||||
|
rl.DrawModel(model, {0.0, 0.0, 0.0}, 1, rl.RED)
|
||||||
|
rl.DrawGrid(10, 1.0)
|
||||||
|
rl.EndMode3D()
|
||||||
|
}
|
||||||
|
|
||||||
|
if do_debug_elements {
|
||||||
|
rl.DrawCircle(400, 300, 50, rl.GREEN)
|
||||||
|
rl.DrawLine(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, rl.BLUE)
|
||||||
|
|
||||||
|
|
||||||
rl.DrawCircle(100, 100, 120, rl.RED)
|
rl.DrawCircle(100, 100, 120, rl.RED)
|
||||||
|
}
|
||||||
|
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if do_debug_model {
|
||||||
|
rl.UnloadMesh(mesh)
|
||||||
|
rl.UnloadModel(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -63,7 +91,10 @@ rl_window_loop :: proc() {
|
|||||||
main :: proc() {
|
main :: proc() {
|
||||||
rl.SetTraceLogLevel(rl.TraceLogLevel.ERROR)
|
rl.SetTraceLogLevel(rl.TraceLogLevel.ERROR)
|
||||||
|
|
||||||
// Fill pixelbuffer with raytraced image.
|
WINDOW_HEIGHT = cast(i32)math.ceil((cast(f32)WINDOW_WIDTH/1.7778))
|
||||||
|
fmt.printf("Window dimensions %i x %i \n", WINDOW_WIDTH, WINDOW_HEIGHT)
|
||||||
|
|
||||||
|
// Fill pixelbuffer with raytraced image.
|
||||||
|
|
||||||
rayt_cpu_main()
|
rayt_cpu_main()
|
||||||
|
|
||||||
@ -71,3 +102,40 @@ main :: proc() {
|
|||||||
|
|
||||||
rl_window_loop()
|
rl_window_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create_mesh_from_triangles :: proc() -> rl.Mesh {
|
||||||
|
vertex_count := len(tri_indices) * 3
|
||||||
|
vertices := make([]f32, vertex_count * 3)
|
||||||
|
indices := make([]u16, vertex_count)
|
||||||
|
|
||||||
|
for tri, i in entities {
|
||||||
|
base_idx := i * 3
|
||||||
|
// Vertex 0
|
||||||
|
vertices[base_idx * 3 + 0] = tri.v0.x
|
||||||
|
vertices[base_idx * 3 + 1] = tri.v0.y
|
||||||
|
vertices[base_idx * 3 + 2] = tri.v0.z
|
||||||
|
// Vertex 1
|
||||||
|
vertices[base_idx * 3 + 3] = tri.v1.x
|
||||||
|
vertices[base_idx * 3 + 4] = tri.v1.y
|
||||||
|
vertices[base_idx * 3 + 5] = tri.v1.z
|
||||||
|
// Vertex 2
|
||||||
|
vertices[base_idx * 3 + 6] = tri.v2.x
|
||||||
|
vertices[base_idx * 3 + 7] = tri.v2.y
|
||||||
|
vertices[base_idx * 3 + 8] = tri.v2.z
|
||||||
|
// Indices (simple sequential indices since each triangle is independent)
|
||||||
|
indices[base_idx + 0] = cast(u16)(base_idx + 0)
|
||||||
|
indices[base_idx + 1] = cast(u16)(base_idx + 1)
|
||||||
|
indices[base_idx + 2] = cast(u16)(base_idx + 2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh: rl.Mesh
|
||||||
|
mesh.vertexCount = cast(i32)vertex_count
|
||||||
|
mesh.triangleCount = cast(i32)len(tri_indices)
|
||||||
|
mesh.vertices = &vertices[0]
|
||||||
|
mesh.indices = &indices[0]
|
||||||
|
|
||||||
|
rl.UploadMesh(&mesh, false)
|
||||||
|
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "core:os"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:strconv"
|
||||||
import "core:math/rand"
|
import "core:math/rand"
|
||||||
import "core:math/linalg"
|
import "core:math/linalg"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
@ -17,9 +20,8 @@ COLOR_WHITE :: Vec3{1.0, 1.0, 1.0}
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Global program parameters
|
// Global program parameters
|
||||||
IMAGE_WIDTH :: 1280
|
IMAGE_WIDTH :: WINDOW_WIDTH
|
||||||
ASPECT_RATIO :: 1.7778 // 16:9
|
ASPECT_RATIO :: 1.7778 // 16:9
|
||||||
MAX_NUM_ENTITIES :: 64
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Struct defs
|
// Struct defs
|
||||||
@ -56,7 +58,6 @@ HitRecord :: struct {
|
|||||||
point : Vec3,
|
point : Vec3,
|
||||||
normal : Vec3,
|
normal : Vec3,
|
||||||
t : f32,
|
t : f32,
|
||||||
hit : b32,
|
|
||||||
front_face : b32,
|
front_face : b32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,13 +76,14 @@ Entity :: struct {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/// Main global variables
|
/// Main global variables
|
||||||
stopwatch : time.Stopwatch
|
stopwatch : time.Stopwatch
|
||||||
|
use_bvh := true
|
||||||
|
|
||||||
image: Image
|
image: Image
|
||||||
camera: Camera
|
camera: Camera
|
||||||
viewport: Viewport
|
viewport: Viewport
|
||||||
|
|
||||||
entities: [MAX_NUM_ENTITIES]Entity
|
entities: []Entity
|
||||||
tri_indices: [MAX_NUM_ENTITIES]u32
|
tri_indices: []u32
|
||||||
|
|
||||||
|
|
||||||
pixelbuffer: []Vec3
|
pixelbuffer: []Vec3
|
||||||
@ -112,29 +114,31 @@ ray_get :: proc(x : f32, y : f32) -> Ray {
|
|||||||
|
|
||||||
rayt_cpu_main :: proc() {
|
rayt_cpu_main :: proc() {
|
||||||
rand.reset(RAND_SEED)
|
rand.reset(RAND_SEED)
|
||||||
|
|
||||||
|
load_triangles()
|
||||||
|
|
||||||
// Random triangles
|
// Random triangles
|
||||||
{
|
//{
|
||||||
center_shift := Vec3{5.0, 5.0, 5.0}
|
// center_shift := Vec3{5.0, 5.0, 5.0}
|
||||||
// Generate triangles inside a box
|
// // Generate triangles inside a box
|
||||||
for i in 0..<MAX_NUM_ENTITIES {
|
// for i in 0..<MAX_NUM_ENTITIES {
|
||||||
r0 := vec3_rand_uniform();
|
// r0 := vec3_rand_uniform();
|
||||||
r1 := vec3_rand_uniform();
|
// r1 := vec3_rand_uniform();
|
||||||
r2 := vec3_rand_uniform();
|
// r2 := vec3_rand_uniform();
|
||||||
|
//
|
||||||
// Put the first vertex within a 10x10x10 cube centered at the origin
|
// // Put the first vertex within a 10x10x10 cube centered at the origin
|
||||||
v0 := 9.0*r0
|
// v0 := 9.0*r0
|
||||||
v0 = v0 - center_shift
|
// v0 = v0 - center_shift
|
||||||
|
//
|
||||||
entities[i].kind = EntityKind.Tri
|
// entities[i].kind = EntityKind.Tri
|
||||||
entities[i].v0 = v0
|
// entities[i].v0 = v0
|
||||||
entities[i].v1 = v0 + r1
|
// entities[i].v1 = v0 + r1
|
||||||
entities[i].v2 = v0 + r2
|
// entities[i].v2 = v0 + r2
|
||||||
entities[i].center = 0.3333*(entities[i].v0 + entities[i].v1 + entities[i].v2)
|
// entities[i].center = 0.3333*(entities[i].v0 + entities[i].v1 + entities[i].v2)
|
||||||
tri_indices[i] = cast(u32)i
|
// tri_indices[i] = cast(u32)i
|
||||||
//fmt.printf("Triangle idx %i \n", tri_indices[i])
|
// //fmt.printf("Triangle idx %i \n", tri_indices[i])
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Set up scene globals
|
// Set up scene globals
|
||||||
{
|
{
|
||||||
@ -145,7 +149,7 @@ rayt_cpu_main :: proc() {
|
|||||||
image.width, image.height, image.aspect_ratio)
|
image.width, image.height, image.aspect_ratio)
|
||||||
|
|
||||||
camera.focal_length = 3.0
|
camera.focal_length = 3.0
|
||||||
camera.center = Vec3{0.0, 0.0, 18.0}
|
camera.center = Vec3{-2.0, 0.0, 4.0}
|
||||||
|
|
||||||
viewport.height = 2.0
|
viewport.height = 2.0
|
||||||
viewport.width = viewport.height * cast(f32)(image.width)/cast(f32)(image.height)
|
viewport.width = viewport.height * cast(f32)(image.width)/cast(f32)(image.height)
|
||||||
@ -178,11 +182,11 @@ rayt_cpu_main :: proc() {
|
|||||||
bvh_stats()
|
bvh_stats()
|
||||||
|
|
||||||
fmt.printf("Starting CPU raytracing")
|
fmt.printf("Starting CPU raytracing")
|
||||||
if bvh.num_leaf_nodes > 1 {
|
if !use_bvh {
|
||||||
fmt.printf(" - WITH BVH!")
|
fmt.printf(" - NB NB NB! NO BVH! WITHOUT BVH!")
|
||||||
}
|
}
|
||||||
fmt.printf("\n")
|
fmt.printf("\n")
|
||||||
|
|
||||||
time.stopwatch_start(&stopwatch)
|
time.stopwatch_start(&stopwatch)
|
||||||
cpu_raytracing()
|
cpu_raytracing()
|
||||||
time.stopwatch_stop(&stopwatch)
|
time.stopwatch_stop(&stopwatch)
|
||||||
@ -222,15 +226,15 @@ ray_point :: proc(t : f32, ray : ^Ray) -> Vec3 {
|
|||||||
triangle_intersection :: proc(ray : ^Ray, rec : ^HitRecord, triangle : ^Entity) {
|
triangle_intersection :: proc(ray : ^Ray, rec : ^HitRecord, triangle : ^Entity) {
|
||||||
edge1 := triangle.v1-triangle.v0
|
edge1 := triangle.v1-triangle.v0
|
||||||
edge2 := triangle.v2-triangle.v0
|
edge2 := triangle.v2-triangle.v0
|
||||||
rec.hit = false
|
|
||||||
|
|
||||||
// Moller-Trumbore intersection algorithm
|
// Moller-Trumbore intersection algorithm
|
||||||
|
closest_so_far : f32 = rec.t
|
||||||
{
|
{
|
||||||
h := linalg.cross(ray.direction, edge2)
|
h := linalg.cross(ray.direction, edge2)
|
||||||
closest_so_far : f32 = rec.t
|
closest_so_far : f32 = rec.t
|
||||||
a := linalg.dot(edge1, h)
|
a := linalg.dot(edge1, h)
|
||||||
|
|
||||||
if a <= -0.001 || a >= 0.001 {
|
if a <= -0.0001 || a >= 0.0001 {
|
||||||
f := 1.0/a
|
f := 1.0/a
|
||||||
s := ray.origin-triangle.v0
|
s := ray.origin-triangle.v0
|
||||||
u := f * linalg.dot(s, h)
|
u := f * linalg.dot(s, h)
|
||||||
@ -239,17 +243,17 @@ triangle_intersection :: proc(ray : ^Ray, rec : ^HitRecord, triangle : ^Entity)
|
|||||||
v := f * linalg.dot(ray.direction, q)
|
v := f * linalg.dot(ray.direction, q)
|
||||||
if v >= 0.0 && (u + v) <= 1.0 {
|
if v >= 0.0 && (u + v) <= 1.0 {
|
||||||
t := f * linalg.dot(edge2, q)
|
t := f * linalg.dot(edge2, q)
|
||||||
if t > 0.0001 && t <= closest_so_far {
|
if t > 0.0001 {
|
||||||
rec.hit = true
|
rec.t = math.min(t, rec.t)
|
||||||
rec.t = t
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if rec.hit {
|
if rec.t < closest_so_far {
|
||||||
intersection_point := ray_point(rec.t, ray)
|
intersection_point := ray_point(rec.t, ray)
|
||||||
v0_normal := linalg.cross(edge1, edge2)
|
v0_normal := linalg.cross(edge1, edge2)
|
||||||
v0_normal = linalg.normalize(v0_normal)
|
v0_normal = linalg.normalize(v0_normal)
|
||||||
@ -266,7 +270,7 @@ triangle_intersection :: proc(ray : ^Ray, rec : ^HitRecord, triangle : ^Entity)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpu_raytracing :: proc() {
|
cpu_raytracing :: proc() {
|
||||||
|
do_trace_without_bvh := false
|
||||||
num_hits : u32 = 0
|
num_hits : u32 = 0
|
||||||
last_ray : Ray
|
last_ray : Ray
|
||||||
// Temp fill pixels
|
// Temp fill pixels
|
||||||
@ -281,42 +285,28 @@ cpu_raytracing :: proc() {
|
|||||||
ray := ray_get(cast(f32)x, cast(f32)y)
|
ray := ray_get(cast(f32)x, cast(f32)y)
|
||||||
|
|
||||||
|
|
||||||
hit_rec.hit = false
|
|
||||||
hit_rec.t = math.F32_MAX
|
hit_rec.t = math.F32_MAX
|
||||||
temp_hit_rec : HitRecord
|
|
||||||
temp_hit_rec.hit = false
|
|
||||||
temp_hit_rec.t = hit_rec.t
|
|
||||||
|
|
||||||
{
|
if use_bvh {
|
||||||
bvh_intersect(&ray, &hit_rec, bvh.root_index)
|
bvh_intersect(&ray, &hit_rec, bvh.root_index)
|
||||||
|
} else if do_trace_without_bvh {
|
||||||
|
for i in 0..<len(entities) {
|
||||||
|
tri_ref := &entities[i]
|
||||||
|
triangle_intersection(&ray, &hit_rec, tri_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//{
|
|
||||||
// for i in 0..<MAX_NUM_ENTITIES {
|
|
||||||
// tri_ref := &entities[i]
|
|
||||||
// triangle_intersection(&ray, &temp_hit_rec, tri_ref)
|
|
||||||
// if temp_hit_rec.hit {
|
|
||||||
// hit_rec.hit = true
|
|
||||||
// hit_rec.t = temp_hit_rec.t
|
|
||||||
// hit_rec.normal = temp_hit_rec.normal
|
|
||||||
// num_hits += 1
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
if hit_rec.t < math.F32_MAX {
|
||||||
if hit_rec.hit {
|
|
||||||
// Color triangle
|
// Color triangle
|
||||||
sample_pixel_color = 0.5*(hit_rec.normal + COLOR_WHITE)
|
sample_pixel_color = 0.5*(hit_rec.normal + COLOR_WHITE)
|
||||||
|
//sample_pixel_color = Vec3{0.7, 0.2, 0.2}
|
||||||
} else {
|
} else {
|
||||||
// Background gradient
|
// Background gradient
|
||||||
unit_dir := linalg.normalize(ray.direction)
|
unit_dir := linalg.normalize(ray.direction)
|
||||||
|
|
||||||
blend : f32 = 0.5*(unit_dir.y + 1.0)
|
blend : f32 = 0.5*(unit_dir.y + 1.0)
|
||||||
|
|
||||||
sample_pixel_color = vec3_lerp(blend, COLOR_WHITE, COLOR_LIGHT_BLUE)
|
sample_pixel_color = vec3_lerp(blend, COLOR_WHITE, COLOR_LIGHT_BLUE)
|
||||||
|
//sample_pixel_color = Vec3{0.0, 0.0, 0.0}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +320,81 @@ cpu_raytracing :: proc() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
elapsed_time_ms :: proc() -> f64 {
|
elapsed_time_ms :: proc() -> f64 {
|
||||||
return time.duration_milliseconds(time.stopwatch_duration(stopwatch))
|
return time.duration_milliseconds(time.stopwatch_duration(stopwatch))
|
||||||
|
}
|
||||||
|
|
||||||
|
load_triangles :: proc() {
|
||||||
|
|
||||||
|
do_debug_print := false
|
||||||
|
|
||||||
|
file_path := "W:/rayt/assets/unity.tri"
|
||||||
|
data, ok := os.read_entire_file(file_path)
|
||||||
|
if !ok {
|
||||||
|
fmt.println("Error reading file: ", file_path)
|
||||||
|
os.exit(1);
|
||||||
|
}
|
||||||
|
defer delete(data)
|
||||||
|
|
||||||
|
|
||||||
|
content := string(data)
|
||||||
|
lines := strings.split(content, "\n")
|
||||||
|
num_triangles := len(lines)
|
||||||
|
entities = make([]Entity, num_triangles)
|
||||||
|
tri_indices = make([]u32, num_triangles)
|
||||||
|
|
||||||
|
entity_idx : u32 = 0
|
||||||
|
for line in lines {
|
||||||
|
trimmed := strings.trim_space(line)
|
||||||
|
if len(trimmed) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.split(trimmed, " ")
|
||||||
|
defer delete(fields)
|
||||||
|
|
||||||
|
if len(fields) != 9 {
|
||||||
|
fmt.printf("Warning, line '%s' does not contain 9 values \n", trimmed)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
values: [9]f32
|
||||||
|
valid := true
|
||||||
|
for field, i in fields {
|
||||||
|
if num, ok := strconv.parse_f32(field); ok {
|
||||||
|
values[i] = num
|
||||||
|
} else {
|
||||||
|
fmt.printf("Error: could not prase '%s' as f32 in line '%s' \n", field, trimmed)
|
||||||
|
valid = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
os.exit(1)
|
||||||
|
} else {
|
||||||
|
if do_debug_print {
|
||||||
|
fmt.printf("Creating triangle %i, ", entity_idx)
|
||||||
|
}
|
||||||
|
entities[entity_idx].v0 = Vec3{values[0], values[1], values[2]}
|
||||||
|
entities[entity_idx].v1 = Vec3{values[3], values[4], values[5]}
|
||||||
|
entities[entity_idx].v2 = Vec3{values[6], values[7], values[8]}
|
||||||
|
entities[entity_idx].center = 0.3333*
|
||||||
|
(entities[entity_idx].v0
|
||||||
|
+ entities[entity_idx].v1 + entities[entity_idx].v2)
|
||||||
|
tri_indices[entity_idx] = entity_idx
|
||||||
|
if do_debug_print {
|
||||||
|
fmt.printf("added to tri_indices[%i] = %i", entity_idx, tri_indices[entity_idx])
|
||||||
|
}
|
||||||
|
entity_idx += 1
|
||||||
|
if do_debug_print {
|
||||||
|
fmt.printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.printf("Parsed %i triangles from file %s \n", len(tri_indices), file_path)
|
||||||
|
assert(num_triangles == len(tri_indices))
|
||||||
|
assert(num_triangles == len(entities))
|
||||||
|
assert(num_triangles == int(entity_idx))
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -121,26 +121,22 @@ bvh_subdivide :: proc(node_idx : u32) {
|
|||||||
node.tri_count = 0
|
node.tri_count = 0
|
||||||
|
|
||||||
bvh_update_bounds(left_child_idx)
|
bvh_update_bounds(left_child_idx)
|
||||||
bvh_update_bounds(right_child_idx)
|
|
||||||
|
|
||||||
bvh_subdivide(left_child_idx)
|
bvh_subdivide(left_child_idx)
|
||||||
|
|
||||||
|
bvh_update_bounds(right_child_idx)
|
||||||
bvh_subdivide(right_child_idx)
|
bvh_subdivide(right_child_idx)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bvh_intersect :: proc(ray : ^Ray, rec : ^HitRecord, node_idx : u32) {
|
bvh_intersect :: proc(ray : ^Ray, rec : ^HitRecord, node_idx : u32) {
|
||||||
node : ^BVHNode = &bvh.nodes[node_idx]
|
node : ^BVHNode = &bvh.nodes[node_idx]
|
||||||
|
|
||||||
any_hit : b32 = false
|
|
||||||
if intersect_aabb(ray, node.aabb_min, node.aabb_max, rec.t) {
|
if intersect_aabb(ray, node.aabb_min, node.aabb_max, rec.t) {
|
||||||
if node.tri_count > 0 {
|
if node.tri_count > 0 {
|
||||||
for i in 0..<node.tri_count {
|
for i in 0..<node.tri_count {
|
||||||
tri_idx := tri_indices[node.left_first + i]
|
tri_idx := tri_indices[node.left_first + i]
|
||||||
triangle : ^Entity = &entities[tri_idx]
|
triangle : ^Entity = &entities[tri_idx]
|
||||||
triangle_intersection(ray, rec, triangle)
|
triangle_intersection(ray, rec, triangle)
|
||||||
if rec.hit {
|
|
||||||
any_hit = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bvh_intersect(ray, rec, node.left_first)
|
bvh_intersect(ray, rec, node.left_first)
|
||||||
@ -148,24 +144,20 @@ bvh_intersect :: proc(ray : ^Ray, rec : ^HitRecord, node_idx : u32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rec.hit {
|
|
||||||
rec.hit = any_hit
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bvh_build :: proc() {
|
bvh_build :: proc() {
|
||||||
bvh.max_num_nodes = 2 * MAX_NUM_ENTITIES - 1
|
num_triangles : u32 = cast(u32)len(tri_indices)
|
||||||
|
bvh.max_num_nodes = 2 * num_triangles - 1
|
||||||
bvh.nodes = make([]BVHNode, bvh.max_num_nodes)
|
bvh.nodes = make([]BVHNode, bvh.max_num_nodes)
|
||||||
bvh.used_nodes = 2 // We skip first two nodes, for some reason. TODO comment this, read the tutorial
|
bvh.used_nodes = 2 // We skip first two nodes, for some reason. TODO comment this, read the tutorial
|
||||||
bvh.num_leaf_entities = 8
|
bvh.num_leaf_entities = 2
|
||||||
bvh.root_index = 0
|
bvh.root_index = 0
|
||||||
|
|
||||||
// Init root node
|
// Init root node
|
||||||
root : ^BVHNode = &bvh.nodes[bvh.root_index]
|
root : ^BVHNode = &bvh.nodes[bvh.root_index]
|
||||||
root.left_first = 0
|
root.left_first = 0
|
||||||
root.tri_count = MAX_NUM_ENTITIES
|
root.tri_count = num_triangles
|
||||||
|
|
||||||
bvh_update_bounds(bvh.root_index)
|
bvh_update_bounds(bvh.root_index)
|
||||||
|
|
||||||
@ -175,19 +167,22 @@ bvh_build :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bvh_stats :: proc() {
|
bvh_stats :: proc() {
|
||||||
do_print : b32 = false
|
do_print : b32 = true
|
||||||
num_leaf_nodes : u32 = 0
|
num_leaf_nodes : u32 = 0
|
||||||
|
total_triangles_in_bvh : u32 = 0
|
||||||
for i in 0..<bvh.max_num_nodes {
|
for i in 0..<bvh.max_num_nodes {
|
||||||
node : ^BVHNode = &bvh.nodes[i]
|
node : ^BVHNode = &bvh.nodes[i]
|
||||||
if node.tri_count > 0 {
|
if node.tri_count > 0 {
|
||||||
if do_print {
|
if do_print {
|
||||||
fmt.printf("Node %i is leaf node with %i triangles \n", i, node.tri_count)
|
//fmt.printf("Node %i is leaf node with %i triangles \n", i, node.tri_count)
|
||||||
}
|
}
|
||||||
num_leaf_nodes += 1
|
num_leaf_nodes += 1
|
||||||
|
total_triangles_in_bvh += node.tri_count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if do_print {
|
if do_print {
|
||||||
fmt.printf("Total number of leaf nodes: %i \n", num_leaf_nodes)
|
fmt.printf("Total number of leaf nodes: %i \n", num_leaf_nodes)
|
||||||
|
fmt.printf("Total number of triangles in BVH: %i \n", total_triangles_in_bvh)
|
||||||
}
|
}
|
||||||
bvh.num_leaf_nodes = num_leaf_nodes
|
bvh.num_leaf_nodes = num_leaf_nodes
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user