Exemple #1
0
        /// <summary>
        ///     Calculates an OBB with a given set of points.
        ///     Tests every orientations between initValues and endValues, stepping through angle intervals with a given step size.
        ///     Goes on until it reaches a step less than 0.01
        /// </summary>
        /// <returns>A generated Oriented Bounding Box that contains the set of points</returns>
        private static OrientedBoundingBox ComputeFromPointsRecursive(Vector3[] points, Vector3 initValues, Vector3 endValues,
                                                                      float step)
        {
            var   minObb = new OrientedBoundingBox();
            var   minimumVolume = float.MaxValue;
            var   minInitValues = Vector3.Zero;
            var   minEndValues = Vector3.Zero;
            var   transformedPoints = new Vector3[points.Length];
            float y, z;

            var x = initValues.X;

            while (x <= endValues.X)
            {
                y = initValues.Y;
                var rotationX = MathHelper.ToRadians(x);
                while (y <= endValues.Y)
                {
                    z = initValues.Z;
                    var rotationY = MathHelper.ToRadians(y);
                    while (z <= endValues.Z)
                    {
                        // Rotation matrix
                        var rotationZ      = MathHelper.ToRadians(z);
                        var rotationMatrix = Matrix.CreateFromYawPitchRoll(rotationY, rotationX, rotationZ);

                        // Transform every point to OBB-Space
                        for (var index = 0; index < transformedPoints.Length; index++)
                        {
                            transformedPoints[index] = Vector3.Transform(points[index], rotationMatrix);
                        }

                        // Obtain an AABB enclosing every transformed point
                        var aabb = BoundingBox.CreateFromPoints(transformedPoints);

                        // Calculate the volume of the AABB
                        var volume = BoundingVolumesExtensions.GetVolume(aabb);

                        // Find lesser volume
                        if (volume < minimumVolume)
                        {
                            minimumVolume = volume;
                            minInitValues = new Vector3(x, y, z);
                            minEndValues  = new Vector3(x + step, y + step, z + step);

                            // Restore the AABB center in World-Space
                            var center = BoundingVolumesExtensions.GetCenter(aabb);
                            center = Vector3.Transform(center, rotationMatrix);

                            // Create OBB
                            minObb             = new OrientedBoundingBox(center, BoundingVolumesExtensions.GetExtents(aabb));
                            minObb.Orientation = rotationMatrix;
                        }

                        z += step;
                    }
                    y += step;
                }
                x += step;
            }

            // Loop again if the step is higher than a given acceptance threshold
            if (step > 0.01f)
            {
                minObb = ComputeFromPointsRecursive(points, minInitValues, minEndValues, step / 10f);
            }

            return(minObb);
        }
Exemple #2
0
        /// <summary>
        ///     Tests if this OBB intersects with another OBB.
        /// </summary>
        /// <param name="box">The other OBB to test</param>
        /// <returns>True if the two boxes intersect</returns>
        public bool Intersects(OrientedBoundingBox box)
        {
            float ra;
            float rb;
            var   R    = new float[3, 3];
            var   AbsR = new float[3, 3];
            var   ae   = ToArray(Extents);
            var   be   = ToArray(box.Extents);

            // Compute rotation matrix expressing the other box in this box coordinate frame

            var result = ToFloatArray(Matrix.Multiply(Orientation, box.Orientation));

            for (var i = 0; i < 3; i++)
            {
                for (var j = 0; j < 3; j++)
                {
                    R[i, j] = result[i * 3 + j];
                }
            }


            // Compute translation vector t
            var tVec = box.Center - Center;

            // Bring translation into this boxs coordinate frame

            var t = ToArray(Vector3.Transform(tVec, Orientation));

            // Compute common subexpressions. Add in an epsilon term to
            // counteract arithmetic errors when two edges are parallel and
            // their cross product is (near) null (see text for details)

            for (var i = 0; i < 3; i++)
            {
                for (var j = 0; j < 3; j++)
                {
                    AbsR[i, j] = MathF.Abs(R[i, j]) + float.Epsilon;
                }
            }

            // Test axes L = A0, L = A1, L = A2
            for (var i = 0; i < 3; i++)
            {
                ra = ae[i];
                rb = be[0] * AbsR[i, 0] + be[1] * AbsR[i, 1] + be[2] * AbsR[i, 2];
                if (MathF.Abs(t[i]) > ra + rb)
                {
                    return(false);
                }
            }

            // Test axes L = B0, L = B1, L = B2
            for (var i = 0; i < 3; i++)
            {
                ra = ae[0] * AbsR[0, i] + ae[1] * AbsR[1, i] + ae[2] * AbsR[2, i];
                rb = be[i];
                if (MathF.Abs(t[0] * R[0, i] + t[1] * R[1, i] + t[2] * R[2, i]) > ra + rb)
                {
                    return(false);
                }
            }

            // Test axis L = A0 x B0
            ra = ae[1] * AbsR[2, 0] + ae[2] * AbsR[1, 0];
            rb = be[1] * AbsR[0, 2] + be[2] * AbsR[0, 1];
            if (MathF.Abs(t[2] * R[1, 0] - t[1] * R[2, 0]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A0 x B1
            ra = ae[1] * AbsR[2, 1] + ae[2] * AbsR[1, 1];
            rb = be[0] * AbsR[0, 2] + be[2] * AbsR[0, 0];
            if (MathF.Abs(t[2] * R[1, 1] - t[1] * R[2, 1]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A0 x B2
            ra = ae[1] * AbsR[2, 2] + ae[2] * AbsR[1, 2];
            rb = be[0] * AbsR[0, 1] + be[1] * AbsR[0, 0];
            if (MathF.Abs(t[2] * R[1, 2] - t[1] * R[2, 2]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A1 x B0
            ra = ae[0] * AbsR[2, 0] + ae[2] * AbsR[0, 0];
            rb = be[1] * AbsR[1, 2] + be[2] * AbsR[1, 1];
            if (MathF.Abs(t[0] * R[2, 0] - t[2] * R[0, 0]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A1 x B1
            ra = ae[0] * AbsR[2, 1] + ae[2] * AbsR[0, 1];
            rb = be[0] * AbsR[1, 2] + be[2] * AbsR[1, 0];
            if (MathF.Abs(t[0] * R[2, 1] - t[2] * R[0, 1]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A1 x B2
            ra = ae[0] * AbsR[2, 2] + ae[2] * AbsR[0, 2];
            rb = be[0] * AbsR[1, 1] + be[1] * AbsR[1, 0];
            if (MathF.Abs(t[0] * R[2, 2] - t[2] * R[0, 2]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A2 x B0
            ra = ae[0] * AbsR[1, 0] + ae[1] * AbsR[0, 0];
            rb = be[1] * AbsR[2, 2] + be[2] * AbsR[2, 1];
            if (MathF.Abs(t[1] * R[0, 0] - t[0] * R[1, 0]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A2 x B1
            ra = ae[0] * AbsR[1, 1] + ae[1] * AbsR[0, 1];
            rb = be[0] * AbsR[2, 2] + be[2] * AbsR[2, 0];
            if (MathF.Abs(t[1] * R[0, 1] - t[0] * R[1, 1]) > ra + rb)
            {
                return(false);
            }

            // Test axis L = A2 x B2
            ra = ae[0] * AbsR[1, 2] + ae[1] * AbsR[0, 2];
            rb = be[0] * AbsR[2, 1] + be[1] * AbsR[2, 0];
            if (MathF.Abs(t[1] * R[0, 2] - t[0] * R[1, 2]) > ra + rb)
            {
                return(false);
            }

            // Since no separating axis is found, the OBBs must be intersecting
            return(true);
        }