Pregunta

He estado luchando con esto durante un buen tiempo. Estoy tratando de determinar las coordenadas de pantalla de los vértices en un modelo en la pantalla de mis NDS utilizando devkitPro. La biblioteca parece poner en práctica algunas funciones de OpenGL, pero en particular, la función gluProject falta, lo que (supongo) me permite hacer exactamente eso, fácilmente.

He tratado por un buen tiempo ahora para calcular las coordenadas de la pantalla de forma manual utilizando las matrices de proyección que se almacenan en los registros de la DS, pero no he estado teniendo mucha suerte, incluso cuando se trata de construir la matriz de proyección de rayar sobre la base de la documentación de OpenGL. Aquí está el código que estoy tratando de usar:

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);

} 

Hay un montón de cambios implicados, el DS funciona internamente usando la notación de punto fijo y necesito convertir a que se duplica para trabajar. Lo que estoy recibiendo parece ser algo correct-- los píxeles se traducen perfectamente si estoy usando un quad plana que está frente a la pantalla, pero la rotación es poco firme. También, ya voy por la matriz de proyección (que representa la pantalla de anchura / altura?) Los últimos pasos Estoy realmente interesado en la utilización No parece justo en absoluto. ¿No debería ser la proyección Matrix logrando el salto a la resolución de pantalla para mí?

Soy bastante nuevo en todo esto, tengo una idea justa en las matemáticas de matriz, pero no estoy tan hábil como me gustaría estar en gráficos 3D. ¿Alguien aquí sabe de alguna manera, dado el 3D, las coordenadas de los vértices de un modelo no transformada, y también teniendo en cuenta las matrices de los cuales serán aplicados a la misma, para venir en realidad con las coordenadas de la pantalla, sin necesidad de utilizar la función gluProject de OpenGL? ¿Puede usted ver algo claramente evidente que me falta en mi código? (Voy a aclarar cuando sea posible, sé que es difícil, este es un prototipo que estoy trabajando, la limpieza no es una prioridad alta)

Gracias un montón!

PD: Como lo entiendo, currentMatrix, que me tire de los registros de la DS, debe Me puede dar la proyección, traducción y matriz de rotación combinado, como debe ser la matriz exacto que está pasando que se utilizará para la traducción por propio hardware de la DS, al menos de acuerdo a las especificaciones en GBATEK. En la práctica, no parece que en realidad tienen las coordenadas de proyección que se le aplican, que supongo que tiene algo que ver con mis problemas. Pero no estoy seguro, ya que el cálculo de la proyección mismo no está generando resultados diferentes.

¿Fue útil?

Solución

Eso es casi correcta.

Los pasos correctos son:

  • Multiplicar Modelview con la matriz de proyección (como ya ha hecho).

  • Amplíe su vértice 3D a un coordenadas homogéneas mediante la adición de una W-componente con el valor 1. Por ejemplo, su (x, y, z)-vector se convierte en (x, y, z, w) con w = 1.

  • Multiplicar este vector con el producto de la matriz. Su matriz debe ser 4x4 y su vector de tamaño 4. El resultado será un vector de size4 así (no deje caer w todavía!). El resultado de esta multiplicación es su vector de clip-espacio. FYI: Ya se puede hacer un par de cosas muy útiles aquí con este vector: Prueba si el punto está en la pantalla. Las seis condiciones son:

    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)
  • Proyecto su punto en el espacio 2D. Para ello divide x e y por w:
  x' = x / w;
  y' = y / w;
  • Si está interesado en la profundidad del valor (por ejemplo, que escribe la entrada a la ZBuffer) que se pueda proyectar z así:
 z' = z / w
  • Tenga en cuenta que el paso anterior no funcionará si w es cero. Este caso happends si el punto es igual a la posición de la cámara. Lo mejor que podría hacer en este caso es establecer x 'e y' a cero. (Moverá el punto en el centro de la pantalla en el paso siguiente ..).

  • Paso final: Obtener el visor OpenGL coordenadas y aplicarlo:

  x_screen = viewport_left + (x' + 1) * viewport_width  * 0.5;
  y_screen = viewport_top  + (y' + 1) * viewport_height * 0.5;
  • Importante: La coordenada y de la pantalla puede ser al revés. Contrariamente a la mayoría de otras APIs gráficas en OpenGL y = 0 denota la parte inferior de la pantalla.

Eso es todo.

Otros consejos

Voy a añadir algunos pensamientos más a fondo a la respuesta Nils'.

  1. No utilice dobles. No estoy familiarizado con NDS, pero dudo que tiene cualquier hardware de doble matemáticas.
  2. También dudan de vista del modelo y la proyección no estén ya multiplicados si están leyendo los registros de hardware. Todavía tengo que ver una plataforma de hardware que no utiliza el MVP completa en los registros directamente.
  3. el almacenamiento matriz en registros puede o puede no estar en el mismo orden que OpenGL. si no lo son, las necesidades multiplicación de la matriz-vector por hacer en el otro orden.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top