//! Merges a point
        public void MergePoint(ref IndexedVector3 point)
        {
            m_min.X = BoxCollision.BT_MIN(m_min.X, point.X);
            m_min.Y = BoxCollision.BT_MIN(m_min.Y, point.Y);
            m_min.Z = BoxCollision.BT_MIN(m_min.Z, point.Z);

            m_max.X = BoxCollision.BT_MAX(m_max.X, point.X);
            m_max.Y = BoxCollision.BT_MAX(m_max.Y, point.Y);
            m_max.Z = BoxCollision.BT_MAX(m_max.Z, point.Z);
        }
        //! Finds the intersecting box between this box and the other.
        public void FindIntersection(ref AABB other, ref AABB intersection)
        {
            intersection.m_min.X = BoxCollision.BT_MAX(other.m_min.X, m_min.X);
            intersection.m_min.Y = BoxCollision.BT_MAX(other.m_min.Y, m_min.Y);
            intersection.m_min.Z = BoxCollision.BT_MAX(other.m_min.Z, m_min.Z);

            intersection.m_max.X = BoxCollision.BT_MIN(other.m_max.X, m_max.X);
            intersection.m_max.Y = BoxCollision.BT_MIN(other.m_max.Y, m_max.Y);
            intersection.m_max.Z = BoxCollision.BT_MIN(other.m_max.Z, m_max.Z);
        }
        public void Merge(ref AABB box)
        {
            m_min.X = BoxCollision.BT_MIN(m_min.X, box.m_min.X);
            m_min.Y = BoxCollision.BT_MIN(m_min.Y, box.m_min.Y);
            m_min.Z = BoxCollision.BT_MIN(m_min.Z, box.m_min.Z);

            m_max.X = BoxCollision.BT_MAX(m_max.X, box.m_max.X);
            m_max.Y = BoxCollision.BT_MAX(m_max.Y, box.m_max.Y);
            m_max.Z = BoxCollision.BT_MAX(m_max.Z, box.m_max.Z);
        }
        public void CalcFromTriangle(ref IndexedVector3 V1, ref IndexedVector3 V2, ref IndexedVector3 V3)
        {
            m_min.X = BoxCollision.BT_MIN3(V1.X, V2.X, V3.X);
            m_min.Y = BoxCollision.BT_MIN3(V1.Y, V2.Y, V3.Y);
            m_min.Z = BoxCollision.BT_MIN3(V1.Z, V2.Z, V3.Z);

            m_max.X = BoxCollision.BT_MAX3(V1.X, V2.X, V3.X);
            m_max.Y = BoxCollision.BT_MAX3(V1.Y, V2.Y, V3.Y);
            m_max.Z = BoxCollision.BT_MAX3(V1.Z, V2.Z, V3.Z);
        }
        public AABB(ref IndexedVector3 V1,
                    ref IndexedVector3 V2,
                    ref IndexedVector3 V3)
        {
            m_min = new IndexedVector3();
            m_max = new IndexedVector3();

            m_min.X = BoxCollision.BT_MIN3(V1.X, V2.X, V3.X);
            m_min.Y = BoxCollision.BT_MIN3(V1.Y, V2.Y, V3.Y);
            m_min.Z = BoxCollision.BT_MIN3(V1.Z, V2.Z, V3.Z);

            m_max.X = BoxCollision.BT_MAX3(V1.X, V2.X, V3.X);
            m_max.Y = BoxCollision.BT_MAX3(V1.Y, V2.Y, V3.Y);
            m_max.Z = BoxCollision.BT_MAX3(V1.Z, V2.Z, V3.Z);
        }
        //! test for a triangle, with edges
        public bool CollideTriangleExact(ref IndexedVector3 p1, ref IndexedVector3 p2, ref IndexedVector3 p3, ref IndexedVector4 triangle_plane)
        {
            if (!CollidePlane(ref triangle_plane))
            {
                return(false);
            }

            IndexedVector3 center, extends;

            GetCenterExtend(out center, out extends);

            IndexedVector3 v1 = (p1 - center);
            IndexedVector3 v2 = (p2 - center);
            IndexedVector3 v3 = (p3 - center);

            //First axis
            IndexedVector3 diff     = (v2 - v1);
            IndexedVector3 abs_diff = diff.Absolute();

            //Test With X axis
            BoxCollision.TEST_CROSS_EDGE_BOX_X_AXIS_MCR(ref diff, ref abs_diff, ref v1, ref v3, ref extends);
            //Test With Y axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(ref diff, ref abs_diff, ref v1, ref v3, ref extends);
            //Test With Z axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(ref diff, ref abs_diff, ref v1, ref v3, ref extends);


            diff     = v3 - v2;
            abs_diff = diff.Absolute();
            //Test With X axis
            BoxCollision.TEST_CROSS_EDGE_BOX_X_AXIS_MCR(ref diff, ref abs_diff, ref v2, ref v1, ref extends);
            //Test With Y axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(ref diff, ref abs_diff, ref v2, ref v1, ref extends);
            //Test With Z axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(ref diff, ref abs_diff, ref v2, ref v1, ref extends);

            diff     = v1 - v3;
            abs_diff = diff.Absolute();

            //Test With X axis
            BoxCollision.TEST_CROSS_EDGE_BOX_X_AXIS_MCR(ref diff, ref abs_diff, ref v3, ref v2, ref extends);
            //Test With Y axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(ref diff, ref abs_diff, ref v3, ref v2, ref extends);
            //Test With Z axis
            BoxCollision.TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(ref diff, ref abs_diff, ref v3, ref v2, ref extends);

            return(true);
        }
        public void CalcFromTriangleMargin(ref IndexedVector3 V1, ref IndexedVector3 V2, ref IndexedVector3 V3, float margin)
        {
            m_min.X = BoxCollision.BT_MIN3(V1.X, V2.X, V3.X);
            m_min.Y = BoxCollision.BT_MIN3(V1.Y, V2.Y, V3.Y);
            m_min.Z = BoxCollision.BT_MIN3(V1.Z, V2.Z, V3.Z);

            m_max.X = BoxCollision.BT_MAX3(V1.X, V2.X, V3.X);
            m_max.Y = BoxCollision.BT_MAX3(V1.Y, V2.Y, V3.Y);
            m_max.Z = BoxCollision.BT_MAX3(V1.Z, V2.Z, V3.Z);

            m_min.X -= margin;
            m_min.Y -= margin;
            m_min.Z -= margin;
            m_max.X += margin;
            m_max.Y += margin;
            m_max.Z += margin;
        }
        /*! \brief Finds the Ray intersection parameter.
         * \param aabb Aligned box
         * \param vorigin A vec3f with the origin of the ray
         * \param vdir A vec3f with the direction of the ray
         */
        public bool CollideRay(ref IndexedVector3 vorigin, ref IndexedVector3 vdir)
        {
            IndexedVector3 extents, center;

            GetCenterExtend(out center, out extents);

            float Dx = vorigin.X - center.X;

            if (BoxCollision.BT_GREATER(Dx, extents.X) && Dx * vdir.X >= 0.0f)
            {
                return(false);
            }
            float Dy = vorigin.Y - center.Y;

            if (BoxCollision.BT_GREATER(Dy, extents.Y) && Dy * vdir.Y >= 0.0f)
            {
                return(false);
            }
            float Dz = vorigin.Z - center.Z;

            if (BoxCollision.BT_GREATER(Dz, extents.Z) && Dz * vdir.Z >= 0.0f)
            {
                return(false);
            }


            float f = vdir.Y * Dz - vdir.Z * Dy;

            if (Math.Abs(f) > extents.Y * Math.Abs(vdir.Z) + extents.Z * Math.Abs(vdir.Y))
            {
                return(false);
            }
            f = vdir.Z * Dx - vdir.X * Dz;
            if (Math.Abs(f) > extents.X * Math.Abs(vdir.Z) + extents.Z * Math.Abs(vdir.X))
            {
                return(false);
            }
            f = vdir.X * Dy - vdir.Y * Dx;
            if (Math.Abs(f) > extents.X * Math.Abs(vdir.Y) + extents.Y * Math.Abs(vdir.X))
            {
                return(false);
            }
            return(true);
        }
        public AABB(ref IndexedVector3 V1, ref IndexedVector3 V2, ref IndexedVector3 V3, float margin)
        {
            m_min   = new IndexedVector3();
            m_max   = new IndexedVector3();
            m_min.X = BoxCollision.BT_MIN3(V1.X, V2.X, V3.X);
            m_min.Y = BoxCollision.BT_MIN3(V1.Y, V2.Y, V3.Y);
            m_min.Z = BoxCollision.BT_MIN3(V1.Z, V2.Z, V3.Z);

            m_max.X = BoxCollision.BT_MAX3(V1.X, V2.X, V3.X);
            m_max.Y = BoxCollision.BT_MAX3(V1.Y, V2.Y, V3.Y);
            m_max.Z = BoxCollision.BT_MAX3(V1.Z, V2.Z, V3.Z);

            m_min.X -= margin;
            m_min.Y -= margin;
            m_min.Z -= margin;
            m_max.X += margin;
            m_max.Y += margin;
            m_max.Z += margin;
        }
        //! transcache is the transformation cache from box to this AABB
        public bool OverlappingTransCache(ref AABB box, ref BT_BOX_BOX_TRANSFORM_CACHE transcache, bool fulltest)
        {
            //Taken from OPCODE
            IndexedVector3 ea, eb; //extends
            IndexedVector3 ca, cb; //extends

            GetCenterExtend(out ca, out ea);
            box.GetCenterExtend(out cb, out eb);



            IndexedVector3 T = new IndexedVector3(0, 0, 0);
            float          t, t2;
            int            i;

            // Class I : A's basis vectors

            for (i = 0; i < 3; i++)
            {
                T[i] = transcache.m_R1to0[i].Dot(ref cb) + transcache.m_T1to0[i] - ca[i];
                t    = transcache.m_AR[i].Dot(ref eb) + ea[i];

                if (BoxCollision.BT_GREATER(T[i], t))
                {
                    return(false);
                }
            }
            // Class II : B's basis vectors
            for (i = 0; i < 3; i++)
            {
                t  = Mat3DotCol(ref transcache.m_R1to0, ref T, i);
                t2 = Mat3DotCol(ref transcache.m_AR, ref ea, i) + eb[i];
                if (BoxCollision.BT_GREATER(t, t2))
                {
                    return(false);
                }
            }
            // Class III : 9 cross products
            if (fulltest)
            {
                // check to see if these need to be restored back or are read-only
                float[,] m_R1to0 = MathUtil.BasisMatrixToFloatArray(ref transcache.m_R1to0);
                float[,] m_AR    = MathUtil.BasisMatrixToFloatArray(ref transcache.m_AR);


                int j, m, n, o, p, q, r;
                for (i = 0; i < 3; i++)
                {
                    m = (i + 1) % 3;
                    n = (i + 2) % 3;
                    o = i == 0 ? 1 : 0;
                    p = i == 2 ? 1 : 2;
                    for (j = 0; j < 3; j++)
                    {
                        q  = j == 2 ? 1 : 2;
                        r  = j == 0 ? 1 : 0;
                        t  = T[n] * m_R1to0[m, j] - T[m] * m_R1to0[n, j];
                        t2 = ea[o] * m_AR[p, j] + ea[p] * m_AR[o, j] +
                             eb[r] * m_AR[i, q] + eb[q] * m_AR[i, r];
                        if (BoxCollision.BT_GREATER(t, t2))
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }