Do wyznaczenia jest para (u,v), gdzie u zależy od kąta θ, v zależy od kąta φ, u∈⟨0,1⟩, v∈⟨0,1⟩, 0⩽.
Poniżej podane wzory znacząco się upraszczają jeśli wektory \mathbf{\hat U}, \mathbf{\hat F}, \mathbf{\hat R} są wersorami układu współrzędnych, a środek sfery to środek układu współrzędnych. Wtedy korzystamy z klasycznych wzorów na konwersję z układu kartezjańskiego na sferyczny.
Normalna (wektor znormalizowany) w punkcie P ma wartość:
\hat N = \widehat{OP}
Wyznaczenie wartości \mathbf{\varphi}:\cos \varphi = \hat U \cdot \hat N
\varphi = arccos \left ( \hat U \cdot \hat N \right )
Wyznaczenie wartości \mathbf{\theta}:\varphi = arccos \left ( \hat U \cdot \hat N \right )
\vec A = \hat U \times \hat N
\hat B = \widehat{\vec A \times \hat U}
\cos \theta = \hat N \cdot \hat B
\theta = arccos \left ( \hat N \cdot \hat B \right )
Mając wyznaczone oba kąty trzeba je zmapować na (u,v). \hat B = \widehat{\vec A \times \hat U}
\cos \theta = \hat N \cdot \hat B
\theta = arccos \left ( \hat N \cdot \hat B \right )
Chcemy by v zależał kąta \mathbf{\varphi}. Zauważmy że wartości funkcji arccos zmieniają się w zakresie \mathbf{\left < 0, \pi \right >}. Dla ujemnych wartości \mathbf{\varphi} wartość arccos nie zmienia się co do znaku. Tak więc:
v = \displaystyle\frac{\varphi}{\pi}
W przypadku mapowania v znak kąta ma znaczenie. Chcemy by v zmieniało się w granicach od zera do jeden dla \mathbf{\theta} zmieniającej się od 0 do 2\pi. Ponieważ arccos zmienia się w zakresie \left < 0, \pi \right > musimy rozpoznać czy punkt P leży z tyłu, czy z przodu sfery. W tym celu badamy znak \mathbf{\cos \alpha = \hat F \cdot \hat B}. Jest on równy kosinusowi kąta między tymi dwoma wektorami. Jeśli \cos \alpha > 0 to \displaystyle-\frac{\pi}{2}<\alpha<\displaystyle\frac{\pi}{2}. Czyli punkt P znajduje się z tyłu sfery. Dla punktów z tyłu sfery współrzędną u liczymy tak:v = \displaystyle\frac{\theta}{2\pi}
Z przodu:v = 1 - \displaystyle\frac{\theta}{2\pi}
Przykład implementacji w C#:public override Vector2 GetUV(Intersection a_intersection) { Vector3 normal = (a_intersection.Pos - Pos).Normalized; Vector3 B = Vector3.CrossProduct( Vector3.CrossProduct(Up, normal), Up).Normalized; double a = Forward * B; if (a < 0) { return new Vector2( 1 - (Math.Acos(Right * B) / (2 * Constants.PI)), Math.Acos(Up * normal) / Constants.PI); } else { return new Vector2( Math.Acos(Right * B) / (2 * Constants.PI), Math.Acos(Up * normal) / Constants.PI); } }W przypadku gdy punkt na sferze do lokalnego układu współrzędnych obliczenia znacząco się upraszczają:
public virtual Vector3 GetUVW(Intersection a_intersection) { return WorldToLocal * a_intersection.Pos; } public override Vector2 GetUV(Intersection a_intersection) { Vector3 uvw = a_intersection.UVW; double v = Math.Acos(uvw.Y / uvw.Length) / Constants.PI; double u1 = Math.Atan2(uvw.Z, uvw.X) / (2 * Constants.PI); if (uvw.Z > 0) return new Vector2(u1, v); else return new Vector2(1 + u1, v); }