Kort genomgång av grunderna för 3D-grafik
(För att enklare kunna hänga med så är det ett tips att kolla på koden som finns i slutet på posten.)
En 3D-värld i en dator byggs upp av punkter (vertex'ar) och trianglar mellan punkterna.
Punkterna är representerade som vektorer i ett koordinatsystem. En vektor har en längd och en riktning, och man kan t.ex. ändra dess längd men behålla riktningen om man multiplicerar den med ett vanligt tal (ett vanligt tal kallas för en skalär).
Det är viktigt att göra sig bekant med hur man matematiskt kan räkna med vektorer. Det bästa sättet att lära sig det på är att läsa en kurs i linjär algebra som ges på högskolor. http://sv.wikipedia.org/wiki/Linjär_algebra (på bilden uppe till höger så ser ni hur en föreläsning på högskolan kan gå till, för er som undrat
Men för den som inte orkar vänta så går mycket att plocka upp på nätet om man är intresserad och har relativt lätt för matte. Här följer två sidor som jag tycker verkar ha bra beskrivningar av vektorer, men det finns såklart många fler: http://matmin.kevius.com/vektor.php, http://sv.wikipedia.org/wiki/Vektor
För att ändra på längden på en vektor så multiplicerar man alltså med en skalär (ett vanligt tal), men
att ändra en vektors riktning är lite mera komplicerat, då måste man använda sig av en matris. Matriser är så att säga nästa nivå i linjär algebra och är lite krångligare att räkna med och att förstå hur man ska tolka.
Att lära sig "allt" om matriser kan ta en lång tid, men som tur är så ska vi använda en begränsad del av de operationer man kan utföra med en matris. Det är främst två saker vi behöver kunna göra med matriser:
1. Multiplicera en matris med en vektor, vilket man gör för att transformera (rotera, skala, translatera (flytta)) en vektor, v2 = M * v1, där M är matrisen, v1 är den gamla vektorn och v2 är den nya, transfomerade vektorn.
2. Multiplicera två matriser vilket man gör för att göra en ny matris som är den sammansatta transformen av de två multiplicerade matriserna, M3 = M2 * M1, där M3 är matrisen som representerar den sammansatta transformen av matriserna M1 och M2 (i den ordningen).
Att räkna med matriser är lite annorlunda än att räkna med vanliga tal för M1 * M2 är inte lika med M2 * M1, så man måste hålla reda på ordningen. Här är ett par sidor som verkar ha bra genomgångar av matriser: http://matmin.kevius.com/matris.php, http://www.math.kth.se/~kpetters/avsnitt2.pdf (kolla speciellt där det står om matrismultiplikation.)
Man ska sen alltså använda matriserna för att transformera vektorer. Här finns en sida som har bra illustrerat de vanligaste transformerna: http://www8.tfe.umu.se/courses/systemteknik/Multimed2/mm2_99/....
För att rotera och skala en 3-vektor, (x, y, z), så behöver man multiplicera med en 3x3 matris. Men en translationstransformation kan inte utföras med en 3x3 matris, utan vad man måste göra är att då är att konvertera 3-vektorn (x, y, z) till en 4-vektor (x, y, z, w) genom att lägga till en fjärde komponent som är 1, (x, y, z) -> (x, y, z, 1), och sedan multiplicera med en 4x4 matris. På så vis kan man utföra alla affina transformationer (linjära avbildningar), se http://en.wikipedia.org/wiki/Transformation_matrix#Affine_tra....
När man har konverterat den vanliga 3-vektorn till en 4-vektor så kallades de för homogena koordinater. Namnet homogena koordinater har egentligen ingen betydelse och ett bra sätt att se på det är att det är någonting man gör bara för att smidigt kunna uttrycka alla transformationer på ett enhetligt sätt som 4x4 matriser. När man sedan har gjort klart transformationen så går man tillbaka från 4-vektorn till en vanlig 3-vektorer genom att dividera x, y och z-komponenterna med w-komponenten: (x, y, z, w) -> (x/w, y/w, z/w). Låt inte namnet homogena koordinater skrämma, det är fortfarande precis samma sak, vektorer och matriser!
En snabb tillbakablick:
Multiplikation med skalär (ett tal): kan ändra längden på en vektorn men inte riktningen.
Multiplikation med 3x3 matris: kan rotera och skala en vektorn, men inte translatera eller utföra perspektivprojektion.
Konvertera till 4-vektor och multiplicera med 4x4 matris: kan utföra alla linjära transformationer.
Nu är vi redo att ta punkter som representerar ett objekt och transformera dem så att de hamnar på skärmen. Först så representeras ett objekt, säg en kub, i sitt lokala koordinatsystem, där t.ex. kubens mitt är i origo (0, 0, 0).
1. Kuben transformeras sedan till världskoordinater med en transform som kan t.ex. skala, rotera och flytta kuben.
2. Sedan transformeras världskoordinaterna till kamerakoordinater genom att flytta/rotera hela världen så att kameran hamnar i origo. Värt att notera är att i OpenGL så är transformation 1 och 2 redan sammanslagna till en enda transform. Det är därifrån ModelView matrisen i OpenGL fått sitt namn, för att den är en sammanslagning av Model och View matriserna.
3. Sedan görs en perspektivtransform som gör att saker långt borta blir mindre och saker nära blir större på skärmen, http://en.wikipedia.org/wiki/3D_projection. Efter denna transformation så är punkterna i normaliserade skärmkoordinater.
4. Det enda som är kvar nu är att transformera de normaliserade skärmkoordinaterna till var på skärmen vi vill att vår 3D-scen ska ritas. Det görs utifrån en viewport som säger vänster-, höger-, botten- och toppen-koordinaterna på skärmen.
Alla dessa fyra transformationer görs med matrismultiplikationer:
v_skärm = M_viewport * M_perspektiv * M_kamera * M_värld * v_objekt
där v_objekt är en punkt i objektets lokala koordinatsystem, M_xxx är transform-matriserna och v_skärm är den transformerade punkten i skärmkoordinater.
De fyra matriserna M_viewport, M_perspektiv, M_kamera, M_värld kan slås samman med matrismultiplikationer till en enda matris:
M_tranform = M_viewport * M_perspektiv * M_kamera * M_värld
så att man kan skriva punktens hela transform som:
v_skärm = M_transform * v_objekt
Efter detta är gjort så kan man rita linjer polygoner mellan punkterna på skärmen.
Jag gjorde ett enkelt program som illustrerar det här, det är en fil som finns här http://pastebin.com/pVRXa77G. Det är C++ som går att kompilera i VS2010 och antagligen VS2008 och som körs i Windows. Eller så går det att ladda ner med en projektfil som går att kompilera i VS2010 och där det finns en färdigbyggd binär här http://www.niktech.se/RotatingCubeLines.zip.
Det är ganska mycket information i den här texten som det skulle behövas mycket mera tid och plats för att skriva om, men om ni har frågor så är det säkert någon som kan svara här.
Uppdaterat: Ändrade formuleringen kring homogena koordinater.