• Non ci sono risultati.

4.3 Implementazione dello standard

4.3.1 Import

Per leggere le informazioni contenute in un file COLLADA è stata utilizzata la classe precedentemente presentata, che realizza il parser XML. L’interpretazione e l’implementazione delle informazioni contenute nella struttura creata, ha seguito l’ordine prestabilito durante l’approccio iniziale del progetto.

La difficoltà realizzativa dell’import è stata maggiore rispetto all’export, perché in questa fase è stata richiesta la gestione, per ogni specifica, di tutte le sue possibili rappresentazioni.

CAPITOLO 4 - REALIZZAZIONE DEL PROGETTO PG 45

Geometrie

Il primo aspetto considerato è stato quello delle geometrie mesh, che come già spiegato, in COLLADA sono descritte mediante sette tipologie di primitive: Line, Linestrips, Polygons, Polylist, Triangles, Trifans e Tristrips.

All’interno di ogni geometria sono presenti degli array che contengono tutti i punti che la descrivono, perciò la prima operazione svolta è la loro memorizzazione all’interno di un contenitore map avente come coppia chiave-valore l’id univoco dell’array e il puntatore al vector dei vertici (ognuno composto da tre valori float corrispondenti alle coordinate X, Y e Z). Questa fase è necessaria per poter gestire l’eventuale istanziazione di un array contenuto all’interno di un’altra geometria. Spazio3D supporta degli oggetti per la rappresentazione di linee tridimensionali, gestibili semplicemente specificando la sequenza dei vertici che le compongono, esattamente allo stesso modo previsto per le Linestrips.

Questa caratteristica ha permesso l’immediata traduzione delle Linestrips, semplicemente riportando la sequenza degli indici che le compongono. Per le Line invece, si è deciso di generare una nuova linea solamente quando l’indice finale di una non corrisponde a quello iniziale della successiva. Ad esempio, se la sequenza degli indici è 0 1 2 3 3 4 4 5, non vengono create le quattro linee (0; 1) (2; 3) (3; 4) e (4; 5) ma solo due (0; 1) e (2; 3; 4; 5).

Le rimanenti cinque primitive costituiscono rappresentazioni diverse per la definizione d’insiemi di facce. Tra queste, le più semplici sono certamente le Triangles, Trifans e Tristrips perchè descrivono facce triangolari. All’interno di Spazio3D possono essere gestite facce da tre o quattro vertici, perciò è possibile riprodurre esattamente le facce gestendo correttamente la sequenza degli indici secondo la primitiva specificata.

Polygons e Polylist sono le primitive che hanno presentano le maggiori difficoltà perchè descrivono facce con un numero arbitrario di vertici e nel primo caso possono contenere anche dei fori. Nel caso in cui una faccia sia costituita da meno di cinque vertici e non abbia fori al suo interno, viene facilmente ricreata senza dover compiere alcuna operazione d’attamento. Se invece la faccia non rientra in questa casistica, vengono utilizzati i metodi della classe Covering per la sua copertura. Purtroppo, gli algoritmi implementati all’interno di questa classe lavorano solo sulle coordinate x e y dei punti; perciò prima d’utilizzarli dovranno essere portati tutti in pianta, aumentando ulteriormente il tempo già oneroso, necessario alla loro computazione. Questa operazione avviene mediante una matrice di trasformazione calcolata rispetto al piano generato da tre punti presi a caso (ovviamente tra quelli che compongono la faccia stessa). Una volta calcolata la copertura, tutte le facce calcolate vengono riportate nella corretta posizione applicando, ad ognuna di esse, la matrice di trasformazione inversa rispetto a quella precedentemente utilizzata. Dopo aver ricavato tutte le facce della geometria, viene creato un oggetto mesh per racchiuderle assieme ai rispettivi vertici.

Ogni linea e ogni oggetto mesh viene inserito all’interno di un contenitore di tipo blocco. In questo modo si concretizza la possibilità di avere una geometria composta da un numero arbitrario di primitive e di poterla memorizzare all’interno di un map

puntatore al blocco.

Verrà ora proposto uno pseudo-codice che a grandi linee racchiude l’insieme di operazioni appena descritte:

Individua la Library_geometry Per ogni geometria

{

Per ogni array {

Carica l’array di valori float;

Inserisci nel vector i punti tridimensionali creati raccogliendo a tre a tre i valori dell’array;

Crea la coppia id dell’array e puntatore al vector; Inserisci la coppia nel contenitore map per i vertici; }

}

Per ogni geometria {

Carica la sequenza degli indici;

Richiama il vettore di vertici specificato; Se la primitiva è Line

{

Crea la prima linea e inserisci il primo indice; Scorri la sequenza degli indici

{

Se l’indice finale di una linea corrisponde all’inizio della successiva

Accoda l’indice finale alla sequenza descrittiva della linea; Altrimenti

Termina la linea con l’indice finale e crea una nuova linea con il corrispondente indice d’inizio;

}

Inserisci le linee nel blocco; }

Se la primitiva è Linestrips {

Crea una linea e assegnale l’intera sequenza degli indici; Inserisci la linea nel blocco;

}

Se la primitiva è Triangles {

Per ogni gruppo di tre indici

Crea una faccia e assegna gli indici facendo corrispondere il terzo vertice con il quarto;

Crea un oggetto mesh e inserisci l’insieme di facce e vertici; Inserisci l’oggetto mesh nel blocco;

}

Se la primitiva è Trifans {

Scorri la sequenza degli indici a partire dal terzo

Crea una faccia con: il primo indice, l’indice corrente e quello precedente, facendo corrispondere il terzo vertice con il quarto; Crea un oggetto mesh e inserisci l’insieme di facce e vertici;

Inserisci l’oggetto mesh nel blocco; }

Se la primitiva è Tristrips {

Scorri la sequenza degli indici a partire dal terzo

Crea una faccia con l’indice corrente e i due precedenti, facendo corrispondere il terzo vertice con il quarto; Crea un oggetto mesh e inserisci l’insieme di facce e vertici;

CAPITOLO 4 - REALIZZAZIONE DEL PROGETTO PG 47

Inserisci l’oggetto mesh nel blocco; }

Se la primitiva è Polylist {

Scorri la sequenza degli indici

Se la faccia è composta da tre o quattro vertici

Crea la faccia con i relativi indici, facendo corrispondere se necessario il terzo vertice con il quarto;

Altrimenti {

Ricava la matrice di trasformazione per portare in pianta i punti e la relativa matrice inversa;

Applica la matrice ai punti;

Utilizza i metodi della classe Covering per ottenere le facce corrette;

Applica la matrice inversa ai punti; }

Crea un oggetto mesh e inserisci l’insieme di facce e vertici; Inserisci l’oggetto mesh nel blocco;

}

Se la primitiva è Polygons {

Scorri la sequenza degli indici

Se la faccia è composta da tre o quattro vertici e non ha fori Crea la faccia con i relativi indici, facendo corrispondere se necessario il terzo vertice con il quarto;

Altrimenti {

Ricava la matrice di trasformazione per portare in pianta i punti e la relativa matrice inversa;

Applica la matrice sia ai punti del perimetro esterno sia ai punti dei fori;

Utilizza i metodi della classe Covering per ottenere le facce corrette;

Applica la matrice inversa sia ai punti del perimetro esterno sia ai punti dei fori;

}

Crea un oggetto mesh e inserisci l’insieme di facce e vertici; Inserisci l’oggetto mesh nel blocco;

} }

Crea la coppia id della geometria e puntatore al blocco; Inserisci la coppia nel contenitore map per le geometrie;

Ovviamente, il codice reale è molto più complesso ed articolato, avendo un gran numero di controlli per la correttezza dei dati e la suddivisione delle operazioni in funzioni. Se presenti, vengono inoltre inseriti i valori delle normali ai relativi vertici, tranne nel caso in cui le facce siano generate dalla classe Covering, in quanto in alcuni casi si potrebbe perdere la corrispondenza con i punti della faccia originale.

Importazione delle geometrie di una moto

L’importazione delle spline e delle convex mesh non è stata realizzata. Nel primo caso basterà adattarle alle spline proprie di Spazio3D mentre nel secondo caso dovrà essere implementato un algoritmo per il calcolo del guscio convesso dell’insieme dei vertici di una o più geometrie richiamate.

Materiali

Ad ogni mesh può essere associato un materiale, il quale sarà costituito da un particolare effetto creato dalla combinazione di colori e texture associate alle proprietà fisiche della luce. In COLLADA i colori sono rappresentati da quattro valori float che rappresentano i valori normalizzati dei rispettivi colori RGBA. Spazio3D gestisce i colori attraverso una palette di 256 elementi di cui all’incirca metà sono già preassegnati. Avendone perciò a disposizione solo un numero ristretto, non viene occupato un posto libero nel caso il colore richiesto non figuri tra quelli presenti ma invece viene prima eseguita una ricerca per vicinanza alla tonalità. Solo nel caso in cui la distanza sia troppo grande viene inserito un nuovo colore. Per il calcolo della distanza è stata sfruttata la possibilità di associare i valori RGB a dei punti con coordinate XYZ; ne consegue che, la distanza tra due colori diventa la distanza euclidea dei corrispondenti punti, mentre la ricerca può essere paragonata al trovare il punto più vicino a quello dato in un intorno sferico di raggio pari alla massima tolleranza desiderata.

Verrà ora proposto uno pseudo-codice che descrive le operazioni necessarie per l’assegnazione di un colore:

CAPITOLO 4 - REALIZZAZIONE DEL PROGETTO PG 49

Crea un punto con i valori XYZ pari a quelli RGB;

Inizializza la distanza minima trovata con un valore molto grande; Per ogni elemento della palette

{

Se l’elemento è vuoto Memorizza l’indice; Altrimenti

{

Crea un punto con i valori XYZ pari a quelli RGB dell’elemento; Calcola la distanza tra i punti;

Se la distanza è inferiore a quella minima precedentemente trovata memorizza l’indice dell’elemento;

}

Se la distanza è inferiore ad una certa tolleranza data Utilizza l’indice dell’elemento con distanza minima; Altrimenti

{

Se c’è un elemento vuoto

Assegna all’elemento i valori RGB del colore richiesto; Altrimenti

Lancia eccezione; }

Luci

Per importare le luci non è stato necessario compiere alcun adattamento in quanto trovavano una corrispondenza esatta rispetto a quelle presenti in Spazio3D, con l’unica eccezione che riguarda la luce direzionale, perchè non prevista.

Per la sua rappresentazione si è scelto di approssimarne l’effetto utilizzando un punto luce con le stesse proprietà e di posizionarla lungo la direzione prevista ad una distanza molto grande rispetto agli altri componenti della scena. In questo modo i raggi che colpiscono le superfici delle entità risultano essere quasi paralleli, come se fossero appunto originati da una luce direzionale. Come una luce d’ambiente anche quella direzionale non ha attenuazione, perciò ai coefficienti costanti, lineari e quadratici, vengono dati valori molto prossimi allo zero.

Telecamere

Per quanto riguarda le telecamere, COLLADA ne gestisce due tipologie: ortogonali e prospettiche, che come visto catturano proiezioni di spazio differenti e vengono posizionate all’interno della scena modificando l’orientamento comune prefissato attraverso l’applicazione delle matrici di trasformazione proprie del node in cui vengono istanziate.

Spazio3D invece, ne mette a disposizione una con un volume di vista rappresentabile mediante un cono, avente l’apice posizionato nel punto d’osservazione e la lunghezza della focale infinita.

La soluzione scelta per adattare queste diverse tecniche, prevede la circoscrizione del piano rettangolare del volume di vista più vicino al punto d’osservazione (presente sia nella proiezione ortogonale sia in quella prospettica) nella circonferenza corrispondente alla sezione del cono passante per il piano stesso. Dal raggio della circonferenza così ottenuta, si risale al valore dell’angolo di campo. La conoscenza di questo valore è resa necessaria dal fatto che Spazio3D lo utilizza come parametro fondamentale per la definizione della telecamera stessa.

Formule per il calcolo dell’angolo di campo Scena

Come visto, COLLADA permette la definizione di più scene all’interno dello stesso file e di poterne istanziare una, quella effettivamente visualizzata. Spazio3D può gestire una sola scena e perciò viene importata solamente quella istanziata.

Prima di esaminare il contenuto della scena, viene eseguita una scansione di tutti i node contenuti nella libreria delle scene e nella libreria dei node, memorizzando in un map la coppia id del node ed un puntatore ad esso. Questa scansione servirà nel caso in cui all’interno della scena sia presente l’istanziazione di un node, rendendo perciò il suo ritrovamento quasi immediato. Ogni node, rappresentando un raggruppamento, viene associato ad un blocco e tutte le trasformazioni ed istanziazioni vengono applicate al blocco stesso.

La lettura della scena avviene attraverso l’ispezione del relativo albero dei node. Si è optato per la creazione di due alternative: mantenere inalterata la struttura o semplificare gli elementi node in caso in cui abbiano un solo figlio o siano figli unici. La prima opzione prevede la costruzione di un blocco in corrispondenza di ogni node e l’inserimento nello stesso delle istanziazioni presenti. Nel secondo caso invece, il contenuto del node dovrà essere inserito nel padre e le trasformazioni che conteneva, dovranno essere applicate ai figli.

Si possono trovare file con gerarchie di node che non contengono alcun tipo d’istanziazione, perciò vuoti e quindi non devono essere rappresentati in alcun caso. Per questo motivo prima di esaminare il contenuto di un node viene sempre eseguito un controllo.

Il contenuto di una scena viene istanziato solo all’interno di un node, perciò non è possibile determinare se i node al livello più alto siano o no dei veri gruppi. Essendo possibile specificare l’autore del file, si può capire se esso sia il risultato di un’esportazione diretta da Spazio3D. In tal caso, vengono eseguite delle semplificazioni iniziali in modo tale da mantenere inalterata l’intera struttura.

CAPITOLO 4 - REALIZZAZIONE DEL PROGETTO PG 51

COLLADA prevede quattro elementi per descrivere le varie trasformazioni: rotate, scale, translate e matrix. Si è scelto di riportare tutte queste trasformazioni sotto forma di matrice e di moltiplicarle tra loro, in modo tale da avere una sola matrice da applicare ai figli del node. Per la non commutatività della moltiplicazione delle matrici, l’ordine delle moltiplicazioni stesse, dovrà essere inversa rispetto all’ordine in cui appaiono.

Conversione delle trasformazioni COLLADA in matrici Asset

Ogni elemento asset può contenere come informazioni l’unità di misura e il sistema di coordinate da utilizzare. Per poter utilizzare queste informazioni, esse vengono convertite in matrici. L’unità di misura viene associata ad una matrice di cambio scala, il cui valore è rapportato con quello di riferimento di Spazio3D. Le coordinate di sistema vengono tradotte in matrici di rotazione in modo tale da riportare la rappresentazione degli elementi in un sistema d’assi comune.

Nel documento Uso di COLLADA nella rappresentazione CAD (pagine 48-55)

Documenti correlati