Пример #1
0
        /// <summary>
        /// Caculates the matrix required to transfer any point from one <see cref="OrientedBoundingBox"/> local corrdinates to another.
        /// </summary>
        /// <param name="A">The source OrientedBoundingBox.</param>
        /// <param name="B">The target OrientedBoundingBox.</param>
        /// <param name="NoMatrixScaleApplied">
        /// If true, the method will use a fast algorithm which is inapplicable if a scale is applied to the transformation matrix of the OrientedBoundingBox.
        /// </param>
        /// <returns></returns>
        public static Matrix4x4 GetBoxToBoxMatrix(ref OrientedBoundingBox A, ref OrientedBoundingBox B, bool NoMatrixScaleApplied = false)
        {
            Matrix4x4 AtoB_Matrix;

            // Calculate B to A transformation matrix
            if (NoMatrixScaleApplied)
            {
                var RotA = GetRows(ref A.Transformation);
                var RotB = GetRows(ref B.Transformation);
                AtoB_Matrix = new Matrix4x4();
                int i, k;
                for (i = 0; i < 3; i++)
                {
                    for (k = 0; k < 3; k++)
                    {
                        Matrix4x4Ex.SetValue(AtoB_Matrix, i, k, Vector3.Dot(RotB[i], RotA[k]));
                    }
                }

                var v = B.Center - A.Center;
                AtoB_Matrix.M41 = Vector3.Dot(v, RotA[0]);
                AtoB_Matrix.M42 = Vector3.Dot(v, RotA[1]);
                AtoB_Matrix.M43 = Vector3.Dot(v, RotA[2]);
                AtoB_Matrix.M44 = 1;
            }
            else
            {
                Matrix4x4 AInvMat;
                Matrix4x4.Invert(A.Transformation, out AInvMat);
                AtoB_Matrix = B.Transformation * AInvMat;
            }

            return(AtoB_Matrix);
        }
Пример #2
0
        /// <summary>
        /// Check the intersection between an <see cref="OrientedBoundingBox"/> and <see cref="BoundingBox"/>
        /// </summary>
        /// <param name="box">The BoundingBox to test.</param>
        /// <returns>The type of containment the two objects have.</returns>
        /// <remarks>
        /// For accuracy, The transformation matrix for the <see cref="OrientedBoundingBox"/> must not have any scaling applied to it.
        /// Anyway, scaling using Scale method will keep this method accurate.
        /// </remarks>
        public ContainmentType Contains(ref BoundingBox box)
        {
            var cornersCheck = this.Contains(box.GetCorners());

            if (cornersCheck != ContainmentType.Disjoint)
            {
                return(cornersCheck);
            }

            var boxCenter  = box.Minimum + (box.Maximum - box.Minimum) / 2f;
            var boxExtents = box.Maximum - boxCenter;

            var SizeA = Extents;
            var SizeB = boxExtents;
            var RotA  = GetRows(ref Transformation);

            float ExtentA, ExtentB, Separation;
            int   i, k;

            Matrix4x4 R;                   // Rotation from B to A

            Matrix4x4.Invert(Transformation, out R);
            var AR = new Matrix4x4();      // absolute values of R matrix, to use with box extents

            for (i = 0; i < 3; i++)
            {
                for (k = 0; k < 3; k++)
                {
                    Matrix4x4Ex.SetValue(AR, i, k, Math.Abs(Matrix4x4Ex.GetValue(R, i, k)));
                }
            }


            // Vector separating the centers of Box B and of Box A
            var vSepWS = boxCenter - this.Center;
            // Rotated into Box A's coordinates
            var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2]));

            // Test if any of A's basis vectors separate the box
            for (i = 0; i < 3; i++)
            {
                ExtentA = SizeA.GetValue(i);
                ExtentB = Vector3.Dot(SizeB, new Vector3(
                                          Matrix4x4Ex.GetValue(AR, i, 0),
                                          Matrix4x4Ex.GetValue(AR, i, 1),
                                          Matrix4x4Ex.GetValue(AR, i, 2)));
                Separation = Math.Abs(vSepA.GetValue(i));

                if (Separation > ExtentA + ExtentB)
                {
                    return(ContainmentType.Disjoint);
                }
            }

            // Test if any of B's basis vectors separate the box
            for (k = 0; k < 3; k++)
            {
                ExtentA = Vector3.Dot(SizeA, new Vector3(
                                          Matrix4x4Ex.GetValue(AR, 0, k),
                                          Matrix4x4Ex.GetValue(AR, 1, k),
                                          Matrix4x4Ex.GetValue(AR, 2, k)));
                ExtentB    = SizeB.GetValue(k);
                Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(
                                                      Matrix4x4Ex.GetValue(R, 0, k),
                                                      Matrix4x4Ex.GetValue(R, 1, k),
                                                      Matrix4x4Ex.GetValue(R, 2, k))));

                if (Separation > ExtentA + ExtentB)
                {
                    return(ContainmentType.Disjoint);
                }
            }

            // Now test Cross Products of each basis vector combination ( A[i], B[k] )
            for (i = 0; i < 3; i++)
            {
                for (k = 0; k < 3; k++)
                {
                    int i1 = (i + 1) % 3, i2 = (i + 2) % 3;
                    int k1 = (k + 1) % 3, k2 = (k + 2) % 3;
                    ExtentA =
                        SizeA.GetValue(i1) * Matrix4x4Ex.GetValue(AR, i2, k) +
                        SizeA.GetValue(i2) * Matrix4x4Ex.GetValue(AR, i1, k);
                    ExtentB =
                        SizeB.GetValue(k1) * Matrix4x4Ex.GetValue(AR, i, k2) +
                        SizeB.GetValue(k2) * Matrix4x4Ex.GetValue(AR, i, k1);
                    Separation = Math.Abs(
                        vSepA.GetValue(i2) * Matrix4x4Ex.GetValue(R, i1, k) -
                        vSepA.GetValue(i1) * Matrix4x4Ex.GetValue(R, i2, k));
                    if (Separation > ExtentA + ExtentB)
                    {
                        return(ContainmentType.Disjoint);
                    }
                }
            }

            // No separating axis found, the boxes overlap
            return(ContainmentType.Intersects);
        }
Пример #3
0
        /// <summary>
        /// Check the intersection between two <see cref="OrientedBoundingBox"/>
        /// </summary>
        /// <param name="obb">The OrientedBoundingBoxs to test.</param>
        /// <returns>The type of containment the two objects have.</returns>
        /// <remarks>
        /// For accuracy, The transformation matrix for both <see cref="OrientedBoundingBox"/> must not have any scaling applied to it.
        /// Anyway, scaling using Scale method will keep this method accurate.
        /// </remarks>
        public ContainmentType Contains(ref OrientedBoundingBox obb)
        {
            var cornersCheck = this.Contains(obb.GetCorners());

            if (cornersCheck != ContainmentType.Disjoint)
            {
                return(cornersCheck);
            }

            //http://www.3dkingdoms.com/weekly/bbox.cpp
            var SizeA = Extents;
            var SizeB = obb.Extents;
            var RotA  = GetRows(ref Transformation);
            var RotB  = GetRows(ref obb.Transformation);

            var R  = new Matrix4x4();      // Rotation from B to A
            var AR = new Matrix4x4();      // absolute values of R matrix, to use with box extents

            float ExtentA, ExtentB, Separation;
            int   i, k;

            // Calculate B to A rotation matrix
            for (i = 0; i < 3; i++)
            {
                for (k = 0; k < 3; k++)
                {
                    Matrix4x4Ex.SetValue(R, i, k, Vector3.Dot(RotA[i], RotB[k]));
                    Matrix4x4Ex.SetValue(AR, i, k, Math.Abs(Matrix4x4Ex.GetValue(R, i, k)));
                }
            }


            // Vector separating the centers of Box B and of Box A
            var vSepWS = obb.Center - this.Center;
            // Rotated into Box A's coordinates
            var vSepA = new Vector3(Vector3.Dot(vSepWS, RotA[0]), Vector3.Dot(vSepWS, RotA[1]), Vector3.Dot(vSepWS, RotA[2]));

            // Test if any of A's basis vectors separate the box
            for (i = 0; i < 3; i++)
            {
                ExtentA = SizeA.GetValue(i);
                ExtentB = Vector3.Dot(SizeB, new Vector3(
                                          Matrix4x4Ex.GetValue(AR, i, 0),
                                          Matrix4x4Ex.GetValue(AR, i, 1),
                                          Matrix4x4Ex.GetValue(AR, i, 2)));
                Separation = Math.Abs(vSepA.GetValue(i));

                if (Separation > ExtentA + ExtentB)
                {
                    return(ContainmentType.Disjoint);
                }
            }

            // Test if any of B's basis vectors separate the box
            for (k = 0; k < 3; k++)
            {
                ExtentA = Vector3.Dot(SizeA, new Vector3(
                                          Matrix4x4Ex.GetValue(AR, 0, k),
                                          Matrix4x4Ex.GetValue(AR, 1, k),
                                          Matrix4x4Ex.GetValue(AR, 2, k)));
                ExtentB    = SizeB.GetValue(k);
                Separation = Math.Abs(Vector3.Dot(vSepA, new Vector3(
                                                      Matrix4x4Ex.GetValue(R, 0, k),
                                                      Matrix4x4Ex.GetValue(R, 1, k),
                                                      Matrix4x4Ex.GetValue(R, 2, k))));

                if (Separation > ExtentA + ExtentB)
                {
                    return(ContainmentType.Disjoint);
                }
            }

            // Now test Cross Products of each basis vector combination ( A[i], B[k] )
            for (i = 0; i < 3; i++)
            {
                for (k = 0; k < 3; k++)
                {
                    int i1 = (i + 1) % 3, i2 = (i + 2) % 3;
                    int k1 = (k + 1) % 3, k2 = (k + 2) % 3;
                    ExtentA =
                        SizeA.GetValue(i1) * Matrix4x4Ex.GetValue(AR, i2, k) +
                        SizeA.GetValue(i2) * Matrix4x4Ex.GetValue(AR, i1, k);
                    ExtentB =
                        SizeB.GetValue(k1) * Matrix4x4Ex.GetValue(AR, i, k2) +
                        SizeB.GetValue(k2) * Matrix4x4Ex.GetValue(AR, i, k1);
                    Separation = Math.Abs(
                        vSepA.GetValue(i2) * Matrix4x4Ex.GetValue(R, i1, k) -
                        vSepA.GetValue(i1) * Matrix4x4Ex.GetValue(R, i2, k));
                    if (Separation > ExtentA + ExtentB)
                    {
                        return(ContainmentType.Disjoint);
                    }
                }
            }

            // No separating axis found, the boxes overlap
            return(ContainmentType.Intersects);
        }