FmVec3 GetClosestPointTriangle(FmVec3 p, FmVec3 a, FmVec3 b, FmVec3 c)
{
    FmVec3 result;
    FmVec3 ab, ac, ap;
    ab = b - a;
    ac = c - a;
    ap = p - a;

    float d1 = ab.dot(ap);
    float d2 = ac.dot(ap);
    if (d1 <= 0.0f && d2 <= 0.0f)
    {
        result = a;
        return result;
    }

    FmVec3 bp;
    bp = p - b;
    float d3 = ab.dot(bp);
    float d4 = ac.dot(bp);
    if (d3 >= 0.0f && d4 <= d3)
    {
        // barycentric coordinates (0,1,0)
        result = b;
        return result;
    }

    // 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)
    {
        // barycentric coordinates (1-v,v,0)
        float v = d1 / (d1 - d3);
        result.x = a.x + v * ab.x;
        result.y = a.y + v * ab.y;
        result.z = a.z + v * ab.z;
        return result;
    }

    FmVec3 cp = p - c;
    float d5 = ab.dot(cp);
    float d6 = ac.dot(cp);
    if (d6 >= 0.0f && d5 <= d6)
    {
        // barycentric coordinates (0,0,1)
        result = c;
        return result;
    }

    // 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)
    {
        // barycentric coordinates (1-w,0,w)
        float w = d2 / (d2 - d6);
        result.x = a.x + w * ac.x;
        result.y = a.y + w * ac.y;
        result.z = a.z + w * ac.z;
        return result;
    }

    // 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)
    {
        // barycentric coordinates (0,1-w,w)
        float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
        result.x = b.x + w * (c.x - b.x);
        result.y = b.y + w * (c.y - b.y);
        result.z = b.z + w * (c.z - b.z);
        return result;
    }

    // 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.x = a.x + ab.x * v + ac.x * w;
    result.y = a.y + ab.y * v + ac.y * w;
    result.z = a.z + ab.z * v + ac.z * w;

    return result;
}

 

posted on 2020-04-16 17:27  jackdesk  阅读(247)  评论(0编辑  收藏  举报