2011-12-09

Torus - mapowanie tekstury

Mamy punkt uderzenia promienia w torus $P(X,Y,Z)$ w lokalnym układzie współrzędnych, w którym torus leży w środku układu współrzędnych w płaszczyźnie XZ.

Współrzędna u jest liczona całkiem podobnie jak dla sfery $u=\arctan(^X/_Z)/2\pi$. Teraz dla drugiej połowy okręgu współrzędną trzeba zwiększyć o jeden. W moim przypadku przyjąłem, że współrzędna u=0 leży na dodatniej osi X.

Ze współrzędną v jest trochę trudniej. Zauważmy, że niezależnie od położenia punktu na torusie w płaszczyźnie go przecinającej przechodzącej przez oś Y kątowa wartość współrzędnej v ma wartość: $\arccos(^Y/_r)$. Teraz tylko musimy ją odpowiednio przekształcić w zależności w której ćwiartce znalazł się punkt uderzenia. Ja przyjąłem, że współrzędna $v=0$ jest wewnątrz torusa, $v=0.25$ na górze (góra w kierunki osi Y) itd.

Znajdująca się w kodzie korekta wartości argumentu dla arccos to korekta błędów numerycznych. Oczywiście jeśli wartość jest większa od jeden albo mniejsza od -1 o więcej niż wynosi dopuszczalny błąd to zdecydowanie jest coś nie tak.

Kod:
public override Vector2 GetUV(Intersection a_intersection)
{
    Vector3 local_pos = a_intersection.LocalPos;

    float ca = local_pos.Y / m_local_small_radius;
    Debug.Assert(ca.IsAlmostRelativeGreaterOrEqualThen(-1));
    Debug.Assert(ca.IsAlmostRelativeLessOrEqualThen(1));
    ca = SingleExtensions.Limit(ca, -1, 1);

    float v = (float)Math.Acos(ca) / Constants.PI / 2;

    if (local_pos.X * local_pos.X + local_pos.Z * local_pos.Z > 
        m_local_big_radius * m_local_big_radius)
    {
        v = v + 0.25f;
    }
    else
    {
        if (local_pos.Y > 0)
            v = 0.25f - v;
        else
            v = 1.25f - v;
    }

    float u = (float)Math.Atan2(local_pos.X, local_pos.Z) / (2 * Constants.PI);

    if (local_pos.X < 0)
        u = u + 1;

    return new Vector2(u, v);
}

Brak komentarzy:

Prześlij komentarz