Appunti modulo 03 - Dipartimento di Matematica e Informatica

Transcript

Appunti modulo 03 - Dipartimento di Matematica e Informatica
Modulo 3. Rappresentazione di solidi mediante forntiera e strutture dati collegate.
Nel precedente modulo abbiamo presentato le modalità di rappresentazione di un solido mediante
enumerazione o mediante algoritmi decisionali/costruttivi.
In questo modulo passiamo in rassegna il modello “vincente” che è alla base della maggior parte dei
sistemi 3d diffusi oggi.
Si tratta del metodo di rappresentazione mediante la frontiera: boundary representation, o
brevemente B-rep. Secondo questo approccio visualizzare un modello 3d significa univocamente
visualizzare la sua “superficie” (buccia).
2-manifold
In grafica si sceglie di lavorare solo con superficie che siano 2-manifold.
Una 2-manifold è una superficie bidimensionale tale che: preso comunque un punto su di essa è
possibile scegliere una sferetta centrata nel punto la cui intersezione con la superficie si può
deformare con continuità (senza strappi, tagli o auto-intersezioni) in un disco piano con al centro il
punto.
La superficie esterna della maggior parte degli oggetti fisici reali è, (almeno in prima
approssimazione) una 2-manifold.
Non è sempre così infatti la superficie esterna di un solido ideale costituito da due cubi che
condividono un intero spigolo tra loroo un singolo vertice non è una 2-manifold.
“Come rappresentare” la superficie?
Soluzione universalmente adottata: una superficie sarà un mosaico di poligoni piani definiti tramite
i loro vertici. Quali poligoni?
In hardware non c’è scelta: TRIANGOLI (semplicità=efficienza);
In software: è comodo usare in certe operazioni quadrilateri, pentagoni eccetera. Tale scelta però
alla fine prevede sempre al momento della resa sullo schermo la “riconversione” in triangoli.
In pratica si può pensare ad un sistema grafico 3d come un software con due “layer”. Il layer più
basso che parla con le librerie grafiche (nel caso di Blender con le librerie OpenGL) utilizza solo
triangoli. Il layer superiore, che è quello visibile dall'utente e direttamente gestibile tramite la
interfaccia invece offre maggiore flessibilità ed include poligoni arbitrari.
Formula di Eulero-Poincarè
Qualunque genere di poligoni si scelga gli elementi che descriveranno la superficie ai fini della
computer grafica sono: i vertici, i lati (o spigoli) e le facce (o poligoni).
La matematica ha da molto tempo trovato la relazione che lega il numero dei vertici, dei lati e delle
facce alla cosiddetta “topologia” dell’oggetto solido che si sta modellando.
Vale infatti per solidi connessi e senza buchi la cui frontiera sia una 2-manifold la cosiddetta
formula di Eulero-Poincarè:
#vertici - #lati + #facce = 2
In realtà esiste una formula di Eulero-Poincarè più generale che include tutti i tipi di solidi:
#vertici - #lati + #facce = 2(s –h)
Ove s è il numero di componenti connesse del solido e h il numero dei “buchi” nel solido.
Attenzione: queste sono condizioni necessarie che una rappresentazione di un solido mediante
poligoni dovrà avere ma non sono sufficienti: posso costruire collezioni di poligoni che soddisfino
la equazione sopra senza definire alcun solido.
Problemi più pratici da risolvere se si vuole modellare con i poligoni.
Resta da capire:
i) come definire (con quali strumenti interattivi, con quali operazioni matematiche) i triangoli che
compongono l’oggetto
ii) come memorizzarli in RAM (al momento della elaborazione e utilizzo dei modelli)
iii) come memorizzarli in memoria di massa.
iv) è inoltre indispensabile avere una modalità “rapida” di visualizzazione che sacrifichi la qualità
per la immediatezza e la interattività.
Al punto i) si risponde in moltissimi modi diversi.
Tutto il software “comune” adotta la seguente filosofia: offrire e combinare tra loro le seguenti
operazioni:
a) la creazione di “modelli base” predefiniti, o configurabili in base ad alcuni semplici
parametri. Successivamente si interviene su tali modelli “mesh” con operazioni “globali”
(scala, traslazione) o con operazioni locali (spostare vertici della “mesh”, eliminare vertici,
aggiungere vertici e lati, estrudere facce, lati, vertici eccetera).
b) La creazione di oggetto “complessi” mediante operazioni semplici: solidi di rotazione a
partire da profili, solidi “estrusi” in 3d a partire dalla loro silouette 3d.
c) La definizione di superficie che “appaiono curve” e non piatte definendo alcuni “punti di
controllo”. Curve e superficie di Bezier, spline e variazioni raffinate sul tema.
d) L’uso (anche se non esclusivo) della cosiddetta “solid constructive geometry” che definisce
gli oggetti come primitive solide semplici (cubi, sfere, cilindri, coni, eccetera) e li combina
con le operazioni di intersezione, unione, sottrazione eccetera (nelle versioni
“regolarizzate”). Questa modalità è molto intuitiva e si ritrova nei software più comuni ma
presenta il problema che è difficile ottenere i triangoli finali a partire da questi modelli
almeno nelle situazioni più complesse.
Ovviamente la combinazione di questi strumenti pone numerosi problemi: ogni metodo usa una
struttura dati a lui più conveniente e combinare metodi diversi implica una
integrazione/trasformazione tra strutture dati diverse… un bel problema di algoritmi!
Il punto ii) è stato oggetto di molti studi e proposte. Il modello che ha “vinto” è ormai quello a “lati
alati” (winged edges o la sua variazione degli “half edges”). Raramente chi “usa” un software di
modellazione si pone questo problema. Esso è però centrale per l’informatico che deve disegnare e
scrivere tali software!
Il punto iii) è invece noto come problema dei “formati 3d”. Non possiamo trattare appieno, per
mancanza di tempo, questo argomento. Tuttavia gli studenti possono avere una idea di un formato
grafico estremamente comune: il formato “obj” leggendone la descrizione nella dispensa scaricabile
dal sito del corso.
Al punto iv) tipicamente si risponde visualizzando SOLO i vertici dei poligoni (puntini) e i lati dei
poligoni stessi, come fossero fili di ferro (“wireframe”). Un modello visualizzato in questo modo
assomiglia ad un cestino intessuto in vimini, una “rete” o in inglese “mesh”. Altre soluzioni sono
ormai rese possibili dalla velocità dell’hardware (visualizzazione “solid” o a ombreggiatura/colore
costante su tutta la superficie del poligono eccetera).
Come organizzare il DB dei punti/lati/facce di un modello
I dati essenziali da memorizzare sono:
a) i vertici e le loro coordinate nello spazio 3d di riferimento;
b) le relazioni “ a due a due” tra vertici (lati o spigoli);
c) le relazioni di gruppi di vertici che definiscono un poligono piano o “faccia” del solido;
E’ però spesso utile conoscere:
dato un vertice quali sono tutti i lati incidenti in esso;
dato un lato, quali sono tutti lati con cui esso condivide un vertice;
data una faccia, quali sono tutti i lati che compongono il suo perimetro;
data una faccia, quali sono tutte la altre facce che condividono con essa un lato.
Una particolare query è di enorme utilità: data una faccia conoscere le componenti del vettore che
indica la direzione normale alla faccia nella direzione rivolta verso l’esterno del solido. Tale
informazione sulla normale è essenziale sia per decidere l’ombreggiatura della faccia sia per
comprendere se essa è visibile o meno dalla telecamera che ritrae una scena.
Ottimizzare l’occupazione di memoria e mantenere la possibilità di rispondere rapidamente a
queste query è uno dei grandi problemi della modellazione.
Per illustrare le idee seguenti la cosa migliore è partire da un esempio. Un semplice cubo di lato
unitario con uno spigolo nella origine e con i lati allineati agli assi coordinati.
Lo studente è invitato a costruire (carta e penna) analoghi DB di semplici solidi di sua scelta per
verificare la comprensione delle strutture dati che andiamo a presentare di seguito.
Un DB semplice ma poco utile
TABELLA DEI VERTICI
vertice x y z
A
0 0 1
B
1 0 1
C
1 1 1
D
0 1 1
E
0 0 0
F
1 0 0
G
1 1 0
H
0 1 0
faccia
vertici
(in senso orario rispetto ad un omino che sia orientato
come la normale alla faccia rivolta verso l’esterno del
solido)
1
2
3
4
5
6
A
E
H
D
E
G
E
H
D
A
A
C
F
G
C
B
D
B
B
F
G
C
H
F
lato
a
b
c
d
e
f
g
h
i
l
m
n
parte da
A
E
H
D
E
E
H
D
B
B
F
G
arriva a
B
F
G
C
A
H
D
A
C
F
G
C
Questa prima strutturazione delle informazioni descrive le entità e le relazioni fondamentali ma
rende poco agevoli le query di cui si parlava prima.
Si osservi che la situazione non cambia di molto se invece di registrare i vertici che compongono il
perimetro di ciascuna faccia registro i lati (percorrendoli in senso orario)
La struttura winged edges (lati alati)
Alcune semplici osservazioni:
Se scegliamo in maniera arbitraria l’ordinamento dei lati (ed è questo ciò che abbiamo fatto sopra)
quando descriviamo il perimetro delle facce, in senso orario a partire da un lato arbitrario, ciascun
lato verrà percorso due volte, cioè una volta per ciascuna faccia cui appartiene.Una volta verrà
percorso in senso “concorde” al suo orientamento ed un’altra volta nel senso “discorde” al suo
orientamento.
Questa osservazione e l’aggiunta di una piccola ridondanza di informazioni nel DB che andiamo a
costruire permetterà di realizzare alcune delle query elencate prima in maniera naturale ed
efficiente.
Il nuovo DB sarà imperniato su una nuova tabella i cui record sono detti winged edges.
Per comprendere meglio cosa è un winged edge guardiamo un ingrandimento di un lato tratto dal
nostro modello geometrico e definiamo alcune importanti entità ad esso relative.
d
b
b
V_end
Faccia 1
Faccia 2
c
a
V_start
e
Osserviamo il lato a.
Chiamiamo V_start (VS) e V_end(VE) i vertici del lato (scelti in maniera arbitraria) Si osservi che
una volta che siano stati fissati l’orientamento del lato è fissato arbitrariamente di conseguenza.
Le due facce incidenti in tale lato siano la 1 e la 2.
Se ci orientiamo con la normale della faccia 1 e percorriamo i lati in senso orario il lato a verrà
percorso in verso concorde al suo orientamento.
Se ci orientiamo con la normale della faccia 2 e percorriamo i lati in senso orario il lato a verrà
percorso in verso discorde al suo orientamento.
Chiameremo la faccia 1 ClockWiseFace o brevemente CWF del lato a e la faccia 2
CounterClockWiseFace o brevemente CCWF del lato a.
Se ci muoviamo sulla faccia CWF, nel nostro caso la 1, il lato b è il NextClockWiseEdge (NCWE)
di a. Similmente il lato d è il PreviousClockWiseEdge (PCWE) di a.
Se ci muoviamo sulla faccia CCWF di a, il lato e è il NextCounterClockWiseEdge di a. (NCCWE).
Similmente il lato c è il PreviousCounterClockWiseEdge di a (PCCWE). Si noti che gli altri
eventuali lati incidenti in V_start o V_end non hanno importanza per noi.
Possiamo dunque definire il record che “memorizzerà” il nostro lato e la sua “geometria”
relativamente al solido di cui ci stiamo occupando:
record winged edge
Id. lato
V start
V end
CWF
CCWF
PCWE
NCWE
PCCWE
NCCWE
Il nostro cubo genererà quindi una tabella con 12 record di tipo winged edge.
Il Data base sarà completato:
a) da una tabella per i vertici come nel caso precedente. A tale tabella sarà però aggiunta una
colonna che conterrà l’id di uno dei lati incidenti in tale vertice.
b) da una tabella che elenca le facce del solido. Per ciascuna faccia verrà solo indicato uno dei lati
che ne formano il perimetro.
Si osservi che sebbene la tabella dei lati risulti adesso più complessa essa ha record di dimensioni
fisse.
Ma anche la tabella delle facce adesso ha record (piccoli) e di dimensione fissata. Nel rpecedente
caso invece tale tabella aveva record di dimensioni variabili a seconda del numero dei suoi vertici
(nel nostro esempio solo casualmente tale numero era 4 per ciascuna faccia).
Si intuisce che questo è un enorme vantaggio per la implementazione.
Il vantaggio è però anche nella esecuzione di alcune query.
Per illustrarlo riporto di seguito le tabelle WingedEdegs, Vertici e Facce del nostro cubo:
Tabella Winged Edges
Id Vs Ve CWF CCWF
a
A
B
4
1
b
E
F
1
2
c
H G
2
3
d D
C
3
4
e
E
A
5
1
f
E
H
2
5
g H D
3
5
h D A
4
5
i
B
C
4
6
l
B
F
6
1
m F
G
6
2
n G
C
6
3
PCWE
h
e
f
g
f
b
c
d
a
i
l
m
NCWE
i
l
m
n
h
c
d
a
d
m
n
i
PCCWE
l
m
n
i
a
g
h
e
n
b
c
d
NCCWE
e
f
g
h
b
e
f
g
l
a
b
c
(il prof. spera di non avere sbagliato qualche etichetta… come si vede la compilazione di tabelle di questo tipo è un compito tipico da COMPUTER e
non da UMANO)
Tabella estesa dei vertici
vertice x y z Un lato incidente
(scelto arbitrariamente)
A
0 0 1
a
B
1 0 1
a
C
1 1 1
d
D
0 1 1
d
E
0 0 0
e
F
1 0 0
m
G
1 1 0
m
H
0 1 0
f
Nuova tabella delle facce
Id faccia Un lato del perimetro della faccia
scelto arbitrariamente
1
a
2
b
3
c
4
d
5
e
6
n
Nella prossima pagina illustreremo al esecuzione di alcune query usando le tre tabelle riportate qui.
Query 1 – trovare tutti i lati di una faccia.
Proviamo a trovare i lati che formano il perimetro della faccia 6
Partiamo dalla tabella delle facce. Ne ricaviamo subito che il lato n fa parte di questa faccia.
Nella tabella WE scopriamo che la faccia 6 è la CWF del lato n. Il lato della faccia 6 successivo ad n si trova dunque
nella colonna NCWE ed è il lato i.
Nella tabella WE al rigo del lato i leggiamo che la faccia 6 è la CCWF di i. Il lato sulla faccia 6 successivo a i è quindi
indicato dalla colonna NCCWE ed è il lato l.
Nella tabella WE al rigo del lato l leggiamo che la faccia 6 è la CWF del alto l. Il lato sulla faccia 6 successivo ad l è
quindi scritto nella colonna NCWE del rigo l. Esso è il lato m.
Nella tabella WE al rigo del lato m leggiamo che la faccia 6 è la CWF del lato m. Il lato sulla faccia 6 successivo ad m
è quindi scritto nella colonna NCWE del rigo m. Esso è il lato n da cui eravamo partiti. Abbiamo dunque ricostruito la
intera sequenza: n-i-l-m.
Query 2 – trovare tutti i vertici di una faccia.
Si esegua la query 1 e man mano che si scorrono i lati si annotino i loro estremi (tenendo conto dell’orientazione del
lato).
Giusto per scrivere la procedura noiosa che ne viene fuori:
Partiamo dalla tabella delle facce. Ne ricaviamo subito che il lato n fa parte di questa faccia.
Nella tabella WE scopriamo che la faccia 6 è la CWF del lato n.
I vertici G e C sono quindi i primi due vertici della faccia 6 letti in senso orario rispetto alla normale della faccia 6.
Il lato della faccia 6 successivo ad n si trova nella colonna NCWE ed è il lato i.
Nella tabella WE al rigo del lato i leggiamo che la faccia 6 è la CCWF di i.
I vertici C e B (attenzione all’ordine) sono dunque i vertici successivi della faccia 6.
Il lato sulla faccia 6 successivo a i è indicato dalla colonna NCCWE ed è il lato l.
Nella tabella WE al rigo del lato l leggiamo che la faccia 6 è la CWF del alto l.
I vertici B e F sono dunque i vertici successivi della faccia 6.
Il lato sulla faccia 6 successivo ad l è scritto nella colonna NCWE del rigo l. Esso è il lato m.
Nella tabella WE al rigo del lato m leggiamo che la faccia 6 è la CWF del lato m.
I vertici F e G sono i due vertici successivi.
Il lato sulla faccia 6 successivo ad m è quindi scritto nella colonna NCWE del rigo m. Esso è il lato n da cui eravamo
partiti. Abbiamo dunque ricostruito la intera sequenza: n-i-l-m. dei lati e GCBF dei vertici.
Query 3 – trovare tutti i lati incidenti in un vertice.
Cerchiamo tutti i lati incidenti nel vertice A.
La tabella dei vertici ci dice che il lato a è incidente in A.
La tabella WE alla riga del lato a ci informa che il vertice A è il vertice di partenza del lato a.
Data la struttura dei winged edge il precedente lato incidente in A, girando in senso orario attorno ad A stesso è il lato
nel campo PCWE cioè il lato h.
La tabella WE alla riga del lato h ci informa che il vertice A è il vertice di arrivo del lato A.
Data la struttura dei winged edge il precedente lato incidente in A, continuando a girare in senso orario attorno ad A
stesso è il lato nel campo PCCWE cioè il lato e.
La tabella WE alla riga del lato e ci informa che il vertice A è il vertice di arrivo del lato A.
Data la struttura dei winged edge il precedente lato incidente in A, continuando a girare in senso orario attorno ad A
stesso è il lato nel campo PCCWE cioè il lato a. Il cerchio si è chiuso.