/// <summary> /// Creates the smallest BoundingSphere that can contain a specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to create the BoundingSphere from.</param><param name="result">[OutAttribute] The created BoundingSphere.</param> public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result) { // Find the center of the box. Vector3 center = new Vector3((box.Min.X + box.Max.X) / 2.0f, (box.Min.Y + box.Max.Y) / 2.0f, (box.Min.Z + box.Max.Z) / 2.0f); // Find the distance between the center and one of the corners of the box. float radius = Vector3.Distance(center, box.Max); result = new BoundingSphere(center, radius); }
/// <summary> /// Checks whether the current BoundingFrustum intersects a BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingFrustum and BoundingSphere intersect; false otherwise.</param> public void Intersects(ref BoundingSphere sphere, out bool result) { ContainmentType containment; Contains(ref sphere, out containment); result = containment != ContainmentType.Disjoint; }
/// <summary> /// Checks whether the current BoundingFrustum contains the specified BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingSphere sphere, out ContainmentType result) { CreatePlanes(); var intersects = false; for (var i = 0; i < PlaneCount; ++i) { PlaneIntersectionType planeIntersectionType; sphere.Intersects(ref _planes[i], out planeIntersectionType); switch (planeIntersectionType) { case PlaneIntersectionType.Front: result = ContainmentType.Disjoint; return; case PlaneIntersectionType.Intersecting: intersects = true; break; } } result = intersects ? ContainmentType.Intersects : ContainmentType.Contains; }
public bool Intersects(BoundingSphere sphere) { bool result; Intersects(ref sphere, out result); return result; }
public void AssertThat_Inflate_ByNegativeValue_DecreasesRadius() { BoundingSphere s = new BoundingSphere(Vector3.Zero, 10); Assert.AreEqual(5, s.Inflate(-10).Radius); }
/// <summary> /// Creates the smallest BoundingBox that will contain the specified BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to contain.</param><param name="result">[OutAttribute] The created BoundingBox.</param> public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result) { var corner = new Vector3(sphere.Radius); result.Min = sphere.Center - corner; result.Max = sphere.Center + corner; }
/// <summary> /// Tests whether the BoundingBox contains a BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingSphere sphere, out ContainmentType result) { if (sphere.Center.X - Min.X >= sphere.Radius && sphere.Center.Y - Min.Y >= sphere.Radius && sphere.Center.Z - Min.Z >= sphere.Radius && Max.X - sphere.Center.X >= sphere.Radius && Max.Y - sphere.Center.Y >= sphere.Radius && Max.Z - sphere.Center.Z >= sphere.Radius) { result = ContainmentType.Contains; return; } double dmin = 0; double e = sphere.Center.X - Min.X; if (e < 0) { if (e < -sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } else { e = sphere.Center.X - Max.X; if (e > 0) { if (e > sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } } e = sphere.Center.Y - Min.Y; if (e < 0) { if (e < -sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } else { e = sphere.Center.Y - Max.Y; if (e > 0) { if (e > sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } } e = sphere.Center.Z - Min.Z; if (e < 0) { if (e < -sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } else { e = sphere.Center.Z - Max.Z; if (e > 0) { if (e > sphere.Radius) { result = ContainmentType.Disjoint; return; } dmin += e * e; } } if (dmin <= sphere.Radius * sphere.Radius) { result = ContainmentType.Intersects; return; } result = ContainmentType.Disjoint; }
/// <summary> /// Creates a BoundingSphere that contains the two specified BoundingSphere instances. /// </summary> /// <param name="original">BoundingSphere to be merged.</param><param name="additional">BoundingSphere to be merged.</param><param name="result">[OutAttribute] The created BoundingSphere.</param> public static void CreateMerged(ref BoundingSphere original, ref BoundingSphere additional, out BoundingSphere result) { Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center); float distance = ocenterToaCenter.Length(); if (distance <= original.Radius + additional.Radius)//intersect { if (distance <= original.Radius - additional.Radius)//original contain additional { result = original; return; } if (distance <= additional.Radius - original.Radius)//additional contain original { result = additional; return; } } //else find center of new sphere and radius float leftRadius = Math.Max(original.Radius - distance, additional.Radius); float rightradius = Math.Max(original.Radius + distance, additional.Radius); ocenterToaCenter = ocenterToaCenter + (((leftRadius - rightradius) / (2 * ocenterToaCenter.Length())) * ocenterToaCenter);//oCenterToResultCenter result = new BoundingSphere { Center = original.Center + ocenterToaCenter, Radius = (leftRadius + rightradius) / 2 }; }
/// <summary> /// Expand bounding sphere diameter by distance /// </summary> /// <param name="sphere">The sphere to mutate</param> /// <param name="distance"></param> /// <returns></returns> public static void Inflate(ref BoundingSphere sphere, float distance) { var r = sphere.Radius + distance / 2; if (r < 0) throw new ArgumentOutOfRangeException("distance", "Distance specified to inflate sphere is a negative value larger than the total diameter (this would cause a negative radius!)"); sphere.Radius = r; }
/// <summary> /// Checks whether the current Ray intersects a BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to check for intersection with.</param><param name="result">[OutAttribute] Distance at which the ray intersects the BoundingSphere or null if there is no intersection.</param> public void Intersects(ref BoundingSphere sphere, out float? result) { // Find the vector between where the ray starts the the sphere's centre Vector3 difference = sphere.Center - Position; float differenceLengthSquared = difference.LengthSquared(); float sphereRadiusSquared = sphere.Radius * sphere.Radius; // If the distance between the ray start and the sphere's centre is less than // the radius of the sphere, it means we've intersected. N.B. checking the LengthSquared is faster. if (differenceLengthSquared < sphereRadiusSquared) { result = 0.0f; return; } var distanceAlongRay = Vector3.Dot(Direction, difference); // If the ray is pointing away from the sphere then we don't ever intersect if (distanceAlongRay < 0) { result = null; return; } // Next we kinda use Pythagoras to check if we are within the bounds of the sphere // if x = radius of sphere // if y = distance between ray position and sphere centre // if z = the distance we've travelled along the ray // if x^2 + z^2 - y^2 < 0, we do not intersect float dist = sphereRadiusSquared + distanceAlongRay * distanceAlongRay - differenceLengthSquared; result = (dist < 0) ? null : distanceAlongRay - (float?)Math.Sqrt(dist); }
/// <summary> /// Creates a BoundingSphere that contains the two specified BoundingSphere instances. /// </summary> /// <param name="original">BoundingSphere to be merged.</param><param name="additional">BoundingSphere to be merged.</param> public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional) { BoundingSphere result; CreateMerged(ref original, ref additional, out result); return result; }
/// <summary> /// Checks whether the Ray intersects a specified BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to check for intersection with the Ray.</param> public float? Intersects(BoundingSphere sphere) { float? result; Intersects(ref sphere, out result); return result; }
public IEnumerable<string> Intersections(BoundingSphere sphere) { return _model .Model .SkinningData .Bounds .Select((b, i) => { Matrix4x4 transform; Matrix4x4.Invert(_worldTransforms[i], out transform); var center = Vector3.Transform(sphere.Center, transform); //Transform sphere center into bone space var intersects = b.Intersects(new BoundingSphere(center, sphere.Radius)); //Intersect new sphere in bone space var name = _model.Model.SkinningData.Names[i]; return new KeyValuePair<bool, string>(intersects, name); }) .Where(a => a.Key) .Select(a => a.Value); }
public void AssertThat_Inflate_IncreasesRadius() { BoundingSphere s = new BoundingSphere(Vector3.Zero, 10); Assert.AreEqual(15, s.Inflate(10).Radius); }
public static void AddBoundingSphere(BoundingSphere sphere, Color color, float life = 0f) { // Get a DebugShape we can use to draw the sphere DebugShape shape = GetShapeForLines(SPHERE_LINE_COUNT, life); // Iterate our unit sphere vertices for (int i = 0; i < _unitSphere.Length; i++) { // Compute the vertex position by transforming the point by the radius and center of the sphere Vector3 vertPos = _unitSphere[i] * sphere.Radius + sphere.Center; // Add the vertex to the shape shape.Vertices[i] = new VertexPositionColor(vertPos.ToXNA(), color); } }
/// <summary> /// Checks whether the current BoundingSphere contains the specified BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingSphere sphere, out ContainmentType result) { float sqDistance = Vector3.DistanceSquared(sphere.Center, Center); if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius)) result = ContainmentType.Disjoint; else if (sqDistance <= (Radius - sphere.Radius) * (Radius - sphere.Radius)) result = ContainmentType.Contains; else result = ContainmentType.Intersects; }
/// <summary> /// Creates the smallest BoundingBox that will contain the specified BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to contain.</param> public static BoundingBox CreateFromSphere(BoundingSphere sphere) { BoundingBox result; CreateFromSphere(ref sphere, out result); return result; }
/// <summary> /// Determines whether the specified BoundingSphere is equal to the current BoundingSphere. /// </summary> /// <param name="other">The BoundingSphere to compare with the current BoundingSphere.</param> public bool Equals(BoundingSphere other) { return Radius.Equals(other.Radius) && Center.Equals(other.Center); }
public ContainmentType Contains(BoundingSphere sphere) { ContainmentType result; Contains(ref sphere, out result); return result; }
/// <summary> /// Checks whether the current BoundingSphere intersects another BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingSphere instances intersect; false otherwise.</param> public void Intersects(ref BoundingSphere sphere, out bool result) { float sqDistance = Vector3.DistanceSquared(sphere.Center, Center); var totalRadius = sphere.Radius + Radius; result = sqDistance < totalRadius * totalRadius; }
/// <summary> /// Creates an instance of BoundingBox around a BoundingSphere /// </summary> /// <param name="sphere">The sphere to constain within this box</param> public BoundingBox(BoundingSphere sphere) : this(sphere.Center - new Vector3(sphere.Radius), sphere.Center + new Vector3(sphere.Radius)) { }
/// <summary> /// Translates and scales the BoundingSphere using a given Matrix. /// </summary> /// <param name="matrix">A transformation matrix that might include translation, rotation, or uniform scaling. Note that BoundingSphere.Transform will not return correct results if there are non-uniform scaling, shears, or other unusual transforms in this transformation matrix. This is because there is no way to shear or non-uniformly scale a sphere. Such an operation would cause the sphere to lose its shape as a sphere.</param><param name="result">[OutAttribute] The transformed BoundingSphere.</param> public void Transform(ref Matrix4x4 matrix, out BoundingSphere result) { result.Center = Vector3.Transform(Center, matrix); result.Radius = Radius * ((float)Math.Sqrt(Math.Max(((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), Math.Max(((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33))))); }
/// <summary> /// Checks whether the current BoundingBox intersects a BoundingSphere. /// </summary> /// <param name="sphere">The BoundingSphere to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingBox and BoundingSphere intersect; false otherwise.</param> public void Intersects(ref BoundingSphere sphere, out bool result) { if (sphere.Center.X - Min.X > sphere.Radius && sphere.Center.Y - Min.Y > sphere.Radius && sphere.Center.Z - Min.Z > sphere.Radius && Max.X - sphere.Center.X > sphere.Radius && Max.Y - sphere.Center.Y > sphere.Radius && Max.Z - sphere.Center.Z > sphere.Radius) { result = true; return; } double dmin = 0; if (sphere.Center.X - Min.X <= sphere.Radius) dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X); else if (Max.X - sphere.Center.X <= sphere.Radius) dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X); if (sphere.Center.Y - Min.Y <= sphere.Radius) dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y); else if (Max.Y - sphere.Center.Y <= sphere.Radius) dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y); if (sphere.Center.Z - Min.Z <= sphere.Radius) dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z); else if (Max.Z - sphere.Center.Z <= sphere.Radius) dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z); if (dmin <= sphere.Radius * sphere.Radius) { result = true; return; } result = false; }
public void AssertThat_Inflate_ByNegativeValueLargerThanDiameter_Throws() { BoundingSphere s = new BoundingSphere(Vector3.Zero, 10); var result = s.Inflate(-50); }