Voxel
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:
Un vârf al unui voxel poate fi
Exista 15 configurații posibile ale vârfurilor unui voxel față de suprafață Pentru codificarea configurațiilor: 2 tabele de căutare
Tabelele - adresate de un indice pe 8 biți:
Calculul coordonatelor punctelor de intersecție
Calculul normalei intr-un vârf al unui voxel
Framework-ul de laborator se poate descărca de aici sau de pe Moodle.
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ă
Î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
cubeindex
din tabela de muchii (din LookupTables
) care identifică muchiile din voxel care sunt intersectate de suprafață. 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
.
grid.p[]
și grid.val[]
. Dacă se completează corect, pe ecran va apărea suprafața triunghiulară (cu normale per triunghi) onInputUpdate()
). La modificarea izovalorii, trebuie reapelată funcția reconstructSurface()
grid.n[]
prin diferențe finite (și apoi să se normalizeze)normallist[]
- tabloul cu normalele asociate punctelor de intersecție de pe muchiile voxelului curent (calculate prin interpolare între normalele din vârfurile voxelului)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ă