Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
BoundingSphere.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under MIT License. See LICENSE.md for details.
3 //
4 // -----------------------------------------------------------------------------
5 // Original code from SlimMath project. http://code.google.com/p/slimmath/
6 // Greetings to SlimDX Group. Original code published with the following license:
7 // -----------------------------------------------------------------------------
8 /*
9 * Copyright (c) 2007-2011 SlimDX Group
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 */
29 using System;
30 using System.Globalization;
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
33 using SiliconStudio.Core.Serialization;
34 
35 namespace SiliconStudio.Core.Mathematics
36 {
37  /// <summary>
38  /// Represents a bounding sphere in three dimensional space.
39  /// </summary>
40  [DataContract]
41  [StructLayout(LayoutKind.Sequential, Pack = 4)]
42  public struct BoundingSphere : IEquatable<BoundingSphere>, IFormattable
43  {
44  /// <summary>
45  /// The center of the sphere in three dimensional space.
46  /// </summary>
47  public Vector3 Center;
48 
49  /// <summary>
50  /// The radious of the sphere.
51  /// </summary>
52  public float Radius;
53 
54  /// <summary>
55  /// Initializes a new instance of the <see cref="SiliconStudio.Core.Mathematics.BoundingBox"/> struct.
56  /// </summary>
57  /// <param name="center">The center of the sphere in three dimensional space.</param>
58  /// <param name="radius">The radius of the sphere.</param>
59  public BoundingSphere(Vector3 center, float radius)
60  {
61  this.Center = center;
62  this.Radius = radius;
63  }
64 
65  /// <summary>
66  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.Ray"/>.
67  /// </summary>
68  /// <param name="ray">The ray to test.</param>
69  /// <returns>Whether the two objects intersected.</returns>
70  public bool Intersects(ref Ray ray)
71  {
72  float distance;
73  return Collision.RayIntersectsSphere(ref ray, ref this, out distance);
74  }
75 
76  /// <summary>
77  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.Ray"/>.
78  /// </summary>
79  /// <param name="ray">The ray to test.</param>
80  /// <param name="distance">When the method completes, contains the distance of the intersection,
81  /// or 0 if there was no intersection.</param>
82  /// <returns>Whether the two objects intersected.</returns>
83  public bool Intersects(ref Ray ray, out float distance)
84  {
85  return Collision.RayIntersectsSphere(ref ray, ref this, out distance);
86  }
87 
88  /// <summary>
89  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.Ray"/>.
90  /// </summary>
91  /// <param name="ray">The ray to test.</param>
92  /// <param name="point">When the method completes, contains the point of intersection,
93  /// or <see cref="SiliconStudio.Core.Mathematics.Vector3.Zero"/> if there was no intersection.</param>
94  /// <returns>Whether the two objects intersected.</returns>
95  public bool Intersects(ref Ray ray, out Vector3 point)
96  {
97  return Collision.RayIntersectsSphere(ref ray, ref this, out point);
98  }
99 
100  /// <summary>
101  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.Plane"/>.
102  /// </summary>
103  /// <param name="plane">The plane to test.</param>
104  /// <returns>Whether the two objects intersected.</returns>
106  {
107  return Collision.PlaneIntersectsSphere(ref plane, ref this);
108  }
109 
110  /// <summary>
111  /// Determines if there is an intersection between the current object and a triangle.
112  /// </summary>
113  /// <param name="vertex1">The first vertex of the triangle to test.</param>
114  /// <param name="vertex2">The second vertex of the triagnle to test.</param>
115  /// <param name="vertex3">The third vertex of the triangle to test.</param>
116  /// <returns>Whether the two objects intersected.</returns>
117  public bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
118  {
119  return Collision.SphereIntersectsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
120  }
121 
122  /// <summary>
123  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.BoundingBox"/>.
124  /// </summary>
125  /// <param name="box">The box to test.</param>
126  /// <returns>Whether the two objects intersected.</returns>
127  public bool Intersects(ref BoundingBox box)
128  {
129  return Collision.BoxIntersectsSphere(ref box, ref this);
130  }
131 
132  /// <summary>
133  /// Determines if there is an intersection between the current object and a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/>.
134  /// </summary>
135  /// <param name="sphere">The sphere to test.</param>
136  /// <returns>Whether the two objects intersected.</returns>
137  public bool Intersects(ref BoundingSphere sphere)
138  {
139  return Collision.SphereIntersectsSphere(ref this, ref sphere);
140  }
141 
142  /// <summary>
143  /// Determines whether the current objects contains a point.
144  /// </summary>
145  /// <param name="point">The point to test.</param>
146  /// <returns>The type of containment the two objects have.</returns>
147  public ContainmentType Contains(ref Vector3 point)
148  {
149  return Collision.SphereContainsPoint(ref this, ref point);
150  }
151 
152  /// <summary>
153  /// Determines whether the current objects contains a triangle.
154  /// </summary>
155  /// <param name="vertex1">The first vertex of the triangle to test.</param>
156  /// <param name="vertex2">The second vertex of the triagnle to test.</param>
157  /// <param name="vertex3">The third vertex of the triangle to test.</param>
158  /// <returns>The type of containment the two objects have.</returns>
159  public ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
160  {
161  return Collision.SphereContainsTriangle(ref this, ref vertex1, ref vertex2, ref vertex3);
162  }
163 
164  /// <summary>
165  /// Determines whether the current objects contains a <see cref="SiliconStudio.Core.Mathematics.BoundingBox"/>.
166  /// </summary>
167  /// <param name="box">The box to test.</param>
168  /// <returns>The type of containment the two objects have.</returns>
170  {
171  return Collision.SphereContainsBox(ref this, ref box);
172  }
173 
174  /// <summary>
175  /// Determines whether the current objects contains a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/>.
176  /// </summary>
177  /// <param name="sphere">The sphere to test.</param>
178  /// <returns>The type of containment the two objects have.</returns>
180  {
181  return Collision.SphereContainsSphere(ref this, ref sphere);
182  }
183 
184  /// <summary>
185  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> that fully contains the given points.
186  /// </summary>
187  /// <param name="points">The points that will be contained by the sphere.</param>
188  /// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
189  public static void FromPoints(Vector3[] points, out BoundingSphere result)
190  {
191  //Find the center of all points.
192  Vector3 center = Vector3.Zero;
193  for (int i = 0; i < points.Length; ++i)
194  {
195  Vector3.Add(ref points[i], ref center, out center);
196  }
197 
198  //This is the center of our sphere.
199  center /= (float)points.Length;
200 
201  //Find the radius of the sphere
202  float radius = 0f;
203  for (int i = 0; i < points.Length; ++i)
204  {
205  //We are doing a relative distance comparasin to find the maximum distance
206  //from the center of our sphere.
207  float distance;
208  Vector3.DistanceSquared(ref center, ref points[i], out distance);
209 
210  if (distance > radius)
211  radius = distance;
212  }
213 
214  //Find the real distance from the DistanceSquared.
215  radius = (float)Math.Sqrt(radius);
216 
217  //Construct the sphere.
218  result.Center = center;
219  result.Radius = radius;
220  }
221 
222  /// <summary>
223  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> that fully contains the given points.
224  /// </summary>
225  /// <param name="points">The points that will be contained by the sphere.</param>
226  /// <returns>The newly constructed bounding sphere.</returns>
227  public static BoundingSphere FromPoints(Vector3[] points)
228  {
229  BoundingSphere result;
230  FromPoints(points, out result);
231  return result;
232  }
233 
234  /// <summary>
235  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> from a given box.
236  /// </summary>
237  /// <param name="box">The box that will designate the extents of the sphere.</param>
238  /// <param name="result">When the method completes, the newly constructed bounding sphere.</param>
239  public static void FromBox(ref BoundingBox box, out BoundingSphere result)
240  {
241  Vector3.Lerp(ref box.Minimum, ref box.Maximum, 0.5f, out result.Center);
242 
243  float x = box.Minimum.X - box.Maximum.X;
244  float y = box.Minimum.Y - box.Maximum.Y;
245  float z = box.Minimum.Z - box.Maximum.Z;
246 
247  float distance = (float)(Math.Sqrt((x * x) + (y * y) + (z * z)));
248  result.Radius = distance * 0.5f;
249  }
250 
251  /// <summary>
252  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> from a given box.
253  /// </summary>
254  /// <param name="box">The box that will designate the extents of the sphere.</param>
255  /// <returns>The newly constructed bounding sphere.</returns>
256  public static BoundingSphere FromBox(BoundingBox box)
257  {
258  BoundingSphere result;
259  FromBox(ref box, out result);
260  return result;
261  }
262 
263  /// <summary>
264  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> that is the as large as the total combined area of the two specified spheres.
265  /// </summary>
266  /// <param name="value1">The first sphere to merge.</param>
267  /// <param name="value2">The second sphere to merge.</param>
268  /// <param name="result">When the method completes, contains the newly constructed bounding sphere.</param>
269  public static void Merge(ref BoundingSphere value1, ref BoundingSphere value2, out BoundingSphere result)
270  {
271  Vector3 difference = value2.Center - value1.Center;
272 
273  float length = difference.Length();
274  float radius = value1.Radius;
275  float radius2 = value2.Radius;
276 
277  if (radius + radius2 >= length)
278  {
279  if (radius - radius2 >= length)
280  {
281  result = value1;
282  return;
283  }
284 
285  if (radius2 - radius >= length)
286  {
287  result = value2;
288  return;
289  }
290  }
291 
292  Vector3 vector = difference * (1.0f / length);
293  float min = Math.Min(-radius, length - radius2);
294  float max = (Math.Max(radius, length + radius2) - min) * 0.5f;
295 
296  result.Center = value1.Center + vector * (max + min);
297  result.Radius = max;
298  }
299 
300  /// <summary>
301  /// Constructs a <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> that is the as large as the total combined area of the two specified spheres.
302  /// </summary>
303  /// <param name="value1">The first sphere to merge.</param>
304  /// <param name="value2">The second sphere to merge.</param>
305  /// <returns>The newly constructed bounding sphere.</returns>
306  public static BoundingSphere Merge(BoundingSphere value1, BoundingSphere value2)
307  {
308  BoundingSphere result;
309  Merge(ref value1, ref value2, out result);
310  return result;
311  }
312 
313  /// <summary>
314  /// Tests for equality between two objects.
315  /// </summary>
316  /// <param name="left">The first value to compare.</param>
317  /// <param name="right">The second value to compare.</param>
318  /// <returns><c>true</c> if <paramref name="left"/> has the same value as <paramref name="right"/>; otherwise, <c>false</c>.</returns>
319  public static bool operator ==(BoundingSphere left, BoundingSphere right)
320  {
321  return left.Equals(right);
322  }
323 
324  /// <summary>
325  /// Tests for inequality between two objects.
326  /// </summary>
327  /// <param name="left">The first value to compare.</param>
328  /// <param name="right">The second value to compare.</param>
329  /// <returns><c>true</c> if <paramref name="left"/> has a different value than <paramref name="right"/>; otherwise, <c>false</c>.</returns>
330  public static bool operator !=(BoundingSphere left, BoundingSphere right)
331  {
332  return !left.Equals(right);
333  }
334 
335  /// <summary>
336  /// Returns a <see cref="System.String"/> that represents this instance.
337  /// </summary>
338  /// <returns>
339  /// A <see cref="System.String"/> that represents this instance.
340  /// </returns>
341  public override string ToString()
342  {
343  return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString());
344  }
345 
346  /// <summary>
347  /// Returns a <see cref="System.String"/> that represents this instance.
348  /// </summary>
349  /// <param name="format">The format.</param>
350  /// <returns>
351  /// A <see cref="System.String"/> that represents this instance.
352  /// </returns>
353  public string ToString(string format)
354  {
355  if (format == null)
356  return ToString();
357 
358  return string.Format(CultureInfo.CurrentCulture, "Center:{0} Radius:{1}", Center.ToString(format, CultureInfo.CurrentCulture),
359  Radius.ToString(format, CultureInfo.CurrentCulture));
360  }
361 
362  /// <summary>
363  /// Returns a <see cref="System.String"/> that represents this instance.
364  /// </summary>
365  /// <param name="formatProvider">The format provider.</param>
366  /// <returns>
367  /// A <see cref="System.String"/> that represents this instance.
368  /// </returns>
369  public string ToString(IFormatProvider formatProvider)
370  {
371  return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(), Radius.ToString());
372  }
373 
374  /// <summary>
375  /// Returns a <see cref="System.String"/> that represents this instance.
376  /// </summary>
377  /// <param name="format">The format.</param>
378  /// <param name="formatProvider">The format provider.</param>
379  /// <returns>
380  /// A <see cref="System.String"/> that represents this instance.
381  /// </returns>
382  public string ToString(string format, IFormatProvider formatProvider)
383  {
384  if (format == null)
385  return ToString(formatProvider);
386 
387  return string.Format(formatProvider, "Center:{0} Radius:{1}", Center.ToString(format, formatProvider),
388  Radius.ToString(format, formatProvider));
389  }
390 
391  /// <summary>
392  /// Returns a hash code for this instance.
393  /// </summary>
394  /// <returns>
395  /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
396  /// </returns>
397  public override int GetHashCode()
398  {
399  return Center.GetHashCode() + Radius.GetHashCode();
400  }
401 
402  /// <summary>
403  /// Determines whether the specified <see cref="SiliconStudio.Core.Mathematics.Vector4"/> is equal to this instance.
404  /// </summary>
405  /// <param name="value">The <see cref="SiliconStudio.Core.Mathematics.Vector4"/> to compare with this instance.</param>
406  /// <returns>
407  /// <c>true</c> if the specified <see cref="SiliconStudio.Core.Mathematics.Vector4"/> is equal to this instance; otherwise, <c>false</c>.
408  /// </returns>
409  public bool Equals(BoundingSphere value)
410  {
411  return Center == value.Center && Radius == value.Radius;
412  }
413 
414  /// <summary>
415  /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
416  /// </summary>
417  /// <param name="value">The <see cref="System.Object"/> to compare with this instance.</param>
418  /// <returns>
419  /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
420  /// </returns>
421  public override bool Equals(object value)
422  {
423  if (value == null)
424  return false;
425 
426  if (value.GetType() != GetType())
427  return false;
428 
429  return Equals((BoundingSphere)value);
430  }
431 
432 #if SlimDX1xInterop
433  /// <summary>
434  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> to <see cref="SlimDX.BoundingSphere"/>.
435  /// </summary>
436  /// <param name="value">The value.</param>
437  /// <returns>The result of the conversion.</returns>
438  public static implicit operator SlimDX.BoundingSphere(BoundingSphere value)
439  {
440  return new SlimDX.BoundingSphere(value.Center, value.Radius);
441  }
442 
443  /// <summary>
444  /// Performs an implicit conversion from <see cref="SlimDX.BoundingSphere"/> to <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/>.
445  /// </summary>
446  /// <param name="value">The value.</param>
447  /// <returns>The result of the conversion.</returns>
448  public static implicit operator BoundingSphere(SlimDX.BoundingSphere value)
449  {
450  return new BoundingSphere(value.Center, value.Radius);
451  }
452 #endif
453 
454 #if SlimDX1xInterop
455  /// <summary>
456  /// Performs an implicit conversion from <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/> to <see cref="Microsoft.Xna.Framework.BoundingSphere"/>.
457  /// </summary>
458  /// <param name="value">The value.</param>
459  /// <returns>The result of the conversion.</returns>
460  public static implicit operator Microsoft.Xna.Framework.BoundingSphere(BoundingSphere value)
461  {
462  return new Microsoft.Xna.Framework.BoundingSphere(value.Center, value.Radius);
463  }
464 
465  /// <summary>
466  /// Performs an implicit conversion from <see cref="Microsoft.Xna.Framework.BoundingSphere"/> to <see cref="SiliconStudio.Core.Mathematics.BoundingSphere"/>.
467  /// </summary>
468  /// <param name="value">The value.</param>
469  /// <returns>The result of the conversion.</returns>
470  public static implicit operator BoundingSphere(Microsoft.Xna.Framework.BoundingSphere value)
471  {
472  return new BoundingSphere(value.Center, value.Radius);
473  }
474 #endif
475  }
476 }
Represents an axis-aligned bounding box in three dimensional space.
Definition: BoundingBox.cs:42
override int GetHashCode()
Returns a hash code for this instance.
override string ToString()
Returns a System.String that represents this instance.
static BoundingSphere Merge(BoundingSphere value1, BoundingSphere value2)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere that is the as large as the total combined...
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Definition: DirectXTexP.h:191
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
float Length()
Calculates the length of the vector.
Definition: Vector3.cs:195
string ToString(IFormatProvider formatProvider)
Returns a System.String that represents this instance.
bool Intersects(ref BoundingSphere sphere)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.BoundingSphere.
static void Merge(ref BoundingSphere value1, ref BoundingSphere value2, out BoundingSphere result)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere that is the as large as the total combined...
ContainmentType Contains(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
Determines whether the current objects contains a triangle.
Represents a bounding sphere in three dimensional space.
bool Intersects(ref Ray ray, out float distance)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.Ray.
static BoundingSphere FromPoints(Vector3[] points)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere that fully contains the given points...
static void FromBox(ref BoundingBox box, out BoundingSphere result)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere from a given box.
Represents a plane in three dimensional space.
Definition: Plane.cs:42
ContainmentType
Describes how one bounding volume contains another.
Vector3 Center
The center of the sphere in three dimensional space.
string ToString(string format)
Returns a System.String that represents this instance.
Represents a three dimensional line based on a point in space and a direction.
Definition: Ray.cs:42
static void FromPoints(Vector3[] points, out BoundingSphere result)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere that fully contains the given points...
PlaneIntersectionType
Describes the result of an intersection with a plane in three dimensions.
bool Intersects(ref Ray ray)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.Ray.
BoundingSphere(Vector3 center, float radius)
Initializes a new instance of the SiliconStudio.Core.Mathematics.BoundingBox struct.
bool Intersects(ref Vector3 vertex1, ref Vector3 vertex2, ref Vector3 vertex3)
Determines if there is an intersection between the current object and a triangle. ...
ContainmentType Contains(ref BoundingSphere sphere)
Determines whether the current objects contains a SiliconStudio.Core.Mathematics.BoundingSphere.
static BoundingSphere FromBox(BoundingBox box)
Constructs a SiliconStudio.Core.Mathematics.BoundingSphere from a given box.
bool Intersects(ref BoundingBox box)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.BoundingBox.
ContainmentType Contains(ref Vector3 point)
Determines whether the current objects contains a point.
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Definition: DirectXTexP.h:175
bool Intersects(ref Ray ray, out Vector3 point)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.Ray.
PlaneIntersectionType Intersects(ref Plane plane)
Determines if there is an intersection between the current object and a SiliconStudio.Core.Mathematics.Plane.
override bool Equals(object value)
Determines whether the specified System.Object is equal to this instance.
ContainmentType Contains(ref BoundingBox box)
Determines whether the current objects contains a SiliconStudio.Core.Mathematics.BoundingBox.
string ToString(string format, IFormatProvider formatProvider)
Returns a System.String that represents this instance.
bool Equals(BoundingSphere value)
Determines whether the specified SiliconStudio.Core.Mathematics.Vector4 is equal to this instance...
float Radius
The radious of the sphere.
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t size_t z
Definition: DirectXTexP.h:191