this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

some optimisations

Altagos d41d3da4 c66683fc

+224 -204
+212
src/BVH.zig
··· 1 + const std = @import("std"); 2 + 3 + const AABB = @import("AABB.zig"); 4 + const hittable = @import("hittable.zig"); 5 + const Hittable = hittable.Hittable; 6 + const HitRecord = hittable.HitRecord; 7 + const IntervalF32 = @import("interval.zig").IntervalF32; 8 + const Ray = @import("Ray.zig"); 9 + const util = @import("util.zig"); 10 + 11 + pub const BVH = @This(); 12 + 13 + const Ast = struct { 14 + left: ?*Node = null, 15 + right: ?*Node = null, 16 + bbox: AABB = AABB{}, 17 + 18 + pub fn hit(self: *Ast, r: *Ray, ray_t: IntervalF32) ?HitRecord { 19 + var rec: ?HitRecord = null; 20 + var interval = ray_t; 21 + if (self.left) |left| { 22 + if (left.hit(r, interval)) |res| { 23 + interval = IntervalF32.init(ray_t.min, res.t); 24 + rec = res; 25 + } 26 + } 27 + 28 + if (self.right) |right| { 29 + if (right.hit(r, interval)) |res| { 30 + return res; 31 + } 32 + } 33 + 34 + return rec; 35 + } 36 + }; 37 + 38 + const Leaf = Hittable; 39 + 40 + const Node = union(enum) { 41 + ast: Ast, 42 + leaf: Leaf, 43 + 44 + pub fn init( 45 + self: *Node, 46 + allocator: std.mem.Allocator, 47 + objects: []hittable.Hittable, 48 + ) !void { 49 + if (objects.len == 1) { 50 + self.* = .{ .leaf = objects[0] }; 51 + return; 52 + } 53 + 54 + var ast_bbox = AABB{}; 55 + for (0..objects.len) |idx| { 56 + ast_bbox = AABB.initAB(&ast_bbox, &objects[idx].boundingBox()); 57 + } 58 + 59 + const axis = ast_bbox.longestAxis(); 60 + 61 + var left = try allocator.create(Node); 62 + var right = try allocator.create(Node); 63 + 64 + if (axis == 0) { 65 + std.mem.sort(Hittable, objects, .{}, boxXCompare); 66 + } else if (axis == 1) { 67 + std.mem.sort(Hittable, objects, .{}, boxYCompare); 68 + } else { 69 + std.mem.sort(Hittable, objects, .{}, boxZCompare); 70 + } 71 + 72 + const mid = objects.len / 2; 73 + try left.init(allocator, objects[0..mid]); 74 + try right.init(allocator, objects[mid..]); 75 + 76 + self.* = .{ .ast = .{ 77 + .left = left, 78 + .right = right, 79 + .bbox = ast_bbox, 80 + } }; 81 + } 82 + 83 + pub fn deinit(self: *Node, allocator: std.mem.Allocator) void { 84 + switch (self.*) { 85 + .ast => |*a| { 86 + if (a.left) |left| { 87 + left.deinit(allocator); 88 + allocator.destroy(left); 89 + } 90 + if (a.right) |right| { 91 + right.deinit(allocator); 92 + allocator.destroy(right); 93 + } 94 + }, 95 + else => {}, 96 + } 97 + } 98 + 99 + pub inline fn bbox(self: *Node) AABB { 100 + switch (self.*) { 101 + .ast => |*a| return a.bbox, 102 + .leaf => |l| return @constCast(&l).boundingBox(), 103 + } 104 + } 105 + 106 + pub inline fn hit(self: *Node, r: *Ray, ray_t: IntervalF32) ?HitRecord { 107 + if (!@constCast(&self.bbox()).hit(r, ray_t)) { 108 + return null; 109 + } 110 + 111 + switch (self.*) { 112 + .ast => |*a| return a.hit(r, ray_t), 113 + .leaf => |*l| return l.hit(r, ray_t), 114 + } 115 + } 116 + 117 + fn recomputeBbox(self: *Node) AABB { 118 + switch (self.*) { 119 + .leaf => |*l| return l.boundingBox(), 120 + .ast => |*a| { 121 + var left = AABB{}; 122 + var right = AABB{}; 123 + 124 + if (a.left) |l| left = l.recomputeBbox(); 125 + if (a.right) |r| right = r.recomputeBbox(); 126 + 127 + a.bbox = AABB.initAB(&left, &right); 128 + return a.bbox; 129 + }, 130 + } 131 + } 132 + 133 + pub fn print(self: *Node, depth: usize, side: u8) void { 134 + for (0..depth) |_| std.debug.print(" ", .{}); 135 + 136 + switch (self.*) { 137 + .ast => |*a| { 138 + if (side == 1) { 139 + std.debug.print("Left = ", .{}); 140 + } else if (side >= 2) { 141 + std.debug.print("Right = ", .{}); 142 + } 143 + 144 + std.debug.print("Ast\n", .{}); 145 + 146 + if (a.left) |left| left.print(depth + 1, 1); 147 + if (a.right) |right| right.print(depth + 1, 2); 148 + }, 149 + .leaf => |*l| std.debug.print("Leaf = {s}\n", .{l.getName()}), 150 + } 151 + } 152 + 153 + fn combineBbox(self: *Node) void { 154 + var left = AABB{}; 155 + var right = AABB{}; 156 + 157 + if (self.left) |l| left = l.bbox; 158 + if (self.right) |r| right = r.bbox; 159 + 160 + self.bbox = AABB.initAB(&left, &right); 161 + } 162 + }; 163 + 164 + allocator: std.mem.Allocator, 165 + root: *Node, 166 + bbox: AABB, 167 + 168 + pub fn init(allocator: std.mem.Allocator, objects: hittable.HittableList) !BVH { 169 + defer @constCast(&objects).deinit(); 170 + std.log.info("Creating BVH Tree with {} objects", .{objects.list.items.len}); 171 + 172 + const root = try allocator.create(Node); 173 + try root.init(allocator, objects.list.items); 174 + const bbox = root.recomputeBbox(); 175 + 176 + // root.print(0, 0); 177 + return .{ 178 + .allocator = allocator, 179 + .root = root, 180 + .bbox = bbox, 181 + }; 182 + } 183 + 184 + pub fn deinit(self: *BVH) void { 185 + self.root.deinit(self.allocator); 186 + } 187 + 188 + pub inline fn hit(self: *BVH, r: *Ray, ray_t: IntervalF32) ?HitRecord { 189 + if (!self.bbox.hit(r, ray_t)) { 190 + return null; 191 + } 192 + 193 + return self.root.hit(r, ray_t); 194 + } 195 + 196 + inline fn boxCompare(a: *Hittable, b: *Hittable, axis_index: i32) bool { 197 + const a_axis_interval = a.boundingBox().axisInterval(axis_index); 198 + const b_axis_interval = b.boundingBox().axisInterval(axis_index); 199 + return a_axis_interval.min <= b_axis_interval.min; 200 + } 201 + 202 + fn boxXCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 203 + return boxCompare(@constCast(&a), @constCast(&b), 0); 204 + } 205 + 206 + fn boxYCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 207 + return boxCompare(@constCast(&a), @constCast(&b), 1); 208 + } 209 + 210 + fn boxZCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 211 + return boxCompare(@constCast(&a), @constCast(&b), 2); 212 + }
+3 -4
src/hittable.zig
··· 9 9 10 10 // Hittable Objects 11 11 pub const Sphere = @import("hittable/Sphere.zig"); 12 - pub const BVH = @import("hittable/BVH.zig"); 13 12 14 13 pub const HitRecord = struct { 15 14 p: zm.Vec, ··· 25 24 }; 26 25 27 26 pub const Hittable = union(enum) { 28 - sphere: struct {Sphere, []const u8}, 27 + sphere: struct { Sphere, []const u8 }, 29 28 30 29 pub fn sphere(name: []const u8, s: Sphere) Hittable { 31 30 // std.log.info("created sphere with mat: {}", .{s.mat}); 32 - return .{ .sphere = .{ s, name }}; 31 + return .{ .sphere = .{ s, name } }; 33 32 } 34 33 35 34 pub fn boundingBox(self: *Hittable) AABB { ··· 44 43 } 45 44 } 46 45 47 - pub fn hit(self: *Hittable, r: *Ray, ray_t: IntervalF32) ?HitRecord { 46 + pub inline fn hit(self: *Hittable, r: *Ray, ray_t: IntervalF32) ?HitRecord { 48 47 switch (self.*) { 49 48 .sphere => |*s| { 50 49 // std.log.debug("try to hit Sphere: {}", .{s});
-194
src/hittable/BVH.zig
··· 1 - const std = @import("std"); 2 - 3 - const AABB = @import("../AABB.zig"); 4 - const hittable = @import("../hittable.zig"); 5 - const Hittable = hittable.Hittable; 6 - const HitRecord = hittable.HitRecord; 7 - const IntervalF32 = @import("../interval.zig").IntervalF32; 8 - const Ray = @import("../Ray.zig"); 9 - const util = @import("../util.zig"); 10 - 11 - pub const BVH = @This(); 12 - 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 - self.bbox = AABB.initAB(&self.bbox, &objects[0].boundingBox()); 38 - // std.log.info("Node.hittable = .{?}", .{self.hittable}); 39 - return; 40 - } 41 - 42 - var left = try allocator.create(Node); 43 - var right = try allocator.create(Node); 44 - 45 - // if (object_span == 2) { 46 - // try left.init(allocator, objects, start, start + 1); 47 - // try right.init(allocator, objects, start + 1, start + 2); 48 - // } else 49 - if (object_span >= 2) { 50 - // std.log.debug("Node.init axis={} start={} end={}", .{ axis, start, end }); 51 - if (axis == 0) { 52 - // break :blk&boxXCompare; 53 - std.mem.sort(Hittable, objects, .{}, boxXCompare); 54 - } else if (axis == 1) { 55 - // break :blk &boxYCompare; 56 - std.mem.sort(Hittable, objects, .{}, boxYCompare); 57 - } else { 58 - // break :blk &boxZCompare; 59 - std.mem.sort(Hittable, objects, .{}, boxZCompare); 60 - } 61 - // std.mem.sort(Hittable, list, null, comparator); 62 - 63 - const mid = object_span / 2; 64 - try left.init(allocator, objects[0..mid]); 65 - try right.init(allocator, objects[mid..]); 66 - } 67 - 68 - self.left = left; 69 - self.right = right; 70 - 71 - self.combineBbox(); 72 - 73 - // std.log.info("Node created", .{}); 74 - } 75 - 76 - pub fn deinit(self: *Node, allocator: std.mem.Allocator) void { 77 - if (self.left) |l| { 78 - l.deinit(allocator); 79 - allocator.destroy(l); 80 - } 81 - if (self.right) |r| { 82 - r.deinit(allocator); 83 - allocator.destroy(r); 84 - } 85 - } 86 - 87 - pub fn hit(self: *Node, r: *Ray, ray_t: IntervalF32) ?HitRecord { 88 - if (!self.bbox.hit(r, ray_t)) { 89 - return null; 90 - } 91 - 92 - if (self.hittable) |object| { 93 - return @constCast(&object).hit(r, ray_t); 94 - } 95 - 96 - var rec: ?HitRecord = null; 97 - if (self.left) |left| { 98 - if (left.hit(r, ray_t)) |res| { 99 - rec = res; 100 - } 101 - } 102 - 103 - if (self.right) |right| { 104 - const interval = blk: { 105 - if (rec) |rec_| { 106 - break :blk IntervalF32.init(ray_t.min, rec_.t); 107 - } 108 - break :blk ray_t; 109 - }; 110 - 111 - if (right.hit(r, interval)) |res| { 112 - rec = res; 113 - } 114 - } 115 - 116 - return rec; 117 - } 118 - 119 - pub fn print(self: *Node, depth: usize, side: u8) void { 120 - for (0..depth) |_| std.debug.print(" ", .{}); 121 - 122 - if (side == 1) { 123 - std.debug.print("Left = ", .{}); 124 - } else if (side >= 2) { 125 - std.debug.print("Right = ", .{}); 126 - } 127 - 128 - const has_hit = if (self.hittable) |h| @constCast(&h).getName() else "Ast"; 129 - std.debug.print("Node hittable={s}\n", .{has_hit}); 130 - 131 - if (self.left) |left| left.print(depth + 1, 1); 132 - if (self.right) |right| right.print(depth + 1, 2); 133 - } 134 - 135 - fn combineBbox(self: *Node) void { 136 - var left = AABB{}; 137 - var right = AABB{}; 138 - 139 - if (self.left) |l| left = l.bbox; 140 - if (self.right) |r| right = r.bbox; 141 - 142 - self.bbox = AABB.initAB(&left, &right); 143 - } 144 - }; 145 - 146 - allocator: std.mem.Allocator, 147 - // objects: hittable.HittableList, 148 - root: Node, 149 - 150 - pub fn init(allocator: std.mem.Allocator, objects: hittable.HittableList) !BVH { 151 - std.log.info("Creating BVH Tree with {} objects", .{objects.list.items.len}); 152 - // return BVH.init(objects, 0, objects.list.items.len); 153 - var root = Node{}; 154 - try root.init(allocator, objects.list.items); 155 - defer @constCast(&objects).deinit(); 156 - 157 - // root.print(0, 0); 158 - 159 - return .{ 160 - .allocator = allocator, 161 - // .objects = objects, 162 - .root = root, 163 - }; 164 - } 165 - 166 - pub fn deinit(self: *BVH) void { 167 - self.root.deinit(self.allocator); 168 - // self.objects.deinit(); 169 - } 170 - 171 - pub fn hit(self: *BVH, r: *Ray, ray_t: IntervalF32) ?HitRecord { 172 - return self.root.hit(r, ray_t); 173 - } 174 - 175 - pub fn boundingBox(self: *BVH) AABB { 176 - return self.root.bbox; 177 - } 178 - 179 - fn boxCompare(a: *Hittable, b: *Hittable, axis_index: i32) bool { 180 - const a_axis_interval = a.boundingBox().axisInterval(axis_index); 181 - const b_axis_interval = b.boundingBox().axisInterval(axis_index); 182 - return a_axis_interval.min > b_axis_interval.min; 183 - } 184 - 185 - fn boxXCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 186 - return boxCompare(@constCast(&a), @constCast(&b), 0); 187 - } 188 - 189 - fn boxYCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 190 - return boxCompare(@constCast(&a), @constCast(&b), 1); 191 - } 192 - fn boxZCompare(_: @TypeOf(.{}), a: Hittable, b: Hittable) bool { 193 - return boxCompare(@constCast(&a), @constCast(&b), 2); 194 - }
+1 -1
src/hittable/sphere.zig
··· 15 15 center_vec: zm.Vec = zm.f32x4s(0), 16 16 bbox: ?AABB = null, 17 17 18 - pub fn initMoving(center1: zm.Vec, center2: zm.Vec, radius: f32, mat: Material) Sphere { 18 + pub fn initMoving(center1: zm.Vec, center2: zm.Vec, radius: f32, mat: *Material) Sphere { 19 19 const rvec = zm.f32x4s(radius); 20 20 const box1 = AABB.initP(center1 - rvec, center1 + rvec); 21 21 const box2 = AABB.initP(center2 - rvec, center2 + rvec);
+3 -2
src/rayray.zig
··· 4 4 const zigimg = @import("zigimg"); 5 5 const color = zigimg.color; 6 6 7 + pub const BVH = @import("BVH.zig"); 7 8 pub const Camera = @import("Camera.zig"); 8 9 pub const hittable = @import("hittable.zig"); 9 10 const IntervalUsize = @import("interval.zig").IntervalUsize; ··· 25 26 thread_pool: *std.Thread.Pool, 26 27 27 28 camera: Camera, 28 - world: hittable.BVH, 29 + world: BVH, 29 30 30 31 pub fn init(allocator: std.mem.Allocator, world: hittable.HittableList, camera_opts: Camera.Options) !Self { 31 32 var thread_pool = try allocator.create(std.Thread.Pool); ··· 35 36 .allocator = allocator, 36 37 .thread_pool = thread_pool, 37 38 .camera = try Camera.init(allocator, camera_opts), 38 - .world = try hittable.BVH.init(allocator, world), 39 + .world = try BVH.init(allocator, world), 39 40 }; 40 41 } 41 42
+2 -1
src/scences/in_one_weekend.zig
··· 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("Lambertian", Sphere{ .center = center, .radius = 0.2, .mat = material })); 41 + const center2 = center + zm.f32x4(0, rayray.util.randomF32M(0, 0.5), 0, 0); 42 + try world.add(Hittable.sphere("Lambertian", Sphere.initMoving(center, center2, 0.2, material))); 42 43 } else if (choose_mat < 0.95) { 43 44 // metal 44 45 const albedo = rayray.util.randomVec3M(0.5, 1) + zm.f32x4(0, 0, 0, 1);
+3 -2
src/tracer.zig
··· 4 4 const zigimg = @import("zigimg"); 5 5 const zm = @import("zmath"); 6 6 7 + const BVH = @import("BVH.zig"); 7 8 const Camera = @import("Camera.zig"); 8 9 const hittable = @import("hittable.zig"); 9 10 const material = @import("material.zig"); ··· 18 19 19 20 pub const Context = struct { 20 21 cam: *Camera, 21 - world: *hittable.BVH, 22 + world: *BVH, 22 23 height: IntervalUsize, 23 24 width: IntervalUsize, 24 25 }; 25 26 26 - pub fn rayColor(r: *Ray, world: *hittable.BVH, depth: usize) zm.Vec { 27 + pub fn rayColor(r: *Ray, world: *BVH, depth: usize) zm.Vec { 27 28 if (depth <= 0) return zm.f32x4(0, 0, 0, 1.0); 28 29 29 30 if (world.hit(r, .{ .min = 0.001, .max = std.math.inf(f32) })) |rec| {