aboutsummaryrefslogtreecommitdiff
path: root/src/hittable/xy_rect.rs
blob: 2d7dbeb410e3342fb59dad4125d2ad5f3282b6f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use std::sync::Arc;

use crate::{
    hittable::{HitRecord, Hittable, AABB},
    material::Material,
    ray::Ray,
    vec3::{Point3, Vec3},
};

pub struct XYRect {
    pub material: Arc<dyn Material>,
    pub x0: f64,
    pub x1: f64,
    pub y0: f64,
    pub y1: f64,
    pub k: f64,
}

impl XYRect {
    fn has_infinite_bounds(&self) -> bool {
        self.x0.is_infinite()
            || self.x1.is_infinite()
            || self.y0.is_infinite()
            || self.y1.is_infinite()
    }
}

impl Hittable for XYRect {
    fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
        let t = (self.k - ray.origin.z) / ray.direction.z;
        if t < t_min || t > t_max {
            return None;
        }
        let x = ray.origin.x + t * ray.direction.x;
        let y = ray.origin.y + t * ray.direction.y;
        if x < self.x0 || x > self.x1 || y < self.y0 || y > self.y1 {
            return None;
        }
        let mut hit_record = HitRecord::new();
        hit_record.u = (x - self.x0) / (self.x1 - self.x0);
        hit_record.v = (y - self.y0) / (self.y1 - self.y0);
        hit_record.t = t;
        let outward_normal = Vec3 {
            x: 0.0,
            y: 0.0,
            z: 1.0,
        };
        hit_record.set_face_normal(ray, &outward_normal);
        hit_record.material = Some(self.material.clone());
        hit_record.p = ray.at(t);
        Some(hit_record)
    }

    fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> {
        match self.has_infinite_bounds() {
            true => None,
            false => Some(AABB {
                minimum: Point3 {
                    x: self.x0,
                    y: self.y0,
                    z: self.k - 0.0001,
                },
                maximum: Point3 {
                    x: self.x1,
                    y: self.y1,
                    z: self.k + 0.0001,
                },
            }),
        }
    }
}