Laboratorul 1

Marching cubes

Algoritmul marching cubes extrage din volum o suprafață 3D formată din triunghiuri.

Figura 1

Concepte teoretice

Voxel

  • reprezentarea geometrică spațială a unei date volumetrice
  • un cub cu vârfuri care au asociate valori scalare

Izosuprafața - suprafața care are aceeași valoare scalară (izovaloare) în toate punctele sale

Izovaloarea - o valoare care are o anumită semnificație în funcție de domeniu. Exemple:

  • densitate (medicină)
  • presiune (dinamica fluidelor)
  • temperatură (meteorologie)

Un vârf al unui voxel poate fi

  • exterior izosuprafeței (valoarea < izovaloarea)
  • interior izosuprafeței (valoarea > izovaloarea)
  • pe izosuprafață (valoarea = izovaloarea)

Figura 2

Exista 15 configurații posibile ale vârfurilor unui voxel față de suprafață Pentru codificarea configurațiilor: 2 tabele de căutare

  • tabela de laturi: laturile care sunt intersectate de izosuprafață pentru o combinație de vârfuri
  • tabela de triunghiuri: modul în care trebuie conectate punctele de intersecție

Tabelele - adresate de un indice pe 8 biți:

  • $b_i=1$ dacă $v_i$ e interior izosuprafeței
  • $b_i=0$ dacă $v_i$ e exterior izosuprafeței

Calculul coordonatelor punctelor de intersecție

  • interpolare liniară între extremitățile laturii intersectate, folosind valorile vârfurilor $V_1$ și $V_2$ și izolvaloarea $izoval$
  • similar pentru calculul normalei

Figura 3

Calculul normalei intr-un vârf al unui voxel

  • suprafețele voxelilor nu aparțin unor suprafețe reale
  • în locul normalelor la fețe sau la vârfurile voxelilor se folosește gradientul câmpului scalar (variația câmpului scalar în punctele de eșantionare)
  • gradientul se poate aproxima discret, prin diferențe finite (centrate)

Figura 4

Implementare

Framework-ul de laborator se poate descărca de aici sau de pe Moodle.

Atribute

  unsigned int xsize, ysize, zsize; // dimensiunile volumului de date
  unsigned char *volumeData; //tablou care conține valorile scalare din volum
  double isolevel;  //izovaloarea izosuprafeței
  TRIANGLE *tri;  //tabloul în care se stochează suprafața triunghiulară  

Metode

Încărcare date din fișier

 bool loadRAWFile(const string& fileLocation, unsigned int xsize, unsigned int ysize, unsigned int zsize); 

Această funcție este deja completată. Se încarcă în volumeData datele dintr-un fișier .raw. Fișierele .raw se găsesc în \assets\volumes\ iar informațiile despre dimensiunea fiecărui volum, în \assets\volumes\readme.txt

Reconstrucție suprafață

 void reconstructSurface(Mesh *mesh) 

Această funcție este completată parțial. Aici se completează informațiile pentru voxelul curent GRIDCELL grid;:

  • grid.p[] conțin pozițiile vârfurilor voxelului: de exemplu, pentru iteratorii x, y, z prin volum,
grid.p[0]=glm::vec3(x,y,z)
grid.p[1]=glm::vec3(x+1,y,z)
//A se vedea ordinea vârfurilor în LookupTables.h  !!!
  • grid.val[] conțin valorile scalare ale voxelului curent: de exemplu,
 grid.val[0] = volumeData[z * xsize * ysize + y * xsize + x];
 grid.val[1] = volumeData[z * xsize * ysize + y * xsize + (x+1)];
  • grid.n[] conțin normalele vârfurilor voxelului curent (calculate conform Fig. 4): de exemplu,
 grid.n[0] = glm::vec3(volumeData[z * xsize * ysize + y * xsize + (x+1)] - volumeData[z * xsize * ysize + y * xsize + (x-1)],volumeData[z * xsize * ysize + (y+1) * xsize + x] - volumeData[z * xsize * ysize + (y-1) * xsize + x],volumeData[(z+1) * xsize * ysize + y * xsize + x] - volumeData[(z-1) * xsize * ysize + y * xsize + x]);
 grid.n[1] = glm::vec3(volumeData[z * xsize * ysize + y * xsize + (x+2)] - volumeData[z * xsize * ysize + y * xsize + x],volumeData[z * xsize * ysize + (y+1) * xsize + (x+1)] - volumeData[z * xsize * ysize + (y-1) * xsize + (x+1)],volumeData[(z+1) * xsize * ysize + y * xsize + (x+1)] - volumeData[(z-1) * xsize * ysize + y * xsize + (x+1)]);
//Atentie sa nu ieșiti din volum  !!!

Calcul intersecție dintre un voxel și suprafață

 int PolygoniseCube(GRIDCELL g, double iso, TRIANGLE *tri); 

Această funcție este completată parțial. Ea

  • determină configurația voxelului relativ la suprafață: indicele cubeindex din tabela de muchii (din LookupTables) care identifică muchiile din voxel care sunt intersectate de suprafață.
  • calculează (prin interpolare) vârfurile unde suprafața intersectează voxelul
  • creează suprafața triunghiulară rezultată, pe baza tabelei de triunghiuri (din LookupTables).

Interpolare liniară

glm::vec3 VertexInterp(double isolevel, glm::vec3 p1, glm::vec3 p2, double valp1, double valp2); 

Această funcție este deja completată. Se întoarce poziția punctului de intersecție de pe muchia dintre p1 și p2, în funcție de izovaloare (isolevel) și de valorile punctelor p1 și p2.

Cerinte laborator

  1. Să se completeze pozitiile și valorile scalare ale vârfurilor voxelilor din volum, grid.p[] și grid.val[]. Dacă se completează corect, pe ecran va apărea suprafața triunghiulară (cu normale per triunghi)
  2. Să se modifice izovaloarea la apăsarea unor taste (în onInputUpdate()). La modificarea izovalorii, trebuie reapelată funcția reconstructSurface()
  3. Să se calculeze normalele vârfurilor voxelilor din volum, grid.n[] prin diferențe finite (și apoi să se normalizeze)
  4. Să se completeze normallist[] - tabloul cu normalele asociate punctelor de intersecție de pe muchiile voxelului curent (calculate prin interpolare între normalele din vârfurile voxelului)
  5. Să se determine normalele normal1, normal2 și normal3 asociate triunghiului curent care rezultă în urma intersecției dintre izosuprafață și voxel. Să se înlocuiască normala per triunghi cu normalele per vârfurile triunghiului. Dacă se completează corect, pe ecran va apărea suprafața triunghiulară netedă

Demo

vdvac/lab1.txt · Last modified: 2024/03/07 08:52 by anca.morar
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