This is an old revision of the document!
In aceasta tema, veti avea de realizat un joc in care jucatorul controleaza un elicopter ce se deplaseaza pe suprafata unui asteroid deluros. Misiunea jucatorului este sa culeaga mai multe mostre dintr-o resursa speciala ce se gaseste pe acest asteroid, ce are forma unui copacel. Controlul jocului este in totalitate cu butonul dreapta de la mouse. Acest buton este utilizat pentru selectia pozitiei de destinatie pentru deplasarea elicopterului si pentru selectia copacilor de pe asteroid.
Puteți viziona mai jos un filmuleț demonstrativ cu o aplicație construită pe baza framework-ului de laborator, care acoperă cerințele.
Procesul de desenare a suprafetei asteroidului se realizeaza in mai multi pasi:
Primul pas necesita realizarea unei geometrii suport sub forma unui plan creat dintr-o retea poligonala ce contine cel putin 10 000 de varfuri. Un exemplu pentru aceasta geometrie se gaseste in urmatoarea imagine:
Geometria suport se realizeaza pe CPU si se trimite la desenare pentru a se deforma conform urmatorilor pasi.
Al doilea pas realizeaza deformarea geometriei suport conform unei harti de inaltimi, similar precum in laboratorul 8. Rezultatul acestei operatii se poate observa in imaginea de mai jos:
Suprafata deformata la pasul anterior se coloreaza prin esantionarea a 2 texturi, pe baza inaltimii suprafetei, similar precum in bonusul din laboratorul 8. Rezultatul se poate vedea in urmatoarea imagine:
Ultimul pas este descris in sectiunea urmatoare si reprezinta deformarea suprafetei pentru a se obtine o curbura. Se poate observa rezultatul in imaginea de mai jos:
Rezultatul este doar un efect vizual ce curbează geometria în jurul elicopterului, astfel că acesta poate ajunge la limita geometriei lumii, altfel spus la capătul ei și să și depășească acest capăt :) .
Realizeaza curburii obiectelor din lume se realizează la pasul de desenare a obiectelor din scenă. Acest efect se creează prin modificarea componentei y a coordonatelor pentru toate vârfurile din care este realizata suprafata asteroidului. Procesul este creat în vertex shader. Componenta y a tuturor vârfurilor se modifică după cum urmează:
$$ Pozitie_{v_y} = Pozitie_{v_y} - \|{Pozitie_{elicopter}-Pozitie_v}\|^2 \cdot factorCurbura $$
Factorul de curbură este proporțional cu dimensiunea obiectelor din lume. Pentru demo-ul de mai sus, este utilizat un factor de 0.02.
Pentru plasarea unui obiect pe suprafata asteroidului trebuie sa realizam urmatoarele transformari:
Pentru realizarea transformarilor de mai sus, aveti 2 optiuni:
Geometria elicopterului poate fi vizualizata in animatia de mai jos.
Geometria elicopterului este compusa din doua cuburi redimensionate neuniform pentru a defini cabina si coada elicopterului, impreuna cu 4 cuburi, de asemenea redimensionate neuniform pentru a reprezenta cele 2 elice. Geometria cabinei si a cozii are o culoare diferita de cea a elicelor.
Dupa cum se poate vedea si in imaginea de mai sus, cele 2 elice au o animatie continua de rotatie.
Geometria marcajului destinatie pentru elicopter poate fi vizualizata in imaginea de mai jos.
Paralelipipedul din partea superioara este obtinut prin redimensionarea neuniforma a unui cub. Acesta are o animatie continua de oscilatie in directia sus-jos.
In partea de jos a marcajului, se afla un disc de cerc ce se afla putin de-asupra terenului.
Geometria copacului se realizeaza prin desenarea unei ierarhii de paralelipipede cu mai multe niveluri, unde fiecare la fiecare nivel, se deseneaza un paralelipiped redimensionat uniform, rotit si translatat in capatul paralelipipedului de la nivelul anterior. Pentru a finaliza desenarea, se aplica la final toate transformarile utilizate in desenarea paralelipipedului de la nivelul anterior. Rezultatul se poate vedea in imaginea de mai jos.
La fiecare nivel al ierarhiei de paralelipipede, se deseneaza 3 ramuri de ierarhie, fiecare rotita la 120 de grade fata de axa OY, una fata de cealalta. Pentru copacul din imagine, s-au utilizat 6 niveluri ale ierarhiei de paralelipipede.
Pentru colorarea copacului, se utilizeaza procesul de mapare cilindrica. Se folosesc 2 texturi, una pentru trunchiul copacului si una pentru frunzisul coroanei. Pentru a calcula coordonatele de textura in varfurile geometriei ce descrie copacul, se utilizeaza procesul de mapare cilindrica ce are urmatoarele formule:
$$ u = \frac{1}{2\pi}arctan(z/x) \\ v = \frac{y}{treeHeight} $$
unde u si v sunt componentele x si y ale coordonatei de textura si (x, y, z) reprezinta componentele coordonatei varfului in spatiul lumii.
Suplimentar, pentru imbunatatirea calitatii vizuale, desenarea se realizeaza dupa cum urmeaza:
Rezultatul poate fi vizualizat in imaginea de mai jos.
Pentru a realiza procesul de selectie, se deseneaza toata scena intr-un obiect de tip framebuffer creat de voi. Acest framebuffer contine 2 texturi de culoare:
RGBA32F
si tipul de data float
.
Pentru a afisa informatia din prima textura de culoare in fereastra, trebuie copiat continutul primei texturi de culoare din obiectul de tip framebuffer creat de voi in textura de culoare a obiectului de tip framebuffer implicit, ce apartine ferestrei. Pentru acest proces, puteti utiliza urmatorul cod:
glBindFramebuffer (GL_READ_FRAMEBUFFER, framebuffer_object); glReadBuffer (GL_COLOR_ATTACHMENT0); glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); glBlitFramebuffer (0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
Texturile de culoare din interiorul obiectului de tip framebuffer creat de voi trebuie sa aiba aceeasi dimensiune precum textura de culoare din interiorul obiectului de tip framebuffer implicit, ce apartine ferestrei. Acest cod trebuie utilizat la finalul cadrului.
Pentru a realiza procesul de selectie a destinatiei, in canalele de culoarea RGB, ale celei de-a doua texturi de culoare ale obiectului de tip framebuffer creat de voi, pastrati coordonata (x, 0, z) a geometriei suport, dupa pasul de deformare pe baza hartii de inaltime si inainte de deformarea pe baza curburii. Cele 2 texturi de culoare pot fi vazute in imaginea de mai jos:
Rezultatul vizual din imagine este obtinut dupa aplicarea deformarii pe baza curburii, dar coordonata (x, 0, z) pastrata in cea de-a doua textura de culoare este cea calculata inainte de realizarea curburii.
Pentru a extrage coordonata (x, 0, z) din cea de-a doua textura de culoare din obiectul de tip framebuffer creat de voi, la momentul apasarii butonului dreapta de la mouse de catre utilizator, extrageti informatia din pixelul la care se afla cursorul la momentul apasarii butonului. Codul pentru acest proces arata in felul urmator:
TODO: Descriere generala
În situația în care se utilizează framework-ul de laborator, pentru desenarea geometriei din perspectiva camerei observator, se poate utiliza obiectul de tip Camera
, după cum urmeaza:
auto camera = GetSceneCamera(); // pozitia relativa a camerei fata de pozitia personajului glm::vec3 relativeCameraPosition = ...; // playerPosition este pozitia in lume a personajului controlat de jucator camera->SetPositionAndRotation( playerPosition + relativeCameraPosition, glm::quatLookAt(-glm::normalize(relativeCameraPosition), glm::vec3(0, 1, 0)) );
Pentru a orienta geometria personajului în direcția de deplasare, se utilizează o matrice de rotație în jurul axei OY. În situația în care se cunoaște direcția de deplasare, unghiul de rotație se poate calcula după cum urmează:
$$ unghi = arctan(\frac{directie_x}{directie_z}) $$
atan2()
pentru calcularea arctangentei.
plane50.obj
. Geometria suport trebuie generata din cod si trebuie sa aiba cel putin 10000 de varfuri.