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

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

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.