Anteriormente vimos cómo dibujar un hexágono, octágono y un círculo con JOGL pero nunca redimensionamos el frame que los contenía. ¿La razón? pues porque no habíamos modificado el método reshape() utilizado por la interfaz GLEventListener, entonces, al redimensionar un frame puede ocurrir que nuestra figura se distorsione tal y como se ve en ésta imagen:


Circunferencia deformada al redimensionar el JFrame.


Para evitar lo anterior, debemos modificar el código contenido dentro del método reshape() de la siguiente manera:

public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
{
// Cargamos la proyección de nuestra imagen
gl.glMatrixMode (GL.GL_PROJECTION);
gl.glLoadIdentity ();

// Cuando el alto es más grande que el ancho
if (w <= h)
{
// Modificamos el fondo (bottom) y la parte de arriba (top) de
// tal manera que no se deforme nuestra figura
gl.glOrtho(-xRange, xRange,
-yRange * ((float)h/(float)w), yRange * ((float)h/(float)w), -zRange, zRange);
}
// Cuando el ancho es más grande que el alto
else
{
// Modificamos el lado izquierdo (left) y el lado derecho (right) de
// tal manera que no se deforme nuestra figura
gl.glOrtho(-xRange * ((float)w/(float)h), xRange * ((float)w/(float)h),
-yRange, yRange, -zRange, zRange);
}
// Se carga el punto de vista del modelo
// con las nuevas dimensiones (width, height)
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glViewport(x, y, width, height);
// Redibujamos el objeto
canvas.repaint ();
}

Como se puede apreciar en el método anterior, hemos utilizado tres variables nuevas: xRange, yRange, zRange, dichas variables definirán nuestro espacio de trabajo y deben ser declaradas e inicializadas en el constructor de nuestro programa:

float xRange = 5.0f;
float yRange = 5.0f;
float zRange = 5.0f;

Con lo anterior, nuestro espacio de trabajo seguirá comprendiendo los rangos:
  • x = [-5,5]
  • y = [-5,5]
  • z = [-5,5]
El método reshape recibe como parámetros cuatro variables:
  1. GLAutodrawable drawable
  2. int x
  3. int y
  4. int width
  5. int height
Dichas variables definen las nuevas dimensiones de nuestro objeto contenido en GLCanvas y es necesario manipularlas para que la figura final no se deforme. De esta manera, al momento de redimensionar el frame que contiene la figura, no importando si la anchura o altura se incrementa, la figura mostrada dentro del objeto GLCanvas permanecerá sin deformaciones tal y como se muestra en las figuras siguientes:







Si desean descargar el código fuente pueden dar click en el siguiente enlace:

Descargar código fuente dibujarCircunferenciaNODeforme.java


Leer más...

Hasta el momento hemos visto los pricipios básicos sobre dibujar líneas y hemos dibujado un cuadrilátero. Utilizaremos esos mismo principios para dibujar una circunferencia utilizando el mismo código simplemente modificando el método display().

Círculo dibujado con JOGL.



Lo que haremos primero será dibujar un hexágono. Para lograr nuestro cometido, dibujaremos 6 vértices de la siguiente manera:
  1. El primer vértice lo dibujaremos en la coordenada (4, 0).
  2. Haremos rotar dicho vértice 60º (360º/6) y lo volvemos a dibujar en sus nuevas coordenadas.
  3. Repetimos el paso anterior 5 veces para dibujar un total de 6 vértices que formarán nuestro hexágono.
Recordemos la fórmula para hacer rotar un punto un ángulo , el nuevo punto estará definido por:




Nos ayudaremos de un array de tipo float de dimensiones [6][2], los cuales representarán nuestras 6 coordenadas, éste array lo inicializaremos dentro del contructor.

Dentro de los métodos glBegin() y glEnd() declaramos nuestros vértices:

gl.glBegin(GL.GL_LINE_LOOP);
// Inicializamos el primer vértice
// Coordenada x
punto[0][0] = 4.0f;

// Coordenada y
punto[0][1] = 0.0f;

// Dibujamos el primer vértice
gl.glVertex2d(punto[0][0], punto[0][1]);

/* Dibujamos los 5 vértices restantes haciendo rotar
* el anterior 60º, utilizaremos el equivalente en
* radianes ya que las funciones sin y cos del
* paquete Math de Java trabaja con estos últimos */

for (int i = 1; i<6; i++)
{
// Coordenada x' = x*cos(60º) - y*sin(60º)
punto[i][0] = punto[i-1][0]*Math.cos(Math.toRadians(60)) -
punto[i-1][1]*Math.sin(Math.toRadians(60));


// Coordenada y' = x*sin(60º) + y*cos(60º)
punto[i][1] = punto[i-1][0]*Math.sin(Math.toRadians(60)) +
punto[i-1][1]*Math.cos(Math.toRadians(60));


// Dibujamos el nuevo vértice obtenido
gl.glVertex2d(punto[i][0], punto[i][1]);
}
gl.glEnd();

Al compilar y ejecutar el código modificado nos muestra un resultado como el siguiente:

Hexágono dibujado con JOGL.

Ahora volveremos a modificar el código, pero ahora, para dibujar un octágono. Utilizaremos el mismo metodo utilizado anteriormente, sólo que en esta ocasión en vez de rotar 60º (360º/6) el vértice lo haremos rotar 45º (360º/8) y dicho vértice lo dibujaremos 8 veces.

Nos ayudaremos de un array de tipo float de dimensiones [8][2], los cuales representarán nuestras 8 coordenadas, éste array lo inicializaremos dentro del contructor.

Dentro de los métodos glBegin() y glEnd() declaramos nuestros vértices:

gl.glBegin(GL.GL_LINE_LOOP);
// Inicializamos el primer vértice
// Coordenada x
punto[0][0] = 4.0f;

// Coordenada y
punto[0][1] = 0.0f;

// Dibujamos el primer vértice
gl.glVertex2d(punto[0][0], punto[0][1]);

/* Dibujamos los 8 vértices restantes haciendo rotar
* el anterior 45º, utilizaremos el equivalente en
* radianes ya que las funciones sin y cos del
* paquete Math de Java trabaja con estos últimos */

for (int i = 1; i<8; i++)
{
// Coordenada x' = x*cos(45º) - y*sin(45º)
punto[i][0] = punto[i-1][0]*Math.cos(Math.toRadians(45)) -
punto[i-1][1]*Math.sin(Math.toRadians(45));


// Coordenada y' = x*sin(45º) + y*cos(45º)
punto[i][1] = punto[i-1][0]*Math.sin(Math.toRadians(45)) +
punto[i-1][1]*Math.cos(Math.toRadians(45));


// Dibujamos el nuevo vértice obtenido
gl.glVertex2d(punto[i][0], punto[i][1]);
}
gl.glEnd();

Al compilar y ejecutar el código modificado nos muestra un resultado como el siguiente

Octágono dibujado con JOGL.

Como se puede apreciar en los ejemplos anteriores, si seguimos aumentando los lados de las figuras, estas van adquiriendo más la forma de una circunferencia. Modifiquemos una vez más el código pero esta vez para dibujar un polígono circular de 360º. Utilizaremos el mismo metodo utilizado anteriormente, sólo que en esta ocasión en vez de rotar 45º (360º/8) el vértice lo haremos rotar solamente 1º (360º/360) y dicho vértice lo dibujaremos 360 veces.

Nos ayudaremos de un array de tipo float de dimensiones [360][2], los cuales representarán nuestras 360 coordenadas, éste array lo inicializaremos dentro del contructor.

Dentro de los métodos glBegin() y glEnd() declaramos nuestros vértices:

gl.glBegin(GL.GL_LINE_LOOP);
// Inicializamos el primer vértice
// Coordenada x
punto[0][0] = 4.0f;

// Coordenada y
punto[0][1] = 0.0f;

// Dibujamos el primer vértice
gl.glVertex2d(punto[0][0], punto[0][1]);

/* Dibujamos los 359 vértices restantes haciendo rotar
* el anterior 1º, utilizaremos el equivalente en
* radianes ya que las funciones sin y cos del
* paquete Math de Java trabaja con estos últimos */

for (int i = 1; i<360; i++)
{
// Coordenada x' = x*cos(1º) - y*sin(1º)
punto[i][0] = punto[i-1][0]*Math.cos(Math.toRadians(1)) -
punto[i-1][1]*Math.sin(Math.toRadians(1));


// Coordenada y' = x*sin(1º) + y*cos(1º)
punto[i][1] = punto[i-1][0]*Math.sin(Math.toRadians(1)) +
punto[i-1][1]*Math.cos(Math.toRadians(1));


// Dibujamos el nuevo vértice obtenido
gl.glVertex2d(punto[i][0], punto[i][1]);
}
gl.glEnd();

Al compilar y ejecutar el código modificado nos muestra un resultado como el siguiente:

Circunferencia dibujada con JOGL.

Y ahí tenemos nuestra circunferencia hecha con JOGL, como los lados están tan juntos y tan pequeños son casi imperceptibles dándonos el aspecto de un círculo. Lo anterior lo hicimos porque JOGL no ofrece funciones específicas para dibujar circunferencias.

Si desean descargar los códigos fuente de las figuras mostradas en los ejemplos simplemente den click en alguno de los siguientes enlaces:

Descargar código fuente dibujarHexagono.java
Descargar código fuente dibujarOctagono.java
Descargar código fuente dibujaCircunferencia.java

NOTA FINAL
En los ejemplos utilizamos un array bidimensional para dibujar los vértices, ésto fue simplemente para hacerlo entendible. Solo como recomendación, para ahorrar memoria del sistema, no utilicen un array ya que entre más grande sea éste más memoria ocuparán. En vez de utilizar un array bidemensional, simplemente utilicen dos variables llamadas, digamos, coordenadaX y coordenadaY y sobreescribánlas en cada ciclo for utilizando otras dos variables auxiliares. Descarguen el siguiente código fuente para ver la manera correcta de hacerlo:

Descargar código fuente dibujaCircunferencia.java sin utilizar array bidimensional.


Leer más...

Veremos un ejemplo de sencillo de un programa que permite dibujar líneas utilizando algunas variaciones de los métodos glVertex de OpenGL, obviamente, utilizando el lenguaje Java y las librerías de JOGL. Ya explicamos anteriormente cómo dibujar un punto utilizando librerías JOGL, pues bien, ese mismo código lo utillizaremos para dibujar líneas.

Líneas definiendo los lados de un cuadrado con JOGL


El código que modificaremos será el contenido dentro de los métodos:
  • init(GLAutoDrawable drawable)
  • reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
  • display(GLAutoDrawable drawable)
Además, por el momento, no permitiremos que nuestro JFrame se redimensione. Entonces, colocaremos el parámetro del método setRezizable(boolean flag), ubicado dentro del constructor, en false. Comenzaremos explicando las modificaciones dentro de los métodos:

init(GLAutoDrawable drawable)

En el código que utilizamos para dibujar un punto también imprimimos la marca de nuestra tarjeta de video y el sistema operativo en pantalla, en esta ocasión simplemente inicializaremos el color de fondo en negro:

public void init(GLAutoDrawable drawable)
{
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}

reshape(GLAutoDrawable drawable, int x, int y, int width, int height)

En éste método lo que haremos será definir un "espacio de trabajo" que comprende los siguientes rangos:
  • x = [-5, 5]
  • y = [-5, 5]
  • z = [-5, 5]
Como estamos trabajando en dos dimensiones, el eje z será imperceptible. Nuestro código quedará de la siguiente manera:

public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
{
gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity();
gl.glOrtho(-5.0f, 5.0f, -5.0f, 5.0f, -5.0f, 5.0f);
canvas.repaint();
}

Recordemos la manera en que definimos nuestro "espacio de trabajo":
  1. El método glOrtho(double left, double right, double bottom, double top, double near, double far) se utiliza para definir la proyección ortográfica.
  2. Por lo tanto, dicho método creará un "espacio de trabajo" similar a un cubo dónde La esquina inferior izquierda de enfrente está definida por las coordenadas (left, bottom, far) y La esquina superior derecha de atrás está definida por las coordenadas (right, top, near).
Definición de nuestro "espacio de trabajo"

display(GLAutoDrawable drawable)

Aquí modificaremos el código de tal manera que podamos utilizar los diferentes métodos para trazar líneas y poder formar un polígono. Primero comenzaremos limpiando los buffers que utiliza nuestra tarjeta de video para dibujar y definiremos el color con el que dibujaremos nuestras líneas. En este caso yo he decidido utilizar el color CYAN, sin embargo, podemos utilizar cualquier otro color siempre y cuando sea diferente al que definimos como fondo.

gl.glClear(GL.GL_COLOR_BUFFER_BIT);
gl.glColor3f(0.0f, 1.0f, 1.0f);

Ahora le indicaremos a JOGL cuáles son los gráficos que se dibujarán utilizando los métodos glBegin(GLEnum Mode) y glEnd(). Recordemos que dentro de estos métodos irán todos los gráficos que serán mostrados dentro de nuestro objeto GLCanvas. Utilizaremos el método glVertex2d(double x, double y) para indicar a JOGL dónde inician y dónde terminan los vértices de las líneas que dibujaremos.

En este ejemplo, lo que haremos será dibujar un cuadrado. Para lograr nuestro cometido simplemente dibujaremos 4 vértices:
  1. (-4, -4)
  2. (4, -4)
  3. (4, 4)
  4. (-4, 4)
Nos ayudaremos de un array de tipo float de dimensiones [4][2], los cuales representarán nuestras 4 coordenadas, éste array lo inicializaremos dentro del constructor.

Dentro de los métodos glBegin() y glEnd() declaramos nuestros vértices:

gl.glBegin(GL.GL_LINE_LOOP);
// Inicializamos el primer vértice
// Coordenada x (primer vértice)
punto[0][0] = -4.0;
// Coordenada y (primer vértice)
punto[0][1] = -4.0;

// Inicializamos el segundo vértice
// Coordenada x (segundo vértice)
punto[1][0] = 4.0;
// Coordenada y (segundo vértice)
punto[1][1] = -4.0;

// Inicializamos el tercer vértice

// Coordenada x (tercer vértice)
punto[2][0] = 4.0;
// Coordenada y (tercer vértice)
punto[2][1] = 4.0;

// Inicializamos el cuarto vértice

// Coordenada x (cuarto vértice)
punto[3][0] = -4.0;
// Coordenada y (cuarto vértice)
punto[3][1] = 4.0;

// Dibujamos TODOS los vértices

gl.glVertex2d(punto[0][0], punto[0][1]);
gl.glVertex2d(punto[1][0], punto[1][1]);
gl.glVertex2d(punto[2][0], punto[2][1]);
gl.glVertex2d(punto[3][0], punto[3][1]);

gl.glEnd();
gl.glFlush();


Al compilar y ejecutar el código modificado nos muestra un resultado como el siguiente:


Líneas utilizando el parámetro GL.GL_LINE_LOOP

El parámetro Mode del método glBegin(GLEnum Mode) será el que modificaremos para mostrar las diferentes formas de dibujar líneas con JOGL. En el ejemplo anterior se utilizó GL_LINE_LOOP, este modo conecta TODOS los vértices con segmentos de líneas de la siguiente manera:
  • Se traza un segmento de línea del primer vértice hacia el segundo.
  • Se traza un segmento de línea del segundo vértice hacia el tercero.
  • . . .
  • Se traza un segmento de línea del último vértice hacia el primero.
Con el parámetro GL_LINES cada par sucesivo de vértices, definidos dentro de los métodos glBegin() y glEnd(), genera un segmento de línea. Si modificamos el código del método:

gl.glBegin(GL.GL_LINE_LOOP);

por:

gl.glBegin(GL.GL_LINES);

obtenemos un resultado como el siguiente:


Líneas utilizando el parámetro GL.GL_LINES

El parámetro GL_LINE_STRIP hace que los vértices definidos dentro de los métodos glBegin() y glEnd() generen una secuencia de segmentos de línea donde el punto final de un segmento de línea será el punto inicial del siguiente segmento de línea, algo parecido a lo que ocurre con GL_LINE_LOOP con la diferencia de que el último vértice no genera un segmento de línea con el primer vértice. Si modificamos el código del método:

gl.glBegin(GL.GL_LINE_LOOP);

por:

gl.glBegin(GL.GL_LINE_STRIP);

obtenemos un resultado como el siguiente:

Líneas utilizando el parámetro GL.GL_LINE_STRIP

Es posible cambiar el grosor de la línea utilizando el método:

gl.glLineWidth(float width);

Por ejemplo si modificamos el código del método:

gl.glBegin(GL.GL_LINE_LOOP);

por:

gl.glLineWidth(5);
gl.glBegin(GL.GL_LINE_LOOP);

obtenemos un resultado como el siguiente:

Puntos utilizando el método gl.glLineWidth(5)

¿Que sucede si simplemente dibujamos los vértices? Modicamos el código del método:

gl.glBegin(GL.GL_LINE_LOOP);

por:

// Puntos de 12 pixeles para que se puedan apreciar
gl.glPointSize(12);
gl.glBegin(GL.GL_POINTS);

obtenemos un resultado como el siguiente:

Puntos utilizando el parámetro GL.GL_POINTS

Si desean descargar el código fuente puden dar click en el siguiente enlace:

Descargar código fuente dibujaLineas.java


Leer más...