2011-10-08 15 views
2

Utilisation de Monotouch et d'OpenTK J'essaie d'obtenir les coordonnées de l'écran d'un point 3D. J'ai ma matrice de projection vue du monde, et OpenGL a du sens et projette parfaitement mon modèle 3D, mais comment utiliser la même matrice pour projeter un seul point de la 2D à la 3D?Projection d'un point 3D vers une coordonnée d'écran 2D OpenTK

Je pensais que je pourrais simplement utiliser:

Vector3.Transform(ref input3Dpos, ref matWorldViewProjection, out projected2Dpos); 

Ensuite ont l'écran de coordonnées projetées dans projected2DPos. Mais le Vector4 résultant ne semble pas représenter la coordonnée d'écran projetée appropriée. Et je ne sais pas comment calculer à partir de là.


J'ai trouvé que je devais diviser par Vector4.w, mais je reçois toujours les mauvaises valeurs. En utilisant cette méthode maintenant:

private static bool GluProject(OpenTK.Vector3 objPos, OpenTK.Matrix4 matWorldViewProjection, int[] viewport, out OpenTK.Vector3 screenPos) 
{ 
    OpenTK.Vector4 _in; 

    _in.X = objPos.X; 
    _in.Y = objPos.Y; 
    _in.Z = objPos.Z; 
    _in.W = 1f; 

    Vector4 _out = OpenTK.Vector4.Transform(_in, matWorldViewProjection); 

    if (_out.W <= 0.0) 
    { 
     screenPos = OpenTK.Vector3.Zero; 
     return false; 
    } 

    _out.X /= _out.W; 
    _out.Y /= _out.W; 
    _out.Z /= _out.W; 
    /* Map x, y and z to range 0-1 */ 
    _out.X = _out.X * 0.5f + 0.5f; 
    _out.Y = -_out.Y * 0.5f + 0.5f; 
    _out.Z = _out.Z * 0.5f + 0.5f; 

    /* Map x,y to viewport */ 
    _out.X = _out.X * viewport[2] + viewport[0]; 
    _out.Y = _out.Y * viewport[3] + viewport[1]; 

    screenPos.X = _out.X; 
    screenPos.Y = _out.Y; 
    screenPos.Z = _out.Z; 

    return true; 
} 

je ne vois aucune erreur mais ...: S

Répondre

1

Dans la première question que vous manquez la dernière étape: la cartographie de NDC (Normalisé périphérique coordonnées) à viewport coordonnées . Voilà ce que les lignes

/* Map x,y to viewport */ 
_out.X = _out.X * viewport[2] + viewport[0]; 
_out.Y = _out.Y * viewport[3] + viewport[1]; 

dans votre GluProject faire,

+0

Je je viens de réaliser fournissais dans les informations de la matrice du monde deux fois, une fois que le point d'entrée (objPos) et à nouveau dans le cadre du matrice donnée. Cela a causé des résultats étranges. Cela fonctionne après avoir entré seulement la vue combinée et la matrice de projection. :) – sinsro

1

Vous avez deux options. Vous pouvez le calculer vous-même ou utiliser la fonction glProject. Je préfère le premier.

Numéro 1:

private Vector2 Convert(
    Vector3 pos, 
    Matrix4 viewMatrix, 
    Matrix4 projectionMatrix, 
    int screenWidth, 
    int screenHeight) 
{ 
    pos = Vector3.Transform(pos, viewMatrix); 
    pos = Vector3.Transform(pos, projectionMatrix); 
    pos.X /= pos.Z; 
    pos.Y /= pos.Z; 
    pos.X = (pos.X + 1) * screenWidth/2; 
    pos.Y = (pos.Y + 1) * screenHeight/2; 

    return new Vector2(pos.X, pos.Y); 
} 

Numéro 2:

public Vector2 form3Dto2D(Vector3 our3DPoint) 
{ 
    Vector3 our2DPoint; 

    float[] modelviewMatrix = new float[16]; 
    float[] projectionMatrix = new float[16]; 
    int[] viewport = new int[4]; 

    GL.GetFloat(GetPName.ModelviewMatrix, modelviewMatrix); 
    GL.GetFloat(GetPName.ProjectionMatrix, projectionMatrix); 
    GL.GetInteger(GetPName.Viewport, viewport); 

    OpenTK.Graphics.Glu.Project(our3DPoint, convertFloatsToDoubles(modelviewMatrix), 
     convertFloatsToDoubles(projectionMatrix), viewport, out our2DPoint); 

    return new Vector2(our2DPoint.X, our2DPoint.Y) 
} 

public static double[] convertFloatsToDoubles(float[] input) 
{ 
    if (input == null) 
    { 
     return null; // Or throw an exception - your choice 
    } 

    double[] output = new double[input.Length]; 
    for (int i = 0; i < input.Length; i++) 
    { 
     output[i] = input[i]; 
    } 
    return output; 
} 
+0

Dans le numéro 1, pourquoi divisons-nous par 'pos.Z' ?! La valeur ne devrait-elle pas être divisée par la composante 'w' du système de coordonnées homogène? – M2X

Questions connexes