raytracing/in_one_weekend/src/sphere.zig

48 lines
1.5 KiB
Zig

const math = @import("std").math;
const Point3 = @import("vec3.zig").Point3;
const Vec3 = @import("vec3.zig").Vec3;
const HitRecord = @import("hittable.zig").HitRecord;
const Ray = @import("ray.zig").Ray;
const Material = @import("material.zig").Material;
pub const Sphere = struct {
center: Point3,
radius: f32,
material: Material,
pub fn hit(self: Sphere, ray: Ray, t_min: f32, t_max: f32) ?HitRecord {
const oc = ray.origin.sub(self.center);
const a = ray.direction.length_squared();
const half_b = Vec3.dot(oc, ray.direction);
const c = oc.length_squared() - self.radius * self.radius;
const discriminant = half_b * half_b - a * c;
if (discriminant < 0) {
return null;
}
const sqrtd = math.sqrt(discriminant);
// Find the nearest root that lies in the acceptable range.
var root = (-half_b - sqrtd) / a;
if (root < t_min or t_max < root) {
root = (-half_b + sqrtd) / a;
if (root < t_min or t_max < root) {
return null;
}
}
const rayAtRoot = ray.at(root);
var hitLocal = HitRecord{
.t = root,
.p = rayAtRoot,
.normal = rayAtRoot.sub(self.center).div(self.radius),
.front_face = false,
.material = self.material,
};
const outwardNormal = hitLocal.p.sub(self.center).div(self.radius);
HitRecord.setFaceNormal(&hitLocal, ray, outwardNormal);
return hitLocal;
}
};