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

Qt Discussion :

[OpenGL] Accès extérieur à un objet de type GLWidget


Sujet :

Qt

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Points : 50
    Points
    50
    Par défaut [OpenGL] Accès extérieur à un objet de type GLWidget
    Bonsoir à tous,

    j'ai une question à vous poser concernant l'utilisation d'une classe dérivée de GLWidget.

    Voici ce que j'ai fait :
    - J'ai créé une classe dérivée de GLWidget que j'ai appelé : GraphicalWindow
    - Cette classe possède une fonction membre nommée : void drawTriangle(const Triangle &monTriangle). Cette fonction prend en paramètre la référence à un objet de type Triangle (comportant les coordonnées des sommets).

    J'aimerais pouvoir "envoyer" à une instance de GraphicalWindow "l'ordre" de tracer un triangle depuis l'extérieur de mon instance comme ci dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    GraphicalWindow w = new GraphicalWindow(this);
    Triangle t = new Triangle(this);            //Bien sur normalement je dois préciser les coordonnées des sommets mais je vous l'épargne car ça n'a pas d’intérêt ici
     
    w->drawTriangle(t);
    Est ce que ce que je souhaite faire est envisageable ou est ce que je me plante complètement :mouarf: ?

    Et si c'est envisageable comment feriez vous cela ?

    Je précise que je ne suis pas un as d'openGL alors excusez moi si c'est trivial.

    Merci d'avance pour votre aide et bonne soirée.

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    C'est faisable (mais pas performant... mais osef dans un premier temps)
    Il y a un tuto sur l'utilisation de Qt et OpenGL, ca devrait t'aider

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Points : 50
    Points
    50
    Par défaut
    Salut mintho carmo et merci pour ta réponse .

    Tu as eu raison de m'orienter vers les tutos Qt+OpenGL, j'avais déjà suivi celui ci :

    http://fhalgand.developpez.com/tutor...ication/#LIV-D

    Mais en allant fouiller dans celui la :

    http://cpp.developpez.com/redaction/...ge=opengl#L3-A

    J'ai trouvé des infos intéressantes qui m'ont permis de clarifier mon idée.

    Ce que je souhaite faire (et qui est je le reconnait très mal exprimé dans le titre de mon topic, je m'en excuse) c'est afficher dynamiquement des objets dans ma scène (être capable de les "charger" et de les "retirer") (au moyen d'une fonction membre utilisé à l'extérieur de mon instance).

    Ce que je fais jusqu’à présent c'est de mettre mes commandes d'affichage dans la fonction membre paintGL de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void GraphicalWindow::paintGL()
    {
        glBegin(GL_TRIANGLES);
            glVertex3f(x1,y1,z1);
            glVertex3f(x2,y2,z2);
            glVertex3f(x3,y3,z3);
        glEnd();
    }
    Dans mon exemple je vous ai épargné la sélection de la pile des transformations et tout le reste, je me concentre sur les commandes d'affichage de mon objet.

    Comment feriez vous pour afficher et supprimer des triangles de manière dynamique ?

    Pourquoi dis tu que ce n'est pas performant de faire de la sorte mintho carmo, comment procèderais tu ?

    Merci à tous

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 858
    Points : 218 575
    Points
    218 575
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Je me pencherai sur une solution bien plus moderne (les glVertex et autre sont dépréciés).
    Vous avez un max de ressource en français sur OpenGL moderne. L'idée, ce n'est plus d'avoir d'appel glVertex, mais un simple appel à glDraw* (en utilisant les VBO). Ainsi, chacune de vos classes de primitives d'objet n'aurait qu'à tenir un pointeur vers un buffer et ce pointeur peut "directement" être envoyé à OpenGL. Ainsi, vous avez un plus haut dynamisme et vous n'avez qu'à créer des instances de Triangle ou autre, les ajouter dans votre scène et hop, tout fonctionne.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Points : 50
    Points
    50
    Par défaut
    Salut LittleWhite,

    suite à vos messages je suis en train de balayer des chapitres concernant les display list, les vertex array et les vertex buffer object et je me rend compte que mes compétences en openGL sont bien maigre .

    J’espérais qu'une solution simple et intuitive (sous entendu applicable avec mes connaissances sommaires d'openGL) existe. Je vais me plonger dans les vertex buffer object comme tu me le conseilles car je ne connais pas leur fonctionnement.

    J'essayerais de poster ma solutions quand ce sera fait.

    Merci pour votre aide à tous les deux.

  6. #6
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Points : 50
    Points
    50
    Par défaut
    Salut à tous,

    me revoilà avec de nouvelles infos.

    Dans le but de solutionner mon problème de création dynamique d'objet dans openGL j'essais d'utiliser les listes d'affichages.

    Vos messages m'ont bien fait comprendre le fait que les listes d'affichages ne sont pas performantes et qu'elle sont dépassées en openGL moderne.

    Cela dit dans le but de me former à openGL petit à petit je commence par me familiariser à leur utilisation avant de passé à une techno plus récente .

    Malheureusement ce que j'ai fais ne fonctionne pas (comme je le souhaite) et je ne comprend pas pourquoi.

    Merci d'avance pour vos commentaires sur mon code.

    Voici ce que j'ai fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //Dans la fonction paintGL de ma classe GraphicalWindow j'appelle l'ensemble des listes d'affichages du vector list membre de ma classe.
    if (list.size() != 0)
        {
            for (int i=0; i<list.size(); i++)
            {
                glCallList(list[i]);
            }
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //J'ai une fonction membre drawObject qui crée une nouvelle liste à chaque appel avec en entrée un maillage composé de triangles.
    void GraphicalWindow::drawObject(const Mesh &M)
    {
        list.push_back(glGenLists(1));
     
        glNewList(list[list.size()-1], GL_COMPILE);
     
        for (int i=0; i<M.numberOfTriangle(); i++)
        {
            drawTriangle(M.triangle(i+1));         //La fonction drawTriangle contient simplement glBegin et glEnd avec les trois vertex.
        }
     
        glEndList();
    }
    A partir de la vous savez tout sur mon raisonnement. Maintenant je distingue deux cas :

    -> Premier cas : je charge mon maillage dans le constructeur de ma classe GraphicalWindow et j'utilise ma fonction drawObject dans la fonction initializeGL().
    -> Deuxième cas : Une instance de ma classe GraphicalWindow est créer avant le chargement de mon maillage et l'appel de la fonction drawObject de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //Code pour le second cas
    GraphicalWindow w;
    Mesh mesh("monMaillage");
     
    w.drawObject(mesh);
    Le premier cas fonctionne et affiche mon maillage mais ce n'est pas ce que je souhaite faire puisque je ne peux pas ajouter d'objet depuis l’extérieur de mon instance.

    Le second cas compile mais ne fonctionne pas (il n'affiche pas mon maillage).

    Avez vous des idées sur ce que je fais de mal ?

    Merci d'avance pour votre intérêt

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Je comprend un peu mieux ton problème Cela serait plus simple d'avoir le code complet de ta classe pour bien comprendre ce qu'elle fait

    Pour resumer le fonctionnement de QWidget (de memoire) :
    • QWidget cree un contexte OpenGL
    • QWidget appelle la fonction InitializeGL pour que l'utilisateur puisse faire ses initialisations avec le contexte GL
    • A chaque update, QWidget appelle paintGL pour mettre a jour l'affichage


    En appelant ton code de dessin (glBegin/glEnd) en dehors de paintGL, celui ci n'est appelé qu'une seule fois, et en dehors de la séquence "normale" d'affichage de Qt. Du coup, l'appel est directement écrasé par le premier appel de paintGL (sachant qu'avant le premier appel a paintGL, la fenêtre n'est pas encore afficher, donc tes appels aux fonctions GL partent dans un contexte qui n'est pas encore affiché...)

    Ta fonction drawObject ne doit pas dessiner, mais simplement créer les listes GL (donc il faut changer le nom de cette fonction, puisqu'elle ne fera plus de "draw"). Il faut déplacer les fonctions GL de dessin dans paintGL.
    C'est la limitation des listes, cela produit directement le dessin 3D (on parle de mode direct). Du coup, avec ton approche, tu ne peux pas créer tes list en dehors de paintGL. L’idéal est de séparer l'envoi des données (ie la création de liste de dessin) de l'affichage proprement dit. C'est justement le rôle des buffers dont parle le tuto (et c'est ce qui explique la différence de performances entre les différentes approches).

    C'est pour cela que LittleWhite de conseillait de lire un tuto "moderne", qui n'utilise pas le mode directe (qui date de plus de 15 ans et qui est déprécié depuis 10 ans). Honnêtement, l'utilisation des buffers n'est pas plus compliqué a comprendre que le mode direct, la différence importante est que l'on sépare le transfert des données (entre le CPU et le GPU) et l'utilisation de ces données par le GPU (rendu).

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 113
    Points : 50
    Points
    50
    Par défaut
    Ah d'accord ! Donc si je comprends bien, il est impossible de charger un nouvel objet 3D dans une scène openGL déjà ouverte à l'aide de listes d'affichage. La seule utilisation possible est le chargement d'objet déjà connu de la scène à son initialisation.

    Bon bah je me renseigne sur les buffers et je vous reposte mon code =).

    Je précise que je n'étais pas sourd à vos conseilles sur l'utilisation des buffers, je cherchais simplement à répondre à mon besoin le plus intuitivement possible avant de complexifier les choses pour plus de performance. Je n'avais pas compris qu'il y avait incompatibilité entre mon besoin et les listes d'affichages.

    A+

Discussions similaires

  1. [Debutant][Conception] visibilité des objets de type conteneur
    Par thebloodyman dans le forum Général Java
    Réponses: 10
    Dernier message: 04/01/2006, 12h44
  2. Réponses: 3
    Dernier message: 28/10/2005, 01h12
  3. Tableau d'objets de type différents
    Par Hell dans le forum C++
    Réponses: 9
    Dernier message: 11/01/2005, 22h57
  4. [Sérialisation] d'objets de types différents
    Par Amnesiak dans le forum Général Java
    Réponses: 3
    Dernier message: 08/12/2004, 22h28
  5. DB objet sous types heritage
    Par smex dans le forum Décisions SGBD
    Réponses: 2
    Dernier message: 15/06/2004, 21h58

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