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