1 #ifndef __GNUC__
2 #pragma once
3 #endif
4 #ifndef __XR_AABB_H__
5 #define __XR_AABB_H__
6 
7 #include "xr_vector3.h"
8 #include "xr_limits.h"
9 
10 namespace xray_re {
11 
12 template<typename T> struct _aabb {
13 	_aabb<T>&	null();
14 	_aabb<T>&	set(const _aabb<T>& box);
15 	_aabb<T>&	invalidate();
16 	_aabb<T>&	extend(const _vector3<T>& p);
17 	_aabb<T>&	grow(T s);
18 	_aabb<T>&	grow(const _vector3<T>& s);
19 	_aabb<T>&	shrink(T s);
20 	_aabb<T>&	shrink(const _vector3<T>& s);
21 	_aabb<T>&	fix();
22 	T		volume() const;
23 	T		size() const;
24 	T		width() const;
25 	T		height() const;
26 	T		depth() const;
27 	void		center(_vector3<T>& v) const;
28 	T		overlap_ratio(const _aabb<T>& box) const;
29 	bool		contain(const _vector3<T>& p) const;
30 	bool		contain(const _aabb<T>& box) const;
31 	bool		intersect(const _aabb<T>& box) const;
32 	bool		intersect_zy(const _aabb<T>& box) const;
33 	_aabb<T>&	merge(const _aabb<T>& box);
34 
35 	union {
36 		struct {
37 			_vector3<T>	min;
38 			_vector3<T>	max;
39 		};
40 		struct {
41 			T		x1, y1, z1;
42 			T		x2, y2, z2;
43 		};
44 	};
45 };
46 
47 typedef _aabb<float> fbox;
48 typedef _aabb<int16_t> i16box;
49 
null()50 template<typename T> inline _aabb<T>& _aabb<T>::null()
51 {
52 	min.set();
53 	max.set();
54 	return *this;
55 }
56 
set(const _aabb<T> & box)57 template<typename T> inline _aabb<T>& _aabb<T>::set(const _aabb<T>& box)
58 {
59 	min.set(box.min);
60 	max.set(box.max);
61 	return *this;
62 }
63 
invalidate()64 template<typename T> inline _aabb<T>& _aabb<T>::invalidate()
65 {
66 	x1 = y1 = z1 = xr_numeric_limits<T>::max();
67 	x2 = y2 = z2 = xr_numeric_limits<T>::real_min();
68 	return *this;
69 }
70 
extend(const _vector3<T> & p)71 template<typename T> inline _aabb<T>& _aabb<T>::extend(const _vector3<T>& p)
72 {
73 	min.min(p);
74 	max.max(p);
75 	return *this;
76 }
77 
grow(const _vector3<T> & s)78 template<typename T> inline _aabb<T>& _aabb<T>::grow(const _vector3<T>& s)
79 {
80 	min.sub(s);
81 	max.add(s);
82 	return *this;
83 }
84 
grow(T s)85 template<typename T> inline _aabb<T>& _aabb<T>::grow(T s)
86 {
87 	min.sub(s);
88 	max.add(s);
89 	return *this;
90 }
91 
shrink(const _vector3<T> & s)92 template<typename T> inline _aabb<T>& _aabb<T>::shrink(const _vector3<T>& s)
93 {
94 	min.sub(s);
95 	max.add(s);
96 	return fix();
97 }
98 
shrink(T s)99 template<typename T> inline _aabb<T>& _aabb<T>::shrink(T s)
100 {
101 	min.add(s);
102 	max.sub(s);
103 	return fix();
104 }
105 
fix()106 template<typename T> inline _aabb<T>& _aabb<T>::fix()
107 {
108 	if (x2 < x1)
109 		x1 = x2 = T(0.5)*(x1 + x2);
110 	if (y2 < y1)
111 		y1 = y2 = T(0.5)*(y1 + y2);
112 	if (z2 < z1)
113 		z1 = z2 = T(0.5)*(z1 + z2);
114 	return *this;
115 }
116 
contain(const _vector3<T> & p)117 template<typename T> inline bool _aabb<T>::contain(const _vector3<T>& p) const
118 {
119 	return (p.x >= min.x && p.x <= max.x) &&
120 			(p.y >= min.y && p.y <= max.y) &&
121 			(p.z >= min.z && p.z <= max.z);
122 }
123 
contain(const _aabb<T> & box)124 template<typename T> inline bool _aabb<T>::contain(const _aabb<T>& box) const
125 {
126 	return (x1 <= box.x1 && box.x2 <= x2) &&
127 			(y1 <= box.y1 && box.y2 <= y2) &&
128 			(z1 <= box.z1 && box.z2 <= z2);
129 }
130 
intersect(const _aabb<T> & box)131 template<typename T> inline bool _aabb<T>::intersect(const _aabb<T>& box) const
132 {
133 	if (x1 > box.x2 || x2 < box.x1)
134 		return false;
135 	if (y1 > box.y2 || y2 < box.y1)
136 		return false;
137 	if (z1 > box.z2 || z2 < box.z1)
138 		return false;
139 	return true;
140 }
141 
intersect_zy(const _aabb<T> & box)142 template<typename T> inline bool _aabb<T>::intersect_zy(const _aabb<T>& box) const
143 {
144 	if (z1 > box.z2 || z2 < box.z1)
145 		return false;
146 	if (y1 > box.y2 || y2 < box.y1)
147 		return false;
148 	return true;
149 }
150 
volume()151 template<typename T> inline T _aabb<T>::volume() const
152 {
153 	return (x2 - x1)*(y2 - y1)*(z2 - z1);
154 }
155 
size()156 template<typename T> inline T _aabb<T>::size() const
157 {
158 	return (x2 - x1) + (y2 - y1) + (z2 - z1);
159 }
160 
width()161 template<typename T> inline T _aabb<T>::width() const { return x2 - x1; }
height()162 template<typename T> inline T _aabb<T>::height() const { return y2 - y1; }
depth()163 template<typename T> inline T _aabb<T>::depth() const { return z2 - z1; }
164 
center(_vector3<T> & p)165 template<typename T> inline void _aabb<T>::center(_vector3<T>& p) const
166 {
167 	p.add(max, min).mul(T(0.5));
168 }
169 
overlap_ratio(const _aabb<T> & box)170 template<typename T> inline T _aabb<T>::overlap_ratio(const _aabb<T>& box) const
171 {
172 	T w = (x2 < box.x2) ? x2 : box.x2;
173 	w -= (x1 < box.x1) ? box.x1 : x1;
174 	if (w <= 0)
175 		return 0;
176 	T h = (y2 < box.z2) ? y2 : box.y2;
177 	h -= (y1 < box.y1) ? box.y1 : y1;
178 	if (h <= 0)
179 		return 0;
180 	T d = (z2 < box.z2) ? z2 : box.z2;
181 	d -= (z1 < box.z1) ? box.z1 : z1;
182 	if (d <= 0)
183 		return 0;
184 	return (w*h*d)/box.volume();
185 }
186 
merge(const _aabb<T> & box)187 template<typename T> inline _aabb<T>& _aabb<T>::merge(const _aabb<T>& box)
188 {
189 	if (x1 > box.x1)
190 		x1 = box.x1;
191 	if (y1 > box.y1)
192 		y1 = box.y1;
193 	if (z1 > box.z1)
194 		z1 = box.z1;
195 	if (x2 < box.x2)
196 		x2 = box.x2;
197 	if (y2 < box.y2)
198 		y2 = box.y2;
199 	if (z2 < box.z2)
200 		z2 = box.z2;
201 	return *this;
202 }
203 
204 } // end of namespace xray_re
205 
206 #endif
207