In questa lezione ci occupiamo di capire come funziona la content pipeline. Quando aggiungiamo un file, in base alla sua estensione, XNA associa di default due classi con cui elaborare il file. La prima classe è il cosidetto importer, che si occupa di caricare il file dal disco e di portarlo in un formato standard che riflette i suoi contenuti. Ci sono vari importer, uno per ciascuna tipologia di file gestita da XNA:
Importer | Nome | Dati Importati |
---|---|---|
Autodesk FBX | FbxImporter |
NodeContent |
Effect | EffectImporter |
EffectContent |
Sprite Font Description | FontDescriptionImporter |
FontDescription |
Texture | TextureImporter |
TextureContent |
X File | XImporter |
NodeContent |
XML Content | XmlImporter |
Object |
Di ciascun importer ci interessa maggiormente il tipo di dato che l'importer carica. Ad esempio, gli importer Autodesk FBX e X File si occupano di caricare modelli in due formati diversi, ma è interessante vedere come ciascuno di questi formati caricherà lo stesso dato (un NodeContent
) in modo da nascondere al processor il modo in cui le informazioni erano memorizzate sul file, ottenendo una certa astrazione.
Effect carica i dati di uno shader, Sprite Font Description carica un font di sistema, Texture carica una immagine da disco da vari formati e XML Content carica dei semplici dati in XML.
Dopo che l'importer ha condizionato i dati in modo da nascondere le specificità di memorizzazione sul disco di ciascun file, viene invocato il processor. XNA offre vari processor, responsabili di rendere i dati nel formato che servirà al run-time. Possiamo immaginare che un processor metta già i dati in una forma quasi identica a quella che avranno i singoli bit in memoria RAM e della scheda video quando lanceremo il gioco.
I principali processor che troviamo sono:
Processor | Nome | Input | Output |
---|---|---|---|
Effect - XNA Framework | EffectProcessor | EffectContent | CompiledEffect |
Model - XNA Framework | ModelProcessor | NodeContent Class | ModelContent Class |
Sprite Font Description - XNA Framework | Sprite Font Description - XNA Framework | Sprite Font Description - XNA Framework | Sprite Font Description - XNA Framework |
No Processing Required | PassThroughProcessor | Object | Object |
Sprite Font Description - XNA Framework | FontDescriptionProcessor | FontDescription | SpriteFontContent |
Sprite Font Texture - XNA Framework | FontTextureProcessor | TextureContent | SpriteFontContent |
Texture - XNA Framework | TextureProcessor | TextureContent | TextureContent |
I vari processor prendono in input dei dati dall'importer (associato al relativo file) e restituiscono i dati che verranno salvati su disco, pronti per il caricamento dal content writer. In XNA 4.0 il content writer (e il suo duale a runtime, il content reader) viene generato automaticamente in base al dato da salvare. Esaminiamo le funzioni di alcuni dei processor elencati in tabella.
Processor | Serve a... |
---|---|
Effect - XNA Framework | caricare uno shader |
No Processing Required | non eseguire alcun processing e passare i dati importati |
Sprite Font Description - XNA Framework | caricare un font da una descrizione di un font di sistema |
Sprite Font Texture - XNA Framework | caricare un font da una texture contenente i caratteri |
Texture - XNA Framework | caricare una texture |
Model - XNA Framework | caricare un modello |
Model Importer e Model Processor
Vediamo un esempio un po' più dettagliato di cosa succede ad un modello nella content pipeline. Durante l'importing, il file 3D viene convertito in una gerarchia di NodeContent.
Puó suonare un po' strano parlare di un modello 3D rappresentato come gerarchia, piuttosto che come semplice lista di triangoli, vertici e materiali. L'albero, però, rende possibili relazioni tra le parti del modello tali, che alcune trasformazioni ad una sua parte possono dipendere dalle trasformazioni ad altre parti (i nodi genitore).
Immaginiamo di avere un modello 3D di un corpo umano, diviso in testa, busto, braccia e gambe; il busto potrebbe essere la radice (il punto di partenza) della gerarchia. Ignorando le gambe, la gerarchia potrebbe essere:
in cui Frame
denota una trasformazione locale (i dettagli dei modelli e delle animazioni verranno discussi in una lezione successiva). Il primo passo puó quindi essere schematizzato come:
La gerarchia di NodeContent
viene passata automaticamente al ModelProcessor, che la attraversa ricorsivamente e per ogni NodeContent
che contiene i dati di una mesh (ossia il cui tipo dinamico è MeshContent
) esporta i dati della geometria (GeometryContent
), composti di vertici e triangoli, e i dati dei materiali (MaterialContent
), composti di shaders e textures. Il ModelContent
risultante viene salvato su disco pronto per essere caricato dal gioco e visualizzato: