Să construim un motor grafic 3D puncte, vectori și concepte de bază

Motoarele de jocuri 3D care se află în spatele celor mai mari jocuri de astăzi sunt lucrări uimitoare ale matematicii și programării, iar mulți dezvoltatori de jocuri consideră că înțelegerea lor în întregime este o sarcină dificilă. Dacă sunteți lipsit de experiență (sau un grad de colegiu, ca mine), această sarcină devine și mai dificilă. În această serie, scopul meu este să vă umblu prin elementele de bază ale sistemelor grafice în motoarele 3D.

Mai exact, în acest tutorial vom discuta punctele și vectorii și toată distracția care vine cu ei. Dacă aveți o înțelegere de bază a algebrei (variabile și matematică variabilă) și informatică (elementele de bază ale oricărui limbaj de programare orientat în funcție de obiect), ar trebui să aveți posibilitatea să faceți acest lucru prin majoritatea acestor tutoriale, dar dacă aveți probleme cu oricare dintre concepte, vă rugăm să puneți întrebări! Unele dintre aceste subiecte pot fi extrem de dificile.

Puteți obține, de asemenea, ajutor suplimentar la Envato Studio, unde puteți găsi o mulțime de servicii fantastice de design și modelare 3D pentru prețuri accesibile. 

Proiectare și modelare 3D pe Envato Studio

Elementele de bază ale sistemelor de coordonate

Să începem de la elementele de bază. Grafica tridimensională necesită conceptul unui spațiu tridimensional. Cea mai frecventă utilizare a acestor spații se numește spațiul cartezian, care ne conferă avantajele coordonatelor cartesiene (notațiile de bază \ ((x, y) \) și graficele 2D cu grilă distribuite care sunt predate în majoritatea liceelor).


Înfățișată: răzvrătirea existenței multor colegi de școală.

Spațiul cartesian 3-dimensional ne dă o axă x, y și z (descriind poziția bazată pe plasarea orizontală, plasarea verticală și, respectiv, adâncimea). Coordonatele pentru orice punct din acest spațiu sunt arătate ca a tuplu (în acest caz un 3-tuple, deoarece există trei axe). Pe un plan 2-dimensional, o tuplă ar putea fi descrisă ca \ ((x, y) \), iar în plan tridimensional, ea este reprezentată ca \ ((x, y, z) \). Utilizarea acestei 3-tuple este aceea că arată locația unui punct relativ la originea spațiului (care în sine este prezentat în general ca \ ((0,0,0) \)).

Bacsis: Tuple: o listă ordonată (sau secvență) a elementelor din informatică sau matematică. Deci, \ ((K, y, l, e) \) ar fi o 4-tuplă, arătând o secvență de caractere care îmi alcătuiesc numele.

În acest spațiu, vom defini un punct ca o reprezentare a unei 3-tuple. Acest lucru poate fi afișat și ca:

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

Pe lângă această definiție a unui punct, trebuie să definim părțile sale.

Fiecare dintre elementele din această 3-tuplă este a mărime scalară (număr) care definește o poziție de-a lungul unui vector de bază. Fiecare vector de bază trebuie să aibă o lungime de unitate (adică, o lungime de exact 1), deci 3-tuple precum \ ((1,1,1) \) și \ ((2,2,2) \) să fie vectori de bază deoarece sunt prea lungi.

Definim trei vectori de bază pentru spațiul nostru:

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


Sursă: http://www.thefullwiki.org/Arithmetics/Cartesian_Coordinate.

Sistemul de coordonate

Acum, să vorbim despre definiția matematică a sistemului nostru de coordonate, despre modul în care afectează sistemul nostru grafic și despre calculele pe care le putem face.

Reprezentarea punctelor

punct de origine din sistemul nostru de coordonate poate fi reprezentat ca punct \ (O \), care reprezintă 3-tuple (0,0,0). Aceasta înseamnă că reprezentarea matematică a sistemului nostru de coordonate poate fi reprezentată ca:

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

Prin această afirmație, puteți spune că \ ((x, y, z) \) reprezintă poziția unui punct în raport cu originea. Această definiție înseamnă, de asemenea, că orice punct \ (P \), \ ((a, b, c) \) poate fi reprezentat ca:

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

De aici vom face referire la scalare în litere mici și vectori în majuscule - deci \ (a \), \ (b \) și \ (c \) sunt scalare și \ (X \), \ Y \) și \ (Z \) sunt vectori. (Ei sunt de fapt vectorii de bază pe care i-am definit mai devreme.)

Aceasta înseamnă că un punct al cărui picior este (2,3,4) ar putea fi reprezentat ca:

\ [\ Begin aliniat
(2,3,4) a = (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) \\
& = 0 + 2X + 3Y + 4Z \\
\ End aliniat \]

Deci, am luat acest concept abstract de "un punct în spațiul 3D" și l-am definit ca fiind patru obiecte separate adăugate împreună. Acest tip de definiție este foarte important ori de câte ori dorim să punem orice concept în cod.

Perpendiculară reciproc

Sistemul de coordonate pe care îl vom folosi are și proprietatea valoroasă a ființei reciproc perpendicular. Aceasta înseamnă că există un unghi de 90 de grade între fiecare dintre axele pe care se întâlnesc pe planurile lor respective.


Sistemul nostru de coordonate va fi de asemenea definit drept "dreptaci":

Sursă: http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html.

Din punct de vedere matematic, aceasta înseamnă că:

\ [X = Y \ ori Z \]

... unde \ (\ ori \) reprezintă operatorul de produs încrucișat.

În cazul în care nu sunteți sigur ce este un produs încrucișat, acesta poate fi definit prin următoarea ecuație (presupunând că vi se dau două 3 tuple):

\ (a, b, c) \ ori (d, e, f) = (bf - ce, cd - af, ae - bd)

Aceste afirmații ar putea părea plictisitoare, dar mai târziu, ele ne vor permite să facem o varietate de calcule și transformări diferite mult mai ușor. Din fericire, nu trebuie să memorați toate aceste ecuații atunci când construiți un motor de joc - puteți construi pur și simplu din aceste afirmații și apoi puteți construi și sisteme mai puțin complicate. Ei bine, până când trebuie să modificați ceva fundamental în motorul dvs. și trebuie să vă reîmprospătați din nou pe toate acestea!


Puncte și vectori

Cu toate elementele de bază ale sistemului nostru de coordonate blocate, timpul să vorbim despre puncte și vectori și, mai important, modul în care interacționează unul cu celălalt. Primul lucru de reținut este că punctele și vectorii sunt lucruri distincte diferite: un punct este o locație fizică în spațiul dvs.; un vector este spațiul dintre două puncte.


Pentru a vă asigura că cei doi nu se confundă, voi scrie puncte în italice de capital, ca \ (P \) și vectori în capital boldface, ca \ (\ mathbf V \).

Există două axiome principale cu care ne vom ocupa atunci când vom folosi puncte și vectori și care sunt:

  • Axiomul 1: Diferența dintre două puncte este un vector, deci \ (\ mathbf V = P - Q \)
  • Axiom 2: Suma unui punct și a unui vector este un punct, deci \ (Q = P + \ mathbf V \)
Bacsis: Un axiomă este un punct de raționament, adesea văzut ca suficient de evident pentru a fi acceptat fără argumente.

Construirea motorului

Având în vedere aceste axiome, avem acum suficiente informații pentru a crea clasele blocului de clădiri care se află în centrul oricărui motor de joc 3D: Punct clasa și Vector clasă. Dacă am avea de gând să construim propria noastră mașină folosind aceste informații, s-ar face și alți pași importanți în crearea acestor clase (mai ales în ceea ce privește optimizarea sau tratarea API-urilor deja existente), dar le vom lăsa de dragul simplității.

Exemplele de clasă de mai jos vor fi toate în pseudocod, astfel încât să puteți urma împreună cu limba dvs. de programare de alegere. Iată contururile celor două clase:

Clasa de puncte Variabile: număr [3]; // (x, y, z) Operatori: Point AddVectorToPoint (Vector); Punctul SubtractVectorFromPoint (Vector); Vector SubtractPointFromPoint (punct); Funcția: // mai târziu aceasta va apela o funcție dintr-un grafic API, dar pentru moment // ar trebui să fie doar tipărirea coordonatelor punctelor în ecranul drawPoint; 
Clasa Vector Variables: num tuple [3]; // (x, y, z) Operatori: Vector AddVectorToVector (Vector); Vector SubtractVectorFromVector (Vector); 

Ca exercițiu, încercați să completați funcțiile fiecărei clase cu codul de lucru (pe baza a ceea ce am parcurs până acum). Odată ce ați terminat toate acestea, puneți-l la încercare făcând acest exemplu de program:

principal var punct1 = punct nou (1,2,1); var punctul2 = punct nou (0,4,4); var vector1 = vector nou (2,0,0); var vector2; point1.drawPoint (); // ar trebui să afișeze (1,2,1) point2.drawPoint (); // ar trebui să afișeze (0,4,4) vector2 = point1.subtractPointFromPoint (point2); vector1 = vector1.addVectorToVector (vector2); point1.addVectorToPoint (vector1); point1.drawPoint (); // ar trebui să afișeze (4,0, -2) point2.subtractVectorFromPoint (vector2); point2.drawPoint (); // ar trebui să afișeze (-1,6,7)

Concluzie

Ai reușit până la urmă! Ar putea părea ca o grămadă de matematică să facă doar două clase - și cu siguranță este. În cele mai multe cazuri, nu va trebui niciodată să lucrați la un joc la acest nivel, însă cunoașterea intimă a funcționării motorului dvs. de joc este de ajutor (totuși, numai pentru satisfacția de sine).

Dacă ați crezut că acest lucru este distractiv, atunci asigurați-vă că pentru a verifica meu următorul tutorial pe bază de sistem grafic: transformări!

Desigur, odată ce ați creat motorul grafic, va trebui să adăugați conținut, deci nu ezitați să verificați selecția largă a jocurilor și a modelelor 3D de pe Envato Market.