2011-10-07 12 views
12

tempo per un po 'di matematica per la fine del giorno ..OpenGL Math - Proiezione spazio sullo schermo allo spazio mondo coordinate

ho bisogno di proiettare 4 punti del formato della finestra:

< 0,0> < 1024,768>

in uno spazio mondo coordinate modo si formerà una forma quadrilatera che verrà successivamente utilizzato per l'abbattimento del terreno - senza GluUnproject

Per la prova unica, ho utilizzare le coordinate del mouse - e cercare di proiettarli sul mondo coords

+1

non è la dimensione della finestra irrilevante? la forma/aspetto sicuramente, ma quello che cerchi è la forma rettangolare conica specifica delle forme di visualizzazione della videocamera, giusto? – Breton

+0

ho trovato qualcosa di interessante http://collagefactory.blogspot.com/2010/03/gluunproject-source-code.html – YAHOOOOO

+0

Breton, la cosa che sto cercando è costruire un 'bounding box' dalla vista della telecamera che io usa in seguito per trovare quali celle del terreno sono "dentro" così posso renderle. Quindi ho bisogno di sapere dove sono in alto a sinistra, in alto a destra, in basso a sinistra e in basso a destra nello spazio del mondo 3d in modo da poter trovare più tardi le cellule del terreno che si trovano all'interno di questo intervallo. – PeeS

risposta

28

RISOLTO

Ecco come fare esattamente, passo dopo passo.

0) Ottieni i tuoi coordinate del mouse all'interno dell'area client

1) Ottenere il vostro matrice e Vista matrice di proiezione, se non a matrice modello richiesto.

2) Moltiplicare proiezione * Vedi

3) Inverse i risultati delle moltiplicazioni

4) Costruire una vector4 costituito da

x = mouseposition.x raggio di finestra x - trasformare a valori compresi tra -1 e 1

y = mouseposition.y in un intervallo di finestre y - Trasforma in valori compresi tra -1 e 1 - ricordarsi di invertire la posizione.y se necessario

z =the depth value (questo può essere ottenuto con glReadPixel) - si può andare manualmente da -1 a 1 (zNear, zFar)

w = 1.0

5) Moltiplicare il vettore per matrice inversa creato prima

6) Dividere il vettore risultato dalla sua componente w dopo la moltiplicazione della matrice (divisione prospettica)

 POINT mousePos; 
     GetCursorPos(&mousePos); 
     ScreenToClient(this->GetWindowHWND(), &mousePos);   

     CMatrix4x4 matProjection = m_pCamera->getViewMatrix() * m_pCamera->getProjectionMatrix() ; 

     CMatrix4x4 matInverse = matProjection.inverse(); 


     float in[4]; 
     float winZ = 1.0; 


     in[0]=(2.0f*((float)(mousePos.x-0)/(this->GetResolution().x-0)))-1.0f, 
     in[1]=1.0f-(2.0f*((float)(mousePos.y-0)/(this->GetResolution().y-0))); 
     in[2]=2.0* winZ -1.0; 
     in[3]=1.0;   

     CVector4 vIn = CVector4(in[0],in[1],in[2],in[3]); 
     pos = vIn * matInverse; 

     pos.w = 1.0/pos.w; 

     pos.x *= pos.w; 
     pos.y *= pos.w; 
     pos.z *= pos.w; 



     sprintf(strTitle,"%f %f %f/%f,%f,%f ",m_pCamera->m_vPosition.x,m_pCamera->m_vPosition.y,m_pCamera->m_vPosition.z,pos.x,pos.y,pos.z); 

     SetWindowText(this->GetWindowHWND(),strTitle); 
+0

Si può semplicemente pos.x/= pos.w – RobotRock

+2

perché si calcola la proiezione con viewMatrix * projectMatrix invece di projectMatrix * viewMatrix? –

2

Se si ha accesso alle biblioteche GLU, utilizzare gluUnProject (Winx, vinoso, Winz, il modello, la proiezione, finestra, & objX, & objY, & objZ);

winX e winY saranno gli angoli dello schermo in pixel. winZ è un numero in [0,1] che specificherà dove tra zNear e zFar (piani di ritaglio) i punti dovrebbero cadere. objX-Z manterrà i risultati. Le variabili medie sono le matrici rilevanti. Possono essere interrogati se necessario.

+0

Sì, mi dispiace per quello, non ho detto che non voglio usare gluunproject - ho bisogno di operare solo su matrici. – PeeS

+0

@PeeS Ma la documentazione collegata spiega l'implementazione di gluUnProject e, dato che è estremamente semplice, puoi semplicemente scriverlo da solo. Vedi la risposta di crazyjul. –

+0

Grazie, ora sto cercando di implementarlo. – PeeS

7

Moltiplica tutte le tue matrici. Quindi inverti il ​​risultato. I punti dopo la proiezione sono sempre in -1,1. Quindi i quattro punti dello schermo d'angolo sono -1, -1; -1,1; 1, -1; 1,1. Ma devi ancora scegliere il valore z. Se siete in OpenGL, z è compreso tra -1 e 1. Per directx, la gamma va da 0 a 1. Infine prendere i punti e trasformarli con la matrice

+0

Questo è quello che faccio in realtà, Faccio una proiezione moltiplicativa matrice MVP * (Visualizza * modello) Quindi io inverso quello, guarda sopra (aggiornato il primo post) - forse c'è qualcosa che mi manca nella Z valore..? – PeeS

+0

@PeeS Al momento la tua z è -3, sono sicuro che questo non è inteso, dato che z deve essere in [-1,1] (forse vuoi solo -1?). Il resto sembra ragionevole, ma non dimenticare di invertire 'source.y' se il sistema di coordinate della finestra sta andando dall'alto verso il basso. E spero che 'VectorMatrixMultiply' assuma implicitamente un 1 per il componente w, e non uno 0. –

+0

Christian, grazie ora sto correggendo ciò che hai indicato, e inoltre ho aggiornato il post principale con il metodo' CMatrix4x4 operator * ', quindi puoi dare un'occhiata se è ok - in quanto questa classe non è mia, e non so se posso fidarmi di questa situazione. – PeeS

Problemi correlati