CMSC 405 OpenGL and Java

By: Nicholas Duchon
Date: Sep 20, 2016


Outline:
My pages
Other pages


GLEW:


Mac GLUT deprecation:

Setup:

A code example:


Code:

// File: Project1.java
// Date: Aug 4, 2016
// Author: Nicholas Duchon
// Purpose: reproduce Duane Jarc's C++ Project 1
//   in Java using JOGL
// Environment:
//   JDK 8
//   JOGL - jar libraries:
//      JOGL/jogamp-all-platforms/jar/gluegen-rt.jar
//      JOGL/jogamp-all-platforms/jar/jogl-all.jar
//   API:
//      https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/
//      https://jogamp.org/
//   See:
//      GLUT class for predefined objects

import javax.swing.JFrame;     // hold the GUI stuff
import javax.swing.JButton;    // add a control
import javax.swing.JSplitPane; // put two JOGL panels into frame
import java.awt.BorderLayout;  // put JOGL stuff in center of screen

// ND: Your code may need to reference:
//     com.jogamp package rather than javax.media
// for example:
//  import com.jogamp.opengl.GL2;

import javax.media.opengl.awt.GLJPanel;    // ND: location of GLJPanel for java JPanel
import javax.media.opengl.GLEventListener; // make JOGL work
import javax.media.opengl.GLAutoDrawable;  // parameter for event listener interfaces
import javax.media.opengl.GL2;             // drawing graphic context

public class Project1 extends JFrame {
   public static final long serialVersionUID = 982374; // garbage value
 
   int count = 0; // button counter to test button events
   JButton jbA;   // just for fun, and an example
 
   public Project1 (String t) {
      setSize(200, 200);
      setVisible (true);
      setLocationRelativeTo (null);
      setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
     
      jbA = new JButton ("One: " + count);
      add (jbA, BorderLayout.NORTH);
      jbA.addActionListener (e -> buttonPress ());
     
      MyGLPanel mg1 = new MyGLPanel (new float [] { 1f, .5f, 1f, 0f});
      MyGLPanel mg2 = new MyGLPanel (new float [] {.5f, .5f, 1f, 0f});
     
      JSplitPane jsp = new JSplitPane (1, mg1, mg2); // 0 = -, 1 = |
      jsp.setDividerLocation (130);
      add (jsp, BorderLayout.CENTER);
     
      validate (); // show button and other stuff
  
} // end String constructor
 
   void buttonPress () {
      jbA.setText ("Count:  " + ++count);
  
} // end method buttonPress
 
   public static void main (String args []) {
      new Project1 ("JOGL Project 1");
      System.out.println ("--- Done ---");
  
} // end main
} // end class Project1

class MyGLPanel extends
   GLJPanel                    // extends javax.swing.JPanel
   implements GLEventListener  // 4 methods: init, display, reshape, dispose
{

   public static final long serialVersionUID = 23; // garbage value
   float [] bc = {0f, 1f, 1f, 0f}; // background color
  
   { addGLEventListener (this); } // instance initializer
  
   public MyGLPanel () {} // end constructor
  
   // background color constructor
   public MyGLPanel (float [] pbc) {bc = pbc;}
 
   public void init    (GLAutoDrawable d) {}
   public void reshape (GLAutoDrawable d, int x, int y, int w, int h) {}
   public void dispose (GLAutoDrawable d) {}

   public void display (GLAutoDrawable d) {
      GL2 gl = d.getGL().getGL2();
   //       drawOne (gl);
      drawTwo (gl);
  
} // end interface method display
  
   // GL_POINTS mode
   void drawTwo (GL2 gl) {
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
      double r1 = .2, r2 = .5, dx = .2, dy = -.2;
      double s, c;
     
      gl.glPointSize (3f);  // measured in pixels?
      gl.glBegin (GL2.GL_POINTS);
      {
         for (double d = 0; d < 2 * Math.PI; d += Math.PI / 30) {
            s = r1 * Math.sin (d); // draws ellipses,
            c = r2 * Math.cos (d);
            gl.glColor4f  (1f, 0f, 0f, 0f);  // foreground color = red
            gl.glVertex2d (s + dx, c + dy);
            gl.glColor4f  (0f, 0f, 0f, 0f);  // foreground color = black
            gl.glVertex2d (s - dx, c + dy);
            gl.glColor4f  (1f, 1f, 0f, 0f);  // foreground color = yellow
            gl.glVertex2d (s + dx, c - dy);
            gl.glColor4f  (1f, 1f, 1f, 0f);  // foreground color = white
            gl.glVertex2d (s - dx, c - dy);
         } // end for every entry in circle
      } gl.glEnd (); // end points in GL2
  
  
} // end method drawTwo
  
   // GL_TRIANGLES mode
   void drawOne (GL2 gl) {
      // three triangles:
      float[] coords = {  0  ,   0, -.5F, -.5F, .5f, -.5F
                        , .3f, .3f,  .2f,  .2f, .4f,  .2f
                        , .0f, .0f,   4f,   0f, 4f,   -4f
                       };
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
  
      gl.glBegin(GL2.GL_TRIANGLES); // solid triangle
      {
         // first triangle, vertex colors blended
         gl.glColor4f    (1f, 0f, 0f, 0f);  // foreground color = red
         gl.glVertex2fv(coords, 0);         // first vertex data starts at index 0
         gl.glColor4f    (0f, 0f, 1f, 0f);  // foreground color = blue
         gl.glVertex2fv(coords, 2);         // second vertex data starts at index 2
         gl.glColor4f    (1f, 1f, 0f, 0f);  // foreground color = yellow
         gl.glVertex2fv(coords, 4);         // third vertex data starts at index 4
     
         // second triangle - yellow
         gl.glColor4f    (1f, 1f, 0f, 0f);  // foreground color = yellow
         gl.glVertex2fv(coords, 6);         // 3 vertices, start locations 6,8,10
         gl.glVertex2fv(coords, 8);         //
         gl.glVertex2fv(coords, 10);        //
     
         // third triangle - yellow, oversized
         gl.glColor4f  (0f, 1f, 0f, 0f);     // foreground color = green
         gl.glVertex2fv(coords, 12);         // 3 vertices, start locations 6,8,10
         gl.glVertex2fv(coords, 14);         //
         gl.glVertex2fv(coords, 16);         //
     
      } gl.glEnd(); 
     
      gl.glTranslated (-.5, .2, 0);
      gl.glRectd (0, 0, .2, .2);
      gl.glTranslated (.5, -.2, 0);
  
   } // end method drawOne

} // end class MyGLPanel

// Primitives, as in, modes of glBegin:
//   gl.glBegin (GL2.<primitive>);
// GL_POINTS
// GL_LINES
// GL_LINE_STRIP
// GL_LINE_LOOP
// GL_TRIANGLES
// GL_TRIANGLE_FAN
// GL_POLYGON

// figure methods in GL2
//  

// import com.jogamp.opengl.util;
// import javax.media.opengl.GLCapabilities;  // setup in parent class?
// import javax.media.opengl.GLProfile;       // more setup?
// import javax.media.opengl.awt.GLCanvas;        // ??

// ------- GLEventListener: INTERFACE methods -------//
//   public void init    (GLAutoDrawable d) {}
//   public void display (GLAutoDrawable d) {}
//   public void reshape (GLAutoDrawable d, int x, int y, int w, int h) {}
//   public void dispose (GLAutoDrawable d) {}

// GLCanvas // ND: Canvas and JPanel seem to work about the same way

//         gl.glClear(javax.media.opengl.GL.GL_DEPTH_BUFFER_BIT);
//         gl.glLoadIdentity();

//    public void init    (GLAutoDrawable d) {
//       GL2 gl = d.getGL().getGL2();
//         gl.glShadeModel(javax.media.opengl.fixedfunc.GLLightingFunc.GL_SMOOTH);
//         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//         gl.glClearDepth(1.0f);
//         gl.glEnable(javax.media.opengl.GL.GL_DEPTH_TEST);
//         gl.glDepthFunc(javax.media.opengl.GL.GL_LEQUAL);
//         gl.glHint(javax.media.opengl.GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT,
//               javax.media.opengl.GL.GL_NICEST);
//    } // end init from JOGLQuad.java - none of this is required for a simple triangle

   //       setupJOGL ();

   /**
    * Create the basics of the JOGL screen details.
    */
//    private void setupJOGL()
//    {
//    //         GLCapabilities caps = new GLCapabilities();
//       GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); // ND:
//       caps.setDoubleBuffered(true);
//       caps.setHardwareAccelerated(true);
//   
//       canvas = new GLCanvas(caps);
//       canvas.addGLEventListener(this);
//   
//       add(canvas, BorderLayout.CENTER);
//   
//       Animator anim = new Animator(canvas);
//       anim.start();
//    }



glutBitmapString

The code needed on a Mac to implement this call:

void glutBitmapString (void * fontID, const char * string) {
    for(int c = 0; c < strlen( ( char * )string ); c++ )
        glutBitmapCharacter(fontID, string[c]);
} // end local method from freeGLUT

// Sample call:
  const char * x = "this is a test";
  glutBitmapString (GLUT_BITMAP_HELVETICA_12, x);


Second Example:



Code:

// File: Project1.java
// Date: Aug 4, 2016
// Author: Nicholas Duchon
// Purpose: reproduce Duane Jarc's C++ Project 1
//   in Java using JOGL
//   now experimenting with JOGL issues
// Environment:
//   JDK 8
//   JOGL - jar libraries:
//      JOGL/jogamp-all-platforms/jar/gluegen-rt.jar
//      JOGL/jogamp-all-platforms/jar/jogl-all.jar
//   API:
//      https://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/
//      https://jogamp.org/
//   See:
//      GLUT class for predefined objects

import javax.swing.JFrame;     // hold the GUI stuff
import javax.swing.JButton;    // add a control
import javax.swing.JSplitPane; // put two JOGL panels into frame
import java.awt.BorderLayout;  // put JOGL stuff in center of screen
import java.awt.Font;
import java.util.Random;

// ND: Your code may need to reference - careful, some classes in one package, some in the other
//     com.jogamp
//     javax.media

//   documentation differentiates javax.media stuff from com.jogamp stuff!
//          see the documentation link:
//        >>>> https://jogamp.org/deployment/v2.1.0/javadoc/jogl/javadoc/index.html

// The following worked in my installation of JOGL

import javax.media.opengl.awt.GLJPanel;    // ND: location of GLJPanel for java JPanel
import javax.media.opengl.GLEventListener; // make JOGL work
import javax.media.opengl.GLAutoDrawable;  // parameter for event listener interfaces
import javax.media.opengl.GL2;             // drawing graphic context
import javax.media.opengl.GL;

import com.jogamp.opengl.util.awt.TextRenderer;  // Fancy text using fonts and integer font locations
// import com.jogamp.opengl.util.gl2.GLUT;          // plain text using double font locations.

public class Project1 extends JFrame {
   public static final long serialVersionUID = 982374; // garbage value
 
   int count = 0; // button counter to test button events
 
   public Project1 (String t) {
      setSize(1300, 300);
      setTitle (t);
      setVisible (true);
      setLocationRelativeTo (null);
      setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
     
      // just for fun, and an example
      JButton jbA = new JButton ("One: " + count);
      add (jbA, BorderLayout.NORTH);
      jbA.addActionListener (e -> jbA.setText ("Count:  " + ++count));
     
      MyGLPanel mg1 = new MyGLPanel (1, new float [] { 1f, .5f,  1f, 0f});
      MyGLPanel mg2 = new MyGLPanel (2, new float [] {.5f, .5f,  1f, 0f});
      MyGLPanel mg3 = new MyGLPanel (3, new float [] { 1f,  1f,  0f, 0f});
      MyGLPanel mg4 = new MyGLPanel (4, new float [] { 1f, .5f, .5f, 0f});
      MyGLPanel mg5 = new MyGLPanel (5, new float [] { 1f,  1f,  1f, 0f});
     
      JSplitPane jsp1 = new JSplitPane (1,  mg1, mg2); // 0 = -, 1 = |
      jsp1.setDividerLocation (200);
      JSplitPane jsp2 = new JSplitPane (1, jsp1, mg3); // 0 = -, 1 = |
      jsp2.setDividerLocation (400);
      JSplitPane jsp3 = new JSplitPane (1, jsp2, mg4); // 0 = -, 1 = |
      jsp3.setDividerLocation (800);
      JSplitPane jsp4 = new JSplitPane (1, jsp3, mg5); // 0 = -, 1 = |
      jsp4.setDividerLocation (1000);
      add (jsp4, BorderLayout.CENTER);
     
      validate ();
     
  
} // end String constructor
 
   public static void main (String args []) {
      new Project1 ("JOGL Project 1");
      System.out.println ("--- Done ---");
  
} // end main
} // end class Project1

class MyGLPanel extends
   GLJPanel                    // extends javax.swing.JPanel
   implements GLEventListener  // 4 methods: init, display, reshape, dispose
{

   public static final long serialVersionUID = 23; // garbage value
   float [] bc = {0f, 1f, 1f, 0f}; // background color
   int type = 0; // select what is displayed on this panel, see display method below
  
   { addGLEventListener (this); } // instance initializer
  
   public MyGLPanel () {} // end constructor
  
   // background color constructor
   public MyGLPanel (int t, float [] pbc) {type = t; bc = pbc;}
 
   public void init    (GLAutoDrawable d) {
           // called when the panel is created
      if (type == 5) { // 3d drawing panel
         GL2 gl = d.getGL().getGL2();
         gl.glClearColor(0.8F, 0.8F, 0.8F, 1.0F);
         gl.glEnable(GL.GL_DEPTH_TEST);
         gl.glEnable(GL2.GL_LIGHTING);
         gl.glEnable(GL2.GL_LIGHT0);
         gl.glEnable(GL2.GL_COLOR_MATERIAL);
      } // end if type = 5
  
} // end interface method init

   public void reshape (GLAutoDrawable d, int x, int y, int w, int h) {}
   public void dispose (GLAutoDrawable d) {}

   public void display (GLAutoDrawable d) {
      GL2 gl = d.getGL().getGL2();
      switch (type) {
         case 1: drawOne   (gl);
            break;
         case 2: drawTwo   (gl);
            break;
         case 3: drawThree (d);
            break;
         case 4: drawFour  (d);
            break;
         case 5: drawFive  (d);
            break;
      } // end switch type
  
} // end interface method display
  
   // GL_TRIANGLES mode
   void drawOne (GL2 gl) {
      // three triangles:
      float[] coords = {  0  ,   0, -.5F, -.5F, .5f, -.5F
                        , .3f, .3f,  .2f,  .2f, .4f,  .2f
                        , .0f, .0f,   4f,   0f, 4f,   -4f
                       };
      int dim   =    2; // dimension, coordinates per point
      int index = -dim; // walk through coordinates, always index += dim
  
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]);          // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
  
      gl.glBegin(GL2.GL_TRIANGLES); // solid triangle
      {
         // first triangle, vertex colors blended
         gl.glColor4f    (1f, 0f, 0f, 0f);     // foreground color = red
         gl.glVertex2fv(coords, index += dim); // first vertex data starts at index 0
         gl.glColor4f    (0f, 0f, 1f, 0f);     // foreground color = blue
         gl.glVertex2fv(coords, index += dim); // second vertex data starts at index 2
         gl.glColor4f    (1f, 1f, 0f, 0f);     // foreground color = yellow
         gl.glVertex2fv(coords, index += dim); // third vertex data starts at index 4
     
         // second triangle - yellow
         gl.glColor4f    (1f, 1f, 0f, 0f);     // foreground color = yellow
         gl.glVertex2fv(coords, index += dim); // 3 vertices, start locations 6,8,10
         gl.glVertex2fv(coords, index += dim); //
         gl.glVertex2fv(coords, index += dim); //
     
         // third triangle - green, oversized
         gl.glColor4f  (0f, 1f, 0f, 0f);       // foreground color = green
         gl.glVertex2fv(coords, index += dim); // 3 vertices, start locations 12, 14, 16
         gl.glVertex2fv(coords, index += dim); //
         gl.glVertex2fv(coords, index += dim); //
     
      } gl.glEnd(); 
     
      gl.glTranslated (-.5, .2, 0);
      gl.glRectd (0, 0, .2, .2);
      gl.glTranslated (.5, -.2, 0); // Untranslate, otherwise translates chain
  
  
} // end method drawOne

   // GL_POINTS mode
   void drawTwo (GL2 gl) {
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
  
      double r1 = .5, r2 = .2, xOffset = .2, yOffset = -.2;
      double dx, dy;
      int steps = 50;
     
      gl.glPointSize (3f);  // measured in pixels?
      gl.glBegin (GL2.GL_POINTS);
      {
         for (double d = 0; d < 2 * Math.PI; d += Math.PI / steps) {
            dx = r1 * Math.sin (d); // draws ellipses,
            dy = r2 * Math.cos (d);
            gl.glColor4f  (1f, 0f, 0f, 0f);  // foreground color = red
            gl.glVertex2d (dx + xOffset, dy + yOffset);
            gl.glColor4f  (0f, 0f, 0f, 0f);  // foreground color = black
            gl.glVertex2d (dx - xOffset, dy + yOffset);
            gl.glColor4f  (1f, 1f, 0f, 0f);  // foreground color = yellow
            gl.glVertex2d (dx + xOffset, dy - yOffset);
            gl.glColor4f  (1f, 1f, 1f, 0f);  // foreground color = white
            gl.glVertex2d (dx - xOffset, dy - yOffset);
         } // end for every entry in circle
      } gl.glEnd (); // end points in GL2
  
  
} // end method drawTwo
  
   // rendering text: drawing a string
   void drawThree (GLAutoDrawable d) {
      TextRenderer renderer;
      GL2 gl = d.getGL().getGL2();
      int xp, yp;
  
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
     
   //       renderer = new TextRenderer(new java.awt.Font("SansSerif", java.awt.Font.BOLD, 20));
   //       renderer = new TextRenderer(new java.awt.Font("Luminari", java.awt.Font.BOLD, 36));
     
      xp = 10; yp = 20;
      renderer = new TextRenderer(new Font("Phosphate", Font.BOLD, 36));
      renderer.beginRendering(d.getWidth(), d.getHeight());
      {
         renderer.setColor(1.0f, 0.2f, 0.2f, 0.8f);
         renderer.draw("Pos: (" + xp + "," + yp + ")", xp, yp);
         xp += 10; yp += 30;
         renderer.draw("Pos: (" + xp + "," + yp + ")", xp, yp);
         xp = 50; yp += 30;
         renderer.draw("Pos: (" + xp + "," + yp + ")", xp, yp);
      } renderer.endRendering();
     
      xp = 30; yp = 150;
      renderer = new TextRenderer(new Font("Luminari", Font.BOLD, 36));
      renderer.beginRendering(d.getWidth(), d.getHeight());
      {
         renderer.setColor(1.0f, 0.2f, 0.2f, 0.8f);
         renderer.draw("Pos: (" + xp + "," + yp + ")", xp, yp);
         xp = 150; yp += 50;
         renderer.draw("Pos: (" + xp + "," + yp + ")", xp, yp);
      } renderer.endRendering();
  
     
      gl.glColor4f  (0f, 0f, 1f, 0f);  // foreground color = green
      GLUT glut = new GLUT ();
  
      gl.glRasterPos2d (0, 0); // Apparently 2i just fails
   //       gl.glRasterPos2i (10,10); // Apparently 2i just fails
      glut.glutBitmapString (GLUT.BITMAP_9_BY_15, "Center");
  
      gl.glRasterPos2d (-.9, .8);
      glut.glutBitmapString (GLUT.BITMAP_9_BY_15, "Pos: (-.2,.3)");
  
      gl.glRasterPos2d (.2, -.8);
      glut.glutBitmapString (GLUT.BITMAP_TIMES_ROMAN_24, "Pos: (.2,.5)");
  
      gl.glRasterPos2d (0, 0); // reset raster position, otherwise following stuff messed up     
  
  
} // end method drawThree
  
   // rendering text: drawing a string
   // draw a random noise bit map
   void drawFour (GLAutoDrawable d) {
      GL2 gl = d.getGL().getGL2();
      Random rn = new Random ();
  
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(javax.media.opengl.GL.GL_COLOR_BUFFER_BIT); // do this AFTER clear color
           
      gl.glColor4f  (1f, 1f, 1f, 0f);  // foreground color = white
  
      GLUT glut = new GLUT ();
      gl.glRasterPos2d (-.97, .8);
      glut.glutBitmapString (GLUT.BITMAP_9_BY_15, "DrawFour Center");
      gl.glRasterPos2d (-.97, .9);
      glut.glutBitmapString (GLUT.BITMAP_9_BY_15, "Random Noise Bit Map");
  
      // random noise bit map
      int rows = 64, cols = 128;
      byte [] bm = new byte [rows*cols];
      rn.nextBytes (bm); // new radom thing every time resize or display event called
  
      gl.glColor4f  (0f, 0f, 1f, 0f);  // foreground color = blue
      gl.glRasterPos2d (-.8, -.5);
      gl.glBitmap (cols, rows, 0f, 0f, 0f, 0f, bm, 0);
      gl.glRasterPos2d (0, 0); // reset raster position, otherwise following stuff messed up     
  
  
} // end method drawFour
  
   // drawing dodecahedrons
   void drawFive (GLAutoDrawable d) {
      GL2 gl = d.getGL().getGL2();
      int xr = 90, yr = 45, zr = 0;
  
      gl.glClearColor (bc[0], bc[1], bc[2], bc[3]); // background color
      gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT ); // do this AFTER clear color
     
      GLUT glut = new GLUT ();
  
      gl.glColor4f  (0f, 0f, 1f, 0f);  // foreground color = white
      gl.glMatrixMode(GL2.GL_PROJECTION);  //
      gl.glLoadIdentity();
      int dim = 16;
      gl.glOrtho(-dim,  dim, -dim,  dim, -dim,  dim);      // parameters are doubles
      gl.glMatrixMode(GL2.GL_MODELVIEW);
  
      xr = 0;
      double xa = -14, yas = 14, ya;
      for (int i = 0; i < 8; i++) {
         yr = 0; ya = yas;
         for (int j = 0; j < 8; j++) {
            gl.glLoadIdentity();             // Set up modelview transform.
            gl.glTranslated (xa, ya, 0);
            gl.glRotated(xr,1,0,0);
            gl.glRotated(yr,0,1,0);
            gl.glRotated(0,0,0,1);
            glut.glutSolidDodecahedron ();
            yr += 45;
            ya -= 4;
         } // end for y values
         xr += 45;
         xa += 4;
      } // end for x values
  
   } // end method drawFive
  

} // end class MyGLPanel



(end)