1 // This code is in the public domain -- castanyo@yahoo.es
2 
3 #ifndef NV_MATH_BOX_H
4 #define NV_MATH_BOX_H
5 
6 #include <nvmath/Vector.h>
7 
8 #include <float.h> // FLT_MAX
9 
10 namespace nv
11 {
12 
13 /// Axis Aligned Bounding Box.
14 class Box
15 {
16 public:
17 
18 	/// Default ctor.
Box()19 	Box() { };
20 
21 	/// Copy ctor.
Box(const Box & b)22 	Box( const Box & b ) : m_mins(b.m_mins), m_maxs(b.m_maxs) { }
23 
24 	/// Init ctor.
Box(Vector3::Arg mins,Vector3::Arg maxs)25 	Box( Vector3::Arg mins, Vector3::Arg maxs ) : m_mins(mins), m_maxs(maxs) { }
26 
27 	// Cast operators.
28 	operator const float * () const { return reinterpret_cast<const float *>(this); }
29 
30 	/// Min corner of the box.
mins()31 	Vector3 mins() const { return m_mins; }
32 
33 	/// Max corner of the box.
maxs()34 	Vector3 maxs() const { return m_maxs; }
35 
36 	/// Clear the bounds.
clearBounds()37 	void clearBounds()
38 	{
39 		m_mins.set(FLT_MAX, FLT_MAX, FLT_MAX);
40 		m_maxs.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
41 	}
42 
43 	/// Build a cube centered on center and with edge = 2*dist
cube(Vector3::Arg center,float dist)44 	void cube(Vector3::Arg center, float dist)
45 	{
46 		setCenterExtents(center, Vector3(dist, dist, dist));
47 	}
48 
49 	/// Build a box, given center and extents.
setCenterExtents(Vector3::Arg center,Vector3::Arg extents)50 	void setCenterExtents(Vector3::Arg center, Vector3::Arg extents)
51 	{
52 		m_mins = center - extents;
53 		m_maxs = center + extents;
54 	}
55 
56 	/// Get box center.
center()57 	Vector3 center() const
58 	{
59 		return (m_mins + m_maxs) * 0.5f;
60 	}
61 
62 	/// Return extents of the box.
extents()63 	Vector3 extents() const
64 	{
65 		return (m_maxs - m_mins) * 0.5f;
66 	}
67 
68 	/// Return extents of the box.
extents(uint axis)69 	scalar extents(uint axis) const
70 	{
71 		nvDebugCheck(axis < 3);
72 		if (axis == 0) return (m_maxs.x() - m_mins.x()) * 0.5f;
73 		if (axis == 1) return (m_maxs.y() - m_mins.y()) * 0.5f;
74 		if (axis == 2) return (m_maxs.z() - m_mins.z()) * 0.5f;
75 		nvAssume(false);
76 		return 0.0f;
77 	}
78 
79 	/// Add a point to this box.
addPointToBounds(Vector3::Arg p)80 	void addPointToBounds(Vector3::Arg p)
81 	{
82 		m_mins = min(m_mins, p);
83 		m_maxs = max(m_maxs, p);
84 	}
85 
86 	/// Add a box to this box.
addBoxToBounds(const Box & b)87 	void addBoxToBounds(const Box & b)
88 	{
89 		m_mins = min(m_mins, b.m_mins);
90 		m_maxs = max(m_maxs, b.m_maxs);
91 	}
92 
93 	/// Translate box.
translate(Vector3::Arg v)94 	void translate(Vector3::Arg v)
95 	{
96 		m_mins += v;
97 		m_maxs += v;
98 	}
99 
100 	/// Scale the box.
scale(float s)101 	void scale(float s)
102 	{
103 		m_mins *= s;
104 		m_maxs *= s;
105 	}
106 
107 	/// Get the area of the box.
area()108 	float area() const
109 	{
110 		const Vector3 d = extents();
111 		return 8.0f * (d.x()*d.y() + d.x()*d.z() + d.y()*d.z());
112 	}
113 
114 	/// Get the volume of the box.
volume()115 	float volume() const
116 	{
117 		Vector3 d = extents();
118 		return 8.0f * (d.x() * d.y() * d.z());
119 	}
120 
121 	/// Return true if the box contains the given point.
contains(Vector3::Arg p)122 	bool contains(Vector3::Arg p) const
123 	{
124 		return
125 			m_mins.x() < p.x() && m_mins.y() < p.y() && m_mins.z() < p.z() &&
126 			m_maxs.x() > p.x() && m_maxs.y() > p.y() && m_maxs.z() > p.z();
127 	}
128 
129 private:
130 
131 	Vector3 m_mins;
132 	Vector3 m_maxs;
133 };
134 
135 
136 
137 } // nv namespace
138 
139 
140 #endif // NV_MATH_BOX_H
141