diff --git a/vcg/complex/trimesh/create/readme.txt b/vcg/complex/trimesh/create/readme.txt new file mode 100644 index 00000000..6f86da17 --- /dev/null +++ b/vcg/complex/trimesh/create/readme.txt @@ -0,0 +1,102 @@ +MARCHING CUBES & EXTENDED MARCHING CUBES +=================================================================================== +In breve le classi coinvolte sono 3 e sono: + * MerchingCubes ed ExtendedMarchingCubes + processano una cella alla volta, aggiungendo per ogni chiamata a ProcessCell + l'insieme di triangoli approssimante la superficie che interseca la cella + * Walker + gestisce l'attraversamento del volume, servendo le chiamate effettuate dagli + algoritmi di estrazione della superficie al volume e cachandone i risultato + * Volume + conosce come calcolare il campo scalare all'interno del volume da processare + e come calcolare le intersezioni superficie/segmenti. + + +DESCRIZIONE +==================================================================================== + Le classi che implementano gli algoritmi MarchingCubes ed ExtendedMarchingCubes +sono state implementate così da risultare quanto più generiche possibile: ogni chiamata +al metodo ProcessCell(Point3i p1, Point3i p2) analizza la cella del volume individuata +dai due punti p1 e p2 e l'analisi di questa cella si conclude esattamente al ritorno da questa +chiamata: nel caso infatti la superficie da estrarre attraversi questa cella, all'interno +di questa stessa chiamata la mesh viene aggiornata con un opportuno insieme di triangoli. +L'assunzione alla base di questa astrazione è l'esistenza di altri due entità, il Walker +ed il Volume; sebbene sulla loro implementazione è lasciata la più completa libertà, è utile +precisare in quale relazione essi stiano rispetto agli algoritmi di estrazione di superfici. + +Un esempio che riassume quanto qui esposto è incluso nella libreria: vd. vcg/apps/test/extractors. + +VOLUME +==================================================================================== + Gli algoritmi di estrazione di superfici risalgono alla superficie utilizzando i valori +di un campo scalare definito sul volume da processare campionato sui vertici di una qualche +griglia. Questo campo scalare sarà generalmente diverso a seconda del tipo di applicazione. +Il Volume è appunto quella classe che racchiude il campo scalare e di cui ne conosce le proprietà. +In realtà, all'interno dell'algoritmo di estrazione di superfici, non esiste alcun collegamento +esplicito con il Volume: tutte le sue chiamate sono rivolte al Walker. Questo perché +(per motivi che saranno esposti successivamente a proposito del Walker) il Walker potrebbe già +possedere il valore del campo calcolato in un dato punto, che evita così di farselo ricalcolare +nuovamente dal Volume: Similmente, quando viene chiesto di calcolare il punto di intersezione +della superficie con un segmento, se il Walker dispone già di questa informazione, la restituisce +all'algoritmo di estrazione di superfici, altrimenti il calcolo verrà effettuato dal Volume: il +punto ottenuto verrà restituito al Walker che potrà quindi soddisfare la richiesta iniziale. +Il motivo per cui si è scelto di frapporre un Walker fra gli algoritmi di estrazione di superfici +ed il Volume è esclusivamente di ottimizzazione. L'idea di fondo è che il Walker è quell'oggetto +attrverso cui avviene la visita del volume: per ogni cella del volume, esso effettua la chiamata +ProcessCell. Conoscendo l'ordine di visita, il Walker è anche la classe candidata ad implementare +le politiche di caching, in quanto sa esattamente da che momento può essere utile una certa +informazione e per quanto a lungo può essere conveniente mantenerla prima di liberarsene. + +WALKER +==================================================================================== +Poiché la politica di visita del volume è realizzata all'interno del walker, +è opportuno che sempre all'interno del walker vengano realizzate le politiche +di caching rivolte ad ottimizzare l'esecuzione degli algoritmi MC ed EMC. Durante +il processing di ogni cella questi algoritmi possono chiamare le seguenti funzioni +del Walker: + MC EMC + ------------------------------------------ + V(i, j, k) X X + GetXIntercept(p1, p2, v) X X + GetYIntercept(p1, p2, v) X X + GetZIntercept(p1, p2, v) X X + Exist(p1, p2, v) X + +const float V(int i, int j, int k) const + La superficie che attraversa ogni cella viene ricavata dall'algoritmo di estrazione + analizzando il valore del campo sugli otto spigoli di ogni voxel del volume; + per ogni voxel, il valore del campo sui suoi otto spigoli vengono richiesti + dall'algoritmo di estrazione al walker: se questo valore è già stato calcolato + e cachato, il walker restituisce direttamente tale valore; altrimenti il valore + del campo in questo spigolo viene calcolato (eventualmente cachato) e restituito + al walker. In questo modo il valoro del campo ad ogni punto viene calcolato una + sola volta anziché 8, questo puo' essere molto utile nel caso si utilizzi dataset + volumetrici mantenuti implicitamente. + +void GetXIntercept(Point3i p1, Point3i p2, VertexPointer v) +void GetYIntercept(Point3i p1, Point3i p2, VertexPointer v) +void GetZIntercept(Point3i p1, Point3i p2, VertexPointer v) + Dall'analisi del valore del campo agli spigoli di un dato voxel, l'algoritmo di + estrazione ha rilevato che la superficie interseca lo spigolo avente estremi p1 + e p2(a seconda dell'orientazione di questo spigolo, viene chiamato uno dei tre + metodi): al termine di una di queste chiamate, v deve puntare al vertice della + mesh (di coordinate comprese fra p1 e p2) attraverso cui passa la superficie. + Se questo vertice è stato già calcolato ed inserito nella mesh, il walker deve + risalire a tale vertice e memorizzarne in v il suo puntatore. Altrimenti deve provvedere + ad aggiugnere un nuovo vertice ed a calcolare la sua posizione; v deve puntare + in questo caso al vertice appena inserito. + Il motivo per cui questo calcolo non viene implementato direttamente negli algoritmi + di estrazione (possibile per es. attraverso interpolazione lineare del valore + del campo nei punti p1 e p2) è che questo calcolo può essere fatto in maniere + molto più precisa conoscendo come il campo viene calcolato, essendo infatti ciò + dipendente dall'applicazione. + +bool Exist(Point3i p1, Point3i p2, VertexPointer v) + Questo metodo viene chiamato solamente all'interno dell'algoritmo MarchingCubes. + A differenza dei tre motodi precedenti, in questo caso si vuole sapere solamente + se esiste già un vertice tra i punti p1 e p2: nel caso tale vertice esista, Exist + deve resituire true ed v deve puntare a tale vertice; se invece tale vertice non + esiste, Exist deve restituire false e v deve prendere il valore NULL. + NB: nel caso in cui il vertice non esiste, alla mesh non deve essere + aggiunto alcun nuovo vertice. +