四角形内の任意の点のUVを求める方法(三次元版、未検証)

 

    // 線形補間
    private Vector2 Lerp(Vector2 start, Vector2 end, float t)
    {
        return start + t * (end - start);
    }
 
    // 三次元空間内の四角形のUV座標を計算
    public Vector2 CalculateUV(Vector3 A, Vector3 B, Vector3 C, Vector3 D, 
                               Vector3 E, Vector3 F, Vector3 G, Vector3 H, Vector3 I)
    {
        // 上面ABCDの平面における点Iの投影を計算
        Vector3 normalABCD = Vector3.Cross(B - A, C - A).normalized;
        Vector3 projectionIOnABCD = I - Vector3.Dot(I - A, normalABCD) * normalABCD;
 
        // 下面EFGHの平面における点Iの投影を計算
        Vector3 normalEFGH = Vector3.Cross(F - E, G - E).normalized;
        Vector3 projectionIOnEFGH = I - Vector3.Dot(I - E, normalEFGH) * normalEFGH;
 
        // 上面と下面の投影点からUV座標を計算
        Vector2 uvABCD = CalculateUVOnPlane(A, B, C, D, projectionIOnABCD);
        Vector2 uvEFGH = CalculateUVOnPlane(E, F, G, H, projectionIOnEFGH);
 
        // 点Iが上面と下面の間でどの位置にあるかに基づいてUV座標を補間
        float distanceToABCD = Vector3.Distance(I, projectionIOnABCD);
        float distanceToEFGH = Vector3.Distance(I, projectionIOnEFGH);
        float totalDistance = distanceToABCD + distanceToEFGH;
        float weightABCD = distanceToEFGH / totalDistance;
        float weightEFGH = distanceToABCD / totalDistance;
 
        // 重み付けされたUV座標を算出
        return Lerp(uvEFGH, uvABCD, weightABCD);
    }
 
// 平面上の四角形内の点のUV座標を計算
    private Vector2 CalculateUVOnPlane(Vector3 A, Vector3 B, Vector3 C, Vector3 D, Vector3 P)
    {
        // 辺ABとCDに沿った補間
        Vector3 AB = B - A;
        Vector3 CD = D - C;
        float tAB = Vector3.Dot(P - A, AB) / AB.sqrMagnitude;
        float tCD = Vector3.Dot(P - C, CD) / CD.sqrMagnitude;
        Vector3 AB_P = A + tAB * AB;
        Vector3 CD_P = C + tCD * CD;
 
        // 辺ADとBCに沿った補間
        Vector3 AD = D - A;
        Vector3 BC = C - B;
        float tAD = Vector3.Dot(P - A, AD) / AD.sqrMagnitude;
        float tBC = Vector3.Dot(P - B, BC) / BC.sqrMagnitude;
        Vector3 AD_P = A + tAD * AD;
        Vector3 BC_P = B + tBC * BC;
 
        // 辺に沿った補間からUV座標を計算
        float u = (P - AB_P).magnitude / (CD_P - AB_P).magnitude;
        float v = (P - AD_P).magnitude / (BC_P - AD_P).magnitude;
 
        // 最終的なUV座標を算出
        return new Vector2(u, v);
    }