1 #ifndef AABB_HXX
2 #define AABB_HXX
3
4 #include "Primitive.hxx"
5
6 class AABB : public Primitive
7 {
8 Vec3f _center;
9 Vec3f _min;
10 Vec3f _max;
11
12 /**
13 * compute bounding box for an axis aligned box
14 * with the help of min and max vector
15 */
16 Box CalcBounds()
17 {
18 Box bb;
19 bb.Extend(_min);
20 bb.Extend(_max);
21 return bb;
22 }
23
24 public:
25 AABB(Vec3f min, Vec3f max) : _min(min), _max(max)
26 {
27 // compute center of the axis aligned bounding box
28 _center = (_min + _max) * 0.5;
29 };
30
31 ~AABB()
32 {};
33
34 bool Intersect(Ray &ray)
35 {
36 float tmin, tmax, tymin, tymax, tzmin, tzmax;
37
38 // inverse direction to catch float problems
39 Vec3f invrd = 1.0 / ray.dir;
40
41 if (invrd.x() >= 0)
42 {
43 tmin = (_min.x() - ray.org.x()) * invrd.x();
44 tmax = (_max.x() - ray.org.x()) * invrd.x();
45 } else
46 {
47 tmin = (_max.x() - ray.org.x()) * invrd.x();
48 tmax = (_min.x() - ray.org.x()) * invrd.x();
49 }
50
51 if (invrd.y() >= 0)
52 {
53 tymin = (_min.y() - ray.org.y()) * invrd.y();
54 tymax = (_max.y() - ray.org.y()) * invrd.y();
55 } else
56 {
57 tymin = (_max.y() - ray.org.y()) * invrd.y();
58 tymax = (_min.y() - ray.org.y()) * invrd.y();
59 }
60
61 if ( (tmin > tymax) || (tymin > tmax) ) return false;
62 if ( tymin > tmin) tmin = tymin;
63 if ( tymax < tmax) tmax = tymax;
64
65 if (invrd.z() >= 0)
66 {
67 tzmin = (_min.z() - ray.org.z()) * invrd.z();
68 tzmax = (_max.z() - ray.org.z()) * invrd.z();
69 }else
70 {
71 tzmin = (_max.z() - ray.org.z()) * invrd.z();
72 tzmax = (_min.z() - ray.org.z()) * invrd.z();
73 }
74
75 if ( (tmin > tzmax) || (tzmin > tmax) ) return false;
76 if ( tzmin > tmin) tmin = tzmin;
77 if ( tzmax < tmax) tmax = tzmax;
78
79 // check if values are valid
80 if (tmin < 0) tmin = tmax;
81 if (tmax < 0) return false;
82
83 ray.t = tmin;
84 ray.hit = this;
85 return true;
86 };
87
88 /**
89 * compute normal of an axis aligned box
90 * Therefore take the maximum entry of dir (the vector from the center of the box to the hitpoint),
91 * which indicates on which side the box is hit. The normal is then of one of the unit vector.
92 * Important: take the side length into account.
93 */
94 virtual Vec3f GetNormal(Ray &ray)
95 {
96 Vec3f hit = ray.org + ray.t * ray.dir;
97 Vec3f dir = hit - _center;
98
99 Vec3f width = fabs(_max - _min);
100 Vec3f ratio = fabs( Vec3f( dir[0] / width[0],
101 dir[1] / width[1],
102 dir[2] / width[2] ));
103 int max = ratio.MaxDim();
104
105 Vec3f normal = Vec3f(0);
106
107 if (dir[max] > 0)
108 normal[max] = 1.0;
109 else normal[max] = -1.0;
110
111 return normal;
112 };
113
114 /**
115 * compute UV values for a box
116 */
117 virtual Vec2f GetUV(Ray &ray)
118 {
119 /**
120 * first get the normal vector
121 */
122 Vec3f normal = (*this).GetNormal(ray);
123
124 /**
125 * and check which side of the box is hit
126 * save the corresponding axis in get_i (0 = xAxis, 1 = yAxis, 2 = zAxis)
127 */
128 int get_i = 0;
129 for (unsigned int i = 0; i < 3; i++)
130 if ( fabs(normal[i]) )
131 get_i = i;
132
133 /**
134 * then take the vector from the hitpoint to
135 * either the min or the max vector of the box
136 */
137 Vec3f hitpoint = ray.org + ray.t * ray.dir;
138 Vec3f diff;
139
140 if ( normal[get_i] == 1)
141 diff = hitpoint - _min;
142 else diff = hitpoint - _max;
143
144 /**
145 * normalize this vector, to get entries in between 0 and 1
146 */
147 Normalize(diff);
148
149 /**
150 * take two entries out of the vector
151 * depending on the side which is hit
152 */
153 float u = diff[ (get_i + 2) % 3 ];
154 float v = diff[ (get_i + 1) % 3 ];
155
156 return Vec2f(u,v);
157 };
158
159 };
160
161 #endif
syntax highlighted by Code2HTML, v. 0.9.1