The Xna-Way: Tutorial 2: Camera

Finalmente trovo il tempo e la voglia di scrivere qualche altra riga.
Questa volta mi sono occupato della camera della scena. Una semplice telecamera fissa, perchè per poter aggiungere altre funzionalità dovrò prima implementare altri servizi e componenti, tra i quali quelli per gestire l'input da tastiera (e mouse) e un modo semplice per renderizzare qualcosa a scena.

Purtroppo per vedere gli effetti di quanto scrivo dovremo attentere il prossimo articolo. Questo non perchè non funziona, ma solo perchè non ci sarà niente da renderizzare nella scena (come ho detto dovrò poi implementare un qualcosa per far renderizzare un modello tridimensionale!)
Questo componenten va aggiunto al progetto myLibrary.
Ecco il codice del file:

Camera.cs
Hide/Show


Naturalmente nessuno ci vieta di aggiungere funzionalità al nostro codice in futuro :)

Analizziamo il codice pezzo a pezzo:
il vettore position è quello che contiene la posizione dal quale stiamo osservando la scena, mentre target è il vettore che contiene il punto che stiamo osservando.
Up è il vettore che indica in quale direzione è l'alto nella scena.
Con il codice scritto abbiamo che la telecamera (o punto di osservazione) è posizionato in posizione X = 0, Y = 0, Z = 20.
Stiamo osservando il punto X = Y = Z = 0, e l'alto è dato dal vettore con componente Y positiva (in teoria [0,1,0]).

float aspectRatio = (float)Game.GraphicsDevice.Viewport.Width /
(float)Game.GraphicsDevice.Viewport.Height;
Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
aspectRatio, 1.0f, 10000.0f, out projection);
Matrix.CreateLookAt(ref position, ref target, ref up, out view);

Con questo codice creiamo prima di tutto il rapporto tra le dimensioni del nostro schermo (di solito un televisore è in 4:3 o 16:9). Nel nostro caso il rapporto è tra la larghezza e l'altezza delle dimensioni dell'area di rendering.
Per accedere a questa informazione utiliziamo
Game.GraphicsDevice.Viewport.Width e Game.GraphicsDevice.Viewport.Height.

Queste informazioni vengono utilizzate poi per creare la projection matrix: questa matrice serve a definire come viene presentato a schermo quello che viene renderizzato nella scena. Gli ultimi due parametri numerici sono il nearPlane e il farPlane. Indicano i limiti di quanto è possibile vedere: cioè tutto quello che risulterà distante dalla telecameta e tra nearPlane e farPlane sarà visibile.
Come si può vedere gli passiamo anche l'aspectRatio calcolato prima.
L'ultimo parametro, quello con "out", definisce in quale variabile andrà a finire il risultato.

La view matrix identifca la telecamera, e ci serve a definire in quale punto siamo, cosa stiamo osservando, e dove si trova la direzione dell'alto. Come si vede per calcolarla si utilizza le tre variabili definite prima.

Per ora la telecamera è fissa, cioè non si muove, non cambia punto di osservazione... Nulla un punto fisso.
Questo è il più semplice tipo di telecamera che si piò creare. Si potrà poi utilizzare questa classe come base per ereditare altri tipi di telecamere.

Per poterla utilizzare, nel costruttore di Game1.cs si deve creare un oggetto di tipo camera ed aggiungerlo alla collezione dei components.

Torniamo un attimo al costruttore della telecamera, ed osserviamo questa riga:
game.Services.AddService(typeof(CameraI), this);
Che cosa fa?
Be con l'FPSCounter avevamo visto come creare un component ed aggiungerlo alla collezione dei Components in modo che poi venisse gestito in automatico.
Quello che faccio ora è creare un servizio: un servizio è un componente che implementa un'interfaccia. Tramite questa interfaccia possiamo poi riferire il servizio ed accedere al servizio stesso tramite i metodi e le proprietà definite dall'interfaccia.
C'è da dire però che ci deve essere nei Services un solo oggetto che implementa una certa interfaccia. Quindi non posso aggiungere due gestori per la camera che implementano la CameraI, dato che poi non sapremo come recupere l'uno o l'altro. Se voglio aggiungere due telecamere diverse i due oggetti devono implementare due interfacce diverse.
Per aggiungerlo alla collezione dei servizi dobbiamo prima di tutto accedere tramite l'oggetto game alla collezione dei servizi, e poi gli dobbiamo dire di che tipo considerare l'oggetto che stiamo aggiungendo (in questo caso come un tipo CameraI) e l'oggetto da aggiungere (in questo caso l'oggetto che stiamo costruendo e quindi this).
Vediamo infatti che la notra classe implementa l'interfaccia CameraI, la quale definisce delle proprietà che andranno a recuperare i valori della projection e della view matrix.
Quando in un altro punto del nostro gioco andremo a recuperare il riferimento al servizio che implementa la CameraI andremo a recuperare il riferimento del solito oggetto, e quindi andremo a recuperare sempre le stesse informazioni.

Per ora finisco qui.
La prossima volta vedrò di dire come si può creare un componente che si occupa di caricare e renderizzare nella scena un oggetto tridimensionale, e come recueperare il riferimento al servizio della camera appena creato ed aggiunto.

Questa volta niente sorgenti, dato che ho messo il file completo nel post :)
Spero di essere stato chiaro.
Se qualcosa è spiegato frettolosamente o in malo modo ditelo e provvederò a correggere! :D

Ciau! Alla prossima!

0 commenti:

Donazioni

My Menu'