public void AssertThat_Inflate_IncreasesSize() { BoundingBox s = new BoundingBox(new Vector3(0), new Vector3(10)); Assert.AreEqual(new Vector3(-5), s.Inflate(10).Min); Assert.AreEqual(new Vector3(15), s.Inflate(10).Max); }
public void AssertThat_Inflate_ByNegativeValue_DecreasesSize() { BoundingBox s = new BoundingBox(new Vector3(0), new Vector3(10)); Assert.AreEqual(new Vector3(3), s.Inflate(-6).Min); Assert.AreEqual(new Vector3(7), s.Inflate(-6).Max); }
/// <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); }
private BoundingRectangle CalculateScreenSpaceBounds(IGeometry item, View view) { //Create a bounding box around this geometry var box = new BoundingBox(item.BoundingSphere); box.GetCorners(_corners); //Multiply box corners by WVP matrix to move into screen space for (int i = 0; i < _corners.Length; i++) { //Why is world matrix Identity? //THe bounding sphere is already in world space, we don't need to apply it again! _corners[i] = view.Viewport.Project(_corners[i].ToXNA(), view.Camera.Projection.ToXNA(), view.Camera.View.ToXNA(), Microsoft.Xna.Framework.Matrix.Identity).FromXNA(); _corners2D[i] = _corners[i].XY(); } //Find a rectangle around this box var rect = BoundingRectangle.CreateFromPoints(_corners2D); return rect; }
internal Node(Octree octree, Node parent, BoundingBox bounds) { Octree = octree; Parent = parent; Bounds = bounds; }
private BoundingRectangle CalculateScreenSpaceBounds(IGeometry item, View view) { //Create a bounding box around this geometry var box = new BoundingBox(item.BoundingSphere); var corners = box.GetCorners(); //Multiply box corners by WVP matrix to move into screen space for (int i = 0; i < corners.Length; i++) { corners[i] = view.Viewport.Project(corners[i].ToXNA(), view.Camera.Projection.ToXNA(), view.Camera.View.ToXNA(), Matrix.Identity).FromXNA(); } //Find a rectangle around this box var rect = BoundingRectangle.CreateFromPoints(corners.Select(a => a.XY())); return rect; }
public void AssertThat_InflateSphere_ByNegativeValueLargerThanSize_Throws() { BoundingBox s = new BoundingBox(Vector3.Zero, new Vector3(10)); var result = s.Inflate(-50); }
/// <summary> /// Checks whether the current Ray intersects a BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with.</param><param name="result">[OutAttribute] Distance at which the ray intersects the BoundingBox or null if there is no intersection.</param> public void Intersects(ref BoundingBox box, out float? result) { const float EPSILON = 1e-6f; float? tMin = null, tMax = null; if (Math.Abs(Direction.X) < EPSILON) { if (Position.X < box.Min.X || Position.X > box.Max.X) { result = null; return; } } else { tMin = (box.Min.X - Position.X) / Direction.X; tMax = (box.Max.X - Position.X) / Direction.X; if (tMin > tMax) { var temp = tMin; tMin = tMax; tMax = temp; } } if (Math.Abs(Direction.Y) < EPSILON) { if (Position.Y < box.Min.Y || Position.Y > box.Max.Y) { result = null; return; } } else { var tMinY = (box.Min.Y - Position.Y) / Direction.Y; var tMaxY = (box.Max.Y - Position.Y) / Direction.Y; if (tMinY > tMaxY) { var temp = tMinY; tMinY = tMaxY; tMaxY = temp; } if ((tMin.HasValue && tMin > tMaxY) || (tMax.HasValue && tMinY > tMax)) { result = null; return; } if (!tMin.HasValue || tMinY > tMin) tMin = tMinY; if (!tMax.HasValue || tMaxY < tMax) tMax = tMaxY; } if (Math.Abs(Direction.Z) < EPSILON) { if (Position.Z < box.Min.Z || Position.Z > box.Max.Z) { result = null; return; } } else { var tMinZ = (box.Min.Z - Position.Z) / Direction.Z; var tMaxZ = (box.Max.Z - Position.Z) / Direction.Z; if (tMinZ > tMaxZ) { var temp = tMinZ; tMinZ = tMaxZ; tMaxZ = temp; } if ((tMin.HasValue && tMin > tMaxZ) || (tMax.HasValue && tMinZ > tMax)) { result = null; return; } if (!tMin.HasValue || tMinZ > tMin) tMin = tMinZ; if (!tMax.HasValue || tMaxZ < tMax) tMax = tMaxZ; } // having a positive tMin and a negative tMax means the ray is inside the box // we expect the intesection distance to be 0 in that case if ((tMin.HasValue && tMin < 0) && tMax > 0) { result = 0; return; } // a negative tMin means that the intersection point is behind the ray's origin // we discard these as not hitting the AABB if (tMin < 0) { result = null; return; } result = tMin; }
public static void AddBoundingBox(BoundingBox box, Color color, float life = 0f) { // Get a DebugShape we can use to draw the box DebugShape shape = GetShapeForLines(12, life); // Get the corners of the box box.GetCorners(_corners); // Fill in the vertices for the bottom of the box shape.Vertices[0] = new VertexPositionColor(_corners[0].ToXNA(), color); shape.Vertices[1] = new VertexPositionColor(_corners[1].ToXNA(), color); shape.Vertices[2] = new VertexPositionColor(_corners[1].ToXNA(), color); shape.Vertices[3] = new VertexPositionColor(_corners[2].ToXNA(), color); shape.Vertices[4] = new VertexPositionColor(_corners[2].ToXNA(), color); shape.Vertices[5] = new VertexPositionColor(_corners[3].ToXNA(), color); shape.Vertices[6] = new VertexPositionColor(_corners[3].ToXNA(), color); shape.Vertices[7] = new VertexPositionColor(_corners[0].ToXNA(), color); // Fill in the vertices for the top of the box shape.Vertices[8] = new VertexPositionColor(_corners[4].ToXNA(), color); shape.Vertices[9] = new VertexPositionColor(_corners[5].ToXNA(), color); shape.Vertices[10] = new VertexPositionColor(_corners[5].ToXNA(), color); shape.Vertices[11] = new VertexPositionColor(_corners[6].ToXNA(), color); shape.Vertices[12] = new VertexPositionColor(_corners[6].ToXNA(), color); shape.Vertices[13] = new VertexPositionColor(_corners[7].ToXNA(), color); shape.Vertices[14] = new VertexPositionColor(_corners[7].ToXNA(), color); shape.Vertices[15] = new VertexPositionColor(_corners[4].ToXNA(), color); // Fill in the vertices for the vertical sides of the box shape.Vertices[16] = new VertexPositionColor(_corners[0].ToXNA(), color); shape.Vertices[17] = new VertexPositionColor(_corners[4].ToXNA(), color); shape.Vertices[18] = new VertexPositionColor(_corners[1].ToXNA(), color); shape.Vertices[19] = new VertexPositionColor(_corners[5].ToXNA(), color); shape.Vertices[20] = new VertexPositionColor(_corners[2].ToXNA(), color); shape.Vertices[21] = new VertexPositionColor(_corners[6].ToXNA(), color); shape.Vertices[22] = new VertexPositionColor(_corners[3].ToXNA(), color); shape.Vertices[23] = new VertexPositionColor(_corners[7].ToXNA(), color); }
/// <summary> /// Tests whether the BoundingBox contains a BoundingBox. /// </summary> /// <param name="box">The BoundingBox to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingBox box, out ContainmentType result) { //test if all corner is in the same side of a face by just checking min and max if (box.Max.X < Min.X || box.Min.X > Max.X || box.Max.Y < Min.Y || box.Min.Y > Max.Y || box.Max.Z < Min.Z || box.Min.Z > Max.Z) { result = ContainmentType.Disjoint; return; } if (box.Min.X >= Min.X && box.Max.X <= Max.X && box.Min.Y >= Min.Y && box.Max.Y <= Max.Y && box.Min.Z >= Min.Z && box.Max.Z <= Max.Z) { result = ContainmentType.Contains; return; } result = ContainmentType.Intersects; }
public bool Intersects(BoundingBox box) { bool result; Intersects(ref box, out result); return result; }
/// <summary> /// Creates the smallest BoundingBox that contains the two specified BoundingBox instances. /// </summary> /// <param name="original">One of the BoundingBoxs to contain.</param><param name="additional">One of the BoundingBoxs to contain.</param> public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional) { BoundingBox result; CreateMerged(ref original, ref additional, out result); return result; }
/// <summary> /// Expand bounding box by distance / 2 at min and max (total of distance) /// </summary> /// <param name="box">The box to mutate</param> /// <param name="distance"></param> /// <returns></returns> public static void Inflate(ref BoundingBox box, float distance) { var min = box.Min - new Vector3(distance / 2); var max = box.Max + new Vector3(distance / 2); if (distance < 0) { if (Vector3.Min(min, max) != min) throw new ArgumentOutOfRangeException("distance", "Distance specified to inflate rectangle is a negative value larger than the total diagonal size of the rectangle (doing this would invert the rectangle!"); } box.Min = min; box.Max = max; }
/// <summary> /// Checks whether the current BoundingFrustum intersects a BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingFrustum and BoundingBox intersect; false otherwise.</param> public void Intersects(ref BoundingBox box, out bool result) { ContainmentType containment; Contains(ref box, out containment); result = containment != ContainmentType.Disjoint; }
/// <summary> /// Checks whether the current BoundingSphere contains the specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingBox box, out ContainmentType result) { //check if all corner is in sphere bool inside = true; foreach (Vector3 corner in box.GetCorners()) { if (Contains(corner) == ContainmentType.Disjoint) { inside = false; break; } } if (inside) { result = ContainmentType.Contains; return; } //check if the distance from sphere center to cube face < radius double dmin = 0; if (Center.X < box.Min.X) dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X); else if (Center.X > box.Max.X) dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X); if (Center.Y < box.Min.Y) dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y); else if (Center.Y > box.Max.Y) dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y); if (Center.Z < box.Min.Z) dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z); else if (Center.Z > box.Max.Z) dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z); if (dmin <= Radius * Radius) { result = ContainmentType.Intersects; return; } //else disjoint result = ContainmentType.Disjoint; }
/// <summary> /// Checks whether the current BoundingFrustum contains the specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to test for overlap.</param><param name="result">[OutAttribute] Enumeration indicating the extent of overlap.</param> public void Contains(ref BoundingBox box, out ContainmentType result) { CreatePlanes(); var intersects = false; for (var i = 0; i < PlaneCount; ++i) { PlaneIntersectionType planeIntersectionType; box.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; }
private void Update() { _axisAligned = _bounds.Transform(ref _transform); _dirty = false; }
/// <summary> /// Checks whether the current BoundingSphere intersects with a specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with the current BoundingSphere.</param> public bool Intersects(BoundingBox box) { return box.Intersects(this); }
/// <summary> /// Creates the smallest BoundingSphere that can contain a specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to create the BoundingSphere from.</param> public static BoundingSphere CreateFromBoundingBox(BoundingBox box) { BoundingSphere result; CreateFromBoundingBox(ref box, out result); return result; }
/// <summary> /// Checks whether the current BoundingSphere intersects a BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingSphere and BoundingBox intersect; false otherwise.</param> public void Intersects(ref BoundingBox box, out bool result) { result = box.Intersects(this); }
/// <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> /// Fetches all nodes (including non leaf nodes) which intersect the given bounds /// </summary> /// <param name="bounds"></param> /// <returns></returns> public IEnumerable<Node> NodesOverlappingBounds(BoundingBox bounds) { if (!bounds.Intersects(Bounds)) yield break; yield return this; if (_children != null) foreach (var descendant in _children.SelectMany(c => c.NodesOverlappingBounds(bounds))) yield return descendant; }
/// <summary> /// Creates the smallest BoundingBox that contains the two specified BoundingBox instances. /// </summary> /// <param name="original">One of the BoundingBox instances to contain.</param><param name="additional">One of the BoundingBox instances to contain.</param><param name="result">[OutAttribute] The created BoundingBox.</param> public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result) { result = new BoundingBox( Vector3.Min(original.Min, additional.Min), Vector3.Max(original.Max, additional.Max) ); }
/// <summary> /// Construct a new octree with a single root node covering the given bounds /// </summary> /// <param name="bounds"></param> /// <param name="childFactory"></param> public Octree(BoundingBox bounds, Func<Octree, Node, BoundingBox, Node> childFactory) { _childFactory = childFactory; Root = _childFactory(this, null, bounds); }
public ContainmentType Contains(BoundingBox box) { ContainmentType result; Contains(ref box, out result); return result; }
/// <summary> /// Get all nodes overlapping the bounds /// </summary> /// <param name="bounds"></param> /// <returns></returns> public IEnumerable<Node> NodesOverlappingBounds(BoundingBox bounds) { return Root.NodesOverlappingBounds(bounds); }
public bool Equals(BoundingBox other) { return Min.Equals(other.Min) && Max.Equals(other.Max); }
private Node CreateChild(Node parent, BoundingBox bounds) { return _childFactory(this, parent, bounds); }
/// <summary> /// Checks whether the current BoundingBox intersects another BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with.</param><param name="result">[OutAttribute] true if the BoundingBox instances intersect; false otherwise.</param> public void Intersects(ref BoundingBox box, out bool result) { result = box.Min.X < Max.X && box.Max.X > Min.X && box.Min.Y < Max.Y && box.Max.Y > Min.Y && box.Min.Z < Max.Z && box.Max.Z > Min.Z; }
//public float DistanceToPoint(Vector3 point) //{ //} //public void DistanceToPoint(ref Vector3 point, out float distance) //{ //float result; //DistanceToPoint(ref point, out result); //return result; //} //public RayRayIntersection? Intersects(Ray3 ray, out Parallelism parallelism) //{ //} //public RayRayIntersection? Intersects(Ray3 ray) //{ //} //public struct RayRayIntersection //{ // /// <summary> // /// The position where the two rays intersect // /// </summary> // public readonly Vector3 Position; // /// <summary> // /// The distance along ray A. Units are in ray lengths, so 0 indicates the start, 1 indicates the end. // /// </summary> // public readonly float DistanceAlongA; // /// <summary> // /// The distance along ray B. Units are in ray lengths, so 0 indicates the start, 1 indicates the end. // /// </summary> // public readonly float DistanceAlongB; // public RayRayIntersection(Vector3 position, float distanceAlongLineA, float distanceAlongLineB) // { // Position = position; // DistanceAlongA = distanceAlongLineA; // DistanceAlongB = distanceAlongLineB; // } //} /// <summary> /// Checks whether the Ray intersects a specified BoundingBox. /// </summary> /// <param name="box">The BoundingBox to check for intersection with the Ray.</param> public float? Intersects(BoundingBox box) { float? result; Intersects(ref box, out result); return result; }