Bonjour à tous,

J'essaie d'apprendre la 3D avec JOGL. Pour ce faire, je lis les célèbres cours de NeHe. Dans le tutoriel numéro 9, le but est de créer des étoiles qui se dirigent lentement vers le centre de l'écran en opérant une rotation sur elles-mêmes.

Voici à quoi devrait ressembler le résultat final :



Mon code fonctionne dans le sens où la rotation sur l'image est correcte (les étoiles sont bien attirées vers le centre et tournent sur elles-même (voir les flèches rouges sur le screenshot)). Mais, je ne sais pas pourquoi, mes images forment toutes un seul bloc et ne sont pas "dissipées" à l'écran. Une image valant mieux qu'un long discours :



Voici mon code complet :
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
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
 
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.glu.GLU;
 
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
 
public class Lesson09 implements GLEventListener, KeyListener {
 
    private GLU glu = new GLU();
 
    private boolean twinkle = false; // Étoiles brillantes
 
    private final int NUM = 50;
    private Star[] stars = new Star[NUM]; // Tableau d'étoiles
 
    private float zoom = -15.0f; // Distance entre l'observateur et les étoiles
    private float tilt = 90.0f; // Inclinaison de l'observateur
    private float spin = 0; // Rotation du scintillement des etoiles
    private int texture[] = new int[1]; // Tableau de stockage des textures
 
    @Override
    public void init(GLAutoDrawable gLDrawable) {
        GL2 gl = gLDrawable.getGL().getGL2();
 
        gl.glShadeModel(GL2.GL_SMOOTH); // Active les ombres douces
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
 
        /* Profondeur */
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glDepthFunc(GL2.GL_LEQUAL);
 
        gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
 
        /* Texture */
        gl.glEnable(GL2.GL_TEXTURE_2D);
        try {
            Texture loadedTexture = TextureIO.newTexture(new File("resources/star.bmp"), true);
            texture[0] = loadedTexture.getTextureObject(gl);
        } catch (GLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        gl.glBindTexture(GL2.GL_TEXTURE_2D, texture[0]);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
 
        /* Fonctions de mélange (pour l'utilisation de l'alpha) */
        gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE); // Positionne la fonction de melange sur la transparence
        gl.glEnable(GL2.GL_BLEND); // Activation du melange
 
        // Initialisation des étoiles
        for(int i = 0; i < NUM; i++) {
            stars[i] = new Star();
            stars[i].angle = 0.0f;
            stars[i].dist = (i/NUM) * 5.0f; // Calcul de la distance depuis le centre
            // Attribution des couleurs de façon aléatoire
            stars[i].r = (int)(Math.random()*1000)%256;
            stars[i].g = (int)(Math.random()*1000)%256;
            stars[i].b = (int)(Math.random()*1000)%256;
        }
    }
 
    @Override
    public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) {
        GL2 gl = gLDrawable.getGL().getGL2();
        if(height <= 0) {
            height = 1;
        }
        gl.glViewport(0, 0, width, height);
 
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
 
        glu.gluPerspective(45.0f, width/height, 0.1f, 100.0f);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }
 
    @Override
    public void display(GLAutoDrawable gLDrawable) {
        GL2 gl = gLDrawable.getGL().getGL2();
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
 
        gl.glBindTexture(GL2.GL_TEXTURE_2D, texture[0]); // Sélectionner la texture
        for(int i = 0; i < NUM-1; i++) {
            gl.glLoadIdentity(); // Reinitialisation des valeurs
 
            /* Place le "curseur" pour afficher l'étoile */
            gl.glTranslatef(0, 0, zoom); // Zoom dans l'écran (En utilisant la valeur de 'zoom')
            gl.glRotatef(tilt, 1.0f, 0, 0); // Tourne la vue (En utilisant la valeur de 'tilt')
 
            gl.glRotatef(stars[i].angle, 0, 1.0f, 0); // Tourne l'étoile selon son angle
            gl.glTranslatef(stars[i].dist, 0, 0); //Bouge d'une valeur positive sur le plan des X
 
            /* "Applatissement" de l'étoile pour la voir de face */
            gl.glRotatef(-stars[i].angle, 0, 1.0f, 0); // Annule la rotation de l'angle
            gl.glRotatef(-tilt, 1.0f, 0, 0); // Annule l'inclinaison de l'ecran
 
            /* Dessiner l'étoile */
            if(twinkle) { // Si le scintillement est actif, on dessine une 2e étoile
                // Appliquer une couleur (de l'étoile précédente) en utilisant les octets
                if(i < 0) {
                    gl.glColor4ub((byte)stars[i-1].r, (byte)stars[i-1].g, (byte)stars[i-1].b, (byte)255);
                } else {
                    gl.glColor4ub((byte)stars[i].r, (byte)stars[i].g, (byte)stars[i].b, (byte)255);
                }
                gl.glBegin(GL2.GL_QUADS); // Dessin
                    gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f,-1.0f, 0.0f);
                    gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f,-1.0f, 0.0f);
                    gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 0.0f);
                    gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 0.0f);
                gl.glEnd();
            }
 
            // Etoile principale (avec ou sans twinkle)
            gl.glRotatef(spin, 0.0f, 0.0f, 1.0f); // Applique une rotation a l'etoile sur l'axe des Z
            // Appliquer une couleur en utilisant les octets
            gl.glColor4ub((byte)stars[i].r, (byte)stars[i].g, (byte)stars[i].b, (byte)255);
            gl.glBegin(GL2.GL_QUADS); // Dessin
                gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f,-1.0f, 0.0f);
                gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f,-1.0f, 0.0f);
                gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f, 1.0f, 0.0f);
                gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f, 1.0f, 0.0f);
            gl.glEnd();
 
            spin+=0.01f; // Change la valeur d'inclinaison des etoiles
            stars[i].angle += i/NUM; // Change l'angle de l'etoile
            stars[i].dist -= 0.01f; // Change la distance entre l'etoile et le centre
 
            if (stars[i].dist < 0.0f) { // Est-ce que l'etoile est arrivee au centre ?
                stars[i].dist += 5.0f; // Bouge l'etoile de 5 unités loin du centre
                stars[i].r = (int)(Math.random()*1000)%256; // Attribution d'une nouvelle composante rouge
                stars[i].g = (int)(Math.random()*1000)%256; // Attribution d'une nouvelle composante verte
                stars[i].b = (int)(Math.random()*1000)%256; // Attribution d'une nouvelle composante bleue
            }
        }
    }
 
    @Override
    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()) {
            case KeyEvent.VK_ESCAPE:
                System.exit(0);
                break;
            case KeyEvent.VK_T:
                twinkle = true;
                break;
        }
    }
 
    public void keyReleased(KeyEvent e) {
        switch(e.getKeyCode()) {
        case KeyEvent.VK_T:
            twinkle = false;
            break;
    }
    }
 
    public void dispose(GLAutoDrawable gLDrawable) {}
    public void keyTyped(KeyEvent e) {}
 
    public class Star {
        int r, g, b; // Couleurs
        float dist; // Distance depuis le centre
        float angle; // Angle
    }
}
Et le main :
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
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
 
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
 
import nehe.lesson.Lesson09;
import nehe.variables.GlobalVariables;
 
import com.jogamp.opengl.util.Animator;
 
 
public class Application01 {
 
    public static void main(String[] args) {
        GLProfile.initSingleton();
        GLProfile glp = GLProfile.getDefault();
        GLCapabilities caps = new GLCapabilities(glp);
        GLCanvas canvas = new GLCanvas(caps);
 
        Frame frame = new Frame("OpenGL learning");
        frame.add(canvas);
        frame.setSize(GlobalVariables.WINDOW_W, GlobalVariables.WINDOW_H);
        frame.setVisible(true);
 
        final Animator animator = new Animator(canvas);
 
        frame.addWindowListener(new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            animator.stop();
            System.exit(0);
          }
        });
 
        Lesson09 current = new Lesson09();
        canvas.addGLEventListener(current);
        canvas.addKeyListener(current);
 
        animator.start();
        canvas.requestFocus();
    }
}
D'avance un tout grand merci à quiconque se plongera dans mon code pour trouver la solution !!!