this repo has no description
1const std = @import("std");
2
3const zm = @import("zmath");
4
5const AABB = @import("AABB.zig");
6const IntervalF32 = @import("interval.zig").IntervalF32;
7const Material = @import("material.zig").Material;
8const Ray = @import("Ray.zig");
9
10// Hittable Objects
11pub const Sphere = @import("hittable/Sphere.zig");
12
13pub const HitRecord = struct {
14 p: zm.Vec,
15 normal: zm.Vec = zm.f32x4s(1.0),
16 mat: *Material,
17 t: f32,
18 u: f32 = 0,
19 v: f32 = 0,
20 front_face: bool = true,
21
22 pub fn setFaceNormal(self: *HitRecord, r: *Ray, outward_normal: zm.Vec) void {
23 self.front_face = zm.dot3(r.dir, outward_normal)[0] < 0.0;
24 self.normal = if (self.front_face) outward_normal else -outward_normal;
25 }
26};
27
28pub const Hittable = union(enum) {
29 sphere: Sphere,
30
31 pub fn initSphere(s: Sphere) Hittable {
32 return .{ .sphere = s };
33 }
34
35 pub fn boundingBox(self: *Hittable) AABB {
36 switch (self.*) {
37 inline else => |*n| return n.bbox,
38 }
39 }
40
41 pub fn hit(self: *const Hittable, r: *Ray, ray_t: IntervalF32) ?HitRecord {
42 switch (self.*) {
43 inline else => |*n| return n.hit(r, ray_t),
44 }
45 }
46};
47
48pub const HittableList = struct {
49 list: std.ArrayList(Hittable),
50 bbox: AABB = AABB{},
51
52 pub fn init(allocator: std.mem.Allocator) HittableList {
53 const list = std.ArrayList(Hittable).init(allocator);
54
55 return .{ .list = list };
56 }
57
58 pub fn initH(allocator: std.mem.Allocator, item: Hittable) !HittableList {
59 var list = std.ArrayList(Hittable).init(allocator);
60 try list.append(item);
61 return .{ .list = list, .bbox = AABB.initAB(&AABB{}, &(@constCast(&item).boundingBox())) };
62 }
63
64 pub fn deinit(self: *HittableList) void {
65 self.list.deinit();
66 }
67
68 pub fn add(self: *HittableList, item: Hittable) !void {
69 try self.list.append(item);
70 self.bbox = AABB.initAB(&self.bbox, &(@constCast(&item).boundingBox()));
71 }
72
73 pub fn boundingBox(self: *HittableList) AABB {
74 return self.bbox;
75 }
76
77 pub fn hit(self: *HittableList, r: *Ray, ray_t: IntervalF32) ?HitRecord {
78 var rec: ?HitRecord = null;
79 var hit_anything = false;
80 var closest_so_far = ray_t.max;
81
82 for (self.list.items) |*object| {
83 if (object.hit(r, IntervalF32.init(ray_t.min, closest_so_far))) |new_rec| {
84 rec = new_rec;
85 hit_anything = true;
86 closest_so_far = new_rec.t;
87 }
88 }
89
90 return rec;
91 }
92};