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ą S−1. 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=(TRS−1)ROT=RS−1
Przy okazji zauważmy, że mając macierz obiekt-świat: M=TRS, macierz transformacji normalnej możemy zapisać jako:
MN=(TRS−1)ROT=((T−1)T(R−1)T(S−1)T)ROT=(((XRS)−1)T)ROT=((M−1)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