2012-05-07 5 views
2

J'utilise XNA 4.0 et j'essaie de prendre un Vector3 et de le transformer en Vector2 qui représente ses coordonnées sur l'écran. Je sais que vous pouvez utiliser Viewport.Project et cela me donne des résultats parfaits, mais j'ai besoin de faire ma propre méthode pour le faire. Je dois convertir chaque vertex en coordonnées 2D par trame et sur CPU au lieu de GPU. L'utilisation de la méthode Project fournie est un peu plus lente que ce que je souhaiterais. Il renvoie également une valeur "z" que je n'utiliserai même pas. Je veux juste retourner un (x, y) de la manière la plus simple possible.Projeter le vecteur 3D vers les coordonnées de l'écran 2D

Voici ce que j'ai trouvé jusqu'à présent, et il donne des résultats presque corrects. Mais pas tout à fait encore là

private Vector2 ScreenCoords(Vector3 v) 
    { 
     return new Vector2(
      viewProj.M11 * v.X + viewProj.M21 * v.Y + viewProj.M31 * v.Z + viewProj.M41, 
      viewProj.M12 * v.X + viewProj.M22 * v.Y + viewProj.M32 * v.Z + viewProj.M42); 
    } 

viewProj est juste (viewMatrix * ProjectionMatrix)

Un sommet au centre de l'écran semble toujours revenir (0, 0) mais je reçois des résultats légèrement foiré comme le vertex change les coordonnées de l'écran (comme je déplace la caméra) Lorsque le vertex se déplace à gauche, le X de mon résultat projeté diminue, et lorsque le vertex descend, le Y du résultat projeté augmente. Donc, au moins, j'ai ce droit, mais le taux auquel ils changent n'est pas correct ou cohérent.

EDIT: voici comment il est fait, sans doute le meilleur moyen de le faire (notez que cela renvoie les coordonnées dans l'intervalle [-1, 1])

private Vector2 ScreenCoords(Vector3 v) 
    { 
     float 
      w = viewProj.M14 * v.X + viewProj.M24 * v.Y + viewProj.M34 * v.Z + viewProj.M44; 
     return new Vector2(
      (viewProj.M11 * v.X + viewProj.M21 * v.Y + viewProj.M31 * v.Z + viewProj.M41)/w, 
      (viewProj.M12 * v.X + viewProj.M22 * v.Y + viewProj.M32 * v.Z + viewProj.M42)/w);   
    } 

Voici une comparaison à l'utilisation Viewport .project pour obtenir les coordonnées 2D -
FPS avec Project - 81
FPS avec ScreenCoords - 143
FPS sans un ou l'autre - 152
Je recommande donc quelque chose comme ça pour quelqu'un d'autre qui fait beaucoup de projection par image .

Répondre

2

Vous devez réaliser que les projections en perspective ont besoin homogeneus coordonnées, vous devez diviser

les composants par le facteur de homegeneus W.

Voici le calcul:

Vector4 position = new Vector4(pos3, 1); 
Vector4.Transform(ref position, ref worldViewProjection, out position); 
position /= position.W; 

vous pouvez également trouver plus info ici: http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection

+0

Cela m'a eu ce dont j'avais besoin merci! J'essaie d'éviter d'utiliser des choses comme transformer et projeter, et obtenir la réponse en utilisant mes propres calculs, mais cela m'a permis d'y arriver. Publier la nouvelle méthode au plus haut niveau, n'importe qui le veut. – Frobot

+0

Est-ce bon de savoir ce qui est derrière les mathématiques, mais je pense que cette transformation est utilisée pour être plus efficace dans le shader. – Blau

+0

Oui et la transformée obtient également la valeur pour ce pixel dans le z-buffer qui est une partie que je découpe car je n'en aurai pas besoin. J'espère que je peux implémenter tout mon algorithme dans un shader et que je n'aurai même plus besoin de trouver les coordonnées de l'écran 2D sur le CPU et ça sera BEAUCOUP plus rapide – Frobot

Questions connexes