Låt oss bygga en 3D-grafikmotor poäng, vektorer och grundläggande begrepp

3D-spelmotorerna som ligger bakom dagens största spel är svindlande verk av matematik och programmering, och många spelutvecklare tycker att det är en svår uppgift att förstå dem i sin helhet. Om du saknar erfarenhet (eller en högskoleexamen, som jag själv) blir denna uppgift ännu svårare. I denna serie strävar jag efter att gå igenom grunderna för grafiksystem i 3D-motorer.

Mer specifikt, i denna handledning diskuteras punkter och vektorer, och allt det roliga som följer med dem. Om du har ett grundläggande grepp om algebra (variabler och variabel matematik) och datavetenskap (grunden för något objektorienterat programmeringsspråk) borde du kunna göra det genom de flesta av dessa handledning, men om du har problem med Några av koncepten, var snäll och fråga! Några av dessa ämnen kan vara fruktansvärt svåra.

Du kan också få extra hjälp på Envato Studio, där du kan hitta massor av fantastiska 3D Design & Modeling-tjänster till överkomliga priser. 

3D Design & Modeling tjänster på Envato Studio

Grunderna för koordinatsystem

Låt oss börja från grunderna. Tredimensionell grafik kräver begreppet ett tredimensionellt utrymme. Det mest använda av dessa utrymmen kallas det kartesiska rymden, vilket ger oss nytta av kartesiska koordinater (de grundläggande \ ((x, y) \) notationerna och 2D-raderna i rymdgraderna som lärs på de flesta högskolor).


Avbildad: Banan av många gymnasieelever.

3-dimensionellt kartesiskt utrymme ger oss en x-, y- och z-axel (beskrivande position baserad på horisontell placering, vertikal placering och respektive djup). Koordinaterna för vilken punkt som helst inom detta utrymme visas som en tupel (i detta fall en 3-tuple, eftersom det finns tre axlar). På ett 2-dimensionellt plan kan en tuple avbildas som \ ((x, y) \) och i tredimensionellt plan visas den som \ ((x, y, z) \). Användningen av denna 3-tuple är att den visar en punkts plats i förhållande till rymdens ursprung (som i sig visas vanligen som \ ((0,0,0) \)).

Tips: Tuple: en ordnad lista (eller sekvens) av element i datavetenskap eller matematik. Så, \ ((K, y, l, e) \) skulle vara en 4-tuple, som visar en sekvens av tecken som utgör mitt namn.

Inom detta utrymme kommer vi att definiera en punkt som en representation av en 3-tupel. Detta kan också visas som:

\ [P = (x, y, z) \]

Förutom denna definition av en punkt måste vi definiera sina delar.

Var och en av elementen inom denna 3-tuple är en skalär (tal) som definierar en position längs a grundvektor. Varje grundvektor måste ha en enhetslängd (det vill säga en längd av exakt 1), så 3-tuples som \ ((1,1,1) \) och \ ((2,2,2) \) kunde inte vara grundviktorer eftersom de är för långa.

Vi definierar tre grundläggande vektorer för vårt utrymme:

\ [\ Begin linje
X & = (1,0,0) \\
Y & = (0,1,0) \\
Z & = (0,0,1)
\ End linje \]


Källa: http://www.thefullwiki.org/Arithmetics/Cartesian_Coordinate.

Koordinatsystemet

Låt oss nu prata om den matematiska definitionen av vårt koordinatsystem, hur det påverkar vårt grafiksystem och de beräkningar vi kan göra.

Representerar poäng

De ursprungspunkten av vårt koordinatsystem kan avbildas som punkten \ (O \), som representerar 3-tupeln (0,0,0). Det betyder att den matematiska representationen av vårt koordinatsystem kan avbildas som:

\ [\ O; X, Y, Z \ \]

Med detta uttalande kan du säga att \ ((x, y, z) \) representerar en punkts position i förhållande till ursprunget. Denna definition betyder också att varje punkt \ (P \), \ ((a, b, c) \) kan representeras som:

\ [P = O + aX + bY + cZ \]

Härifrån kommer jag att referera skalarer i små bokstäver och vektorer i övre fall - så \ (a \), \ (b \) och \ (c \) är skalärer, och \ (X \), \ Y \) och \ (Z \) är vektorer. (De är faktiskt de grundläggande vektorerna vi definierade tidigare.)

Det betyder att en punkt vars tupel är (2,3,4) kan representeras som:

\ [\ Begin linje
(2,3,4) & = (2,0,0) + (0,3,0) + (0,0,4) \\
& = (0,0,0) + (2,0,0) + (0,3,0) + (0,0,4) \\
& = (0,0,0) + 2 (1,0,0) + 3 (0,1,0) + 4 (0,0,1) \\
& = O + 2X + 3Y + 4Z \\
\ End linje \]

Så vi har tagit det här abstrakta begreppet "en punkt i 3D-rymden" och definierat det som fyra separata objekt som lagts till ihop. Denna typ av definition är väldigt viktig när vi vill lägga in koncept i kod.

Ömsesidigt vinkelrätt

Det koordinatsystem som vi ska använda har också den värdefulla egenskapen att vara ömsesidigt vinkelrätt. Det innebär att det finns en 90 graders vinkel mellan var och en av axlarna där de träffas på respektive plan.


Vårt koordinatsystem definieras också som "högerhänt":

Källa: http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html.

I matematiska termer betyder detta att:

\ [X = Y \ gånger Z \]

... där \ (\ times \) representerar korsproduktoperatören.

Om du inte är säker på vad en korsprodukt är, kan den definieras av följande ekvation (förutsatt att du får två 3-tum):

\ [(a, b, c) \ tider (d, e, f) = (bf - ce, cd - av, ae - bd) \]

Dessa uttalanden kan verka tråkiga, men senare kommer de att tillåta oss att göra en mängd olika beräkningar och transformationer mycket lättare. Lyckligtvis behöver du inte memorera alla dessa ekvationer när du bygger en spelmotor - du kan enkelt bygga utifrån dessa uttalanden och sedan bygga ännu mindre komplicerade system utöver det. Tja, tills du måste redigera någonting grundläggande inom din motor och måste uppdatera dig själv på allt detta igen!


Punkter och vektorer

Med alla grunderna i vårt koordinatsystem låses ner, är det dags att prata om punkter och vektorer och, ännu viktigare, hur de interagerar med varandra. Det första att notera är att punkter och vektorer är tydligt olika saker: en punkt är en fysisk plats inom ditt utrymme; en vektor är utrymmet mellan två punkter.


För att försäkra mig om att de två inte blir förvirrade skriver jag punkter i kursiv kursiv, som \ (P \) och vektorer i fetstil, som \ (\ mathbf V \).

Det finns två huvudsakliga axiom som vi ska hantera när vi använder punkter och vektorer, och de är:

  • Axiom 1: Skillnaden mellan två punkter är en vektor, så \ (\ mathbf V = P - Q \)
  • Axiom 2: Summan av en punkt och en vektor är en punkt, så \ (Q = P + \ mathbf V \)
Tips: En axiom är en punkt av resonemang, som ofta ses som uppenbar nog att accepteras utan argument.

Bygga motorn

Med dessa axiom angivna har vi nu tillräckligt med information för att skapa byggklassen som ligger i hjärtat av alla 3D-spelmotorer: Punkt klass och Vektor klass. Om vi ​​skulle bygga vår egen motor med hjälp av denna information skulle det finnas några andra viktiga steg att vidta vid utformningen av dessa klasser (för det mesta att göra med optimering eller hantering av redan befintliga API-er), men vi kommer att lämna dessa ut för enkelhetens skull.

Klassexemplen nedan kommer alla att vara i pseudokod så att du kan följa med ditt programmerade språk. Här är skisser av våra två klasser:

Point Class Variables: num tuple [3]; // (x, y, z) Operatörer: Peka AddVectorToPoint (Vector); Punkt SubtraherVectorFromPoint (Vector); Vector SubtractPointFromPoint (Punkt); Funktion: // senare kommer det att ringa en funktion från ett grafik API, men för nu // bör det här bara skriva ut punktkoordinaterna till skärmdraken drawPoint; 
Vektor klass Variabler: num tuple [3]; // (x, y, z) Operatörer: Vector AddVectorToVector (Vector); Vector SubtraherVectorFromVector (Vector); 

Som en övning, försök att fylla i var och en av dessa klassers funktioner med arbetskod (baserat på vad vi har gått över hittills). När du har fått allt som är klart, gör det till testet genom att göra det här exemplet programmet:

main var punkt1 = ny punkt (1,2,1); var point2 = ny punkt (0,4,4); var vektor1 = ny vektor (2,0,0); var vektor2; point1.drawPoint (); // ska visa (1,2,1) punkt2.drawPoint (); // ska visa (0,4,4) vector2 = point1.subtractPointFromPoint (punkt2); vector1 = vector1.addVectorToVector (vector2); point1.addVectorToPoint (Vector1); point1.drawPoint (); // ska visa (4,0, -2) point2.subtractVectorFromPoint (vector2); point2.drawPoint (); // ska visa (-1,6,7)

Slutsats

Du gjorde det till slutet! Det kan tyckas som en väldigt massa matematik att bara göra två klasser - och det är definitivt. I de flesta fall kommer du aldrig att behöva jobba på ett spel på den här nivån, men med en intim kunskap om hur din spelmotor fungerar är det ändå till hjälp (om bara för självtillfredsställelse).

Om du trodde att det var kul så var noga med att kolla in min nästa handledning om grunderna för grafiksystem: transformationer!

Naturligtvis, när du har skapat grafikmotorn måste du lägga till lite innehåll, så gärna checka ut det brett urvalet av speltillgångar och 3D-modeller på Envato Market.