Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293const std = @import("std");
const zm = @import("zmath");
const AABB = @import("AABB.zig");const IntervalF32 = @import("interval.zig").IntervalF32;const Material = @import("material.zig").Material;const Ray = @import("Ray.zig");
// Hittable Objectspub const Sphere = @import("hittable/Sphere.zig");
pub const HitRecord = struct { p: zm.Vec, normal: zm.Vec = zm.f32x4s(1.0), mat: *Material, t: f32, u: f32 = 0, v: f32 = 0, front_face: bool = true,
pub fn setFaceNormal(self: *HitRecord, r: *Ray, outward_normal: zm.Vec) void { self.front_face = zm.dot3(r.dir, outward_normal)[0] < 0.0; self.normal = if (self.front_face) outward_normal else -outward_normal; }};
pub const Hittable = union(enum) { sphere: Sphere,
pub fn initSphere(s: Sphere) Hittable { return .{ .sphere = s }; }
pub fn boundingBox(self: *Hittable) AABB { switch (self.*) { inline else => |*n| return n.bbox, } }
pub fn hit(self: *const Hittable, r: *Ray, ray_t: IntervalF32) ?HitRecord { switch (self.*) { inline else => |*n| return n.hit(r, ray_t), } }};
pub const HittableList = struct { list: std.ArrayList(Hittable), bbox: AABB = AABB{},
pub fn init(allocator: std.mem.Allocator) HittableList { const list = std.ArrayList(Hittable).init(allocator);
return .{ .list = list }; }
pub fn initH(allocator: std.mem.Allocator, item: Hittable) !HittableList { var list = std.ArrayList(Hittable).init(allocator); try list.append(item); return .{ .list = list, .bbox = AABB.initAB(&AABB{}, &(@constCast(&item).boundingBox())) }; }
pub fn deinit(self: *HittableList) void { self.list.deinit(); }
pub fn add(self: *HittableList, item: Hittable) !void { try self.list.append(item); self.bbox = AABB.initAB(&self.bbox, &(@constCast(&item).boundingBox())); }
pub fn boundingBox(self: *HittableList) AABB { return self.bbox; }
pub fn hit(self: *HittableList, r: *Ray, ray_t: IntervalF32) ?HitRecord { var rec: ?HitRecord = null; var hit_anything = false; var closest_so_far = ray_t.max;
for (self.list.items) |*object| { if (object.hit(r, IntervalF32.init(ray_t.min, closest_so_far))) |new_rec| { rec = new_rec; hit_anything = true; closest_so_far = new_rec.t; } }
return rec; }};