Ejemplo n.º 1
0
            public bool ClosestPtPointTriangle(JVector p, JVector a, JVector b, JVector c,
                ref SubSimplexClosestResult result)
            {
                result.UsedVertices.Reset();

                float v, w;

                // Check if P in vertex region outside A
                JVector ab = b - a;
                JVector ac = c - a;
                JVector ap = p - a;
                float d1 = JVector.Dot(ab, ap);
                float d2 = JVector.Dot(ac, ap);
                if (d1 <= 0f && d2 <= 0f)
                {
                    result.ClosestPointOnSimplex = a;
                    result.UsedVertices.UsedVertexA = true;
                    result.SetBarycentricCoordinates(1, 0, 0, 0);
                    return true; // a; // barycentric coordinates (1,0,0)
                }

                // Check if P in vertex region outside B
                JVector bp = p - b;
                float d3 = JVector.Dot(ab, bp);
                float d4 = JVector.Dot(ac, bp);
                if (d3 >= 0f && d4 <= d3)
                {
                    result.ClosestPointOnSimplex = b;
                    result.UsedVertices.UsedVertexB = true;
                    result.SetBarycentricCoordinates(0, 1, 0, 0);

                    return true; // b; // barycentric coordinates (0,1,0)
                }
                // Check if P in edge region of AB, if so return projection of P onto AB
                float vc = d1 * d4 - d3 * d2;
                if (vc <= 0f && d1 >= 0f && d3 <= 0f)
                {
                    v = d1 / (d1 - d3);
                    result.ClosestPointOnSimplex = a + v * ab;
                    result.UsedVertices.UsedVertexA = true;
                    result.UsedVertices.UsedVertexB = true;
                    result.SetBarycentricCoordinates(1 - v, v, 0, 0);
                    return true;
                    //return a + v * ab; // barycentric coordinates (1-v,v,0)
                }

                // Check if P in vertex region outside C
                JVector cp = p - c;
                float d5 = JVector.Dot(ab, cp);
                float d6 = JVector.Dot(ac, cp);
                if (d6 >= 0f && d5 <= d6)
                {
                    result.ClosestPointOnSimplex = c;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(0, 0, 1, 0);
                    return true;//c; // barycentric coordinates (0,0,1)
                }

                // Check if P in edge region of AC, if so return projection of P onto AC
                float vb = d5 * d2 - d1 * d6;
                if (vb <= 0f && d2 >= 0f && d6 <= 0f)
                {
                    w = d2 / (d2 - d6);
                    result.ClosestPointOnSimplex = a + w * ac;
                    result.UsedVertices.UsedVertexA = true;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(1 - w, 0, w, 0);
                    return true;
                    //return a + w * ac; // barycentric coordinates (1-w,0,w)
                }

                // Check if P in edge region of BC, if so return projection of P onto BC
                float va = d3 * d6 - d5 * d4;
                if (va <= 0f && (d4 - d3) >= 0f && (d5 - d6) >= 0f)
                {
                    w = (d4 - d3) / ((d4 - d3) + (d5 - d6));

                    result.ClosestPointOnSimplex = b + w * (c - b);
                    result.UsedVertices.UsedVertexB = true;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(0, 1 - w, w, 0);
                    return true;
                    // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
                }

                // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
                float denom = 1.0f / (va + vb + vc);
                v = vb * denom;
                w = vc * denom;

                result.ClosestPointOnSimplex = a + ab * v + ac * w;
                result.UsedVertices.UsedVertexA = true;
                result.UsedVertices.UsedVertexB = true;
                result.UsedVertices.UsedVertexC = true;
                result.SetBarycentricCoordinates(1 - v - w, v, w, 0);

                return true;
            }
Ejemplo n.º 2
0
            public bool ClosestPtPointTetrahedron(JVector p, JVector a, JVector b, JVector c, JVector d,
                ref SubSimplexClosestResult finalResult)
            {
                tempResult.Reset();

                // Start out assuming point inside all halfspaces, so closest to itself
                finalResult.ClosestPointOnSimplex = p;
                finalResult.UsedVertices.Reset();
                finalResult.UsedVertices.UsedVertexA = true;
                finalResult.UsedVertices.UsedVertexB = true;
                finalResult.UsedVertices.UsedVertexC = true;
                finalResult.UsedVertices.UsedVertexD = true;

                int pointOutsideABC = PointOutsideOfPlane(p, a, b, c, d);
                int pointOutsideACD = PointOutsideOfPlane(p, a, c, d, b);
                int pointOutsideADB = PointOutsideOfPlane(p, a, d, b, c);
                int pointOutsideBDC = PointOutsideOfPlane(p, b, d, c, a);

                if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
                {
                    finalResult.Degenerate = true;
                    return false;
                }

                if (pointOutsideABC == 0 && pointOutsideACD == 0 && pointOutsideADB == 0 && pointOutsideBDC == 0)
                    return false;

                float bestSqDist = float.MaxValue;
                // If point outside face abc then compute closest point on abc
                if (pointOutsideABC != 0)
                {
                    ClosestPtPointTriangle(p, a, b, c, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    // Update best closest point if (squared) distance is less than current best
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        //convert result bitmask!
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                                tempResult.BarycentricCoords[VertexA],
                                tempResult.BarycentricCoords[VertexB],
                                tempResult.BarycentricCoords[VertexC],
                                0);
                    }
                }

                // Repeat test for face acd
                if (pointOutsideACD != 0)
                {
                    ClosestPtPointTriangle(p, a, c, d, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                                tempResult.BarycentricCoords[VertexA],
                                0,
                                tempResult.BarycentricCoords[VertexB],
                                tempResult.BarycentricCoords[VertexC]);
                    }
                }
                // Repeat test for face adb

                if (pointOutsideADB != 0)
                {
                    ClosestPtPointTriangle(p, a, d, b, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                                tempResult.BarycentricCoords[VertexA],
                                tempResult.BarycentricCoords[VertexC],
                                0,
                                tempResult.BarycentricCoords[VertexB]);

                    }
                }
                // Repeat test for face bdc

                if (pointOutsideBDC != 0)
                {
                    ClosestPtPointTriangle(p, b, d, c, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!
                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC;

                        finalResult.SetBarycentricCoordinates(
                                0,
                                tempResult.BarycentricCoords[VertexA],
                                tempResult.BarycentricCoords[VertexC],
                                tempResult.BarycentricCoords[VertexB]);
                    }
                }

                //help! we ended up full !

                if (finalResult.UsedVertices.UsedVertexA &&
                    finalResult.UsedVertices.UsedVertexB &&
                    finalResult.UsedVertices.UsedVertexC &&
                    finalResult.UsedVertices.UsedVertexD)
                {
                    return true;
                }

                return true;
            }
Ejemplo n.º 3
0
            public bool ClosestPtPointTetrahedron(JVector p, JVector a, JVector b, JVector c, JVector d,
                                                  ref SubSimplexClosestResult finalResult)
            {
                tempResult.Reset();

                // Start out assuming point inside all halfspaces, so closest to itself
                finalResult.ClosestPointOnSimplex = p;
                finalResult.UsedVertices.Reset();
                finalResult.UsedVertices.UsedVertexA = true;
                finalResult.UsedVertices.UsedVertexB = true;
                finalResult.UsedVertices.UsedVertexC = true;
                finalResult.UsedVertices.UsedVertexD = true;

                int pointOutsideABC = PointOutsideOfPlane(p, a, b, c, d);
                int pointOutsideACD = PointOutsideOfPlane(p, a, c, d, b);
                int pointOutsideADB = PointOutsideOfPlane(p, a, d, b, c);
                int pointOutsideBDC = PointOutsideOfPlane(p, b, d, c, a);

                if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
                {
                    finalResult.Degenerate = true;
                    return(false);
                }

                if (pointOutsideABC == 0 && pointOutsideACD == 0 && pointOutsideADB == 0 && pointOutsideBDC == 0)
                {
                    return(false);
                }

                float bestSqDist = float.MaxValue;

                // If point outside face abc then compute closest point on abc
                if (pointOutsideABC != 0)
                {
                    ClosestPtPointTriangle(p, a, b, c, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    // Update best closest point if (squared) distance is less than current best
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        //convert result bitmask!
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                            tempResult.BarycentricCoords[VertexA],
                            tempResult.BarycentricCoords[VertexB],
                            tempResult.BarycentricCoords[VertexC],
                            0);
                    }
                }

                // Repeat test for face acd
                if (pointOutsideACD != 0)
                {
                    ClosestPtPointTriangle(p, a, c, d, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                            tempResult.BarycentricCoords[VertexA],
                            0,
                            tempResult.BarycentricCoords[VertexB],
                            tempResult.BarycentricCoords[VertexC]);
                    }
                }
                // Repeat test for face adb

                if (pointOutsideADB != 0)
                {
                    ClosestPtPointTriangle(p, a, d, b, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!

                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexA = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexC;
                        finalResult.SetBarycentricCoordinates(
                            tempResult.BarycentricCoords[VertexA],
                            tempResult.BarycentricCoords[VertexC],
                            0,
                            tempResult.BarycentricCoords[VertexB]);
                    }
                }
                // Repeat test for face bdc

                if (pointOutsideBDC != 0)
                {
                    ClosestPtPointTriangle(p, b, d, c, ref tempResult);
                    JVector q = tempResult.ClosestPointOnSimplex;
                    //convert result bitmask!
                    float sqDist = ((JVector)(q - p)).LengthSquared();
                    if (sqDist < bestSqDist)
                    {
                        bestSqDist = sqDist;
                        finalResult.ClosestPointOnSimplex = q;
                        finalResult.UsedVertices.Reset();
                        finalResult.UsedVertices.UsedVertexB = tempResult.UsedVertices.UsedVertexA;
                        finalResult.UsedVertices.UsedVertexD = tempResult.UsedVertices.UsedVertexB;
                        finalResult.UsedVertices.UsedVertexC = tempResult.UsedVertices.UsedVertexC;

                        finalResult.SetBarycentricCoordinates(
                            0,
                            tempResult.BarycentricCoords[VertexA],
                            tempResult.BarycentricCoords[VertexC],
                            tempResult.BarycentricCoords[VertexB]);
                    }
                }

                //help! we ended up full !

                if (finalResult.UsedVertices.UsedVertexA &&
                    finalResult.UsedVertices.UsedVertexB &&
                    finalResult.UsedVertices.UsedVertexC &&
                    finalResult.UsedVertices.UsedVertexD)
                {
                    return(true);
                }

                return(true);
            }
Ejemplo n.º 4
0
            public bool ClosestPtPointTriangle(JVector p, JVector a, JVector b, JVector c,
                                               ref SubSimplexClosestResult result)
            {
                result.UsedVertices.Reset();

                float v, w;

                // Check if P in vertex region outside A
                JVector ab = b - a;
                JVector ac = c - a;
                JVector ap = p - a;
                float   d1 = JVector.Dot(ab, ap);
                float   d2 = JVector.Dot(ac, ap);

                if (d1 <= 0f && d2 <= 0f)
                {
                    result.ClosestPointOnSimplex    = a;
                    result.UsedVertices.UsedVertexA = true;
                    result.SetBarycentricCoordinates(1, 0, 0, 0);
                    return(true); // a; // barycentric coordinates (1,0,0)
                }

                // Check if P in vertex region outside B
                JVector bp = p - b;
                float   d3 = JVector.Dot(ab, bp);
                float   d4 = JVector.Dot(ac, bp);

                if (d3 >= 0f && d4 <= d3)
                {
                    result.ClosestPointOnSimplex    = b;
                    result.UsedVertices.UsedVertexB = true;
                    result.SetBarycentricCoordinates(0, 1, 0, 0);

                    return(true); // b; // barycentric coordinates (0,1,0)
                }
                // Check if P in edge region of AB, if so return projection of P onto AB
                float vc = d1 * d4 - d3 * d2;

                if (vc <= 0f && d1 >= 0f && d3 <= 0f)
                {
                    v = d1 / (d1 - d3);
                    result.ClosestPointOnSimplex    = a + v * ab;
                    result.UsedVertices.UsedVertexA = true;
                    result.UsedVertices.UsedVertexB = true;
                    result.SetBarycentricCoordinates(1 - v, v, 0, 0);
                    return(true);
                    //return a + v * ab; // barycentric coordinates (1-v,v,0)
                }

                // Check if P in vertex region outside C
                JVector cp = p - c;
                float   d5 = JVector.Dot(ab, cp);
                float   d6 = JVector.Dot(ac, cp);

                if (d6 >= 0f && d5 <= d6)
                {
                    result.ClosestPointOnSimplex    = c;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(0, 0, 1, 0);
                    return(true);//c; // barycentric coordinates (0,0,1)
                }

                // Check if P in edge region of AC, if so return projection of P onto AC
                float vb = d5 * d2 - d1 * d6;

                if (vb <= 0f && d2 >= 0f && d6 <= 0f)
                {
                    w = d2 / (d2 - d6);
                    result.ClosestPointOnSimplex    = a + w * ac;
                    result.UsedVertices.UsedVertexA = true;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(1 - w, 0, w, 0);
                    return(true);
                    //return a + w * ac; // barycentric coordinates (1-w,0,w)
                }

                // Check if P in edge region of BC, if so return projection of P onto BC
                float va = d3 * d6 - d5 * d4;

                if (va <= 0f && (d4 - d3) >= 0f && (d5 - d6) >= 0f)
                {
                    w = (d4 - d3) / ((d4 - d3) + (d5 - d6));

                    result.ClosestPointOnSimplex    = b + w * (c - b);
                    result.UsedVertices.UsedVertexB = true;
                    result.UsedVertices.UsedVertexC = true;
                    result.SetBarycentricCoordinates(0, 1 - w, w, 0);
                    return(true);
                    // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
                }

                // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
                float denom = 1.0f / (va + vb + vc);

                v = vb * denom;
                w = vc * denom;

                result.ClosestPointOnSimplex    = a + ab * v + ac * w;
                result.UsedVertices.UsedVertexA = true;
                result.UsedVertices.UsedVertexB = true;
                result.UsedVertices.UsedVertexC = true;
                result.SetBarycentricCoordinates(1 - v - w, v, w, 0);

                return(true);
            }
Ejemplo n.º 5
0
        bool closestPtPointTetrahedron(ref btVector3 p, ref btVector3 a, ref btVector3 b, ref btVector3 c, ref btVector3 d, SubSimplexClosestResult finalResult)
        {
            tempResult.reset();

            // Start out assuming point inside all halfspaces, so closest to itself
            finalResult.m_closestPointOnSimplex = p;
            finalResult.m_usedVertices.reset();
            finalResult.m_usedVertices.usedVertexA = true;
            finalResult.m_usedVertices.usedVertexB = true;
            finalResult.m_usedVertices.usedVertexC = true;
            finalResult.m_usedVertices.usedVertexD = true;

            int pointOutsideABC = pointOutsideOfPlane(ref p, ref a, ref b, ref c, ref d);
            int pointOutsideACD = pointOutsideOfPlane(ref p, ref a, ref c, ref d, ref b);
            int pointOutsideADB = pointOutsideOfPlane(ref p, ref a, ref d, ref b, ref c);
            int pointOutsideBDC = pointOutsideOfPlane(ref p, ref b, ref d, ref c, ref a);

            if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
            {
                finalResult.m_degenerate = true;
                return false;
            }

            if (pointOutsideABC == 0 && pointOutsideACD == 0 && pointOutsideADB == 0 && pointOutsideBDC == 0)
            {
                return false;
            }


            float bestSqDist = float.MaxValue;
            // If point outside face abc then compute closest point on abc
            if (pointOutsideABC != 0)
            {
                closestPtPointTriangle(ref p, ref a, ref b, ref  c, tempResult);
                btVector3 q = tempResult.m_closestPointOnSimplex;

                float sqDist = (q - p).dot(q - p);
                // Update best closest point if (squared) distance is less than current best
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    finalResult.m_closestPointOnSimplex = q;
                    //convert result bitmask!
                    finalResult.m_usedVertices.reset();
                    finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
                    finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
                    finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
                    finalResult.setBarycentricCoordinates(
                            tempResult.m_barycentricCoords[VERTA],
                            tempResult.m_barycentricCoords[VERTB],
                            tempResult.m_barycentricCoords[VERTC],
                            0
                    );

                }
            }


            // Repeat test for face acd
            if (pointOutsideACD != 0)
            {
                closestPtPointTriangle(ref p, ref a, ref c, ref d, tempResult);
                btVector3 q = tempResult.m_closestPointOnSimplex;
                //convert result bitmask!

                float sqDist = (q - p).dot(q - p);
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    finalResult.m_closestPointOnSimplex = q;
                    finalResult.m_usedVertices.reset();
                    finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;

                    finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
                    finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
                    finalResult.setBarycentricCoordinates(
                            tempResult.m_barycentricCoords[VERTA],
                            0,
                            tempResult.m_barycentricCoords[VERTB],
                            tempResult.m_barycentricCoords[VERTC]
                    );

                }
            }
            // Repeat test for face adb


            if (pointOutsideADB != 0)
            {
                closestPtPointTriangle(ref p, ref a, ref d, ref b, tempResult);
                btVector3 q = tempResult.m_closestPointOnSimplex;
                //convert result bitmask!

                float sqDist = (q - p).dot(q - p);
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    finalResult.m_closestPointOnSimplex = q;
                    finalResult.m_usedVertices.reset();
                    finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
                    finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;

                    finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
                    finalResult.setBarycentricCoordinates(
                            tempResult.m_barycentricCoords[VERTA],
                            tempResult.m_barycentricCoords[VERTC],
                            0,
                            tempResult.m_barycentricCoords[VERTB]
                    );

                }
            }
            // Repeat test for face bdc


            if (pointOutsideBDC != 0)
            {
                closestPtPointTriangle(ref p, ref b, ref d, ref c, tempResult);
                btVector3 q = tempResult.m_closestPointOnSimplex;
                //convert result bitmask!
                float sqDist = (q - p).dot(q - p);
                if (sqDist < bestSqDist)
                {
                    bestSqDist = sqDist;
                    finalResult.m_closestPointOnSimplex = q;
                    finalResult.m_usedVertices.reset();
                    //
                    finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
                    finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
                    finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;

                    finalResult.setBarycentricCoordinates(
                            0,
                            tempResult.m_barycentricCoords[VERTA],
                            tempResult.m_barycentricCoords[VERTC],
                            tempResult.m_barycentricCoords[VERTB]
                    );

                }
            }

            //help! we ended up full !

            if (finalResult.m_usedVertices.usedVertexA &&
                finalResult.m_usedVertices.usedVertexB &&
                finalResult.m_usedVertices.usedVertexC &&
                finalResult.m_usedVertices.usedVertexD)
            {
                return true;
            }

            return true;
        }
Ejemplo n.º 6
0
        bool closestPtPointTriangle(ref btVector3 p, ref btVector3 a, ref btVector3 b, ref btVector3 c, SubSimplexClosestResult result)
        {
            result.m_usedVertices.reset();

            // Check if P in vertex region outside A
            btVector3 ab = b - a;
            btVector3 ac = c - a;
            btVector3 ap = p - a;
            float d1 = ab.dot(ap);
            float d2 = ac.dot(ap);
            if (d1 <= 0.0f && d2 <= 0.0f)
            {
                result.m_closestPointOnSimplex = a;
                result.m_usedVertices.usedVertexA = true;
                result.setBarycentricCoordinates(1, 0, 0);
                return true;// a; // barycentric coordinates (1,0,0)
            }

            // Check if P in vertex region outside B
            btVector3 bp = p - b;
            float d3 = ab.dot(bp);
            float d4 = ac.dot(bp);
            if (d3 >= 0.0f && d4 <= d3)
            {
                result.m_closestPointOnSimplex = b;
                result.m_usedVertices.usedVertexB = true;
                result.setBarycentricCoordinates(0, 1, 0);

                return true; // b; // barycentric coordinates (0,1,0)
            }
            // Check if P in edge region of AB, if so return projection of P onto AB
            float vc = d1 * d4 - d3 * d2;
            if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f)
            {
                float v = d1 / (d1 - d3);
                result.m_closestPointOnSimplex = a + v * ab;
                result.m_usedVertices.usedVertexA = true;
                result.m_usedVertices.usedVertexB = true;
                result.setBarycentricCoordinates(1 - v, v, 0);
                return true;
                //return a + v * ab; // barycentric coordinates (1-v,v,0)
            }

            // Check if P in vertex region outside C
            btVector3 cp = p - c;
            float d5 = ab.dot(cp);
            float d6 = ac.dot(cp);
            if (d6 >= 0.0f && d5 <= d6)
            {
                result.m_closestPointOnSimplex = c;
                result.m_usedVertices.usedVertexC = true;
                result.setBarycentricCoordinates(0, 0, 1);
                return true;//c; // barycentric coordinates (0,0,1)
            }

            // Check if P in edge region of AC, if so return projection of P onto AC
            float vb = d5 * d2 - d1 * d6;
            if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f)
            {
                float w = d2 / (d2 - d6);
                result.m_closestPointOnSimplex = a + w * ac;
                result.m_usedVertices.usedVertexA = true;
                result.m_usedVertices.usedVertexC = true;
                result.setBarycentricCoordinates(1 - w, 0, w);
                return true;
                //return a + w * ac; // barycentric coordinates (1-w,0,w)
            }

            // Check if P in edge region of BC, if so return projection of P onto BC
            float va = d3 * d6 - d5 * d4;
            if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f)
            {
                float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));

                result.m_closestPointOnSimplex = b + w * (c - b);
                result.m_usedVertices.usedVertexB = true;
                result.m_usedVertices.usedVertexC = true;
                result.setBarycentricCoordinates(0, 1 - w, w);
                return true;
                // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
            }
            {
                // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
                float denom = 1.0f / (va + vb + vc);
                float v = vb * denom;
                float w = vc * denom;

                result.m_closestPointOnSimplex = a + ab * v + ac * w;
                result.m_usedVertices.usedVertexA = true;
                result.m_usedVertices.usedVertexB = true;
                result.m_usedVertices.usedVertexC = true;
                result.setBarycentricCoordinates(1 - v - w, v, w);
            }
            return true;
            //	return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w

        }