Romtransformasjoner
Det vil si at dersom jeg legger den høyre hånda loddrett ned, som i karate, med fingrene langs den positive x-aksen, og krummer hånda mot y-aksen, vil tommelen peke opp langs den positive z-aksen. |
Vi bruker homogene koordinater fra starten av. Det vil si at den generelle transformasjonsmatrisen er en 4x4 matrise, og den generelle vektorformen er en kolonnevektor med fire rader.
P2=M·P1
|x2| |m11 m12 m13 m14| |x1| |y2| |m21 m22 m23 m24| |y1| |z2| = |m31 m32 m33 m34| * |z1| |1 | |m41 m42 m43 m44| |1 |
Translasjon
|1 0 0 tx| |0 1 0 ty| |0 0 1 tz| |0 0 0 1 | |
En translasjon i rommet er beskrevet ved tx, ty og tz. Vi ser lett at denne matrisen realiserer ligningene: x2=x1+tx y2=y1+ty z2=z1+tz |
Skalering
|sx 0 0 0| |0 sy 0 0| |0 0 sz 0| |0 0 0 1| |
Skalering i rommet er beskrevet ved sx, sy og sz. Vi ser at denne matrisen realiserer følgende ligninger: x2=x1·sx y2=y1·sy z2=z1·sz |
Rotasjon
Rotasjon er litt mer komplisert. Vi definerer tre ulike basisrotasjoner, en om hver av aksene.
Om Z-aksen |cos(v) -sin(v) 0 0| |sin(v) cos(v) 0 0| |0 0 1 0| |0 0 0 1| |
Om X-aksen|1 0 0 0| |0 cos(v) -sin(v) 0| |0 sin(v) cos(v) 0| |0 0 0 1| |
Om Y-aksen|cos(v) 0 sin(v) 0| | 0 1 0 0| |-sin(v) 0 cos(v) 0| | 0 0 0 1| |
Geometri
Identitetsmatrisa
|1 0 0 0| |0 1 0 0| |0 0 1 0| |0 0 0 1| |
Igjen kan vi tolke den som:
|
Speiling
|1 0 0 0| |0 1 0 0| |0 0 -1 0| |0 0 0 1| |
Vi kan speile om de ulike planene ved å bruke skaleringsfaktor -1 på aksen som står normalt på planet. Merk spesielt matrisen til venstre. Den speiler om xy-planet, og endrer derved koordinatene fra et høyrehåndssystem til et venstrehåndssystem |
Projeksjon
|1 0 0 0| |0 1 0 0| |0 0 0 0| |0 0 0 1| |
Vi har så langt kun konsentrert oss om å flytte rundt på punkter i planet og rommet. Vi skal senere bekymre oss for hvordan vi kan avbilde romfigurer på et plan. Det kan være nyttig å merke seg allerede nå at vi kan gjøre også dette ved hjelp av en matriseoperasjon. Vi kan projisere et punkt ortogonalt ned i et av hovedplanene ved å anvende en matrise som skalerer aksen normalt på planet med 0. Matrisen til venstre er en parallellprojeksjon ned i xy-planet. |
Sammensatte operasjoner
De samme resonnementene vi førte i planet kan overføres til rommet. Igjen benytter vi oss av at vi kan lage sammensatte transformasjonsmatriser som representerer sammensatte geometriske transformasjoner.
I planet er situasjonen ganske oversiktlig og vi kan lett følge operasjonene grafisk. I rommet blir det fort komplisert, spesielt når vi roterer. En ganske krevende øvelse som ofte gjengis i grafisk litteratur er rotasjon om en vilkårlig akse. Vi drar ikke dette resonnementet her. Det er sjelden vi får bruk for å konstruere såpass kompliserte transformasjoner i hodet når vi programmerer. Som regel kan vi slippe unna med enklere løsninger dersom vi treffer noen fornuftige valg i beskrivelsen av de objektene vi vil framstille.
La oss ta et enkelt eksempel på rotasjon om en akse parallell til en av hovedaksene. Vi ønsker å rotere klossen på figuren 90 grader om en akse som går gjennom P og er loddrett på xy-planet. Klossen har sidekanter på 1. Etter operasjonen bør punktet Q (2,4,4) havne i Q2(1,3,4), og P(2,3,4) bør havne uforandret i P2(2,3,4).
Med vår kunnskap om transformasjoner må det være en god strategi å:
- flytte punktet P inn til z-aksen, matrisen T1
- rotere om z-aksen, matrisen R
- flytte klossen tilbake, matrisen T2
Vi husker fra kapittelet om 2D-transformasjoner at vi anvender matrisene i motsatt rekkefølge og multipliserer fra venstre. Vi lager altså matrisen M=T2·R·T1, og kan finne Q'=M·Q og P'=M·P.
|1 0 0 2| |0 -1 0 0| |1 0 0 -2| |0 -1 0 5| M=|0 1 0 3|*|1 0 0 0|*|0 1 0 -3|=|1 0 0 1| |0 0 1 0| |0 0 1 0| |0 0 1 0| |0 0 1 0| |0 0 0 1| |0 0 0 1| |0 0 0 1| |0 0 0 1| |0 -1 0 5| |2| |1| Q2=M*Q=|1 0 0 1|*|4|=|3| |0 0 1 0| |4| |4| |0 0 0 1| |1| |1| |0 -1 0 5| |2| |2| P2=M*P=|1 0 0 1|*|3|=|3| |0 0 1 0| |4| |4| |0 0 0 1| |1| |1|
Figuren eller koordinatsystemet
For å gjenta kort: Resonnementet ovenfor er basert på
følgende:
Vi holdt fast i ideen om å flytte figuren. Rekkefølgen på matrisene er omvendt av den geometrisk logiske rekkefølgen, av grunner som vi drøftet tidligere for planoperasjoner.
Vi kan velge et annet resonnement som på en måte
passer bedre til logikken med rekkefølgen av operasjoner.
Det går som følger:
- Vi flytter origo ut til rotasjonsaksen, T2
- Vi roterer, R
- Vi flytter origo tilbake, T1
Med dette resonnementet blir rekkefølgen M=T2·R·T1 kanskje mer logisk.
I OpenGL
De aktuelle funksjonene i OpenGL:
glLoadIdentity() glTanslatef(tx,ty,tz) glRotatef(v,x,y,z) glScalef(sx,sy,sz)
Merk at f-en i funksjonsnavnene angir at parametrene er i flytetall. Det finnes også heltallsvarianter av funksjonene. Merk videre at glRotate spesifiserer både rotasjonsvinkel (i grader) og rotasjonsakse. En rotasjon med 30 grader mot klokka om z-aksen blir således:
glRotatef(30.0f,0.0f,0.0f,1.0f)
I tillegg til dette har OpenGL noen funksjoner som setter oss i stand til å manipulere transformasjonsmatrisene direkte.
glLoadMatrixd(...)
lar oss sette matrisa direkte og
glMultMatrixd(...)
lar oss multiplisere med en egendefinert matrise. Merk OpenGLs homogenisering av resultatet, se modulen Homogenisering
Vi kan også få tak i gjeldende matrise med den generelle glGetFloatv() funksjonen, f.eks. slik
glGetFloatv(GL_MODELVIEW_MATRIX,..)
Rader og kolonner
Igjen har vi valget om vi vil skrive operasjonene som P2=M·P, med P og P2 som kolonnevektorer eller P2=P·M, med P og P2 som radvektorer.
Dersom vi velger den siste varianten blir de respektive basismatrisene:
Translasjon |
|1 0 0 0| |0 1 0 0| |0 0 1 0| |tx ty tz 1| |
Skalering |
|sx 0 0 0| |0 sy 0 0| |0 0 sz 0| |0 0 0 1 | |
Rotasjon om z-aksen |
|cos sin 0 0| |-sin cos 0 0| |0 0 1 0| |0 0 0 1| |
Rotasjon om x-aksen |
|1 0 0 0| |0 cos sin 0| |0 -sin cos 0| |0 0 0 1| |
Rotasjon om y-aksen |
|cos 0 -sin 0| |0 1 0 0| |sin 0 cos 0| |0 0 0 1| |
En god del grafisk litteratur beskriver transformasjoner på denne måte. Se også transponering av matriser i modulen: Homogenisering.