IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

Traduire coordonnées 2D en coordonnées 3D


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut Traduire coordonnées 2D en coordonnées 3D
    Bonjour :p.

    Voilà j'ai actuellement un petit problème pour traduire des coordonnées 2D (donc x, y, que je récupère suivant le clique de la souris), en coordonnées 3D.

    Je pense que ça doit être une histoire de matrices et je pense que c'est expliqué dans le livre de math que je me suis acheté récemment, mais pas encore eu le temps de le lire, et j'ai besoin d'une solution pour l'instant. J'ai donc récupéré un code sur Internet, que voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    CVector & ScreenToWorld (int screenx, int screeny, int screenz)
    {
    	GLint viewport[4];
    	GLdouble modelview[16];
    	GLdouble projection[16];
    	GLfloat winX, winY, winZ;
    	GLdouble posX, posY, posZ;
     
    	glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    	glGetDoublev( GL_PROJECTION_MATRIX, projection );
    	glGetIntegerv( GL_VIEWPORT, viewport );
     
    	winX = (float)screenx;
    	winY = (float)viewport[3] - (float)screeny;
     
    	gluUnProject (winX, winY, screenz, modelview, projection, viewport, &posX, &posY, &posZ);
     
    	return CVector ((posX), (posY), (posZ));
    }
    C'est un code que j'ai trouvé plusieurs fois sur le net, il a l'air correct, toutefois les valeurs renvoyées sont bizarre.

    Ma première utilisation, c'est de dessiner un point quand on clique avec la souris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    MouseState = SDL_GetMouseState (&x, &y);
     
    if (MouseState & SDL_BUTTON(SDL_BUTTON_LEFT))
    {
    	CVector coordinates = ScreenToWorld (x, y, 0);
     
    	glBegin (GL_POINTS);
    		glVertex3f (coordinates.x, coordinates.y, coordinates.z);
    	glEnd ();
    }
    Ici, pas de soucis, le point est dessiné exactement à la bonne position. Toutefois, dans la seconde utilisation que j'en fais, je rencontre un problème. En fait je souhaite gérer, via le moteur Newton, les objets via la souris (les prendre, les jeter,...), et plutôt que de faire une technique habituelle comme celle expliquée dans les tutos de la librairie, j'ai préféré en essayer une autre, qui consiste à créer un joint invisible pile à l'endroit du clique, et "attacher" le corps à ce joint, ce qui va ainsi l'arrêter. Voici comment je procède :

    1) Je récupère la position x, y du clique, et je converti pour avoir les coordonnées 3D puis j'envoie un rayon (raycast) et je vérifie que le rayon est touché un corps, si oui, j'ajoute le joint à l'endroit desirée.

    La position du début du lancer de rayon est obtenue comme ceci :
    CVector p0 = ScreenToWorld (x, y, 0.0f);

    Et la position d'arrivée :
    CVector p1 = ScreenToWorld (x, y, 1.0f);

    Bref, tout ceci devrait fonctionner normalement mais en pratique, le joint ne se place pas au bonne endroit, et pour cause, en ayant vérifié les valeurs renvoyées par ScreenToWorld, les valeurs sont très étranges :

    Ainsi, en cliquant sur le bord droit maximum de l'écran, j'obtient comme valeur pour p0.x environ 0.076 et à gauche -0.076, ce qui est totalement pas normal étant donné que la largeur de ma boîte qui prend à peine en largeur 1/10 de l'écran à déjà une longueur d'une unité, en tout logique je devrais me trouver vers 9-10 lorsque je clique à droite et -9 -10 à gauche...

    Après avoir reculé la caméra via gluLookAt de 30 unités, j'obtient exactement les mêmes résultats ! (-0.076 et 0.076),...

    Bref, je voudrais savoir comment récupérer les vrais positions dans les coordonnées globales. Par exemple, mon cube est placé à la position 0.0, et puisqu'il fait 1.0 de largeur, en toute logique si je clique sur son extrêmité droite je devrais obtenir pour p0.x 0.5, alors que j'obtient 0.004 actuellement :/...

    Mais le plus étrange c'est que pour dessiner le point sous la souris, ben là ça marche correctement, le point est bien dessiné sous la souris,... Bref, si quelqu'un a une idée...

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Vérifie qu'il ne traîne pas la transformation du dernier cube affiché dans la matrice de model-view. Si tu veux des coordonnées "globales" il faut que cette matrice ne contienne que la transformation de la caméra.

  3. #3
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Citation Envoyé par Laurent Gomila
    Vérifie qu'il ne traîne pas la transformation du dernier cube affiché dans la matrice de model-view. Si tu veux des coordonnées "globales" il faut que cette matrice ne contienne que la transformation de la caméra.
    Je ne pense pas étant donné que je fais l'appel juste après avoir remis la matrice à l'identité :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity ();
     
    gluLookAt (0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
     
    raycast->ShootRay (); // ICI !!
    Je viens d'essayer de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity ();
     
    glViewport (0, 0, 800, 600); // On règle le Viewport
     
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60.0, 800.0 / 600.0, 0.1, 1000.0);
     
    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity (); // On rétablit la matrice identité
     
    gluLookAt (0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
     
    raycast->ShootRay ();
    Mais ça n'y change absolument rien !

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    gluLookAt (0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    Ce sont les paramètres de ta caméra ? Parce qu'il ne faut pas qu'ils soient différents de ceux que tu utilises pour le lancer de rayon.

  5. #5
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Citation Envoyé par Laurent Gomila
    Ce sont les paramètres de ta caméra ? Parce qu'il ne faut pas qu'ils soient différents de ceux que tu utilises pour le lancer de rayon.
    Ils ne le sont pas, puisque le rayon est lancé juste après le gluLookAt. Pour vérifier je suis aller relire toute la classe RayCast et nul part on modifie de matrice, dont la matrice quand on lance le rayon est bien celle juste après le gluLookAt... Je comprend pas pourquoi ça ne marche pas :/.

  6. #6
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Par défaut
    heu...
    [quote=Bakura]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    CVector & ScreenToWorld (int screenx, int screeny, int screenz)
    {
        // blah blah
        return CVector ((posX), (posY), (posZ));
    }
    déja, la il y a un problème majeur, tu retourne une reference vers un objet local qui sera de toute façon détruit a la sortie de la fonction... donc les valeurs que tu va lire seront forcement bidon
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  7. #7
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    [QUOTE=bafman]heu...
    Citation Envoyé par Bakura
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    CVector & ScreenToWorld (int screenx, int screeny, int screenz)
    {
        // blah blah
        return CVector ((posX), (posY), (posZ));
    }
    déja, la il y a un problème majeur, tu retourne une reference vers un objet local qui sera de toute façon détruit a la sortie de la fonction... donc les valeurs que tu va lire seront forcement bidon
    Ah... Pourtant ce sont bien les bonnes valeurs puisque je les ait également testés a l'intérieur de la fonction avant le return, et ce sont bien les mêmes que celles en dehors de la fonction ... Et puis je les aurait reconnu, généralement quand les données pointent vers un truc non valides ça fait un truc tout laid du genre 0.77xe-20 .

    M'enfin, dans tous les cas c'est pas ça le problème

  8. #8
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Par défaut
    Citation Envoyé par Bakura
    Et puis je les aurait reconnu, généralement quand les données pointent vers un truc non valides ça fait un truc tout laid du genre 0.77xe-20 .
    non justement, ce n'est pas toujours le cas... pour ca, il suffit que rien ne soit venu les ecraser dans la pile pour qu'elle restent les mêmes que celles au moment du retour.
    essaye en faisant un printf entre l'appel de la fonction et l'utilisation du resultat
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  9. #9
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Citation Envoyé par bafman
    non justement, ce n'est pas toujours le cas... pour ca, il suffit que rien ne soit venu les ecraser dans la pile pour qu'elle restent les mêmes que celles au moment du retour.
    essaye en faisant un printf entre l'appel de la fonction et l'utilisation du resultat
    Déjà fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CVector ScreenToWorld (int screenx, int screeny, int screenz)
    {
    	// .....
     
    	std::cout << posX << ' ';
     
    	return CVector ((posX), (posY), (posZ));
    }
    Puis dans la fonction qui récupère le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout << p0.x << ' ';
    Et les valeurs sont bien les mêmes !

  10. #10
    Membre éprouvé Avatar de razmott
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 133
    Par défaut
    Salut !

    Les coordonnées que SDL renvoient, sont dans l'intervalle [0; taille de la fenêtre]. Or normalement, après transformation, les objets ont des coordonnées dans l'intervalle [-0.5 ; 0.5]. Il y a peut-être un problème à ce niveau non ?

    Bon courage !

    @+

  11. #11
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Up... Si personne voit va falloir que je trouve une toute autre solution....

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Déjà il y a un truc qui cloche en dehors de la fonction, puisque tu arrives à avoir des résultats correct pour un point avec z = 0, et le même appel pour cette fois ton rayon ne marche plus. Essaye de partir du code qui marche (le point 2D) en allant pas à pas vers le code qui ne marche pas (le rayon) et tu tomberas forcément sur le code qui met le boxon.

  13. #13
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Justement c'est ça qui est COMPLÈTEMENT illogique ! Les coordonnées sont les mêmes lorsque je dessine le point :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    glPointSize (6.0f);
    	glColor3ub (255, 255, 255);
     
    	Uint8 MouseState;
    	int x, y;
     
    	MouseState = SDL_GetMouseState (&x, &y);
     
    	if (MouseState & SDL_BUTTON(SDL_BUTTON_LEFT))
    	{
    		CVector coordinates = ScreenToWorld (x, y, 0);
     
    		std::cout << "x:" << coordinates.x << ' ';
    		glBegin (GL_POINTS);
    			glVertex3f (coordinates.x, coordinates.y, coordinates.z);
    		glEnd ();
    	}
    coordinates.x est bien le même ! (c'est à dire environ 0.07 au bord droit maximum). Alors comment est-ce que c'est possible pour que ça dessine le point au bon endroit, j'en sais rien du tout...

  14. #14
    Membre éprouvé Avatar de razmott
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    133
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 133
    Par défaut
    Salut !

    Je pense que le code de la fonction est correcte.
    Ainsi le point s'affiche quelque soit le z vu que la fonction recherche les bonnes valeurs. Essaie avec d'autre valeur de z pour voir.

    Pour sélectionner un objet, il faudrait connaître la profondeur du point. Ce qui peut ce faire via les PBOs : tu récupère le depth buffer, puis la profondeur du point aux coordonnées choisies. Ainsi tu auras la "bon" z pour gluUnproject.
    Les coordonnées ne devraient plus être aussi bizarres.

    Autres solutions, tu fais comme bullet : tu lances un rayon dans la direction pointée par la souris et tu récupères le point d'intersection avec l'objet. C'est peut-être la meilleure solution (vu que les exemples de Bullet l'utilisent ).

    Bon courage !

    @+

  15. #15
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Autres solutions, tu fais comme bullet : tu lances un rayon dans la direction pointée par la souris et tu récupères le point d'intersection avec l'objet. C'est peut-être la meilleure solution (vu que les exemples de Bullet l'utilisent )
    C'est exactement ce qu'il veut faire

    Justement c'est ça qui est COMPLÈTEMENT illogique ! Les coordonnées sont les mêmes lorsque je dessine le point
    Oui, donc ce que je suggérais c'était de partir de ce code qui fonctionne et d'ajouter petit à petit ce qu'il faut pour arriver au code qui ne fonctionne pas ; en y allant par étapes tu tomberas forcément sur le truc qui met le boxon...

  16. #16
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    ENFIN ! Solution trouvée :p Sur un vieux topic de Gamedev :

    WinZ = (1.0f/fNear-1.0f/fDistance)/(1.0f/fNear-1.0f/fFar)
    Where fNear/fFar are the near/far plane distances, and fDistance is the distance you want the unprojected point to be from the camera.
    Voilà :p... Donc je n'ai qu'à remplacer le fDistance par la coordonnée z de l'objet et ça marche (ne reste plus qu'à trouver cette coordonnée z :p).

    Et maintenant ça marche du feu de dieu :p.

Discussions similaires

  1. Obtenir les coordonné 2D de coordonné 3D
    Par LastSpear dans le forum OpenGL
    Réponses: 6
    Dernier message: 20/08/2009, 23h23
  2. openGL: passage coordonnées 3D a coordonnées fenetre
    Par zeder59 dans le forum Moteurs 3D
    Réponses: 1
    Dernier message: 16/06/2009, 16h12
  3. Conversion coordonnées 2D en coordonnées géographiques
    Par Clemsgc dans le forum Mathématiques
    Réponses: 2
    Dernier message: 28/05/2009, 12h27
  4. Réponses: 2
    Dernier message: 13/05/2008, 11h53
  5. coordonnée spaciale et coordonnée d'écran
    Par moldavi dans le forum DirectX
    Réponses: 2
    Dernier message: 07/04/2005, 21h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo