예제 #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);
        }
예제 #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);
        }
예제 #3
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);
        }
예제 #4
0
        public bool SegmentTriangleIntersection(out float tS, out float tT0, out float tT1,
                                                MySegment seg, MyColDetVoxelTriangle triangle)
        {
            /// the parameters - if hit then they get copied into the args
            float u, v, t;

            tS  = 0;
            tT0 = 0;
            tT1 = 0;

            Vector3 e1 = triangle.Edge0;
            Vector3 e2 = triangle.Edge1;
            Vector3 p  = Vector3.Cross(seg.Delta, e2);
            float   a  = Vector3.Dot(e1, p);

            if (a > -MyPhysicsConfig.Epsilon && a < MyPhysicsConfig.Epsilon)
            {
                return(false);
            }
            float   f = 1.0f / a;
            Vector3 s = seg.Origin - triangle.Origin;

            u = f * Vector3.Dot(s, p);
            if (u < 0.0f || u > 1.0f)
            {
                return(false);
            }
            Vector3 q = Vector3.Cross(s, e1);

            v = f * Vector3.Dot(seg.Delta, q);
            if (v < 0.0f || (u + v) > 1.0f)
            {
                return(false);
            }
            t = f * Vector3.Dot(e2, q);
            if (t < 0.0f || t > 1.0f)
            {
                return(false);
            }

            tS  = t;
            tT0 = u;
            tT1 = v;
            //if (tS != 0) tS = t;
            //if (tT0 != 0) tT0 = u;
            //if (tT1 != 0) tT1 = v;
            return(true);
        }
예제 #5
0
        public static void LoadData()
        {
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyVoxelMaps.LoadData");

            MyMwcLog.WriteLine("MyVoxelMaps.LoadData() - START");
            MyMwcLog.IncreaseIndent();

            m_voxelMaps.Clear();
            m_voxelMapsSafeIterationHelper.Clear();

            MyMwcLog.DecreaseIndent();
            MyMwcLog.WriteLine("MyVoxelMaps.LoadData() - END");

            for (int i = 0; i < MyVoxelConstants.MAX_POTENTIAL_COLDET_TRIANGLES_COUNT; i++)
            {
                PotentialColDetTriangles[i] = new MyColDetVoxelTriangle();
            }
            MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
        }
        protected override bool Interact(bool staticCollision)
        {
            if (staticCollision)
            {
                //MyCommonDebugUtils.AssertDebug(false, "Sphere-voxel static interaction called! And that's wrong.");
            }
            else
            {
                MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("SphereVoxelInteraction");

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

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

                Matrix matrix0 = RBElement1.GetGlobalTransformation();
                Matrix matrix1 = RBElement2.GetGlobalTransformation();

                float sphereRadius = ((MyRBSphereElement)RBElement1).Radius;

                Vector3 body0Pos = matrix0.Translation; // sphere pos
                Vector3 body1Pos = matrix1.Translation;

                float dt      = MyPhysics.physicsSystem.GetRigidBodyModule().CurrentTimeStep;
                float epsylon = MyPhysics.physicsSystem.GetRigidBodyModule().CollisionEpsilon;

                Vector3 newBody0Pos = matrix0.Translation + GetRigidBody1().LinearVelocity *dt;

                float sphereTolR  = epsylon + sphereRadius;
                float sphereTolR2 = sphereTolR * sphereTolR;

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

                Vector3 collNormal = Vector3.Zero;

                //var colDetThroughVoxels = MyConstants.SPHERE_VOXELMAP_COLDET_THROUGH_VOXELS;
                var colDetThroughVoxels = !GetRigidBody1().ReadFlag(RigidBodyFlag.RBF_COLDET_THROUGH_VOXEL_TRIANGLES);

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

                if (colDetThroughVoxels)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("colDetThroughVoxels");

                    BoundingSphere newSphere;
                    newSphere.Center = newBody0Pos;
                    newSphere.Radius = sphereRadius;

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PoolList.Get");
                    using (var voxelMapsFounded = PoolList <MyVoxelMap> .Get())
                    {
                        MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere");

                        MyVoxelMaps.GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere(ref newSphere, voxelMapsFounded, null);

                        MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("foreach (MyVoxelMap voxelMap in voxelMapsFounded)");
                        foreach (MyVoxelMap voxelMap in voxelMapsFounded)
                        {
                            if (voxelMap != null)
                            {
                                //  We will iterate only voxels contained in the bounding box of new sphere, so here we get min/max corned in voxel units
                                MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3(
                                                                                                      newSphere.Center.X - newSphere.Radius,
                                                                                                      newSphere.Center.Y - newSphere.Radius,
                                                                                                      newSphere.Center.Z - newSphere.Radius));
                                MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(new Vector3(
                                                                                                      newSphere.Center.X + newSphere.Radius,
                                                                                                      newSphere.Center.Y + newSphere.Radius,
                                                                                                      newSphere.Center.Z + newSphere.Radius));
                                voxelMap.FixVoxelCoord(ref minCorner);
                                voxelMap.FixVoxelCoord(ref maxCorner);

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

                                MyMwcVector3Int tempVoxelCoord;
                                for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++)
                                {
                                    for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++)
                                    {
                                        for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++)
                                        {
                                            byte voxelContent = voxelMap.GetVoxelContent(ref tempVoxelCoord);

                                            //  Ignore voxels bellow the ISO value (empty, partialy empty...)
                                            if (voxelContent < MyVoxelConstants.VOXEL_ISO_LEVEL)
                                            {
                                                continue;
                                            }

                                            Vector3 voxelPosition = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord);

                                            //float voxelSize = MyVoxelMaps.GetVoxelContentAsFloat(voxelContent) * MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF;
                                            float voxelSize = MyVoxelMaps.GetVoxelContentAsFloat(voxelContent) * MyVoxelConstants.VOXEL_RADIUS;

                                            //  If distance to voxel border is less than sphere radius, we have a collision
                                            //  So now we calculate normal vector and penetration depth but on OLD sphere
                                            float newDistanceToVoxel = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize;
                                            if (newDistanceToVoxel < (epsylon + newSphere.Radius))
                                            {
                                                Vector3 collisionN = MyMwcUtils.Normalize(voxelPosition - body0Pos);

                                                if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                                                {
                                                    //  Calculate penetration depth, but from old sphere (not new)
                                                    float oldDistanceToVoxel  = Vector3.Distance(voxelPosition, newSphere.Center) - voxelSize;
                                                    float oldPenetrationDepth = oldDistanceToVoxel - sphereRadius;

                                                    // Vector3 pt = body0Pos + sphereRadius * collisionN;
                                                    Vector3 pt = voxelPosition - collisionN * (voxelSize - epsylon);

                                                    collPtArray[numCollPts++] = new MySmallCollPointInfo(pt - body0Pos, pt - body1Pos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, collisionN, oldPenetrationDepth, pt);
                                                }

                                                collNormal -= collisionN;
                                            }
                                        }
                                    }
                                }

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

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

                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock();
                }
                else //if (colDetThroughVoxels)
                {
                    MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("ColDet triangles");

                    int optimalIterationCount = (int)(GetRigidBody1().LinearVelocity.Length() * dt / sphereRadius);
                    int maxIndex = (int)MathHelper.Min(MathHelper.Max(optimalIterationCount, 1), 16);

                    for (int i = 0; i < maxIndex; i++)
                    {
                        float velocityAdd = GetRigidBody1().LinearVelocity.Length() * dt / (float)maxIndex;

                        Vector3 interpolatedPosition = body0Pos + GetRigidBody1().LinearVelocity *dt *i / (float)maxIndex;

                        BoundingSphere newSphere;
                        newSphere.Center = interpolatedPosition;
                        newSphere.Radius = sphereRadius;

                        int numTriangles;

                        BoundingBox bb = BoundingBox.CreateFromSphere(newSphere);
                        MyVoxelMaps.GetPotentialTrianglesForColDet(out numTriangles, ref bb);

                        for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle)
                        {
                            MyColDetVoxelTriangle meshTriangle = MyVoxelMaps.PotentialColDetTriangles[iTriangle]; // mesh.GetTriangle(potentialTriangles[iTriangle]);


                            MyTriangle_Vertex_Normal triangle = new MyTriangle_Vertex_Normal();
                            triangle.Vertexes.Vertex0 = meshTriangle.Vertex0;
                            triangle.Vertexes.Vertex1 = meshTriangle.Vertex1;
                            triangle.Vertexes.Vertex2 = meshTriangle.Vertex2;


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

                            if ((triangle.Vertexes.Vertex1 - triangle.Vertexes.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon)
                            {
                                continue;
                            }

                            if ((triangle.Vertexes.Vertex0 - triangle.Vertexes.Vertex2).LengthSquared() < MyPhysicsConfig.TriangleEpsilon)
                            {
                                continue;
                            }

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

                            Vector3?pt = MyUtils.GetSphereTriangleIntersection(ref newSphere, ref plane, ref triangle.Vertexes);
                            if (pt == null)
                            {
                                continue;
                            }


                            Vector3 collisionN = plane.Normal;

                            // skip triangle in case the normal is in wrong dir (narrow walls)
                            Vector3 tempV = (newBody0Pos - pt.Value);
                            if (Vector3.Dot(collisionN, tempV) >= 0.8f * tempV.Length())  // equivalent to dot(collisionN, normalize(tempV)) > 0.8f, but works for zero vectors
                            {
                                continue;
                            }

                            float depth = Vector3.Distance(pt.Value, body0Pos) - sphereRadius;

                            if (numCollPts < MyPhysicsConfig.MaxContactPoints)
                            {
                                // since impulse get applied at the old position
                                Vector3 p2 = pt.Value;

                                collPtArray[numCollPts++] = new MySmallCollPointInfo(p2 - body0Pos, p2 - body1Pos, GetRigidBody1().LinearVelocity, GetRigidBody2().LinearVelocity, collisionN, depth, p2);
                            }

                            collNormal += collisionN;
                        }
                    }

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

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

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

            return(false);
        }
예제 #7
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);
                }
            }
        }
        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;
                }
            }
          
        }
        public bool SegmentTriangleIntersection(out float tS, out float tT0, out float tT1,
                                               MySegment seg, MyColDetVoxelTriangle triangle)
        {
            /// the parameters - if hit then they get copied into the args
            float u, v, t;

            tS = 0;
            tT0 = 0;
            tT1 = 0;

            Vector3 e1 = triangle.Edge0;
            Vector3 e2 = triangle.Edge1;
            Vector3 p = Vector3.Cross(seg.Delta, e2);
            float a = Vector3.Dot(e1, p);
            if (a > -MyPhysicsConfig.Epsilon && a < MyPhysicsConfig.Epsilon)
                return false;
            float f = 1.0f / a;
            Vector3 s = seg.Origin - triangle.Origin;
            u = f * Vector3.Dot(s, p);
            if (u < 0.0f || u > 1.0f)
                return false;
            Vector3 q = Vector3.Cross(s, e1);
            v = f * Vector3.Dot(seg.Delta, q);
            if (v < 0.0f || (u + v) > 1.0f)
                return false;
            t = f * Vector3.Dot(e2, q);
            if (t < 0.0f || t > 1.0f)
                return false;

            tS = t;
            tT0 = u;
            tT1 = v;
            //if (tS != 0) tS = t;
            //if (tT0 != 0) tT0 = u;
            //if (tT1 != 0) tT1 = v;
            return true;
        }
예제 #10
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);
            }
        }
예제 #11
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;
        }
예제 #12
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;
        }
예제 #13
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;
 }        
예제 #14
0
        /// <summary>
        /// point vs Voxel triangle distancesq
        /// </summary>
        public static float PointColDetVoxelTriangleDistanceSq(out float pfSParam, out float pfTParam, Vector3 rkPoint, MyColDetVoxelTriangle rkTri)
        {
            Vector3 kDiff = rkTri.Origin - rkPoint;
            float   fA00  = rkTri.Edge0.LengthSquared();
            float   fA01  = Vector3.Dot(rkTri.Edge0, rkTri.Edge1);
            float   fA11  = rkTri.Edge1.LengthSquared();
            float   fB0   = Vector3.Dot(kDiff, rkTri.Edge0);
            float   fB1   = Vector3.Dot(kDiff, rkTri.Edge1);
            float   fC    = kDiff.LengthSquared();
            float   fDet  = System.Math.Abs(fA00 * fA11 - fA01 * fA01);
            float   fS    = fA01 * fB1 - fA11 * fB0;
            float   fT    = fA01 * fB0 - fA00 * fB1;
            float   fSqrDist;

            if (fS + fT <= fDet)
            {
                if (fS < 0.0f)
                {
                    if (fT < 0.0f)  // region 4
                    {
                        if (fB0 < 0.0f)
                        {
                            fT = 0.0f;
                            if (-fB0 >= fA00)
                            {
                                fS       = 1.0f;
                                fSqrDist = fA00 + 2.0f * fB0 + fC;
                            }
                            else
                            {
                                fS       = -fB0 / fA00;
                                fSqrDist = fB0 * fS + fC;
                            }
                        }
                        else
                        {
                            fS = 0.0f;
                            if (fB1 >= 0.0f)
                            {
                                fT       = 0.0f;
                                fSqrDist = fC;
                            }
                            else if (-fB1 >= fA11)
                            {
                                fT       = 1.0f;
                                fSqrDist = fA11 + 2.0f * fB1 + fC;
                            }
                            else
                            {
                                fT       = -fB1 / fA11;
                                fSqrDist = fB1 * fT + fC;
                            }
                        }
                    }
                    else  // region 3
                    {
                        fS = 0.0f;
                        if (fB1 >= 0.0f)
                        {
                            fT       = 0.0f;
                            fSqrDist = fC;
                        }
                        else if (-fB1 >= fA11)
                        {
                            fT       = 1.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else
                        {
                            fT       = -fB1 / fA11;
                            fSqrDist = fB1 * fT + fC;
                        }
                    }
                }
                else if (fT < 0.0f)  // region 5
                {
                    fT = 0.0f;
                    if (fB0 >= 0.0f)
                    {
                        fS       = 0.0f;
                        fSqrDist = fC;
                    }
                    else if (-fB0 >= fA00)
                    {
                        fS       = 1.0f;
                        fSqrDist = fA00 + 2.0f * fB0 + fC;
                    }
                    else
                    {
                        fS       = -fB0 / fA00;
                        fSqrDist = fB0 * fS + fC;
                    }
                }
                else  // region 0
                {
                    // minimum at interior point
                    float fInvDet = 1.0f / fDet;
                    fS      *= fInvDet;
                    fT      *= fInvDet;
                    fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                               fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                }
            }
            else
            {
                float fTmp0, fTmp1, fNumer, fDenom;

                if (fS < 0.0f)  // region 2
                {
                    fTmp0 = fA01 + fB0;
                    fTmp1 = fA11 + fB1;
                    if (fTmp1 > fTmp0)
                    {
                        fNumer = fTmp1 - fTmp0;
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fS       = 1.0f;
                            fT       = 0.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else
                        {
                            fS       = fNumer / fDenom;
                            fT       = 1.0f - fS;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                                       fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                    else
                    {
                        fS = 0.0f;
                        if (fTmp1 <= 0.0f)
                        {
                            fT       = 1.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else if (fB1 >= 0.0f)
                        {
                            fT       = 0.0f;
                            fSqrDist = fC;
                        }
                        else
                        {
                            fT       = -fB1 / fA11;
                            fSqrDist = fB1 * fT + fC;
                        }
                    }
                }
                else if (fT < 0.0f)  // region 6
                {
                    fTmp0 = fA01 + fB1;
                    fTmp1 = fA00 + fB0;
                    if (fTmp1 > fTmp0)
                    {
                        fNumer = fTmp1 - fTmp0;
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fT       = 1.0f;
                            fS       = 0.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else
                        {
                            fT       = fNumer / fDenom;
                            fS       = 1.0f - fT;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                                       fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                    else
                    {
                        fT = 0.0f;
                        if (fTmp1 <= 0.0f)
                        {
                            fS       = 1.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else if (fB0 >= 0.0f)
                        {
                            fS       = 0.0f;
                            fSqrDist = fC;
                        }
                        else
                        {
                            fS       = -fB0 / fA00;
                            fSqrDist = fB0 * fS + fC;
                        }
                    }
                }
                else  // region 1
                {
                    fNumer = fA11 + fB1 - fA01 - fB0;
                    if (fNumer <= 0.0f)
                    {
                        fS       = 0.0f;
                        fT       = 1.0f;
                        fSqrDist = fA11 + 2.0f * fB1 + fC;
                    }
                    else
                    {
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fS       = 1.0f;
                            fT       = 0.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else
                        {
                            fS       = fNumer / fDenom;
                            fT       = 1.0f - fS;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                                       fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                }
            }

            pfSParam = fS;
            pfTParam = fT;

            return(System.Math.Abs(fSqrDist));
        }
예제 #15
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);
        }
예제 #16
0
        /// <summary>
        /// point vs Voxel triangle distancesq
        /// </summary>
        public static float PointColDetVoxelTriangleDistanceSq(out float pfSParam, out float pfTParam, Vector3 rkPoint, MyColDetVoxelTriangle rkTri)
        {
            Vector3 kDiff = rkTri.Origin - rkPoint;
            float fA00 = rkTri.Edge0.LengthSquared();
            float fA01 = Vector3.Dot(rkTri.Edge0, rkTri.Edge1);
            float fA11 = rkTri.Edge1.LengthSquared();
            float fB0 = Vector3.Dot(kDiff, rkTri.Edge0);
            float fB1 = Vector3.Dot(kDiff, rkTri.Edge1);
            float fC = kDiff.LengthSquared();
            float fDet = System.Math.Abs(fA00 * fA11 - fA01 * fA01);
            float fS = fA01 * fB1 - fA11 * fB0;
            float fT = fA01 * fB0 - fA00 * fB1;
            float fSqrDist;

            if (fS + fT <= fDet)
            {
                if (fS < 0.0f)
                {
                    if (fT < 0.0f)  // region 4
                    {
                        if (fB0 < 0.0f)
                        {
                            fT = 0.0f;
                            if (-fB0 >= fA00)
                            {
                                fS = 1.0f;
                                fSqrDist = fA00 + 2.0f * fB0 + fC;
                            }
                            else
                            {
                                fS = -fB0 / fA00;
                                fSqrDist = fB0 * fS + fC;
                            }
                        }
                        else
                        {
                            fS = 0.0f;
                            if (fB1 >= 0.0f)
                            {
                                fT = 0.0f;
                                fSqrDist = fC;
                            }
                            else if (-fB1 >= fA11)
                            {
                                fT = 1.0f;
                                fSqrDist = fA11 + 2.0f * fB1 + fC;
                            }
                            else
                            {
                                fT = -fB1 / fA11;
                                fSqrDist = fB1 * fT + fC;
                            }
                        }
                    }
                    else  // region 3
                    {
                        fS = 0.0f;
                        if (fB1 >= 0.0f)
                        {
                            fT = 0.0f;
                            fSqrDist = fC;
                        }
                        else if (-fB1 >= fA11)
                        {
                            fT = 1.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else
                        {
                            fT = -fB1 / fA11;
                            fSqrDist = fB1 * fT + fC;
                        }
                    }
                }
                else if (fT < 0.0f)  // region 5
                {
                    fT = 0.0f;
                    if (fB0 >= 0.0f)
                    {
                        fS = 0.0f;
                        fSqrDist = fC;
                    }
                    else if (-fB0 >= fA00)
                    {
                        fS = 1.0f;
                        fSqrDist = fA00 + 2.0f * fB0 + fC;
                    }
                    else
                    {
                        fS = -fB0 / fA00;
                        fSqrDist = fB0 * fS + fC;
                    }
                }
                else  // region 0
                {
                    // minimum at interior point
                    float fInvDet = 1.0f / fDet;
                    fS *= fInvDet;
                    fT *= fInvDet;
                    fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                      fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                }
            }
            else
            {
                float fTmp0, fTmp1, fNumer, fDenom;

                if (fS < 0.0f)  // region 2
                {
                    fTmp0 = fA01 + fB0;
                    fTmp1 = fA11 + fB1;
                    if (fTmp1 > fTmp0)
                    {
                        fNumer = fTmp1 - fTmp0;
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fS = 1.0f;
                            fT = 0.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else
                        {
                            fS = fNumer / fDenom;
                            fT = 1.0f - fS;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                              fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                    else
                    {
                        fS = 0.0f;
                        if (fTmp1 <= 0.0f)
                        {
                            fT = 1.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else if (fB1 >= 0.0f)
                        {
                            fT = 0.0f;
                            fSqrDist = fC;
                        }
                        else
                        {
                            fT = -fB1 / fA11;
                            fSqrDist = fB1 * fT + fC;
                        }
                    }
                }
                else if (fT < 0.0f)  // region 6
                {
                    fTmp0 = fA01 + fB1;
                    fTmp1 = fA00 + fB0;
                    if (fTmp1 > fTmp0)
                    {
                        fNumer = fTmp1 - fTmp0;
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fT = 1.0f;
                            fS = 0.0f;
                            fSqrDist = fA11 + 2.0f * fB1 + fC;
                        }
                        else
                        {
                            fT = fNumer / fDenom;
                            fS = 1.0f - fT;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                              fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                    else
                    {
                        fT = 0.0f;
                        if (fTmp1 <= 0.0f)
                        {
                            fS = 1.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else if (fB0 >= 0.0f)
                        {
                            fS = 0.0f;
                            fSqrDist = fC;
                        }
                        else
                        {
                            fS = -fB0 / fA00;
                            fSqrDist = fB0 * fS + fC;
                        }
                    }
                }
                else  // region 1
                {
                    fNumer = fA11 + fB1 - fA01 - fB0;
                    if (fNumer <= 0.0f)
                    {
                        fS = 0.0f;
                        fT = 1.0f;
                        fSqrDist = fA11 + 2.0f * fB1 + fC;
                    }
                    else
                    {
                        fDenom = fA00 - 2.0f * fA01 + fA11;
                        if (fNumer >= fDenom)
                        {
                            fS = 1.0f;
                            fT = 0.0f;
                            fSqrDist = fA00 + 2.0f * fB0 + fC;
                        }
                        else
                        {
                            fS = fNumer / fDenom;
                            fT = 1.0f - fS;
                            fSqrDist = fS * (fA00 * fS + fA01 * fT + 2.0f * fB0) +
                              fT * (fA01 * fS + fA11 * fT + 2.0f * fB1) + fC;
                        }
                    }
                }
            }

            pfSParam = fS;
            pfTParam = fT;

            return System.Math.Abs(fSqrDist);
        }
예제 #17
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;
        }