OpenGL et trackball camera

Salut à tous!:

Je débute un peu en OpenGL, et je réalise actuellement une application Java6 nécessitant un peu d’OpenGL simple pour un rendu graphique 3D.

J’utilise JOGL pour l’OpenGL, pour ceux qui ne connaissent pas, ça permet d’utiliser OpenGL quasiment exactement de la même façon qu’en C/C++.
Bref, le problème n’est pas là, car tout ceci marche, j’arrive à afficher ce que je veux sans problèmes.

Mon programme affiche des points (coordonnées 3D) dans l’espace.
Ce que je cherche à faire est de pouvoir faire tourner cet ensemble de points à la souris, un peu à la façon de GoogleEarth.

Voici l’extrait de mon code concerné, qui est très simple:

[code]/**

  • Initializing OpenGL

  • @param drawable
    */
    public void init(GLAutoDrawable drawable)
    {
    GL gl = drawable.getGL();

     gl.glClearColor(0, 0, 0, 0);
     gl.glMatrixMode(GL.GL_PROJECTION);
     gl.glLoadIdentity();
     gl.glOrtho(-1, 1, -1, 1, -1, 1);
    

}

/**

  • Refresh OpenGL display

  • @param drawable
    */
    public void display(GLAutoDrawable drawable)
    {
    GL gl = drawable.getGL();

    gl.glClear(GL.GL_COLOR_BUFFER_BIT);

    // moving camera, if necessary
    gl.glRotated((double)(rotationAngleX/5),0,1,0);
    gl.glRotated((double)(rotationAngleY/5),1,0,0);

    // drawing points
    gl.glBegin(GL.GL_POINTS);
    gl.glColor3d(255, 0, 0);
    /* Une boucle qui trace un ensemble de points en utilisant gl.glVertex3d() */
    gl.glEnd();

    rotationAngleX = 0;
    rotationAngleY = 0;

    gl.glFlush();
    }[/code]

Comme vous pouvez le voir, il y a deux variables, rotationAngleX, et rotationAngleY, qui sont modifiées lorsque l’on fait un drag avec la souris sur le canvas OpenGL:

[code]/**

  • Mouse button down
  • @param e
    */
    public void mousePressed(MouseEvent e)
    {
    mousePrevX = e.getX();
    mousePrevY = e.getY();
    }

/**

  • Mouse dragged, updating display

  • @param e
    */
    public void mouseDragged(MouseEvent e)
    {
    // computing display rotation with mouse movings
    int x = e.getX();
    int y = e.getY();
    rotationAngleX = x - mousePrevX;
    rotationAngleY = y - mousePrevY;
    mousePrevX = x;
    mousePrevY = y;
    if (rotationAngleY > 90)
    rotationAngleY = 90;
    else if(rotationAngleY < -90)
    rotationAngleY = -90;

    updateCanvas(); // refresh display
    }[/code]

Le problème: quand j’effectue ma première rotation gl.glRotated((double)(rotationAngleX/5),0,1,0), le repère lui aussi va bouger.
Ce qui fait que lorsque j’effectue la seconde rotation, elle ne se fera pas de la façon dont l’utilisateur a déplacé la souris sur son écran.

J’aimerai que, à n’importe quel moment, si l’utilisateur bouge sa souris de gauche à droite, l’ensemble des points tourne dans ce sens, pareil de haut en bas. En gros la même chose que GoogleEarth.

Ce qui n’est pas le cas, puisque après la première rotation, le repère est changé.
Il faudrait donc que je puise conserver le repère dans son état initial, mais je n’arrive pas à le faire correctement. J’ai essayé d’utiliser glPushMatrix() et glPopMatrix(), mais rien n’y fait.

J’ai donc besoin d’un petit coup de pouce :slight_smile:

Quelqu’un saurait-il m’aider?

Alors je vais essayer de t’aider un peu. Il y a quelques années, j’ai eu le même problème sur un programme OpenGL et C++.

En faite, ce que tu essaies de faire, c’est un manipulateur de type ArcBall qui permet une manipulation intuitive de la scène avec la souris.

Maintenant pour réaliser se genre de manipulation géométrique, tu vas être obligé de passer par des matrices et des quaternions afin de stocker les différentes transformations géométrique et avoir une animation fluide.

Malheureusement mes souvenirs dans ce domaine commence sérieusement à s’effacer. Mais heureusement pour toi (ou pas), je me souviens du tutoriel que j’ai suivis pour implémenter cette fonction.

Tu trouveras ce tutoriel ici .

Il y a une description point par point, plus les fichiers source de la classe Arcball dans différents langages (C++, Delphi, Python) mais pas en Java.
Mais je pense que tu pourras facilement adapter les classes C++ en Java.

Bon courage.

Je te remercie pour ton lien, je vais voir ça desuite :slight_smile:

Je ne suis pas un spécialiste mais il me semble qu’il faut que tu fasses toutes les rotations d’un seul coup non ? Sinon problème. Ce n’est pas avec glPushMatrix et glPopMatrix qu’on fait justement ce produit de matrices ? Tu multiplies la matrice de la première rotation par la seconde, tu obtiens la composition de tes deux rotations dans le même repère. Enfin, ce n’est qu’un vague souvenir, à vérifier donc.

Je dirais quelque chose comme cela

[code]/**

  • Initializing OpenGL

  • @param drawable
    */
    public void init(GLAutoDrawable drawable)
    {
    GL gl = drawable.getGL();

     gl.glClearColor(0, 0, 0, 0);
     gl.glMatrixMode(GL.GL_PROJECTION);
     gl.glLoadIdentity();
     gl.glOrtho(-1, 1, -1, 1, -1, 1);
    
     // Rotation en modelview et non en projection 
     gl.glMatrixMode(GL.GL_MODELVIEW);
     gl.glLoadIdentity();
    

}

/**

  • Refresh OpenGL display

  • @param drawable
    */
    public void display(GLAutoDrawable drawable)
    {
    GL gl = drawable.getGL();

    // push the modelview matrix
    

    gl.glPushMatrix();

    gl.glClear(GL.GL_COLOR_BUFFER_BIT);

    // moving camera, if necessary
    gl.glRotated((double)(rotationAngleX/5),0,1,0);
    gl.glRotated((double)(rotationAngleY/5),1,0,0);

    // drawing points
    gl.glBegin(GL.GL_POINTS);
    gl.glColor3d(255, 0, 0);
    /* Une boucle qui trace un ensemble de points en utilisant gl.glVertex3d() */
    gl.glEnd();

    rotationAngleX = 0;
    rotationAngleY = 0;

    gl.glFlush();

    // pop the modelview matrix
    gl.glPopMatrix();
    }[/code]

Code non tester. Jette un coup d’oeil au redbook, tu auras toute l’info qui t’es necessaire.
Autre chose: tu peux aussi utiliser un gluLookAt, plus simple a utiliser que les rotations pures.

Je vous remercie tous pour vos réponses, je devrai arriver à m’en sortir maintenant :crying:

Et puis au cas où, je reviendrai vous demander :slight_smile:

Il faudra que je pense à poster mon code quand il sera fonctionnel.