Exemple #1
0
        private float Disjoint(out bool b, Vector3 axis, MyBox box, MyColDetVoxelTriangle triangle, float collTolerance)
        {
            float ret;

            b = Disjoint(out ret, axis, box, triangle, collTolerance);
            return(ret);
        }
Exemple #2
0
        //  Disjoint Returns true if disjoint.  Returns false if intersecting,
        //  and sets the overlap depth, d scaled by the axis length
        private static bool Disjoint(out float d, Vector3 axis, MyBox box, MyColDetVoxelTriangle triangle, float collTolerance)
        {
            float min0, max0, min1, max1;

            box.GetSpan(out min0, out max0, axis);
            triangle.GetSpan(out min1, out max1, axis);

            if (min0 > (max1 + collTolerance) ||
                min1 > (max0 + collTolerance))
            {
                d = 0.0f;
                return(true);
            }

            if ((max0 > max1) && (min1 > min0))
            {
                // triangleVertexes is inside - choose the min dist to move it out
                d = System.Math.Min(max0 - min1, max1 - min0);
            }
            else if ((max1 > max0) && (min0 > min1))
            {
                // box is inside - choose the min dist to move it out
                d = System.Math.Min(max1 - min0, max0 - min1);
            }
            else
            {
                // objects overlap
                d  = (max0 < max1) ? max0 : max1;
                d -= (min0 > min1) ? min0 : min1;
            }

            return(false);
        }
        /// <summary>
        /// Pushes intersection points (in world space) onto the back of pts.
        /// Intersection is between an AABox faces and an orientated box's
        /// edges. orient and pos are used to transform the points from the
        /// AABox frame back into the original frame.
        /// </summary>
        private static int GetAABox2BoxEdgesIntersectionPoints(List <ContactPoint> pts, ref Vector3 sides,
                                                               MyBox box, ref Matrix origBoxOrient, ref Vector3 origBoxPos, float combinationDistanceSq)
        {
            int num = 0;

            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);
            MyBox.Edge[] edges;
            box.GetEdges(out edges);

            for (int iedge = 0; iedge < 12; ++iedge)
            {
                Vector3 edgePt0 = boxPts[(int)edges[iedge].Ind0];
                Vector3 edgePt1 = boxPts[(int)edges[iedge].Ind1];

                num += GetAABox2EdgeIntersectionPoints(pts,
                                                       ref sides, box, ref edgePt0, ref edgePt1,
                                                       ref origBoxOrient, ref origBoxPos, combinationDistanceSq);

                // Don't think we can get more than 8... and anyway if we get too many
                // then the penetration must be so bad who cares about the details?
                if (num >= 8)
                {
                    return(num);
                }
            }
            return(num);
        }
        /// <summary>
        /// Disjoint Returns true if disjoint. Returns false if intersecting,
        /// and sets the overlap depth, d scaled by the axis length.
        /// </summary>
        private static bool Disjoint(out float d, ref Vector3 axis, MyBox box0, MyBox box1, float collTolerance)
        {
            float min0, max0, min1, max1;

            box0.GetSpan(out min0, out max0, axis);
            box1.GetSpan(out min1, out max1, axis);

            if (min0 > (max1 + collTolerance + MyPhysicsConfig.CollisionEpsilon) ||
                min1 > (max0 + collTolerance + MyPhysicsConfig.CollisionEpsilon))
            {
                d = 0.0f;
                return(true);
            }

            if ((max0 > max1) && (min1 > min0))
            {
                // box1 is inside - choose the min dist to move it out
                d = MathHelper.Min(max0 - min1, max1 - min0);
            }
            else if ((max1 > max0) && (min0 > min1))
            {
                // box0 is inside - choose the min dist to move it out
                d = MathHelper.Min(max1 - min0, max0 - min1);
            }
            else
            {
                // boxes overlap
                d  = (max0 < max1) ? max0 : max1;
                d -= (min0 > min1) ? min0 : min1;
            }

            return(false);
        }
        /// <summary>
        /// Disjoint Returns true if disjoint. Returns false if intersecting,
        /// and sets the overlap depth, d scaled by the axis length.
        /// </summary>
        private static bool Disjoint(out float d, ref Vector3 axis, MyBox box0, MyBox box1, float collTolerance)
        {
            float min0, max0, min1, max1;

            box0.GetSpan(out min0, out max0, axis);
            box1.GetSpan(out min1, out max1, axis);

            if (min0 > (max1 + collTolerance + MyPhysicsConfig.CollisionEpsilon) ||
                min1 > (max0 + collTolerance + MyPhysicsConfig.CollisionEpsilon))
            {
                d = 0.0f;
                return true;
            }

            if ((max0 > max1) && (min1 > min0))
            {
                // box1 is inside - choose the min dist to move it out
                d = MathHelper.Min(max0 - min1, max1 - min0);
            }
            else if ((max1 > max0) && (min0 > min1))
            {
                // box0 is inside - choose the min dist to move it out
                d = MathHelper.Min(max1 - min0, max0 - min1);
            }
            else
            {
                // boxes overlap
                d = (max0 < max1) ? max0 : max1;
                d -= (min0 > min1) ? min0 : min1;
            }

            return false;
        }
        /// <summary>
        /// Pushes intersection points onto the back of pts. Returns the
        /// number of points found.
        /// Points that are close together (compared to
        /// combinationDistance) get combined
        /// dirToBody0 is the collision normal towards box0
        /// </summary>
        private static int GetBoxBoxIntersectionPoints(List <ContactPoint> pts,
                                                       MyBox box0, MyBox box1, float combinationDistance,
                                                       float collTolerance)
        {
            // first transform box1 into box0 space - there box0 has a corner
            // at the origin and faces parallel to the world planes. Then intersect
            // each of box1's edges with box0 faces, transforming each point back into
            // world space. Finally combine points
            float tolVal = 0.5f * collTolerance;

            Vector3 tol = new Vector3(tolVal);

            combinationDistance += collTolerance * 2.0f * (float)System.Math.Sqrt(3.0d);

            for (int ibox = 0; ibox < 2; ++ibox)
            {
                MyBox boxA = (ibox != 0) ? box1 : box0;
                MyBox boxB = (ibox != 0) ? box0 : box1;

                #region REFERENCE: Matrix boxAInvOrient = Matrix.Transpose(boxA.Orientation);
                Matrix boxAInvOrient;
                Matrix.Transpose(ref boxA.Transform.Orientation, out boxAInvOrient);
                #endregion

                #region REFERENCE: Vector3 pos = Vector3.Transform(boxB.m_initialSunWindPosition - boxA.m_initialSunWindPosition,boxAInvOrient)
                Vector3 pos;
                Vector3.Subtract(ref boxB.Transform.Position, ref boxA.Transform.Position, out pos);
                Vector3.TransformNormal(ref pos, ref boxAInvOrient, out pos);
                #endregion

                #region REFERENCE: Matrix boxOrient = boxB.Orientation * boxAInvOrient;
                Matrix boxOrient;
                Matrix.Multiply(ref boxB.Transform.Orientation, ref boxAInvOrient, out boxOrient);
                #endregion

                MyBox box = tempBox;
                box.Position    = pos;
                box.Orientation = boxOrient;
                box.SideLengths = boxB.SideLengths;


                // if we get more than a certain number of points back from this call,
                // and iBox == 0, could probably skip the other test...
                Vector3 sL = boxA.SideLengths;
                GetAABox2BoxEdgesIntersectionPoints(pts, ref sL,
                                                    box, ref boxA.Transform.Orientation, ref boxA.Transform.Position, combinationDistance * combinationDistance);
            }

            return(pts.Count);
        }
Exemple #7
0
        //  GetBoxTriangleIntersectionPoints
        //  Pushes intersection points onto the back of pts. Returns the
        //  number of points found.
        //  Points that are close together (compared to
        //  combinationDistance) get combined
        private int GetBoxTriangleIntersectionPoints(List <MyCP> pts, MyBox box, MyColDetVoxelTriangle triangle, float combinationDistance)
        {
            // first intersect each edge of the box with the triangleVertexes
            MyBox.Edge[] edges;
            box.GetEdges(out edges);
            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);

            float tS;
            float tv1, tv2;

            int iEdge;

            for (iEdge = 0; iEdge < 12; ++iEdge)
            {
                MyBox.Edge edge = edges[iEdge];
                MySegment  seg  = new MySegment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]);
                if (this.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle))
                {
                    float depthA = Vector3.Dot(boxPts[(int)edge.Ind0] - seg.GetPoint(tS), triangle.Normal);
                    float depthB = Vector3.Dot(boxPts[(int)edge.Ind1] - seg.GetPoint(tS), triangle.Normal);
                    AddPoint(pts, seg.GetPoint(tS), triangle.Normal, depthA < depthB ? depthA : depthB, combinationDistance * combinationDistance);
                }
            }

            Vector3 pos, n;

            // now each edge of the triangleVertexes with the box
            for (iEdge = 0; iEdge < 3; ++iEdge)
            {
                Vector3   pt0 = triangle.GetPoint(iEdge);
                Vector3   pt1 = triangle.GetPoint((iEdge + 1) % 3);
                MySegment s1  = new MySegment(pt0, pt1 - pt0);
                MySegment s2  = new MySegment(pt1, pt0 - pt1);
                if (box.SegmentIntersect(out tS, out pos, out n, s1))
                {
                    float depthA = Vector3.Dot(pt0 - pos, triangle.Normal);
                    float depthB = Vector3.Dot(pt1 - pos, triangle.Normal);
                    AddPoint(pts, pos, triangle.Normal, depthA < depthB ? depthA : depthB, combinationDistance * combinationDistance);
                }
                if (box.SegmentIntersect(out tS, out pos, out n, s2))
                {
                    float depthA = Vector3.Dot(pt0 - pos, triangle.Normal);
                    float depthB = Vector3.Dot(pt1 - pos, triangle.Normal);
                    AddPoint(pts, pos, triangle.Normal, depthA < depthB ? depthA : depthB, combinationDistance * combinationDistance);
                }
            }

            return(pts.Count);
        }
        /// <summary>
        /// The AABox has a corner at the origin and size sides.
        /// </summary>
        private static int GetAABox2EdgeIntersectionPoints(List <ContactPoint> pts,
                                                           ref Vector3 sides, MyBox box, ref Vector3 edgePt0, ref Vector3 edgePt1,
                                                           ref Matrix origBoxOrient, ref Vector3 origBoxPos,
                                                           float combinationDistanceSq)
        {
            // The AABox faces are aligned with the world directions. Loop
            // over the 3 directions and do the two tests. We know that the
            // AABox has a corner at the origin
            #region REFERENCE: Vector3 edgeDir = JiggleMath.NormalizeSafe(edgePt1 - edgePt0);
            Vector3 edgeDir;
            Vector3.Subtract(ref edgePt1, ref edgePt0, out edgeDir);
            MyPhysicsUtils.NormalizeSafe(ref edgeDir);
            #endregion

            int num = 0;

            for (int idir = 3; idir-- != 0;)
            {
                // skip edge/face tests if nearly parallel
                if (System.Math.Abs(MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgeDir, idir)) < 0.1f)
                {
                    continue;
                }

                int jdir = (idir + 1) % 3;
                int kdir = (idir + 2) % 3;
                for (int iface = 2; iface-- != 0;)
                {
                    float offset = 0.0f;
                    if (iface == 1)
                    {
                        offset = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, idir);
                    }

                    float dist0 = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgePt0, idir) - offset;
                    float dist1 = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgePt1, idir) - offset;

                    float frac = -1.0f;

                    if (dist0 * dist1 < -MyPhysicsConfig.CollisionEpsilon)
                    {
                        frac = -dist0 / (dist1 - dist0);
                    }
                    else if (System.Math.Abs(dist0) < MyPhysicsConfig.CollisionEpsilon)
                    {
                        frac = 0.0f;
                    }
                    else if (System.Math.Abs(dist1) < MyPhysicsConfig.CollisionEpsilon)
                    {
                        frac = 1.0f;
                    }

                    if (frac >= 0.0f)
                    {
                        #region REFERENCE: Vector3 pt = (1.0f - frac) * edgePt0 + frac * edgePt1
                        Vector3 tmp; Vector3 pt;
                        Vector3.Multiply(ref edgePt1, frac, out tmp);
                        Vector3.Multiply(ref edgePt0, 1.0f - frac, out pt);
                        Vector3.Add(ref pt, ref tmp, out pt);
                        #endregion

                        // check the point is within the face rectangle
                        float ptJdir = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref pt, jdir);
                        float ptKdir = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref pt, kdir);

                        if ((ptJdir > -MyPhysicsConfig.CollisionEpsilon) &&
                            (ptJdir < MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, jdir) + MyPhysicsConfig.CollisionEpsilon) &&
                            (ptKdir > -MyPhysicsConfig.CollisionEpsilon) &&
                            (ptKdir < MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, kdir) + MyPhysicsConfig.CollisionEpsilon))
                        {
                            // woohoo got a point
                            #region REFERENCE: Vector3 pos = origBoxPos + Vector3.Transform(pt, origBoxOrient);
                            Vector3 pos;
                            Vector3.Transform(ref pt, ref origBoxOrient, out pos);
                            Vector3.Add(ref origBoxPos, ref pos, out pos);
                            #endregion

                            AddPoint(pts, ref pos, combinationDistanceSq);

                            if (++num == 2)
                            {
                                return(num);
                            }
                        }
                    }
                }
            }
            return(num);
        }
        //  Disjoint Returns true if disjoint.  Returns false if intersecting,
        //  and sets the overlap depth, d scaled by the axis length
        private static bool Disjoint(out float d, Vector3 axis, MyBox box, MyColDetVoxelTriangle triangle, float collTolerance)
        {
            float min0, max0, min1, max1;

            box.GetSpan(out min0, out max0, axis);
            triangle.GetSpan(out min1, out max1, axis);

            if (min0 > (max1 + collTolerance ) ||
                min1 > (max0 + collTolerance ))
            {
                d = 0.0f;
                return true;
            }

            if ((max0 > max1) && (min1 > min0))
            {
                // triangleVertexes is inside - choose the min dist to move it out
                d = System.Math.Min(max0 - min1, max1 - min0);
            }
            else if ((max1 > max0) && (min0 > min1))
            {
                // box is inside - choose the min dist to move it out
                d = System.Math.Min(max1 - min0, max0 - min1);
            }
            else
            {
                // objects overlap
                d = (max0 < max1) ? max0 : max1;
                d -= (min0 > min1) ? min0 : min1;
            }

            return false;
        }
        /// <summary>
        /// Pushes intersection points (in world space) onto the back of pts.
        /// Intersection is between an AABox faces and an orientated box's
        /// edges. orient and pos are used to transform the points from the
        /// AABox frame back into the original frame.
        /// </summary>
        private static int GetAABox2BoxEdgesIntersectionPoints(List<ContactPoint> pts, ref Vector3 sides,
            MyBox box, ref Matrix origBoxOrient, ref Vector3 origBoxPos, float combinationDistanceSq)
        {
            int num = 0;
            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);
            MyBox.Edge[] edges;
            box.GetEdges(out edges);

            for (int iedge = 0; iedge < 12; ++iedge)
            {
                Vector3 edgePt0 = boxPts[(int)edges[iedge].Ind0];
                Vector3 edgePt1 = boxPts[(int)edges[iedge].Ind1];

                num += GetAABox2EdgeIntersectionPoints(pts,
                    ref sides, box, ref edgePt0, ref edgePt1,
                    ref origBoxOrient, ref origBoxPos, combinationDistanceSq);

                // Don't think we can get more than 8... and anyway if we get too many 
                // then the penetration must be so bad who cares about the details?
                if (num >= 8) return num;
            }
            return num;
        }
        private static void GetSupportPoint(out Vector3 p, MyBox box, Vector3 axis)
        {
            #region INLINE: Vector3 orient0 = box.Orientation.Right;
            Vector3 orient0 = new Vector3(
                box.Transform.Orientation.M11,
                box.Transform.Orientation.M12,
                box.Transform.Orientation.M13);
            #endregion

            #region INLINE: Vector3 orient1 = box.Orientation.Up;
            Vector3 orient1 = new Vector3(
                box.Transform.Orientation.M21,
                box.Transform.Orientation.M22,
                box.Transform.Orientation.M23);
            #endregion

            #region INLINE: Vector3 orient2 = box.Orientation.Backward;
            Vector3 orient2 = new Vector3(
                box.Transform.Orientation.M31,
                box.Transform.Orientation.M32,
                box.Transform.Orientation.M33);
            #endregion

            #region INLINE: float ass = Vector3.Dot(axis,orient0);
            float ass = axis.X * orient0.X + axis.Y * orient0.Y + axis.Z * orient0.Z;
            #endregion

            #region INLINE: float au = Vector3.Dot(axis,orient1);
            float au = axis.X * orient1.X + axis.Y * orient1.Y + axis.Z * orient1.Z;
            #endregion

            #region INLINE: float ad = Vector3.Dot(axis,orient2);
            float ad = axis.X * orient2.X + axis.Y * orient2.Y + axis.Z * orient2.Z;
            #endregion

            float threshold = MyPhysicsConfig.CollisionEpsilon;

            box.GetCentre(out p);

            if (ass < -threshold)
            {
                #region INLINE: p += orient0 * (0.5 * box.SideLength.X);
                p.X += orient0.X * (0.5f * box.SideLengths.X);
                p.Y += orient0.Y * (0.5f * box.SideLengths.X);
                p.Z += orient0.Z * (0.5f * box.SideLengths.X);
                #endregion
            }
            else if (ass >= threshold)
            {
                #region INLINE: p -=  orient0 * (0.5 * box.SideLength.X);
                p.X -= orient0.X * (0.5f * box.SideLengths.X);
                p.Y -= orient0.Y * (0.5f * box.SideLengths.X);
                p.Z -= orient0.Z * (0.5f * box.SideLengths.X);
                #endregion
            }

            if (au < -threshold)
            {
                #region INLINE: p += orient1 * (0.5 * box.SideLength.Y);
                p.X += orient1.X * (0.5f * box.SideLengths.Y);
                p.Y += orient1.Y * (0.5f * box.SideLengths.Y);
                p.Z += orient1.Z * (0.5f * box.SideLengths.Y);
                #endregion
            }
            else if (au >= threshold)
            {
                #region INLINE: p -= orient1 * (0.5 * box.SideLength.Y);
                p.X -= orient1.X * (0.5f * box.SideLengths.Y);
                p.Y -= orient1.Y * (0.5f * box.SideLengths.Y);
                p.Z -= orient1.Z * (0.5f * box.SideLengths.Y);
                #endregion
            }

            if (ad < -threshold)
            {
                #region INLINE: p += orient2 * (0.5 * box.SideLength.Z);
                p.X += orient2.X * (0.5f * box.SideLengths.Z);
                p.Y += orient2.Y * (0.5f * box.SideLengths.Z);
                p.Z += orient2.Z * (0.5f * box.SideLengths.Z);
                #endregion
            }
            else if (ad >= threshold)
            {
                #region INLINE: p -= orient2 * (0.5 * box.SideLength.Z);
                p.X -= orient2.X * (0.5f * box.SideLengths.Z);
                p.Y -= orient2.Y * (0.5f * box.SideLengths.Z);
                p.Z -= orient2.Z * (0.5f * box.SideLengths.Z);
                #endregion
            }
        }
Exemple #12
0
        private bool DoOverlapBoxTriangleTest(MyBox box, ref MyColDetVoxelTriangle triangle)
        {
            Matrix dirs0 = box.Orientation;

            Vector3 triEdge0;
            Vector3 triEdge1;
            Vector3 triEdge2;

            triEdge0 = MyMwcUtils.Normalize(triangle.Edge0);
            triEdge1 = MyMwcUtils.Normalize(triangle.Edge1);
            triEdge2 = MyMwcUtils.Normalize(triangle.Edge2);

            Vector3 triNormal = triangle.Plane.Normal;

            // the 15 potential separating axes (comment by Marek Rosa: note says 15 but code uses 13... I don't know why, mistake in the note??)
            const int        NUM_AXES = 13;
            MyVector3Array13 axes     = new MyVector3Array13();

            axes[0]  = triNormal;
            axes[1]  = dirs0.Right;
            axes[2]  = dirs0.Up;
            axes[3]  = dirs0.Backward;
            axes[4]  = Vector3.Cross(axes[1], triEdge0);
            axes[5]  = Vector3.Cross(axes[1], triEdge1);
            axes[6]  = Vector3.Cross(axes[1], triEdge2);
            axes[7]  = Vector3.Cross(axes[2], triEdge0);
            axes[8]  = Vector3.Cross(axes[2], triEdge1);
            axes[9]  = Vector3.Cross(axes[2], triEdge2);
            axes[10] = Vector3.Cross(axes[3], triEdge0);
            axes[11] = Vector3.Cross(axes[3], triEdge1);
            axes[12] = Vector3.Cross(axes[3], triEdge2);

            // the overlap depths along each axis
            MyFloatArray13 overlapDepths = new MyFloatArray13();

            // see if the boxes are separate along any axis, and if not keep a
            // record of the depths along each axis
            int i;

            for (i = 0; i < NUM_AXES; ++i)
            {
                overlapDepths[i] = 1.0f;

                bool b;
                overlapDepths[i] = Disjoint(out b, axes[i], box, triangle, MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon);
                if (b)
                {
                    return(false);
                }
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int   minAxis  = -1;

            for (i = 0; i < NUM_AXES; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                {
                    continue;
                }

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                axes[i]          *= invl;
                overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (overlapDepths[i] < minDepth)
                {
                    minDepth = overlapDepths[i];
                    minAxis  = i;
                }
            }

            if (minAxis == -1)
            {
                return(false);
            }

            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D     = box.GetCentre() - triangle.Centre;
            Vector3 N     = axes[minAxis];
            float   depth = overlapDepths[minAxis];

            if (Vector3.Dot(D, N) < 0.0f)
            {
                N *= -1;
            }

            MyRigidBody rbo0 = GetRigidBody1();
            MyRigidBody rbo1 = GetRigidBody2();
            float       dt   = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

            Vector3 boxOldPos = rbo0.Position;
            Vector3 boxNewPos = rbo0.Position + rbo0.LinearVelocity * dt;
            Vector3 meshPos   = rbo1.Position;

            m_CPList.Clear();

            GetBoxTriangleIntersectionPoints(m_CPList, box, triangle, MyPhysicsConfig.CollisionEpsilon);

            // adjust the depth
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            // report collisions
            int numPts = m_CPList.Count;
            MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc();
            {
                if (numPts > 0)
                {
                    if (numPts >= MyPhysicsConfig.MaxContactPoints)
                    {
                        numPts = MyPhysicsConfig.MaxContactPoints - 1;
                    }

                    // adjust positions
                    for (i = 0; i < numPts; ++i)
                    {
                        collPtArray[i] = new MySmallCollPointInfo(m_CPList[i].m_Position - boxOldPos, m_CPList[i].m_Position - meshPos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, m_CPList[i].m_Normal, m_CPList[i].m_Depth, m_CPList[i].m_Position);
                    }

                    MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, numPts);
                    MyContactInfoCache.FreeStackAlloc(collPtArray);
                    return(true);
                }
                else
                {
                    MyContactInfoCache.FreeStackAlloc(collPtArray);
                    return(false);
                }
            }
        }
Exemple #13
0
        private bool DoOverlapBoxTriangleStaticTest(MyBox box, ref MyColDetVoxelTriangle triangle)
        {
            Matrix dirs0 = box.Orientation;

            #region triEdge0
            Vector3 pt0;
            Vector3 pt1;
            triangle.GetPoint(0, out pt0);
            triangle.GetPoint(1, out pt1);

            Vector3 triEdge0;
            Vector3.Subtract(ref pt1, ref pt0, out triEdge0);

            if (triEdge0.LengthSquared() < MyPhysicsConfig.Epsilon)
            {
                return(false);
            }

            #endregion

            #region triEdge1
            Vector3 pt2;
            triangle.GetPoint(2, out pt2);

            Vector3 triEdge1;
            Vector3.Subtract(ref pt2, ref pt1, out triEdge1);

            if (triEdge1.LengthSquared() < MyPhysicsConfig.Epsilon)
            {
                return(false);
            }

            #endregion

            #region triEdge2
            Vector3 triEdge2;
            Vector3.Subtract(ref pt0, ref pt2, out triEdge2);

            if (triEdge2.LengthSquared() < MyPhysicsConfig.Epsilon)
            {
                return(false);
            }

            #endregion

            triEdge0.Normalize();
            triEdge1.Normalize();
            triEdge2.Normalize();

            Vector3 triNormal = triangle.Plane.Normal;

            m_axes[0] = triNormal;
            m_axes[1] = dirs0.Right;
            m_axes[2] = dirs0.Up;
            m_axes[3] = dirs0.Backward;
            Vector3.Cross(ref m_axes[1], ref triEdge0, out m_axes[4]);
            Vector3.Cross(ref m_axes[1], ref triEdge1, out m_axes[5]);
            Vector3.Cross(ref m_axes[1], ref triEdge2, out m_axes[6]);
            Vector3.Cross(ref m_axes[2], ref triEdge0, out m_axes[7]);
            Vector3.Cross(ref m_axes[2], ref triEdge1, out m_axes[8]);
            Vector3.Cross(ref m_axes[2], ref triEdge2, out m_axes[9]);
            Vector3.Cross(ref m_axes[3], ref triEdge0, out m_axes[10]);
            Vector3.Cross(ref m_axes[3], ref triEdge1, out m_axes[11]);
            Vector3.Cross(ref m_axes[3], ref triEdge2, out m_axes[12]);

            // the overlap depths along each axis


            // see if the boxes are separate along any axis, and if not keep a
            // record of the depths along each axis
            int i;
            for (i = 0; i < numAxes; ++i)
            {
                m_overlapDepths[i] = 1.0f;
                if (Disjoint(out m_overlapDepths[i], m_axes[i], box, triangle, MyPhysicsConfig.CollisionEpsilon))
                {
                    return(false);
                }
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int   minAxis  = -1;

            for (i = 0; i < numAxes; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = m_axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                {
                    continue;
                }

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                m_axes[i]          *= invl;
                m_overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (m_overlapDepths[i] < minDepth)
                {
                    minDepth = m_overlapDepths[i];
                    minAxis  = i;
                }
            }

            if (minAxis == -1)
            {
                return(false);
            }

            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D     = box.GetCentre() - triangle.Centre;
            Vector3 N     = m_axes[minAxis];
            float   depth = m_overlapDepths[minAxis];

            if (Vector3.Dot(D, N) < 0.0f)
            {
                N *= -1;
            }

            MyRigidBody rbo0 = GetRigidBody1();
            MyRigidBody rbo1 = GetRigidBody2();
            float       dt   = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

            Vector3 boxOldPos = rbo0.Position;
            Vector3 boxNewPos = rbo0.Position + rbo0.LinearVelocity * dt;
            Vector3 meshPos   = rbo1.Position;

            m_CPList.Clear();
            GetBoxTriangleIntersectionPoints(m_CPList, box, triangle, MyPhysicsConfig.CollisionEpsilon);

            // adjust the depth
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            int numPts = m_CPList.Count;
            if (numPts > 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        protected override bool Interact(bool staticCollision)
        {
            try
            {
                if (!staticCollision)
                {
                    TestsCount++;
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("BoxTriangleIntersection");
                }

                if (RBElement1.GetElementType() != MyRBElementType.ET_BOX)
                {
                    SwapElements();
                }

                var boxElement       = (MyRBBoxElement)RBElement1;
                var triangleMeshElem = (MyRBTriangleMeshElement)RBElement2;

                MyModel model = ((boxElement.Flags & MyElementFlag.EF_MODEL_PREFER_LOD0) > 0 ? triangleMeshElem.ModelLOD0 : triangleMeshElem.Model);

                Matrix boxMatrix          = boxElement.GetGlobalTransformation();
                Matrix triangleMeshMatrix = triangleMeshElem.GetGlobalTransformation();

                Matrix newMatrix = boxMatrix;

                if (!staticCollision)
                {
                    // MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep
                    newMatrix.Translation = newMatrix.Translation + boxElement.GetRigidBody().LinearVelocity *MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;
                }

                MyBox oldBox = m_tempBox1;
                MyBox newBox = m_tempBox2;

                oldBox.Transform.Orientation             = boxMatrix;
                oldBox.Transform.Orientation.Translation = Vector3.Zero;
                oldBox.Transform.Position = boxMatrix.Translation - Vector3.TransformNormal(boxElement.Size * 0.5f, boxMatrix);

                newBox.Transform.Orientation             = newMatrix;
                newBox.Transform.Orientation.Translation = Vector3.Zero;
                newBox.Transform.Position = newMatrix.Translation - Vector3.TransformNormal(boxElement.Size * 0.5f, newMatrix);

                oldBox.SideLengths = boxElement.Size;
                newBox.SideLengths = boxElement.Size;

                float boxRadius = newBox.GetBoundingRadiusAroundCentre();

                #region REFERENCE: Vector3 boxCentre = newBox.GetCentre();
                Vector3 boxCentre;
                newBox.GetCentre(out boxCentre);
                // Deano need to trasnform the box center into mesh space
                Matrix invTransformMatrix = Matrix.Invert(triangleMeshMatrix);

                Vector3.Transform(ref boxCentre, ref invTransformMatrix, out boxCentre);
                #endregion

                BoundingBox bb = boxElement.GetWorldSpaceAABB();

                if (staticCollision)
                {
                    Vector3 bbMin = Vector3.Transform(bb.Min, invTransformMatrix);
                    Vector3 bbMax = Vector3.Transform(bb.Max, invTransformMatrix);

                    BoundingSphere bs = new BoundingSphere((bbMax + bbMin) / 2, Vector3.Distance(bbMin, bbMax));
                    List <MyTriangle_Vertex_Normal> triangles = MyPhysics.physicsSystem.GetContactConstraintModule().GetTriangleCache().GetFreeTriangleList(this);
                    model.GetTrianglePruningStructure().GetTrianglesIntersectingSphere(ref bs, triangles, triangles.Capacity);

                    for (int iTriangle = 0; iTriangle < triangles.Count; iTriangle++)
                    {
                        MyTriangle_Vertex_Normal triangle = triangles[iTriangle];

                        MyPlane plane = new MyPlane(ref triangle.Vertexes);

                        // quick early test is done in mesh space
                        float dist = MyUtils.GetDistanceFromPointToPlane(ref boxCentre, ref plane);

                        if (dist > boxRadius || dist < -boxRadius)
                        {
                            continue;
                        }

                        Vector3 oldPos           = boxMatrix.Translation;
                        Vector3 newPos           = newMatrix.Translation;
                        float   collisionEpsilon = 0;//pz to test not sure about value

                        if (DoOverlapBoxTriangleStaticTest(
                                oldBox, newBox,
                                triangle,
                                plane,
                                collisionEpsilon,
                                ref triangleMeshMatrix,
                                ref oldPos,
                                ref newPos))
                        {
                            return(true);
                        }
                    }
                    return(false);
                }
                else
                {
                    bb.Min += boxElement.GetRigidBody().LinearVelocity *MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;
                    bb.Max += boxElement.GetRigidBody().LinearVelocity *MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

                    var boxCenter = bb.GetCenter();
                    // aabox is done in mesh space and handles the mesh transform correctly
                    //int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb);

                    //boxElement.GetRigidBody().Position = Vector3.Zero;
                    //triangleMeshElem.GetRigidBody().Position = Vector3.Zero;
                    //BoundingSphere bs = new BoundingSphere((bbMax + bbMin) / 2, Vector3.Distance(bbMin, bbMax));

                    var         halfSize = bb.Size() / 2;
                    BoundingBox bb2      = new BoundingBox(boxCentre - halfSize, boxCentre + halfSize);

                    List <MyTriangle_Vertex_Normal> triangles = MyPhysics.physicsSystem.GetContactConstraintModule().GetTriangleCache().GetFreeTriangleList(this);

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PruningStructure");

                    model.GetTrianglePruningStructure().GetTrianglesIntersectingAABB(ref bb2, triangles, triangles.Capacity);
                    //model.GetTrianglePruningStructure().GetTrianglesIntersectingSphere(ref bs, triangles, triangles.Capacity);
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Tests count ", TestsCount);

                    MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc();
                    int refPointer = 0;

                    m_collPoints.Clear();

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Triangles");

                    for (int iTriangle = 0; iTriangle < triangles.Count; iTriangle++)
                    {
                        MyTriangle_Vertex_Normal triangle = triangles[iTriangle];
                        //IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]);

                        MyPlane plane = new MyPlane(ref triangle.Vertexes);

                        // quick early test is done in mesh space
                        //float dist = meshTriangle.Plane.DotCoordinate(boxCentre);
                        float dist = MyUtils.GetDistanceFromPointToPlane(ref boxCentre, ref plane);

                        if (dist > boxRadius || dist < -boxRadius)
                        {
                            continue;
                        }

                        Vector3 oldPos = boxMatrix.Translation;
                        Vector3 newPos = newMatrix.Translation;

                        DoOverlapBoxTriangleTest(
                            oldBox, newBox,
                            triangle,
                            plane,
                            MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon,
                            ref triangleMeshMatrix,
                            ref oldPos,
                            ref newPos,
                            m_collPoints);
                    }

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

                    TrianglesTested += triangles.Count;

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().ProfileCustomValue("Triangles tested ", TrianglesTested);

                    m_collPoints.Sort(m_colPointComparer);

                    refPointer = 0;
                    foreach (MyCollisionPointStruct collPoint in m_collPoints)
                    {
                        collPtArray[refPointer] = collPoint.CollPointInfo;
                        refPointer++;
                        if (refPointer >= MyPhysicsConfig.MaxContactPoints)
                        {
                            break;
                        }
                    }

                    if (refPointer > 0)
                    {
                        MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, refPointer);
                    }


                    MyContactInfoCache.FreeStackAlloc(collPtArray);
                    MyPhysics.physicsSystem.GetContactConstraintModule().GetTriangleCache().PushBackTriangleList(triangles);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (!staticCollision)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }
            }
            return(false);
        }
        private bool DoOverlapBoxTriangleTest(MyBox oldBox, MyBox newBox, MyTriangle_Vertex_Normal triangle, MyPlane plane, float collTolerance,
                                              ref Matrix transformMatrix, ref Vector3 oldBoxPos, ref Vector3 newBoxPos, List <MyCollisionPointStruct> collPoints)
        {
            Matrix dirs0 = newBox.Orientation;

            dirs0.Translation = Vector3.Zero;

            #region Triangle
            Vector3 triVec0 = triangle.Vertexes.Vertex0;
            Vector3 triVec1 = triangle.Vertexes.Vertex1;
            Vector3 triVec2 = triangle.Vertexes.Vertex2;
            //mesh.GetVertex(triangle.GetVertexIndex(0), out triVec0);
            //mesh.GetVertex(triangle.GetVertexIndex(1), out triVec1);
            //mesh.GetVertex(triangle.GetVertexIndex(2), out triVec2);

            // Deano move tri into world space
            //Matrix transformMatrix = mesh.TransformMatrix;
            Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0);
            Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1);
            Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2);

            MyTriangle tri = new MyTriangle(ref triVec0, ref triVec1, ref triVec2);
            #endregion


            #region triEdge0
            Vector3 pt0;
            Vector3 pt1;
            tri.GetPoint(0, out pt0);
            tri.GetPoint(1, out pt1);

            Vector3 triEdge0;
            Vector3.Subtract(ref pt1, ref pt0, out triEdge0);
            #endregion

            #region triEdge1
            Vector3 pt2;
            tri.GetPoint(2, out pt2);

            Vector3 triEdge1;
            Vector3.Subtract(ref pt2, ref pt1, out triEdge1);
            #endregion

            #region triEdge2
            Vector3 triEdge2;
            Vector3.Subtract(ref pt0, ref pt2, out triEdge2);
            #endregion


            if (triEdge0.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }
            if (triEdge1.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }
            if (triEdge2.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }


            /*
             * triEdge0 = MyMwcUtils.Normalize(triEdge0);
             * triEdge1 = MyMwcUtils.Normalize(triEdge1);
             * triEdge2 = MyMwcUtils.Normalize(triEdge2);
             */
            triEdge0.Normalize();
            triEdge1.Normalize();
            triEdge2.Normalize();

            //Vector3 triNormal = triangle.Plane.Normal;
            Vector3 triNormal = plane.Normal;
            Vector3.TransformNormal(ref triNormal, ref transformMatrix, out triNormal);



            // the 15 potential separating axes (comment by Marek Rosa: note says 15 but code uses 13... I don't know why, mistake in the note??)
            const int        NUM_AXES = 13;
            MyVector3Array13 axes     = new MyVector3Array13();

            axes[0]  = triNormal;
            axes[1]  = dirs0.Right;
            axes[2]  = dirs0.Up;
            axes[3]  = dirs0.Backward;
            axes[4]  = Vector3.Cross(axes[1], triEdge0);
            axes[5]  = Vector3.Cross(axes[1], triEdge1);
            axes[6]  = Vector3.Cross(axes[1], triEdge2);
            axes[7]  = Vector3.Cross(axes[2], triEdge0);
            axes[8]  = Vector3.Cross(axes[2], triEdge1);
            axes[9]  = Vector3.Cross(axes[2], triEdge2);
            axes[10] = Vector3.Cross(axes[3], triEdge0);
            axes[11] = Vector3.Cross(axes[3], triEdge1);
            axes[12] = Vector3.Cross(axes[3], triEdge2);

            // the overlap depths along each axis
            MyFloatArray13 overlapDepths = new MyFloatArray13();

            // see if the boxes are separate along any axis, and if not keep a
            // record of the depths along each axis
            int i;
            for (i = 0; i < NUM_AXES; ++i)
            {
                overlapDepths[i] = 1.0f;

                bool b;
                overlapDepths[i] = Disjoint(out b, axes[i], newBox, tri, collTolerance);
                if (b)
                {
                    return(false);
                }
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int   minAxis  = -1;

            for (i = 0; i < NUM_AXES; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                {
                    continue;
                }

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                axes[i]          *= invl;
                overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (overlapDepths[i] < minDepth)
                {
                    minDepth = overlapDepths[i];
                    minAxis  = i;
                }
            }

            if (minAxis == -1)
            {
                return(false);
            }


            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D     = newBox.GetCentre() - tri.Centre;
            Vector3 N     = axes[minAxis];
            float   depth = overlapDepths[minAxis];

            if (Vector3.Dot(D, N) > 0.0f)
            {
                N *= -1;
            }

            Vector3 boxOldPos = oldBoxPos;                   //(info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 boxNewPos = newBoxPos;                   // (info.Skin0.Owner != null) ? info.Skin0.Owner.Position : Vector3.Zero;
            Vector3 meshPos   = transformMatrix.Translation; // (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            m_pts.Clear();

            const float combinationDist = 0.05f;
            GetBoxTriangleIntersectionPoints(m_pts, newBox, tri, depth + combinationDist);

            // adjust the depth
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            #region oldDepth
            float oldDepth;
            Vector3.Dot(ref delta, ref N, out oldDepth);
            oldDepth += depth;
            #endregion


            // report collisions

            int numPts = m_pts.Count;
            if (numPts > 0)
            {
                for (i = 0; i < numPts; ++i)
                {
                    collPoints.Add(new MyCollisionPointStruct(-oldDepth, new MySmallCollPointInfo(m_pts[i] - boxNewPos, m_pts[i] - meshPos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, N, -oldDepth, m_pts[i])));
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
        private bool DoOverlapBoxTriangleStaticTest(MyBox oldBox, MyBox newBox,
                                                    MyTriangle_Vertex_Normal triangle, MyPlane plane, float collTolerance,
                                                    ref Matrix transformMatrix, ref Vector3 oldBoxPos, ref Vector3 newBoxPos)
        {
            Matrix dirs0 = newBox.Orientation;

            dirs0.Translation = Vector3.Zero;

            #region REFERENCE: Triangle tri = new Triangle(mesh.GetVertex(triangleVertexes.GetVertexIndex(0)),mesh.GetVertex(triangleVertexes.GetVertexIndex(1)),mesh.GetVertex(triangleVertexes.GetVertexIndex(2)));
            Vector3 triVec0 = triangle.Vertexes.Vertex0;
            Vector3 triVec1 = triangle.Vertexes.Vertex1;
            Vector3 triVec2 = triangle.Vertexes.Vertex2;

            // Deano move tri into world space
            //Matrix transformMatrix = mesh.TransformMatrix;
            Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0);
            Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1);
            Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2);

            MyTriangle tri = new MyTriangle(ref triVec0, ref triVec1, ref triVec2);
            #endregion

            #region REFERENCE Vector3 triEdge0 = (tri.GetPoint(1) - tri.GetPoint(0));
            Vector3 pt0;
            Vector3 pt1;
            tri.GetPoint(0, out pt0);
            tri.GetPoint(1, out pt1);

            Vector3 triEdge0;
            Vector3.Subtract(ref pt1, ref pt0, out triEdge0);
            #endregion

            #region REFERENCE Vector3 triEdge1 = (tri.GetPoint(2) - tri.GetPoint(1));
            Vector3 pt2;
            tri.GetPoint(2, out pt2);

            Vector3 triEdge1;
            Vector3.Subtract(ref pt2, ref pt1, out triEdge1);
            #endregion

            #region REFERENCE Vector3 triEdge2 = (tri.GetPoint(0) - tri.GetPoint(2));
            Vector3 triEdge2;
            Vector3.Subtract(ref pt0, ref pt2, out triEdge2);
            #endregion

            if (triEdge0.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }
            if (triEdge1.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }
            if (triEdge2.LengthSquared() < MyMwcMathConstants.EPSILON)
            {
                return(false);
            }

            triEdge0.Normalize();
            triEdge1.Normalize();
            triEdge2.Normalize();

            //Vector3 triNormal = triangle.Plane.Normal;
            Vector3 triNormal = plane.Normal;
            Vector3.TransformNormal(ref triNormal, ref transformMatrix, out triNormal);

            // the 15 potential separating axes
            const int numAxes = 13;
            Vector3[] axes    = new Vector3[numAxes];

            axes[0] = triNormal;
            axes[1] = dirs0.Right;
            axes[2] = dirs0.Up;
            axes[3] = dirs0.Backward;
            Vector3.Cross(ref axes[1], ref triEdge0, out axes[4]);
            Vector3.Cross(ref axes[1], ref triEdge1, out axes[5]);
            Vector3.Cross(ref axes[1], ref triEdge2, out axes[6]);
            Vector3.Cross(ref axes[2], ref triEdge0, out axes[7]);
            Vector3.Cross(ref axes[2], ref triEdge1, out axes[8]);
            Vector3.Cross(ref axes[2], ref triEdge2, out axes[9]);
            Vector3.Cross(ref axes[3], ref triEdge0, out axes[10]);
            Vector3.Cross(ref axes[3], ref triEdge1, out axes[11]);
            Vector3.Cross(ref axes[3], ref triEdge2, out axes[12]);

            // the overlap depths along each axis
            float[] overlapDepths = new float[numAxes];

            // see if the boxes are separate along any axis, and if not keep a
            // record of the depths along each axis
            int i;
            for (i = 0; i < numAxes; ++i)
            {
                overlapDepths[i] = 1.0f;
                if (Disjoint(out overlapDepths[i], axes[i], newBox, tri, collTolerance))
                {
                    return(false);
                }
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int   minAxis  = -1;

            for (i = 0; i < numAxes; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                {
                    continue;
                }

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                axes[i]          *= invl;
                overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (overlapDepths[i] < minDepth)
                {
                    minDepth = overlapDepths[i];
                    minAxis  = i;
                }
            }

            if (minAxis == -1)
            {
                return(false);
            }

            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D     = newBox.GetCentre() - tri.Centre;
            Vector3 N     = axes[minAxis];
            float   depth = overlapDepths[minAxis];

            if (Vector3.Dot(D, N) > 0.0f)
            {
                N *= -1;
            }

            Vector3 boxOldPos = oldBoxPos;                   //(info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero;
            Vector3 boxNewPos = newBoxPos;                   // (info.Skin0.Owner != null) ? info.Skin0.Owner.Position : Vector3.Zero;
            Vector3 meshPos   = transformMatrix.Translation; // (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero;

            List <Vector3> pts = new List <Vector3>();
            //pts.Clear();

            const float combinationDist = 0.05f;
            GetBoxTriangleIntersectionPoints(pts, newBox, tri, depth + combinationDist);

            // adjust the depth
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            #region oldDepth
            float oldDepth;
            Vector3.Dot(ref delta, ref N, out oldDepth);
            oldDepth += depth;
            #endregion

            // report collisions
            int numPts = pts.Count;

            if (numPts > 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        //  GetBoxTriangleIntersectionPoints
        //  Pushes intersection points onto the back of pts. Returns the
        //  number of points found.
        //  Points that are close together (compared to 
        //  combinationDistance) get combined
        private int GetBoxTriangleIntersectionPoints(List<MyCP> pts, MyBox box, MyColDetVoxelTriangle triangle, float combinationDistance)
        {
            // first intersect each edge of the box with the triangleVertexes
            MyBox.Edge[] edges;
            box.GetEdges(out edges);
            Vector3[] boxPts;
            box.GetCornerPoints(out boxPts);

            float tS;
            float tv1, tv2;

            int iEdge;
            for (iEdge = 0; iEdge < 12; ++iEdge)
            {
                MyBox.Edge edge = edges[iEdge];
                MySegment seg = new MySegment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]);
                if (this.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle))
                {
                    float depthA = Vector3.Dot(boxPts[(int)edge.Ind0] - seg.GetPoint(tS), triangle.Normal);
                    float depthB = Vector3.Dot(boxPts[(int)edge.Ind1] - seg.GetPoint(tS), triangle.Normal);
                    AddPoint(pts, seg.GetPoint(tS),triangle.Normal, depthA < depthB ? depthA : depthB , combinationDistance * combinationDistance);
                }
            }

            Vector3 pos, n;
            // now each edge of the triangleVertexes with the box
            for (iEdge = 0; iEdge < 3; ++iEdge)
            {
                Vector3 pt0 = triangle.GetPoint(iEdge);
                Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3);
                MySegment s1 = new MySegment(pt0, pt1 - pt0);
                MySegment s2 = new MySegment(pt1, pt0 - pt1);
                if (box.SegmentIntersect(out tS, out pos, out n, s1))
                {
                    float depthA = Vector3.Dot(pt0 - pos, triangle.Normal);
                    float depthB = Vector3.Dot(pt1 - pos, triangle.Normal);
                    AddPoint(pts, pos, triangle.Normal, depthA < depthB ? depthA : depthB, combinationDistance * combinationDistance);
                }
                if (box.SegmentIntersect(out tS, out pos, out n, s2))
                {
                    float depthA = Vector3.Dot(pt0 - pos, triangle.Normal);
                    float depthB = Vector3.Dot(pt1 - pos, triangle.Normal);
                    AddPoint(pts, pos, triangle.Normal, depthA < depthB ? depthA : depthB, combinationDistance * combinationDistance);
                }
            }

            return pts.Count;
        }
        protected override bool Interact(bool staticCollision)
        {
            if (!staticCollision)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("BoxBoxInteraction");
            }

            try
            {
                MyRBBoxElement rbbox0 = (MyRBBoxElement)RBElement1;
                MyRBBoxElement rbbox1 = (MyRBBoxElement)RBElement2;

                MyBox box0 = m_TempBox1;
                MyBox box1 = m_TempBox2;

                Matrix matrix0 = rbbox0.GetGlobalTransformation();
                Matrix matrix1 = rbbox1.GetGlobalTransformation();

                box0.Transform.Orientation             = matrix0;
                box0.Transform.Orientation.Translation = Vector3.Zero;
                box0.Transform.Position = matrix0.Translation - Vector3.TransformNormal(rbbox0.Size * 0.5f, matrix0);

                box1.Transform.Orientation             = matrix1;
                box1.Transform.Orientation.Translation = Vector3.Zero;
                box1.Transform.Position = matrix1.Translation - Vector3.TransformNormal(rbbox1.Size * 0.5f, matrix1);

                box0.SideLengths = rbbox0.Size;
                box1.SideLengths = rbbox1.Size;

                // see if the boxes are separate along any axis, and if not keep a
                // record of the depths along each axis
                for (int i = 0; i < 15; ++i)
                {
                    switch (i)
                    {
                    case 0: seperatingAxes[0] = box0.Orientation.Right; break;

                    case 1: seperatingAxes[1] = box0.Orientation.Up; break;

                    case 2: seperatingAxes[2] = box0.Orientation.Backward; break;

                    case 3: seperatingAxes[3] = box1.Orientation.Right; break;

                    case 4: seperatingAxes[4] = box1.Orientation.Up; break;

                    case 5: seperatingAxes[5] = box1.Orientation.Backward; break;

                    case 6: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[3], out seperatingAxes[6]); break;

                    case 7: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[4], out seperatingAxes[7]); break;

                    case 8: Vector3.Cross(ref seperatingAxes[0], ref seperatingAxes[5], out seperatingAxes[8]); break;

                    case 9: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[3], out seperatingAxes[9]); break;

                    case 10: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[4], out seperatingAxes[10]); break;

                    case 11: Vector3.Cross(ref seperatingAxes[1], ref seperatingAxes[5], out seperatingAxes[11]); break;

                    case 12: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[3], out seperatingAxes[12]); break;

                    case 13: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[4], out seperatingAxes[13]); break;

                    case 14: Vector3.Cross(ref seperatingAxes[2], ref seperatingAxes[5], out seperatingAxes[14]); break;
                    }

                    // If we can't normalise the axis, skip it
                    if (seperatingAxes[i].LengthSquared() < MyPhysicsConfig.CollisionEpsilon)
                    {
                        continue;
                    }

                    overlapDepth[i] = float.MaxValue;

                    if (Disjoint(out overlapDepth[i], ref seperatingAxes[i], box0, box1, MyPhysicsConfig.CollisionEpsilon))
                    {
                        return(false);
                    }
                }

                if (staticCollision)
                {
                    return(true);  // Static collision: we're done.
                }

                // Dynamic collision.
                // The boxes overlap, find the seperation depth closest to 0.
                float minDepth = float.MaxValue;
                int   minAxis  = -1;

                for (int i = 0; i < 15; ++i)
                {
                    // If we can't normalise the axis, skip it
                    float l2 = seperatingAxes[i].LengthSquared();
                    if (l2 < MyPhysicsConfig.CollisionEpsilon)
                    {
                        continue;
                    }

                    // Normalise the separation axis and depth
                    float invl = 1.0f / (float)System.Math.Sqrt(l2);
                    seperatingAxes[i] *= invl;
                    overlapDepth[i]   *= invl;

                    // If this axis is the minmum, select it
                    if (overlapDepth[i] < minDepth)
                    {
                        minDepth = overlapDepth[i];
                        minAxis  = i;
                    }
                }

                if (minAxis == -1)
                {
                    return(false);
                }

                // Make sure the axis is facing towards the 0th box.
                // if not, invert it
                Vector3 D     = box1.GetCentre() - box0.GetCentre();
                Vector3 N     = seperatingAxes[minAxis];
                float   depth = overlapDepth[minAxis];

                if (Vector3.Dot(D, N) < 0.0f)
                {
                    N *= -1.0f;
                }

                float minA = MathHelper.Min(box0.SideLengths.X, MathHelper.Min(box0.SideLengths.Y, box0.SideLengths.Z));
                float minB = MathHelper.Min(box1.SideLengths.X, MathHelper.Min(box1.SideLengths.Y, box1.SideLengths.Z));

                float combinationDist = 0.05f * MathHelper.Min(minA, minB);

                // the contact points
                contactPts.Clear();

                int numPts = contactPts.Count;
                GetBoxBoxIntersectionPoints(contactPts, box0, box1, combinationDist, MyPhysicsConfig.CollisionEpsilon);
                numPts = contactPts.Count;

                MyRigidBody rbo0 = GetRigidBody1();
                MyRigidBody rbo1 = GetRigidBody2();
                float       dt   = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

                Vector3 body0OldPos = rbo0.Position;
                Vector3 body1OldPos = rbo1.Position;
                Vector3 body0NewPos = (rbo0.Position + rbo0.LinearVelocity * dt);
                Vector3 body1NewPos = (rbo1.Position + rbo1.LinearVelocity * dt);

                #region REFERENCE: Vector3 bodyDelta = body0NewPos - body0OldPos - body1NewPos + body1OldPos;
                Vector3 bodyDelta;
                Vector3.Subtract(ref body0NewPos, ref body0OldPos, out bodyDelta);
                Vector3.Subtract(ref bodyDelta, ref body1NewPos, out bodyDelta);
                Vector3.Add(ref bodyDelta, ref body1OldPos, out bodyDelta);
                #endregion

                #region REFERENCE: float bodyDeltaLen = Vector3.Dot(bodyDelta,N);
                float bodyDeltaLen;
                Vector3.Dot(ref bodyDelta, ref N, out bodyDeltaLen);
                #endregion

                float oldDepth = depth + bodyDeltaLen;

                MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc();
                {
                    int numCollPts = 0;

                    Vector3 SATPoint;

                    switch (minAxis)
                    {
                    // Box0 face, Box1 corner collision
                    case 0:
                    case 1:
                    case 2:
                    {
                        // Get the lowest point on the box1 along box1 normal
                        GetSupportPoint(out SATPoint, box1, -N);
                        break;
                    }

                    // We have a Box2 corner/Box1 face collision
                    case 3:
                    case 4:
                    case 5:
                    {
                        // Find with vertex on the triangleVertexes collided
                        GetSupportPoint(out SATPoint, box0, N);
                        break;
                    }

                    // We have an edge/edge collision
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                    case 10:
                    case 11:
                    case 12:
                    case 13:
                    case 14:
                    {
                        {
                            // Retrieve which edges collided.
                            int i  = minAxis - 6;
                            int ia = i / 3;
                            int ib = i - ia * 3;
                            // find two P0, P1 point on both edges.
                            Vector3 P0, P1;
                            GetSupportPoint(out P0, box0, N);
                            GetSupportPoint(out P1, box1, -N);
                            // Find the edge intersection.
                            // plane along N and F, and passing through PB
                            Vector3 box0Orient, box1Orient;
                            MyPhysicsUtils.MyPhysicsUnsafe.Get(ref box0.Transform.Orientation, ia, out box0Orient);
                            MyPhysicsUtils.MyPhysicsUnsafe.Get(ref box1.Transform.Orientation, ib, out box1Orient);

                            #region REFERENCE: Vector3 planeNormal = Vector3.Cross(N, box1Orient[ib]);
                            Vector3 planeNormal;
                            Vector3.Cross(ref N, ref box1Orient, out planeNormal);
                            #endregion

                            #region REFERENCE: float planeD = Vector3.Dot(planeNormal, P1);
                            float planeD;
                            Vector3.Dot(ref planeNormal, ref P1, out planeD);
                            #endregion

                            // find the intersection t, where Pintersection = P0 + t*box edge dir
                            #region REFERENCE: float div = Vector3.Dot(box0Orient, planeNormal);
                            float div;
                            Vector3.Dot(ref box0Orient, ref planeNormal, out div);
                            #endregion

                            // plane and ray colinear, skip the intersection.
                            if (System.Math.Abs(div) < MyPhysicsConfig.CollisionEpsilon)
                            {
                                return(false);
                            }

                            float t = (planeD - Vector3.Dot(P0, planeNormal)) / div;

                            // point on edge of box0
                            #region REFERENCE: P0 += box0Orient * t;
                            P0 = Vector3.Add(Vector3.Multiply(box0Orient, t), P0);
                            #endregion

                            #region REFERENCE: SATPoint = (P0 + (0.5f * depth) * N);
                            Vector3.Multiply(ref N, 0.5f * depth, out SATPoint);
                            Vector3.Add(ref SATPoint, ref P0, out SATPoint);
                            #endregion
                        }
                        break;
                    }

                    default:
                    {
                        SATPoint = Vector3.Zero;
                        Debug.Assert(false);
                        break;
                    }
                    }

                    // distribute the depth according to the distance to the SAT point
                    if (numPts > 0)
                    {
                        float minDist = float.MaxValue;
                        float maxDist = float.MinValue;
                        for (int i = 0; i < numPts; ++i)
                        {
                            float dist = MyPhysicsUtils.PointPointDistance(contactPts[i].Pos, SATPoint);
                            if (dist < minDist)
                            {
                                minDist = dist;
                            }
                            if (dist > maxDist)
                            {
                                maxDist = dist;
                            }
                        }

                        // got some intersection points
                        for (int i = 0; i < numPts; ++i)
                        {
                            float minDepthScale = 0.0f;
                            float dist          = MyPhysicsUtils.PointPointDistance(contactPts[i].Pos, SATPoint);

                            float safeDivisionDist = (maxDist - minDist);
                            if ((maxDist - minDist) == 0.0f)
                            {
                                safeDivisionDist = MyPhysicsConfig.CollisionEpsilon;
                            }
                            float depthScale = (dist - minDist) / safeDivisionDist;

                            depth = (1.0f - depthScale) * oldDepth + minDepthScale * depthScale * oldDepth;

                            if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                            {
                                collPtArray[numCollPts++] = new MySmallCollPointInfo(contactPts[i].Pos - body0OldPos, contactPts[i].Pos - body1OldPos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, N, depth, contactPts[i].Pos);
                            }
                        }
                    }
                    else
                    {
                        #region REFERENCE: collPts.Add(new CollPointInfo(SATPoint - body0NewPos, SATPoint - body1NewPos, oldDepth));
                        //collPts.Add(new CollPointInfo(SATPoint - body0NewPos, SATPoint - body1NewPos, oldDepth));
                        Vector3 cp0;
                        Vector3.Subtract(ref SATPoint, ref body0NewPos, out cp0);

                        Vector3 cp1;
                        Vector3.Subtract(ref SATPoint, ref body1NewPos, out cp1);

                        if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                        {
                            collPtArray[numCollPts++] = new MySmallCollPointInfo(cp0, cp1, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, N, oldDepth, SATPoint);
                        }
                        #endregion
                    }

                    // report Collisions
                    MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, numCollPts);
                }
                MyContactInfoCache.FreeStackAlloc(collPtArray);
            }
            catch
            {
                throw;
            }
            finally
            {
                if (!staticCollision)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }
            }
            return(false);
        }
Exemple #19
0
        protected override bool Interact(bool staticCollision)
        {
            if (RBElement1.GetElementType() != MyRBElementType.ET_BOX)
            {
                SwapElements();
            }

            if (!staticCollision)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("BoxVoxelInteraction");
            }

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Transformations");

            MyRBBoxElement rbbox0 = (MyRBBoxElement)RBElement1;

            Matrix matrix0 = RBElement1.GetGlobalTransformation();

            MyBox box = tempBox;

            box.Transform.Orientation             = matrix0;
            box.Transform.Orientation.Translation = Vector3.Zero;
            box.Transform.Position = matrix0.Translation - Vector3.TransformNormal(rbbox0.Size * 0.5f, matrix0);

            box.SideLengths = rbbox0.Size;

            float boxRadius = box.GetBoundingRadiusAroundCentre();

            #region boxCentre
            Vector3 boxCentre;
            box.GetCentre(out boxCentre);
            // Deano need to trasnform the box center into mesh space
            //Matrix invTransformMatrix = mesh.InverseTransformMatrix;
            //Vector3.Transform(ref boxCentre, ref invTransformMatrix, out boxCentre);
            #endregion

            BoundingBox bb = RBElement1.GetWorldSpaceAABB();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("GetPotentialTrianglesForColDet");
            // extent bb for the movement
            int numTriangles;
            MyVoxelMaps.GetPotentialTrianglesForColDet(out numTriangles, ref bb);

            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();

            if (staticCollision)
            {
                for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                {
                    MyColDetVoxelTriangle triangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle];

                    // quick early test is done in mesh space
                    float dist = triangle.Plane.DotCoordinate(boxCentre);

                    if (dist > boxRadius)
                    {
                        continue;
                    }

                    // skip too narrow triangles causing destability
                    if ((triangle.Vertex0 - triangle.Vertex1).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex1 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex0 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon
                        )
                    {
                        continue;
                    }

                    if (DoOverlapBoxTriangleStaticTest(box, ref triangle))
                    {
                        return(true);
                    }
                }
            }
            else
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("for DoOverlapBoxTriangleTest");

                for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                {
                    MyColDetVoxelTriangle triangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle];

                    // skip too narrow triangles causing destability
                    if ((triangle.Vertex0 - triangle.Vertex1).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex1 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon ||
                        (triangle.Vertex0 - triangle.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon
                        )
                    {
                        continue;
                    }

                    DoOverlapBoxTriangleTest(box, ref triangle);
                }

                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }

            if (!staticCollision)
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
            }
            return(false);
        }
        /// <summary>
        /// The AABox has a corner at the origin and size sides.
        /// </summary>
        private static int GetAABox2EdgeIntersectionPoints(List<ContactPoint> pts,
            ref Vector3 sides, MyBox box, ref Vector3 edgePt0, ref Vector3 edgePt1,
            ref Matrix origBoxOrient, ref Vector3 origBoxPos,
            float combinationDistanceSq)
        {
            // The AABox faces are aligned with the world directions. Loop 
            // over the 3 directions and do the two tests. We know that the
            // AABox has a corner at the origin
            #region REFERENCE: Vector3 edgeDir = JiggleMath.NormalizeSafe(edgePt1 - edgePt0);
            Vector3 edgeDir;
            Vector3.Subtract(ref edgePt1, ref edgePt0, out edgeDir);
            MyPhysicsUtils.NormalizeSafe(ref edgeDir);
            #endregion

            int num = 0;

            for (int idir = 3; idir-- != 0; )
            {
                // skip edge/face tests if nearly parallel
                if (System.Math.Abs(MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgeDir, idir)) < 0.1f) continue;

                int jdir = (idir + 1) % 3;
                int kdir = (idir + 2) % 3;
                for (int iface = 2; iface-- != 0; )
                {
                    float offset = 0.0f;
                    if (iface == 1)
                    {
                        offset = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, idir);
                    }

                    float dist0 = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgePt0, idir) - offset;
                    float dist1 = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref edgePt1, idir) - offset;

                    float frac = -1.0f;

                    if (dist0 * dist1 < -MyPhysicsConfig.CollisionEpsilon)
                        frac = -dist0 / (dist1 - dist0);
                    else if (System.Math.Abs(dist0) < MyPhysicsConfig.CollisionEpsilon)
                        frac = 0.0f;
                    else if (System.Math.Abs(dist1) < MyPhysicsConfig.CollisionEpsilon)
                        frac = 1.0f;

                    if (frac >= 0.0f)
                    {
                        #region REFERENCE: Vector3 pt = (1.0f - frac) * edgePt0 + frac * edgePt1
                        Vector3 tmp; Vector3 pt;
                        Vector3.Multiply(ref edgePt1, frac, out tmp);
                        Vector3.Multiply(ref edgePt0, 1.0f - frac, out pt);
                        Vector3.Add(ref pt, ref tmp, out pt);
                        #endregion

                        // check the point is within the face rectangle
                        float ptJdir = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref pt, jdir);
                        float ptKdir = MyPhysicsUtils.MyPhysicsUnsafe.Get(ref pt, kdir);

                        if ((ptJdir > -MyPhysicsConfig.CollisionEpsilon) &&
                            (ptJdir < MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, jdir) + MyPhysicsConfig.CollisionEpsilon) &&
                            (ptKdir > -MyPhysicsConfig.CollisionEpsilon) &&
                            (ptKdir < MyPhysicsUtils.MyPhysicsUnsafe.Get(ref sides, kdir) + MyPhysicsConfig.CollisionEpsilon))
                        {
                            // woohoo got a point
                            #region REFERENCE: Vector3 pos = origBoxPos + Vector3.Transform(pt, origBoxOrient);
                            Vector3 pos;
                            Vector3.Transform(ref pt, ref origBoxOrient, out pos);
                            Vector3.Add(ref origBoxPos, ref pos, out pos);
                            #endregion

                            AddPoint(pts, ref pos, combinationDistanceSq);

                            if (++num == 2)
                                return num;
                        }
                    }
                }
            }
            return num;
        }
        private bool DoOverlapBoxTriangleTest(MyBox box, ref MyColDetVoxelTriangle triangle)
        {
            Matrix dirs0 = box.Orientation;

            Vector3 triEdge0;
            Vector3 triEdge1;
            Vector3 triEdge2;

            triEdge0 = MyMwcUtils.Normalize(triangle.Edge0);
            triEdge1 = MyMwcUtils.Normalize(triangle.Edge1);
            triEdge2 = MyMwcUtils.Normalize(triangle.Edge2);

            Vector3 triNormal = triangle.Plane.Normal;

            // the 15 potential separating axes (comment by Marek Rosa: note says 15 but code uses 13... I don't know why, mistake in the note??)
            const int NUM_AXES = 13;
            MyVector3Array13 axes = new MyVector3Array13();

            axes[0] = triNormal;
            axes[1] = dirs0.Right;
            axes[2] = dirs0.Up;
            axes[3] = dirs0.Backward;
            axes[4] = Vector3.Cross(axes[1], triEdge0);
            axes[5] = Vector3.Cross(axes[1], triEdge1);
            axes[6] = Vector3.Cross(axes[1], triEdge2);
            axes[7] = Vector3.Cross(axes[2], triEdge0);
            axes[8] = Vector3.Cross(axes[2], triEdge1);
            axes[9] = Vector3.Cross(axes[2], triEdge2);
            axes[10] = Vector3.Cross(axes[3], triEdge0);
            axes[11] = Vector3.Cross(axes[3], triEdge1);
            axes[12] = Vector3.Cross(axes[3], triEdge2);

            // the overlap depths along each axis
            MyFloatArray13 overlapDepths = new MyFloatArray13();

            // see if the boxes are separate along any axis, and if not keep a 
            // record of the depths along each axis
            int i;
            for (i = 0; i < NUM_AXES; ++i)
            {
                overlapDepths[i] = 1.0f;

                bool b;
                overlapDepths[i] = Disjoint(out b, axes[i], box, triangle, MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon);
                if (b) return false;
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int minAxis = -1;

            for (i = 0; i < NUM_AXES; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                    continue;

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                axes[i] *= invl;
                overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (overlapDepths[i] < minDepth)
                {
                    minDepth = overlapDepths[i];
                    minAxis = i;
                }
            }

            if (minAxis == -1)
                return false;

            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D = box.GetCentre() - triangle.Centre;
            Vector3 N = axes[minAxis];
            float depth = overlapDepths[minAxis];

            if (Vector3.Dot(D, N) < 0.0f)
                N *= -1;

            MyRigidBody rbo0 = GetRigidBody1();
            MyRigidBody rbo1 = GetRigidBody2();
            float dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

            Vector3 boxOldPos = rbo0.Position;
            Vector3 boxNewPos = rbo0.Position + rbo0.LinearVelocity * dt;
            Vector3 meshPos = rbo1.Position;

            m_CPList.Clear();

            GetBoxTriangleIntersectionPoints(m_CPList, box, triangle, MyPhysicsConfig.CollisionEpsilon);

            // adjust the depth 
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            // report collisions
            int numPts = m_CPList.Count;
            MySmallCollPointInfo[] collPtArray = MyContactInfoCache.SCPIStackAlloc();
            {
                if (numPts > 0)
                {
                    if (numPts >= MyPhysicsConfig.MaxContactPoints)
                    {
                        numPts = MyPhysicsConfig.MaxContactPoints - 1;
                    }

                    // adjust positions
                    for (i = 0; i < numPts; ++i)
                    {
                        collPtArray[i] = new MySmallCollPointInfo(m_CPList[i].m_Position - boxOldPos, m_CPList[i].m_Position - meshPos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, m_CPList[i].m_Normal, m_CPList[i].m_Depth, m_CPList[i].m_Position);
                    }

                    MyPhysics.physicsSystem.GetContactConstraintModule().AddContactConstraint(this, collPtArray, numPts);
                    MyContactInfoCache.FreeStackAlloc(collPtArray);
                    return true;
                }
                else
                {
                    MyContactInfoCache.FreeStackAlloc(collPtArray);
                    return false;
                }
            }
          
        }
        /// <summary>
        /// Pushes intersection points onto the back of pts. Returns the
        /// number of points found.
        /// Points that are close together (compared to 
        /// combinationDistance) get combined
        /// dirToBody0 is the collision normal towards box0
        /// </summary>
        private static int GetBoxBoxIntersectionPoints(List<ContactPoint> pts,
            MyBox box0, MyBox box1, float combinationDistance,
            float collTolerance)
        {
            // first transform box1 into box0 space - there box0 has a corner
            // at the origin and faces parallel to the world planes. Then intersect
            // each of box1's edges with box0 faces, transforming each point back into
            // world space. Finally combine points
            float tolVal = 0.5f * collTolerance;

            Vector3 tol = new Vector3(tolVal);

            combinationDistance += collTolerance * 2.0f * (float)System.Math.Sqrt(3.0d);

            for (int ibox = 0; ibox < 2; ++ibox)
            {
                MyBox boxA = (ibox != 0) ? box1 : box0;
                MyBox boxB = (ibox != 0) ? box0 : box1;

                #region REFERENCE: Matrix boxAInvOrient = Matrix.Transpose(boxA.Orientation);
                Matrix boxAInvOrient;
                Matrix.Transpose(ref boxA.Transform.Orientation, out boxAInvOrient);
                #endregion

                #region REFERENCE: Vector3 pos = Vector3.Transform(boxB.m_initialSunWindPosition - boxA.m_initialSunWindPosition,boxAInvOrient)
                Vector3 pos;
                Vector3.Subtract(ref boxB.Transform.Position, ref boxA.Transform.Position, out pos);
                Vector3.TransformNormal(ref pos, ref boxAInvOrient, out pos);
                #endregion

                #region REFERENCE: Matrix boxOrient = boxB.Orientation * boxAInvOrient;
                Matrix boxOrient;
                Matrix.Multiply(ref boxB.Transform.Orientation, ref boxAInvOrient, out boxOrient);
                #endregion

                MyBox box = tempBox;
                box.Position = pos;
                box.Orientation = boxOrient;
                box.SideLengths = boxB.SideLengths;


                // if we get more than a certain number of points back from this call,
                // and iBox == 0, could probably skip the other test...
                Vector3 sL = boxA.SideLengths;
                GetAABox2BoxEdgesIntersectionPoints(pts, ref sL,
                    box, ref boxA.Transform.Orientation, ref boxA.Transform.Position, combinationDistance * combinationDistance);
            }

            return pts.Count;
        }
 private float Disjoint(out bool b, Vector3 axis, MyBox box, MyColDetVoxelTriangle triangle, float collTolerance)
 {
     float ret;
     b = Disjoint(out ret, axis, box, triangle, collTolerance);
     return ret;
 }        
        private static void GetSupportPoint(out Vector3 p, MyBox box, Vector3 axis)
        {
            #region INLINE: Vector3 orient0 = box.Orientation.Right;
            Vector3 orient0 = new Vector3(
                box.Transform.Orientation.M11,
                box.Transform.Orientation.M12,
                box.Transform.Orientation.M13);
            #endregion

            #region INLINE: Vector3 orient1 = box.Orientation.Up;
            Vector3 orient1 = new Vector3(
                box.Transform.Orientation.M21,
                box.Transform.Orientation.M22,
                box.Transform.Orientation.M23);
            #endregion

            #region INLINE: Vector3 orient2 = box.Orientation.Backward;
            Vector3 orient2 = new Vector3(
                box.Transform.Orientation.M31,
                box.Transform.Orientation.M32,
                box.Transform.Orientation.M33);
            #endregion

            #region INLINE: float ass = Vector3.Dot(axis,orient0);
            float ass = axis.X * orient0.X + axis.Y * orient0.Y + axis.Z * orient0.Z;
            #endregion

            #region INLINE: float au = Vector3.Dot(axis,orient1);
            float au = axis.X * orient1.X + axis.Y * orient1.Y + axis.Z * orient1.Z;
            #endregion

            #region INLINE: float ad = Vector3.Dot(axis,orient2);
            float ad = axis.X * orient2.X + axis.Y * orient2.Y + axis.Z * orient2.Z;
            #endregion

            float threshold = MyPhysicsConfig.CollisionEpsilon;

            box.GetCentre(out p);

            if (ass < -threshold)
            {
                #region INLINE: p += orient0 * (0.5 * box.SideLength.X);
                p.X += orient0.X * (0.5f * box.SideLengths.X);
                p.Y += orient0.Y * (0.5f * box.SideLengths.X);
                p.Z += orient0.Z * (0.5f * box.SideLengths.X);
                #endregion
            }
            else if (ass >= threshold)
            {
                #region INLINE: p -=  orient0 * (0.5 * box.SideLength.X);
                p.X -= orient0.X * (0.5f * box.SideLengths.X);
                p.Y -= orient0.Y * (0.5f * box.SideLengths.X);
                p.Z -= orient0.Z * (0.5f * box.SideLengths.X);
                #endregion
            }

            if (au < -threshold)
            {
                #region INLINE: p += orient1 * (0.5 * box.SideLength.Y);
                p.X += orient1.X * (0.5f * box.SideLengths.Y);
                p.Y += orient1.Y * (0.5f * box.SideLengths.Y);
                p.Z += orient1.Z * (0.5f * box.SideLengths.Y);
                #endregion
            }
            else if (au >= threshold)
            {
                #region INLINE: p -= orient1 * (0.5 * box.SideLength.Y);
                p.X -= orient1.X * (0.5f * box.SideLengths.Y);
                p.Y -= orient1.Y * (0.5f * box.SideLengths.Y);
                p.Z -= orient1.Z * (0.5f * box.SideLengths.Y);
                #endregion
            }

            if (ad < -threshold)
            {
                #region INLINE: p += orient2 * (0.5 * box.SideLength.Z);
                p.X += orient2.X * (0.5f * box.SideLengths.Z);
                p.Y += orient2.Y * (0.5f * box.SideLengths.Z);
                p.Z += orient2.Z * (0.5f * box.SideLengths.Z);
                #endregion
            }
            else if (ad >= threshold)
            {
                #region INLINE: p -= orient2 * (0.5 * box.SideLength.Z);
                p.X -= orient2.X * (0.5f * box.SideLengths.Z);
                p.Y -= orient2.Y * (0.5f * box.SideLengths.Z);
                p.Z -= orient2.Z * (0.5f * box.SideLengths.Z);
                #endregion
            }
        }
        private bool DoOverlapBoxTriangleStaticTest(MyBox box, ref MyColDetVoxelTriangle triangle)
        {

            Matrix dirs0 = box.Orientation;

            #region triEdge0
            Vector3 pt0;
            Vector3 pt1;
            triangle.GetPoint(0, out pt0);
            triangle.GetPoint(1, out pt1);

            Vector3 triEdge0;
            Vector3.Subtract(ref pt1, ref pt0, out triEdge0);

            if (triEdge0.LengthSquared() < MyPhysicsConfig.Epsilon)
                return false;

            #endregion

            #region triEdge1
            Vector3 pt2;
            triangle.GetPoint(2, out pt2);

            Vector3 triEdge1;
            Vector3.Subtract(ref pt2, ref pt1, out triEdge1);

            if (triEdge1.LengthSquared() < MyPhysicsConfig.Epsilon)
                return false;

            #endregion

            #region triEdge2
            Vector3 triEdge2;
            Vector3.Subtract(ref pt0, ref pt2, out triEdge2);

            if (triEdge2.LengthSquared() < MyPhysicsConfig.Epsilon)
                return false;

            #endregion

            triEdge0.Normalize();
            triEdge1.Normalize();
            triEdge2.Normalize();

            Vector3 triNormal = triangle.Plane.Normal;             

            m_axes[0] = triNormal;
            m_axes[1] = dirs0.Right;
            m_axes[2] = dirs0.Up;
            m_axes[3] = dirs0.Backward;
            Vector3.Cross(ref m_axes[1], ref triEdge0, out m_axes[4]);
            Vector3.Cross(ref m_axes[1], ref triEdge1, out m_axes[5]);
            Vector3.Cross(ref m_axes[1], ref triEdge2, out m_axes[6]);
            Vector3.Cross(ref m_axes[2], ref triEdge0, out m_axes[7]);
            Vector3.Cross(ref m_axes[2], ref triEdge1, out m_axes[8]);
            Vector3.Cross(ref m_axes[2], ref triEdge2, out m_axes[9]);
            Vector3.Cross(ref m_axes[3], ref triEdge0, out m_axes[10]);
            Vector3.Cross(ref m_axes[3], ref triEdge1, out m_axes[11]);
            Vector3.Cross(ref m_axes[3], ref triEdge2, out m_axes[12]);

            // the overlap depths along each axis
            

            // see if the boxes are separate along any axis, and if not keep a 
            // record of the depths along each axis
            int i;
            for (i = 0; i < numAxes; ++i)
            {
                m_overlapDepths[i] = 1.0f;
                if (Disjoint(out m_overlapDepths[i], m_axes[i], box, triangle, MyPhysicsConfig.CollisionEpsilon))
                    return false;
            }

            // The box overlap, find the separation depth closest to 0.
            float minDepth = float.MaxValue;
            int minAxis = -1;

            for (i = 0; i < numAxes; ++i)
            {
                // If we can't normalise the axis, skip it
                float l2 = m_axes[i].LengthSquared();
                if (l2 < MyPhysicsConfig.Epsilon)
                    continue;

                // Normalise the separation axis and the depth
                float invl = 1.0f / (float)System.Math.Sqrt(l2);
                m_axes[i] *= invl;
                m_overlapDepths[i] *= invl;

                // If this axis is the minimum, select it
                if (m_overlapDepths[i] < minDepth)
                {
                    minDepth = m_overlapDepths[i];
                    minAxis = i;
                }
            }

            if (minAxis == -1)
                return false;

            // Make sure the axis is facing towards the 0th box.
            // if not, invert it
            Vector3 D = box.GetCentre() - triangle.Centre;
            Vector3 N = m_axes[minAxis];
            float depth = m_overlapDepths[minAxis];

            if (Vector3.Dot(D, N) < 0.0f)
                N *= -1;

            MyRigidBody rbo0 = GetRigidBody1();
            MyRigidBody rbo1 = GetRigidBody2();
            float dt = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;

            Vector3 boxOldPos = rbo0.Position;
            Vector3 boxNewPos = rbo0.Position + rbo0.LinearVelocity * dt;
            Vector3 meshPos = rbo1.Position;

            m_CPList.Clear();
            GetBoxTriangleIntersectionPoints(m_CPList, box, triangle, MyPhysicsConfig.CollisionEpsilon);

            // adjust the depth 
            #region delta
            Vector3 delta;
            Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta);
            #endregion

            int numPts = m_CPList.Count;
            if (numPts > 0)
                return true;
            else
                return false;
        }