3 * Copyright (c) 2007-2010 SlimDX Group
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "../SlimDXException.h"
28 #include "BoundingSphere.h"
29 #include "BoundingBox.h"
33 using namespace System;
34 using namespace System::Globalization;
38 BoundingSphere::BoundingSphere( Vector3 center, float radius )
44 ContainmentType BoundingSphere::Contains( BoundingSphere sphere, BoundingBox box )
48 if( !BoundingBox::Intersects( box, sphere ) )
49 return ContainmentType::Disjoint;
51 float radius = sphere.Radius * sphere.Radius;
52 vector.X = sphere.Center.X - box.Minimum.X;
53 vector.Y = sphere.Center.Y - box.Maximum.Y;
54 vector.Z = sphere.Center.Z - box.Maximum.Z;
56 if( vector.LengthSquared() > radius )
57 return ContainmentType::Intersects;
59 vector.X = sphere.Center.X - box.Maximum.X;
60 vector.Y = sphere.Center.Y - box.Maximum.Y;
61 vector.Z = sphere.Center.Z - box.Maximum.Z;
63 if( vector.LengthSquared() > radius )
64 return ContainmentType::Intersects;
66 vector.X = sphere.Center.X - box.Maximum.X;
67 vector.Y = sphere.Center.Y - box.Minimum.Y;
68 vector.Z = sphere.Center.Z - box.Maximum.Z;
70 if( vector.LengthSquared() > radius )
71 return ContainmentType::Intersects;
73 vector.X = sphere.Center.X - box.Minimum.X;
74 vector.Y = sphere.Center.Y - box.Minimum.Y;
75 vector.Z = sphere.Center.Z - box.Maximum.Z;
77 if( vector.LengthSquared() > radius )
78 return ContainmentType::Intersects;
80 vector.X = sphere.Center.X - box.Minimum.X;
81 vector.Y = sphere.Center.Y - box.Maximum.Y;
82 vector.Z = sphere.Center.Z - box.Minimum.Z;
84 if( vector.LengthSquared() > radius )
85 return ContainmentType::Intersects;
87 vector.X = sphere.Center.X - box.Maximum.X;
88 vector.Y = sphere.Center.Y - box.Maximum.Y;
89 vector.Z = sphere.Center.Z - box.Minimum.Z;
91 if( vector.LengthSquared() > radius )
92 return ContainmentType::Intersects;
94 vector.X = sphere.Center.X - box.Maximum.X;
95 vector.Y = sphere.Center.Y - box.Minimum.Y;
96 vector.Z = sphere.Center.Z - box.Minimum.Z;
98 if( vector.LengthSquared() > radius )
99 return ContainmentType::Intersects;
101 vector.X = sphere.Center.X - box.Minimum.X;
102 vector.Y = sphere.Center.Y - box.Minimum.Y;
103 vector.Z = sphere.Center.Z - box.Minimum.Z;
105 if( vector.LengthSquared() > radius )
106 return ContainmentType::Intersects;
108 return ContainmentType::Contains;
111 ContainmentType BoundingSphere::Contains( BoundingSphere sphere1, BoundingSphere sphere2 )
114 float x = sphere1.Center.X - sphere2.Center.X;
115 float y = sphere1.Center.Y - sphere2.Center.Y;
116 float z = sphere1.Center.Z - sphere2.Center.Z;
118 distance = static_cast<float>( Math::Sqrt( (x * x) + (y * y) + (z * z) ) );
119 float radius = sphere1.Radius;
120 float radius2 = sphere2.Radius;
122 if( radius + radius2 < distance )
123 return ContainmentType::Disjoint;
125 if( radius - radius2 < distance )
126 return ContainmentType::Intersects;
128 return ContainmentType::Contains;
131 ContainmentType BoundingSphere::Contains( BoundingSphere sphere, Vector3 vector )
133 float x = vector.X - sphere.Center.X;
134 float y = vector.Y - sphere.Center.Y;
135 float z = vector.Z - sphere.Center.Z;
137 float distance = (x * x) + (y * y) + (z * z);
139 if( distance >= (sphere.Radius * sphere.Radius) )
140 return ContainmentType::Disjoint;
142 return ContainmentType::Contains;
145 BoundingSphere BoundingSphere::FromBox( BoundingBox box )
147 BoundingSphere sphere;
148 Vector3::Lerp( box.Minimum, box.Maximum, 0.5f, sphere.Center );
150 float x = box.Minimum.X - box.Maximum.X;
151 float y = box.Minimum.Y - box.Maximum.Y;
152 float z = box.Minimum.Z - box.Maximum.Z;
154 float distance = static_cast<float>( Math::Sqrt( (x * x) + (y * y) + (z * z) ) );
156 sphere.Radius = distance * 0.5f;
161 BoundingSphere BoundingSphere::FromPoints( array<Vector3>^ points )
165 pin_ptr<Vector3> pinnedPoints = &points[0];
167 HRESULT hr = D3DXComputeBoundingSphere( reinterpret_cast<const D3DXVECTOR3*>( pinnedPoints ), points->Length, sizeof(float) * 3, ¢er, &radius );
168 if( RECORD_SDX( hr ).IsFailure )
169 return BoundingSphere();
171 BoundingSphere sphere;
172 sphere.Center = Vector3( center.x, center.y, center.z );
173 sphere.Radius = radius;
178 BoundingSphere BoundingSphere::Merge( BoundingSphere sphere1, BoundingSphere sphere2 )
180 BoundingSphere sphere;
181 Vector3 difference = sphere2.Center - sphere1.Center;
183 float length = difference.Length();
184 float radius = sphere1.Radius;
185 float radius2 = sphere2.Radius;
187 if( radius + radius2 >= length)
189 if( radius - radius2 >= length )
192 if( radius2 - radius >= length )
196 Vector3 vector = difference * ( 1.0f / length );
197 float min = Math::Min( -radius, length - radius2 );
198 float max = ( Math::Max( radius, length + radius2 ) - min ) * 0.5f;
200 sphere.Center = sphere1.Center + vector * ( max + min );
206 bool BoundingSphere::Intersects( BoundingSphere sphere, BoundingBox box )
208 return BoundingBox::Intersects( box, sphere );
211 bool BoundingSphere::Intersects( BoundingSphere sphere1, BoundingSphere sphere2 )
214 distance = Vector3::DistanceSquared( sphere1.Center, sphere2.Center );
215 float radius = sphere1.Radius;
216 float radius2 = sphere2.Radius;
218 if( (radius * radius) + (2.0f * radius * radius2) + (radius2 * radius2) <= distance )
224 bool BoundingSphere::Intersects( BoundingSphere sphere, Ray ray, [Out] float% distance )
226 return Ray::Intersects( ray, sphere, distance );
229 PlaneIntersectionType BoundingSphere::Intersects( BoundingSphere sphere, Plane plane )
231 return Plane::Intersects( plane, sphere );
234 bool BoundingSphere::operator == ( BoundingSphere left, BoundingSphere right )
236 return BoundingSphere::Equals( left, right );
239 bool BoundingSphere::operator != ( BoundingSphere left, BoundingSphere right )
241 return !BoundingSphere::Equals( left, right );
244 String^ BoundingSphere::ToString()
246 return String::Format( CultureInfo::CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString(CultureInfo::CurrentCulture) );
249 int BoundingSphere::GetHashCode()
251 return Center.GetHashCode() + Radius.GetHashCode();
254 bool BoundingSphere::Equals( Object^ value )
256 if( value == nullptr )
259 if( value->GetType() != GetType() )
262 return Equals( safe_cast<BoundingSphere>( value ) );
265 bool BoundingSphere::Equals( BoundingSphere value )
267 return ( Center == value.Center && Radius == value.Radius );
270 bool BoundingSphere::Equals( BoundingSphere% value1, BoundingSphere% value2 )
272 return ( value1.Center == value2.Center && value1.Radius == value2.Radius );