Processing math: 100%

2011-09-01

Transformacja normalnej

Promień uderza w skalowaną nierównomiernie sferę, czyli elipsoidę. Nie chcemy jednak pisać osobnego kodu na obsługę elipsy. Promień przed analizą intersekcji poddajemy transformacji świat-obiekt. W wyniku czego nasz promień uderza w sferę o środku w środku układu współrzędnych. Znajdujemy punkt intersekcji. Transformujemy go z powrotem obiekt-świat. To działa. Teraz chcemy wyliczyć normalną w punkcie uderzenia naszej elipsy. Podobnie transformujemy punkt uderzenia świat-obiekt. Wyliczamy normalną dla sfery. Transformujemy ją obiekt-świat. To nie działa.


  
    
      
    
    
      
    
    
      
    
  
  
  
    
      
        image/svg+xml
        
        
      
    
  
  
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
      
      
    
    
  


Na pierwszym rysunku widzimy normalne dla sfery. Na drugim normalne sfery zmapowane obiekt-świat błędnie, za pomocą takiej samej metody jak dla punktów intersekcji. Na trzecim widzimy to co chcielibyśmy uzyskać.

Weźmy prostą w 2D f=ax, jej pochodna f=a, jej normalna (nazwijmy ją tak) f=a. Teraz tak jak na naszym rysunku skalujemy zwężając dwukrotnie w osi Y. Równanie naszej prostej f=12ax, zaś normalnej f=12a. Załóżmy teraz dwukrotnie rozciągamy w osi X. Równanie naszej prostej, pochodnej i normalnej zmienia się podobnie. Czyli skalując o a skalujemy normalną o 12. Podobnie moglibyśmy wykazać wychodząc z definicji pochodnej.

Czyli jeśli nasza macierz skalowania to S, to musimy ją zastąpić w macierzy transformacji obiekt-świat macierzą S1. Translację powinniśmy pominąć, gdyż mamy do czynienia nie z punktem, a z wektorem. Rotację musimy zachować. Jeśli macierz naszej transformacji dla wierzchołków ma postać M=TRS, to dla normalnych będzie miała postać M=(TRS1)ROT=RS1

Przy okazji zauważmy, że mając macierz obiekt-świat: M=TRS, macierz transformacji normalnej możemy zapisać jako:

MN=(TRS1)ROT=((T1)T(R1)T(S1)T)ROT=(((XRS)1)T)ROT=((M1)T)ROT=((MT)1)ROT

W przekształceniach skorzystaliśmy z faktu, że macierz odwrotna macierzy rotacji jest równa jej transpozycji, macierz transponowana macierzy skalowania jest równa jej samej. X to przekształcona macierz transpozycji. Ponieważ bierzemy część rotacji X ulega ona zniesieniu, równie dobrze możemy wpisać dowolną macierz która w części rotacyjnej 3x3 jest macierzą jednostkową, w szczególności T. Zauważmy, że elementy macierzy T nie wpływają na elementy macierzy rotacji 3x3 w macierzy S i R, ani ich iloczynu. Tak więc macierz transpozycji obiekt-świat dla normalnych jest równa odwrotnej transponowanej macierzy obiekt-świat dla wierzchołków, albo jak kto woli odwrotnej transponowanej macierzy obiekt-świat dla wierzchołków. Czasami może nam się to przydać jeśli nie wiemy jak taka macierz została złożona.

Przykład kodu:
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;
    m_local_to_world_normal = m_world_to_local.Transposed.Rotation;
}

Brak komentarzy:

Prześlij komentarz