Sprite 2D su coordinate 3D

Se vi state chiedendo a cosa possa servire un metodo del genere, provate a pensare ad un qualsiasi gioco dove appaiono delle barre d'energia sopra a dei personaggi che si muovono su uno spazio tridimensionale, tipo su strategico in tempo reale, oppure al numero di punti ferita tolti ad un nemico su un gioco di ruolo in prospettiva isometrica oppure al classico sprite o numeretto che identifica il giocatore che state usando su un gioco di calcio..

barre energia
sprite 2D

  


Quelli che vedete sono in pratica, degli sprite 2D che seguono un modello 3D.
Per fare questo è necessario un semplice metodo che trasforma le coordinare di un Vector3 in coordinate su schermo, dunque da Vector3 a Vector2.
Vi propongo ora un metodo pronto all'uso che richiede un parametro di tipo Vector3 in entrata e che ci restituirà un Vector2 in uscita.

Per "incollare" lo sprite 2D su un oggetto 3D dovremmo trovare la posizione Vector2 sullo schermo che occupa il modello.
Il metodo in questione ci restituisce proprio questo, ovvero la posizione sullo schermo di un oggetto 3D. Dunque potrà tornare utile anche in altre occasioni.


       
Vector2 posiziona_imm(Vector3 posizione)
        {
            //Calcolo la ViewProjMatrix semplicemente moltiplicando le due matrici View e Projection
           Matrix ViewProjMatrix = ViewMatrix * ProjMatrix;

            //Trasformo le coordinate 3D in 2D su schermo in base ViewProjMatrix
            Vector4 source = Vector4.Transform(posizione, ViewProjMatrix);

            //Calcoliamo il punto sullo schermo in cui si trova il Vector3 posizione
          Vector2 posizione2D = new Vector2( (int)((source.X / source.W + 1f) / 2f * m_graphicsMgr.PreferredBackBufferWidth),
                                             (int)((-source.Y / source.W + 1f) / 2f * m_graphicsMgr.PreferredBackBufferHeight));

            //Mettiamo in uscita il Vector2 appena trovato
            return posizione2D;
        }


.
Riassumiamo le variabili che abbiamo usato:
ViewProjMatrix
è la moltiplicazione delle solite matrici View e Projection della nostra telecamera.
m_graphicsMgr.PreferredBackBufferWidth e m_graphicsMgr.PreferredBackBufferHeight rappresentano larghezza e altezza dello schermo (m_graphicsMgr è il nostro GraphicDeviceManager) .
posizione è il Vector3 che rappresenta le coordinate 3D dell'oggetto.
pos_imm è il Vector2 in uscita che rappresenta la posizione dell'oggetto sullo schermo.

Ora potremmo "attaccare" un'immagine a qualunque oggetto del nostro mondo 3D! Bello no?

(Ringrazio dsoft20 per l'idea del vettore in uscita :) ).