1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /**
3  *	Contains code to compute the minimal bounding sphere.
4  *	\file		IceBoundingSphere.h
5  *	\author		Pierre Terdiman
6  *	\date		January, 29, 2000
7  */
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 // Include Guard
12 #ifndef __ICEBOUNDINGSPHERE_H__
13 #define __ICEBOUNDINGSPHERE_H__
14 
15 	enum BSphereMethod
16 	{
17 		BS_NONE,
18 		BS_GEMS,
19 		BS_MINIBALL,
20 
21 		BS_FORCE_DWORD	= 0x7fffffff
22 	};
23 
24 	class ICEMATHS_API Sphere
25 	{
26 		public:
27 		//! Constructor
Sphere()28 		inline_					Sphere()																		{}
29 		//! Constructor
Sphere(const Point & center,float radius)30 		inline_					Sphere(const Point& center, float radius) : mCenter(center), mRadius(radius)	{}
31 		//! Constructor
32 								Sphere(udword nb_verts, const Point* verts);
33 		//! Copy constructor
Sphere(const Sphere & sphere)34 		inline_					Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius)	{}
35 		//! Destructor
~Sphere()36 		inline_					~Sphere()																		{}
37 
38 				BSphereMethod	Compute(udword nb_verts, const Point* verts);
39 				bool			FastCompute(udword nb_verts, const Point* verts);
40 
41 		// Access methods
GetCenter()42 		inline_	const Point&	GetCenter()						const		{ return mCenter; }
GetRadius()43 		inline_	float			GetRadius()						const		{ return mRadius; }
44 
Center()45 		inline_	const Point&	Center()						const		{ return mCenter; }
Radius()46 		inline_	float			Radius()						const		{ return mRadius; }
47 
Set(const Point & center,float radius)48 		inline_	Sphere&			Set(const Point& center, float radius)		{ mCenter = center; mRadius = radius; return *this; }
SetCenter(const Point & center)49 		inline_	Sphere&			SetCenter(const Point& center)				{ mCenter = center; return *this; }
SetRadius(float radius)50 		inline_	Sphere&			SetRadius(float radius)						{ mRadius = radius; return *this; }
51 
52 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53 		/**
54 		 *	Tests if a point is contained within the sphere.
55 		 *	\param		p	[in] the point to test
56 		 *	\return		true if inside the sphere
57 		 */
58 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Contains(const Point & p)59 		inline_	bool			Contains(const Point& p)		const
60 								{
61 									return mCenter.SquareDistance(p) <= mRadius*mRadius;
62 								}
63 
64 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65 		/**
66 		 *	Tests if a sphere is contained within the sphere.
67 		 *	\param		sphere	[in] the sphere to test
68 		 *	\return		true if inside the sphere
69 		 */
70 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Contains(const Sphere & sphere)71 		inline_	bool			Contains(const Sphere& sphere)	const
72 								{
73 									// If our radius is the smallest, we can't possibly contain the other sphere
74 									if(mRadius < sphere.mRadius)	return false;
75 									// So r is always positive or null now
76 									float r = mRadius - sphere.mRadius;
77 									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
78 								}
79 
80 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 		/**
82 		 *	Tests if a box is contained within the sphere.
83 		 *	\param		aabb	[in] the box to test
84 		 *	\return		true if inside the sphere
85 		 */
86 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Contains(const AABB & aabb)87 		inline_ BOOL			Contains(const AABB& aabb)	const
88 								{
89 									// I assume if all 8 box vertices are inside the sphere, so does the whole box.
90 									// Sounds ok but maybe there's a better way?
91 									float R2 = mRadius * mRadius;
92 #ifdef USE_MIN_MAX
93 									const Point& Max = ((ShadowAABB&)&aabb).mMax;
94 									const Point& Min = ((ShadowAABB&)&aabb).mMin;
95 #else
96 									Point Max; aabb.GetMax(Max);
97 									Point Min; aabb.GetMin(Min);
98 #endif
99 									Point p;
100 									p.x=Max.x; p.y=Max.y; p.z=Max.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
101 									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
102 									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
103 									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
104 									p.x=Max.x; p.y=Max.y; p.z=Min.z;	if(mCenter.SquareDistance(p)>=R2)	return FALSE;
105 									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
106 									p.x=Max.x; p.y=Min.y;				if(mCenter.SquareDistance(p)>=R2)	return FALSE;
107 									p.x=Min.x;							if(mCenter.SquareDistance(p)>=R2)	return FALSE;
108 
109 									return TRUE;
110 								}
111 
112 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113 		/**
114 		 *	Tests if the sphere intersects another sphere
115 		 *	\param		sphere	[in] the other sphere
116 		 *	\return		true if spheres overlap
117 		 */
118 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Intersect(const Sphere & sphere)119 		inline_	bool			Intersect(const Sphere& sphere)	const
120 								{
121 									float r = mRadius + sphere.mRadius;
122 									return mCenter.SquareDistance(sphere.mCenter) <= r*r;
123 								}
124 
125 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 		/**
127 		 *	Checks the sphere is valid.
128 		 *	\return		true if the box is valid
129 		 */
130 		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IsValid()131 		inline_	BOOL			IsValid()	const
132 								{
133 									// Consistency condition for spheres: Radius >= 0.0f
134 									if(mRadius < 0.0f)	return FALSE;
135 									return TRUE;
136 								}
137 		public:
138 				Point			mCenter;		//!< Sphere center
139 				float			mRadius;		//!< Sphere radius
140 	};
141 
142 #endif // __ICEBOUNDINGSPHERE_H__
143