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
72
use material::Material;
use plane::Plane;
use ray::Ray;
use Traceable;
use cgmath::prelude::*;
extern crate cgmath;
type Float3 = cgmath::Vector3<f64>;
#[derive(Copy, Clone)]
pub struct Rectangle {
pub position: Float3,
pub normal: Float3,
pub left: Float3,
pub up: Float3,
pub width: f64,
pub height: f64,
pub material: Material,
}
impl Rectangle {
pub fn new(
position: Float3,
normal: Float3,
left: Float3,
up: Float3,
width: f64,
height: f64,
material: Material,
) -> Rectangle {
Rectangle {
position: position,
normal: normal,
left: left,
up: up,
width: width,
height: height,
material: material,
}
}
}
impl Traceable for Rectangle {
fn intersect(&self, r: &Ray, result: &mut ::Hit) -> bool {
let rectangle_plane = Plane::new(self.position, self.normal, self.material);
let hit = rectangle_plane.intersect(r, result);
if hit == true {
let p = r.origin + r.direction * result.t;
let v = p - self.position;
let half_width = self.width * 0.5;
let half_height = self.height * 0.5;
if v.dot(self.left).abs() <= half_width && v.dot(self.up).abs() <= half_height {
result.p = p;
result.n = if Float3::dot(self.normal, r.direction) < 0.0 {
self.normal
} else {
self.normal * -1.0
};
result.material = self.material;
return true;
}
}
return false;
}
}