Question

J'ai eu du mal avec cela pour un bon moment maintenant. Je suis en train de déterminer les coordonnées d'écran des vertex dans un modèle sur l'écran de mon NDS à l'aide devkitPro. La bibliothèque semble mettre en œuvre certaines fonctionnalités d'OpenGL, mais en particulier, la fonction gluProject manque, qui (je suppose) me permettre de faire exactement cela, facilement.

Je l'ai essayé pendant un bon moment maintenant pour calculer l'écran les coordonnées manuellement à l'aide des projections matricies qui sont stockés dans les registres de la DS, mais je ne l'ai pas eu beaucoup de chance, même en essayant de construire la matrice de projection de gratter basée sur la documentation OpenGL. Voici le code que je suis en train d'utiliser:

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

} 

Il y a beaucoup de changements impliqués, la DS fonctionne en utilisant la notation interne point fixe et je dois convertir en double pour travailler avec. Ce que je veux semble être un peu correct-- les pixels sont traduits parfaitement si j'utilise un quad plat qui est face à l'écran, mais la rotation est bancale. En outre, depuis que je vais par la matrice de projection (qui représente la largeur de l'écran / hauteur?) Les dernières étapes je besoin d'utiliser ne semblent pas bien du tout. Ne doit pas la matrice de projection accomplirez l'étape jusqu'à la résolution de l'écran pour moi?

Je suis assez nouveau à tout cela, j'ai une connaissance juste sur les mathématiques de la matrice, mais je ne suis pas aussi doué que je voudrais être dans les graphiques 3D. Est-ce que quelqu'un sait ici une certaine façon, compte tenu de la 3D, les coordonnées non transformées des vertex d'un modèle, et aussi compte tenu des matricies qui sera appliquée, pour venir réellement avec les coordonnées de l'écran, sans utiliser la fonction gluProject OpenGL? Pouvez-vous voir quelque chose que tout à fait évident que je manque dans mon code? (Je vais préciser, si possible, je sais qu'il est difficile, c'est un prototype je travaille, la propreté est pas une priorité élevée)

Merci un groupe!

PS: Si je comprends bien, currentmatrix, que je tire des registres de DS, devrait me donnera la projection combinée, la traduction et la matrice de rotation, comme cela devrait être la matrice exacte qui va à utiliser pour la traduction par le propre matériel du DS, au moins selon les spécifications à GBATEK. Dans la pratique, il ne semble pas avoir fait la projection des coordonnées appliquée, que je suppose a quelque chose à voir avec mes problèmes. Mais je ne suis pas sûr, comme le calcul de la projection moi-même ne génère pas de résultats différents.

Était-ce utile?

La solution

C'est presque correct.

Les étapes correctes sont:

  • Multiplier avec la matrice de modèle-vue projection (comme vous l'avez déjà fait).

  • Elargir sommet 3D à une coordonnée homogène par addition d'un composant de W avec la valeur 1. Par exemple, le (x, y, z) -vector devient (x, y, z, w) avec w = 1.

  • Multipliez ce vecteur avec le produit de la matrice. Votre matrice doit être 4x4 et votre vecteur de taille 4. Le résultat sera un vecteur de size4 aussi bien (ne laissez pas tomber w encore!). Le résultat de cette multiplication est votre vecteur dans l'espace clip. Pour votre information: Vous pouvez déjà faire quelques choses très utiles ici avec ce vecteur: Test si le point est à l'écran. Les six conditions sont les suivantes:

    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)
  • Projet votre point dans l'espace 2D. Pour ce faire, diviser x et y par w:
  x' = x / w;
  y' = y / w;
  • Si vous êtes intéressé par la valeur de profondeur (par exemple ce qui sera écrit à la zbuffer) vous pouvez projeter z ainsi:
 z' = z / w
  • Notez que l'étape précédente ne fonctionnera pas si w est égal à zéro. Ce cas happends si votre point est égale à la position de la caméra. Le mieux que vous pouvez faire dans ce cas est de mettre x « et y » à zéro. (Se déplacera le point dans le centre de l'écran à l'étape suivante ..).

  • Etape finale: Obtenir les coordonnées viewport OpenGL et l'appliquer:

  x_screen = viewport_left + (x' + 1) * viewport_width  * 0.5;
  y_screen = viewport_top  + (y' + 1) * viewport_height * 0.5;
  • Important: La coordonnée y de votre écran peut être à l'envers. Contrairement à la plupart des autres API graphiques en OpenGL y = 0 représente le bas de l'écran.

C'est tout.

Autres conseils

Je vais ajouter quelques réflexions à réponse complète de Nils.

  1. ne pas utiliser double. Je ne suis pas familier avec NDS, mais je doute que ça a tout le matériel pour le double calcul.
  2. Je doute aussi vue du modèle et la projection ne sont pas déjà multipliés si vous lisez les registres matériels. Je dois encore voir une plate-forme matérielle qui n'utilise pas le plein MVP dans les registres directement.
  3. le stockage de la matrice dans des registres peut ou peut ne pas être dans le même ordre que OpenGL. si elles ne sont pas, la matrice vecteur de multiplication doit être fait dans l'autre ordre.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top