Laboratorio 001: Herramientas de desarrollo de la Asignatura

publicado a la‎(s)‎ 9 may 2012, 8:48 por Hernan Nina Hanco   [ actualizado el 17 sept 2012, 14:47 ]

I) Objetivo

  • Proporcionar al estudiante opciones de herramientas de desarrollo para el desarrollo de aplicativos en la asignatura de Computación Gráfica I.

II) Marco conceptual

Introducción a OpenGL

En OpenGL se proporciona una biblioteca básica de funciones para especificar primitivas gráficas, atributos, transformaciones geométricas, transformaciones de visualización y muchas otras operaciones. Está diseñada para ser independiente del hardware, por tanto, muchas operaciones, tales como las subrutinas de entrada y salida, no están incluidas en la biblioteca básica. Sin embargo, las subrutinas de entrada y salida y muchas funciones adicionales están disponibles en bibliotecas auxiliares que se han desarrollado para programas OpenGL.


Sintaxis básica de OpenGL

Los nombres de las funciones de la biblioteca básica de OpenGL utiliza como prefijo gl.

glBegin, glClear, glCopyPixels, glPolygonMode

Todas las constantes comienzan con las letras GL en mayúsculas.

GL_2D, GL_RGB, GL_CCW, GWOLYGON, GL_AMB I ENT_AND_D IFFUSE

Las funciones de OpenGL también esperan tipos de datos específicos. Por ejemplo, GLbyte, GLshort, GLint, GLfloat, GLdouble, GLboolean.


A algunos argumentos de funciones de OpenGL se les puede asignar valores empleando una matriz que enumera un conjunto de valores de datos. Esta opción se utiliza para especificar una lista de valores como un puntero a una matriz, en lugar de especificar cada elemento de la lista explícitamente como un argumento. Un ejemplo típico del uso de esta opción es la especificación de los valores de las coordenadas xyz.


Bibliotecas relacionadas

Existe un gran número de bibliotecas relacionadas para la realización de operaciones especiales, además de la biblioteca básica de OpenGL. La utilidad GLU (OpenGL Utility) proporciona subrutinas para la configuración de las matrices de visualización y proyección, descripción de objetos complejos mediante líneas y aproximaciones poligonales, visualización de cuádricas y splines B empleando aproximaciones lineales, procesamiento de operaciones de representación de superficies y otras tareas complejas. Toda implementación de OpenGL incluye la biblioteca GLU. Todos los nombres de las funciones de GLU comienzan con el prefijo glu. También existe un conjunto de herramientas orientadas a objetos basado en OpenGL, llamado Open Inventor que proporciona subrutinas y formas de objetos predefinidos para su uso en aplicaciones tridimensionales interactivas.

Para crear gráficos utilizando OpenGL, necesitamos en primer lugar configurar una ventana de visualización en nuestra pantalla de vídeo. Se trata simplemente de la zona rectangular de la pantalla en la que nuestra imagen se mostrará. No podemos crear directamente la ventana de visualización con las funciones de OpenGL básicas, ya que esta biblioteca contiene únicamente funciones gráficas independientes del dispositivo, y las operaciones de gestión de ventanas dependen de la computadora que estemos utilizando. Sin embargo, existen varias bibliotecas de sistema de ventanas que soportan las funciones de OpenGL en una gran variedad de máquinas. El kit de herramientas GLUT (OpenGL Utility Toolkit) proporciona una biblioteca de funciones para interactuar con cualquier sistema de ventanas. Las funciones de la biblioteca GLUT utilizan como prefijo glut. Esta biblioteca también contiene métodos para describir y representar superficies y curvas cuádricas.


Programación OpenGL en Java

OpenGL es compatible con principales sistemas operativos, funciona con cualquier sistema de ventanas, y se puede utilizar desde muchos lenguajes de programación. Ofrece total independencia de los protocolos de red y topologías.

En java existen APIs variadas que permite la escritura de aplicaciones OpenGL en java, por ejemplo las siguientes:

  • Proyecto  JOGL soportado por OpenGL API (JSR-231), JOGL provee un acceso completo a las APIs de OpenGL 1.3 - 3.0.

  • Lightweight Java Game Library

  • Java 3D

  • Java 3D for Mac OS X

  • OpenGL for Java (GL4Java)

  • YAJOGLB

  • jGL: a 3D graphics library for the Java


III) Prácticas

1) Configuración inicial de JOGL en Netbeans

Esta práctica está destinado a practicar la implementación JOGL desde sus inicios. Ayuda a configurar una instalación reciente JOGL en Netbeans en Windows.

En primer lugar se necesita descargar JOGL. se puede descargar los últimos binarios JOGL de http://schabby.de/jogl-download/.

Para esta práctica se utilizó los binarios:

  • jogl-2.0-b752-20120504-windows-i586

  • gluegen-2.0-b552-20120504-windows-i586


Descargados estos archivos, debemos descomprimirlos y luego añadir a la librería de nuestra aplicación en java los paquetes de clases Jar siguientes:

  • gluegen-rt.jar

  • gluegen-rt-natives-windows-i586.jar

  • jogl.all.jar

  • jogl-all-natives-windows-i586.jar


Una vez cargados estos Jar en la librería crear las Renderer y Ventana como se muestra en la figura:

Clase Ventana


package geometrias.frontend;


import geometrias.Renderer_Punto;

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 javax.swing.JFrame;


/**

*

* @author hernan

*/

public class Ventana {


   public static void main(String[] args) {

       // 1. Configuración de OpenGL Version 2

       GLProfile profile = GLProfile.get(GLProfile.GL2);

       GLCapabilities capabilities = new GLCapabilities(profile);


       // 2. Canvas es el aplicativo gráfico que se empotra en un JFrame

       GLCanvas glcanvas = new GLCanvas(capabilities);

       glcanvas.addGLEventListener(new Renderer_Punto());

       glcanvas.setSize(400, 400);

       

       // 3. Crear la ventana para mostrar la aplicación de dibujo

       JFrame frame = new JFrame("Aplicación de OpenGL");

       frame.getContentPane().add(glcanvas);

       // 4. Añadir el evento para cerrar la ventana

       frame.addWindowListener(new WindowAdapter() {

           @Override

           public void windowClosing(WindowEvent ev) {

               System.exit(0);

           }

       });

       // 5. Cambiar el tamaño de la ventana y visualizarla

       frame.setSize(frame.getContentPane().getPreferredSize());

       frame.setVisible(true);

   }

}


Clase Renderer_Punto


package geometrias;


import java.util.logging.Level;

import java.util.logging.Logger;

import javax.media.opengl.GL2;

import javax.media.opengl.GLAutoDrawable;

import javax.media.opengl.GLEventListener;


/**

*

* @author hernan

*/

public class Renderer_Punto implements GLEventListener {


   static final Logger logger = Logger.getLogger("BasicLoggingExample");

   //     

   private GL2 gl;


   @Override

   public void init(GLAutoDrawable gLDrawable) {

       logger.log(Level.INFO, "método - init");

       // Provee un objeto que enlaza las APIs del OpenGL

       // Que se encargara de realizar las instrucciones de dibujos

       gl = gLDrawable.getGL().getGL2();


       // 6. Especificar el color del dibujo: gris

       gl.glColor3f(0.5f, 0.5f, 0.5f);

       gl.glDrawBuffer(GL2.GL_FRONT_AND_BACK);

   }


   @Override

   public void reshape(GLAutoDrawable glad, int x, int y, int width,

           int height) {

       logger.log(Level.INFO, "Reshape");

       // 7. Especificar el área de dibujo (frame) utilizamos coordenadas

       gl.glMatrixMode(GL2.GL_PROJECTION);

       gl.glLoadIdentity();

       gl.glOrtho(0, width, 0, height, -1.0, 1.0);

   }


   @Override

   public void display(GLAutoDrawable drawable) {

       logger.log(Level.INFO, "Display");

       // 8. Especificar el dibujo de un punto

       gl.glPointSize(10); // Determina el tamaño de un punto

       gl.glBegin(GL2.GL_POINTS);

       gl.glVertex2i(350, 350);

       gl.glEnd();

   }

   @Override

   public void dispose(GLAutoDrawable glad) {

       throw new UnsupportedOperationException("Not supported yet.");

   }


}


Resultado:


IV) Tarea

1) En base a la aplicación de la práctica modifique la aplicación cambiar el color de la ventana a blanco.

2) Modificar el programa de la práctica para dibujar puntos aleatorios en la ventana.

3) Modificar el programa de la práctica para que el programa pueda solicitar al usuario coordenadas de puntos para que se dibujen en la ventana.


V) Referencias

VI) Solución de Ejercicios
Ejercicio 2: Modificar el programa de la práctica para dibujar puntos aleatorios en la ventana.

La Clase Ventana no varia, solo se cambiar el Renderer_Punto utilizado en anteriores programas, por esta nueva clase Renderer_Punto_Aleatorios. El método Display es la que hace los dibujos en este caso dibuja puntos, se ha añadido un bucle for donde se genera puntos aleatorios con la el Math.Random y luego de ello se llama a un método que dibujo un punto, de esta manera obtenemos el dibujo de puntos.
package geometrias.puntos; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.opengl.GL import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; /** * * @author hernan */ public class Renderer_Punto_Aleatorios implements GLEventListener { static final Logger logger = Logger.getLogger("BasicLoggingExample"); // protected GL2 gl; @Override public void init(GLAutoDrawable gLDrawable) { logger.log(Level.INFO, "método - init"); // Provee un objeto que enlaza las APIs del OpenGL // Que se encargara de realizar las instrucciones de dibujos gl = gLDrawable.getGL().getGL2(); // 6. Especificar el color del dibujo: Rojo gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glDrawBuffer(GL2.GL_FRONT_AND_BACK); } @Override public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { logger.log(Level.INFO, "Reshape"); // 7. Especificar el área de dibujo (frame) utilizamos coordenadas gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrtho(0, width, 0, height, -1.0, 1.0); } @Override public void display(GLAutoDrawable drawable) { for (int i = 1; i <= 20; i++) { // 7. Generar un punto de coordenadas aleatorias double x = Math.random() * 400; double y = Math.random() * 400; // Especificar aleatoriamente el color de dibujo gl.glColor3d(Math.random(), Math.random(), Math.random()); gl.glPointSize(5); // Dibujar un punto dibujarPunto(x, y); } } protected void dibujarPunto(double x, double y) { gl.glBegin(GL.GL_POINTS); gl.glVertex2d(x, y); gl.glEnd(); } @Override public void dispose(GLAutoDrawable glad) { // throw new UnsupportedOperationException("Not supported yet."); } }

Resultado:

Ejercicio 3) Modificar el programa de la práctica para añadir un panel de ingreso de valores de coordenadas x, y de un punto por el usuario, y en base a ello dibujar el punto correspondiente en la ventana.

Para dar solución a este problema vamos a generar una nueva ventana la cual lleva el siguiente diseño de la figura. Se requiere, dos paneles para visualizar el gráfico de OpenGL y un panel de ingreso de datos.
El diseño lo desarrollamos en la siguiente clase: Ventana_Entrada

package geometrias.frontend; import geometrias.puntos.Renderer_Punto_Entrada; import java.awt.Container; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import javax.swing.JFrame; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.border.EtchedBorder; public class Ventana_Entrada extends JFrame implements ActionListener { // Atributos de Clase // objetos de swing private JPanel pOpenGL; private JPanel pEntrada; private JButton btnDibujar; private JTextField txtX; private JTextField txtY; // objetos de libreria JOGL private GLCanvas glCanvas; // Objeto graficador de un punto private Renderer_Punto_Entrada render_punto; public Ventana_Entrada() { inicializarVentana(); } // Inicializar la ventana private void inicializarVentana() { // habilita el botón cerrar de la ventana setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Crear un panel para ubicar el graficador Opengl pOpenGL = new JPanel(new BorderLayout()); pOpenGL.setBorder(new TitledBorder( new EtchedBorder(), // Tipo de Borde "OpenGL")); // Título del borde // Añadir el graficador al panel de OpenGL // 1. Configuración de OpenGL Version 2 GLProfile profile = GLProfile.get(GLProfile.GL2); GLCapabilities capabilities = new GLCapabilities(profile); // 2. Canvas es el aplicativo gráfico que se empotra en un JFrame - Ventana glCanvas = new GLCanvas(capabilities); render_punto = new Renderer_Punto_Entrada(); glCanvas.addGLEventListener(render_punto); pOpenGL.add(glCanvas); // Se añade el graficador OpenGL al panel glCanvas.setSize(500,500); // Crear el panel de entrada de datos pEntrada = new JPanel(); pEntrada.setBorder(new TitledBorder( new EtchedBorder(), // Tipo de Borde "Datos de gráfico")); // Añadir controles JLabel lblX = new JLabel("X: "); txtX = new JTextField(5); JLabel lblY = new JLabel("Y: "); txtY = new JTextField(5); btnDibujar = new JButton("Dibujar"); // Añadir los controles al panel de entrada de datos pEntrada.add(lblX); pEntrada.add(txtY); pEntrada.add(lblY); pEntrada.add(txtX); pEntrada.add(btnDibujar); // hacer que el botón capte eventos cuando se hace click sobre él. btnDibujar.addActionListener(this); // Añadir los paneles en la ventana // Obtener el contenedor de componentes Container content = getContentPane(); content.add(pOpenGL, BorderLayout.CENTER); content.add(pEntrada, BorderLayout.SOUTH); // Mostrar ventana pack(); setVisible(true); } /* * Método para tratar eventos en el formulario. */ @Override public void actionPerformed(ActionEvent e) { // Identificar el objeto o control donde se genero el evento Object source = e.getSource(); if (source == btnDibujar) { // si hay evento click en el botón // ubicar las nuevas coordenadas del punto int x = Integer.parseInt(txtX.getText()); int y = Integer.parseInt(txtY.getText()); // actualizar los valores de los puntos en el dibujador render_punto.setX(x); render_punto.setY(y); // repintar el nuevo punto glCanvas.repaint(); } } public static void main(String args[]) { // iniciar la ventana Ventana_Entrada ventana; ventana = new Ventana_Entrada(); } }


La siguiente clase denominada Renderer_Punto_Entrada, se añade dos atributos x,y que representan las coordenadas el punto, estos valores son utilizados para dibujar el punto.

package geometrias.puntos; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; /** * * @author hernan */ public class Renderer_Punto_Entrada implements GLEventListener { static final Logger logger = Logger.getLogger("BasicLoggingExample"); // protected GL2 gl; private int x; private int y; public Renderer_Punto_Entrada() { this.x = 0; this.y = 0; } public Renderer_Punto_Entrada(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } @Override public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { logger.log(Level.INFO, "Reshape"); // 7. Especificar el área de dibujo (frame) utilizamos coordenadas gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrtho(0, width, 0, height, -1.0, 1.0); } @Override public void display(GLAutoDrawable drawable) { gl.glClear(GL2.GL_COLOR_BUFFER_BIT); // Especificar aleatoriamente el color de dibujo gl.glColor3d(Math.random(), Math.random(), Math.random()); gl.glPointSize(10); // Dibujar un punto dibujarPunto(this.x, this.y); } protected void dibujarPunto(double x, double y) { gl.glBegin(GL.GL_POINTS); gl.glVertex2d(x, y); gl.glEnd(); } @Override public void init(GLAutoDrawable glad) { logger.log(Level.INFO, "método - init"); // Provee un objeto que enlaza las APIs del OpenGL // Que se encargara de realizar las instrucciones de dibujos gl = glad.getGL().getGL2(); // 6. Especificar el color del dibujo: Rojo gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glDrawBuffer(GL2.GL_FRONT_AND_BACK); } @Override public void dispose(GLAutoDrawable glad) { } }


Resultado:

Vídeo de YouTube





Comments