this repo has no description

bvh works but not completly

+149 -88
+2 -2
build.zig.zon
··· 17 17 .hash = "1220753b2f9e7c4f3fb6cdc8fc275cc9073904ea7032a1f5596aa776a857de69f72c", 18 18 }, 19 19 .zigimg = .{ 20 - .url = "git+https://github.com/MidlightStudio/zigimg#29d34702995a7e84e097004e87ede905cdb674dd", 21 - .hash = "12206b669a4712ff9c06d4111a650f298d7597dd39f9d4853858d7f298c819353a65", 20 + .url = "git+https://github.com/MidlightStudio/zigimg#637974e2d31dcdbc33f1e9cc8ffb2e46abd2e215", 21 + .hash = "122012026c3a65ff1d4acba3b3fe80785f7cee9c6b4cdaff7ed0fbf23b0a6c803989", 22 22 }, 23 23 }, 24 24 .paths = .{
+11 -15
src/hittable.zig
··· 25 25 }; 26 26 27 27 pub const Hittable = union(enum) { 28 - sphere: Sphere, 29 - bvh_node: BVH, 28 + sphere: struct {Sphere, []const u8}, 30 29 31 - pub fn sphere(s: Sphere) Hittable { 30 + pub fn sphere(name: []const u8, s: Sphere) Hittable { 32 31 // std.log.info("created sphere with mat: {}", .{s.mat}); 33 - return .{ .sphere = s }; 32 + return .{ .sphere = .{ s, name }}; 34 33 } 35 34 36 - pub fn bvh(b: BVH) Hittable { 37 - return .{ .bvh_node = b }; 35 + pub fn boundingBox(self: *Hittable) AABB { 36 + switch (self.*) { 37 + .sphere => |*s| return s[0].boundingBox(), 38 + } 38 39 } 39 40 40 - pub fn boundingBox(self: *Hittable) AABB { 41 + pub fn getName(self: *Hittable) []const u8 { 41 42 switch (self.*) { 42 - .sphere => |*s| return s.boundingBox(), 43 - .bvh_node => |*s| return s.boundingBox(), 43 + .sphere => |*s| return s[1], 44 44 } 45 45 } 46 46 47 47 pub fn hit(self: *Hittable, r: *Ray, ray_t: IntervalF32) ?HitRecord { 48 48 switch (self.*) { 49 49 .sphere => |*s| { 50 - std.log.debug("try to hit Sphere: {}", .{s}); 50 + // std.log.debug("try to hit Sphere: {}", .{s}); 51 51 // std.log.info("hitting sphere with mat: {}", .{s.mat}); 52 - return s.hit(r, ray_t); 53 - }, 54 - .bvh_node => |*s| { 55 - // std.log.debug("try to hit BVH", .{}); 56 - return s.hit(r, ray_t); 52 + return s[0].hit(r, ray_t); 57 53 }, 58 54 } 59 55
+124 -57
src/hittable/BVH.zig
··· 10 10 11 11 pub const BVH = @This(); 12 12 13 - objects: *hittable.HittableList, 14 - left: *Hittable, 15 - right: *Hittable, 16 - bbox: AABB, 13 + const Node = struct { 14 + left: ?*Node = null, 15 + right: ?*Node = null, 16 + bbox: AABB = AABB{}, 17 + hittable: ?Hittable = null, 18 + 19 + // pub fn add(self: *Node, allocator: std.mem.Allocator, object: *Hittable) void {} 20 + // 21 + pub fn init( 22 + self: *Node, 23 + allocator: std.mem.Allocator, 24 + objects: []hittable.Hittable, 25 + // start: usize, 26 + // end: usize, 27 + ) !void { 28 + for (0..objects.len) |idx| { 29 + self.bbox = AABB.initAB(&self.bbox, &objects[idx].boundingBox()); 30 + } 31 + 32 + const axis = self.bbox.longestAxis(); 33 + const object_span = objects.len; 34 + 35 + if (object_span == 1) { 36 + self.hittable = objects[0]; 37 + // std.log.info("Node.hittable = .{?}", .{self.hittable}); 38 + return; 39 + } 40 + 41 + var left = try allocator.create(Node); 42 + var right = try allocator.create(Node); 43 + 44 + // if (object_span == 2) { 45 + // try left.init(allocator, objects, start, start + 1); 46 + // try right.init(allocator, objects, start + 1, start + 2); 47 + // } else 48 + if (object_span >= 2) { 49 + // std.log.debug("Node.init axis={} start={} end={}", .{ axis, start, end }); 50 + if (axis == 0) { 51 + // break :blk&boxXCompare; 52 + std.mem.sort(Hittable, objects, .{}, boxXCompare); 53 + } else if (axis == 1) { 54 + // break :blk &boxYCompare; 55 + std.mem.sort(Hittable, objects, .{}, boxYCompare); 56 + } else { 57 + // break :blk &boxZCompare; 58 + std.mem.sort(Hittable, objects, .{}, boxZCompare); 59 + } 60 + // std.mem.sort(Hittable, list, null, comparator); 61 + 62 + const mid = object_span / 2; 63 + try left.init(allocator, objects[0..mid]); 64 + try right.init(allocator, objects[mid..]); 65 + } 66 + 67 + self.left = left; 68 + self.right = right; 17 69 18 - pub fn initL(objects: *hittable.HittableList) BVH { 19 - std.log.info("starting to create BVH", .{}); 20 - return BVH.init(objects, 0, objects.list.items.len); 21 - } 70 + // std.log.info("Node created", .{}); 71 + } 22 72 23 - pub fn init(objects: *hittable.HittableList, start: usize, end: usize) BVH { 24 - const list = objects.list.items; 25 - var bbox = AABB{}; 26 - for (start..end) |idx| { 27 - bbox = AABB.initAB(&bbox, &list[idx].boundingBox()); 73 + pub fn deinit(self: *Node, allocator: std.mem.Allocator) void { 74 + if (self.left) |l| { 75 + l.deinit(allocator); 76 + allocator.destroy(l); 77 + } 78 + if (self.right) |r| { 79 + r.deinit(allocator); 80 + allocator.destroy(r); 81 + } 28 82 } 29 83 30 - const axis = bbox.longestAxis(); 84 + pub fn hit(self: *Node, r: *Ray, ray_t: IntervalF32) ?HitRecord { 85 + if (!self.bbox.hit(r, ray_t)) { 86 + return null; 87 + } 88 + 89 + if (self.hittable) |object| { 90 + return @constCast(&object).hit(r, ray_t); 91 + } 92 + 93 + if (self.left) |left| { 94 + if (left.hit(r, ray_t)) |rec| { 95 + return rec; 96 + } 97 + } 31 98 32 - // const comparator = blk: { 33 - // if (axis == 0) { 34 - // break :blk &boxXCompare; 35 - // } else if (axis == 1) { 36 - // break :blk &boxYCompare; 37 - // } 38 - // break :blk &boxZCompare; 39 - // }; 99 + if (self.right) |right| { 100 + if (right.hit(r, ray_t)) |rec| { 101 + return rec; 102 + } 103 + } 104 + 105 + return null; 106 + } 40 107 41 - const object_span = end - start; 108 + pub fn print(self: *Node, depth: usize, side: u8) void { 109 + for (0..depth) |_| std.debug.print(" ", .{}); 42 110 43 - var left = &list[start]; 44 - var right = &list[start]; 45 - if (object_span == 2) { 46 - left = &list[start]; 47 - right = &list[start + 1]; 48 - } else if (object_span > 2) { 49 - std.log.debug("BVH.init axis={} start={} end={}", .{axis, start, end}); 50 - if (axis == 0) { 51 - // break :blk&boxXCompare; 52 - std.mem.sort(Hittable, list, .{}, boxXCompare); 53 - } else if (axis == 1) { 54 - // break :blk &boxYCompare; 55 - std.mem.sort(Hittable, list, .{}, boxYCompare); 56 - } else { 57 - // break :blk &boxZCompare; 58 - std.mem.sort(Hittable, list, .{}, boxZCompare); 111 + if (side == 1) { 112 + std.debug.print("Left = ", .{}); 113 + } else if (side >= 2) { 114 + std.debug.print("Right = ", .{}); 59 115 } 60 - // std.mem.sort(Hittable, list, null, comparator); 61 116 62 - const mid = start + object_span / 2; 63 - left = @constCast(&Hittable.bvh(BVH.init(objects, start, mid))); 64 - right = @constCast(&Hittable.bvh(BVH.init(objects, mid, end))); 117 + const has_hit = if (self.hittable) |h| @constCast(&h).getName() else "Ast"; 118 + std.debug.print("Node hittable={s}\n", .{has_hit}); 119 + 120 + if (self.left) |left| left.print(depth + 1, 1); 121 + if (self.right) |right| right.print(depth + 1, 2); 65 122 } 123 + }; 124 + 125 + allocator: std.mem.Allocator, 126 + // objects: hittable.HittableList, 127 + root: Node, 66 128 67 - std.log.info("BVH created", .{}); 129 + pub fn init(allocator: std.mem.Allocator, objects: hittable.HittableList) !BVH { 130 + std.log.info("Creating BVH Tree with {} objects", .{objects.list.items.len}); 131 + // return BVH.init(objects, 0, objects.list.items.len); 132 + var root = Node{}; 133 + try root.init(allocator, objects.list.items); 134 + defer @constCast(&objects).deinit(); 135 + 136 + root.print(0, 0); 68 137 69 138 return .{ 70 - .objects = objects, 71 - .left = left, 72 - .right = right, 73 - .bbox = bbox, 139 + .allocator = allocator, 140 + // .objects = objects, 141 + .root = root, 74 142 }; 75 143 } 76 144 77 - pub fn hit(self: *BVH, r: *Ray, ray_t: IntervalF32) ?HitRecord { 78 - if (!self.bbox.hit(r, ray_t)) { 79 - return null; 80 - } 145 + pub fn deinit(self: *BVH) void { 146 + self.root.deinit(self.allocator); 147 + // self.objects.deinit(); 148 + } 81 149 82 - if (self.left.hit(r, ray_t)) |rec| return rec; 83 - if (self.right.hit(r, ray_t)) |rec| return rec; 84 - return null; 150 + pub fn hit(self: *BVH, r: *Ray, ray_t: IntervalF32) ?HitRecord { 151 + return self.root.hit(r, ray_t); 85 152 } 86 153 87 154 pub fn boundingBox(self: *BVH) AABB { 88 - return self.bbox; 155 + return self.root.bbox; 89 156 } 90 157 91 158 fn boxCompare(a: *Hittable, b: *Hittable, axis_index: i32) bool { 92 159 const a_axis_interval = a.boundingBox().axisInterval(axis_index); 93 160 const b_axis_interval = b.boundingBox().axisInterval(axis_index); 94 - return a_axis_interval.min < b_axis_interval.min; 161 + return a_axis_interval.min > b_axis_interval.min; 95 162 } 96 163 97 164 fn boxXCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool {
+2 -2
src/rayray.zig
··· 25 25 thread_pool: *std.Thread.Pool, 26 26 27 27 camera: Camera, 28 - world: hittable.HittableList, 28 + world: hittable.BVH, 29 29 30 30 pub fn init(allocator: std.mem.Allocator, world: hittable.HittableList, camera_opts: Camera.Options) !Self { 31 31 var thread_pool = try allocator.create(std.Thread.Pool); ··· 35 35 .allocator = allocator, 36 36 .thread_pool = thread_pool, 37 37 .camera = try Camera.init(allocator, camera_opts), 38 - .world = world, 38 + .world = try hittable.BVH.init(allocator, world), 39 39 }; 40 40 } 41 41
+8 -10
src/scences/in_one_weekend.zig
··· 17 17 18 18 const material_ground = try allocator.create(Material); 19 19 material_ground.* = Material.lambertian(zm.f32x4(0.5, 0.5, 0.5, 1.0)); 20 - try world.add(Hittable.sphere(Sphere{ .center = zm.f32x4(0, -1000, 0, 0), .radius = 1000, .mat = material_ground })); 20 + try world.add(Hittable.sphere("Ground", Sphere{ .center = zm.f32x4(0, -1000, 0, 0), .radius = 1000, .mat = material_ground })); 21 21 22 22 var a: isize = -11; 23 23 while (a < 11) : (a += 1) { ··· 38 38 // diffuse 39 39 const albedo = rayray.util.randomVec3() * rayray.util.randomVec3() + zm.f32x4(0, 0, 0, 1); 40 40 material.* = Material.lambertian(albedo); 41 - try world.add(Hittable.sphere(Sphere{ .center = center, .radius = 0.2, .mat = material })); 41 + try world.add(Hittable.sphere("Lambertian", Sphere{ .center = center, .radius = 0.2, .mat = material })); 42 42 } else if (choose_mat < 0.95) { 43 43 // metal 44 44 const albedo = rayray.util.randomVec3M(0.5, 1) + zm.f32x4(0, 0, 0, 1); 45 45 const fuzz = rayray.util.randomF32M(0, 0.5); 46 46 material.* = Material.metal(albedo, fuzz); 47 - try world.add(Hittable.sphere(Sphere{ .center = center, .radius = 0.2, .mat = material })); 47 + try world.add(Hittable.sphere("Metal", Sphere{ .center = center, .radius = 0.2, .mat = material })); 48 48 } else { 49 49 // glass 50 50 material.* = Material.dielectric(1.5); 51 - try world.add(Hittable.sphere(Sphere{ .center = center, .radius = 0.2, .mat = material })); 51 + try world.add(Hittable.sphere("Dielectric", Sphere{ .center = center, .radius = 0.2, .mat = material })); 52 52 } 53 53 } 54 54 } ··· 56 56 57 57 const material1 = try allocator.create(Material); 58 58 material1.* = Material.dielectric(1.5); 59 - try world.add(Hittable.sphere(Sphere{ .center = zm.f32x4(0, 1, 0, 0), .radius = 1, .mat = material1 })); 59 + try world.add(Hittable.sphere("One", Sphere{ .center = zm.f32x4(0, 1, 0, 0), .radius = 1, .mat = material1 })); 60 60 61 61 const material2 = try allocator.create(Material); 62 62 material2.* = Material.lambertian(zm.f32x4(0.4, 0.2, 0.1, 1)); 63 - try world.add(Hittable.sphere(Sphere{ .center = zm.f32x4(-4, 1, 0, 0), .radius = 1, .mat = material2 })); 63 + try world.add(Hittable.sphere("Two", Sphere{ .center = zm.f32x4(-4, 1, 0, 0), .radius = 1, .mat = material2 })); 64 64 65 65 const material3 = try allocator.create(Material); 66 66 material3.* = Material.metal(zm.f32x4(0.7, 0.6, 0.5, 1), 0); 67 - try world.add(Hittable.sphere(Sphere{ .center = zm.f32x4(4, 1, 0, 0), .radius = 1, .mat = material3 })); 67 + try world.add(Hittable.sphere("Three", Sphere{ .center = zm.f32x4(4, 1, 0, 0), .radius = 1, .mat = material3 })); 68 68 69 - var world2 = HittableList.init(allocator); 70 - try world2.add(Hittable.bvh(BVH.initL(&world))); 71 - return .{ .allocator = allocator, .world = world2 }; 69 + return .{ .allocator = allocator, .world = world }; 72 70 } 73 71 74 72 pub fn deinit(self: *@This()) void {
+2 -2
src/tracer.zig
··· 18 18 19 19 pub const Context = struct { 20 20 cam: *Camera, 21 - world: *hittable.HittableList, 21 + world: *hittable.BVH, 22 22 height: IntervalUsize, 23 23 width: IntervalUsize, 24 24 }; 25 25 26 - pub fn rayColor(r: *Ray, world: *hittable.HittableList, depth: usize) zm.Vec { 26 + pub fn rayColor(r: *Ray, world: *hittable.BVH, depth: usize) zm.Vec { 27 27 if (depth <= 0) return zm.f32x4(0, 0, 0, 1.0); 28 28 29 29 if (world.hit(r, .{ .min = 0.001, .max = std.math.inf(f32) })) |rec| {