Differences

This shows you the differences between two versions of the page.

Link to this comparison view

egc:laboratoare:04 [2021/11/01 12:08]
victor.asavei [Utilizarea bibliotecii GLM]
egc:laboratoare:04 [2024/10/27 19:21] (current)
mihnea.mitrache [Transformări 3D]
Line 2: Line 2:
 **Video Laborator 4**: https://​youtu.be/​huCrfe9sbMQ\\ **Video Laborator 4**: https://​youtu.be/​huCrfe9sbMQ\\
 **Autor**: [[adix64@gmail.com | Alex Dinu]] **Autor**: [[adix64@gmail.com | Alex Dinu]]
 +===== Operații de calcul cu vectori =====
 +
 +<​hidden>​
 +----
 +
 +Aceste exemple ar trebui doar explicate la tablă ca un reminder despre lucrul cu vectori, nu există vreun exercițiu în framework pentru studenți să le și testeze.
 +</​hidden> ​  
 +
 +Până acum în laboratoare ați folosit tipul de date **glm::​vec3** pentru a reprezenta vectori de 3 dimensiuni, în mod special pentru a reprezenta poziția unui obiect în spațiu. Poate apărea însă o confuzie între termenul de **vector** și **poziție**:​ pentru că prin definiție, un vector are o **direcție** și o **magnitudine** (sau lungime).
 +
 +Niște exemple de vectori în spațiul 2D (în 3D este același principiu, dar este mai ușor de observat în 2D) arată așa:
 +
 +{{ :​egc:​laboratoare:​vectors_repr.png?​nolink&​300 |}}
 +
 +<note important>​
 +**Atenție!** Se poate observa cum vectorul V și W sunt egali, deși au o origine diferită. Asta se întâmplă deoarece ei reprezintă aceeași direcție, cu aceeași lungime.
 +
 +Prin urmare, dacă vrem să vizualizăm **vectorii ca o poziție**, putem să ne imaginăm un vector cu originea în (0, 0, 0) și apoi cu direcția către locul unde vrem să fie poziția, construind astfel un **"​vector de poziție"​** (cum este in acest exemplu, vectorul V).
 +</​note>​
 +
 +
 +=== Principalele operații cu vectori ===
 +**1. Operatii cu un scalar:**
 +
 +{{ :​egc:​laboratoare:​vectors_scalar_op.png?​nolink&​300 |}}
 +
 +Unde în loc de **+** pot fi folosiți operatorul de diferență,​ înmulțire sau împărțire.
 +
 +**2. Opusul unui vector:**
 +
 +{{ :​egc:​laboratoare:​vector_negation.png?​nolink&​300 |}}
 +
 +Calculul unui vector cu direcția inversă se poate face înmulțind vectorul cu scalarul -1.
 +
 +**3. Adunarea și scăderea vectorilor:​**
 +
 +Matematic, adunarea a doi vectori se face făcând suma pe componente, ca în exemplul de mai jos:
 +
 +{{ :​egc:​laboratoare:​vector_addition_math.png?​nolink&​400 |}}
 +
 +Vizual însă, efectul **adunării** este următorul (**regula triunghiului**):​
 +
 +{{ :​egc:​laboratoare:​vector_addition_viz.png?​nolink&​300 |}}
 +
 +În mod asemănător,​ efectul vizual al **scăderii** este următorul:
 +
 +{{ :​egc:​laboratoare:​vector_subtraction.png?​nolink&​300 |}}
 +
 +**4. Lungimea unui vector:**
 +
 +In mod normal, lungimea se calculeaza folosind teorema lui Pitagora, deci unde lungimea vectorului ar fi: $$length = sqrt(x*x + y*y);$$
 +
 +{{ :​egc:​laboratoare:​vectors_length.png?​nolink&​300 |}}
 +
 +În OpenGL, există o funcție în **GLM** pentru calculul lungimii:
 +<code cpp>
 +glm::vec3 v = glm::​vec3(2,​ 3, 5);
 +float length = glm::​length(v);​ // 6.164414
 +</​code>​
 +
 +<​note>​
 +Un alt tip special de vector poartă denumirea de **vector unitate** care are o proprietate în plus, anume faptul că are lungimea 1. Pentru a obține acest rezultat se va împărți vectorul la lungimea lui. În OpenGL, funcția această este deja implementată pentru voi:
 +<code cpp>
 +glm::vec3 v = glm::​vec3(2,​ 3, 5);
 +glm::vec3 v_norm = glm::​normalize(v);​ // (0.324443, 0.486664, 0.811107)
 +</​code>​
 +Normalizarea ajută la lucrul cu vectori, mai ales în cazuri unde ne interesează doar direcția acestora.
 +</​note>​
 +
 +**5. Produsul scalar (Dot-product):​**
 +
 +{{ :​egc:​laboratoare:​vector_dot_product_formula.png?​nolink&​300 |}}
 +
 +O aplicație foarte interesantă este atunci când vectorii sunt **unitate** (au lungime 1), deoarece produsul scalar o să fie valoarea cosinusului. Un exemplu vizual este următorul: ​
 +
 +{{ :​egc:​laboratoare:​vectors_dot_product_anim.gif?​direct&​500 |}}
 +
 +În OpenGL, există o funcție în **GLM** pentru calculul produsului scalar:
 +<code cpp>
 +glm::vec3 a = glm::​vec3(0,​ 1, 0);
 +glm::vec3 b = glm::​vec3(1,​ 0, 0);
 +float dotProd = glm::dot(a, b);
 +</​code>​
 +
 +**6. Produsul vectorial (Cross-product):​**
 +
 +Produsul vectorial este definit numit în spațiul 3D, unde primește 2 vectori (care nu sunt paraleli) ca input și produce un al treilea vector care este perpendicular pe cei 2 vectori:
 +
 +{{ :​egc:​laboratoare:​vectors_crossproduct.png?​nolink&​300 |}}
 +
 +În OpenGL, există o funcție în **GLM** pentru calculul produsului vectorial:
 +<code cpp>
 +glm::vec3 a = glm::​vec3(0,​ 1, 0);
 +glm::vec3 b = glm::​vec3(1,​ 0, 0);
 +glm::vec3 crossProd = glm::​cross(a,​ b); // (0, 0, -1)
 +</​code>​
 +
 +<​note>​
 +Pentru alte informații utile despre operațiile vectoriale puteți citi mai departe [[https://​learnopengl.com/​Getting-started/​Transformations|aici]].
 +</​note>​
 +
 ===== Transformări 3D ===== ===== Transformări 3D =====
  
-Obiectele 3D sunt definite într-un sistem ​de coordonate 3D, de exemplu XYZ+La laboratorul anterior am explorat o serie de transformări 2D. Am înțeles că este necesara utilizarea coordonatelor omogene și implicit a matricelor ​de 3x3 pentru realizarea tuturor transformărilor 2D
-În cadrul acestui ​laborator vom implementa diferite tipuri ​de transformări ce pot fi aplicate obiectelor: translațiirotații și scalări. Acestea sunt definite ​în format matricealîn coordonate omgene, așa cum ați învățat deja la cursMatricile acestor transformări sunt următoarele:+În acest laborator vom extinde conceptele la spațiul 3D. Vom lucra cu obiecte tridimensionale în sistemul ​de coordonate din OpenGL. 
 +<note tip> 
 +Acesta este un sistem de coordonate regulat dreapta. Axa x este orientată spre dreaptaaxa y este orientată în susiar axa z este orientată spre privitor. 
 +</​note>​ 
 +{{ :egc:​laboratoare:​lab4sistemcoordonate0.png?​500 |}}
  
 +Vom implementa diferite tipuri de transformări ce pot fi aplicate obiectelor: translații,​ rotații și scalări. Similar cu cazul 2D, vom utiliza coordonate omogene pentru a realiza aceste transformări. Diferența este dată de faptul că putem deplasa obiectele într-o dimensiune suplimentară,​ adică pe axa z. Astfel, vom adăuga o coloană și o linie în matricele de transformare,​ astfel încât acestea vor fi de 4x4.
 ==== Translația ==== ==== Translația ====
  
Line 29: Line 135:
 \end{bmatrix} ​ \end{bmatrix} ​
 $$ $$
 +==== Scalarea ====
 +
 +=== Scalarea față de origine ===
 +$$
 +\begin{bmatrix}
 +{x}'​\\ ​
 +{y}'\\
 +{z}'​\\ ​
 +1
 +\end{bmatrix} = \begin{bmatrix}
 +s_x & 0 & 0 &0 \\ 
 +0 & s_y & 0 &0 \\ 
 +0 & 0 & s_z &0 \\
 +0 & 0 & 0 &​1 ​
 +\end{bmatrix}
 +
 +\begin{bmatrix}
 +x\\ 
 +y\\ 
 +z\\ 
 +1
 +\end{bmatrix} ​
 +$$
 +
 +Dacă $sx = sy = sz$ atunci avem scalare uniformă, altfel avem scalare neuniformă.
 +
 +=== Scalarea față de un punct oarecare ===
 +
 +Scalarea relativă la un punct oarecare se rezolvă în cel mai simplu mod prin:
 +  - translatarea atât a punctului asupra căruia se aplică scalarea cât și a punctului față de care se face scalarea a.î. cel din urmă să fie originea sistemului de coordonate
 +  - scalarea normală (față de origine)
 +  - translatarea rezultatului a.î. punctul față de care s-a făcut scalarea să ajungă în poziția sa inițială
 +
 ==== Rotația ==== ==== Rotația ====
 +Spre deosebire de celelalte două operații de mai sus, rotația este puțin mai interesantă când trecem la 3D. Putem să rotim un obiect în jurul uneia dintre cele trei axe cât și jurul unei axe oarecare.
 +<note tip>
 +În 2D am realizat rotații față de origine sau față de un punct oarecare. Înțelegem acum că rotația aceea era în jurul axei Z, perpendiculară pe planul de lucru.
 +</​note>​
 +{{:​egc:​laboratoare:​lab4rotation2d_gif.gif}}
 +
 +Pentru rotațiile în jurul axelor de coordonate ne putem imagina că realizăm rotația prin "​înșurubarea"​ în jurul acestora.
 +
 +{{:​egc:​laboratoare:​lab4rotation3d_gif.gif|}}
  
 === Rotația față de axa OX === === Rotația față de axa OX ===
Line 112: Line 260:
  
 La curs veți învăța cum puteți realiza rotații față de axe oarecare (care nu sunt paralele cu OX, OY sau OZ). La curs veți învăța cum puteți realiza rotații față de axe oarecare (care nu sunt paralele cu OX, OY sau OZ).
-==== Scalarea ==== 
- 
-=== Scalarea față de origine === 
-$$ 
-\begin{bmatrix} 
-{x}'​\\ ​ 
-{y}'\\ 
-{z}'​\\ ​ 
-1 
-\end{bmatrix} = \begin{bmatrix} 
-s_x & 0 & 0 &0 \\  
-0 & s_y & 0 &0 \\  
-0 & 0 & s_z &0 \\ 
-0 & 0 & 0 &​1 ​ 
-\end{bmatrix} 
- 
-\begin{bmatrix} 
-x\\  
-y\\  
-z\\  
-1 
-\end{bmatrix} ​ 
-$$ 
- 
-Dacă $sx = sy = sz$ atunci avem scalare uniformă, altfel avem scalare neuniformă. 
- 
-=== Scalarea față de un punct oarecare === 
- 
-Scalarea relativă la un punct oarecare se rezolvă în cel mai simplu mod prin: 
-  - translatarea atât a punctului asupra căruia se aplică scalarea cât și a punctului față de care se face scalarea a.î. cel din urmă să fie originea sistemului de coordonate 
-  - scalarea normală (față de origine) 
-  - translatarea rezultatului a.î. punctul față de care s-a făcut scalarea să ajungă în poziția sa inițială 
  
 ===== Utilizarea bibliotecii GLM ===== ===== Utilizarea bibliotecii GLM =====
Line 190: Line 306:
 Pentru exemplul anterior, matricea de translație creată va avea ca efect translatarea cubului curent cu (1, 2, 1). Pentru efecte de animație continuă, pașii de translație ar trebui să se modifice în timp. Pentru exemplul anterior, matricea de translație creată va avea ca efect translatarea cubului curent cu (1, 2, 1). Pentru efecte de animație continuă, pașii de translație ar trebui să se modifice în timp.
 </​note>​ </​note>​
 +
 +===== Transformarea fereastră-poartă =====
 +
 +în laboratorul 3, s-a discutat despre transformarea fereastră-poartă si a fost parcursă matematica din spatele ei. în realitate, transformarea fereastră-poartă face parte din transformările fixe din banda grafică și nu este o operație care poate fi modificată de programatorul care se folosește de OpenGL.
 +
 +Modul în care se poate interacționa cu transformarea fereastră-poartă în OpenGL este funcția:
 +<code cpp>
 +glViewport(GLint x, GLint y, GLint width, GLint height)
 +</​code>​
 +
 +Această funcție specifică OpenGLului că ceea ce urmează să fie trimis către randare va trebui să apară pe ecran în coordonatele fizice: $$(x, y) – (x + width, y + height)$$
 +
 +<note important>​
 +**Atenție!** Dacă nu este șters conținutul depth bufferului după ce scena a fost desenată în primul viewport, este posibil ca al 2lea viewport să fie randat în spatele obiectelor din scenă, producându-se efecte vizuale neplăcute.
 +
 +**Depth Buffer**: Depth bufferul (sau Z bufferul) este o structură în care se menține adâncimea în scenă a fiecărui fragment din imaginea desenată.
 +</​note>​
 +
 +[[https://​registry.khronos.org/​OpenGL-Refpages/​gl4/​html/​glViewport.xhtml|glViewport]] poate fi extrem de util în diverse situații în care s-ar dori redarea mai multor puncte de vedere dintr-o scenă în același timp, ca de exemplu: oglinzi retrovizoare într-un joc cu mașini sau o hartă văzută de sus care se actualizează odată cu mișcarea jucătorului,​ cum se poate observa în animația de mai jos:
 +
 +{{ :​egc:​laboratoare:​lab4minimapdemo.gif?​nolink&​400 |}}
 +
 +
 ==== Cerințe laborator ==== ==== Cerințe laborator ====
  
   - Descărcați [[https://​github.com/​UPB-Graphics/​Framework-EGC/​archive/​master.zip|framework-ul de laborator]]   - Descărcați [[https://​github.com/​UPB-Graphics/​Framework-EGC/​archive/​master.zip|framework-ul de laborator]]
-  - Completați funcțiile de translație,​ rotație și scalare din ''/​Laborator4/Transform3D.h''​+  - Completați funcțiile de translație,​ rotație și scalare din ''/​lab4/transform3D.h''​
   - Să se realizeze animații la apăsarea tastelor (în ''​OnInputUpdate''​) pentru cele 3 cuburi, astfel:   - Să se realizeze animații la apăsarea tastelor (în ''​OnInputUpdate''​) pentru cele 3 cuburi, astfel:
     * cu tastele W, A, S, D, R, F să se deplaseze primul cub în scenă     * cu tastele W, A, S, D, R, F să se deplaseze primul cub în scenă
     * cu tastele 1 și 2 să se scaleze al doilea cub (să se mărească și să se micșoreze) față de centrul propriu     * cu tastele 1 și 2 să se scaleze al doilea cub (să se mărească și să se micșoreze) față de centrul propriu
     * cu tastele 3, 4, 5, 6, 7, 8 să se rotească al treilea cub față de axele locale OX, OY, OZ     * cu tastele 3, 4, 5, 6, 7, 8 să se rotească al treilea cub față de axele locale OX, OY, OZ
 +  - Randați toate obiectele din scenă și în viewportul mic din colț
 +  - Aplicați modificări asupra viewportului mic din colt, astfel:
 +    * I, J, K, L să deplaseze viewportul mic în ecran (sus, stânga, jos, respectiv dreapta) (în ''​OnKeyPress''​)
 +    * U, O să micșoreze, respectiv mărească viewportul mic (în ''​OnKeyPress''​)
  
 <​hidden>​ <​hidden>​
egc/laboratoare/04.1635761326.txt.gz · Last modified: 2021/11/01 12:08 by victor.asavei
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