This is an old revision of the document!


Temă - Asteroid Hills

  • Lansare: 10 decembrie 2024
  • Termen de predare: Înainte de momentul prezentării
  • Termen de prezentare: Ultima dată de prezentare anunțată, nu mai târziu de ultima zi din semestru
  • Regulament: Regulament temă
  • Notă: Orice informație ce nu a fost acoperită în acest document este la latitudinea voastră!

În cadrul acestei teme, veți realiza un joc în care utilizatorul controlează un elicopter ce se deplasează pe suprafața unui asteroid deluros. Misiunea jucătorului este să culeagă mai multe mostre dintr-o resursă specială ce se găsește pe acest asteroid, resursă ce are forma unui copăcel. Controlul jocului se realizează în totalitate prin apăsarea butonului dreapta de la mouse. Acest buton este utilizat pentru selecția poziției de destinație pentru deplasarea elicopterului și pentru selecția 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.

Deformarea terenului și curbura sunt doar efecte vizuale. Toate calculele de control prin deplasare și orientare ale elicopterului, împreună cu calculele de poziționare a obiectelor în lume se realizează într-un spațiu ce este în totalitate în 2 dimensiuni.

Detalii de implementare

Construcție și desenare suprață asteroid

Procesul de desenare a suprafeței asteroidului se realizează în mai mulți pași:

Primul pas necesită realizarea unei geometrii suport ce are forma unui plan. Această geometrie este creată dintr-o rețea poligonală ce conține cel puțin 10.000 de vârfuri. Un exemplu pentru această geometrie se găsește în următoarea imagine.

Geometria suport se realizează pe CPU și se trimite la desenare pentru a se deforma conform următorilor pași.

În ce de-al doilea pas, se realizează deformarea geometriei suport conform unei hărți de înălțimi, similar precum în laboratorul 8. Rezultatul acestei operații se poate observa în imaginea de mai jos.

Suprafața deformată la pasul anterior se colorează prin eșantionarea a două texturi, pe baza inălțimii suprafeței, similar precum în bonusul din laboratorul 8. Rezultatul se poate vedea în următoarea imagine.

Ultimul pas este descris în secțiunea următoare și reprezintă deformarea suprafeței pentru a se obține o curbură. Acest rezultat se poate observa în imaginea de mai jos.

Curbură geometrie

Pentru a crea efectul vizual de curbură a geometriei, se utilizează o abordare simplă ce oferă rezultate satisfăcătoare :).

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 :) .

Efectul de curbură se realizează prin modificarea componentei y a coordonatelor pentru toate vârfurile din care este realizată suprafața 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 $$

  • $Pozitie_v$ - poziția în spațiul lumii a vârfului procesat de vertex shader
  • $Pozitie_{elicopter}$ - poziția în spațiul lumii a elicopterului controlat de jucător
  • $Pozitie_{v_y}$ - componenta y a poziției vârfului
  • $factorCurbura$ - un factor ce controlează curbura geometriei

Factorul de curbură este proporțional cu dimensiunea obiectelor din lume. Pentru demo-ul de mai sus, este utilizat un factor de 0.02.

Plasare obiecte pe suprafața asteroidului

Pentru plasarea unui obiect pe suprafața asteroidului, trebuie să fie aplicate obiectului următoarele transformări:

  1. Translația coordonatei vârfurilor cu deplasamentul dat de deformarea suprafaței în punctul de pe suprafață pe care se află obiectul ce trebuie plasat pe asteroid. Pentru acest pas, trebuie eșantionată harta de înălțime în punctul corect. Vedeți notița de mai jos.
  2. Translația coordonatei vârfurilor cu deplasamentul dat de curbarea suprafeței în punctul de pe suprafață pe care se află obiectul ce trebuie plasat pe asteroid.

Pentru prima transformare, NU utilizați coordonatele de textură ale obiectului pe care doriți să îl plasați pe suprafață pentru eșantionarea hărții de înălțime. Puteți utiliza coordonata obiectului în spatiul lumii pentru calcularea coordonatei de textură în care să eșantionați harta de înălțime.

Pentru realizarea transformărilor de mai sus, există două opțiuni:

  1. Eșantionarea hărții de înălțime și calcularea curburii pe baza coordonatei în spațiul lumii a vârfului. În această situație, obiectul este deformat similar cu suprafața pe care se află. Această opțiune trebuie să fie utilizată pentru desenarea tuturor obiectelor din scenă, cu excepția elicopterului.
  2. Eșantionarea hărții de înălțime și calcularea curburii pe baza coordonatei în spațiul lumii a unei poziții comune pentru toate vârfurile unui obiect. Această abordare plasează corect obiectul la suprafața asteroidului doar în situația în care deformarea suprafeței asteroidului pe baza curburii se realizează față de obiectul plasat pe teren. În această situație, obiectul își păstrează forma înițială. Opțiunea aceasta trebuie să fie utilizată doar pentru desenarea elicopterului.

Construcție geometrie elicopter

Geometria elicopterului poate fi vizualizată în animația de mai jos.

Geometria elicopterului este compusă din două cuburi redimensionate neuniform pentru a defini cabina și coada elicopterului, împreună cu alte patru cuburi, de asemenea redimensionate neuniform, pentru a reprezenta cele două elice. Geometria cabinei și a cozii este desenată cu o culoare diferită față de cea a elicelor.

După cum se poate vedea și în imaginea de mai sus, cele două elice au o animație continuă de rotație.

Pentru a nu se deforma geometria elicopterului și în plus, pentru a nu suferi o animație continuă de deformare de-a lungul deplasării, în procesul de desenare, se utilizează opțiunea 2 de plasare pe suprafața asteroidului, descrisă mai sus.

Construcție și animație marcaj destinație elicopter

Geometria marcajului destinație pentru elicopter poate fi vizualizată în imaginea de mai jos.

Paralelipipedul din partea superioară este obținut prin redimensionarea neuniformă a unui cub. Acesta are o animație continuă de oscilație în direcția sus-jos.

În partea de jos a marcajului, se află un disc de cerc ce se află puțin de-asupra terenului.

Pentru a se deforma geometria marcajului cu scopul de a lua forma zonei de teren pe care se află, în procesul de desenare, se utilizează opțiunea 1 de plasare pe suprafața asteroidului, descrisă mai sus.

Construcție și desenare geometrie copac

Construcție geometrie copac

Geometria copacului se realizează prin desenarea unei ierarhii de paralelipipede cu mai multe niveluri, unde la fiecare nivel, se desenează un paralelipiped redimensionat uniform, rotit și translatat în capătul paralelipipedului de la nivelul anterior. Pentru a finaliza desenarea, se aplică la final toate transformările utilizate în desenarea paralelipipedului de la nivelul anterior. Rezultatul se poate vedea în imaginea de mai jos.

La fiecare nivel al ierarhiei de paralelipipede, se desenează 3 ramuri de ierarhie, fiecare rotită la 120 de grade față de axa OY, una față de cealaltă. Pentru copacul din imagine, s-au utilizat 6 niveluri ale ierarhiei de paralelipipede.

Este recomandat să nu utilizați redimensionări neuniforme în procesul de construcție a geometriei copacului. Creați din start geometria unui paralelipiped.

Desenare geometrie copac

Pentru colorarea copacului, se utilizează procesul de mapare cilindrică. Se folosesc două texturi, una pentru trunchiul copacului și una pentru frunzișul coroanei. Pentru a calcula coordonatele de textura în vârfurile geometriei ce descrie copacul, se utilizează procesul de mapare cilindrică ce are următoarele formule:

$$ u = \frac{1}{2\pi}arctan(z/x) \\ v = \frac{y}{treeHeight} $$

unde u și v sunt componentele x și y ale coordonatei de textură, (x, y, z) reprezintă componentele coordonatei vârfului în spațiul lumii și treeHeight reprezintă înălțimea copacului în spațiul lumii.

Suplimentar, pentru îmbunătățirea calității vizuale, desenarea se realizează după cum urmează:

  1. Paralelipipedele din primele 4 niveluri ale ierarhiei sunt desenate prin aplicarea texturii de trunchi de copac;
  2. Paralelipipedele de pe nivelul 5 al ierarhiei sunt desenate prin combinarea culorii din texturile de copac și de frunziș al coroanei;
  3. Paralelipipedele de pe nivelul 6, respectiv ultimul nivel al ierarhiei, sunt desenate prin aplicarea texturii de frunziș al coroanei.

Aveți libertate să utilizați orice texturi doriți voi, împreună cu modificarea numărului de niveluri, comportamentului de împrăștiere a ramurilor pe un nivel, numărul de ramuri pe un nivel și regula de colorare prezentată mai sus, atâta timp cât texturile alese de voi și modificările realizate urmăresc scopul de simulare a suprafeței componentelor unui copac și au un rezultat vizual similar.

Rezultatul poate fi vizualizat în imaginea de mai jos.

Pentru o deformare suplimentară a geometriei copacului, în procesul de desenare a ierarhiei de paralelipipede, se utilizează opțiunea 1 de plasare pe suprafața asteroidului, descrisă mai sus.

Procesul de selecție

Pentru a realiza procesul de selecție, se desenează toată scena într-un obiect de tip framebuffer creat de voi. Acest framebuffer conține 2 texturi de culoare:

  1. O textură de culoare în care se salvează culoarea propriu-zisă a obiectelor;
  2. O textură de culoare în care se salvează informație suplimentară pentru fiecare obiect în parte.

Pentru cea de-a doua textură de culoare din obiectul de tip framebuffer creat de voi, utilizați informație de tip RGBA32F și tipul de dată float.

Pentru a afișa informația din prima textură de culoare pe ecranul fereastrei date de sistemul de operare, trebuie copiat conținutul primei texturi de culoare din obiectul de tip framebuffer creat de voi în textura de culoare a obiectului de tip framebuffer implicit, ce aparține ferestrei. Pentru acest proces, puteți utiliza următorul cod:

// custom_framebuffer_object reprezinta identificatorul obiectului de tip framebuffer creat de voi
glBindFramebuffer (GL_READ_FRAMEBUFFER, custom_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.

Selectie destinatie

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:

// x si y reprezinta pozitia mouse-ului pe ecran, in pixeli.
float data [4];
 
y = window->props.resolution.y - y;
 
// custom_framebuffer_object reprezinta identificatorul obiectului de tip framebuffer creat de voi
glBindFramebuffer (GL_FRAMEBUFFER, framebuffer_object);
glReadBuffer (GL_COLOR_ATTACHMENT1);
 
glReadPixels (x, y, 1, 1, GL_RGBA, GL_FLOAT, data);

Selectie obiect

Pentru a realiza procesul de selectie a unui obiect, se pastreaza suplimentar in canalul A din cea de-a doua textura de culoare a obiectului de tip framebuffer creat de voi un identificator pentru toate obiectele din scena. O prezentare vizuala a acestor identificatori, sub forma de nuante de gri, se poate vedea in imaginea de mai jos.

Nuantele de gri din cea de-a doua textura de culoare din imaginea de mai sus au scop de prezentare pentru a se putea vizualiza identificatorul sub forma unei culori. Datorita faptului ca cea de-a doua textura de culoare contine informatie de tip RGBA32F, aceasta permite pastrarea unor valori ce depasesc valoarea 1.

Control elicopter

Elicopterul se deplaseaza spre locatia de destinatie in momentul in care utilizatorul alege o astfel de destinatie prin apasarea butonului dreapta de la mouse. La momentul alegerii destinatiei, se plaseaza pe suprafata obiectul de marcaj prezentat mai sus si acesta ramane la pozitia respectiva pana la momentul in care elicopterul ajunge la destinatie. In momentul in care elicopterul se opreste, obiectul de marcaj al destinatiei dispare.

Atasat de elicopter se afla o camera observator ce urmareste elicopterul. Suplimentar, in momentul deplasarii elicopterului, acesta este orientat cu fata spre directia de deplasare.

Comportament cameră observator

Î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))
);

Orientare elicopter

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}) $$

Recomandarea este să utilizați atan2() pentru calcularea arctangentei.

Barem

Funcționalități obligatorii (3 puncte)

  • Asteroidul (0.8p total)
    • Constructie si desenare geometrie suport - 0.3p
      • NU este permisa utilizarea modelului plane50.obj. Geometria suport trebuie generata din cod si trebuie sa aiba cel putin 10000 de varfuri.
    • Desenare teren cu deformare pe baza hartii de inaltime + multitexturare + curbura - 0.5p
      • Aceasta cerinta NU se puncteaza partial. Trebuie realizate toate elementele specificate in cerinta.
  • Selectie + marcare selectie cu marcajul din demo + animatie marcaj - 0.5p
    • Aceasta cerinta NU se puncteaza partial. Trebuie realizate toate elementele specificate in cerinta.
  • Elicopterul (1p total)
    • Constructie si desenare geometrie elicopter - 0.2p
    • Animatie cele 2 elice - 0.2p
    • Camera ce urmareste elicopterul - 0.2p
    • Control prin selectie (0.4p total)
      • Deplasare elicopter - 0.2p
      • Orientare elicopter pe baza directiei de deplasare - 0.2p
    • Depunctare: Lipsa plasare elicopter pe suprafata asteroidului - -0.2p
  • Copacul (0.7p total)
    • Constructie si desenare geometrie copac (0.6p total)
      • Constructie geometrie - 0.45p
      • Aplicare textura cu mapare cilindrica - 0.15p
    • Disparitie copac prin selectie - 0.1p
    • Depunctare: Lipsa plasare copac pe suprafata asteroidului - -0.2p

Exemple de funcționalități bonus

Orice funcționalitate suplimentară implementată (care nu este inclusă în cerințele obligatorii) poate fi considerată pentru acordarea unui punctaj bonus dacă este suficient de complexă.

  • Geometrie mai complexă față de cea din cerința de bază pentru elementele vizuale din joc
  • Orice aduce îmbunătățiri vizuale jocului
ppbg/tema/2024.1733850467.txt.gz · Last modified: 2024/12/10 19:07 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