• Non ci sono risultati.

Nel presentare l'organizzazione degli oggetti virtuali e della scena abbiamo trascurato un aspetto fondamentale: la gestione delle istanze delle classi. Per capire quale può essere il problema supponiamo di creare due oggetti virtuali (istanze di VR3Obj) specicando un le da cui prelevare i dati per l'unica mesh negli oggetti. Se per i due oggetti virtuali viene specicato lo stesso le e la stessa mesh al suo interno, risulta conveniente associare ai due la stessa istanza di VR3Mesh per evitare una inutile replicazione di dati (multiple istanze di VR3Mesh identiche tra loro).

Questo principio si applica a diverse classi: • VR3Mesh

È inutile creare diverse mesh se alcuni oggetti virtuali fanno riferimento allo stesso le e alla stessa mesh al suo interno.

• VR3Material

È inutile creare molteplici istanze della classe VR3Material quando diverse mesh fanno riferimento allo stesso materiale (i cui dati vengono estratti da un le esterno).

• VR3Texture

È inutile caricare e costruire sul server GL due diverse texture che si riferiscono alla stessa immagine (stesso le): diversi materiali che sfruttano la stessa immagine come texture possono fare riferimento allo stesso oggetto di tipo VR3Texture.

Inoltre si applica anche alla classe VR3PhyMesh di cui non abbiamo ancora parlato e che verrà introdotta in sez. 5.6; fondamentalmente questa classe incapsula la geometria e il materiale da utilizzare nella simulazione sica di un oggetto virtuale. Ad ognuna delle classi sopra è stato quindi assegnato un gestore: una classe non istanziabile che fornisce una serie di funzioni membro statiche. Un gestore è semanticamente simile al concetto di namespace, ma vi sono anche dei membri dati statici accessibili alle funzioni membro statiche. Ogni gestore mantiene un insieme di riferimenti a istanze della classe gestita ed è in grado di recuperare un qualunque riferimento sfruttando dei parametri che identicano la particolare istanza (una chiave, come il path assoluto del le caricato per le istanze di VR3Texture).

Quando si deve ottenere un riferimento ad un oggetto gestito (come una mesh durante la costruzione dell'oggetto virtuale), la prima operazione svolta è l'inter- rogazione del gestore al ne di scoprire se tale oggetto è già stato caricato (in tal caso si recupera un riferimento e in questo modo si evita una inutile replicazione di dati). Se l'oggetto non è ancora stato creato si costruisce in memoria dinamica e si incarica il relativo gestore di caricarne il contenuto. Il gestore quindi registra il nuovo oggetto nell'insieme di istanze gestite e carica il contenuto sulla base del tipo di oggetto (ad esempio caricherà l'immagine come texture nel caso di VR3Texture). I vari gestori sono allora anche dei caricatori per istanze della classe gestita.

Visto che un oggetto gestito (ad esempio una istanza di VR3Mesh) può essere ri- ferito da molteplici entità (diverse istanze di VR3Obj), quando si distrugge un'entità che lo riferisce non è sempre lecito distruggere anche l'oggetto gestito (questo po- trebbe ancora servire ad altre entità). Si è allora previsto all'interno di ogni gestore un meccanismo di reference counting che consente di deallocare l'oggetto gestito so- lamente quando il numero di entità che lo riferiscono scende a 0. Anche l'utente può possedere un riferimento esplicito ad un oggetto gestito (ad esempio un riferimento ad una istanza di VR3Mesh) e anche questo tipo di riferimento conta al ne di capire se l'oggetto può venire o meno deallocato. Per facilitare le operazioni con gli oggetti gestiti, viene proibita la chiamata al distruttore da parte delle entità che riferisco- no l'oggetto gestito: si fornisce invece una funzione Destroy() che sfrutta i servizi del gestore per modicare il contatore di riferimenti ed eventualmente deallocare l'oggetto gestito (se il contatore scende a 0).

La lista dei gestori e le relative classi gestite è riportata di seguito: • VR3MeshManager, gestore di oggetti di tipo VR3Mesh;

• VR3MaterialManager, gestore di oggetti di tipo VR3Material; • VR3TextureManager, gestore di oggetti di tipo VR3Texture; • VR3PhyMeshManager, gestore di oggetti di tipo VR3PhyMesh.

La chiave utilizzata per identicare una particolare istanza cambia di gestore in ge- store; per esempio, nel caso di oggetti di tipo VR3Texture avremo come chiave il path assoluto del le contenente l'immagine caricata, mentre per identicare un'istanza di VR3Mesh useremo il path assoluto del le contenente la mesh in combinazione con un identicatore della mesh all'interno del le stesso.

CAPITOLO 5. STRUTTURA E FUNZIONAMENTO DELLA VR3LIB 151

Figura 5.4: Gestori nella VR3Lib

Notiamo che si utilizzano dei contenitori associativi di tipo std::map (forniti dal- la STL) per associare ad ogni chiave un particolare riferimento all'oggetto gestito. Non è richiesta una particolare ecienza nell'accesso a queste strutture associative perchè gli accessi avverranno tipicamente in fase di inizializzazione e in fase di ter- minazione dell'applicazione, ma non durante il ciclo di rendering principale (quindi contenitori di tipo std::map risultano idonei).

Alcune funzioni vengono fornite dai gestori (nella forma List*()) per consentire all'utente di recuperare una lista di oggetti che si possono caricare da un le speci- cato. Questo è utile quando un singolo le può contenere diversi oggetti che possono essere caricati singolarmente tramite il gestore (non si applica dunque al caso delle texture dove si carica un intero le che rappresenta un'immagine). Queste funzioni di esplorazione sono attualmente disponibili solamente nel caso di le AAM (vedi sec. 5.10).

Nella precedente versione della VRLib non erano disponibili gestori come quelli presentati in questa sezione: un'approccio simile a quello visto veniva applicato nel caso delle texture, ma non si evitava automaticamente la replicazione dei dati relativi a mesh e materiali.