Proiezione di un oggetto tridimensionale su una superfice a due dimensioni

Proiezione
Il mondo è tridimensionale, ma i mezzi che abbiamo a disposizione per visualizzarlo funzionano a 2 dimensioni (ad esempio l'occhio).
Il mondo virtuale 3d si comporta esattamente alla stessa maniera e il monitor (il nostro "occhio virtuale") soffre del medesimo "difetto", viaggia a una dimensione in meno.
Tutti gli oggetti 3d devono quindi essere proiettati sulla superficie 2d dello schermo per essere visualizzati correttamente. Questo processo viene chiamato proiezione appunto, e viene eseguito numerose volte al secondo in modo da far apparire il movimento di tutti questi oggetti proiettati il più fluido possibile.
I primi videogames 3d calcolavano con semplici operazioni matematiche ogni singolo pixel dello schermo utilizzando il processore. Col l'evoluzione che hanno subito questi tipi di giochi si è passato all’affinamento degli algoritmi di calcolo e l'utilizzo di cpu dedicate sulle schede video (GPU) studiate appositamente per eseguire più velocemente calcoli di questo tipo.
La GPU non si occupa solo si renderizzare il risultato, ma esegue anche tutti i calcoli necessari alla trasformazione da 2d a 3d. Sono due le tecniche fondamentali che permettono questa operazione: il vertex shader che trasforma tutti i punti (vertici) che compongono la struttura dell'oggetto 3d in coordinate dello schermo e il pixel shader che si occupa di "vestire" questa proiezione elaborando l'origine sempre a favore dei pixel dello schermo. 



Come si può vedere dall'immagine esistono tre attori fondamentali in questo contesto:

  1.   Il punto di vista (il punto da cui vengono "visti" gli oggetti proiettati)
  2.   E il piano di proiezione (la superficie del monitor)
  3.   Il mondo 3d (tutti gli oggetti 3d nel campo visivo)


Per rappresentare questo scenario in XNA possiamo procedere come segue:

1) Con l'ausilio dell'oggetto Matrix del framework XNA creiamo un punto di vista:

Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(20f, 15f, 0f), Vector3.Zero, Vector3.Up);

  • Il primo parametro è un vettore a 3 dimensioni che specifica i 3 valori delle coordinate X Y e Z (in sostanza la posizione) del punto di vista.
  • Il secondo un vector3 che indica la posizione verso cui è rivolta la visuale (nella figura 1 è rappresentata dalla punta della freccia rossa centrale che finisce oltre l'oggetto 3D)
  • Il terzo indica la posizione del verso "alto" della punto di vista (per un settaggio normale un vector3.up = new vector(0f, 1f, 0f) mentre un new vector3(0f, -1f, 0f) per una visuale capovolta orizzontalmente)

2) Sempre grazie all'oggetto Matrix creiamo un piano di visualizzazione a 2 dimensioni su cui verranno "proiettati" gli oggetti 3D   
Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f), (640.0f / 480.0f), 10.0f, 10000.0f);

  • Nel primo argomento si definisce la distanza del piano di proiezione
  • il secondo le proporzioni del piano (larghezza / altezza - permette quindi di stabilire il formato di visualizzazione 4/3, 16/9, etc. )
  • il terzo e il quarto sono rispettivamente il limite minimo e massimo di renderizzazione (il primo spesso usato per evitare che oggetti troppo vicini occupino tutta l'area di visualizzazione e il secondo per limitare la renderizzazione di oggetti superflui considerevolmente "lontani" rispetto al piano di visualizzazione a salvaguardia delle prestazioni)

3) Altra matrice per definire la matrice di "manipolazione" degli oggetti 3D che compongono il nostro world.
Matrix worldMatrix = Matrix.CreateRotationY(10f);

 

  • In questo caso abbiamo deciso di operare una sola rotazione dell'asse Y del world, ma le operazioni applicabili sono svariate.

una volta impostati questi parametri, è sufficiente istruire con essi le proprietà di un oggetto che si occuperà di renderizzare il tutto, come uno di tipo BasicEffect (sfruttando come detto in precedenza le potenzialità dell'hardware della scheda video).

...
BasicEffect effect = new BasicEffect(graphicsDevice, effectPool);
...
protected override void Draw(GameTime gameTime)
{
...

effect.View = viewMatrix;
effect.Projection = projectionMatrix;
effect.World = worldMatrix;

...
}

Print | posted on mercoledì 17 ottobre 2007 03:51

Comments have been closed on this topic.

Copyright © Paolo Bragonzi

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski