Processing math: 21%

2011-08-02

Mapowanie tekstury na sferę

Rysunek:


  
    
      
    
    
      
    
    
      
    
    
      
    
  
  
  
    
      
        image/svg+xml
        
        
      
    
  
  
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
    
    
      
      
    
    
      
      
    
    
    
    P
    O
    U
    F
    R
    A
    B
    φ
    ϴ
    
    
  
Wektory ˆU (góra), ˆF (wprzód), ˆR (prawo) orientując sferę w przestrzeni. Zakładamy, że wektory te są znormalizowane. Mapowanie przeprowadzamy dla punktu P znajdującego się na sferze.

Do wyznaczenia jest para (u,v), gdzie u zależy od kąta θ, v zależy od kąta φ, u0,1, v0,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}:

\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).

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);
}

Dodanie skalowanie obiektów

Dodanie skalowanie umożliwi nam skalowanie obiektów, dzięki czemu będziemy w stanie przeskalować element lub grupę elementów sceny bez modyfikacji ich współrzędnych i parametrów. Dzięki skalowaniu będziemy też mogli zrobić z sfery elipsoidę.

Dodanie skalowania wymusi zmiany na większości już napisanego kodu. Większość parametrów intersekcji i samego promienia przed wykorzystaniem w kodzie obiektów sceny będzie musiała zostać sprowadzona do lokalnego układu współrzędnych.

Dzięki temu kod w wielu miejscach będzie można uprościć gdyż obiekt w lokalnym układzie współrzędnych będzie zorientowany wzdłuż wersorów układu współrzędnych, a jego środek będzie w środku układu współrzędnych.

Z dużym prawdopodobieństwem zmiany wprowadzone przy okazji dodawania skalowania powinny także pociągnąć pochylanie.

Współczynniki skalowania mogą być także ujemne.

Orientacja obiektu w przestrzeni - skalowanie

Po dodaniu skalowania do informacji orientującej obiekt w przestrzeni kod tworzący macierze transformacji świat-obiekt zmienia się z :
private void UpdateTransformationMatrices()
{
    m_local_to_world = Matrix4.CreateTranslation(Pos) *
        new Matrix4(Right, Up, Forward);
    m_world_to_local = m_local_to_world.Inverted;
}
na:
private void UpdateTransformationMatrices()
{
    m_local_to_world = Matrix4.CreateTranslation(Pos) * 
        new Matrix4(Right, Up, Forward) * Matrix4.CreateScale(Scale);
    m_world_to_local = m_local_to_world.Inverted;
}