Pour déplacer des objets 3d dans une scène windows 3d

Soyez le premier à donner votre avis sur cette source.

Vue 6 067 fois - Téléchargée 1 647 fois

Description

Ce démonstrateur est un petit logiciel qui montre une manière spécifique de gérer un objet 3d placé dans une scène. Il est développé en OpenGL, C++ et API de Windows. La partie intéressante consiste à modifier comme on le veut la position, l'orientation et l'échelle de l'objet sélectionné. Mais ce qui était recherché c'était de pouvoir programmer ces actions sous deux conditions. La première condition concerne la géométrie de l'objet : les sommets qui le définissent doivent être renseignés dans le repère propre de l'objet et ne doivent pas être recalculés à l'occasion des actions faites sur l'objet. La deuxième condition était de programmer et de fournir à l'utilisateur la possibilité d'effectuer les translations, les rotations et le changement d'échelle dans les axes propres de l'objet et non pas dans les axes de la scène où il est placé. Le programme principal est une simple adaptation de la première leçon de NeHe. La difficulté traitée provient du fait que les changements du point de vue de la scène d'une part et les déplacements effectués d'autre part ne sont pas bien adaptés à l'utilisation habituelle de la pile des matrices 4x4 qui servent dans OpenGL à placer les objets. La solution présentée ici est simple à comprendre et fonctionne selon les conditions souhaitées. Si on peut faire mieux ou plus performant ce serait intéressant à signaler. Avec un "skybox" autour de la scène, c'est plus amusant même si cela ne change rien au traitement de la fonction présentée ici.

Source / Exemple :


// drawobj2.cpp 

#include "drawobj2.h"

void drawobj2() {
// Ici l'objet est un petit carré défini dans son propre repère et accompagné de ses propres axes.
// Pour l'affichage : les 7 variables booléennes odx2 ... orz2 et ozm2 sont toutes à : false
// sauf au plus une seule d'entr'elles, celle de l'action en cours souhaitée par l'utilisateur.
    double fz = 1.01;    // facteur de zoom éventuel à chaque affichage
    double dt = 0.01;    // incrément éventuel de translation à chaque affichage
    double da = 1.0;     // incrément éventuel d'angle, en dégrés, à chaque affichage
    static GLdouble r[16] = {1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0};
    static GLdouble t[16] = {1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0};
    static double zm = 1.0;
// Positionnement initial de l'objet
    glPushMatrix();
    glTranslated(0.3, 0.3, 0.0);
// Affichage de l'objet
// 1°) translation de l'objet dans les axes de l'objet
// on accumule les translations élémentaires successives
// mais on les applique dans les vecteurs colonnes de r
    glPushMatrix();
    glLoadMatrixd(t);
    if(odx2) glTranslated(delta(dt)*r[0], delta(dt)*r[1], delta(dt)*r[2]);
    if(ody2) glTranslated(delta(dt)*r[4], delta(dt)*r[5], delta(dt)*r[6]);
    if(odz2) glTranslated(delta(dt)*r[8], delta(dt)*r[9], delta(dt)*r[10]);
    glGetDoublev(GL_MODELVIEW_MATRIX, t);
    glPopMatrix();
    glMultMatrixd(t);
// 2°) zoom de l'objet
    if(ozm2) {
        if(keys[VK_RIGHT]) zm = zm*fz;
        if(keys[VK_LEFT])  zm = zm/fz;
    }
    glScaled(zm,zm,zm);
// 3°) rotation de l'objet autour des axes du repère de l'objet
// la matrice r accumule les rotations élémentaires successives
    glPushMatrix();
    glLoadMatrixd(r);
    if(orx2) glRotated(delta(da), 1.0, 0.0, 0.0 );
    if(ory2) glRotated(delta(da), 0.0, 1.0, 0.0 );
    if(orz2) glRotated(delta(da), 0.0, 0.0, 1.0 );
    glGetDoublev(GL_MODELVIEW_MATRIX, r);
    glPopMatrix();
    glMultMatrixd(r);
// on affiche les 4 sommets du carré
    glColor3d(1.0, 1.0, 1.0);
    glPointSize(2.0f);
    glBegin(GL_POINTS);
    glVertex3d(-0.2, -0.2, 0.0); 
    glVertex3d(-0.2, 0.2, 0.0); 
    glVertex3d(0.2, -0.2, 0.0); 
    glVertex3d(0.2, 0.2, 0.0); 
    glEnd();
// on affiche les axes
    glBegin(GL_LINES);
    glLineWidth(2.0f);
    glColor3d(1.0, 0.0, 0.0);   // son axe Ox
    glVertex3d(0.0, 0.0, 0.0);
    glVertex3d(0.3, 0.0, 0.0);
    glColor3d(0.0, 1.0 ,0.0);   // son axe Oy
    glVertex3d(0.0 ,0.0 ,0.0);
    glVertex3d(0.0, 0.3, 0.0);
    glColor3d(0.0, 0.0, 1.0);   // son axe Oz
    glVertex3d(0.0, 0.0, 0.0);  
    glVertex3d(0.0, 0.0, 0.3);
    glEnd();
// on affiche le carré qui est défini
// comme prévu dans ses axes propres.
    glBegin(GL_TRIANGLES);
    glColor3d(0.2, 0.2, 0.2);
    glVertex3d(-0.2, -0.2, 0.0);
    glVertex3d(0.2, -0.2, 0.0);
    glVertex3d(-0.2, 0.2, 0.0);
    glVertex3d(-0.2, 0.2, 0.0);
    glVertex3d(0.2, -0.2, 0.0);
    glVertex3d(0.2, 0.2, 0.0);
    glEnd();
    glPopMatrix();
}

Conclusion :


En tant que démonstrateur toutes les actions successives sont simplement effectuées via le menu et les 2 touches droite et gauche du clavier.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

pgl10
Messages postés
312
Date d'inscription
samedi 18 décembre 2004
Statut
Membre
Dernière intervention
5 février 2020
1
Shenron666 : En août 2008, M. Cyril Doillon, déjà cité dans mon commentaire du 10/03/2013, a publié un document ayant pour titre : "La géométrie en OpenGL : vers les VertexBufferObject" Il y compare les avantages et inconvénients de la méthode de dessin immédiat ( glBegin, glEnd, glVertex, ... ), de celle des Vertex Array et de celle des Vertex Buffer Object. En ce qui concerne le dessin immédiat, il explique bien que cela comporte un grand nombre d'inconvénients très gênants pour des applications "tempsréel" en raison d'échanges très nombreux entre CPU et GPU. Mais il cite aussi les avantages de ces fonctions, lesquelles sont dites ailleurs "obsolètes" et "dépréciées", et je cite : - Permet de définir indépendamment chacune des informations des vertex - Permet d'augmenter la lisibilité du code - Regroupe clairement chaque rendu par type de primitives. Le commentaire de CptPingu indiquait déjà cela. J'en déduis que cette utilisation n'est pas "peu lisible" pour tout le monde. J'aimerais bien voir la "traduction" de mon code avec les VBO bien que mon vrai sujet concerne le placement des objets dans la scène, leur affichage est nécessaire mais accessoire ici.
shenron666
Messages postés
229
Date d'inscription
dimanche 14 septembre 2003
Statut
Membre
Dernière intervention
20 août 2014

Tu as le droit de ne pas être d'accord mais je maintient mes propos :
Le code serai plus lisible sans toutes ces fonctions dépréciées.
et mes commentaires ne gênent en rien ceux qui veulent s'exprimer, ils sont toujours aussi libres de le faire.
pgl10
Messages postés
312
Date d'inscription
samedi 18 décembre 2004
Statut
Membre
Dernière intervention
5 février 2020
1
Merci Shorzy. Je peux même dire cela autrement. Le fait d'appeler deux fois, deux fois seulement, la fonction glGetDouble() à chaque affichage de chaque objet de la scène doit augmenter les échanges entre CPU et GPU ce qui peut diminuer les performances. Il serait peut-être plus judicieux de faire directement ces calculs matriciels sans passer par OpenGL pour cela, ce qui est très facile à faire maintenant que l'on sait la méthode utilisée. Voici donc un commentaire qui aurait pu valablement être fait concernant ce démonstrateur. C'est autre chose que de critiquer les fonctions directes glBegin(), glEnd, glVertex3d(),... utilisées ici pour afficher un triangle et un rectangle. Utiliser pour cela les VBO complique le démonstrateur et ne change rien à mon sujet. Ce qui est dommage, c'est de penser que des propos hors sujet peuvent gêner ceux qui auraient voulu s'exprimer au sujet de la méthode exposée.
shorzy
Messages postés
94
Date d'inscription
jeudi 23 novembre 2000
Statut
Membre
Dernière intervention
1 juin 2013

J'aime bien, et je soutient PGL10 (10/10) !!!
"Aujourd'hui on en prends plein la Gueule pour pas un rond !!!"
pgl10
Messages postés
312
Date d'inscription
samedi 18 décembre 2004
Statut
Membre
Dernière intervention
5 février 2020
1
CptPingu : merci beaucoup. A partir de ce démonstrateur j'ai pu assez facilement développer Polymoff : un compositeur de scènes 3d. Les fonctions présentées ici y sont essentielles pour placer et déplacer les objets de la scène.
Afficher les 11 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.