This is an old revision of the document!


Laboratorul 02

Pentru rezolvarea cerințelor din acest laborator, aveți nevoie de codul utilizat în rezolvarea cerințelor din cadrul laboratorului 1. În laboratoarele 2 și 3, vom reutiliza acest cod. În situatia în care nu ați rezolvat laboratorul 1, va trebui sa îl realizați mai întâi pe el și ulterior să reveniți la cerințele celui curent.

Reamintire!!! Puteți prezenta rezolvările cerințelor de până la 2 laboratoare, în fiecare săptămână. De exemplu, puteți prezenta laboratorul curent și pe cel din săptămâna anterioară, în totalitate sau parțial, inclusiv punctajul pentru cerința bonus :) .

Pentru studenții care au realizat laboratorul pe o versiune a framework-ului datată înainte de 19.10.2023

Va trebui să descărcați din nou framwork-ul de laborator, deoarece a suferit câteva modificări importante și să copiați codul celor 4 metode: ComputeTriangleArea(), CheckPointInsideTriangle(), ComputePixelColor() și ComputePixelDepth(), din versiunea de framework utilizată pentru rezolvarea cerințelor din laboratorul anterior, în versiunea curentă.

Va fi necesar sa utilizați din nou utilitarul CMake. Pentru a vă reaminti procesul de realizare a setup-ului, puteți să reconsultați pagina dedicată acestui lucru.

Transformări în spații 2D

În laboratorul anterior, am văzut cum se poate desena un triunghi pe ecran, dacă avem la dispoziție informația necesară pentru fiecare vârf: coordonatele în spațiul 2D, valoarea de adâncime și o culoare. Cu toate acestea, un astfel de sistem nu este suficient de flexibil, deoarece, în cadrul unei aplicații grafice în timp real, dorim să realizăm animații cu un model 3D, reprezentat de o rețea de triunghiuri. Coordonatele inițiale ale triunghiurilor trebuie modificate pentru a realiza o animație. Realizarea aceleeași modificări, sau transformări, pentru toate vârfurile unei rețele de triunghiuri, produce, din punct de vedere vizual, efectul de aplicare a modificării pentru întreg ansamblul, respectiv pentru tot modelul 3D.

Din acest motiv, de-alungul timpului, au fost standardizate mai multe tipuri de modificări asupra informației unui vârf, în particular asupra coordonatelor lui, ce pot fi utilizate în vederea realizării animațiilor.

Transformarea de translație (deplasare)

Transformarea cea mai de bază este cea utilizată pentru modificarea coordonatelor unui vârf. Acest proces se realizeaza prin deplasarea coordonatelor unui vârf cu un anumit vector de deplasare și poartă numele de translație sau translatare.

În imaginea de mai jos, în partea dreaptă, se poate observa rezultatul translației pătratului din partea stângă cu vectorul de translație $\vec{t}=\begin{bmatrix}
2 & 1
\end{bmatrix}$ .

Formula pentru realizarea procesului de translație este:

$$ x'=x+t_x\\ y'=y+t_y $$

Transformarea de modificare a scării

O altă transformare, ce poate fi utilizată în realizarea animațiilor, este modificarea scării unui obiect, respectiv mărirea sau micșorarea obiectului.

În imaginea de mai jos, în partea dreaptă, se poate observa rezultatul modificării scării pentru pătratul din partea stângă, cu vectorul de scară $\vec{s}=\begin{bmatrix}
2 & 2
\end{bmatrix}$ .

Formula pentru realizarea procesului de modificare a scării este:

$$ x'=s_x \cdot x\\ y'=s_y \cdot y $$

Transformarea de rotație

Ultima transformare des intalnită în grafica pe calculator este rotația unui model. Pentru realizarea acestui proces, pentru spații 2D, vom utiliza un aparat matematic care se aplică în felul următor: rotația unui triunghi se realizeaza prin rotația tuturor vârfurilor, în sens trigonometric, față de centrul axelor de coordonate.

Un exemplu pentru această transformare se poate vedea în imaginea de mai jos, unde pătratul este rotit cu 45 de grade, în sens trigonometric, față de punctul v0, care este în originea axelor de coordonate.

Formula pentru această transformare este:

$$ x'=x \cdot cos(\theta)-y \cdot sin(\theta)\\ y'=x \cdot sin(\theta)+y \cdot cos(\theta) $$

Această formula reiese din următorul fapt. Conform imaginii de mai jos, avem punctul V, pe care dorim sa îl rotim cu unghiul B, în sens trigonometric, față de originea axelor de coordonate pentru a obține punctul V'.

Componentele x și y ale coordonatei lui V se pot scrie și sub forma:

$$ x=r \cdot cos(\alpha)\\ y=r \cdot sin(\alpha) $$

De asemenea, componentele x' și y' ale coordonatei lui V' se pot scrie sub forma:

$$ x'=r \cdot cos(\alpha + \beta)\\ y'=r \cdot sin(\alpha + \beta)\\ $$

Continuăm prin înlocuirea sumei din funcțiile trigonometrice cu:

$$ x'=r \cdot cos(\alpha) \cdot cos(\beta)-r \cdot sin(\alpha) \cdot sin(\beta)\\ y'=r \cdot cos(\alpha) \cdot sin(\beta)+ r\cdot sin(\alpha) \cdot cos(\beta)\\ $$

În final, înlocuim cu x și y în rezultatul anterior, conform primei formule din această notă și obținem:

$$ x'=x \cdot cos(\theta)-y \cdot sin(\theta)\\ y'=x \cdot sin(\theta)+y \cdot cos(\theta) $$

Compunerea transformărilor

Transformarile de baza, prezentate mai sus, nu sunt suficient de flexibile pentru a obține orice tip de animații prin utilizarea individuală a unui anume tip. Un exemplu este rotația față de \\propriul centru
al unui pătrat de latură 1 ce a fost definit cu colțul stânga-jos în originea axelor de coordonate. O aplicare directă a transformării de rotație rezultă în rotatia pătratului față de colțul stânga-jos. Din acest motiv, este necesar sa obținem rezultatul dorit prin compunerea mai multor transformări. Lanțul de transformări este vizibil în imaginea de mai jos.

  1. Primul pas este translația pătratului, astfel încat centrul lui să se afle în originea axelor de coordonate
  2. În acest moment, putem roti vârfurile pătratului față de centrul lui
  3. După rotație, pătratul rămâne cu centrul în originea axelor de coordonate, astfel că aplicăm transformarea inversă de la punctul 1 pentru a readuce pătratul cu centrul în poziția lui originală

Același proces se poate aplica și pentru transformarea de modificare a scării, pentru a face modificarea de scară din centrul pătratului :) .

Forma matriceală a transformărilor

Compunerea transformărilor definite mai sus poate avea o formă puțin mai greoaie de calculat. De exemplu, formula finală pentru compunerea de mai sus, în care rotim un pătrat față de propriul centru, este:

$$ x'=(x-0.5) \cdot cos(45)-(y-0.5) \cdot sin(45) + 0.5\\ y'=(x-0.5) \cdot sin(45)+(y-0.5) \cdot cos(45) + 0.5 $$

Pentru a simplifica procesul de calcul, se folosește forma matriceală a transformărilor. In plus, pentru a utiliza aceasta forma, vectorii pentru care se aplica transformarea, devin matrici. In aceasta situatie, avem 2 posibilitati:

Vectori linie

Pentru fiecare din cele 3 transformări de bază de mai sus, in situatia in care utilizam vectori linie, forma matriceală este:

$$ \begin{bmatrix} {x+t_x} & {y+t_y} & 1 \end{bmatrix} = \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ t_x & t_y & 1 \end{bmatrix} $$

$$ \begin{bmatrix} {s_x \cdot x} & {s_y \cdot y} & 1 \end{bmatrix} = \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} s_x & 0 & 0\\ 0 & s_y & 0\\ 0 & 0 & 1 \end{bmatrix} $$

$$ \begin{bmatrix} {x \cdot cos(\theta)-y \cdot sin(\theta)} & {x \cdot sin(\theta)+y \cdot cos(\theta)} & 1 \end{bmatrix} = \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} cos(\theta) & sin(\theta) & 0\\ -sin(\theta) & cos(\theta) & 0\\ 0 & 0 & 1 \end{bmatrix} $$

Compunerea transformarilor se poate realiza prin inmultirea matricilor corespunzatoare fiecarei transformari. Astfel, pentru exemplul de mai sus, in care se roteste un patrat in jurul propriului centru, lantul de transformari este urmatorul:

$$ \begin{bmatrix} x' & y' & 1 \end{bmatrix} = \begin{bmatrix} x & y & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ -0.5 & -0.5 & 1 \end{bmatrix} \begin{bmatrix} cos(45) & sin(45) & 0\\ -sin(45) & cos(45) & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0.5 & 0.5 & 1 \end{bmatrix} $$

Se poate observa ca doar transformarea de translatie necesita o matrice de dimensiune 3×3, iar pentru celelalte 2 transformari sunt necesare matrici de dimensiune 2×2. Sunt 2 motive principale pentru care se utilizeaza matrici de 3×3 pentru toate transformarile:

  • Pentru a putea crea transformari compuse, operatia de inmultire intre matrici trebuie sa fie posibila, astfel ca se utilizeaza aceeasi dimensiune pentru toate tipurile de matrici de transformare
  • In procesul de transformare perspectiva, ce va fi utilizata in laboratorul urmator, se utilizeaza coordonate intr-un spatiu omogen, ce necesita o informatie scalara suplimentara. Vom discuta mai multe detalii in legatura cu acest aspect laboratorul urmator :) .

Vectori coloana

Alternativ, se pot utiliza vectorii sub forma unei matrici coloana, de dimensiune 3×1. Pentru a utiliza astfel de vectori, toate matricile descrise anterior trebuie transpuse. Astfel, matricea de translatie devine:

$$ \begin{bmatrix} x+t_x & y+t_y & 1 \end{bmatrix} ^t =( \begin{bmatrix} x& y& 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ t_x & t_y & 1 \end{bmatrix})^t $$

Deoarece, conform urmatoarei proprietati a matricilor:

$$ (M_{0} \cdot M_{1} \cdot ... \cdot M_{n-1} \cdot M_{n})^{t} = M_{n}^{t} \cdot M_{n-1}^{t} \cdot ... \cdot M_{1}^{t}\cdot M_{0}^{t} $$

Rezulta ca forma matricei pentru transformarea de translatie este:

$$ \begin{bmatrix} x+t_x \\ y + t_y \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ t_x & t_y & 1 \end{bmatrix}^t \begin{bmatrix} x& y& 1 \end{bmatrix} ^t= \begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

Analog pentru matricile celorlalte 2 transformari:

$$ \begin{bmatrix} s_x \cdot x \\ s_y \cdot y \\ 1 \end{bmatrix} = \begin{bmatrix} s_x & 0 & 0\\ 0 & s_y & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

$$ \begin{bmatrix} x \cdot cos(\theta)-y \cdot sin(\theta) \\ x \cdot sin(\theta)+y \cdot cos(\theta) \\ 1 \end{bmatrix} = \begin{bmatrix} cos(\theta) & -sin(\theta) & 0\\ sin(\theta) & cos(\theta) & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} $$

Pentru transformarea compusa data exemplu mai devreme, vom avea:

$$ \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0.5\\ 0 & 1 & 0.5\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} cos(45) & -sin(45) & 0\\ sin(45) & cos(45) & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & -0.5\\ 0 & 1 & -0.5\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

Observam ca, in situatia in care folosim vectori coloana, ordinea de aplicare a transformarilor este de la ultima matrice inmultita la prima. In plus, vectorul pentru care se aplica lantul de transformari este intotdeauna la final.

Libraria glm

In cadrul laboratoarelor de la aceasta materie, pana la finalul semestrului, vom utiliza vectori in forma coloana. Ambele forme, atat forma linie si forma coloana a vectorilor, sunt la fel de bune si compatibile cu procesorul grafic.

Din motive de optimizare a accesului la memoria procesorului grafic, libraria glm foloseste la baza matrici column-major, mai precis, matrici care au informatia transpusa in memorie. Astfel, in constructorul tipului de date glm::mat3, trebuie transmisa forma transpusa a matricei pe care dorim sa o retinem.

De exemplu, matricea pentru transformarea de translatie, utilizata pentru inmultirea cu vectori coloana, trebuie initializata astfel:

glm::mat3 Translate(float tx, float ty)
{
	return glm::mat3( 
        	 1,  0, 0,     // coloana 1 in memorie 
		 0,  1, 0,     // coloana 2 in memorie 
		tx, ty, 1);    // coloana 3 in memorie 
 
}

De asemenea, avem optiunea sa o initializam direct cu liniie si sa o transpunem ulterior:

glm::mat3 Translate(float tx, float ty)
{
	return glm::transpose(
		glm::mat3( 1, 0, tx, 
			   0, 1, ty, 
			   0, 0, 1)
	); 
}

Transformarea fereastra-poarta

In situatia in care dorim ca aplicatia grafica proiectata de noi sa nu depinda de rezolutia ferestrei si astfel sa poata rula la rezolutii diferite, indiferent care ar fi acestea, trebuie sa nu mai definim coordonatele varfurilor in coordonatele pixelilor de pe ecran. Pentru acest proces, vom defini un spatiu special, denumit spatiu logic, in a carui coordonate vom defini

In laborator, a fost definit spatiul logic, dupa cum urmeaza:

struct ViewportSpace
{
    int x;
    int y;
    int width;
    int height;
};
 
struct LogicSpace
{
    float x;
    float y;
    float width;
    float height;
};

De exemplu, pentru a transforma obiectele definite in spatiul logic ce are coltul stanga jos la coordonatele (1, 1) si rezolutia de 3×2, astfel incat sa fie puse pe tot ecranul, de rezolutie 1280×720, se pot defini spatiile in felul urmator. De asemenea, transformarea se poate vedea vizual in imaginea de mai jos.

ViewportSpace viewport_space = { 0, 0, 1280, 720 };
LogicSpace logic_space = { 1, 1, 3, 2 };

Lantul de transformari necesar acestui proces este:

$$ \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & V_{x}\\ 0 & 1 & V_{y}\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} V_{w}/L_{w} & 0 & 0\\ 0 & V_{h}/L_{h} & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & -L_x\\ 0 & 1 & -L_y\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

Utilizati tastele sus, jos, stanga si dreapta pentru a controla interactiv pozitia coltului din stanga-jos a spatiului logic.

Cerințe laborator

  1. 0.1p - Completați fisierul transform2D.h cu cele 4 transformari descrise mai sus:
  2. 0.05p - Aplicati transformarile necesare pentru a modifica linia de patrate din partea de sus, conform rezultatului din imaginea de mai jos. Consultati comentariile din cod pentru a primi mai multe detalii despre fiecare transformare.
  3. 0.1p - Aplicati transformarile necesare pentru a modifica linia de patrate din partea de jos, conform rezultatului din imaginea de mai jos. Consultati comentariile din cod pentru a primi mai multe detalii despre fiecare transformare.
    Pana in acest punct, rezultatul pe care ar trebui să îl obțineti este următorul:
  4. 0.05p - Impartiti ecranul cadranul in 4 cadrane si desenati formele geometrice de mai sus de 4 ori, cate o data in fiecare cadran. Modificati spatiul portii de vizualizare, pozitia coltului din stanga jos, respectiv, latimea si inaltimea.

Rezultatul final ar trebui sa fie urmatorul:

Bonus: Realizati razele unei stele prin desenarea multipla a unui triunghi rotit. Este necesar sa construiti o noua geometrie pentru triunghiul ce reprezinta o raza. Un exemplu vizual ar putea fi:

  • Aveti in vedere ca, pentru simplitate, triunghiul ce reprezinta raza, poate fi creat direct cu proprietatea de a fi isoscel :) .
  • Razele se pot suprapune intre ele.

ppbg/laboratoare/02.1697695617.txt.gz · Last modified: 2023/10/19 09:06 by andrei.lambru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0