(hopefully) finished Box::Clip()
[MicroTrace.git] / Box.cxx
1 #include "Box.hxx"
2 #include "InfinitePlane.hxx"
3
4 Box::Box() : m_min(Infinity, Infinity, Infinity),
5 m_max(-Infinity, -Infinity, -Infinity)
6 {
7 }
8
9 Box::Box(Vec3f min, Vec3f max) : m_min(min), m_max(max)
10 {
11 }
12
13 Box::~Box()
14 {
15 }
16
17 Box::Box(const Box& b)
18 {
19 m_min = b.m_min;
20 m_max = b.m_max;
21 }
22
23 Box&
24 Box::operator=(const Box& b)
25 {
26 m_min = b.m_min;
27 m_max = b.m_max;
28 return *this;
29 }
30
31 void
32 Box::Clear()
33 {
34 }
35
36 void
37 Box::Extend(const Vec3f& a)
38 {
39 // for all three coordinates, move m_max or m_min to the point
40 for(size_t i = 0; i < 3; i++) {
41 if(a[i] > m_max[i]) {
42 m_max[i] = a[i];
43 } else if(a[i] < m_min[i]) {
44 m_min[i] = a[i];
45 } // else: do nothing, coordinate is inside the box
46 }
47 }
48
49 void
50 Box::Extend(const Box& box)
51 {
52 }
53
54 bool
55 Box::Overlaps(const Box& b) const
56 {
57 return false;
58 }
59
60 void
61 Box::Clip(const Ray& ray, float& tnear, float& tfar) const
62 {
63 // Note: equations here are the same as in InfinitePlane::Intersect()
64 // t = ((o-a)*n) / (d*n)
65 // o = ray.origin(), d = ray.direction(),
66 // n = surface normal of plane, a = anchor point of plane
67 Vec3f diff_min = m_min - ray.origin(); // o-a
68 Vec3f diff_max = m_max - ray.origin();
69
70 float cos_theta, temp;
71 float tx_near = -Infinity, tx_far = Infinity,
72 ty_near = -Infinity, ty_far = Infinity,
73 tz_near = -Infinity, tz_far = Infinity;
74
75 // clip along x axis
76 if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0) // if not parallel...
77 tx_near = diff_min.dot(Vec3f(1,0,0)) / cos_theta;
78 if((cos_theta = ray.direction().dot(Vec3f(1,0,0))) != 0)
79 tx_far = diff_max.dot(Vec3f(1,0,0)) / cos_theta;
80
81 // we don't know which is nearer, m_min or m_max, so swap them if neccessary
82 if(tx_near > tx_far) {
83 temp = tx_near;
84 tx_near = tx_far;
85 tx_far = temp;
86 }
87
88 // do the same for y axis
89 if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0)
90 ty_near = diff_min.dot(Vec3f(0,1,0)) / cos_theta;
91 if((cos_theta = ray.direction().dot(Vec3f(0,1,0))) != 0)
92 ty_far = diff_max.dot(Vec3f(0,1,0)) / cos_theta;
93 if(ty_near > ty_far) {
94 temp = ty_near;
95 ty_near = ty_far;
96 ty_far = temp;
97 }
98
99 // ...and for z axis
100 if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0)
101 tz_near = diff_min.dot(Vec3f(0,0,1)) / cos_theta;
102 if((cos_theta = ray.direction().dot(Vec3f(0,0,1))) != 0)
103 tz_far = diff_max.dot(Vec3f(0,0,1)) / cos_theta;
104 if(tz_near > tz_far) {
105 temp = tz_near;
106 tz_near = tz_far;
107 tz_far = temp;
108 }
109
110 // now the maximum of "near"s is the entry point of the ray, the minimum
111 // of "far"s is the ray's exit point. Visually speaking: the ray must cross
112 // all three "near" planes before it can be inside the box.
113 // Note: If t_near_max > t_far_min, the ray does not intersect the box
114 tnear = fmax(fmax(tx_near, ty_near), tz_near);
115 tfar = fmin(fmin(tx_far, ty_far), tz_far);
116 }
117
118 const Vec3f&
119 Box::min() const
120 {
121 return m_min;
122 }
123
124 const Vec3f&
125 Box::max() const
126 {
127 return m_max;
128 }
This page took 0.067245 seconds and 5 git commands to generate.