
| public Esfera(float maxpos, float speed, float radio) { this.maxpos = maxpos; this.speed = speed; this.radio = radio; Random r = new Random(); //if (!pass) { //Math.random(time(NULL)); pass = true; // r.setSeed(new java.util.Date().getTime()); // } pos[0] = (float) ((r.nextFloat() % (int) maxpos) - maxpos / 2); pos[1] = (float) ((r.nextFloat() % (int) maxpos) - maxpos / 2); pos[2] = (float) ((r.nextFloat() % (int) maxpos) - maxpos / 2); dir[0] = (float) r.nextFloat(); dir[1] = (float) r.nextFloat(); dir[2] = (float) r.nextFloat(); float dirmod = (float) Math.sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]); dir[0] /= dirmod; dir[1] /= dirmod; dir[2] /= dirmod; dir[0] *= speed; dir[1] *= speed; dir[2] *= speed; // generamos el color de la esfera aleatoriamente. color[0] = (float) (r.nextFloat()); color[1] = (float) (r.nextFloat()); color[2] = (float) (r.nextFloat()); color[3] = (float)1.0; } |
| public void init() { angle_x = (float)0.5; angle_y = (float)0.5; // definimos la posición y características de la luz GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, FloatBuffer.wrap(light_ambient)); GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, FloatBuffer.wrap(light_color)); GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, FloatBuffer.wrap(light_color)); GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, FloatBuffer.wrap(light_pos)); GL11.glEnable(GL11.GL_LIGHT0); // activamos el test de profundidad, inicializamos las matrices de proyección y del modelo de vista, // ajustamos el ángulo de perspectiva GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glClearColor((float) 0.0, (float) 0.0, (float) 0.0, (float) 0.0); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GLU.gluPerspective((float) 55.0, (float) 1.0, (float) 1.0, (float) 100.0); GL11.glMatrixMode(GL11.GL_MODELVIEW); // determinamos la posición de la cámara GLU.gluLookAt((float) 2.0, (float) 2.0, (float) 2.5, (float) 0, (float) 0, (float) 0, (float) 0, (float) 1, (float) 0); // inicializamos las bolas, y ... sphere = new Esfera[NUM_BOLAS]; java.util.Random srand = new java.util.Random(); // ...las colocamos dentro del cubo con velocidades iniciales aleatorias y colores aleatorios for (int i = 0; i < NUM_BOLAS; i++) { sphere[i] = new Esfera(1, ((srand.nextFloat() % 10) / (float)20) + (float)0.1, (float)0.05); } } |
| public void display() { // al cubo no le debe afectar el sistema de iluminación GL11.glDisable(GL11.GL_LIGHTING); // limpiamos la pantalla GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // establecemos el color blanco para dibujar GL11.glColor3f((float)1.0, (float)1.0, (float)1.0); // rotamos el cubo en angulo que corresponda en el eje x e y GL11.glRotatef(angle_x, 1.0f, 0.0f, 0.0f); GL11.glRotatef(angle_y, 0.0f, 1.0f, 0.0f); // y dibujamos el cubo drawCube(); // se van a dibujar las esferas. Volvemos a activar la iluminación GL11.glEnable(GL11.GL_LIGHTING); // aplicamos las características del material para la luz ambiental y difusa GL11.glColorMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE); GL11.glEnable(GL11.GL_COLOR_MATERIAL); for (int i = 0; i < NUM_BOLAS; i++) { GL11.glPushMatrix(); // aplicamos el color del material a la esfera que se está dibujando GL11.glColor4f((sphere[i].getColor())[0], (sphere[i].getColor())[1], (sphere[i].getColor())[2], (sphere[i].getColor())[3]); pos = sphere[i].getPosV(); // movemos la esfera a la nueva posición que le corresponda GL11.glTranslatef((float)pos[0], (float)pos[1], (float)pos[2]); Sphere bolita = new Sphere(); bolita.setDrawStyle(GLU.GLU_FILL); bolita.draw((float)sphere[i].getRadio(), 20, 20); GL11.glPopMatrix(); // comprobamos si la bola choca con alguna cara del cubo, y si es así, hacemos que su dirección cambie, y actualizamos su nueva posición sphere[i].test(); } GL11.glDisable(GL11.GL_COLOR_MATERIAL); try { Thread.sleep(30); } catch (InterruptedException e) { } } |
Una buena práctica sería implementar la posibilidad de que las bolas también puedan chocar entre si. Hay varias formas de hacerlo. Una forma que se me ocurre y que es eficiente en cuanto a velocidad, ya que no hay que recorrer todo el array de esferas cada vez que se quiere chequear si una esfera ha chocado con alguna otra, es utilizar una estructura de tabla hash, donde las claves sean la posición de las esferas y los valores los objetos Esfera. Entonces en el test que se comprueba si una esfera ha chocado con alguna cara del cubo, también se chequearía(en caso que no halla chocado con una cara del cubo) si ha chocado con alguna otra esfera. Como sabemos la posición de la esfera y su radio, es fácil saber si está en colisión con otra esfera que esté muy cerca a ella en cuanto a posición(x, y, z), o dicho de una manera más técnica, si está invadiendo algún pixel de otra esfera. Bueno, te reto a que lo intentes. Si lo logras, puedas dejar tu comentario.
Pues hasta aquí todo lo referente a la iluminación. En proximos artículos nos meteremos de lleno con las técnicas de renderizado de texturas sobre las superficies 3D.
Tags: lwjgl, programacion3D, openGL, luz, iluminación