Laboratorul 01

Bun venit la prima activitate practică a acestei materii! În fiecare săptămână, până la finalul semestrului, vom folosi un framework adaptat special pentru aceste activități practice. Framwork-ul este scris în limbajul C++ și folosește API-ul grafic OpenGL. Primul pas al acestui laborator este să realizați setup-ul framework-ului .

Elemene de geometrie

Vectorul

Vectorul reprezintă un instrument matematic ce descrie deplasamentul unui punct de la o poziție inițială la o poziție finală.

Un astfel de exemplu se poate vedea în imaginea de mai jos, unde vectorul $\vec{V_{12}}$ descrie deplasamentul de la poziția la care se află punctul $P_1$ , la poziția la care se află punctul $P_2$ . Se poate observa faptul că simbolul grafic ce descrie un element de tip vector reprezintă numele elementului, acompaniat de o sageată ce este poziționată deasupra lui.

Termenul de vector provine din limba latină și se traduce în limba română prin “transportator”. Interpretarea aceasta are aplicabilități în domeniul medical, unde se utilizează structura “vector de propagare”. Vizual, aplicarea conceptului de vector în domeniul matematic se poate asocia cu procesul de “transportare” a unui element de la o poziție la o altă poziție într-un spațiu.

Un vector are asociate următoarele 2 proprietăți:

  • Magnitudine, respectiv lungimea distanței vectorului;
  • Direcție; acest concept se va elabora în laboratorul 3.

Un vector se definește printr-o mulțime ordonată de $n$ elemente, pe baza numărului de dimensiuni ale spațiului în care este construit. Pentru vectorul din imaginea de mai sus, descrierea este în felul următor:

$$ \vec{V_{12}} = \begin{bmatrix} 4 & 3 \end{bmatrix} $$

Analog, pentru un vector în spațiul $\mathbb{R}^3$ , el poate fi definit după cum urmează:

$$ \vec{V_{\mathbb{R}^3}} = \begin{bmatrix} 4 & 3 & 1 \end{bmatrix} $$

În situația în care considerăm conceptul de vector în alt context decât cel de descriere a unui deplasament între două puncte, el se descrie vizual printr-o sageată trasată din originea axelor de coordonate, la poziția definită de mulțimea ordonată de $n$ elemente. Pentru această reprezentare vizuală, considerăm faptul că plasăm coada săgeții în originea axelor și capul în poziția descrisă de mulțimea ordonată. Pentru vectorul de mai sus, reprezentarea vizuală este descrisă în imaginea de mai jos.

Toată discuția din acest laborator, împreună cu imaginile demonstrative și aplicațiile, se rezumă la utilizarea conceptului de vector în spațiul $\mathbb{R}^2$. Cu toate acestea, este important de menționat faptul că toate conceptele prezentate sunt valabile și pentru spațiul $\mathbb{R}^3$ și pentru orice alt spațiu $\mathbb{R}^n$. Diferența dintre utilizarea unui vector în spațiul $\mathbb{R}^2$ față de un spațiu $\mathbb{R}^n$ este dată de faptul că formula comună pentru primele 2 componente ale unui vector din spațiul $\mathbb{R}^2$ se aplică pentru restul de n-2 ale spațiului $\mathbb{R}^n$.

Definirea prin diferența a 2 puncte

Un punct reprezintă un instrument matematic ce este definit doar printr-o poziție. Vizual, putem considera că este o formă geometrică descrisă doar printr-o poziție, ce are dimensiunea 0. În practică, punctul este utilizat pentru a descrie poziții în spațiu.

Situația face că un punct se definește la fel precum un vector, printr-o mulțime ordonată de $n$ elemente, pe baza numărului de dimensiuni ale spațiului în care este descris punctul. Este important de considerat în momentul în care se lucrează cu puncte și vectori care este interpretarea fiecărui element. Altfel spus, este important să știm ce element este punct și ce element este vector. În toate formulele din acest laborator, se poate observa că vectorii sunt marcați corespunzător prin simbolul matematic specific.

$$ \vec{V_{12}} = P_2-P_1 = \begin{bmatrix} x_{P_2} - x_{P_1} & y_{P_2}-y_{P_1} \end{bmatrix} $$

Analog, vectorul în direcție opusă, vizibil în imaginea de mai jos, se obține după următoarea formulă:

$$ \vec{V_{21}} = P_1-P_2 = \begin{bmatrix} x_{P_1} - x_{P_2} & y_{P_1}-y_{P_2} \end{bmatrix} $$

În situația în care doriți să obțineți vectorul de deplasare de la punctul $P_1$ la punctul $P_2$ , în direcția spre $P_2$ , se calculează vectorul de diferență $\vec{V_{12}}=P_2-P_1$ . Cu alte cuvinte, punctul spre care doriți să obțineți vectorul rezultant este cel din care scădeți punctul de la care pleacă vectorul.

Adunarea unui punct cu un vector

Analog operației descrise mai sus, putem considera operația inversă, în care adunăm un punct cu un vector. Rezultatul se poate observa în imaginea de mai jos și se poate descrie cu următoarea formulă:

$$ P_{res} = P + \vec{V} = (x_{P}+x_{\vec{V}}, y_{P}+y_{\vec{V}}) $$

Se poate observa și din formulă faptul că în urma adunării unui punct cu un vector, se obține un punct. Este important de menționat faptul că interpretarea ce oferă cele mai multe aplicabilități este cea în care rezultatul este un punct. Schimbarea interpretării rezultatului descrie procesul de compunere a 2 vectori, prezentat mai jos, dar această schimbare nu este consistentă matematic, deoarece interpretarea unuia dintre elementele adunării este un punct.

O observație importantă este faptul că operația de adunare a unui punct cu un vector este comutativă. Prin interschimbarea interpretării celor două elemente din adunare, se obține un punct cu aceleași coordonate.

Compunerea a 2 vectori

Procesul de compunere a 2 vectori produce un alt vector, conform formulei de mai jos:

$$ \vec{V_{res}} = \vec{V_1} + \vec{V_2} = \begin{bmatrix} x_{\vec{V_1}} + x_{\vec{V_2}} & y_{\vec{V_1}}+y_{\vec{V_2}} \end{bmatrix} $$

Procesul de compunere a 2 vectori se poate reprezenta grafic prin plasarea celui de-al doilea vector în continuarea primului. Mai exact, se poate plasa coada săgeții celui de-al doilea vector în capătul sageții primului vector. Dupa acest pas, săgeata obținută prin trasarea ei de la coada primului vector la capătul celui de-al doilea este reprezentarea vizuală a vectorului rezultant. Acesta din urmă se află pe direcția bisectoarei unghiului dintre cei doi vectori. Procesul descris se poate observa în imaginea de mai jos.

Procesul de compunere de vectori are aplicabilitate în geometrie prin faptul că descrie o operație cu care se pot prelucra direcții. Un exemplu de aplicabilitate este compunerea unei direcții de deplasare a unui obiect cu o alta dată de direcția de accelerație a obiectului, ce este diferită de cea de deplasare. Prin procesul de compunere a celor două directii, se obține direcția de deplasare la cadrul curent.

Vectorul unitate

Un vector unitate este un vector ce are lungimea 1.

Un astfel de vector are aplicabilități în programarea jocurilor video pentru realizarea animațiilor continue și în grafica pe calculator pentru simularea efectului de iluminare. Majoritatea situațiilor de utilizare necesită obținerea unui vector unitate $\vec{V_u}$ , ce are aceeași direcție cu un alt vector $\vec{V}$ dat. Pentru a obține acest vector $\vec{V_u}$ , se poate folosi formula de mai jos:

$$ \vec{V_u} = \frac{\vec{V}}{\lVert \vec{V} \rVert} = \begin{bmatrix} \frac{x_{\vec{V}}}{\lVert \vec{V} \rVert} & \frac{y_{\vec{V}}}{\lVert \vec{V} \rVert} \end{bmatrix} $$

unde $\lVert \vec{V} \rVert$ este norma sau lungimea vectorului $\vec{V}$ , ce se calculează după următoarea formulă:

$$ \lVert \vec{V} \rVert = \sqrt{{x_{\vec{V}}}^2+{y_{\vec{V}}}^2} $$

Obținerea vectorului $\vec{V_u}$ poartă denumirea de normalizare a vectorului $\vec{V}$ , deoarece se împarte fiecare componentă la norma lui :) .

Produsul scalar a doi vectori

Această operație produce la finalul ei un scalar. Definiția algebrică a acestui produs este următoarea:

$$ \vec{V_1}\cdot\vec{V_2} = x_{\vec{V_1}}x_{\vec{V_2}} + y_{\vec{V_1}}y_{\vec{V_2}} $$

O interpretare importantă a produsului scalar este în context geometric. Formula de mai sus este echivalentă cu următoarea:

$$ \vec{V_1}\cdot\vec{V_2} = \lVert \vec{V_1} \rVert \lVert \vec{V_2} \rVert \cos{\theta} $$

unde $\theta$ este unghiul dintre cei doi vectori, conform imaginii de mai jos.

Este important de observat faptul că în urma construcției a doi vectori, se pot forma 2 unghiuri între cei doi:

  • $\theta_1<=180^\circ$ ;
  • $\theta_2=360^\circ-\theta_1>=180^\circ$ .

Datorită construcției funcției trigonometrice cosinus, $\cos\theta_1=\cos\theta_2$ .

Pentru bibliografie suplimentară în legatură cu conceptul de vector, aplicat explicit în contextul graficii pe calculator, puteți accesa următorul articol:

  • Goldman, Ronald. (2002). On the algebraic and geometric foundations of computer graphics. ACM Trans. Graph.. 21. 52-86. 10.1145/504789.504792.

Triunghiul

Triunghiul este un poligon cu 3 colțuri și 3 laturi.

Aria unui triunghi oarecare

Pentru calcularea ariei unui triunghi oarecare, se poate folosi formula lui Heron, ce utilizează semiperimetrul triunghiului:

$$ A_{\Delta P_1 P_2 P_3} = \sqrt{s \cdot (s-a) \cdot (s-b) \cdot (s-c)} \\ s = \frac{1}{2} \cdot (a+b+c) \\ a=\lVert P_1-P_2 \rVert \\ b=\lVert P_1-P_3 \rVert \\ c=\lVert P_2-P_3 \rVert \\ $$

unde $P_1$ , $P_2$ si $P_3$ sunt punctele de la colțurile triunghiului, conform imaginii de mai jos:

Punct în interiorul unui triunghi

Pentru a verifica dacă un punct se află în interiorul unui triunghi, se pot folosi ariile triunghiului și cele ale triunghiurilor formate de punct cu perechi de vârfuri din triunghi. În imaginea de mai jos se pot vedea aceste suprafețe.

Astfel, în situația în care suma ariilor triunghiurilor interioare este egală cu aria triunghiului, punctul se află în interior.

$$ A_{\Delta P_1 P_2 P_3} = A_{\Delta P P_1 P_3} + A_{\Delta P P_1 P_2} + A_{\Delta P P_2 P_3} $$

unde $P$ este punctul pentru care se verifica faptul că se află în triunghi. Un exemplu de configurație pentru $P$ se poate vedea în imaginea de mai jos.

Laborator

Biblioteca glm

În framework-ul de laborator, se utilizează biblioteca glm , ce pune la dispoziție structuri de date pentru puncte și vectori, împreună cu operațiile uzuale de lucru cu aceste elemente.

Definirea unui obiect de tip vector în spațiul $\mathbb{R}^2$ se realizează după cum urmează:

glm::vec2 v = glm::vec2(4.0f, 3.0f);

Accesarea componentelor individuale ale unui vector se realizează:

float x = v.x;
float y = v.y;

Obținerea unui vector prin diferența a două puncte:

glm::vec2 p1 = glm::vec2(2, 2);
glm::vec2 p2 = glm::vec2(6, 5);
 
glm::vec2 v12 = p2 - p1;

Compunerea a 2 vectori:

glm::vec2 v1 = glm::vec2(3.0f, 1.0f);
glm::vec2 v2 = glm::vec2(2.0f, 3.0f);
 
glm::vec2 v_res = v1 + v2;

Obținerea magnitudinii unui vector:

glm::vec2 v = glm::vec2(4.0f, 3.0f);
 
float norm = glm::length(v);

Obținerea unui vector unitate pe direcția unui alt vector dat:

glm::vec2 v = glm::vec2(4.0f, 3.0f);
 
glm::vec2 vu = glm::normalize(v);

Produsul scalar a doi vectori:

glm::vec2 v1 = glm::vec2(2, 2);
glm::vec2 v2 = glm::vec2(6, 5);
 
float res = glm::dot(v1, v2);

Descrierea culorilor

Conceptul de culoare este unul complex, care ar putea necesita conținutul unui curs în sine. În domeniul graficii pe calculator, se utilizează modele matematice, denumite modele de culoare pentru a prelucra o astfel de informație. În practică, API-urile grafice, precum și API-ul OpenGL, pe care îl utilizăm în cadrul framework-ului, utilizează modelul de culoare RGB, la care ne vom rezuma și noi până la finalul semestrului.

Modelul de culoare RGB descrie culorile prin descompunerea lor în 3 culori primare, respectiv: roșu, verde și albastru. Acronimul “RGB” provine de la numele lor în limba engleză: “Red”, “Green” și “Blue”.

În cadrul laboratorului, se poate utiliza o structură de tip glm::vec3, ce conține 3 componente, analog structurii glm::vec2, la care se mai adaugă componenta z. Se utilizează această structură de date doar pentru a stoca un triplet de valori ce este interpretat sub formă de culoare în modelul RGB. API-ul grafic OpenGL interpretează valoarea fiecărei componente a tripletului între limitele 0 și 1. Mai jos sunt descrise cateva culori de baza formate din valorile tripletelor.

glm::vec3 red_color = glm::vec3(1, 0, 0);
glm::vec3 green_color = glm::vec3(0, 1, 0);
glm::vec3 blue_color = glm::vec3(0, 0, 1);
 
glm::vec3 yellow_color = glm::vec3(1, 1, 0);
glm::vec3 cyan_color = glm::vec3(0, 1, 1);

Aprofundarea modelelor de culoare depășește conținutul acestui curs. Pentru a obține mai multe informatii despre acest subiect, puteți consulta următoarele cărți:

  • Levkowitz, Haim, ed. Color theory and modeling for computer graphics, visualization, and multimedia applications. Boston, MA: Springer US, 1997.
  • Fairchild, Mark D. Color appearance models. John Wiley & Sons, 2013.

Metode utilitare

În cadrul acestui laborator, sunt oferite metode specifice pentru desenarea mai multor tipuri de primitive grafice. Semnăturile acestor metode sunt scrise mai jos. Consultați fișierul primitives_rendering_scene.h pentru o descriere mai detaliată a fiecărui parametru al metodelor.

void RenderVector(const glm::vec2 &v, const glm::vec3 &color, const std::string& label = std::string (), const glm::vec2 &p = glm::vec2(0.0f));
void RenderPoint(const glm::vec2 &p, const glm::vec3 &color, const std::string &label = std::string());
void RenderArc(float start_angle, float angle, const glm::vec3 &color, float radius = 3.0f, const glm::vec2 &center = glm::vec2(0.0f));
void RenderTriangle(const glm::vec2 &p1, const glm::vec2 &p2, const glm::vec2 &p3, const glm::vec3 &color);
void RenderText(const glm::vec2 &p, const std::string &text, float size, const glm::vec3 &color);

Cerințe laborator

În cadrul acestui laborator, veți avea de rezolvat 6 cerințe distincte. Pentru a schimba între panourile specifice cerințelor, apăsați tastele 1, 2, 3, 4, 5 și 6 de la tastatură.

Completați fisierul lab01.cpp cu următoarele:

  1. 0.05p - Completați metoda Exercise1() astfel:
    1. Desenați vectorui rezultant în urma compunerii vectorilor $\vec{V_1}$ și $\vec{V_2}$ .
    2. Desenați vectorul $\vec{V_2}$ în continuarea lui $\vec{V_1}$ și vectorul $\vec{V_1}$ în continuarea lui $\vec{V_2}$ , conform procesului de compunere a doi vectori, descris mai sus.
      Utilizați metoda RenderVector(…) pentru desenarea unui vector. După rezolvarea acestei cerințe, ar trebui să obțineți rezultatul următor:
  2. 0.05p - Completați metoda Exercise2() pentru desenarea următorilor vectori rezultanți în urma diferenței dintre două puncte: $\{\vec{V_{21}}, \vec{V_{43}}, \vec{V_{56}}, \vec{V_{87}}\}$ .
    După rezolvarea acestei cerințe, ar trebui să obțineti rezultatul următor:
  3. 0.05p - Completati metoda Exercise3() astfel:
    1. Desenați vectorii unitate aflați pe direcția celor 5 vectori prezenți în cadrul cerinței.
    2. Nu utilizați etichete pentru desenarea vectorilor unitate.
      După rezolvare, ar trebui să obțineți rezultatul următor:
  4. 0.05p - Completați metoda Exercise4() pentru desenarea arcului de cerc dintre cei doi vectori.
    Utilizați metoda RenderArc(…) pentru desenarea arcului de cerc, împreună cu produsul scalar și acos(radians) pentru calcularea unghiului dintre cei 2 vectori. După rezolvarea acestei cerințe, ar trebui să obțineți rezultatul următor:
  5. 0.05p - Completați metoda Exercise5() pentru desenarea valorii ariei fiecăruia dintre cele 3 triunghiuri. Textul trebuie afișat la poziția centrului de greutate al fiecărui triunghi.
    Utilizați formula lui Heron pentru calcularea ariei. Folosiți metoda RenderText(…) pentru desenarea valorii ariei. După rezolvarea acestei cerințe, ar trebui să obțineți rezultatul următor:
  6. 0.05p - Completați metoda Exercise6() pentru desenarea punctelor din listă după următoarea regulă:
    1. Punctele ce se află în interiorul triunghiului se desenează în culoarea verde;
    2. Punctele ce se află în afara triunghiului se desenează în culoarea roșie.
      Deoarece ariile sunt calculate cu tipuri de date în virgulă mobilă, nu se poate folosi direct comparația de egalitate și trebuie să ne asumăm un anumit nivel de eroare în calcule. Astfel, în cod, comparația va fi în felul următor:
      const float EPSILON = 0.01f;
       
      bool inside_triangle = abs(area_v1v2v3 - (area_pv1v3 + area_pv1v2 + area_pv2v3)) < EPSILON;


      După rezolvarea acestei cerințe, ar trebui să obțineți rezultatul următor:

Bonus: În cadrul exercițiului 4, desenați cu o culoare diferită arcul de cerc pentru unghiul mare dintre cei doi vectori. După rezolvarea acestei cerințe, ar trebui să obțineți rezultatul următor:

ppbg/laboratoare/01.txt · Last modified: 2024/10/10 18:31 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