Domanda

ho lottato con questo per un bel po 'ormai. Sto cercando di determinare le coordinate dello schermo dei vertici in un modello sullo schermo del mio NDS utilizzando devkitPro. La biblioteca sembra implementare alcune funzionalità di OpenGL, ma in particolare, la funzione gluProject manca, il che (suppongo) mi permette di fare esattamente questo, facilmente.

Ho cercato per un bel po 'ormai per calcolare la schermata coordinate manualmente utilizzando i da matrici di proiezione che vengono memorizzati nei registri del DS, ma io non sto avendo molta fortuna, anche quando si cerca di costruire la matrice di proiezione da graffiare sulla base della documentazione di OpenGL. Qui è il codice che sto cercando di utilizzare:

void get2DPoint(v16 x, v16 y, v16 z, float &result_x, float &result_y)
{
 //Wait for the graphics engine to be ready
 /*while (*(int*)(0x04000600) & BIT(27))
  continue;*/

 //Read in the matrix that we're currently transforming with
 double currentMatrix[4][4]; int i; 
 for (i = 0; i < 16; i++)
  currentMatrix[0][i] = 
  (double(((int*)0x04000640)[i]))/(double(1<<12));

 //Now this hurts-- take that matrix, and multiply it by the projection matrix, so we obtain
 //proper screen coordinates.
 double f = 1.0 / tan(70.0/2.0);
 double aspect = 256.0/192.0;
 double zNear = 0.1;
 double zFar = 40.0;
 double projectionMatrix[4][4] = 
 {
  { (f/aspect), 0.0, 0.0, 0.0 },
  { 0.0, f, 0.0, 0.0 },
  { 0.0, 0.0, ((zFar + zNear) / (zNear - zFar)), ((2*zFar*zNear)/(zNear - zFar)) },
  { 0.0, 0.0, -1.0, 0.0 },
 };

 double finalMatrix[4][4];
 //Ugh...
 int mx = 0; int my = 0;
 for (my = 0; my < 4; my++)
  for (mx = 0; mx < 4; mx++)
   finalMatrix[mx][my] = 
   currentMatrix[my][0] * projectionMatrix[0][mx] + 
   currentMatrix[my][1] * projectionMatrix[1][mx] + 
   currentMatrix[my][2] * projectionMatrix[2][mx] + 
   currentMatrix[my][3] * projectionMatrix[3][mx] ;

 double dx = ((double)x) / (double(1<<12));
 double dy = ((double)y) / (double(1<<12));
 double dz = ((double)z) / (double(1<<12));

 result_x = dx*finalMatrix[0][0] +  dy*finalMatrix[0][1] + dz*finalMatrix[0][2] + finalMatrix[0][3];
 result_y = dx*finalMatrix[1][0] +  dy*finalMatrix[1][1] + dz*finalMatrix[1][2] + finalMatrix[1][3];

 result_x = ((result_x*1.0) + 4.0)*32.0;
 result_y = ((result_y*1.0) + 4.0)*32.0;


 printf("Result: %f, %f\n", result_x, result_y);

} 

Ci sono un sacco di turni coinvolti, il DS funziona internamente utilizzando la notazione punto fisso e ho bisogno di convertire in doppio con cui lavorare. Quello che sto ricevendo sembra essere un po correct-- i pixel vengono convertiti perfettamente se sto usando un quad piatta che sta di fronte allo schermo, ma la rotazione è wonky. Inoltre, dal momento che sto andando dalla matrice di proiezione (che rappresenta la larghezza / altezza dello schermo?) Gli ultimi passi che sto che hanno bisogno di utilizzare non sembrano affatto giusto. non dovrebbe la matrice di proiezione sia realizzando il passo fino a risoluzione dello schermo per me?

Sono piuttosto nuovo a tutto questo, ho una conoscenza fiera su matrice matematica, ma io non sono come abile come mi piacerebbe essere in grafica 3D. C'è qualcuno qui sa un modo, date le coordinate 3D, non trasformate dei vertici di un modello, e anche dato i da matrici che saranno applicati ad esso, in realtà a venire su con le coordinate dello schermo, senza utilizzare la funzione gluProject di OpenGL? Riuscite a vedere qualcosa di palesemente evidente che mi manca nel mio codice? (Io chiarire quando possibile, so che è di massima, questo è un prototipo su cui sto lavorando, la pulizia non è una priorità)

Grazie un mazzo!

PS: A quanto mi risulta, currentMatrix, che mi tiro dai registri del DS, dovrebbe essere avermi dato la proiezione combinata, la traduzione, e matrice di rotazione, come dovrebbe essere la matrice esatto che sta succedendo da utilizzare per la traduzione dal proprio hardware del DS, almeno secondo le specifiche a GBATEK. In pratica, non sembra avere in realtà la proiezione coordinate applicato ad esso, che suppongo abbia a che fare con i miei problemi. Ma non sono sicuro, come calcolare la proiezione me non sta generando risultati diversi.

È stato utile?

Soluzione

Questo è quasi corretto.

I passi corretti sono:

  • Moltiplica Modelview con matrice di proiezione (come hai già fatto).

  • estendere tuo vertice 3D di un coordinate omogenee aggiungendo un W-componente con valore 1. esempio il (x, y, z) -vettore diventa (x, y, z, w) con w = 1.

  • Moltiplicare questo vettore con il prodotto matriciale. La vostra matrice dovrebbe essere 4x4 e il vostro vettore di dimensione 4. Il risultato sarà un vettore di size4 così (non far cadere w ancora!). Il risultato di questa moltiplicazione è il vostro vettore di clip-spazio. FYI: Si può già fare un paio di cose molto utili qui con questo vettore: Verifica se il punto è sullo schermo. Le sei condizioni sono:

    x < -w : Point is outside the screen (left of the viewport)
    x >  W : Point is outside the screen (right of the viewport)
    y < -w : Point is outside the screen (above the viewport)
    y >  w : Point is outside the screen (below the viewport)
    z < -w : Point is outside the screen (beyond znear)
    z >  w : Point is outside the screen (beyond zfar)
  • Progetto tuo punto nello spazio 2D. Per fare questo divario x e y da w:
  x' = x / w;
  y' = y / w;
  • Se siete interessati nella profondità valore (ad esempio, ciò che viene scritto al Zbuffer) è possibile proiettare z così:
 z' = z / w
  • Si noti che il passo precedente non funziona se w è zero. Questo caso happends se il punto è uguale alla posizione della telecamera. Il meglio che si possa fare in questo caso è quello di impostare x 'e y' a zero. (Si spostare il punto al centro dello schermo nel passaggio successivo ..).

  • Passo finale: ottenere le coordinate viewport OpenGL e applicarlo:

  x_screen = viewport_left + (x' + 1) * viewport_width  * 0.5;
  y_screen = viewport_top  + (y' + 1) * viewport_height * 0.5;
  • Importante: La coordinata y dello schermo può essere a testa in giù. Contrariamente alla maggior parte degli altri API grafiche in OpenGL y = 0 indica la parte inferiore dello schermo.

Questo è tutto.

Altri suggerimenti

io aggiungo qualche altro pensiero a risposta esauriente Nils'.

  1. non utilizzare doppie. Non ho familiarità con NDS, ma dubito è avuto alcun hardware per la doppia matematica.
  2. Dubito anche vista del modello e la proiezione non sono già moltiplicati se si sta leggendo i registri hardware. Devo ancora vedere una piattaforma hardware che non utilizza appieno MVP nei registri direttamente.
  3. stoccaggio matrice in registri può o non può essere nello stesso ordine OpenGL. se non lo sono, la moltiplicazione matrice-vettore deve essere fatto in altro ordine.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top