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);
        }
Example #4
0
        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;
        }
Example #5
0
 internal Node(Octree octree, Node parent, BoundingBox bounds)
 {
     Octree = octree;
     Parent = parent;
     Bounds = bounds;
 }
Example #6
0
        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);
        }
Example #8
0
        /// <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;
        }
Example #9
0
		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;
        }
Example #17
0
 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;
 }
Example #22
0
            /// <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)
     );
 }
Example #24
0
 /// <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;
 }
Example #26
0
 /// <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);
 }
Example #28
0
 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;
 }
Example #30
0
 //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;
 }