Exemplo n.º 1
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);
                    }
                }
            }
        }