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 :

2D en perspective


Sujet :

OpenGL

  1. #1
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 36
    Par défaut 2D en perspective
    Bonjour,

    Je programme un jeu en 2D : dans le gameplay, la caméra ne bouge pas, on est toujours en vue de dessus.
    En glOrtho tout se passe bien.

    J'aimerais passer à la perspective : c'est plus joli (quand un cube bouge à droite ou à gauche dans l'écran, on le voit bouger "en 3D tout en restant de dessus").
    Pour cela j'ai compris que je devais passer de glOrtho à gluPerspective + gluLookAt.

    Toute ma scène tient dans un rectangle (un GL_QUAD) dont les dimensions sont celles de la fenêtre, et je veux que ce rectangle soit bien cadré dans la fenêtre, pile aux dimensions de la fenêtre.

    Mon problème est le suivant : Je ne sais pas comment calculer les paramètres de gluPerspective et gluLookAt pour que le GL_QUAD remplisse la fenêtre.
    Des idées ?

    PS : Voici un bout de code qui me permet de passer de l'un à l'autre facilement en transformant le TRUE en FALSE :

    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
     
    	if (TRUE)
    	{
    		glMatrixMode(GL_PROJECTION);
    		glLoadIdentity();
    		glOrtho(0, w, 0, h, -50, 50); 
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    	}
    	else 
    	{
    		glMatrixMode(GL_PROJECTION);
    		glLoadIdentity();
    		gluPerspective(60, w/h, 100, 20000);
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    	 	gluLookAt(w / 2, h / 2, 500, 
    				  w / 2, h / 2,  0, 
    				  0, 1, 0);
    	}

  2. #2
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 594
    Par défaut
    mathématiquement parlant je pense que ça doit être possible à partir des 3 premiers paramètres de gluPerspective :
    - du fov
    - du ratio
    - du near plan

    j'ai déjà vu dans certaines démos le rendu de la pyramide de visibilité
    par contre je ne suis pas très fort dans ce domaine, il faudrait peut-etre demander dans un forum math
    si je retrouve une source qui fait ça te t'en fait part

    edit : il y a les tutos de Nate Robins
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  3. #3
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 594
    Par défaut
    vu que ça m'intéresse, j'ai plongé un peu dans le code du tuto "projection"
    en fait apparemment c'est tout con, il suffit de :
    - récupérer la matrice de projection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    - "calculer" son inverse
    - multiplier la matrice inverse avec la matrice courante du modelview
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glMultMatrixd(inverse);
    - dessiner un quad à 1 unité devant soi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    glBegin(GL_QUADS);
        glVertex3i(1, 1, -1);
        glVertex3i(-1, 1, -1);
        glVertex3i(-1, -1, -1);
        glVertex3i(1, -1, -1);
    glEnd();
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  4. #4
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    Je ne saisis pas trop. Tu affiches ta scène dans un GL_QUAD ? Tu veux dire que tu génères une texture qui représente ta scène dans un GL_QUAD et tu affiches ce dernier texturé ?

    Si oui alors il faut que tu connaisses exactement la position de ton GL_QUAD en 3D. Imaginons qu'il soit centré en 0, orienté de telle sorte qu'il soit dans le plan (x,y) avec les z vers le haut (donc de normale (0,0,1) et de taille w et h (tailles de la fenêtre).

    Après voici la pyramide de vue :



    Choisissons un angle d'ouverture (fov) à 90 degrés. Le ratio doit être égal au ratio de ton quad donc r à w / h. La perspective se fait sur le plan near (c'est l'écran). Il faut trouver le near et le far qui vont bien de telle sorte que GL_QUAD soit entre les deux.

    Pour que tu vois bien le GL_QUAD, il faut choisir le centre d'intérêt le centre de ce dernier donc de coordonnées (0,0,0). Ensuite pour la position de la caméra, il faut qu'elle soit au dessus du centre d'intérêt donc de coordonnées (0,0,z) avec z > 0 à fixer. Ensuite il faut que son vecteur up soit de telle sorte qu'on voit les x horizontaux et les y verticaux donc on va prendre up = (0,1,0).

    Le problème reste à positionner la caméra et plus particulièrement trouver son z et aussi le plan far de telle sorte qu'il soit juste après notre GL_QUAD (sinon on ne le verra pas...). Comme nous avons fixé l'angle d'ouverture (il permet de donner des effets de perspective plus ou moins prononcés sur les côté, il faut donc pouvoir le fixer), il va falloir positionner la caméra de telle sorte que le GL_QUAD remplisse tout l'écran. Si on est trop prêt, il sera trop grand, si on est trop loin, il sera trop grand.


    Coupe dans ta tête la pyramide verticalement en 2. Tu vois apparaître deux triangles rectangles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
          /| B
         /  |
      D/   |
    A /|    |
    /_|__| C
    p  n  q
       E
    Oui c'est très moche, où p est la position de la caméra, n est le plan de near et q le plan où est le quad (en l'occurence le plan (x,y) cad le plan où z = 0.

    Et là on voit thales ! Je rappelle Thales pour ces triangles ABC et ADE :
    BC / DE = AC / AE

    BC = w / 2 donc la moitié de la taille de ton GL_QUAD.
    DE on sait pas
    AE = n c'est la distance à ton plan de near
    AC on sait pas mais c'est le z qu'on cherche (la distance de ta caméra au plan (x,y)).

    Donc on a :
    (w / 2) / n = z / AE
    <=> z = w / (2 * n * DE)

    Il faut qu'on trouve DE. Mais souvenons-nous que nous connaissons l'angle d'ouverture fov ! Dans notre cas c'est 90 degrés. Donc l'angle BAC = fov / 2 (la moitié vu qu'on a coupé la pyramide de vue en 2...).

    Et la comme on sait que (DAE) est un triangle rectangle en E donc on peut appliquer les relations de trigo :
    tan(BAC) = DE / AE
    donc DE = tan(fov / 2) / n

    donc z = w / (2 * n * tan(fov / 2) / n)
    z= w / (2 * tan(fov / 2)

    Et voilà ! T'as trouvé ton z ! Remarquons qu'il n'est pas dépendant de n. Donc on est libre de placer n et f. Sachant qu'il faut que f ne soit pas plus grand que 1000 fois n (sinon t'as des soucis avec la précision en z). Supposons qu'on veuille placer le GL_QUAD juste avant le far plane On peut choisir near et far comme ça :

    f = 1.01 * z
    n = f / 1000.

    Et voilà c'est cool ça pête.

  5. #5
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    Citation Envoyé par shenron666 Voir le message
    vu que ça m'intéresse, j'ai plongé un peu dans le code du tuto "projection"
    en fait apparemment c'est tout con, il suffit de :
    - récupérer la matrice de projection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    - "calculer" son inverse
    - multiplier la matrice inverse avec la matrice courante du modelview
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glMultMatrixd(inverse);
    - dessiner un quad à 1 unité devant soi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    glBegin(GL_QUADS);
        glVertex3i(1, 1, -1);
        glVertex3i(-1, 1, -1);
        glVertex3i(-1, -1, -1);
        glVertex3i(1, -1, -1);
    glEnd();
    Si tu fais ça, tu perds la perspective... vu que tu l'annules en multipliant l'inverse de la matrice de projection avec la modelView donc opengl va faire (notons P la matrice de projection) :

    P*inv(P) = Id

    En gros ça appliquera rien.

  6. #6
    Membre Expert
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 594
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 594
    Par défaut
    justement, si tu multiplies la matrice de projection par son inverse tu cales facilement un quads sur ton near plan
    c'est tout con fallait juste y penser
    je t'invite à regarder les tutos de Nate Robins et à constater par toi même l'efficacité de sa méthode
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  7. #7
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    Ah oui j'suis bête un plan perpendiculaire à la caméra il n'y aura pas d'effet de projection... et je pense qu'il faudrait plutôt qu'il le mette dans le far plane donc plutôt en -1 en z s'il veut ensuite afficher des objets 3D par dessus on sait jamais...

    Donc Titom si tu veux faire un effet 3D sur tes images 2D, dirige-toi plutôt vers la 3D isométrique...

  8. #8
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 36
    Par défaut
    Merci à vous deux pour vos réponses très enrichissantes, je vais étudier tout cela.

    Je ne suis pas sur que la 3D isométrique soit ce que je cherche (on ne dit pas plutôt 2D iso, d'ailleurs ?). En effet : je veux rester "en vue de dessus". Ma scène représente une sorte de cuvette vue de dessus bien centrée sur le centre de la cuvette, l'effet que je veux avoir est d'apercevoir les côtés de la cuvette "de l'intérieur" (en ortho, vu que les côtés sont verticaux on ne les voit pas, et en 2D isométrique je ne serai pas centré au dessus de ma cuvette).

    Je vais lire les tutos, je pense que j'ai beaucoup à comprendre sur les Projections...

    Merci encore

  9. #9
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    En gros tu veux faire une projection "sphérique" ? Peux-tu nous montrer une image que l'on comprenne ?

    Edit : il me semble que c'est 3D isométrique mais je ne pourrais te l'assurer à 100%. Tout indique sur le net que c'est ça mais bon le net... faut pas s'y fier à 100%

  10. #10
    Membre averti
    Inscrit en
    Juin 2002
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 36
    Par défaut
    Voilà un schéma.
    C'est la dernière vue que je cherche à obtenir, tout en faisant en sorte que l'affichage de l'objet remplisse la fenêtre ("fit to screen").

    http://cjoint.com/?iwolcaWgKJ

    J'ai regardé l'exécutable "Projection" dans les tutoriels de Nate Robins, et il est très très bien fait pour comprendre les fonctions gluPerspective et gluLookAt.

    Je poursuis l'apprentissage

  11. #11
    Membre émérite

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2006
    Messages
    450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2006
    Messages : 450
    Par défaut
    Oui mais là comme tu peux le voir c'est plusieurs GL_QUAD et pas un... As-tu ce modèle aussi ? C'est-à-dire 5 GL_QUAD positionnés comme sur les images ? Si oui il faut que tu utilises ma méthode et pas celle donnée par shenron (qui ne fait en fait une perspective cavalière, l'équivalent d'un glOrtho).

    Mais cette fois-ci il faudra positionner tes GL_QUAD de telle manière que l'entrée de cette boîte soit sur le plan z = 0 et donc le fond de la boîte dans les z négatifs. Ensuite il faudra que tu changes le calcul des far plane et near plane :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    f = 1.01 * (z + height)
    n = f / 1000.
    Où height est la hauteur de ta boîte et tu auras le résultat voulu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Objet découpé et perspective
    Par Pedro dans le forum DirectX
    Réponses: 20
    Dernier message: 25/01/2005, 16h21
  2. Réponses: 2
    Dernier message: 05/07/2004, 16h48
  3. Probleme avec glutBitmapCharacter en mode Perspective
    Par killerjeff dans le forum OpenGL
    Réponses: 7
    Dernier message: 17/05/2004, 15h04
  4. probleme de perspective
    Par k-koo dans le forum OpenGL
    Réponses: 15
    Dernier message: 05/05/2004, 21h55
  5. [2.1.2] Perspectives + migration
    Par gromite dans le forum Eclipse Platform
    Réponses: 3
    Dernier message: 15/04/2004, 17h12

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