예제 #1
0
        public static void processCollision(CollisionObject body0, CollisionObject body1, DispatcherInfo dispatchInfo, PersistentManifold resultOut)
        {
            CapsuleShape capsule0 = (CapsuleShape)body0.getCollisionShape();
            CapsuleShape capsule1 = (CapsuleShape)body1.getCollisionShape();

            VIntTransform transform0 = body0.getWorldTransform();
            VIntTransform transform1 = body1.getWorldTransform();

            VInt3 p00 = transform0.TransformPoint(capsule0.getUpAxis() * capsule0.getHalfHeight());
            VInt3 p01 = transform0.TransformPoint(capsule0.getUpAxis() * -capsule0.getHalfHeight());

            VInt3 p10 = transform1.TransformPoint(capsule1.getUpAxis() * capsule1.getHalfHeight());
            VInt3 p11 = transform1.TransformPoint(capsule1.getUpAxis() * -capsule1.getHalfHeight());

            VInt3       x, y;
            VFixedPoint dist2       = Distance.SegmentSegmentDist2(p00, p01 - p00, p10, p11 - p10, out x, out y);
            VFixedPoint dist        = FMath.Sqrt(dist2);
            VFixedPoint penetration = dist - (capsule0.getRadius() + capsule1.getRadius());

            if (penetration > Globals.getContactBreakingThreshold())
            {
                return;
            }

            VInt3 diff = (x - y) / dist;

            VInt3 posWorldOnA = x - diff * capsule0.getRadius();
            VInt3 posWorldOnB = y + diff * capsule1.getRadius();

            ManifoldPoint contractPoint = new ManifoldPoint(posWorldOnA, posWorldOnB, diff, penetration);

            resultOut.addManifoldPoint(contractPoint);
        }
예제 #2
0
        public static void processCollision(CollisionObject body0, CollisionObject body1, DispatcherInfo dispatchInfo, PersistentManifold resultOut)
        {
            bool needSwap = body0.getCollisionShape() is CapsuleShape;

            CollisionObject sphereObject  = needSwap ? body1 : body0;
            CollisionObject capsuleObject = needSwap ? body0 : body1;

            SphereShape  sphere  = (SphereShape)sphereObject.getCollisionShape();
            CapsuleShape capsule = (CapsuleShape)capsuleObject.getCollisionShape();

            VInt3         spherePos        = sphereObject.getWorldTransform().position;
            VIntTransform capsuleTransform = capsuleObject.getWorldTransform();
            VInt3         p0 = capsuleTransform.TransformPoint(capsule.getUpAxis() * capsule.getHalfHeight());
            VInt3         p1 = capsuleTransform.TransformPoint(capsule.getUpAxis() * -capsule.getHalfHeight());

            VFixedPoint param       = VFixedPoint.Zero;
            VFixedPoint dist2       = Distance.distancePointSegmentSquared(p0, p1, spherePos, ref param);
            VFixedPoint dist        = FMath.Sqrt(dist2);
            VFixedPoint penetration = dist - (sphere.getRadius() + capsule.getRadius());

            if (penetration > Globals.getContactBreakingThreshold())
            {
                return;
            }

            VInt3 lineWorldPos = p0 * (VFixedPoint.One - param) + p1 * param;
            VInt3 diff         = (spherePos - lineWorldPos) / dist;

            VInt3 sphereWorldPos  = spherePos - diff * sphere.getRadius();
            VInt3 capsuleWorldPos = lineWorldPos + diff * capsule.getRadius();

            ManifoldPoint contractPoint = new ManifoldPoint(needSwap ? capsuleWorldPos : sphereWorldPos, needSwap ? sphereWorldPos: capsuleWorldPos, diff * (needSwap ? -1 : 1), penetration);

            resultOut.addManifoldPoint(contractPoint);
        }
예제 #3
0
        //sphere move to collide capsule
        static bool sweepSphereCapsule(SphereShape sphere, VIntTransform sphereTransform, VInt3 end,
                                       CapsuleShape capsule, VIntTransform capsuleTransform, ref VInt3 normal, ref VFixedPoint t)
        {
            VInt3       move           = end - sphereTransform.position;
            VFixedPoint radiusSum      = sphere.getRadius() + capsule.getRadius();
            VInt3       capsuleP0      = capsuleTransform.TransformPoint(capsule.getUpAxis() * capsule.getHalfHeight());
            VInt3       capsuleP1      = capsuleTransform.TransformPoint(capsule.getUpAxis() * -capsule.getHalfHeight());
            VInt3       spherePosition = sphereTransform.position;
            VFixedPoint tmp            = VFixedPoint.Zero;

            if (Distance.distancePointSegmentSquared(capsuleP0, capsuleP1, spherePosition, ref tmp) < radiusSum * radiusSum)
            {
                t      = VFixedPoint.Zero;
                normal = -move.Normalize();
                return(true);
            }

            VFixedPoint u0        = VFixedPoint.Zero;
            VInt3       tmpNormal = VInt3.zero;

            if (capsuleP0 == capsuleP1)
            {
                VInt3 ToPos = spherePosition + move;
                if (SphereSphereSweepAlgorithm.sphereSphereSweep(sphere.getRadius(), spherePosition, ToPos, capsule.getRadius(), capsuleTransform.position, ref u0, ref tmp, ref tmpNormal))
                {
                    t      = u0;
                    normal = tmpNormal;
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else if (CapsuleRaytestAlgorithm.raycastCapsule(spherePosition, end, capsuleP0, capsuleP1, radiusSum, ref normal, ref u0))
            {
                t = u0;
                VFixedPoint param             = VFixedPoint.Zero;
                VInt3       movedSphereCenter = spherePosition + (end - spherePosition) * u0;
                Distance.distancePointSegmentSquared(capsuleP0, capsuleP1, movedSphereCenter, ref param);
                normal = movedSphereCenter - (capsuleP0 * (VFixedPoint.One - param) + capsuleP1 * param);
                normal = normal.Normalize();
                return(true);
            }

            return(false);
        }
예제 #4
0
        static int extrudeBox(VInt3 aabbMax, VIntTransform world, VInt3 extrusionDir, Triangle[] tris, VInt3 dir)
        {
            computeBoxPoints(aabbMax, -aabbMax);
            for (int i = 0; i < 12; i++)
            {
                int VRef0 = Indices[i * 3 + 0];
                int VRef1 = Indices[i * 3 + 1];
                int VRef2 = Indices[i * 3 + 2];

                Triangle atriangle = boxTris[i];

                atriangle.verts[0] = world.TransformPoint(boxP[VRef0]);
                atriangle.verts[1] = world.TransformPoint(boxP[VRef1]);
                atriangle.verts[2] = world.TransformPoint(boxP[VRef2]);
            }

            return(extrudeMesh(boxTris, extrusionDir, dir, tris));
        }
예제 #5
0
        public static void processCollision(CollisionObject body0, CollisionObject body1, DispatcherInfo dispatchInfo, PersistentManifold resultOut)
        {
            bool            needSwap      = body0.getCollisionShape() is CapsuleShape;
            CollisionObject boxObject     = needSwap ? body1 : body0;
            CollisionObject capsuleObject = needSwap ? body0 : body1;

            BoxShape     boxShape     = (BoxShape)boxObject.getCollisionShape();
            CapsuleShape capsuleShape = (CapsuleShape)capsuleObject.getCollisionShape();

            VIntTransform boxTransform     = boxObject.getWorldTransform();
            VIntTransform capsuleTransform = capsuleObject.getWorldTransform();

            VInt3       p0 = capsuleTransform.TransformPoint(capsuleShape.getUpAxis() * capsuleShape.getHalfHeight()), p1 = capsuleTransform.TransformPoint(capsuleShape.getUpAxis() * -capsuleShape.getHalfHeight());
            VFixedPoint lParam = VFixedPoint.Zero; VInt3 closestPointBoxLS = VInt3.zero;
            VFixedPoint distSq             = SegmentBoxDistance.distanceSegmentBoxSquared(p0, p1, boxShape.getHalfExtent(), boxTransform, ref lParam, ref closestPointBoxLS);
            VInt3       closestPointBoxWS  = boxTransform.TransformPoint(closestPointBoxLS);
            VInt3       closestPointLineWS = p0 * (VFixedPoint.One - lParam) + p1 * lParam;

            VFixedPoint dist = FMath.Sqrt(distSq) - capsuleShape.getRadius();

            if (dist > VFixedPoint.Zero)
            {
                return;
            }

            if ((closestPointBoxWS - closestPointLineWS).sqrMagnitude > Globals.EPS2)
            {
                VInt3 normalOnBoxWS = (closestPointLineWS - closestPointBoxWS).Normalize();

                ManifoldPoint contactPoint = new ManifoldPoint(needSwap ? closestPointLineWS - normalOnBoxWS * capsuleShape.getRadius() : closestPointBoxWS,
                                                               !needSwap ? closestPointLineWS - normalOnBoxWS * capsuleShape.getRadius() : closestPointBoxWS,
                                                               normalOnBoxWS * (needSwap ? 1 : -1), dist);
                resultOut.addManifoldPoint(contactPoint);
            }
            else //box and line are intersected
            {
                //EPA
                LineShape   coreShape = new LineShape(capsuleShape);
                VInt3       pa = VInt3.zero, pb = VInt3.zero, normal = VInt3.zero;
                VFixedPoint depth  = VFixedPoint.Zero;
                PxGJKStatus result = EpaSolver.calcPenDepth(coreShape, boxShape, capsuleTransform, boxTransform, ref pa, ref pb, ref normal, ref depth);
                if (result == PxGJKStatus.EPA_CONTACT)
                {
                    ManifoldPoint contactPoint = new ManifoldPoint(needSwap ? pa - normal * capsuleShape.getRadius() : pb, !needSwap ? pa - normal * capsuleShape.getRadius() : pb, needSwap ? normal : -normal, depth - capsuleShape.getRadius());
                    resultOut.addManifoldPoint(contactPoint);
                }
            }
        }
예제 #6
0
        static void doSupport(CollisionShape a, CollisionShape b, VIntTransform transformA, VIntTransform transformB, VInt3 dir
                              , out VInt3 supportA, out VInt3 supportB, out VInt3 support)
        {
            VInt3 dirInA = dir;

            dirInA = transformA.InverseTransformDirection(dirInA);

            VInt3 dirInB = -dir;

            dirInB = transformB.InverseTransformDirection(dirInB);

            VInt3 pInA = new VInt3();
            VInt3 qInB = new VInt3();

            pInA = a.support(dirInA);
            qInB = b.support(dirInB);

            supportA = transformA.TransformPoint(pInA);
            supportB = transformB.TransformPoint(qInB);

            support = supportA - supportB;
        }
예제 #7
0
        public void refreshContactPoints(VIntTransform trA, VIntTransform trB)
        {
            VInt3 tmp = VInt3.zero;

            for (int i = cachedPoints - 1; i >= 0; i--)
            {
                ManifoldPoint manifoldPoint = pointCache[i];
                manifoldPoint.positionWorldOnA = trA.TransformPoint(manifoldPoint.localPointA);
                manifoldPoint.positionWorldOnB = trB.TransformPoint(manifoldPoint.localPointB);
                manifoldPoint.distance         = VInt3.Dot(manifoldPoint.normalWorldOnB, manifoldPoint.positionWorldOnA - manifoldPoint.positionWorldOnB);
            }

            VFixedPoint distance2d = VFixedPoint.Zero;
            VInt3       projectedDifference = VInt3.zero, projectedPoint = VInt3.zero;

            for (int i = cachedPoints - 1; i >= 0; i--)
            {
                ManifoldPoint manifoldPoint = pointCache[i];
                if (!validContactDistance(manifoldPoint))
                {
                    removeContactPoint(i);
                }
            }
        }
예제 #8
0
        public static bool sweepCapsuleCapsule(CapsuleShape lss0, VIntTransform transform0, VInt3 toPos, CapsuleShape lss1, VIntTransform transform1, ref VFixedPoint dist, ref VInt3 hitNormal)
        {
            VInt3       FromPos   = transform0.position;
            VFixedPoint radiusSun = lss0.getRadius() + lss1.getRadius();
            VFixedPoint length    = (toPos - FromPos).magnitude;
            VInt3       dir       = (toPos - FromPos) / length;

            VInt3 lss0p0 = transform0.TransformPoint(lss0.getUpAxis() * lss0.getHalfHeight()), lss0p1 = transform0.TransformPoint(lss0.getUpAxis() * -lss0.getHalfHeight());
            VInt3 lss1p0 = transform1.TransformPoint(lss1.getUpAxis() * lss1.getHalfHeight()), lss1p1 = transform1.TransformPoint(lss1.getUpAxis() * -lss1.getHalfHeight());

            bool        initialOverlapStatus = false;
            VFixedPoint tmp = VFixedPoint.Zero;

            if (lss0.getHalfHeight() < Globals.EPS)
            {
                initialOverlapStatus = Distance.distancePointSegmentSquared(lss1p0, lss1p1, lss0p0, ref tmp) < radiusSun * radiusSun;
            }
            else if (lss1.getHalfHeight() < Globals.EPS)
            {
                initialOverlapStatus = Distance.distancePointSegmentSquared(lss0p0, lss0p1, lss1p0, ref tmp) < radiusSun * radiusSun;
            }
            else
            {
                VInt3 x, y;
                initialOverlapStatus = Distance.SegmentSegmentDist2(lss0p0, lss0p1 - lss0p0, lss1p0, lss1p1 - lss1p0, out x, out y) < radiusSun * radiusSun;
            }

            if (initialOverlapStatus)
            {
                dist      = VFixedPoint.Zero;
                hitNormal = (FromPos - toPos).Normalize();
                return(true);
            }

            // 1. Extrude lss0 by lss1's length
            // 2. Inflate extruded shape by lss1's radius
            // 3. Raycast against resulting quad
            VInt3 D = (lss0p1 - lss0p0) * VFixedPoint.Half;
            VInt3 p0 = lss1p0 - D, p1 = lss1p1 - D, p0b = lss1p0 + D, p1b = lss1p1 + D;
            VInt3 normal = VInt3.Cross(p1b - p0b, p1 - p0b); normal = normal.Normalize();

            dist = VFixedPoint.One; bool status = false;

            VInt3 pa, pb, pc;

            if (VInt3.Dot(normal, dir) >= VFixedPoint.Zero)
            {
                pc = p0 - normal * radiusSun;
                pa = p1 - normal * radiusSun;
                pb = p1b - normal * radiusSun;
            }
            else
            {
                pc = p0 + normal * radiusSun;
                pa = p1 + normal * radiusSun;
                pb = p1b + normal * radiusSun;
            }
            VFixedPoint t = VFixedPoint.Zero, u = VFixedPoint.Zero, v = VFixedPoint.Zero;

            if (rayQuad(transform1.position, dir, pa, pb, pc, ref t, ref u, ref v, true) && t >= VFixedPoint.Zero && t < length)
            {
                dist   = t / length;
                status = true;
            }

            if (!status)
            {
                VInt3[] caps = new VInt3[]
                {
                    p0, p1, p1, p1b, p1b, p0b, p0b, p0
                };
                VInt3 tmpNormal = VInt3.zero;
                for (int i = 0; i < 4; i++)
                {
                    VFixedPoint s = VFixedPoint.Zero;
                    if (CapsuleRaytestAlgorithm.raycastCapsule(FromPos, toPos, caps[i * 2], caps[i * 2 + 1], radiusSun, ref tmpNormal, ref s))
                    {
                        if (s > VFixedPoint.Zero && s < dist)
                        {
                            dist   = s;
                            status = true;
                        }
                    }
                }
            }

            if (status)
            {
                VInt3 x, y;
                Distance.SegmentSegmentDist2(lss0p0 + dir * length * dist, lss0p1 - lss0p0, lss1p0, lss1p1 - lss1p0, out x, out y);
                hitNormal = (x - y).Normalize();
            }
            return(status);
        }
예제 #9
0
        public static PxGJKStatus calcPenDepth(CollisionShape a, CollisionShape b, VIntTransform transformA, VIntTransform transformB,
                                               ref VInt3 pa, ref VInt3 pb, ref VInt3 normal, ref VFixedPoint penDepth)
        {
            simplexSolver.reset();
            //Do simple GJK
            VFixedPoint minMargin        = FMath.Min(a.getMargin(), b.getMargin());
            VInt3       initialSearchDir = transformA.position - transformB.position;
            VInt3       v             = initialSearchDir.sqrMagnitude > Globals.EPS2 ? initialSearchDir : VInt3.right;
            bool        notTerminated = true;
            VFixedPoint sDist         = VFixedPoint.MaxValue;
            VFixedPoint minDist       = sDist;
            int         iter          = 0;

            while (notTerminated && iter < MaxGJKIteration)
            {
                minDist = sDist;
                VInt3 supportA = transformA.TransformPoint(a.support(transformA.InverseTransformDirection(v)));
                VInt3 supportB = transformB.TransformPoint(b.support(transformB.InverseTransformDirection(-v)));
                VInt3 support  = supportA - supportB;
                simplexSolver.addVertex(support, supportA, supportB);
                VInt3 p0, p1;
                bool  con = !simplexSolver.compute_points(out p0, out p1);
                v             = p1 - p0;
                sDist         = v.sqrMagnitude;
                notTerminated = con && sDist < minDist;
                iter++;
            }

            if (notTerminated)
            {
                return(PxGJKStatus.EPA_FAIL);
            }

            simplexSolver.getSimplex(aBuf, bBuf, Q);

            VFixedPoint upper_bound = VFixedPoint.MaxValue;
            VFixedPoint lower_bound = VFixedPoint.MinValue;

            int numVertsLocal = 0;

            heap.Clear();
            facetManager.freeAll();

            switch (simplexSolver.numVertices())
            {
            case 1:
                if (!expandPoint(a, b, transformA, transformB, ref numVertsLocal, lower_bound, upper_bound))
                {
                    return(PxGJKStatus.EPA_FAIL);
                }
                break;

            case 2:
                if (!expandSegment(a, b, transformA, transformB, ref numVertsLocal, lower_bound, upper_bound))
                {
                    return(PxGJKStatus.EPA_FAIL);
                }
                break;

            case 3:
                if (!expandTriangle(a, b, transformA, transformB, ref numVertsLocal, lower_bound, upper_bound))
                {
                    return(PxGJKStatus.EPA_FAIL);
                }
                break;

            case 4:
                //check for input face normal. All face normals in this tetrahedron should be all pointing either inwards or outwards. If all face normals are pointing outward, we are good to go. Otherwise, we need to
                //shuffle the input vertexes and make sure all face normals are pointing outward
                VFixedPoint planeDist0 = calculatePlaneDist(0, 1, 2, aBuf, bBuf);
                if (planeDist0 < VFixedPoint.Zero)
                {
                    //shuffle the input vertexes
                    VInt3 tempA = aBuf[2];
                    VInt3 tempB = bBuf[2];
                    aBuf[2] = aBuf[1];
                    bBuf[2] = bBuf[1];
                    aBuf[1] = tempA;
                    bBuf[1] = tempB;
                }

                Facet f0 = addFacet(0, 1, 2, lower_bound, upper_bound);
                Facet f1 = addFacet(0, 3, 1, lower_bound, upper_bound);
                Facet f2 = addFacet(0, 2, 3, lower_bound, upper_bound);
                Facet f3 = addFacet(1, 3, 2, lower_bound, upper_bound);

                if ((f0 == null) || (f1 == null) || (f2 == null) || (f3 == null) || heap.IsEmpty())
                {
                    return(PxGJKStatus.EPA_FAIL);
                }

                f0.link(0, f1, 2);
                f0.link(1, f3, 2);
                f0.link(2, f2, 0);
                f1.link(0, f2, 2);
                f1.link(1, f3, 0);
                f2.link(1, f3, 1);
                numVertsLocal = 4;
                break;
            }

            Facet facet     = null;
            Facet bestFacet = null;

            bool  hasMoreFacets = false;
            VInt3 tempa;
            VInt3 tempb;
            VInt3 q;


            do
            {
                facetManager.processDeferredIDs();
                facet          = heap.pop(); //get the shortest distance triangle of origin from the list
                facet.m_inHeap = false;

                if (!facet.isObsolete())
                {
                    bestFacet = facet;
                    VInt3       planeNormal = facet.getPlaneNormal();
                    VFixedPoint planeDist   = facet.getPlaneDist();

                    doSupport(a, b, transformA, transformB, planeNormal, out tempa, out tempb, out q);

                    //calculate the distance from support point to the origin along the plane normal. Because the support point is search along
                    //the plane normal, which means the distance should be positive. However, if the origin isn't contained in the polytope, dist
                    //might be negative
                    VFixedPoint dist = VInt3.Dot(q, planeNormal);
                    //update the upper bound to the minimum between exisiting upper bound and the distance if distance is positive
                    upper_bound = dist >= VFixedPoint.Zero ? FMath.Min(upper_bound, dist) : upper_bound;
                    //lower bound is the plane distance, which will be the smallest among all the facets in the prority queue
                    lower_bound = planeDist;
                    //if the plane distance and the upper bound is within a small tolerance, which means we found the MTD
                    bool con0 = upper_bound != VFixedPoint.MaxValue && lower_bound != VFixedPoint.MinValue && (upper_bound - lower_bound) <= Globals.EPS2;
                    if (con0)
                    {
                        calculateContactInformation(aBuf, bBuf, facet, a, b, ref pa, ref pb, ref normal, ref penDepth);
                        return(PxGJKStatus.EPA_CONTACT);
                    }
                    //if planeDist is the same as dist, which means the support point we get out from the Mincowsky sum is one of the point
                    //in the triangle facet, we should exist because we can't progress further.
                    VFixedPoint dif = dist - planeDist;
                    bool        degeneratedCondition = dif < Globals.EPS;

                    if (degeneratedCondition)
                    {
                        return(PxGJKStatus.EPA_DEGENERATE);
                    }

                    aBuf[numVertsLocal] = tempa;
                    bBuf[numVertsLocal] = tempb;

                    int index = numVertsLocal++;

                    // Compute the silhouette cast by the new vertex
                    // Note that the new vertex is on the positive side
                    // of the current facet, so the current facet will
                    // not be in the polytope. Start local search
                    // from this facet.
                    edgeBuffer.MakeEmpty();
                    facet.silhouette(q, aBuf, bBuf, edgeBuffer, facetManager);
                    Edge edge       = edgeBuffer.Get(0);
                    int  bufferSize = edgeBuffer.Size();
                    //check to see whether we have enough space in the facet manager to create new facets
                    if (bufferSize > facetManager.getNumRemainingIDs())
                    {
                        return(PxGJKStatus.EPA_DEGENERATE);
                    }

                    Facet firstFacet = addFacet(edge.getTarget(), edge.getSource(), index, lower_bound, upper_bound);
                    firstFacet.link(0, edge.getFacet(), edge.getIndex());
                    Facet lastFacet = firstFacet;

                    bool degenerate = false;
                    for (int i = 1; (i < bufferSize) && (!degenerate); ++i)
                    {
                        edge = edgeBuffer.Get(i);
                        Facet newFacet = addFacet(edge.getTarget(), edge.getSource(), index, lower_bound, upper_bound);
                        bool  b0       = newFacet.link(0, edge.getFacet(), edge.getIndex());
                        bool  b1       = newFacet.link(2, lastFacet, 1);
                        degenerate = degenerate || !b0 || !b1;
                        lastFacet  = newFacet;
                    }

                    if (degenerate)
                    {
                        return(PxGJKStatus.EPA_DEGENERATE);
                    }
                    firstFacet.link(2, lastFacet, 1);
                }
                hasMoreFacets = (heap.size() > 0);

                if (hasMoreFacets && heap.peak().getPlaneDist() > upper_bound)
                {
                    calculateContactInformation(aBuf, bBuf, bestFacet, a, b, ref pa, ref pb, ref normal, ref penDepth);
                    return(PxGJKStatus.EPA_CONTACT);
                }
            } while (hasMoreFacets && numVertsLocal != MaxSupportPoints);

            return(PxGJKStatus.EPA_DEGENERATE);
        }
예제 #10
0
        static void calculateContacts(VFixedPoint extentX, VFixedPoint extentY, VFixedPoint extentZ, VInt3[] pts,
                                      VInt3 incidentfaceNormalInNew, VInt3 localNormal, VFixedPoint contactDist, VIntTransform transformNew,
                                      PersistentManifold resultOut, bool flip)
        {
            localNormal = transformNew.TransformDirection(localNormal);

            VFixedPoint nExtentX = -extentX;
            VFixedPoint nExtentY = -extentY;

            bool[] penetration = new bool[4];
            bool[] area        = new bool[4];

            VInt3 bmin = new VInt3(VFixedPoint.MaxValue, VFixedPoint.MaxValue, VFixedPoint.MaxValue);
            VInt3 bmax = new VInt3(VFixedPoint.MinValue, VFixedPoint.MinValue, VFixedPoint.MinValue);

            VInt3 bound = new VInt3(extentX, extentY, VFixedPoint.MaxValue);

            for (int i = 0; i < 4; i++)
            {
                bmin = VInt3.Min(bmin, pts[i]);
                bmax = VInt3.Max(bmax, pts[i]);
                VFixedPoint z = -pts[i].z;
                if (contactDist > z)
                {
                    penetration[i] = true;

                    VInt3 absPt = pts[i].Abs();
                    bool  con   = bound >= absPt;
                    if (con)
                    {
                        area[i] = true;

                        VInt3         localPointA  = pts[i]; localPointA.z = VFixedPoint.Zero; localPointA = transformNew.TransformPoint(localPointA);
                        VInt3         localPointB  = pts[i]; localPointB = transformNew.TransformPoint(localPointB);
                        ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, z);
                        resultOut.addManifoldPoint(contactPoint);
                    }
                    else
                    {
                        area[i] = false;
                    }
                }
                else
                {
                    penetration[i] = false;
                    area[i]        = false;
                }
            }

            if (resultOut.getContactPointsNum() == PersistentManifold.MANIFOLD_CACHE_SIZE)
            {
                return;
            }

            {
                {
                    VFixedPoint denom = incidentfaceNormalInNew.z;
                    {
                        VInt3 q0 = new VInt3(extentX, extentY, VFixedPoint.Zero);

                        if (contains(pts, q0, bmin, bmax))
                        {
                            VFixedPoint nom = VInt3.Dot(incidentfaceNormalInNew, pts[0] - q0);
                            VFixedPoint t   = nom / denom;
                            VFixedPoint pen = -t;
                            if (contactDist > pen)
                            {
                                VInt3         localPointA  = q0; localPointA = transformNew.TransformPoint(localPointA);
                                VInt3         localPointB  = q0; localPointB.z = t; localPointB = transformNew.TransformPoint(localPointB);
                                ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, pen);
                                resultOut.addManifoldPoint(contactPoint);
                            }
                        }
                    }

                    {
                        VInt3 q0 = new VInt3(extentX, nExtentY, VFixedPoint.Zero);
                        if (contains(pts, q0, bmin, bmax))
                        {
                            VFixedPoint nom = VInt3.Dot(incidentfaceNormalInNew, pts[0] - q0);
                            VFixedPoint t   = nom / denom;
                            VFixedPoint pen = -t;
                            if (contactDist > pen)
                            {
                                VInt3         localPointA  = q0; localPointA = transformNew.TransformPoint(localPointA);
                                VInt3         localPointB  = q0; localPointB.z = t; localPointB = transformNew.TransformPoint(localPointB);
                                ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, pen);
                                resultOut.addManifoldPoint(contactPoint);
                            }
                        }
                    }

                    {
                        VInt3 q0 = new VInt3(nExtentX, extentY, VFixedPoint.Zero);
                        if (contains(pts, q0, bmin, bmax))
                        {
                            VFixedPoint nom = VInt3.Dot(incidentfaceNormalInNew, pts[0] - q0);
                            VFixedPoint t   = nom / denom;
                            VFixedPoint pen = -t;
                            if (contactDist > pen)
                            {
                                VInt3         localPointA  = q0; localPointA = transformNew.TransformPoint(localPointA);
                                VInt3         localPointB  = q0; localPointB.z = t; localPointB = transformNew.TransformPoint(localPointB);
                                ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, pen);
                                resultOut.addManifoldPoint(contactPoint);
                            }
                        }
                    }

                    {
                        VInt3 q0 = new VInt3(nExtentX, nExtentY, VFixedPoint.Zero);
                        if (contains(pts, q0, bmin, bmax))
                        {
                            VFixedPoint nom = VInt3.Dot(incidentfaceNormalInNew, pts[0] - q0);
                            VFixedPoint t   = nom / denom;
                            VFixedPoint pen = -t;
                            if (contactDist > pen)
                            {
                                VInt3         localPointA  = q0; localPointA = transformNew.TransformPoint(localPointA);
                                VInt3         localPointB  = q0; localPointB.z = t; localPointB = transformNew.TransformPoint(localPointB);
                                ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, pen);
                                resultOut.addManifoldPoint(contactPoint);
                            }
                        }
                    }
                }
            }

            VInt3 ext    = new VInt3(extentX, extentY, extentZ * VFixedPoint.Two);
            VInt3 negExt = new VInt3(nExtentX, nExtentY, -(contactDist + Globals.EPS));

            for (int start = 0, end = 3; start < 4; end = start++)
            {
                VInt3 p0 = pts[start];
                VInt3 p1 = pts[end];

                if (!penetration[start] && !penetration[end])
                {
                    continue;
                }

                bool con0 = penetration[start] && area[start];
                bool con1 = penetration[end] && area[end];
                if (con0 && con1)
                {
                    continue;
                }

                VFixedPoint tmin = VFixedPoint.Zero, tmax = VFixedPoint.Zero;
                if (AabbUtils.RayAabb2(p0, p1, negExt, ext, ref tmin, ref tmax))
                {
                    if (!con0 && tmin > VFixedPoint.Zero)
                    {
                        VInt3         intersectP   = p0 * (VFixedPoint.One - tmin) + p1 * tmin;
                        VInt3         localPointA  = intersectP; localPointA.z = VFixedPoint.Zero; localPointA = transformNew.TransformPoint(localPointA);
                        VInt3         localPointB  = intersectP; localPointB = transformNew.TransformPoint(localPointB);
                        ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, -intersectP.z);
                        resultOut.addManifoldPoint(contactPoint);
                    }
                    if (!con1 && tmax < VFixedPoint.One)
                    {
                        VInt3         intersectP   = p0 * (VFixedPoint.One - tmax) + p1 * tmax;
                        VInt3         localPointA  = intersectP; localPointA.z = VFixedPoint.Zero; localPointA = transformNew.TransformPoint(localPointA);
                        VInt3         localPointB  = intersectP; localPointB = transformNew.TransformPoint(localPointB);
                        ManifoldPoint contactPoint = new ManifoldPoint(flip ? localPointB : localPointA, flip ? localPointA : localPointB, localNormal, -intersectP.z);
                        resultOut.addManifoldPoint(contactPoint);
                    }
                }
            }
        }