By: Nicholas Duchon
Date: Sep 20, 2016
Outline: |
My pages |
Other pages |
|
GLEW: |
|
Mac GLUT API's and deprecation: |
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 static final long serialVersionUID = 982374;
// garbage value
int count = 0; // button counter to test button
events
JButton jbA; // just for fun, and an
example
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
jbA.setText ("Count: " +
++count);
new Project1 ("JOGL Project 1");
System.out.println ("--- Done
---");
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
// background color constructor
GL2 gl = d.getGL().getGL2();
// drawOne
(gl);
drawTwo (gl);
// GL_POINTS mode
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?
{
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_TRIANGLES mode
// 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
{
// 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.glTranslated (-.5, .2, 0);
gl.glRectd (0, 0, .2, .2);
gl.glTranslated (.5, -.2, 0);
// 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();
// }
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);
// File: Project1.java
// Date: Aug 4, 2016; Jun 12, 2018
// 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
// Update Jun 12, 2018:
// created MyGLUT class to color the faces of the dodecahedron
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(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(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(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(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 dodecNDahedrons
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
MyGLUT glut = new MyGLUT ();
// gl.glColor4f (0f, 0f, 1f, 0f); // foreground color = white
// gl.glColor3d (1, 0, 0);
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.glutWireDodecahedron (gl);
glut.glutSolidDodecahedron (gl);
yr += 45;
ya -= 4;
} // end for y values
xr += 45;
xa += 4;
} // end for x values
} // end method drawFive
} // end class MyGLPanel
// See the following page for original source code for GLUT
// http://book2s.com/java/src/package/com/jogamp/opengl/util/gl2/glut.html
// See the following page for a list of the colors I used:
// https://sashat.me/2017/01/11/list-of-20-simple-distinct-colors/
// for some reason glColor3i does not seem to be working for me, so:
// /255. is a way to convert int's to double's and use glColor3d
class MyGLUT extends GLUT {
// having dodecND null is a way to make sure init only called once in display method
float[][] dodecND;
static float alpha = (float) Math.sqrt(2.0f / (3.0f + Math.sqrt(5.0)));
static float beta = 1.0f + (float) Math.sqrt(6.0 / (3.0 + Math.sqrt(5.0)) - 2.0
+ 2.0 * Math.sqrt(2.0 / (3.0 + Math.sqrt(5.0))));
public void glutWireDodecahedron(GL2 gl) {
dodecahedron(gl, GL.GL_LINE_LOOP);
} // end method glutWireDodecahedron
public void glutSolidDodecahedron(GL2 gl) {
dodecahedron(gl, GL.GL_TRIANGLE_FAN);
} // end method glutSolidDodecahedron
void initDodecahedron() {
dodecND = new float[20][3];
dodecND[0][0] = -alpha;
dodecND[0][1] = 0;
dodecND[0][2] = beta;
dodecND[1][0] = alpha;
dodecND[1][1] = 0;
dodecND[1][2] = beta;
dodecND[2][0] = -1;
dodecND[2][1] = -1;
dodecND[2][2] = -1;
dodecND[3][0] = -1;
dodecND[3][1] = -1;
dodecND[3][2] = 1;
dodecND[4][0] = -1;
dodecND[4][1] = 1;
dodecND[4][2] = -1;
dodecND[5][0] = -1;
dodecND[5][1] = 1;
dodecND[5][2] = 1;
dodecND[6][0] = 1;
dodecND[6][1] = -1;
dodecND[6][2] = -1;
dodecND[7][0] = 1;
dodecND[7][1] = -1;
dodecND[7][2] = 1;
dodecND[8][0] = 1;
dodecND[8][1] = 1;
dodecND[8][2] = -1;
dodecND[9][0] = 1;
dodecND[9][1] = 1;
dodecND[9][2] = 1;
dodecND[10][0] = beta;
dodecND[10][1] = alpha;
dodecND[10][2] = 0;
dodecND[11][0] = beta;
dodecND[11][1] = -alpha;
dodecND[11][2] = 0;
dodecND[12][0] = -beta;
dodecND[12][1] = alpha;
dodecND[12][2] = 0;
dodecND[13][0] = -beta;
dodecND[13][1] = -alpha;
dodecND[13][2] = 0;
dodecND[14][0] = -alpha;
dodecND[14][1] = 0;
dodecND[14][2] = -beta;
dodecND[15][0] = alpha;
dodecND[15][1] = 0;
dodecND[15][2] = -beta;
dodecND[16][0] = 0;
dodecND[16][1] = beta;
dodecND[16][2] = alpha;
dodecND[17][0] = 0;
dodecND[17][1] = beta;
dodecND[17][2] = -alpha;
dodecND[18][0] = 0;
dodecND[18][1] = -beta;
dodecND[18][2] = alpha;
dodecND[19][0] = 0;
dodecND[19][1] = -beta;
dodecND[19][2] = -alpha;
} // end method initDodecahedron
static void diff3(final float[] a, final float[] b,
final float[] c) {
c[0] = a[0] - b[0];
c[1] = a[1] - b[1];
c[2] = a[2] - b[2];
} // end method diff3
static void crossprod(final float[] v1, final float[] v2,
final float[] prod) {
final float[] p = new float[3]; /* in case prod == v1 or v2 */
p[0] = v1[1] * v2[2] - v2[1] * v1[2];
p[1] = v1[2] * v2[0] - v2[2] * v1[0];
p[2] = v1[0] * v2[1] - v2[0] * v1[1];
prod[0] = p[0];
prod[1] = p[1];
prod[2] = p[2];
} // end method crossprod
static void normalize(final float[] v) {
float d;
d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if (d == 0.0) {
v[0] = d = 1.0f;
}
d = 1 / d;
v[0] *= d;
v[1] *= d;
v[2] *= d;
} // end method normalize
void pentagon(final GL2 gl, final int a, final int b,
final int c, final int d, final int e, final int shadeType) {
final float[] n0 = new float[3];
final float[] d1 = new float[3];
final float[] d2 = new float[3];
diff3(dodecND[a], dodecND[b], d1);
diff3(dodecND[b], dodecND[c], d2);
crossprod(d1, d2, n0);
normalize(n0);
gl.glBegin(shadeType);
gl.glNormal3fv(n0, 0);
gl.glVertex3fv(dodecND[a], 0);
gl.glVertex3fv(dodecND[b], 0);
gl.glVertex3fv(dodecND[c], 0);
gl.glVertex3fv(dodecND[d], 0);
gl.glVertex3fv(dodecND[e], 0);
gl.glEnd();
} // end method pentagon
void dodecahedron(final GL2 gl, final int type) {
if (dodecND == null) {
initDodecahedron();
}
gl.glColor3d (230/255., 25/255., 75/255.);
pentagon(gl, 0, 1, 9, 16, 5, type);
gl.glColor3d (60/255., 180/255., 75/255.);
pentagon(gl, 1, 0, 3, 18, 7, type);
gl.glColor3d (255/255., 225/255., 25/255.);
pentagon(gl, 1, 7, 11, 10, 9, type);
gl.glColor3d (0/255., 130/255., 200/255.);
pentagon(gl, 11, 7, 18, 19, 6, type);
gl.glColor3d (245/255., 130/255., 48/255.);
pentagon(gl, 8, 17, 16, 9, 10, type);
gl.glColor3d (145/255., 30/255., 180/255.) ;
pentagon(gl, 2, 14, 15, 6, 19, type);
gl.glColor3d (70/255., 240/255., 240/255.);
pentagon(gl, 2, 13, 12, 4, 14, type);
gl.glColor3d (240/255., 50/255., 230/255.) ;
pentagon(gl, 2, 19, 18, 3, 13, type);
gl.glColor3d (210/255., 245/255., 60/255.) ;
pentagon(gl, 3, 0, 5, 12, 13, type);
gl.glColor3d (250/255., 190/255., 190/255.) ;
pentagon(gl, 6, 15, 8, 10, 11, type);
gl.glColor3d (0/255., 128/255., 128/255.) ;
pentagon(gl, 4, 17, 8, 15, 14, type);
gl.glColor3d (230/255., 190/255., 255/255.) ;
pentagon(gl, 4, 12, 5, 16, 17, type);
} // end method dodecahedron
} // end class MyGLUT