diff options
author | Kenneth Russel <[email protected]> | 2005-08-06 19:59:40 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2005-08-06 19:59:40 +0000 |
commit | 8ad7326f25441a437e4ab826596a20ffc0bddd5d (patch) | |
tree | 16ce0dc75d3f05acb3b5847b1b830799630e5be4 | |
parent | e99aeb5f40422070161865bb1d37b9158e3de63f (diff) |
Refactored nearly all demos as GLEventListeners and imported most into
JRefract framework. Deleted duplicate Gears code in fullscreen demos.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/branches/JSR-231@107 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
-rwxr-xr-x | src/demos/fullscreen/GearsFullscreen.java | 305 | ||||
-rwxr-xr-x | src/demos/fullscreen/GearsFullscreen2.java | 306 | ||||
-rwxr-xr-x | src/demos/fullscreen/JGearsFullscreen.java | 321 | ||||
-rwxr-xr-x | src/demos/hdr/HDR.java | 609 | ||||
-rw-r--r-- | src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java | 474 | ||||
-rw-r--r-- | src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java | 1896 | ||||
-rwxr-xr-x | src/demos/jrefract/JRefract.java | 145 | ||||
-rwxr-xr-x | src/demos/util/DemoListener.java | 8 | ||||
-rw-r--r-- | src/demos/vertexArrayRange/VertexArrayRange.java | 800 | ||||
-rw-r--r-- | src/demos/vertexBufferObject/VertexBufferObject.java | 830 | ||||
-rw-r--r-- | src/demos/vertexProgRefract/VertexProgRefract.java | 3 | ||||
-rw-r--r-- | src/demos/vertexProgWarp/VertexProgWarp.java | 935 | ||||
-rw-r--r-- | src/gleem/ExaminerViewer.java | 2 |
13 files changed, 2950 insertions, 3684 deletions
diff --git a/src/demos/fullscreen/GearsFullscreen.java b/src/demos/fullscreen/GearsFullscreen.java index f33221a..54d7aa1 100755 --- a/src/demos/fullscreen/GearsFullscreen.java +++ b/src/demos/fullscreen/GearsFullscreen.java @@ -4,6 +4,7 @@ import java.awt.*; import java.awt.event.*; import net.java.games.jogl.*; +import demos.gears.Gears; import demos.util.*; /** @@ -52,7 +53,7 @@ public class GearsFullscreen { } GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - canvas.addGLEventListener(new GearRenderer()); + canvas.addGLEventListener(new Gears()); frame.add(canvas); frame.setSize(initWidth, initHeight); animator = new Animator(canvas); @@ -91,308 +92,6 @@ public class GearsFullscreen { animator.start(); } - class GearRenderer implements GLEventListener, MouseListener, MouseMotionListener { - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private int gear1, gear2, gear3; - private float angle = 0.0f; - - private int prevMouseX, prevMouseY; - private boolean mouseRButtonDown = false; - - public void init(GLAutoDrawable drawable) { - // Use debug pipeline - // drawable.setGL(new DebugGL(drawable.getGL())); - - GL gl = drawable.getGL(); - - // FIXME: workaround for Windows full-screen bug when - // sun.java2d.noddraw=true and similar bug on Mac OS X - if (fullScreen) { - final GLDrawable tmpDrawable = drawable; - EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setBounds(0, 0, initWidth, initHeight); - tmpDrawable.setSize(initWidth, initHeight); - frame.toFront(); - } - }); - } - - System.err.println("INIT GL IS: " + gl.getClass().getName()); - - gl.setSwapInterval(1); - - float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; - float red[] = { 0.8f, 0.1f, 0.0f, 1.0f }; - float green[] = { 0.0f, 0.8f, 0.2f, 1.0f }; - float blue[] = { 0.2f, 0.2f, 1.0f, 1.0f }; - - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0); - gl.glEnable(GL.GL_CULL_FACE); - gl.glEnable(GL.GL_LIGHTING); - gl.glEnable(GL.GL_LIGHT0); - gl.glEnable(GL.GL_DEPTH_TEST); - - /* make the gears */ - gear1 = gl.glGenLists(1); - gl.glNewList(gear1, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0); - gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f); - gl.glEndList(); - - gear2 = gl.glGenLists(1); - gl.glNewList(gear2, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, green, 0); - gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f); - gl.glEndList(); - - gear3 = gl.glGenLists(1); - gl.glNewList(gear3, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0); - gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f); - gl.glEndList(); - - gl.glEnable(GL.GL_NORMALIZE); - - drawable.addMouseListener(this); - drawable.addMouseMotionListener(this); - - drawable.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - dispatchKey(e.getKeyCode()); - } - }); - } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - GL gl = drawable.getGL(); - - float h = (float)height / (float)width; - - gl.glMatrixMode(GL.GL_PROJECTION); - - System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - System.err.println(); - System.err.println("glLoadTransposeMatrixfARB() supported: " + - gl.isFunctionAvailable("glLoadTransposeMatrixfARB")); - if (!gl.isFunctionAvailable("glLoadTransposeMatrixfARB")) { - // --- not using extensions - gl.glLoadIdentity(); - } else { - // --- using extensions - final float[] identityTranspose = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - gl.glLoadTransposeMatrixfARB(identityTranspose, 0); - } - gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); - gl.glTranslatef(0.0f, 0.0f, -40.0f); - } - - public void display(GLAutoDrawable drawable) { - angle += 2.0f; - - GL gl = drawable.getGL(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - gl.glPushMatrix(); - gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); - gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); - gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - - gl.glPushMatrix(); - gl.glTranslatef(-3.0f, -2.0f, 0.0f); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear1); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(3.1f, -2.0f, 0.0f); - gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear2); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(-3.1f, 4.2f, 0.0f); - gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear3); - gl.glPopMatrix(); - - gl.glPopMatrix(); - } - - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - - private void gear(GL gl, - float inner_radius, - float outer_radius, - float width, - int teeth, - float tooth_depth) - { - int i; - float r0, r1, r2; - float angle, da; - float u, v, len; - - r0 = inner_radius; - r1 = outer_radius - tooth_depth / 2.0f; - r2 = outer_radius + tooth_depth / 2.0f; - - da = 2.0f * (float) Math.PI / teeth / 4.0f; - - gl.glShadeModel(GL.GL_FLAT); - - gl.glNormal3f(0.0f, 0.0f, 1.0f); - - /* draw front face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - if(i < teeth) - { - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - } - gl.glEnd(); - - /* draw front sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2.0f * da), r2 * (float)Math.sin(angle + 2.0f * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - gl.glEnd(); - - /* draw back face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw back sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw outward faces of teeth */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - u = r2 * (float)Math.cos(angle + da) - r1 * (float)Math.cos(angle); - v = r2 * (float)Math.sin(angle + da) - r1 * (float)Math.sin(angle); - len = (float)Math.sqrt(u * u + v * v); - u /= len; - v /= len; - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - u = r1 * (float)Math.cos(angle + 3 * da) - r2 * (float)Math.cos(angle + 2 * da); - v = r1 * (float)Math.sin(angle + 3 * da) - r2 * (float)Math.sin(angle + 2 * da); - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - } - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f); - gl.glEnd(); - - gl.glShadeModel(GL.GL_SMOOTH); - - /* draw inside radius cylinder */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glNormal3f(-(float)Math.cos(angle), -(float)Math.sin(angle), 0.0f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - } - gl.glEnd(); - } - - // Methods required for the implementation of MouseListener - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) {} - - public void mousePressed(MouseEvent e) { - prevMouseX = e.getX(); - prevMouseY = e.getY(); - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = true; - } - } - - public void mouseReleased(MouseEvent e) { - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = false; - } - } - - public void mouseClicked(MouseEvent e) {} - - // Methods required for the implementation of MouseMotionListener - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - Dimension size = e.getComponent().getSize(); - - float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)size.width); - float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)size.height); - - prevMouseX = x; - prevMouseY = y; - - view_rotx += thetaX; - view_roty += thetaY; - } - - public void mouseMoved(MouseEvent e) {} - - public void dispatchKey(int keyCode) { - switch (keyCode) { - case KeyEvent.VK_Q: - case KeyEvent.VK_ESCAPE: - runExit(); - } - } - } - public void runExit() { // Run this on another thread than the AWT event queue to // make sure the call to Animator.stop() completes before diff --git a/src/demos/fullscreen/GearsFullscreen2.java b/src/demos/fullscreen/GearsFullscreen2.java index 0afad8c..401ee62 100755 --- a/src/demos/fullscreen/GearsFullscreen2.java +++ b/src/demos/fullscreen/GearsFullscreen2.java @@ -5,6 +5,7 @@ import java.awt.event.*; import javax.swing.*; import net.java.games.jogl.*; +import demos.gears.Gears; import demos.util.*; /** @@ -53,7 +54,7 @@ public class GearsFullscreen2 { } GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - canvas.addGLEventListener(new GearRenderer()); + canvas.addGLEventListener(new Gears()); frame.getContentPane().setLayout(new BorderLayout()); ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); @@ -112,309 +113,6 @@ public class GearsFullscreen2 { animator.start(); } - class GearRenderer implements GLEventListener, MouseListener, MouseMotionListener { - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private int gear1, gear2, gear3; - private float angle = 0.0f; - - private int prevMouseX, prevMouseY; - private boolean mouseRButtonDown = false; - - public void init(GLAutoDrawable drawable) { - // Use debug pipeline - // drawable.setGL(new DebugGL(drawable.getGL())); - - GL gl = drawable.getGL(); - - // FIXME: workaround for Windows full-screen bug when - // sun.java2d.noddraw=true and similar bug on Mac OS X - if (fullScreen) { - final GLDrawable tmpDrawable = drawable; - EventQueue.invokeLater(new Runnable() { - public void run() { - frame.setVisible(false); - frame.setBounds(0, 0, initWidth, initHeight); - frame.setVisible(true); - frame.toFront(); - } - }); - } - - System.err.println("INIT GL IS: " + gl.getClass().getName()); - - gl.setSwapInterval(1); - - float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; - float red[] = { 0.8f, 0.1f, 0.0f, 1.0f }; - float green[] = { 0.0f, 0.8f, 0.2f, 1.0f }; - float blue[] = { 0.2f, 0.2f, 1.0f, 1.0f }; - - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0); - gl.glEnable(GL.GL_CULL_FACE); - gl.glEnable(GL.GL_LIGHTING); - gl.glEnable(GL.GL_LIGHT0); - gl.glEnable(GL.GL_DEPTH_TEST); - - /* make the gears */ - gear1 = gl.glGenLists(1); - gl.glNewList(gear1, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0); - gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f); - gl.glEndList(); - - gear2 = gl.glGenLists(1); - gl.glNewList(gear2, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, green, 0); - gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f); - gl.glEndList(); - - gear3 = gl.glGenLists(1); - gl.glNewList(gear3, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0); - gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f); - gl.glEndList(); - - gl.glEnable(GL.GL_NORMALIZE); - - drawable.addMouseListener(this); - drawable.addMouseMotionListener(this); - - drawable.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - dispatchKey(e.getKeyCode()); - } - }); - } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - GL gl = drawable.getGL(); - - float h = (float)height / (float)width; - - gl.glMatrixMode(GL.GL_PROJECTION); - - System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - System.err.println(); - System.err.println("glLoadTransposeMatrixfARB() supported: " + - gl.isFunctionAvailable("glLoadTransposeMatrixfARB")); - if (!gl.isFunctionAvailable("glLoadTransposeMatrixfARB")) { - // --- not using extensions - gl.glLoadIdentity(); - } else { - // --- using extensions - final float[] identityTranspose = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - gl.glLoadTransposeMatrixfARB(identityTranspose, 0); - } - gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); - gl.glTranslatef(0.0f, 0.0f, -40.0f); - } - - public void display(GLAutoDrawable drawable) { - angle += 2.0f; - - GL gl = drawable.getGL(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - gl.glPushMatrix(); - gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); - gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); - gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - - gl.glPushMatrix(); - gl.glTranslatef(-3.0f, -2.0f, 0.0f); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear1); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(3.1f, -2.0f, 0.0f); - gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear2); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(-3.1f, 4.2f, 0.0f); - gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear3); - gl.glPopMatrix(); - - gl.glPopMatrix(); - } - - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - - private void gear(GL gl, - float inner_radius, - float outer_radius, - float width, - int teeth, - float tooth_depth) - { - int i; - float r0, r1, r2; - float angle, da; - float u, v, len; - - r0 = inner_radius; - r1 = outer_radius - tooth_depth / 2.0f; - r2 = outer_radius + tooth_depth / 2.0f; - - da = 2.0f * (float) Math.PI / teeth / 4.0f; - - gl.glShadeModel(GL.GL_FLAT); - - gl.glNormal3f(0.0f, 0.0f, 1.0f); - - /* draw front face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - if(i < teeth) - { - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - } - gl.glEnd(); - - /* draw front sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2.0f * da), r2 * (float)Math.sin(angle + 2.0f * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - gl.glEnd(); - - /* draw back face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw back sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw outward faces of teeth */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - u = r2 * (float)Math.cos(angle + da) - r1 * (float)Math.cos(angle); - v = r2 * (float)Math.sin(angle + da) - r1 * (float)Math.sin(angle); - len = (float)Math.sqrt(u * u + v * v); - u /= len; - v /= len; - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - u = r1 * (float)Math.cos(angle + 3 * da) - r2 * (float)Math.cos(angle + 2 * da); - v = r1 * (float)Math.sin(angle + 3 * da) - r2 * (float)Math.sin(angle + 2 * da); - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - } - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f); - gl.glEnd(); - - gl.glShadeModel(GL.GL_SMOOTH); - - /* draw inside radius cylinder */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glNormal3f(-(float)Math.cos(angle), -(float)Math.sin(angle), 0.0f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - } - gl.glEnd(); - } - - // Methods required for the implementation of MouseListener - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) {} - - public void mousePressed(MouseEvent e) { - prevMouseX = e.getX(); - prevMouseY = e.getY(); - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = true; - } - } - - public void mouseReleased(MouseEvent e) { - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = false; - } - } - - public void mouseClicked(MouseEvent e) {} - - // Methods required for the implementation of MouseMotionListener - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - Dimension size = e.getComponent().getSize(); - - float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)size.width); - float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)size.height); - - prevMouseX = x; - prevMouseY = y; - - view_rotx += thetaX; - view_roty += thetaY; - } - - public void mouseMoved(MouseEvent e) {} - - public void dispatchKey(int keyCode) { - switch (keyCode) { - case KeyEvent.VK_Q: - case KeyEvent.VK_ESCAPE: - runExit(); - } - } - } - public void runExit() { // Run this on another thread than the AWT event queue to // make sure the call to Animator.stop() completes before diff --git a/src/demos/fullscreen/JGearsFullscreen.java b/src/demos/fullscreen/JGearsFullscreen.java index 62b10fe..ce232ad 100755 --- a/src/demos/fullscreen/JGearsFullscreen.java +++ b/src/demos/fullscreen/JGearsFullscreen.java @@ -5,6 +5,7 @@ import java.awt.event.*; import javax.swing.*; import net.java.games.jogl.*; +import demos.gears.Gears; import demos.util.*; /** @@ -52,7 +53,7 @@ public class JGearsFullscreen { frame.setUndecorated(true); } GLJPanel drawable = GLDrawableFactory.getFactory().createGLJPanel(new GLCapabilities()); - drawable.addGLEventListener(new GearRenderer()); + drawable.addGLEventListener(new Gears()); frame.getContentPane().setLayout(new BorderLayout()); @@ -110,324 +111,6 @@ public class JGearsFullscreen { animator.start(); } - class GearRenderer implements GLEventListener, MouseListener, MouseMotionListener { - private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; - private int gear1, gear2, gear3; - private float angle = 0.0f; - - private int prevMouseX, prevMouseY; - private boolean mouseRButtonDown = false; - - public void init(GLAutoDrawable drawable) { - // Use debug pipeline - // drawable.setGL(new DebugGL(drawable.getGL())); - - GL gl = drawable.getGL(); - - // FIXME: workaround for Windows full-screen bug when - // sun.java2d.noddraw=true and similar bug on Mac OS X - if (fullScreen) { - final GLDrawable tmpDrawable = drawable; - Runnable r = new Runnable() { - public void run() { - frame.setVisible(false); - frame.setBounds(0, 0, initWidth, initHeight); - frame.setVisible(true); - frame.toFront(); - frame.requestFocus(); - } - }; - // FIXME: this is a total hack to work around behavior seen on JDK 1.5 - // Should find a better way / place to do this (to ensure the - // fixup runnable is only invoked once things have settled - // down) - EventQueue.invokeLater(r); - EventQueue.invokeLater(r); - } - - System.err.println("INIT GL IS: " + gl.getClass().getName()); - - gl.setSwapInterval(1); - - float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; - float red[] = { 0.8f, 0.1f, 0.0f, 1.0f }; - float green[] = { 0.0f, 0.8f, 0.2f, 1.0f }; - float blue[] = { 0.2f, 0.2f, 1.0f, 1.0f }; - - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos, 0); - gl.glEnable(GL.GL_CULL_FACE); - gl.glEnable(GL.GL_LIGHTING); - gl.glEnable(GL.GL_LIGHT0); - gl.glEnable(GL.GL_DEPTH_TEST); - - /* make the gears */ - gear1 = gl.glGenLists(1); - gl.glNewList(gear1, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, red, 0); - gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f); - gl.glEndList(); - - gear2 = gl.glGenLists(1); - gl.glNewList(gear2, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, green, 0); - gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f); - gl.glEndList(); - - gear3 = gl.glGenLists(1); - gl.glNewList(gear3, GL.GL_COMPILE); - gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, blue, 0); - gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f); - gl.glEndList(); - - gl.glEnable(GL.GL_NORMALIZE); - - drawable.addMouseListener(this); - drawable.addMouseMotionListener(this); - - // FIXME: for some reason, adding a key listener to the GLJPanel - // isn't working in this configuration - InputMap map = ((GLJPanel) drawable).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - ActionMap actMap = ((GLJPanel) drawable).getActionMap(); - Action act = new AbstractAction() { - public void actionPerformed(ActionEvent e) { - runExit(); - } - }; - - map.put(KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), act); - map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), act); - actMap.put(act, act); - } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - GL gl = drawable.getGL(); - - float h = (float)height / (float)width; - - gl.glMatrixMode(GL.GL_PROJECTION); - - System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR)); - System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER)); - System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION)); - System.err.println(); - System.err.println("glLoadTransposeMatrixfARB() supported: " + - gl.isFunctionAvailable("glLoadTransposeMatrixfARB")); - if (!gl.isFunctionAvailable("glLoadTransposeMatrixfARB")) { - // --- not using extensions - gl.glLoadIdentity(); - } else { - // --- using extensions - final float[] identityTranspose = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - }; - gl.glLoadTransposeMatrixfARB(identityTranspose, 0); - } - gl.glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); - gl.glTranslatef(0.0f, 0.0f, -40.0f); - } - - public void display(GLAutoDrawable drawable) { - angle += 2.0f; - - GL gl = drawable.getGL(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - gl.glPushMatrix(); - gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); - gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); - gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); - - gl.glPushMatrix(); - gl.glTranslatef(-3.0f, -2.0f, 0.0f); - gl.glRotatef(angle, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear1); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(3.1f, -2.0f, 0.0f); - gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear2); - gl.glPopMatrix(); - - gl.glPushMatrix(); - gl.glTranslatef(-3.1f, 4.2f, 0.0f); - gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f); - gl.glCallList(gear3); - gl.glPopMatrix(); - - gl.glPopMatrix(); - } - - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - - private void gear(GL gl, - float inner_radius, - float outer_radius, - float width, - int teeth, - float tooth_depth) - { - int i; - float r0, r1, r2; - float angle, da; - float u, v, len; - - r0 = inner_radius; - r1 = outer_radius - tooth_depth / 2.0f; - r2 = outer_radius + tooth_depth / 2.0f; - - da = 2.0f * (float) Math.PI / teeth / 4.0f; - - gl.glShadeModel(GL.GL_FLAT); - - gl.glNormal3f(0.0f, 0.0f, 1.0f); - - /* draw front face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - if(i < teeth) - { - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - } - gl.glEnd(); - - /* draw front sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2.0f * da), r2 * (float)Math.sin(angle + 2.0f * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f); - } - gl.glEnd(); - - /* draw back face */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw back sides of teeth */ - gl.glBegin(GL.GL_QUADS); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - } - gl.glEnd(); - - /* draw outward faces of teeth */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i < teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f); - u = r2 * (float)Math.cos(angle + da) - r1 * (float)Math.cos(angle); - v = r2 * (float)Math.sin(angle + da) - r1 * (float)Math.sin(angle); - len = (float)Math.sqrt(u * u + v * v); - u /= len; - v /= len; - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), width * 0.5f); - gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f); - u = r1 * (float)Math.cos(angle + 3 * da) - r2 * (float)Math.cos(angle + 2 * da); - v = r1 * (float)Math.sin(angle + 3 * da) - r2 * (float)Math.sin(angle + 2 * da); - gl.glNormal3f(v, -u, 0.0f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f); - gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f); - } - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f); - gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f); - gl.glEnd(); - - gl.glShadeModel(GL.GL_SMOOTH); - - /* draw inside radius cylinder */ - gl.glBegin(GL.GL_QUAD_STRIP); - for (i = 0; i <= teeth; i++) - { - angle = i * 2.0f * (float) Math.PI / teeth; - gl.glNormal3f(-(float)Math.cos(angle), -(float)Math.sin(angle), 0.0f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f); - gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f); - } - gl.glEnd(); - } - - // Methods required for the implementation of MouseListener - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) {} - - public void mousePressed(MouseEvent e) { - prevMouseX = e.getX(); - prevMouseY = e.getY(); - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = true; - } - } - - public void mouseReleased(MouseEvent e) { - if ((e.getModifiers() & e.BUTTON3_MASK) != 0) { - mouseRButtonDown = false; - } - } - - public void mouseClicked(MouseEvent e) {} - - // Methods required for the implementation of MouseMotionListener - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - Dimension size = e.getComponent().getSize(); - - float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)size.width); - float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)size.height); - - prevMouseX = x; - prevMouseY = y; - - view_rotx += thetaX; - view_roty += thetaY; - } - - public void mouseMoved(MouseEvent e) {} - - public void dispatchKey(int keyCode) { - switch (keyCode) { - case KeyEvent.VK_Q: - case KeyEvent.VK_ESCAPE: - runExit(); - } - } - } - public void runExit() { // Run this on another thread than the AWT event queue to // make sure the call to Animator.stop() completes before diff --git a/src/demos/hdr/HDR.java b/src/demos/hdr/HDR.java index b499515..a5e085c 100755 --- a/src/demos/hdr/HDR.java +++ b/src/demos/hdr/HDR.java @@ -19,12 +19,18 @@ import gleem.linalg.*; Ported to Java by Kenneth Russell */ -public class HDR { +public class HDR implements GLEventListener { + private static String[] defaultArgs = { + "demos/data/images/stpeters_cross.hdr", + "512", + "384", + "2", + "7", + "3", + "demos/data/models/teapot.obj" + }; private boolean useCg; - private GLCanvas canvas; - private Frame frame; - private Animator animator; - private boolean initFailed; + private boolean initComplete; private HDRTexture hdr; private String modelFilename; private ObjReader model; @@ -97,10 +103,42 @@ public class HDR { 0.0f, 0.0f, 0.0f, 1.0f }; public static void main(String[] args) { - new HDR().run(args); + GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + HDR demo = new HDR(); + canvas.addGLEventListener(demo); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + public void repaint() {} + }); + demo.setup(args); + + Frame frame = new Frame("HDR test"); + frame.setLayout(new BorderLayout()); + canvas.setSize(demo.getPreferredWidth(), demo.getPreferredHeight()); + + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); + frame.show(); + canvas.requestFocus(); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + runExit(animator); + } + }); + + animator.start(); } - public void run(String[] args) { + public void setup(String[] args) { + if ((args == null) || (args.length == 0)) { + args = defaultArgs; + } + if (args.length < 6 || args.length > 8) { usage(); } @@ -168,343 +206,354 @@ public class HDR { System.exit(0); } - canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - canvas.addGLEventListener(new Listener()); - - animator = new Animator(canvas); + } - frame = new Frame("HDR test"); - frame.setLayout(new BorderLayout()); - canvas.setSize(win_w, win_h); - - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); - frame.setResizable(false); - frame.show(); - canvas.requestFocus(); + public int getPreferredWidth() { + return win_w; + } - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - runExit(); - } - }); + public int getPreferredHeight() { + return win_h; + } - animator.start(); + public void setDemoListener(DemoListener listener) { + demoListener = listener; } //---------------------------------------------------------------------- // Internals only below this point // + private DemoListener demoListener; + //---------------------------------------------------------------------- - // Listeners for main window and pbuffers + // Listener for main window // - class Listener implements GLEventListener { - private float zNear = 0.1f; - private float zFar = 10.0f; - private boolean wire = false; - private boolean toggleWire = false; - - public void init(GLAutoDrawable drawable) { - // printThreadName("init for Listener"); - - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + private float zNear = 0.1f; + private float zFar = 10.0f; + private boolean wire = false; + private boolean toggleWire = false; + + public void init(GLAutoDrawable drawable) { + initComplete = false; + // printThreadName("init for Listener"); + + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); + + checkExtension(gl, "GL_ARB_multitexture"); + checkExtension(gl, "GL_ARB_pbuffer"); + checkExtension(gl, "GL_ARB_vertex_program"); + checkExtension(gl, "GL_ARB_fragment_program"); + if (!gl.isExtensionAvailable("GL_NV_texture_rectangle") && + !gl.isExtensionAvailable("GL_EXT_texture_rectangle") && + !gl.isExtensionAvailable("GL_ARB_texture_rectangle")) { + // NOTE: it turns out the constants associated with these extensions are all identical + unavailableExtension("Texture rectangle extension not available (need one of GL_NV_texture_rectangle, GL_EXT_texture_rectangle or GL_ARB_texture_rectangle"); + } - checkExtension(gl, "GL_ARB_multitexture"); - checkExtension(gl, "GL_ARB_pbuffer"); - checkExtension(gl, "GL_ARB_vertex_program"); - checkExtension(gl, "GL_ARB_fragment_program"); - if (!gl.isExtensionAvailable("GL_NV_texture_rectangle") && - !gl.isExtensionAvailable("GL_EXT_texture_rectangle") && - !gl.isExtensionAvailable("GL_ARB_texture_rectangle")) { - // NOTE: it turns out the constants associated with these extensions are all identical - unavailableExtension("Texture rectangle extension not available (need one of GL_NV_texture_rectangle, GL_EXT_texture_rectangle or GL_ARB_texture_rectangle"); - } + if (!gl.isExtensionAvailable("GL_NV_float_buffer") && + !gl.isExtensionAvailable("GL_ATI_texture_float") && + !gl.isExtensionAvailable("GL_APPLE_float_pixels")) { + unavailableExtension("Floating-point textures not available (need one of GL_NV_float_buffer, GL_ATI_texture_float, or GL_APPLE_float_pixels"); + } - if (!gl.isExtensionAvailable("GL_NV_float_buffer") && - !gl.isExtensionAvailable("GL_ATI_texture_float") && - !gl.isExtensionAvailable("GL_APPLE_float_pixels")) { - unavailableExtension("Floating-point textures not available (need one of GL_NV_float_buffer, GL_ATI_texture_float, or GL_APPLE_float_pixels"); - } + setOrthoProjection(gl, win_w, win_h); + + gamma_tex = createGammaTexture(gl, 1024, 1.0f / 2.2f); + vignette_tex = createVignetteTexture(gl, pbuffer_w, pbuffer_h, 0.25f*pbuffer_w, 0.7f*pbuffer_w); + + int floatBits = 16; + int floatAlphaBits = 0; + // int floatDepthBits = 16; + // Workaround for apparent bug when not using render-to-texture-rectangle + int floatDepthBits = 1; + + GLCapabilities caps = new GLCapabilities(); + caps.setDoubleBuffered(false); + caps.setOffscreenFloatingPointBuffers(true); + caps.setRedBits(floatBits); + caps.setGreenBits(floatBits); + caps.setBlueBits(floatBits); + caps.setAlphaBits(floatAlphaBits); + caps.setDepthBits(floatDepthBits); + int[] tmp = new int[1]; + if (!GLDrawableFactory.getFactory().canCreateGLPbuffer(caps, pbuffer_w, pbuffer_h)) { + unavailableExtension("Can not create pbuffer of size (" + pbuffer_w + ", " + pbuffer_h + ")"); + } + if (pbuffer != null) { + pbuffer.destroy(); + pbuffer = null; + } + if (blur_pbuffer != null) { + blur_pbuffer.destroy(); + blur_pbuffer = null; + } + if (blur2_pbuffer != null) { + blur2_pbuffer.destroy(); + blur2_pbuffer = null; + } + if (tonemap_pbuffer != null) { + tonemap_pbuffer.destroy(); + tonemap_pbuffer = null; + } - setOrthoProjection(gl, win_w, win_h); - - gamma_tex = createGammaTexture(gl, 1024, 1.0f / 2.2f); - vignette_tex = createVignetteTexture(gl, pbuffer_w, pbuffer_h, 0.25f*pbuffer_w, 0.7f*pbuffer_w); - - int floatBits = 16; - int floatAlphaBits = 0; - // int floatDepthBits = 16; - // Workaround for apparent bug when not using render-to-texture-rectangle - int floatDepthBits = 1; - - GLCapabilities caps = new GLCapabilities(); - caps.setDoubleBuffered(false); - caps.setOffscreenFloatingPointBuffers(true); - caps.setRedBits(floatBits); - caps.setGreenBits(floatBits); - caps.setBlueBits(floatBits); - caps.setAlphaBits(floatAlphaBits); - caps.setDepthBits(floatDepthBits); - int[] tmp = new int[1]; - if (!GLDrawableFactory.getFactory().canCreateGLPbuffer(caps, pbuffer_w, pbuffer_h)) { - unavailableExtension("Can not create pbuffer of size (" + pbuffer_w + ", " + pbuffer_h + ")"); - } - GLContext parentContext = drawable.getContext(); - pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, pbuffer_w, pbuffer_h, parentContext); - pbuffer.addGLEventListener(new PbufferListener()); - gl.glGenTextures(1, tmp, 0); - pbuffer_tex = tmp[0]; - blur_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, blur_w, blur_h, parentContext); - blur_pbuffer.addGLEventListener(new BlurPbufferListener()); - gl.glGenTextures(1, tmp, 0); - blur_pbuffer_tex = tmp[0]; - blur2_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, blur_w, blur_h, parentContext); - blur2_pbuffer.addGLEventListener(new Blur2PbufferListener()); - gl.glGenTextures(1, tmp, 0); - blur2_pbuffer_tex = tmp[0]; - caps.setOffscreenFloatingPointBuffers(false); - caps.setRedBits(8); - caps.setGreenBits(8); - caps.setBlueBits(8); - caps.setDepthBits(24); - tonemap_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, pbuffer_w, pbuffer_h, parentContext); - tonemap_pbuffer.addGLEventListener(new TonemapPbufferListener()); - gl.glGenTextures(1, tmp, 0); - tonemap_pbuffer_tex = tmp[0]; + GLContext parentContext = drawable.getContext(); + pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, pbuffer_w, pbuffer_h, parentContext); + pbuffer.addGLEventListener(new PbufferListener()); + gl.glGenTextures(1, tmp, 0); + pbuffer_tex = tmp[0]; + blur_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, blur_w, blur_h, parentContext); + blur_pbuffer.addGLEventListener(new BlurPbufferListener()); + gl.glGenTextures(1, tmp, 0); + blur_pbuffer_tex = tmp[0]; + blur2_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, blur_w, blur_h, parentContext); + blur2_pbuffer.addGLEventListener(new Blur2PbufferListener()); + gl.glGenTextures(1, tmp, 0); + blur2_pbuffer_tex = tmp[0]; + caps.setOffscreenFloatingPointBuffers(false); + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setDepthBits(24); + tonemap_pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, pbuffer_w, pbuffer_h, parentContext); + tonemap_pbuffer.addGLEventListener(new TonemapPbufferListener()); + gl.glGenTextures(1, tmp, 0); + tonemap_pbuffer_tex = tmp[0]; - drawable.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - dispatchKey(e.getKeyCode(), e.getKeyChar()); - } - }); - - // Register the window with the ManipManager - ManipManager manager = ManipManager.getManipManager(); - manager.registerWindow(drawable); - - viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); - viewer.setAutoRedrawMode(false); - viewer.setNoAltKeyMode(true); - viewer.attach(drawable, new BSphereProvider() { - public BSphere getBoundingSphere() { - return new BSphere(new Vec3f(0, 0, 0), 1.0f); - } - }); - viewer.setZNear(zNear); - viewer.setZFar(zFar); - } + drawable.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + dispatchKey(e.getKeyCode(), e.getKeyChar()); + } + }); - public void display(GLAutoDrawable drawable) { - // printThreadName("display for Listener"); + doViewAll = true; - if (initFailed) { - return; - } + // Register the window with the ManipManager + ManipManager manager = ManipManager.getManipManager(); + manager.registerWindow(drawable); - if (!firstRender) { - if (++frameCount == 30) { - timer.stop(); - System.err.println("Frames per second: " + (30.0f / timer.getDurationAsSeconds())); - timer.reset(); - timer.start(); - frameCount = 0; + viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); + viewer.setAutoRedrawMode(false); + viewer.setNoAltKeyMode(true); + viewer.attach(drawable, new BSphereProvider() { + public BSphere getBoundingSphere() { + return new BSphere(new Vec3f(0, 0, 0), 1.0f); } - } else { - firstRender = false; - timer.start(); - } + }); + viewer.setZNear(zNear); + viewer.setZFar(zFar); + initComplete = true; + } - time.update(); + public void display(GLAutoDrawable drawable) { + // printThreadName("display for Listener"); - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + if (!initComplete) { + return; + } - // OK, ready to go - if (b[' ']) { - viewer.rotateAboutFocalPoint(new Rotf(Vec3f.Y_AXIS, (float) (time.deltaT() * animRate))); + if (!firstRender) { + if (++frameCount == 30) { + timer.stop(); + System.err.println("Frames per second: " + (30.0f / timer.getDurationAsSeconds())); + timer.reset(); + timer.start(); + frameCount = 0; } + } else { + firstRender = false; + timer.start(); + } - pbuffer.display(); + time.update(); - // FIXME: because of changes in lazy pbuffer instantiation - // behavior the pbuffer might not have been run just now - if (pipeline == null) { - return; - } + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - // blur pass - if (b['g']) { - // shrink image - blur2Pass = BLUR2_SHRINK_PASS; - blur2_pbuffer.display(); - } + // OK, ready to go + if (b[' ']) { + viewer.rotateAboutFocalPoint(new Rotf(Vec3f.Y_AXIS, (float) (time.deltaT() * animRate))); + } - // horizontal blur - blur_pbuffer.display(); + pbuffer.display(); - // vertical blur - blur2Pass = BLUR2_VERT_BLUR_PASS; + // FIXME: because of changes in lazy pbuffer instantiation + // behavior the pbuffer might not have been run just now + if (pipeline == null) { + return; + } + + // blur pass + if (b['g']) { + // shrink image + blur2Pass = BLUR2_SHRINK_PASS; blur2_pbuffer.display(); + } - // tone mapping pass - tonemap_pbuffer.display(); + // horizontal blur + blur_pbuffer.display(); - // display in window - gl.glEnable(GL.GL_TEXTURE_RECTANGLE_NV); - gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); - gl.glBindTexture(GL.GL_TEXTURE_RECTANGLE_NV, tonemap_pbuffer_tex); - if (b['n']) { - gl.glTexParameteri( GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - } else { - gl.glTexParameteri( GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - } - drawQuadRect4(gl, win_w, win_h, pbuffer_w, pbuffer_h); - gl.glDisable(GL.GL_TEXTURE_RECTANGLE_NV); + // vertical blur + blur2Pass = BLUR2_VERT_BLUR_PASS; + blur2_pbuffer.display(); + + // tone mapping pass + tonemap_pbuffer.display(); - // Try to avoid swamping the CPU on Linux - Thread.yield(); + // display in window + gl.glEnable(GL.GL_TEXTURE_RECTANGLE_NV); + gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); + gl.glBindTexture(GL.GL_TEXTURE_RECTANGLE_NV, tonemap_pbuffer_tex); + if (b['n']) { + gl.glTexParameteri( GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + } else { + gl.glTexParameteri( GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); } + drawQuadRect4(gl, win_w, win_h, pbuffer_w, pbuffer_h); + gl.glDisable(GL.GL_TEXTURE_RECTANGLE_NV); - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + // Try to avoid swamping the CPU on Linux + Thread.yield(); + } - // Unused routines - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + setOrthoProjection(drawable.getGL(), width, height); + win_w = width; + win_h = height; + } - //---------------------------------------------------------------------- - // Internals only below this point - // - private void checkExtension(GL gl, String glExtensionName) { - if (!gl.isExtensionAvailable(glExtensionName)) { - unavailableExtension("Unable to initialize " + glExtensionName + " OpenGL extension"); - } - } + // Unused routines + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - private void unavailableExtension(String message) { - JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - initFailed = true; - runExit(); - throw new GLException(message); + private void checkExtension(GL gl, String glExtensionName) { + if (!gl.isExtensionAvailable(glExtensionName)) { + unavailableExtension("Unable to initialize " + glExtensionName + " OpenGL extension"); } + } - private void dispatchKey(int keyCode, char k) { - if (k < 256) - b[k] = !b[k]; + private void unavailableExtension(String message) { + JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); + demoListener.shutdownDemo(); + throw new GLException(message); + } - switch (keyCode) { - case KeyEvent.VK_ESCAPE: - case KeyEvent.VK_Q: - runExit(); - break; + private void dispatchKey(int keyCode, char k) { + if (k < 256) + b[k] = !b[k]; - case KeyEvent.VK_EQUALS: - exposure *= 2; - break; + switch (keyCode) { + case KeyEvent.VK_ESCAPE: + case KeyEvent.VK_Q: + demoListener.shutdownDemo(); + break; - case KeyEvent.VK_MINUS: - exposure *= 0.5f; - break; + case KeyEvent.VK_EQUALS: + exposure *= 2; + break; - case KeyEvent.VK_PLUS: - exposure += 1.0f; - break; + case KeyEvent.VK_MINUS: + exposure *= 0.5f; + break; - case KeyEvent.VK_UNDERSCORE: - exposure -= 1.0f; - break; + case KeyEvent.VK_PLUS: + exposure += 1.0f; + break; - case KeyEvent.VK_PERIOD: - blurAmount += 0.1f; - break; + case KeyEvent.VK_UNDERSCORE: + exposure -= 1.0f; + break; - case KeyEvent.VK_COMMA: - blurAmount -= 0.1f; - break; + case KeyEvent.VK_PERIOD: + blurAmount += 0.1f; + break; - case KeyEvent.VK_G: - if (b['g']) - blurAmount = 0.5f; - else - blurAmount = 0.0f; - break; + case KeyEvent.VK_COMMA: + blurAmount -= 0.1f; + break; - case KeyEvent.VK_O: - modelno = (modelno + 1) % numModels; - break; + case KeyEvent.VK_G: + if (b['g']) + blurAmount = 0.5f; + else + blurAmount = 0.0f; + break; + + case KeyEvent.VK_O: + modelno = (modelno + 1) % numModels; + break; - case KeyEvent.VK_V: - doViewAll = true; - break; - } + case KeyEvent.VK_V: + doViewAll = true; + break; } + } - // create gamma lookup table texture - private int createGammaTexture(GL gl, int size, float gamma) { - int[] tmp = new int[1]; - gl.glGenTextures(1, tmp, 0); - int texid = tmp[0]; + // create gamma lookup table texture + private int createGammaTexture(GL gl, int size, float gamma) { + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + int texid = tmp[0]; - int target = GL.GL_TEXTURE_1D; - gl.glBindTexture(target, texid); - gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + int target = GL.GL_TEXTURE_1D; + gl.glBindTexture(target, texid); + gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); - float[] img = new float [size]; + float[] img = new float [size]; - for(int i=0; i<size; i++) { - float x = i / (float) size; - img[i] = (float) Math.pow(x, gamma); - } + for(int i=0; i<size; i++) { + float x = i / (float) size; + img[i] = (float) Math.pow(x, gamma); + } - gl.glTexImage1D(target, 0, GL.GL_LUMINANCE, size, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, img, 0); + gl.glTexImage1D(target, 0, GL.GL_LUMINANCE, size, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, img, 0); - return texid; - } + return texid; + } - // create vignette texture - // based on Debevec's pflare.c - int createVignetteTexture(GL gl, int xsiz, int ysiz, float r0, float r1) { - int[] tmp = new int[1]; - gl.glGenTextures(1, tmp, 0); - int texid = tmp[0]; + // create vignette texture + // based on Debevec's pflare.c + int createVignetteTexture(GL gl, int xsiz, int ysiz, float r0, float r1) { + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + int texid = tmp[0]; - gl.glBindTexture(GL.GL_TEXTURE_RECTANGLE_NV, texid); - gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); - gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); - - gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); - - float[] img = new float [xsiz*ysiz]; - - for (int y = 0; y < ysiz; y++) { - for (int x = 0; x < xsiz; x++) { - float radius = (float) Math.sqrt((x-xsiz/2)*(x-xsiz/2) + (y-ysiz/2)*(y-ysiz/2)); - if (radius > r0) { - if (radius < r1) { - float t = 1.0f - (radius-r0)/(r1-r0); - float a = t * 2 - 1; - float reduce = (float) ((0.25 * Math.PI + 0.5 * Math.asin(a) + 0.5 * a * Math.sqrt( 1 - a*a ))/(0.5 * Math.PI)); - img[y*xsiz + x] = reduce; - } else { - img[y*xsiz + x] = 0.0f; - } + gl.glBindTexture(GL.GL_TEXTURE_RECTANGLE_NV, texid); + gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(GL.GL_TEXTURE_RECTANGLE_NV, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); + + float[] img = new float [xsiz*ysiz]; + + for (int y = 0; y < ysiz; y++) { + for (int x = 0; x < xsiz; x++) { + float radius = (float) Math.sqrt((x-xsiz/2)*(x-xsiz/2) + (y-ysiz/2)*(y-ysiz/2)); + if (radius > r0) { + if (radius < r1) { + float t = 1.0f - (radius-r0)/(r1-r0); + float a = t * 2 - 1; + float reduce = (float) ((0.25 * Math.PI + 0.5 * Math.asin(a) + 0.5 * a * Math.sqrt( 1 - a*a ))/(0.5 * Math.PI)); + img[y*xsiz + x] = reduce; } else { - img[y*xsiz + x] = 1.0f; + img[y*xsiz + x] = 0.0f; } + } else { + img[y*xsiz + x] = 1.0f; } } + } - gl.glTexImage2D(GL.GL_TEXTURE_RECTANGLE_NV, 0, GL.GL_LUMINANCE, xsiz, ysiz, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, img, 0); + gl.glTexImage2D(GL.GL_TEXTURE_RECTANGLE_NV, 0, GL.GL_LUMINANCE, xsiz, ysiz, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, img, 0); - return texid; - } + return texid; } //---------------------------------------------------------------------- @@ -1169,14 +1218,14 @@ public class HDR { private void usage() { System.err.println("usage: java demos.hdr.HDR [-cg] image.hdr pbuffer_w pbuffer_h window_scale blur_width blur_decimate [obj file]"); - System.exit(1); + demoListener.shutdownDemo(); } private void printThreadName(String where) { System.err.println("In " + where + ": current thread = " + Thread.currentThread().getName()); } - private void runExit() { + private static void runExit(final Animator animator) { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking diff --git a/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java b/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java index a59b208..8a0cdfc 100644 --- a/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java +++ b/src/demos/hwShadowmapsSimple/HWShadowmapsSimple.java @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2003 Sun Microsystems, Inc. + * Portions Copyright (C) 2003-2005 Sun Microsystems, Inc. * All rights reserved. */ @@ -57,10 +57,45 @@ import gleem.linalg.*; Ported to Java by Kenneth Russell */ -public class HWShadowmapsSimple { - private volatile boolean quit; +public class HWShadowmapsSimple implements GLEventListener { + public static void main(String[] args) { + final GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + HWShadowmapsSimple demo = new HWShadowmapsSimple(); + canvas.addGLEventListener(demo); + + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(); + } + public void repaint() { + canvas.repaint(); + } + }); + + Frame frame = new Frame("ARB_shadow Shadows"); + frame.setLayout(new BorderLayout()); + canvas.setSize(512, 512); + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); + frame.show(); + canvas.requestFocus(); - private GLCanvas canvas; + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + runExit(); + } + }); + } + + public void setDemoListener(DemoListener listener) { + demoListener = listener; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private DemoListener demoListener; private GLPbuffer pbuffer; private GLUT glut; @@ -131,254 +166,226 @@ public class HWShadowmapsSimple { private Mat4f spotlightInverseTransform = new Mat4f(); private Mat4f objectTransform = new Mat4f(); - public static void main(String[] args) { - new HWShadowmapsSimple().run(args); - } + public void init(GLAutoDrawable drawable) { + // Use debug pipeline + // drawable.setGL(new DebugGL(drawable.getGL())); - public void run(String[] args) { - canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - canvas.addGLEventListener(new Listener()); + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); + glut = new GLUT(); - Frame frame = new Frame("ARB_shadow Shadows"); - frame.setLayout(new BorderLayout()); - canvas.setSize(512, 512); - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); - frame.show(); - canvas.requestFocus(); + try { + checkExtension(gl, "GL_ARB_multitexture"); + checkExtension(gl, "GL_ARB_depth_texture"); + checkExtension(gl, "GL_ARB_shadow"); + checkExtension(gl, "GL_ARB_pbuffer"); + checkExtension(gl, "GL_ARB_pixel_format"); + } catch (GLException e) { + e.printStackTrace(); + throw(e); + } + + gl.glClearColor(.5f, .5f, .5f, .5f); - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - runExit(); - } - }); - } + decal = genTexture(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, decal); + BufferedImage img = readPNGImage("demos/data/images/decal_image.png"); + makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, true); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - //---------------------------------------------------------------------- - // Internals only below this point - // + light_image = genTexture(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, light_image); + img = readPNGImage("demos/data/images/nvlogo_spot.png"); + makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, true); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); - class Listener implements GLEventListener { + quad = gl.glGenLists(1); + gl.glNewList(quad, GL.GL_COMPILE); + gl.glPushMatrix(); + gl.glRotatef(-90, 1, 0, 0); + gl.glScalef(4,4,4); + gl.glBegin(GL.GL_QUADS); + gl.glNormal3f(0, 0, 1); + gl.glVertex2f(-1, -1); + gl.glVertex2f(-1, 1); + gl.glVertex2f( 1, 1); + gl.glVertex2f( 1, -1); + gl.glEnd(); + gl.glPopMatrix(); + gl.glEndList(); - public void init(GLAutoDrawable drawable) { - // Use debug pipeline - // drawable.setGL(new DebugGL(drawable.getGL())); + wirecube = gl.glGenLists(1); + gl.glNewList(wirecube, GL.GL_COMPILE); + glut.glutWireCube(gl, 2); + gl.glEndList(); - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - glut = new GLUT(); - - try { - checkExtension(gl, "GL_ARB_multitexture"); - checkExtension(gl, "GL_ARB_depth_texture"); - checkExtension(gl, "GL_ARB_shadow"); - checkExtension(gl, "GL_ARB_pbuffer"); - checkExtension(gl, "GL_ARB_pixel_format"); - } catch (GLException e) { - e.printStackTrace(); - throw(e); - } - - gl.glClearColor(.5f, .5f, .5f, .5f); - - decal = genTexture(gl); - gl.glBindTexture(GL.GL_TEXTURE_2D, decal); - BufferedImage img = readPNGImage("demos/data/images/decal_image.png"); - makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, true); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - - light_image = genTexture(gl); - gl.glBindTexture(GL.GL_TEXTURE_2D, light_image); - img = readPNGImage("demos/data/images/nvlogo_spot.png"); - makeRGBTexture(gl, glu, img, GL.GL_TEXTURE_2D, true); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); - - quad = gl.glGenLists(1); - gl.glNewList(quad, GL.GL_COMPILE); - gl.glPushMatrix(); - gl.glRotatef(-90, 1, 0, 0); - gl.glScalef(4,4,4); - gl.glBegin(GL.GL_QUADS); - gl.glNormal3f(0, 0, 1); - gl.glVertex2f(-1, -1); - gl.glVertex2f(-1, 1); - gl.glVertex2f( 1, 1); - gl.glVertex2f( 1, -1); - gl.glEnd(); - gl.glPopMatrix(); - gl.glEndList(); - - wirecube = gl.glGenLists(1); - gl.glNewList(wirecube, GL.GL_COMPILE); - glut.glutWireCube(gl, 2); - gl.glEndList(); - - geometry = gl.glGenLists(1); - gl.glNewList(geometry, GL.GL_COMPILE); - gl.glPushMatrix(); - glut.glutSolidTeapot(gl, 0.8f); - gl.glPopMatrix(); - gl.glEndList(); - - gl.glEnable(GL.GL_LIGHT0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, light_ambient, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, light_intensity, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, light_intensity, 0); + geometry = gl.glGenLists(1); + gl.glNewList(geometry, GL.GL_COMPILE); + gl.glPushMatrix(); + glut.glutSolidTeapot(gl, 0.8f); + gl.glPopMatrix(); + gl.glEndList(); - gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_LIGHT0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, light_ambient, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, light_intensity, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, light_intensity, 0); + + gl.glEnable(GL.GL_DEPTH_TEST); - // init pbuffer - GLCapabilities caps = new GLCapabilities(); - caps.setDoubleBuffered(false); + // init pbuffer + GLCapabilities caps = new GLCapabilities(); + caps.setDoubleBuffered(false); - if (!GLDrawableFactory.getFactory().canCreateGLPbuffer(caps, TEX_SIZE, TEX_SIZE)) { - unavailableExtension("Can not create pbuffer"); - } - pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, TEX_SIZE, TEX_SIZE, drawable.getContext()); - pbuffer.addGLEventListener(new PbufferListener()); - - // Register the window with the ManipManager - ManipManager manager = ManipManager.getManipManager(); - manager.registerWindow(drawable); - - object = new HandleBoxManip(); - object.setTranslation(new Vec3f(0, 0.7f, 1.8f)); - object.setGeometryScale(new Vec3f(0.7f, 0.7f, 0.7f)); - manager.showManipInWindow(object, drawable); - - spotlight = new HandleBoxManip(); - spotlight.setScale(new Vec3f(0.5f, 0.5f, 0.5f)); - spotlight.setTranslation(new Vec3f(-0.25f, 2.35f, 5.0f)); - spotlight.setRotation(new Rotf(Vec3f.X_AXIS, (float) Math.toRadians(-30.0f))); - manager.showManipInWindow(spotlight, drawable); - - viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); - viewer.attach(drawable, new BSphereProvider() { - public BSphere getBoundingSphere() { - return new BSphere(object.getTranslation(), 2.0f); - } - }); - viewer.setOrientation(new Rotf(Vec3f.Y_AXIS, (float) Math.toRadians(45.0f)).times - (new Rotf(Vec3f.X_AXIS, (float) Math.toRadians(-15.0f)))); - viewer.setVertFOV((float) Math.toRadians(lightshaper_fovy / 2.0f)); - viewer.setZNear(zNear); - viewer.setZFar(zFar); - - float bias = 1/((float) Math.pow(2.0,16.0)-1); - - tweaks.add(new Tweak("r coordinate scale", 0.5f, bias)); - tweaks.add(new Tweak("r coordinate bias", 0.5f, bias)); - tweaks.add(new Tweak("polygon offset scale", 2.5f, 0.5f)); - tweaks.add(new Tweak("polygon offset bias", 10.0f, 1.0f)); - - drawable.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - dispatchKey(e.getKeyChar()); - canvas.repaint(); - } - }); + if (!GLDrawableFactory.getFactory().canCreateGLPbuffer(caps, TEX_SIZE, TEX_SIZE)) { + unavailableExtension("Can not create pbuffer"); } - - public void display(GLAutoDrawable drawable) { - viewer.update(); - - // Grab these values once per render to avoid multithreading - // issues with their values being changed by manipulation from - // the AWT thread during the render - CameraParameters params = viewer.getCameraParameters(); - - cameraPerspective.set(params.getProjectionMatrix()); - cameraInverseTransform.set(params.getModelviewMatrix()); - cameraTransform.set(cameraInverseTransform); - cameraTransform.invertRigid(); - spotlightTransform.set(spotlight.getTransform()); - spotlightInverseTransform.set(spotlightTransform); - spotlightInverseTransform.invertRigid(); - objectTransform.set(object.getTransform()); - - if (displayMode == RENDER_SCENE_FROM_CAMERA_VIEW_SHADOWED || !fullyInitialized) { - if (pbuffer != null) { - pbuffer.display(); + if (pbuffer != null) { + pbuffer.destroy(); + pbuffer = null; + } + pbuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, TEX_SIZE, TEX_SIZE, drawable.getContext()); + pbuffer.addGLEventListener(new PbufferListener()); + + doViewAll = true; + + // Register the window with the ManipManager + ManipManager manager = ManipManager.getManipManager(); + manager.registerWindow(drawable); + + object = new HandleBoxManip(); + object.setTranslation(new Vec3f(0, 0.7f, 1.8f)); + object.setGeometryScale(new Vec3f(0.7f, 0.7f, 0.7f)); + manager.showManipInWindow(object, drawable); + + spotlight = new HandleBoxManip(); + spotlight.setScale(new Vec3f(0.5f, 0.5f, 0.5f)); + spotlight.setTranslation(new Vec3f(-0.25f, 2.35f, 5.0f)); + spotlight.setRotation(new Rotf(Vec3f.X_AXIS, (float) Math.toRadians(-30.0f))); + manager.showManipInWindow(spotlight, drawable); + + viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); + viewer.attach(drawable, new BSphereProvider() { + public BSphere getBoundingSphere() { + return new BSphere(object.getTranslation(), 2.0f); } - } + }); + viewer.setOrientation(new Rotf(Vec3f.Y_AXIS, (float) Math.toRadians(45.0f)).times + (new Rotf(Vec3f.X_AXIS, (float) Math.toRadians(-15.0f)))); + viewer.setVertFOV((float) Math.toRadians(lightshaper_fovy / 2.0f)); + viewer.setZNear(zNear); + viewer.setZFar(zFar); + + float bias = 1/((float) Math.pow(2.0,16.0)-1); + + tweaks.add(new Tweak("r coordinate scale", 0.5f, bias)); + tweaks.add(new Tweak("r coordinate bias", 0.5f, bias)); + tweaks.add(new Tweak("polygon offset scale", 2.5f, 0.5f)); + tweaks.add(new Tweak("polygon offset bias", 10.0f, 1.0f)); + + drawable.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + dispatchKey(e.getKeyChar()); + demoListener.repaint(); + } + }); + } - if (!fullyInitialized) { - // Repaint again later once everything is set up - canvas.repaint(); - return; + public void display(GLAutoDrawable drawable) { + viewer.update(); + + // Grab these values once per render to avoid multithreading + // issues with their values being changed by manipulation from + // the AWT thread during the render + CameraParameters params = viewer.getCameraParameters(); + + cameraPerspective.set(params.getProjectionMatrix()); + cameraInverseTransform.set(params.getModelviewMatrix()); + cameraTransform.set(cameraInverseTransform); + cameraTransform.invertRigid(); + spotlightTransform.set(spotlight.getTransform()); + spotlightInverseTransform.set(spotlightTransform); + spotlightInverseTransform.invertRigid(); + objectTransform.set(object.getTransform()); + + if (displayMode == RENDER_SCENE_FROM_CAMERA_VIEW_SHADOWED || !fullyInitialized) { + if (pbuffer != null) { + pbuffer.display(); } + } - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - if (doViewAll) { - viewer.viewAll(gl); - doViewAll = false; - // Immediately zap effects - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); - // Schedule repaint to clean up first bogus frame - canvas.repaint(); - } + if (!fullyInitialized) { + // Repaint again later once everything is set up + demoListener.repaint(); + return; + } - switch (displayMode) { - case RENDER_SCENE_FROM_CAMERA_VIEW: render_scene_from_camera_view(gl, glu, drawable, params); break; - case RENDER_SCENE_FROM_CAMERA_VIEW_SHADOWED: render_scene_from_camera_view_shadowed(gl, glu, drawable, params); break; - case RENDER_SCENE_FROM_LIGHT_VIEW: render_scene_from_light_view(gl, glu); break; - default: throw new RuntimeException("Illegal display mode " + displayMode); - } + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + if (doViewAll) { + viewer.viewAll(gl); + doViewAll = false; + // Immediately zap effects + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); + // Schedule repaint to clean up first bogus frame + demoListener.repaint(); } - // Unused routines - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + switch (displayMode) { + case RENDER_SCENE_FROM_CAMERA_VIEW: render_scene_from_camera_view(gl, glu, drawable, params); break; + case RENDER_SCENE_FROM_CAMERA_VIEW_SHADOWED: render_scene_from_camera_view_shadowed(gl, glu, drawable, params); break; + case RENDER_SCENE_FROM_LIGHT_VIEW: render_scene_from_light_view(gl, glu, drawable); break; + default: throw new RuntimeException("Illegal display mode " + displayMode); + } + } - //---------------------------------------------------------------------- - // Internals only below this point - // + // Unused routines + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - private void checkExtension(GL gl, String extensionName) { - if (!gl.isExtensionAvailable(extensionName)) { - String message = "Unable to initialize " + extensionName + " OpenGL extension"; - unavailableExtension(message); - } + private void checkExtension(GL gl, String extensionName) { + if (!gl.isExtensionAvailable(extensionName)) { + String message = "Unable to initialize " + extensionName + " OpenGL extension"; + unavailableExtension(message); } + } - private void unavailableExtension(String message) { - JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - throw new GLException(message); - } + private void unavailableExtension(String message) { + JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); + throw new GLException(message); + } - private void dispatchKey(char k) { - switch (k) { - case 27: - case 'q': - runExit(); - break; + private void dispatchKey(char k) { + switch (k) { + case 27: + case 'q': + demoListener.shutdownDemo(); + break; - case 'v': - doViewAll = true; - System.err.println("Forcing viewAll()"); - break; + case 'v': + doViewAll = true; + System.err.println("Forcing viewAll()"); + break; - case ' ': - displayMode = (displayMode + 1) % NUM_DISPLAY_MODES; - System.err.println("Switching to display mode " + displayMode); - break; + case ' ': + displayMode = (displayMode + 1) % NUM_DISPLAY_MODES; + System.err.println("Switching to display mode " + displayMode); + break; - // FIXME: add more key behaviors from original demo + // FIXME: add more key behaviors from original demo - default: - break; - } + default: + break; } } @@ -417,7 +424,7 @@ public class HWShadowmapsSimple { ((Tweak) tweaks.get(POLYGON_OFFSET_BIAS)).val); gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); - render_scene_from_light_view(gl, glu); + render_scene_from_light_view(gl, glu, drawable); gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); @@ -643,7 +650,7 @@ public class HWShadowmapsSimple { gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); - gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight()); + gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); applyTransform(gl, cameraPerspective); gl.glMatrixMode(GL.GL_MODELVIEW); render_scene(gl, cameraTransform, drawable, params); @@ -712,7 +719,7 @@ public class HWShadowmapsSimple { gl.glMatrixMode(GL.GL_PROJECTION); gl.glLoadIdentity(); - gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight()); + gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); applyTransform(gl, cameraPerspective); gl.glMatrixMode(GL.GL_MODELVIEW); render_scene(gl, cameraTransform, drawable, params); @@ -728,16 +735,15 @@ public class HWShadowmapsSimple { render_light_frustum(gl); } - private void largest_square_power_of_two_viewport(GL gl) { - Dimension dim = canvas.getSize(); - float min = Math.min(dim.width, dim.height); + private void largest_square_power_of_two_viewport(GL gl, GLAutoDrawable drawable) { + float min = Math.min(drawable.getWidth(), drawable.getHeight()); float log2min = (float) Math.log(min) / (float) Math.log(2.0); float pow2 = (float) Math.floor(log2min); int size = 1 << (int) pow2; gl.glViewport(0, 0, size, size); } - private void render_scene_from_light_view(GL gl, GLU glu) { + private void render_scene_from_light_view(GL gl, GLU glu, GLAutoDrawable drawable) { // place light gl.glPushMatrix(); gl.glLoadIdentity(); @@ -771,7 +777,7 @@ public class HWShadowmapsSimple { glu.gluPerspective(lightshaper_fovy, 1, lightshaper_zNear, lightshaper_zFar); gl.glMatrixMode(GL.GL_MODELVIEW); if (displayMode == RENDER_SCENE_FROM_LIGHT_VIEW) - largest_square_power_of_two_viewport(gl); + largest_square_power_of_two_viewport(gl, drawable); render_scene(gl, spotlightTransform, null, null); gl.glActiveTextureARB(GL.GL_TEXTURE1_ARB); @@ -820,7 +826,7 @@ public class HWShadowmapsSimple { return m; } - private void runExit() { + private static void runExit() { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking diff --git a/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java b/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java index 7232957..2731fa3 100644 --- a/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java +++ b/src/demos/infiniteShadowVolumes/InfiniteShadowVolumes.java @@ -65,19 +65,22 @@ import gleem.linalg.*; Ported to Java by Kenneth Russell */ -public class InfiniteShadowVolumes { - private GLCanvas canvas; - private volatile boolean quit; - +public class InfiniteShadowVolumes implements GLEventListener { public static void main(String[] args) { - new InfiniteShadowVolumes().run(args); - } - - public void run(String[] args) { GLCapabilities caps = new GLCapabilities(); caps.setStencilBits(16); - canvas = GLDrawableFactory.getFactory().createGLCanvas(caps); - canvas.addGLEventListener(new Listener()); + final GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(caps); + InfiniteShadowVolumes demo = new InfiniteShadowVolumes(); + canvas.addGLEventListener(demo); + + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(); + } + public void repaint() { + canvas.repaint(); + } + }); Frame frame = new Frame("Infinite Stenciled Shadow Volumes"); frame.setLayout(new BorderLayout()); @@ -94,6 +97,16 @@ public class InfiniteShadowVolumes { }); } + public void setDemoListener(DemoListener listener) { + demoListener = listener; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private DemoListener demoListener; + static class Model { Model() { frame_num = 0; @@ -159,1136 +172,1127 @@ public class InfiniteShadowVolumes { private boolean hideCurrentModel; private boolean toggleWireframe; - class Listener implements GLEventListener { - public void init(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - - gl.glClearStencil(128); - //glEnable(GL.GL_DEPTH_CLAMP_NV); - gl.glEnable(GL.GL_DEPTH_TEST); - gl.glDepthFunc(GL.GL_LESS); - gl.glEnable(GL.GL_NORMALIZE); - gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); - float[] ambient = new float[] {0.3f, 0.3f, 0.3f, 1}; - gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); - faceDisplayList = gl.glGenLists(1); - gl.glNewList(faceDisplayList, GL.GL_COMPILE); - drawMesh(gl, 20, 40); - gl.glEndList(); - - int[] tmp = new int[1]; - gl.glGenTextures(1, tmp, 0); - wallTexObject = tmp[0]; - gl.glBindTexture(GL.GL_TEXTURE_2D, wallTexObject); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP_SGIS, GL.GL_TRUE); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - float[] tex = new float[32*32]; - for(int i=0; i < 32; i++) { - for(int j=0; j < 32; j++) { - if ((i>>4 ^ j>>4) != 0) - tex[i+j*32] = 1; - else - tex[i+j*32] = .9f; - } + public void init(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); + + gl.glClearStencil(128); + //glEnable(GL.GL_DEPTH_CLAMP_NV); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glDepthFunc(GL.GL_LESS); + gl.glEnable(GL.GL_NORMALIZE); + gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); + float[] ambient = new float[] {0.3f, 0.3f, 0.3f, 1}; + gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); + faceDisplayList = gl.glGenLists(1); + gl.glNewList(faceDisplayList, GL.GL_COMPILE); + drawMesh(gl, 20, 40); + gl.glEndList(); + + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + wallTexObject = tmp[0]; + gl.glBindTexture(GL.GL_TEXTURE_2D, wallTexObject); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP_SGIS, GL.GL_TRUE); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + float[] tex = new float[32*32]; + for(int i=0; i < 32; i++) { + for(int j=0; j < 32; j++) { + if ((i>>4 ^ j>>4) != 0) + tex[i+j*32] = 1; + else + tex[i+j*32] = .9f; } - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 32, 32, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, tex, 0); + } + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 32, 32, 0, GL.GL_LUMINANCE, GL.GL_FLOAT, tex, 0); - initModel(); - - b['S'] = true; // no silhouette outlines - b['v'] = true; // no volume drawing - b['I'] = true; // use infinite far plane - b['L'] = true; // use local light for shadowing - - drawable.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { - dispatchKey(e.getKeyChar()); - canvas.repaint(); - } - }); - - // Register the window with the ManipManager - ManipManager manager = ManipManager.getManipManager(); - manager.registerWindow(drawable); - - objectManip = new HandleBoxManip(); - manager.showManipInWindow(objectManip, drawable); - objectManip.setTranslation(new Vec3f(0, 0, -2)); - objectManip.setRotation(new Rotf(new Vec3f(1, 0, 0), (float) Math.toRadians(-90))); - - lightManip = new HandleBoxManip(); - manager.showManipInWindow(lightManip, drawable); - lightManip.setTranslation(new Vec3f(0.5f, 0.5f, -1)); - lightManip.setGeometryScale(new Vec3f(0.1f, 0.1f, 0.1f)); - - viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); - viewer.attach(drawable, new BSphereProvider() { - public BSphere getBoundingSphere() { - return new BSphere(objectManip.getTranslation(), 1.0f); - } - }); - viewer.setZNear(1.0f); - viewer.setZFar(100.0f); - viewer.setOrientation(new Rotf(new Vec3f(0, 1, 0), (float) Math.toRadians(15))); + initModel(); - // FIXME - // glutAddMenuEntry("mouse controls view [1]", '1'); - // glutAddMenuEntry("mouse controls model [2]", '2'); - // glutAddMenuEntry("mouse controls light [3]", '3'); - // glutAddMenuEntry("mouse controls room [4]", '4'); - // glutAddMenuEntry("enable depth clamp [!]", '!'); - // glutAddMenuEntry("disable depth clamp [~]", '~'); - // glutAddMenuEntry("start animation [ ]", ' '); - // glutAddMenuEntry("step animation forward [a]", 'a'); - // glutAddMenuEntry("step animation backward [b]", 'b'); - // glutAddMenuEntry("toggle drawing silhouette [S]", 'S'); - // glutAddMenuEntry("toggle drawing shadow [s]", 's'); - // glutAddMenuEntry("toggle drawing visible shadow volume [v]", 'v'); - // glutAddMenuEntry("toggle drawing model geometry[m]", 'm'); + b['S'] = true; // no silhouette outlines + b['v'] = true; // no volume drawing + b['I'] = true; // use infinite far plane + b['L'] = true; // use local light for shadowing - // glutAddMenuEntry("increase shadow volume alpha [;]", ';'); - // glutAddMenuEntry("decrease shadow volume alpha [:]", ':'); + doViewAll = true; - // glutAddMenuEntry("next model [,]", ','); - // glutAddMenuEntry("hide current model [.]", '.'); + drawable.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + dispatchKey(e.getKeyChar()); + demoListener.repaint(); + } + }); - // glutAddMenuEntry("toggle view frustum clip planes [X]", 'X'); + // Register the window with the ManipManager + ManipManager manager = ManipManager.getManipManager(); + manager.registerWindow(drawable); - // glutAddMenuEntry("camera view [5]", '5'); - // glutAddMenuEntry("scene view [6]", '6'); - // glutAddMenuEntry("clipspace view [7]", '7'); + objectManip = new HandleBoxManip(); + manager.showManipInWindow(objectManip, drawable); + objectManip.setTranslation(new Vec3f(0, 0, -2)); + objectManip.setRotation(new Rotf(new Vec3f(1, 0, 0), (float) Math.toRadians(-90))); - // glutAddMenuEntry("enable depth clamp [!]", '!'); - // glutAddMenuEntry("disable depth clamp [~]", '~'); + lightManip = new HandleBoxManip(); + manager.showManipInWindow(lightManip, drawable); + lightManip.setTranslation(new Vec3f(0.5f, 0.5f, -1)); + lightManip.setGeometryScale(new Vec3f(0.1f, 0.1f, 0.1f)); - // glutAddMenuEntry("increase light size [n]", 'n'); - // glutAddMenuEntry("decrease light size [N]", 'N'); + viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); + viewer.attach(drawable, new BSphereProvider() { + public BSphere getBoundingSphere() { + return new BSphere(objectManip.getTranslation(), 1.0f); + } + }); + viewer.setZNear(1.0f); + viewer.setZFar(100.0f); + viewer.setOrientation(new Rotf(new Vec3f(0, 1, 0), (float) Math.toRadians(15))); - // glutAddMenuEntry("move near plane in [[]", '['); - // glutAddMenuEntry("move near plane out []]", ']'); - // glutAddMenuEntry("move far plane in [{]", '['); - // glutAddMenuEntry("move far plane out [}]", ']'); + // FIXME + // glutAddMenuEntry("mouse controls view [1]", '1'); + // glutAddMenuEntry("mouse controls model [2]", '2'); + // glutAddMenuEntry("mouse controls light [3]", '3'); + // glutAddMenuEntry("mouse controls room [4]", '4'); + // glutAddMenuEntry("enable depth clamp [!]", '!'); + // glutAddMenuEntry("disable depth clamp [~]", '~'); + // glutAddMenuEntry("start animation [ ]", ' '); + // glutAddMenuEntry("step animation forward [a]", 'a'); + // glutAddMenuEntry("step animation backward [b]", 'b'); + // glutAddMenuEntry("toggle drawing silhouette [S]", 'S'); + // glutAddMenuEntry("toggle drawing shadow [s]", 's'); + // glutAddMenuEntry("toggle drawing visible shadow volume [v]", 'v'); + // glutAddMenuEntry("toggle drawing model geometry[m]", 'm'); - // glutAddMenuEntry("toggle local/infinite light [L]", 'L'); + // glutAddMenuEntry("increase shadow volume alpha [;]", ';'); + // glutAddMenuEntry("decrease shadow volume alpha [:]", ':'); - // glutAddMenuEntry("hide room [R]", 'R'); + // glutAddMenuEntry("next model [,]", ','); + // glutAddMenuEntry("hide current model [.]", '.'); - // glutAddMenuEntry("view all with camera [c]", 'c'); + // glutAddMenuEntry("toggle view frustum clip planes [X]", 'X'); - // glutAddMenuEntry("quit [<esc>]", 27); - } + // glutAddMenuEntry("camera view [5]", '5'); + // glutAddMenuEntry("scene view [6]", '6'); + // glutAddMenuEntry("clipspace view [7]", '7'); - public void display(GLAutoDrawable drawable) { - if (quit) { - return; - } + // glutAddMenuEntry("enable depth clamp [!]", '!'); + // glutAddMenuEntry("disable depth clamp [~]", '~'); - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + // glutAddMenuEntry("increase light size [n]", 'n'); + // glutAddMenuEntry("decrease light size [N]", 'N'); - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); + // glutAddMenuEntry("move near plane in [[]", '['); + // glutAddMenuEntry("move near plane out []]", ']'); + // glutAddMenuEntry("move far plane in [{]", '['); + // glutAddMenuEntry("move far plane out [}]", ']'); - if (doViewAll) { - viewer.viewAll(gl); - doViewAll = false; - } + // glutAddMenuEntry("toggle local/infinite light [L]", 'L'); - objectManipXform = objectManip.getTransform(); - lightManipXform = lightManip.getTransform(); + // glutAddMenuEntry("hide room [R]", 'R'); - if (toggleDepthClampNV) { - if (enableDepthClampNV) { - gl.glEnable(GL.GL_DEPTH_CLAMP_NV); - } else { - gl.glDisable(GL.GL_DEPTH_CLAMP_NV); - } - toggleDepthClampNV = false; - } + // glutAddMenuEntry("view all with camera [c]", 'c'); - if (b[' ']) { - animateForward = true; - } + // glutAddMenuEntry("quit [<esc>]", 27); + } - if (animateForward) { - Model mm = m[curr_model]; - mm.frame_num += mm.frame_incr; - if (mm.frame_num >= mm.mod.f.length) - mm.frame_num = 0; - interpolate_frame(); - animateForward = false; - } + public void display(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - if (animateBackward) { - Model mm = m[curr_model]; - mm.frame_num -= mm.frame_incr; - if (mm.frame_num < 0) - mm.frame_num += mm.mod.f.length; - interpolate_frame(); - animateBackward = false; - } + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); - if (hideCurrentModel) { - gl.glNewList(faceDisplayList, GL.GL_COMPILE); - drawMesh(gl, 20, 40); - gl.glEndList(); - hideCurrentModel = false; - } + if (doViewAll) { + viewer.viewAll(gl); + doViewAll = false; + } - if (toggleWireframe) { - if(b['w']) - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); - else - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); - } + objectManipXform = objectManip.getTransform(); + lightManipXform = lightManip.getTransform(); - if(b['I']) { - // push far plane to infinity - switch (curr_view) { - case CAMERA_VIEW: - viewer.update(gl); - // Undo perspective effects of ExaminerViewer - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); - applyInfinitePerspective(gl, viewer); - break; - - case SCENE_VIEW: - applyInfinitePerspective(gl, viewer); - // FIXME: do we need more primitives in the ExaminerViewer class? - // scenecam.apply_inverse_transform(); - break; - - case CLIP_VIEW: - applyInfinitePerspective(gl, viewer); - // FIXME - // clipcam.apply_inverse_transform(); - gl.glScalef(10,10,-10); - applyInfinitePerspective(gl, viewer); - break; - - default: - break; - } + if (toggleDepthClampNV) { + if (enableDepthClampNV) { + gl.glEnable(GL.GL_DEPTH_CLAMP_NV); } else { - switch (curr_view) { - case CAMERA_VIEW: - viewer.update(gl); - break; - - case SCENE_VIEW: - applyInfinitePerspective(gl, viewer); - // FIXME - // scenecam.apply_inverse_transform(); - break; - - case CLIP_VIEW: - applyInfinitePerspective(gl, viewer); - // FIXME - // clipcam.apply_inverse_transform(); - gl.glScalef(10,10,-10); - // FIXME - // reshaper.apply_projection(); - break; - - default: - break; - } + gl.glDisable(GL.GL_DEPTH_CLAMP_NV); } + toggleDepthClampNV = false; + } - gl.glMatrixMode(GL.GL_MODELVIEW); + if (b[' ']) { + animateForward = true; + } - // FIXME - if (b['X']) { - gl.glLoadIdentity(); - if(b['I']) { - // FIXME - applyInfinitePerspectiveInverse(gl, viewer); - } else { - // FIXME - // reshaper.apply_projection_inverse(); - } - double[] pos_x = new double[] {-1, 0, 0, 1}; - double[] neg_x = new double[] { 1, 0, 0, 1}; - double[] pos_y = new double[] { 0,-1, 0, 1}; - double[] neg_y = new double[] { 0, 1, 0, 1}; - double[] pos_z = new double[] { 0, 0,-1, 1}; - double[] neg_z = new double[] { 0, 0, 1, 1}; - gl.glClipPlane(GL.GL_CLIP_PLANE0, pos_x, 0); - gl.glClipPlane(GL.GL_CLIP_PLANE1, neg_x, 0); - gl.glClipPlane(GL.GL_CLIP_PLANE2, pos_y, 0); - gl.glClipPlane(GL.GL_CLIP_PLANE3, neg_y, 0); - gl.glClipPlane(GL.GL_CLIP_PLANE4, pos_z, 0); - gl.glClipPlane(GL.GL_CLIP_PLANE5, neg_z, 0); - gl.glEnable(GL.GL_CLIP_PLANE0); - gl.glEnable(GL.GL_CLIP_PLANE1); - gl.glEnable(GL.GL_CLIP_PLANE2); - gl.glEnable(GL.GL_CLIP_PLANE3); - gl.glEnable(GL.GL_CLIP_PLANE4); - gl.glEnable(GL.GL_CLIP_PLANE5); - gl.glLoadIdentity(); - } + if (animateForward) { + Model mm = m[curr_model]; + mm.frame_num += mm.frame_incr; + if (mm.frame_num >= mm.mod.f.length) + mm.frame_num = 0; + interpolate_frame(); + animateForward = false; + } - gl.glPushMatrix(); - // FIXME - // camera.apply_inverse_transform(); - // light.apply_transform(); - gl.glMultMatrixf(getData(lightManipXform), 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, getData(light_position), 0); - gl.glPopMatrix(); - gl.glEnable(GL.GL_LIGHT0); + if (animateBackward) { + Model mm = m[curr_model]; + mm.frame_num -= mm.frame_incr; + if (mm.frame_num < 0) + mm.frame_num += mm.mod.f.length; + interpolate_frame(); + animateBackward = false; + } - // FIXME - gl.glPushMatrix(); - // gl.glLoadIdentity(); - // camera.apply_inverse_transform(); + if (hideCurrentModel) { + gl.glNewList(faceDisplayList, GL.GL_COMPILE); + drawMesh(gl, 20, 40); + gl.glEndList(); + hideCurrentModel = false; + } - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); + if (toggleWireframe) { + if(b['w']) + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); + else + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + } - ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); - ManipManager.getManipManager().render(drawable, gl); + if(b['I']) { + // push far plane to infinity + switch (curr_view) { + case CAMERA_VIEW: + viewer.update(gl); + // Undo perspective effects of ExaminerViewer + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + applyInfinitePerspective(gl, viewer); + break; - if (!b['R']) { - drawRoom(gl, false); - } + case SCENE_VIEW: + applyInfinitePerspective(gl, viewer); + // FIXME: do we need more primitives in the ExaminerViewer class? + // scenecam.apply_inverse_transform(); + break; - if (!b['m']) { - for (int i = 0; i < num_models; i++) - if (m[i].draw) - drawModel(gl, i, false); - } + case CLIP_VIEW: + applyInfinitePerspective(gl, viewer); + // FIXME + // clipcam.apply_inverse_transform(); + gl.glScalef(10,10,-10); + applyInfinitePerspective(gl, viewer); + break; - if (b['X']) { - gl.glDisable(GL.GL_CLIP_PLANE0); - gl.glDisable(GL.GL_CLIP_PLANE1); - gl.glDisable(GL.GL_CLIP_PLANE2); - gl.glDisable(GL.GL_CLIP_PLANE3); - gl.glDisable(GL.GL_CLIP_PLANE4); - gl.glDisable(GL.GL_CLIP_PLANE5); + default: + break; } + } else { + switch (curr_view) { + case CAMERA_VIEW: + viewer.update(gl); + break; + + case SCENE_VIEW: + applyInfinitePerspective(gl, viewer); + // FIXME + // scenecam.apply_inverse_transform(); + break; - if (!b['s']) { - for (int i = 0; i < num_models; i++) - if (m[i].draw) - drawShadowVolumeToStencil(gl, i); - } + case CLIP_VIEW: + applyInfinitePerspective(gl, viewer); + // FIXME + // clipcam.apply_inverse_transform(); + gl.glScalef(10,10,-10); + // FIXME + // reshaper.apply_projection(); + break; - // Be aware that this can cause some multipass artifacts - // due to invariance issues. - if (b['X']) { - gl.glEnable(GL.GL_CLIP_PLANE0); - gl.glEnable(GL.GL_CLIP_PLANE1); - gl.glEnable(GL.GL_CLIP_PLANE2); - gl.glEnable(GL.GL_CLIP_PLANE3); - gl.glEnable(GL.GL_CLIP_PLANE4); - gl.glEnable(GL.GL_CLIP_PLANE5); - } - if (!b['d']) { - if (!b['R']) - drawRoom(gl, true); - if (!b['m']) - for (int i = 0; i < num_models; i++) - if (m[i].draw) - drawModel(gl, i, true); + default: + break; } + } - if(!b['S']) { - for (int i = 0; i < num_models; i++) - if (m[i].draw) - drawPossibleSilhouette(gl, i); + gl.glMatrixMode(GL.GL_MODELVIEW); + + // FIXME + if (b['X']) { + gl.glLoadIdentity(); + if(b['I']) { + // FIXME + applyInfinitePerspectiveInverse(gl, viewer); + } else { + // FIXME + // reshaper.apply_projection_inverse(); } + double[] pos_x = new double[] {-1, 0, 0, 1}; + double[] neg_x = new double[] { 1, 0, 0, 1}; + double[] pos_y = new double[] { 0,-1, 0, 1}; + double[] neg_y = new double[] { 0, 1, 0, 1}; + double[] pos_z = new double[] { 0, 0,-1, 1}; + double[] neg_z = new double[] { 0, 0, 1, 1}; + gl.glClipPlane(GL.GL_CLIP_PLANE0, pos_x, 0); + gl.glClipPlane(GL.GL_CLIP_PLANE1, neg_x, 0); + gl.glClipPlane(GL.GL_CLIP_PLANE2, pos_y, 0); + gl.glClipPlane(GL.GL_CLIP_PLANE3, neg_y, 0); + gl.glClipPlane(GL.GL_CLIP_PLANE4, pos_z, 0); + gl.glClipPlane(GL.GL_CLIP_PLANE5, neg_z, 0); + gl.glEnable(GL.GL_CLIP_PLANE0); + gl.glEnable(GL.GL_CLIP_PLANE1); + gl.glEnable(GL.GL_CLIP_PLANE2); + gl.glEnable(GL.GL_CLIP_PLANE3); + gl.glEnable(GL.GL_CLIP_PLANE4); + gl.glEnable(GL.GL_CLIP_PLANE5); + gl.glLoadIdentity(); + } + + gl.glPushMatrix(); + // FIXME + // camera.apply_inverse_transform(); + // light.apply_transform(); + gl.glMultMatrixf(getData(lightManipXform), 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, getData(light_position), 0); + gl.glPopMatrix(); + gl.glEnable(GL.GL_LIGHT0); + + // FIXME + gl.glPushMatrix(); + // gl.glLoadIdentity(); + // camera.apply_inverse_transform(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); - if (!b['v']) { + ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); + ManipManager.getManipManager().render(drawable, gl); + + if (!b['R']) { + drawRoom(gl, false); + } + + if (!b['m']) { + for (int i = 0; i < num_models; i++) + if (m[i].draw) + drawModel(gl, i, false); + } + + if (b['X']) { + gl.glDisable(GL.GL_CLIP_PLANE0); + gl.glDisable(GL.GL_CLIP_PLANE1); + gl.glDisable(GL.GL_CLIP_PLANE2); + gl.glDisable(GL.GL_CLIP_PLANE3); + gl.glDisable(GL.GL_CLIP_PLANE4); + gl.glDisable(GL.GL_CLIP_PLANE5); + } + + if (!b['s']) { + for (int i = 0; i < num_models; i++) + if (m[i].draw) + drawShadowVolumeToStencil(gl, i); + } + + // Be aware that this can cause some multipass artifacts + // due to invariance issues. + if (b['X']) { + gl.glEnable(GL.GL_CLIP_PLANE0); + gl.glEnable(GL.GL_CLIP_PLANE1); + gl.glEnable(GL.GL_CLIP_PLANE2); + gl.glEnable(GL.GL_CLIP_PLANE3); + gl.glEnable(GL.GL_CLIP_PLANE4); + gl.glEnable(GL.GL_CLIP_PLANE5); + } + if (!b['d']) { + if (!b['R']) + drawRoom(gl, true); + if (!b['m']) for (int i = 0; i < num_models; i++) if (m[i].draw) - drawShadowVolumeToColor(gl, i); - } + drawModel(gl, i, true); + } - // Be aware that this can cause some multipass artifacts - // due to invariance issues. - if (b['X']) { - gl.glDisable(GL.GL_CLIP_PLANE0); - gl.glDisable(GL.GL_CLIP_PLANE1); - gl.glDisable(GL.GL_CLIP_PLANE2); - gl.glDisable(GL.GL_CLIP_PLANE3); - gl.glDisable(GL.GL_CLIP_PLANE4); - gl.glDisable(GL.GL_CLIP_PLANE5); - } + if(!b['S']) { + for (int i = 0; i < num_models; i++) + if (m[i].draw) + drawPossibleSilhouette(gl, i); + } + + if (!b['v']) { + for (int i = 0; i < num_models; i++) + if (m[i].draw) + drawShadowVolumeToColor(gl, i); + } - drawLight(gl, glu); + // Be aware that this can cause some multipass artifacts + // due to invariance issues. + if (b['X']) { + gl.glDisable(GL.GL_CLIP_PLANE0); + gl.glDisable(GL.GL_CLIP_PLANE1); + gl.glDisable(GL.GL_CLIP_PLANE2); + gl.glDisable(GL.GL_CLIP_PLANE3); + gl.glDisable(GL.GL_CLIP_PLANE4); + gl.glDisable(GL.GL_CLIP_PLANE5); + } - gl.glPopMatrix(); + drawLight(gl, glu); - // In an "external" viewing mode, show the camera's view volume - // as a yellow wireframe cube or frustum. - if (curr_view != CAMERA_VIEW) { - gl.glPushMatrix(); - if (b['I']) { - // FIXME - applyInfinitePerspectiveInverse(gl, viewer); - } else { - // FIXME - // reshaper.apply_projection_inverse(); - } - gl.glColor3f(.75f,.75f,0); - gl.glLineWidth(3); - glut.glutWireCube(gl, 2); - gl.glLineWidth(1); - gl.glPopMatrix(); - } + gl.glPopMatrix(); - if (b[' ']) { - // Animating continually. Schedule another repaint soon. - canvas.repaint(); + // In an "external" viewing mode, show the camera's view volume + // as a yellow wireframe cube or frustum. + if (curr_view != CAMERA_VIEW) { + gl.glPushMatrix(); + if (b['I']) { + // FIXME + applyInfinitePerspectiveInverse(gl, viewer); + } else { + // FIXME + // reshaper.apply_projection_inverse(); } + gl.glColor3f(.75f,.75f,0); + gl.glLineWidth(3); + glut.glutWireCube(gl, 2); + gl.glLineWidth(1); + gl.glPopMatrix(); } - // Unused routines - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + if (b[' ']) { + // Animating continually. Schedule another repaint soon. + demoListener.repaint(); + } + } - //---------------------------------------------------------------------- - // Internals only below this point - // + // Unused routines + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - private void dispatchKey(char k) { - b[k] = ! b[k]; - if (k==27 || k=='q') { - runExit(); - return; - } + private void dispatchKey(char k) { + b[k] = ! b[k]; + if (k==27 || k=='q') { + demoListener.shutdownDemo(); + return; + } - if(';' == k) { - volume_alpha *= 1.1f; - } - if(':' == k) { - volume_alpha /= 1.1f; - } + if(';' == k) { + volume_alpha *= 1.1f; + } + if(':' == k) { + volume_alpha /= 1.1f; + } - if('\'' == k) { - room_ambient += .025f; - } - if('"' == k) { - room_ambient -= .025f; - } + if('\'' == k) { + room_ambient += .025f; + } + if('"' == k) { + room_ambient -= .025f; + } - if(',' == k) { - curr_model++; - curr_model %= num_models; - // FIXME - // key('2',0,0); - } - if('.' == k) { - m[curr_model].draw = ! m[curr_model].draw; - } - if('w' == k) { - toggleWireframe = true; - } - if('1' == k) { - // FIXME - /* + if(',' == k) { + curr_model++; + curr_model %= num_models; + // FIXME + // key('2',0,0); + } + if('.' == k) { + m[curr_model].draw = ! m[curr_model].draw; + } + if('w' == k) { + toggleWireframe = true; + } + if('1' == k) { + // FIXME + /* curr_manip = 1; camera.disable(); clipcam.disable(); scenecam.disable(); if(curr_view == 0) - camera.enable(); + camera.enable(); else if(curr_view == 1) - scenecam.enable(); + scenecam.enable(); else - clipcam.enable(); + clipcam.enable(); for(int i=0; i < num_models; i++) - object[i].disable(); + object[i].disable(); light.disable(); room.disable(); - */ - } - if('2' == k) { - // FIXME - /* + */ + } + if('2' == k) { + // FIXME + /* curr_manip = 2; camera.disable(); clipcam.disable(); scenecam.disable(); light.disable(); for(int i=0; i < num_models; i++) - object[i].disable(); + object[i].disable(); object[curr_model].enable(); room.disable(); - */ - } - if('3' == k) { - // FIXME - /* + */ + } + if('3' == k) { + // FIXME + /* curr_manip = 3; camera.disable(); clipcam.disable(); scenecam.disable(); light.enable(); for(int i=0; i < num_models; i++) - object[i].disable(); + object[i].disable(); room.disable(); - */ - } - if('4' == k) { - // FIXME - /* + */ + } + if('4' == k) { + // FIXME + /* curr_manip = 4; camera.disable(); clipcam.disable(); scenecam.disable(); light.disable(); for(int i=0; i < num_models; i++) - object[i].disable(); + object[i].disable(); room.enable(); - */ - } + */ + } - if('5' == k) { - // FIXME - /* + if('5' == k) { + // FIXME + /* curr_view = 0; if(curr_manip == 1) - key('1',0,0); - */ - } + key('1',0,0); + */ + } - if('6' == k) { - // FIXME - /* + if('6' == k) { + // FIXME + /* curr_view = 1; if(curr_manip == 1) - key('1',0,0); - */ - } + key('1',0,0); + */ + } - if('7' == k) { - // FIXME - /* + if('7' == k) { + // FIXME + /* curr_view = 2; if(curr_manip == 1) - key('1',0,0); - */ - } - - if('[' == k) { - // FIXME: correct? - viewer.setZNear(viewer.getZNear() / 2); - // reshaper.zNear /= 2; - } - if(']' == k) { - // FIXME: correct? - viewer.setZNear(viewer.getZNear() * 2); - // reshaper.zNear *= 2; - } + key('1',0,0); + */ + } - if('{' == k) { - // FIXME: correct? - viewer.setZFar(viewer.getZFar() / 2); - // reshaper.zFar /= 2; - } - if('}' == k) { - // FIXME: correct? - viewer.setZFar(viewer.getZFar() * 2); - // reshaper.zFar *= 2; - } + if('[' == k) { + // FIXME: correct? + viewer.setZNear(viewer.getZNear() / 2); + // reshaper.zNear /= 2; + } + if(']' == k) { + // FIXME: correct? + viewer.setZNear(viewer.getZNear() * 2); + // reshaper.zNear *= 2; + } - if('!' == k) { - enableDepthClampNV = true; - toggleDepthClampNV = true; - } - if('~' == k) { - enableDepthClampNV = false; - toggleDepthClampNV = true; - } + if('{' == k) { + // FIXME: correct? + viewer.setZFar(viewer.getZFar() / 2); + // reshaper.zFar /= 2; + } + if('}' == k) { + // FIXME: correct? + viewer.setZFar(viewer.getZFar() * 2); + // reshaper.zFar *= 2; + } - if('a' == k) { - animateForward = true; - } + if('!' == k) { + enableDepthClampNV = true; + toggleDepthClampNV = true; + } + if('~' == k) { + enableDepthClampNV = false; + toggleDepthClampNV = true; + } - if('b' == k) { - animateBackward = true; - } + if('a' == k) { + animateForward = true; + } - if('.' == k) { - hideCurrentModel = true; - } + if('b' == k) { + animateBackward = true; + } - if('n' == k) { - light_object_scale *= 1.1f; - } - if('N' == k) { - light_object_scale /= 1.1f; - } + if('.' == k) { + hideCurrentModel = true; + } - if('L' == k) { - if(b[k]) - light_position.set(0,0,0,1); - else - light_position.set(0.25f, 0.25f, 1, 0); - } + if('n' == k) { + light_object_scale *= 1.1f; + } + if('N' == k) { + light_object_scale /= 1.1f; + } - if ('c' == k) { - doViewAll = true; - } + if('L' == k) { + if(b[k]) + light_position.set(0,0,0,1); + else + light_position.set(0.25f, 0.25f, 1, 0); } - private void initModel() { - int i = 0; - - try { - MD2.Model mod = MD2.loadMD2(getClass().getClassLoader().getResourceAsStream("demos/data/models/knight.md2")); - m[i] = new Model(); - m[i].mod = mod; - m[i].interp_frame = (MD2.Frame) m[i].mod.f[0].clone(); - m[i].ambient.componentMul(m[i].diffuse); - i++; - } catch (IOException e) { - e.printStackTrace(); - } + if ('c' == k) { + doViewAll = true; + } + } - num_models = i; + private void initModel() { + int i = 0; + + try { + MD2.Model mod = MD2.loadMD2(getClass().getClassLoader().getResourceAsStream("demos/data/models/knight.md2")); + m[i] = new Model(); + m[i].mod = mod; + m[i].interp_frame = (MD2.Frame) m[i].mod.f[0].clone(); + m[i].ambient.componentMul(m[i].diffuse); + i++; + } catch (IOException e) { + e.printStackTrace(); } - // interpolate between keyframes - private void interpolate_frame() { - float frac = m[curr_model].frame_num - (float) Math.floor(m[curr_model].frame_num); - int f0_index = (int) Math.floor(m[curr_model].frame_num); - int f1_index = ((int) Math.ceil(m[curr_model].frame_num)) % m[curr_model].mod.f.length; - MD2.Frame f0 = m[curr_model].mod.f[f0_index]; - MD2.Frame f1 = m[curr_model].mod.f[f1_index]; - - for (int i = 0; i < f0.pn.length; i++) { - MD2.PositionNormal pn = m[curr_model].interp_frame.pn[i]; - MD2.PositionNormal pn0 = f0.pn[i]; - MD2.PositionNormal pn1 = f1.pn[i]; - - pn.x = (1-frac) * pn0.x + frac * pn1.x; - pn.y = (1-frac) * pn0.y + frac * pn1.y; - pn.z = (1-frac) * pn0.z + frac * pn1.z; - pn.nx = (1-frac) * pn0.nx + frac * pn1.nx; - pn.ny = (1-frac) * pn0.ny + frac * pn1.ny; - pn.nz = (1-frac) * pn0.nz + frac * pn1.nz; - } + num_models = i; + } + + // interpolate between keyframes + private void interpolate_frame() { + float frac = m[curr_model].frame_num - (float) Math.floor(m[curr_model].frame_num); + int f0_index = (int) Math.floor(m[curr_model].frame_num); + int f1_index = ((int) Math.ceil(m[curr_model].frame_num)) % m[curr_model].mod.f.length; + MD2.Frame f0 = m[curr_model].mod.f[f0_index]; + MD2.Frame f1 = m[curr_model].mod.f[f1_index]; + + for (int i = 0; i < f0.pn.length; i++) { + MD2.PositionNormal pn = m[curr_model].interp_frame.pn[i]; + MD2.PositionNormal pn0 = f0.pn[i]; + MD2.PositionNormal pn1 = f1.pn[i]; + + pn.x = (1-frac) * pn0.x + frac * pn1.x; + pn.y = (1-frac) * pn0.y + frac * pn1.y; + pn.z = (1-frac) * pn0.z + frac * pn1.z; + pn.nx = (1-frac) * pn0.nx + frac * pn1.nx; + pn.ny = (1-frac) * pn0.ny + frac * pn1.ny; + pn.nz = (1-frac) * pn0.nz + frac * pn1.nz; + } - for (int i = 0; i < f0.triplane.length; i++) { - MD2.Plane p = m[curr_model].interp_frame.triplane[i]; + for (int i = 0; i < f0.triplane.length; i++) { + MD2.Plane p = m[curr_model].interp_frame.triplane[i]; - MD2.computePlane(m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[0].pn_index], - m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[1].pn_index], - m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[2].pn_index], - p); - } + MD2.computePlane(m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[0].pn_index], + m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[1].pn_index], + m[curr_model].interp_frame.pn[m[curr_model].mod.tri[i].v[2].pn_index], + p); } + } - // This routine draws the end caps (both local and infinite) for an - // occluder. These caps are required for the zfail approach to work. - private void drawShadowVolumeEndCaps(GL gl, int mindex) { - Vec4f olight = new Vec4f(); + // This routine draws the end caps (both local and infinite) for an + // occluder. These caps are required for the zfail approach to work. + private void drawShadowVolumeEndCaps(GL gl, int mindex) { + Vec4f olight = new Vec4f(); + + Mat4f ml = new Mat4f(objectManipXform); + ml.invertRigid(); + ml = ml.mul(lightManipXform); + ml.xformVec(light_position, olight); + + MD2.PositionNormal[] vpn = m[mindex].interp_frame.pn; + + gl.glPushMatrix(); + gl.glMultMatrixf(getData(objectManipXform), 0); + gl.glBegin(GL.GL_TRIANGLES); + for (int i = 0; i < m[mindex].mod.tri.length; i++) { + if (m[mindex].mod.tri[i].kill) + continue; + MD2.Plane p = m[mindex].interp_frame.triplane[i]; + + boolean facing_light = (( p.a * olight.get(0) + + p.b * olight.get(1) + + p.c * olight.get(2) + + p.d * olight.get(3) ) >= 0 ); + + for (int j = 0; j < 3; j++) { + MD2.PositionNormal pn = vpn[m[mindex].mod.tri[i].v[j].pn_index]; + if (facing_light) // draw locally + gl.glVertex4f(pn.x, pn.y, pn.z, 1); + else // draw at infinity + gl.glVertex4f(pn.x*olight.get(3) - olight.get(0), + pn.y*olight.get(3) - olight.get(1), + pn.z*olight.get(3) - olight.get(2), + 0); + } + } + gl.glEnd(); + gl.glPopMatrix(); + } - Mat4f ml = new Mat4f(objectManipXform); - ml.invertRigid(); - ml = ml.mul(lightManipXform); - ml.xformVec(light_position, olight); + private void drawModel(GL gl, int mindex, boolean do_diffuse) { + MD2.PositionNormal[] vpn = m[mindex].interp_frame.pn; + + float[] zero = new float[] { 0, 0, 0, 0}; + float[] dim = new float[] {.2f,.2f,.2f,.2f}; + float[] diffuse = new float[4]; + float[] specular = new float[4]; + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, getData(m[mindex].ambient), 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, getData(m[mindex].diffuse), 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, getData(m[mindex].specular), 0); + gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, m[mindex].shininess); + if (!do_diffuse) { + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, dim, 0); + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, zero, 0); + } else { + gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); + gl.glEnable(GL.GL_BLEND); + gl.glStencilFunc(GL.GL_EQUAL, 128, ~0); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + gl.glEnable(GL.GL_STENCIL_TEST); + gl.glDepthFunc(GL.GL_EQUAL); + } + gl.glPushMatrix(); + gl.glMultMatrixf(getData(objectManipXform), 0); + gl.glEnable(GL.GL_LIGHTING); - MD2.PositionNormal[] vpn = m[mindex].interp_frame.pn; + gl.glPolygonOffset(0,-2); + gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); - gl.glPushMatrix(); - gl.glMultMatrixf(getData(objectManipXform), 0); - gl.glBegin(GL.GL_TRIANGLES); + gl.glBegin(GL.GL_TRIANGLES); + { for (int i = 0; i < m[mindex].mod.tri.length; i++) { - if (m[mindex].mod.tri[i].kill) - continue; - MD2.Plane p = m[mindex].interp_frame.triplane[i]; - - boolean facing_light = (( p.a * olight.get(0) + - p.b * olight.get(1) + - p.c * olight.get(2) + - p.d * olight.get(3) ) >= 0 ); - - for (int j = 0; j < 3; j++) { + for(int j=0; j < 3; j++) { MD2.PositionNormal pn = vpn[m[mindex].mod.tri[i].v[j].pn_index]; - if (facing_light) // draw locally - gl.glVertex4f(pn.x, pn.y, pn.z, 1); - else // draw at infinity - gl.glVertex4f(pn.x*olight.get(3) - olight.get(0), - pn.y*olight.get(3) - olight.get(1), - pn.z*olight.get(3) - olight.get(2), - 0); + gl.glNormal3f(pn.nx, pn.ny, pn.nz); + gl.glVertex4f(pn.x, pn.y, pn.z, 1); } } - gl.glEnd(); - gl.glPopMatrix(); } + gl.glEnd(); - private void drawModel(GL gl, int mindex, boolean do_diffuse) { - MD2.PositionNormal[] vpn = m[mindex].interp_frame.pn; - - float[] zero = new float[] { 0, 0, 0, 0}; - float[] dim = new float[] {.2f,.2f,.2f,.2f}; - float[] diffuse = new float[4]; - float[] specular = new float[4]; - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, getData(m[mindex].ambient), 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, getData(m[mindex].diffuse), 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, getData(m[mindex].specular), 0); - gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, m[mindex].shininess); - if (!do_diffuse) { - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, dim, 0); - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, zero, 0); - } else { - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); - gl.glEnable(GL.GL_BLEND); - gl.glStencilFunc(GL.GL_EQUAL, 128, ~0); - gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); - gl.glEnable(GL.GL_STENCIL_TEST); - gl.glDepthFunc(GL.GL_EQUAL); - } - gl.glPushMatrix(); - gl.glMultMatrixf(getData(objectManipXform), 0); - gl.glEnable(GL.GL_LIGHTING); - - gl.glPolygonOffset(0,-2); - gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); - - gl.glBegin(GL.GL_TRIANGLES); - { - for (int i = 0; i < m[mindex].mod.tri.length; i++) { - for(int j=0; j < 3; j++) { - MD2.PositionNormal pn = vpn[m[mindex].mod.tri[i].v[j].pn_index]; - gl.glNormal3f(pn.nx, pn.ny, pn.nz); - gl.glVertex4f(pn.x, pn.y, pn.z, 1); - } - } - } - gl.glEnd(); - - gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); + gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); - gl.glDisable(GL.GL_LIGHTING); - gl.glPopMatrix(); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] { 0.8f, 0.8f, 0.8f, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 0.3f, 0.3f, 0.3f, 1}, 0); + gl.glDisable(GL.GL_LIGHTING); + gl.glPopMatrix(); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] { 0.8f, 0.8f, 0.8f, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 0.3f, 0.3f, 0.3f, 1}, 0); - if (!do_diffuse) { - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); - } else { - gl.glDisable(GL.GL_BLEND); - //glDisable(GL.GL_STENCIL_TEST); - gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); - gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + if (!do_diffuse) { + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); + } else { + gl.glDisable(GL.GL_BLEND); + //glDisable(GL.GL_STENCIL_TEST); + gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); - gl.glDepthFunc(GL.GL_LESS); - } + gl.glDepthFunc(GL.GL_LESS); } + } - // This is for drawing the walls of the room. - private void drawMesh(GL gl, float size, int tess) { - float hsize = size/2; - float delta = size/(tess-1); + // This is for drawing the walls of the room. + private void drawMesh(GL gl, float size, int tess) { + float hsize = size/2; + float delta = size/(tess-1); - gl.glPushMatrix(); - gl.glTranslatef(-hsize, -hsize, hsize); + gl.glPushMatrix(); + gl.glTranslatef(-hsize, -hsize, hsize); - gl.glNormal3f(0,0,-1); - - float x = 0; - for(int i=0; i < tess-1; i++) { - float y = 0; - gl.glBegin(GL.GL_QUAD_STRIP); - for(int j=0; j < tess; j++) { - gl.glTexCoord2f( x, y); - gl.glVertex2f ( x, y); - gl.glTexCoord2f(x+delta, y); - gl.glVertex2f (x+delta, y); - y += delta; - } - gl.glEnd(); - x += delta; + gl.glNormal3f(0,0,-1); + + float x = 0; + for(int i=0; i < tess-1; i++) { + float y = 0; + gl.glBegin(GL.GL_QUAD_STRIP); + for(int j=0; j < tess; j++) { + gl.glTexCoord2f( x, y); + gl.glVertex2f ( x, y); + gl.glTexCoord2f(x+delta, y); + gl.glVertex2f (x+delta, y); + y += delta; } - gl.glPopMatrix(); + gl.glEnd(); + x += delta; } + gl.glPopMatrix(); + } - private void drawCube(GL gl) { - gl.glBindTexture(GL.GL_TEXTURE_2D, wallTexObject); - gl.glEnable(GL.GL_TEXTURE_2D); - gl.glPushMatrix(); - // FIXME - // room.apply_transform(); - gl.glCallList(faceDisplayList); - gl.glRotatef(90, 1, 0, 0); - gl.glCallList(faceDisplayList); - gl.glRotatef(90, 1, 0, 0); - gl.glCallList(faceDisplayList); - gl.glRotatef(90, 1, 0, 0); - gl.glCallList(faceDisplayList); - gl.glRotatef(90, 1, 0, 0); - gl.glRotatef(90, 0, 1, 0); - gl.glCallList(faceDisplayList); - gl.glRotatef(180, 0, 1, 0); - gl.glCallList(faceDisplayList); - gl.glPopMatrix(); - gl.glDisable(GL.GL_TEXTURE_2D); - } + private void drawCube(GL gl) { + gl.glBindTexture(GL.GL_TEXTURE_2D, wallTexObject); + gl.glEnable(GL.GL_TEXTURE_2D); + gl.glPushMatrix(); + // FIXME + // room.apply_transform(); + gl.glCallList(faceDisplayList); + gl.glRotatef(90, 1, 0, 0); + gl.glCallList(faceDisplayList); + gl.glRotatef(90, 1, 0, 0); + gl.glCallList(faceDisplayList); + gl.glRotatef(90, 1, 0, 0); + gl.glCallList(faceDisplayList); + gl.glRotatef(90, 1, 0, 0); + gl.glRotatef(90, 0, 1, 0); + gl.glCallList(faceDisplayList); + gl.glRotatef(180, 0, 1, 0); + gl.glCallList(faceDisplayList); + gl.glPopMatrix(); + gl.glDisable(GL.GL_TEXTURE_2D); + } - private void drawRoom(GL gl, boolean do_diffuse) { - float[] zero = new float[] {0,0,0,0}; - float[] a = new float[4]; - a[0] = room_ambient; - a[1] = room_ambient; - a[2] = room_ambient; - a[3] = 1; - - float[] d1 = new float[] {.1f,.1f,.1f,.1f}; - float[] d2 = new float[] {.7f,.7f,.7f,.7f}; - float[] s = new float[] {.7f,.7f,.7f,.7f}; - float[] emission = new float[4]; - float[] ambient = new float[4]; - float[] diffuse = new float[4]; - float[] specular = new float[4]; - - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, a, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {0.8f, 0.8f, 0.8f, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] {0.4f, 0.4f, 0.4f, 1}, 0); - gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 64.0f); - - if (!do_diffuse) { - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, d1, 0); - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, zero, 0); - gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); - } else { - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, emission, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, zero, 0); - gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, zero, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, d2, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, s, 0); - - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); - gl.glEnable(GL.GL_BLEND); - gl.glStencilFunc(GL.GL_EQUAL, 128, ~0); - gl.glDepthFunc(GL.GL_EQUAL); - } - gl.glPushMatrix(); - gl.glTranslatef(0,9,0); - gl.glEnable(GL.GL_LIGHTING); - gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); - gl.glEnable(GL.GL_STENCIL_TEST); + private void drawRoom(GL gl, boolean do_diffuse) { + float[] zero = new float[] {0,0,0,0}; + float[] a = new float[4]; + a[0] = room_ambient; + a[1] = room_ambient; + a[2] = room_ambient; + a[3] = 1; + + float[] d1 = new float[] {.1f,.1f,.1f,.1f}; + float[] d2 = new float[] {.7f,.7f,.7f,.7f}; + float[] s = new float[] {.7f,.7f,.7f,.7f}; + float[] emission = new float[4]; + float[] ambient = new float[4]; + float[] diffuse = new float[4]; + float[] specular = new float[4]; + + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, a, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {0.8f, 0.8f, 0.8f, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] {0.4f, 0.4f, 0.4f, 1}, 0); + gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 64.0f); + + if (!do_diffuse) { + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, d1, 0); + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, zero, 0); + gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); + } else { + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, emission, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, zero, 0); + gl.glGetLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, zero, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, d2, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, s, 0); + + gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); + gl.glEnable(GL.GL_BLEND); + gl.glStencilFunc(GL.GL_EQUAL, 128, ~0); + gl.glDepthFunc(GL.GL_EQUAL); + } + gl.glPushMatrix(); + gl.glTranslatef(0,9,0); + gl.glEnable(GL.GL_LIGHTING); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + gl.glEnable(GL.GL_STENCIL_TEST); - drawCube(gl); + drawCube(gl); - gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); - gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); - gl.glDisable(GL.GL_LIGHTING); - gl.glPopMatrix(); + gl.glDisable(GL.GL_LIGHTING); + gl.glPopMatrix(); - if (!do_diffuse) { - gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); - } else { - gl.glLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, emission, 0); - gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); + if (!do_diffuse) { + gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, specular, 0); + } else { + gl.glLightfv(GL.GL_LIGHT0, GL.GL_EMISSION, emission, 0); + gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0); - gl.glDisable(GL.GL_BLEND); - gl.glDepthFunc(GL.GL_LESS); - } + gl.glDisable(GL.GL_BLEND); + gl.glDepthFunc(GL.GL_LESS); } + } - // This routine draws the extruded "possible silhouette" edge. The - // edge is extruded to infinity. - - // The paper describes identifying silhouette edge loops. The approach - // in this demo is to visit each edge, determine if it's a "possible silhouette" - // or not, and if it is, draw the extruded edge. This approach is not - // as efficient, but it has the benefit of being extremely simple. - - // This routine also doubles as the routine for drawing the local and ininite - // silhouette edges (when prim == GL_LINES). - private void drawShadowVolumeEdges(GL gl, - int mindex, - int prim, - boolean local, - boolean infinity) { - Vec4f olight = new Vec4f(); - - Mat4f ml = new Mat4f(objectManipXform); - ml.invertRigid(); - ml = ml.mul(lightManipXform); - ml.xformVec(light_position, olight); - - gl.glPushMatrix(); - gl.glMultMatrixf(getData(objectManipXform), 0); - - MD2.Frame f = m[mindex].interp_frame; - - gl.glBegin(prim); - for (int i = 0; i < m[mindex].mod.edge.length; i++) { - MD2.WingedEdge we = m[mindex].mod.edge[i]; - if (we.w[0] == -1 || m[mindex].mod.tri[we.w[0]].kill || - we.w[1] == -1 || m[mindex].mod.tri[we.w[1]].kill ) - continue; - - MD2.Plane p0 = f.triplane[we.w[0]]; - float f0 = ( p0.a * olight.get(0) + - p0.b * olight.get(1) + - p0.c * olight.get(2) + - p0.d * olight.get(3) ); + // This routine draws the extruded "possible silhouette" edge. The + // edge is extruded to infinity. + + // The paper describes identifying silhouette edge loops. The approach + // in this demo is to visit each edge, determine if it's a "possible silhouette" + // or not, and if it is, draw the extruded edge. This approach is not + // as efficient, but it has the benefit of being extremely simple. + + // This routine also doubles as the routine for drawing the local and ininite + // silhouette edges (when prim == GL_LINES). + private void drawShadowVolumeEdges(GL gl, + int mindex, + int prim, + boolean local, + boolean infinity) { + Vec4f olight = new Vec4f(); + + Mat4f ml = new Mat4f(objectManipXform); + ml.invertRigid(); + ml = ml.mul(lightManipXform); + ml.xformVec(light_position, olight); + + gl.glPushMatrix(); + gl.glMultMatrixf(getData(objectManipXform), 0); + + MD2.Frame f = m[mindex].interp_frame; + + gl.glBegin(prim); + for (int i = 0; i < m[mindex].mod.edge.length; i++) { + MD2.WingedEdge we = m[mindex].mod.edge[i]; + if (we.w[0] == -1 || m[mindex].mod.tri[we.w[0]].kill || + we.w[1] == -1 || m[mindex].mod.tri[we.w[1]].kill ) + continue; + + MD2.Plane p0 = f.triplane[we.w[0]]; + float f0 = ( p0.a * olight.get(0) + + p0.b * olight.get(1) + + p0.c * olight.get(2) + + p0.d * olight.get(3) ); - float f1 = -f0; - if(we.w[1] != -1) { - MD2.Plane p1 = f.triplane[we.w[1]]; - - f1 = ( p1.a * olight.get(0) + - p1.b * olight.get(1) + - p1.c * olight.get(2) + - p1.d * olight.get(3) ); - } - - int[] edge = new int[2]; - - if(f0 >= 0 && f1 < 0) { - edge[0] = we.e[1]; - edge[1] = we.e[0]; - } else if(f1 >= 0 && f0 < 0) { - edge[0] = we.e[0]; - edge[1] = we.e[1]; - } else { - continue; - } + float f1 = -f0; + if(we.w[1] != -1) { + MD2.Plane p1 = f.triplane[we.w[1]]; + + f1 = ( p1.a * olight.get(0) + + p1.b * olight.get(1) + + p1.c * olight.get(2) + + p1.d * olight.get(3) ); + } + + int[] edge = new int[2]; + + if(f0 >= 0 && f1 < 0) { + edge[0] = we.e[1]; + edge[1] = we.e[0]; + } else if(f1 >= 0 && f0 < 0) { + edge[0] = we.e[0]; + edge[1] = we.e[1]; + } else { + continue; + } - MD2.PositionNormal pn0 = f.pn[edge[0]]; - MD2.PositionNormal pn1 = f.pn[edge[1]]; - - if(prim == GL.GL_QUADS || local) { - // local segment - gl.glVertex4f(pn0.x, pn0.y, pn0.z, 1); - gl.glVertex4f(pn1.x, pn1.y, pn1.z, 1); - } - if(prim == GL.GL_QUADS || infinity) { - // segment projected to infinity - gl.glVertex4f(pn1.x*olight.get(3) - olight.get(0), - pn1.y*olight.get(3) - olight.get(1), - pn1.z*olight.get(3) - olight.get(2), - 0); - gl.glVertex4f(pn0.x*olight.get(3) - olight.get(0), - pn0.y*olight.get(3) - olight.get(1), - pn0.z*olight.get(3) - olight.get(2), - 0); - } - } - gl.glEnd(); - gl.glPopMatrix(); - } + MD2.PositionNormal pn0 = f.pn[edge[0]]; + MD2.PositionNormal pn1 = f.pn[edge[1]]; - private void drawShadowVolumeExtrudedEdges(GL gl, int mindex) { - drawShadowVolumeEdges(gl, mindex, GL.GL_QUADS, true, true); + if(prim == GL.GL_QUADS || local) { + // local segment + gl.glVertex4f(pn0.x, pn0.y, pn0.z, 1); + gl.glVertex4f(pn1.x, pn1.y, pn1.z, 1); + } + if(prim == GL.GL_QUADS || infinity) { + // segment projected to infinity + gl.glVertex4f(pn1.x*olight.get(3) - olight.get(0), + pn1.y*olight.get(3) - olight.get(1), + pn1.z*olight.get(3) - olight.get(2), + 0); + gl.glVertex4f(pn0.x*olight.get(3) - olight.get(0), + pn0.y*olight.get(3) - olight.get(1), + pn0.z*olight.get(3) - olight.get(2), + 0); + } } + gl.glEnd(); + gl.glPopMatrix(); + } - private void drawPossibleSilhouette(GL gl, int mindex) { - gl.glLineWidth(3); - gl.glColor3f(1,1,1); - drawShadowVolumeEdges(gl, mindex, GL.GL_LINES, true, !b['-']); - gl.glLineWidth(1); - } + private void drawShadowVolumeExtrudedEdges(GL gl, int mindex) { + drawShadowVolumeEdges(gl, mindex, GL.GL_QUADS, true, true); + } - // Draw the shadow volume into the stencil buffer. - private void drawShadowVolumeToStencil(GL gl, int mindex) { - gl.glDepthFunc(GL.GL_LESS); - gl.glDepthMask(false); + private void drawPossibleSilhouette(GL gl, int mindex) { + gl.glLineWidth(3); + gl.glColor3f(1,1,1); + drawShadowVolumeEdges(gl, mindex, GL.GL_LINES, true, !b['-']); + gl.glLineWidth(1); + } - gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); - gl.glEnable(GL.GL_STENCIL_TEST); + // Draw the shadow volume into the stencil buffer. + private void drawShadowVolumeToStencil(GL gl, int mindex) { + gl.glDepthFunc(GL.GL_LESS); + gl.glDepthMask(false); - gl.glEnable(GL.GL_CULL_FACE); - gl.glCullFace(GL.GL_FRONT); - gl.glStencilOp(GL.GL_KEEP, GL.GL_INCR, GL.GL_KEEP); - gl.glColorMask(false, false, false, false); + gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); + gl.glEnable(GL.GL_STENCIL_TEST); - drawShadowVolumeExtrudedEdges(gl, mindex); - drawShadowVolumeEndCaps(gl, mindex); + gl.glEnable(GL.GL_CULL_FACE); + gl.glCullFace(GL.GL_FRONT); + gl.glStencilOp(GL.GL_KEEP, GL.GL_INCR, GL.GL_KEEP); + gl.glColorMask(false, false, false, false); - gl.glCullFace(GL.GL_BACK); - gl.glStencilOp(GL.GL_KEEP, GL.GL_DECR, GL.GL_KEEP); + drawShadowVolumeExtrudedEdges(gl, mindex); + drawShadowVolumeEndCaps(gl, mindex); - drawShadowVolumeExtrudedEdges(gl, mindex); - drawShadowVolumeEndCaps(gl, mindex); + gl.glCullFace(GL.GL_BACK); + gl.glStencilOp(GL.GL_KEEP, GL.GL_DECR, GL.GL_KEEP); - gl.glColorMask(true, true, true, true); - gl.glDisable(GL.GL_CULL_FACE); + drawShadowVolumeExtrudedEdges(gl, mindex); + drawShadowVolumeEndCaps(gl, mindex); - gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); - gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); + gl.glColorMask(true, true, true, true); + gl.glDisable(GL.GL_CULL_FACE); - gl.glDepthMask(true); - gl.glDepthFunc(GL.GL_LESS); - } + gl.glStencilFunc(GL.GL_ALWAYS, 128, ~0); + gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP); - // Draw the shadow volume into the color buffer. - private void drawShadowVolumeToColor(GL gl, int mindex) { - gl.glDepthFunc(GL.GL_LESS); - gl.glDepthMask(false); + gl.glDepthMask(true); + gl.glDepthFunc(GL.GL_LESS); + } - gl.glEnable(GL.GL_BLEND); - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); + // Draw the shadow volume into the color buffer. + private void drawShadowVolumeToColor(GL gl, int mindex) { + gl.glDepthFunc(GL.GL_LESS); + gl.glDepthMask(false); - gl.glColor4f(1,1,1,.7f * volume_alpha); - drawShadowVolumeEndCaps(gl, mindex); - gl.glColor4f(1,1,.7f,.15f * volume_alpha); - drawShadowVolumeExtrudedEdges(gl, mindex); + gl.glEnable(GL.GL_BLEND); + gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); - gl.glDepthMask(true); - gl.glDepthFunc(GL.GL_LESS); - gl.glDisable(GL.GL_BLEND); - } + gl.glColor4f(1,1,1,.7f * volume_alpha); + drawShadowVolumeEndCaps(gl, mindex); + gl.glColor4f(1,1,.7f,.15f * volume_alpha); + drawShadowVolumeExtrudedEdges(gl, mindex); - // Draw an icon to show where the local light is - // or in what direction the infinite light is pointing. - private void drawLight(GL gl, GLU glu) { - gl.glColor3f(1,1,0); - gl.glPushMatrix(); - gl.glMultMatrixf(getData(lightManipXform), 0); - gl.glScalef(light_object_scale, light_object_scale, light_object_scale); - if (b['L']) { - glut.glutSolidSphere(glu, .01f, 20, 10); - } else { - Vec3f ldir = new Vec3f(light_position.get(0), - light_position.get(1), - light_position.get(2)); - Rotf r = new Rotf(new Vec3f(0,0,1), ldir); - Mat4f m = new Mat4f(); - m.makeIdent(); - m.setRotation(r); - m = m.mul(perspectiveInverse(30, 1, 0.001f, 0.04f)); - gl.glRotatef(180, 1, 0, 0); - gl.glTranslatef(0,0,-0.02f); - gl.glMultMatrixf(getData(m), 0); - glut.glutSolidCube(gl, 2); - } - gl.glPopMatrix(); - } + gl.glDepthMask(true); + gl.glDepthFunc(GL.GL_LESS); + gl.glDisable(GL.GL_BLEND); + } - // The infinite frustum set-up code. - private Mat4f infiniteFrustum(float left, float right, - float bottom, float top, - float zNear) { + // Draw an icon to show where the local light is + // or in what direction the infinite light is pointing. + private void drawLight(GL gl, GLU glu) { + gl.glColor3f(1,1,0); + gl.glPushMatrix(); + gl.glMultMatrixf(getData(lightManipXform), 0); + gl.glScalef(light_object_scale, light_object_scale, light_object_scale); + if (b['L']) { + glut.glutSolidSphere(glu, .01f, 20, 10); + } else { + Vec3f ldir = new Vec3f(light_position.get(0), + light_position.get(1), + light_position.get(2)); + Rotf r = new Rotf(new Vec3f(0,0,1), ldir); Mat4f m = new Mat4f(); m.makeIdent(); + m.setRotation(r); + m = m.mul(perspectiveInverse(30, 1, 0.001f, 0.04f)); + gl.glRotatef(180, 1, 0, 0); + gl.glTranslatef(0,0,-0.02f); + gl.glMultMatrixf(getData(m), 0); + glut.glutSolidCube(gl, 2); + } + gl.glPopMatrix(); + } + + // The infinite frustum set-up code. + private Mat4f infiniteFrustum(float left, float right, + float bottom, float top, + float zNear) { + Mat4f m = new Mat4f(); + m.makeIdent(); - m.set(0,0, (2*zNear) / (right - left)); - m.set(0,2, (right + left) / (right - left)); + m.set(0,0, (2*zNear) / (right - left)); + m.set(0,2, (right + left) / (right - left)); - m.set(1,1, (2*zNear) / (top - bottom)); - m.set(1,2, (top + bottom) / (top - bottom)); + m.set(1,1, (2*zNear) / (top - bottom)); + m.set(1,2, (top + bottom) / (top - bottom)); - // nudge infinity in just slightly for lsb slop - float nudge = 1 - 1.0f / (1<<23); + // nudge infinity in just slightly for lsb slop + float nudge = 1 - 1.0f / (1<<23); - m.set(2,2, -1 * nudge); - m.set(2,3, -2*zNear * nudge); + m.set(2,2, -1 * nudge); + m.set(2,3, -2*zNear * nudge); - m.set(3,2, -1); - m.set(3,3, 0); + m.set(3,2, -1); + m.set(3,3, 0); - m.transpose(); + m.transpose(); - return m; - } + return m; + } - private Mat4f infiniteFrustumInverse(float left, float right, - float bottom, float top, - float zNear) { - Mat4f m = new Mat4f(); - m.makeIdent(); + private Mat4f infiniteFrustumInverse(float left, float right, + float bottom, float top, + float zNear) { + Mat4f m = new Mat4f(); + m.makeIdent(); - m.set(0,0, (right - left) / (2 * zNear)); - m.set(0,3, (right + left) / (2 * zNear)); + m.set(0,0, (right - left) / (2 * zNear)); + m.set(0,3, (right + left) / (2 * zNear)); - m.set(1,1, (top - bottom) / (2 * zNear)); - m.set(1,3, (top + bottom) / (2 * zNear)); + m.set(1,1, (top - bottom) / (2 * zNear)); + m.set(1,3, (top + bottom) / (2 * zNear)); - m.set(2,2, 0); - m.set(2,3, -1); + m.set(2,2, 0); + m.set(2,3, -1); - m.set(3,2, -1 / (2 * zNear)); - m.set(3,3, 1 / (2 * zNear)); + m.set(3,2, -1 / (2 * zNear)); + m.set(3,3, 1 / (2 * zNear)); - return m; - } + return m; + } - private Mat4f infinitePerspective(float fovy, float aspect, float zNear) { - float tangent = (float) Math.tan(fovy / 2.0); - float y = tangent * zNear; - float x = aspect * y; - return infiniteFrustum(-x, x, -y, y, zNear); - } + private Mat4f infinitePerspective(float fovy, float aspect, float zNear) { + float tangent = (float) Math.tan(fovy / 2.0); + float y = tangent * zNear; + float x = aspect * y; + return infiniteFrustum(-x, x, -y, y, zNear); + } - private Mat4f infinitePerspectiveInverse(float fovy, float aspect, float zNear) { - float tangent = (float) Math.tan(fovy / 2.0); - float y = tangent * zNear; - float x = aspect * y; - return infiniteFrustumInverse(-x, x, -y, y, zNear); - } + private Mat4f infinitePerspectiveInverse(float fovy, float aspect, float zNear) { + float tangent = (float) Math.tan(fovy / 2.0); + float y = tangent * zNear; + float x = aspect * y; + return infiniteFrustumInverse(-x, x, -y, y, zNear); + } - private void applyInfinitePerspective(GL gl, ExaminerViewer v) { - CameraParameters parms = v.getCameraParameters(); - float aspect = parms.getImagePlaneAspectRatio(); - gl.glMultMatrixf(getData(infinitePerspective(parms.getVertFOV(), aspect, v.getZNear())), 0); - } + private void applyInfinitePerspective(GL gl, ExaminerViewer v) { + CameraParameters parms = v.getCameraParameters(); + float aspect = parms.getImagePlaneAspectRatio(); + gl.glMultMatrixf(getData(infinitePerspective(parms.getVertFOV(), aspect, v.getZNear())), 0); + } - private void applyInfinitePerspectiveInverse(GL gl, ExaminerViewer v) { - CameraParameters parms = v.getCameraParameters(); - float aspect = parms.getImagePlaneAspectRatio(); - gl.glMultMatrixf(getData(infinitePerspectiveInverse(parms.getVertFOV(), aspect, v.getZNear())), 0); - } + private void applyInfinitePerspectiveInverse(GL gl, ExaminerViewer v) { + CameraParameters parms = v.getCameraParameters(); + float aspect = parms.getImagePlaneAspectRatio(); + gl.glMultMatrixf(getData(infinitePerspectiveInverse(parms.getVertFOV(), aspect, v.getZNear())), 0); + } - private Mat4f perspectiveInverse(float fovy, float aspect, float zNear, float zFar) { - float tangent = (float) Math.tan(Math.toRadians(fovy / 2.0)); - float y = tangent * zNear; - float x = aspect * y; - return frustumInverse(-x, x, -y, y, zNear, zFar); - } + private Mat4f perspectiveInverse(float fovy, float aspect, float zNear, float zFar) { + float tangent = (float) Math.tan(Math.toRadians(fovy / 2.0)); + float y = tangent * zNear; + float x = aspect * y; + return frustumInverse(-x, x, -y, y, zNear, zFar); + } - private Mat4f frustumInverse(float left, float right, - float bottom, float top, - float zNear, float zFar) { - Mat4f m = new Mat4f(); - m.makeIdent(); + private Mat4f frustumInverse(float left, float right, + float bottom, float top, + float zNear, float zFar) { + Mat4f m = new Mat4f(); + m.makeIdent(); - m.set(0, 0, (right - left) / (2 * zNear)); - m.set(0, 3, (right + left) / (2 * zNear)); + m.set(0, 0, (right - left) / (2 * zNear)); + m.set(0, 3, (right + left) / (2 * zNear)); - m.set(1, 1, (top - bottom) / (2 * zNear)); - m.set(1, 3, (top + bottom) / (2 * zNear)); + m.set(1, 1, (top - bottom) / (2 * zNear)); + m.set(1, 3, (top + bottom) / (2 * zNear)); - m.set(2, 2, 0); - m.set(2, 3, -1); + m.set(2, 2, 0); + m.set(2, 3, -1); - m.set(3, 2, -(zFar - zNear) / (2 * zFar * zNear)); - m.set(3, 3, (zFar + zNear) / (2 * zFar * zNear)); + m.set(3, 2, -(zFar - zNear) / (2 * zFar * zNear)); + m.set(3, 3, (zFar + zNear) / (2 * zFar * zNear)); - return m; - } + return m; + } - private float[] getData(Vec4f v) { - return new float[] { v.x(), v.y(), v.z(), v.w() }; - } + private float[] getData(Vec4f v) { + return new float[] { v.x(), v.y(), v.z(), v.w() }; + } - private float[] getData(Mat4f m) { - float[] res = new float[16]; - m.getColumnMajorData(res); - return res; - } + private float[] getData(Mat4f m) { + float[] res = new float[16]; + m.getColumnMajorData(res); + return res; } - private void runExit() { - quit = true; + private static void runExit() { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking diff --git a/src/demos/jrefract/JRefract.java b/src/demos/jrefract/JRefract.java index eb5b751..b7a32d9 100755 --- a/src/demos/jrefract/JRefract.java +++ b/src/demos/jrefract/JRefract.java @@ -47,9 +47,14 @@ import javax.swing.event.*; import net.java.games.jogl.*; import net.java.games.jogl.util.*; import demos.gears.Gears; +import demos.hdr.HDR; +import demos.hwShadowmapsSimple.HWShadowmapsSimple; +import demos.infiniteShadowVolumes.InfiniteShadowVolumes; import demos.proceduralTexturePhysics.ProceduralTexturePhysics; import demos.util.*; +import demos.vertexBufferObject.VertexBufferObject; import demos.vertexProgRefract.VertexProgRefract; +import demos.vertexProgWarp.VertexProgWarp; /** Wavelength-dependent refraction demo<br> @@ -75,17 +80,25 @@ public class JRefract { new JRefract().run(args); } - private static final int GEARS = 1; - private static final int BUNNY = 2; - private static final int WATER = 3; + private static final int GEARS = 1; + private static final int HDR = 2; + private static final int HWSHADOWS = 3; + private static final int INFINITE = 4; + private static final int REFRACT = 5; + private static final int VBO = 6; + private static final int WARP = 7; + private static final int WATER = 8; private JInternalFrame addWindow(int which) { - String str = null; + String str = ""; switch (which) { - case GEARS: str = "Gears Demo"; break; - case BUNNY: str = "Refraction Using Vertex Programs"; break; - case WATER: str = "Procedural Texture Waves"; break; - default: throw new IllegalArgumentException("Invalid demo " + which); + case GEARS: str = "Gears Demo"; break; + case HDR: str = "High Dynamic Range Rendering Demo"; break; + case HWSHADOWS: str = "ARB_shadow Shadows"; break; + case INFINITE: str = "Infinite Shadow Volumes"; break; + case REFRACT: str = "Refraction Using Vertex Programs"; break; + case VBO: str = "Very Simple vertex_buffer_object demo"; break; + case WATER: str = "Procedural Texture Waves"; break; } final JInternalFrame inner = new JInternalFrame(str); inner.setResizable(true); @@ -96,6 +109,9 @@ public class JRefract { if (which == GEARS) { caps.setAlphaBits(8); } + if (which == INFINITE) { + caps.setStencilBits(16); + } final GLJPanel canvas = GLDrawableFactory.getFactory().createGLJPanel(caps); final DemoListener demoListener = new DemoListener() { public void shutdownDemo() { @@ -106,6 +122,10 @@ public class JRefract { } }); } + + public void repaint() { + canvas.repaint(); + } }; switch (which) { @@ -113,12 +133,56 @@ public class JRefract { canvas.addGLEventListener(new Gears()); break; } - case BUNNY: { + + case HDR: { + HDR demo = new HDR(); + demo.setDemoListener(demoListener); + demo.setup(null); + inner.setSize(demo.getPreferredWidth(), demo.getPreferredHeight()); + canvas.addGLEventListener(demo); + break; + } + + case HWSHADOWS: { + HWShadowmapsSimple demo = new HWShadowmapsSimple(); + demo.setDemoListener(demoListener); + canvas.addGLEventListener(demo); + break; + } + + case INFINITE: { + InfiniteShadowVolumes demo = new InfiniteShadowVolumes(); + demo.setDemoListener(demoListener); + canvas.addGLEventListener(demo); + break; + } + + case REFRACT: { VertexProgRefract demo = new VertexProgRefract(); demo.setDemoListener(demoListener); canvas.addGLEventListener(demo); break; } + + case VBO: { + VertexBufferObject demo = new VertexBufferObject(); + demo.setDemoListener(demoListener); + canvas.addGLEventListener(demo); + break; + } + + case WARP: { + VertexProgWarp demo = new VertexProgWarp(); + demo.setDemoListener(demoListener); + demo.setTitleSetter(new VertexProgWarp.TitleSetter() { + public void setTitle(String title) { + inner.setTitle(title); + } + }); + canvas.addGLEventListener(demo); + break; + } + case WATER: { ProceduralTexturePhysics demo = new ProceduralTexturePhysics(); demo.setDemoListener(demoListener); @@ -142,7 +206,7 @@ public class JRefract { }); inner.getContentPane().setLayout(new BorderLayout()); - if (which == BUNNY) { + if (which == REFRACT) { inner.getContentPane().add(canvas, BorderLayout.CENTER); inner.getContentPane().add(new JButton("West"), BorderLayout.WEST); inner.getContentPane().add(new JButton("East"), BorderLayout.EAST); @@ -173,7 +237,9 @@ public class JRefract { inner.getContentPane().add(canvas, BorderLayout.CENTER); } - inner.setSize(512, 512); + if (which != HDR) { + inner.setSize(512, 512); + } desktop.add(inner); return inner; @@ -201,23 +267,65 @@ public class JRefract { JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("Actions"); - JMenuItem item = new JMenuItem("New bunny"); + JMenuItem item; + + item = new JMenuItem("Gears"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - addWindow(BUNNY); + addWindow(GEARS); } }); menu.add(item); - item = new JMenuItem("New gears"); + item = new JMenuItem("High Dynamic Range"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - addWindow(GEARS); + addWindow(HDR); + } + }); + menu.add(item); + + item = new JMenuItem("Hardware Shadow Maps"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addWindow(HWSHADOWS); + } + }); + menu.add(item); + + item = new JMenuItem("Infinite Shadow Volumes"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addWindow(INFINITE); + } + }); + menu.add(item); + + item = new JMenuItem("Refraction"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addWindow(REFRACT); + } + }); + menu.add(item); + + item = new JMenuItem("Vertex Buffer Object"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addWindow(VBO); + } + }); + menu.add(item); + + item = new JMenuItem("Warp"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + addWindow(WARP); } }); menu.add(item); - item = new JMenuItem("New water"); + item = new JMenuItem("Water"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { addWindow(WATER); @@ -225,7 +333,7 @@ public class JRefract { }); menu.add(item); - item = new JMenuItem("Auto mode"); + item = new JMenuItem("Loop Gears Demo"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { startAutoMode(); @@ -233,12 +341,13 @@ public class JRefract { }); menu.add(item); - item = new JMenuItem("Exit"); + item = new JMenuItem("Quit"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { runExit(); } }); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK)); menu.add(item); menuBar.add(menu); diff --git a/src/demos/util/DemoListener.java b/src/demos/util/DemoListener.java index cbe7570..ee343e7 100755 --- a/src/demos/util/DemoListener.java +++ b/src/demos/util/DemoListener.java @@ -39,8 +39,12 @@ package demos.util; -/** Defines how demos can request to be shut down. Different harnesses - may respond differently to this event. */ +/** Defines certain events demos can send. Different harnesses + may respond differently to these events. */ public interface DemoListener { + /** Indicates that the demo wants to be terminated. */ public void shutdownDemo(); + + /** Indicates that a repaint should be scheduled later. */ + public void repaint(); } diff --git a/src/demos/vertexArrayRange/VertexArrayRange.java b/src/demos/vertexArrayRange/VertexArrayRange.java index 6b598f3..724f0c9 100644 --- a/src/demos/vertexArrayRange/VertexArrayRange.java +++ b/src/demos/vertexArrayRange/VertexArrayRange.java @@ -40,6 +40,7 @@ import java.util.*; import javax.swing.*; import net.java.games.jogl.*; +import demos.util.*; /** <P> A port of NVidia's [tm] Vertex Array Range demonstration to OpenGL[tm] for Java[tm] and the Java programming language. The @@ -72,7 +73,74 @@ import net.java.games.jogl.*; C++ speed with the HotSpot Client and Server compilers, respectively. </P> */ -public class VertexArrayRange { +public class VertexArrayRange implements GLEventListener { + public static void main(String[] args) { + boolean startSlow = false; + + if (args.length > 1) { + usage(); + } + + if (args.length == 1) { + if (args[0].equals("-slow")) { + startSlow = true; + } else { + usage(); + } + } + + GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + VertexArrayRange demo = new VertexArrayRange(); + if (startSlow) { + demo.setFlag('v', false); // VAR off + } + canvas.addGLEventListener(demo); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + }); + + Frame frame = new Frame("Very Simple NV_vertex_array_range demo"); + frame.setLayout(new BorderLayout()); + canvas.setSize(800, 800); + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); + frame.show(); + canvas.requestFocus(); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + runExit(animator); + } + }); + + animator.start(); + } + + private static void usage() { + System.out.println("usage: java VertexArrayRange [-slow]"); + System.out.println("-slow flag starts up using data in the Java heap"); + System.exit(0); + } + + public VertexArrayRange() { + setFlag(' ', true); // animation on + setFlag('i', true); // infinite viewer and light + setFlag('v', true); // VAR on + } + + public void setDemoListener(DemoListener listener) { + demoListener = listener; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private DemoListener demoListener; private boolean[] b = new boolean[256]; private static final int SIZEOF_FLOAT = 4; private static final int STRIP_SIZE = 48; @@ -122,7 +190,6 @@ public class VertexArrayRange { private volatile boolean toggleLighting = false; private volatile boolean toggleLightingModel = false; private volatile boolean recomputeElements = false; - private volatile boolean quit = false; // Frames-per-second computation private boolean firstProfiledFrame; @@ -130,9 +197,6 @@ public class VertexArrayRange { private int numDrawElementsCalls; private long startTimeMillis; - private GLCanvas canvas = null; - private Animator animator; - static class PeriodicIterator { public PeriodicIterator(int arraySize, float period, @@ -176,10 +240,6 @@ public class VertexArrayRange { index = initOffset; } - //---------------------------------------------------------------------- - // Internals only below this point - // - private int arraySizeMask; // fraction bits == 16 private int increment; @@ -187,72 +247,6 @@ public class VertexArrayRange { private int index; } - public static void usage(String className) { - System.out.println("usage: java " + className + " [-slow]"); - System.out.println("-slow flag starts up using data in the Java heap"); - System.exit(0); - } - - public static void main(String[] args) { - new VertexArrayRange().run(args); - } - - public void run(String[] args) { - boolean startSlow = false; - - if (args.length > 1) { - usage(getClass().getName()); - } - - if (args.length == 1) { - if (args[0].equals("-slow")) { - startSlow = true; - } else { - usage(getClass().getName()); - } - } - - if (!startSlow) { - setFlag('v', true); // VAR on - } - setFlag(' ', true); // animation on - setFlag('i', true); // infinite viewer and light - - canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - VARListener listener = new VARListener(); - canvas.addGLEventListener(listener); - - animator = new Animator(canvas); - - Frame frame = new Frame("Very Simple NV_vertex_array_range demo"); - frame.setLayout(new BorderLayout()); - canvas.setSize(800, 800); - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); - frame.show(); - canvas.requestFocus(); - - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - // Run this on another thread than the AWT event queue to - // make sure the call to Animator.stop() completes before - // exiting - new Thread(new Runnable() { - public void run() { - animator.stop(); - System.exit(0); - } - }).start(); - } - }); - - animator.start(); - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - private void setFlag(char key, boolean val) { b[((int) key) & 0xFF] = val; } @@ -261,403 +255,395 @@ public class VertexArrayRange { return b[((int) key) & 0xFF]; } - private void ensurePresent(String function) { - if (!canvas.getGL().isFunctionAvailable(function)) { + private void ensurePresent(GL gl, String function) { + if (!gl.isFunctionAvailable(function)) { final String message = "OpenGL routine \"" + function + "\" not available"; new Thread(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - runExit(); + demoListener.shutdownDemo(); } }).start(); throw new RuntimeException(message); } } - class VARListener implements GLEventListener { - boolean exiting = false; - - public void init(GLAutoDrawable drawable) { - // drawable.setGL(new TraceGL(drawable.getGL(), System.err)); - // drawable.setGL(new DebugGL(drawable.getGL())); + public void init(GLAutoDrawable drawable) { + // drawable.setGL(new TraceGL(drawable.getGL(), System.err)); + // drawable.setGL(new DebugGL(drawable.getGL())); - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - // Try and disable synch-to-retrace for fastest framerate - gl.setSwapInterval(0); + // Try and disable synch-to-retrace for fastest framerate + gl.setSwapInterval(0); - try { - ensurePresent("glVertexArrayRangeNV"); - ensurePresent("glGenFencesNV"); - ensurePresent("glSetFenceNV"); - ensurePresent("glTestFenceNV"); - ensurePresent("glFinishFenceNV"); - ensurePresent("glAllocateMemoryNV"); - } catch (RuntimeException e) { - quit = true; - throw (e); - } + try { + ensurePresent(gl, "glVertexArrayRangeNV"); + ensurePresent(gl, "glGenFencesNV"); + ensurePresent(gl, "glSetFenceNV"); + ensurePresent(gl, "glTestFenceNV"); + ensurePresent(gl, "glFinishFenceNV"); + ensurePresent(gl, "glAllocateMemoryNV"); + } catch (RuntimeException e) { + demoListener.shutdownDemo(); + throw (e); + } - gl.glEnable(GL.GL_DEPTH_TEST); - - gl.glClearColor(0, 0, 0, 0); - - gl.glEnable(GL.GL_LIGHT0); - gl.glEnable(GL.GL_LIGHTING); - gl.glEnable(GL.GL_NORMALIZE); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, new float[] {.1f, .1f, 0, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {.6f, .6f, .1f, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 1, 1, .75f, 1}, 0); - gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 128.f); - - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0}, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); - - // NOTE: it looks like GLUT (or something else) sets up the - // projection matrix in the C version of this demo. - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); - glu.gluPerspective(60, 1.0, 0.1, 100); - gl.glMatrixMode(GL.GL_MODELVIEW); - - allocateBigArray(gl, true); - allocateBuffersAndFences(gl); - - sinArray = new float[SIN_ARRAY_SIZE]; - cosArray = new float[SIN_ARRAY_SIZE]; - - for (int i = 0; i < SIN_ARRAY_SIZE; i++) { - double step = i * 2 * Math.PI / SIN_ARRAY_SIZE; - sinArray[i] = (float) Math.sin(step); - cosArray[i] = (float) Math.cos(step); - } + gl.glEnable(GL.GL_DEPTH_TEST); + + gl.glClearColor(0, 0, 0, 0); + + gl.glEnable(GL.GL_LIGHT0); + gl.glEnable(GL.GL_LIGHTING); + gl.glEnable(GL.GL_NORMALIZE); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, new float[] {.1f, .1f, 0, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {.6f, .6f, .1f, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 1, 1, .75f, 1}, 0); + gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 128.f); + + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0}, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + + // NOTE: it looks like GLUT (or something else) sets up the + // projection matrix in the C version of this demo. + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + glu.gluPerspective(60, 1.0, 0.1, 100); + gl.glMatrixMode(GL.GL_MODELVIEW); + + allocateBigArray(gl, true); + allocateBuffersAndFences(gl); + + sinArray = new float[SIN_ARRAY_SIZE]; + cosArray = new float[SIN_ARRAY_SIZE]; + + for (int i = 0; i < SIN_ARRAY_SIZE; i++) { + double step = i * 2 * Math.PI / SIN_ARRAY_SIZE; + sinArray[i] = (float) Math.sin(step); + cosArray[i] = (float) Math.cos(step); + } - if (getFlag('v')) { - gl.glEnableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); - gl.glVertexArrayRangeNV(bufferSize, bigArrayVar); - bigArray = bigArrayVar; - } else { - bigArray = bigArraySystem; - } - setupBuffers(); - gl.glEnableClientState(GL.GL_VERTEX_ARRAY); - gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + if (getFlag('v')) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); + gl.glVertexArrayRangeNV(bufferSize, bigArrayVar); + bigArray = bigArrayVar; + } else { + bigArray = bigArraySystem; + } + setupBuffers(); + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); - computeElements(); + computeElements(); - drawable.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { - dispatchKey(e.getKeyChar()); - } - }); - } + drawable.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + dispatchKey(e.getKeyChar()); + } + }); + } - private void allocateBuffersAndFences(GL gl) { - buffers = new VarBuffer[numBuffers]; - int[] fences = new int[1]; - for (int i = 0; i < numBuffers; i++) { - buffers[i] = new VarBuffer(); - gl.glGenFencesNV(1, fences, 0); - buffers[i].fence = fences[0]; - } + private void allocateBuffersAndFences(GL gl) { + buffers = new VarBuffer[numBuffers]; + int[] fences = new int[1]; + for (int i = 0; i < numBuffers; i++) { + buffers[i] = new VarBuffer(); + gl.glGenFencesNV(1, fences, 0); + buffers[i].fence = fences[0]; } + } - private void setupBuffers() { - int sliceSize = bufferLength / numBuffers; - for (int i = 0; i < numBuffers; i++) { - int startIndex = i * sliceSize; - buffers[i].vertices = sliceBuffer(bigArray, startIndex, sliceSize); - buffers[i].normals = sliceBuffer(buffers[i].vertices, 3, - buffers[i].vertices.limit() - 3); - } + private void setupBuffers() { + int sliceSize = bufferLength / numBuffers; + for (int i = 0; i < numBuffers; i++) { + int startIndex = i * sliceSize; + buffers[i].vertices = sliceBuffer(bigArray, startIndex, sliceSize); + buffers[i].normals = sliceBuffer(buffers[i].vertices, 3, + buffers[i].vertices.limit() - 3); } + } - private void dispatchKey(char k) { - setFlag(k, !getFlag(k)); - // Quit on escape or 'q' - if ((k == (char) 27) || (k == 'q')) { - runExit(); - } + private void dispatchKey(char k) { + setFlag(k, !getFlag(k)); + // Quit on escape or 'q' + if ((k == (char) 27) || (k == 'q')) { + demoListener.shutdownDemo(); + return; + } - if (k == 'r') { - if (getFlag(k)) { - profiledFrameCount = 0; - numDrawElementsCalls = 0; - firstProfiledFrame = true; - } + if (k == 'r') { + if (getFlag(k)) { + profiledFrameCount = 0; + numDrawElementsCalls = 0; + firstProfiledFrame = true; } + } - if (k == 'w') { - if (getFlag(k)) { - primitive = GL.GL_LINE_STRIP; - } else { - primitive = GL.GL_QUAD_STRIP; - } + if (k == 'w') { + if (getFlag(k)) { + primitive = GL.GL_LINE_STRIP; + } else { + primitive = GL.GL_QUAD_STRIP; } + } - if (k == 'p') { - if (getFlag(k)) { - primitive = GL.GL_POINTS; - } else { - primitive = GL.GL_QUAD_STRIP; - } + if (k == 'p') { + if (getFlag(k)) { + primitive = GL.GL_POINTS; + } else { + primitive = GL.GL_QUAD_STRIP; } + } - if (k == 'v') { - toggleVAR = true; - } + if (k == 'v') { + toggleVAR = true; + } - if (k == 'd') { - toggleLighting = true; - } + if (k == 'd') { + toggleLighting = true; + } - if (k == 'i') { - toggleLightingModel = true; - } + if (k == 'i') { + toggleLightingModel = true; + } - if('h'==k) - hicoef += .005; - if('H'==k) - hicoef -= .005; - if('l'==k) - locoef += .005; - if('L'==k) - locoef -= .005; - if('1'==k) - lofreq += .1f; - if('2'==k) - lofreq -= .1f; - if('3'==k) - hifreq += .1f; - if('4'==k) - hifreq -= .1f; - if('5'==k) - phaseRate += .01f; - if('6'==k) - phaseRate -= .01f; - if('7'==k) - phase2Rate += .01f; - if('8'==k) - phase2Rate -= .01f; - - if('t'==k) { - if(tileSize < 864) { - tileSize += STRIP_SIZE; - recomputeElements = true; - System.err.println("tileSize = " + tileSize); - } - } - - if('T'==k) { - if(tileSize > STRIP_SIZE) { - tileSize -= STRIP_SIZE; - recomputeElements = true; - System.err.println("tileSize = " + tileSize); - } + if('h'==k) + hicoef += .005; + if('H'==k) + hicoef -= .005; + if('l'==k) + locoef += .005; + if('L'==k) + locoef -= .005; + if('1'==k) + lofreq += .1f; + if('2'==k) + lofreq -= .1f; + if('3'==k) + hifreq += .1f; + if('4'==k) + hifreq -= .1f; + if('5'==k) + phaseRate += .01f; + if('6'==k) + phaseRate -= .01f; + if('7'==k) + phase2Rate += .01f; + if('8'==k) + phase2Rate -= .01f; + + if('t'==k) { + if(tileSize < 864) { + tileSize += STRIP_SIZE; + recomputeElements = true; + System.err.println("tileSize = " + tileSize); } } - public void display(GLAutoDrawable drawable) { - // Don't try to do OpenGL operations if we're tearing things down - if (quit) { - return; + if('T'==k) { + if(tileSize > STRIP_SIZE) { + tileSize -= STRIP_SIZE; + recomputeElements = true; + System.err.println("tileSize = " + tileSize); } + } + } - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - - // Check to see whether to animate - if (getFlag(' ')) { - phase += phaseRate; - phase2 += phase2Rate; + public void display(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - if (phase > (float) (20 * Math.PI)) { - phase = 0; - } + // Check to see whether to animate + if (getFlag(' ')) { + phase += phaseRate; + phase2 += phase2Rate; - if (phase2 < (float) (-20 * Math.PI)) { - phase2 = 0; - } + if (phase > (float) (20 * Math.PI)) { + phase = 0; } - PeriodicIterator loX = - new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase, (float) ((1.f/tileSize)*lofreq*Math.PI)); - PeriodicIterator loY = new PeriodicIterator(loX); - PeriodicIterator hiX = - new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase2, (float) ((1.f/tileSize)*hifreq*Math.PI)); - PeriodicIterator hiY = new PeriodicIterator(hiX); - - if (toggleVAR) { - if (getFlag('v')) { - gl.glEnableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); - gl.glVertexArrayRangeNV(bufferSize, bigArrayVar); - bigArray = bigArrayVar; - } else { - gl.glDisableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); - bigArray = bigArraySystem; - } - toggleVAR = false; - setupBuffers(); + if (phase2 < (float) (-20 * Math.PI)) { + phase2 = 0; } + } - if (toggleLighting) { - if (getFlag('d')) { - gl.glDisable(GL.GL_LIGHTING); - } else { - gl.glEnable(GL.GL_LIGHTING); - } - toggleLighting = false; + PeriodicIterator loX = + new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase, (float) ((1.f/tileSize)*lofreq*Math.PI)); + PeriodicIterator loY = new PeriodicIterator(loX); + PeriodicIterator hiX = + new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase2, (float) ((1.f/tileSize)*hifreq*Math.PI)); + PeriodicIterator hiY = new PeriodicIterator(hiX); + + if (toggleVAR) { + if (getFlag('v')) { + gl.glEnableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); + gl.glVertexArrayRangeNV(bufferSize, bigArrayVar); + bigArray = bigArrayVar; + } else { + gl.glDisableClientState(GL.GL_VERTEX_ARRAY_RANGE_NV); + bigArray = bigArraySystem; } + toggleVAR = false; + setupBuffers(); + } - if (toggleLightingModel) { - if(getFlag('i')) { - // infinite light - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0 }, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); - } else { - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, -.5f, 1 }, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 1); - } - toggleLightingModel = false; + if (toggleLighting) { + if (getFlag('d')) { + gl.glDisable(GL.GL_LIGHTING); + } else { + gl.glEnable(GL.GL_LIGHTING); } + toggleLighting = false; + } - if (recomputeElements) { - computeElements(); - recomputeElements = false; + if (toggleLightingModel) { + if(getFlag('i')) { + // infinite light + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0 }, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + } else { + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, -.5f, 1 }, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 1); } + toggleLightingModel = false; + } + + if (recomputeElements) { + computeElements(); + recomputeElements = false; + } - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glPushMatrix(); + gl.glPushMatrix(); - final float[] modelViewMatrix = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, -1, 1 - }; - gl.glLoadMatrixf(modelViewMatrix, 0); + final float[] modelViewMatrix = new float[] { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, -1, 1 + }; + gl.glLoadMatrixf(modelViewMatrix, 0); - // FIXME: add mouse interaction - // camera.apply_inverse_transform(); - // object.apply_transform(); + // FIXME: add mouse interaction + // camera.apply_inverse_transform(); + // object.apply_transform(); - int cur = 0; - int numSlabs = tileSize / STRIP_SIZE; + int cur = 0; + int numSlabs = tileSize / STRIP_SIZE; - for(int slab = numSlabs; --slab>=0; ) { - cur = slab % numBuffers; - if (slab >= numBuffers) { - if (!gl.glTestFenceNV(buffers[cur].fence)) { - gl.glFinishFenceNV(buffers[cur].fence); - } + for(int slab = numSlabs; --slab>=0; ) { + cur = slab % numBuffers; + if (slab >= numBuffers) { + if (!gl.glTestFenceNV(buffers[cur].fence)) { + gl.glFinishFenceNV(buffers[cur].fence); } + } - FloatBuffer v = buffers[cur].vertices; - int vertexIndex = 0; + FloatBuffer v = buffers[cur].vertices; + int vertexIndex = 0; - gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, v); - gl.glNormalPointer(GL.GL_FLOAT, 6 * SIZEOF_FLOAT, buffers[cur].normals); + gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, v); + gl.glNormalPointer(GL.GL_FLOAT, 6 * SIZEOF_FLOAT, buffers[cur].normals); - for(int jj=STRIP_SIZE; --jj>=0; ) { - ysinlo[jj] = sinArray[loY.getIndex()]; - ycoslo[jj] = cosArray[loY.getIndex()]; loY.incr(); - ysinhi[jj] = sinArray[hiY.getIndex()]; - ycoshi[jj] = cosArray[hiY.getIndex()]; hiY.incr(); - } - loY.decr(); - hiY.decr(); - - for(int i = tileSize; --i>=0; ) { - float x = xyArray[i]; - int loXIndex = loX.getIndex(); - int hiXIndex = hiX.getIndex(); - - int jOffset = (STRIP_SIZE-1)*slab; - float nx = locoef * -cosArray[loXIndex] + hicoef * -cosArray[hiXIndex]; - - // Help the HotSpot Client Compiler by hoisting loop - // invariant variables into locals. Note that this may be - // good practice for innermost loops anyway since under - // the new memory model operations like accidental - // synchronization may force any compiler to reload these - // fields from memory, destroying their ability to - // optimize. - float locoef_tmp = locoef; - float hicoef_tmp = hicoef; - float[] ysinlo_tmp = ysinlo; - float[] ysinhi_tmp = ysinhi; - float[] ycoslo_tmp = ycoslo; - float[] ycoshi_tmp = ycoshi; - float[] sinArray_tmp = sinArray; - float[] xyArray_tmp = xyArray; - - for(int j = STRIP_SIZE; --j>=0; ) { - float y; - - y = xyArray_tmp[j + jOffset]; - - float ny; - - v.put(vertexIndex, x); - v.put(vertexIndex + 1, y); - v.put(vertexIndex + 2, (locoef_tmp * (sinArray_tmp[loXIndex] + ysinlo_tmp[j]) + - hicoef_tmp * (sinArray_tmp[hiXIndex] + ysinhi_tmp[j]))); - v.put(vertexIndex + 3, nx); - ny = locoef_tmp * -ycoslo_tmp[j] + hicoef_tmp * -ycoshi_tmp[j]; - v.put(vertexIndex + 4, ny); - v.put(vertexIndex + 5, .15f); //.15f * (1.f - sqrt(nx * nx + ny * ny)); - vertexIndex += 6; - } - loX.incr(); - hiX.incr(); + for(int jj=STRIP_SIZE; --jj>=0; ) { + ysinlo[jj] = sinArray[loY.getIndex()]; + ycoslo[jj] = cosArray[loY.getIndex()]; loY.incr(); + ysinhi[jj] = sinArray[hiY.getIndex()]; + ycoshi[jj] = cosArray[hiY.getIndex()]; hiY.incr(); + } + loY.decr(); + hiY.decr(); + + for(int i = tileSize; --i>=0; ) { + float x = xyArray[i]; + int loXIndex = loX.getIndex(); + int hiXIndex = hiX.getIndex(); + + int jOffset = (STRIP_SIZE-1)*slab; + float nx = locoef * -cosArray[loXIndex] + hicoef * -cosArray[hiXIndex]; + + // Help the HotSpot Client Compiler by hoisting loop + // invariant variables into locals. Note that this may be + // good practice for innermost loops anyway since under + // the new memory model operations like accidental + // synchronization may force any compiler to reload these + // fields from memory, destroying their ability to + // optimize. + float locoef_tmp = locoef; + float hicoef_tmp = hicoef; + float[] ysinlo_tmp = ysinlo; + float[] ysinhi_tmp = ysinhi; + float[] ycoslo_tmp = ycoslo; + float[] ycoshi_tmp = ycoshi; + float[] sinArray_tmp = sinArray; + float[] xyArray_tmp = xyArray; + + for(int j = STRIP_SIZE; --j>=0; ) { + float y; + + y = xyArray_tmp[j + jOffset]; + + float ny; + + v.put(vertexIndex, x); + v.put(vertexIndex + 1, y); + v.put(vertexIndex + 2, (locoef_tmp * (sinArray_tmp[loXIndex] + ysinlo_tmp[j]) + + hicoef_tmp * (sinArray_tmp[hiXIndex] + ysinhi_tmp[j]))); + v.put(vertexIndex + 3, nx); + ny = locoef_tmp * -ycoslo_tmp[j] + hicoef_tmp * -ycoshi_tmp[j]; + v.put(vertexIndex + 4, ny); + v.put(vertexIndex + 5, .15f); //.15f * (1.f - sqrt(nx * nx + ny * ny)); + vertexIndex += 6; } - loX.reset(); - hiX.reset(); - - for (int i = 0; i < elements.length; i++) { - ++numDrawElementsCalls; - gl.glDrawElements(primitive, elements[i].length, GL.GL_UNSIGNED_INT, elements[i], 0); - if(getFlag('f')) { - gl.glFlush(); - } + loX.incr(); + hiX.incr(); + } + loX.reset(); + hiX.reset(); + + for (int i = 0; i < elements.length; i++) { + ++numDrawElementsCalls; + gl.glDrawElements(primitive, elements[i].length, GL.GL_UNSIGNED_INT, elements[i], 0); + if(getFlag('f')) { + gl.glFlush(); } - - gl.glSetFenceNV(buffers[cur].fence, GL.GL_ALL_COMPLETED_NV); } - gl.glPopMatrix(); - - gl.glFinishFenceNV(buffers[cur].fence); - - if (getFlag('r')) { - if (!firstProfiledFrame) { - if (++profiledFrameCount == 30) { - long endTimeMillis = System.currentTimeMillis(); - double secs = (endTimeMillis - startTimeMillis) / 1000.0; - double fps = 30.0 / secs; - double ppf = tileSize * tileSize * 2; - double mpps = ppf * fps / 1000000.0; - System.err.println("fps: " + fps + " polys/frame: " + ppf + " million polys/sec: " + mpps + - " DrawElements calls/frame: " + (numDrawElementsCalls / 30)); - profiledFrameCount = 0; - numDrawElementsCalls = 0; - startTimeMillis = System.currentTimeMillis(); - } - } else { - startTimeMillis = System.currentTimeMillis(); - firstProfiledFrame = false; + gl.glSetFenceNV(buffers[cur].fence, GL.GL_ALL_COMPLETED_NV); + } + gl.glPopMatrix(); + + gl.glFinishFenceNV(buffers[cur].fence); + + if (getFlag('r')) { + if (!firstProfiledFrame) { + if (++profiledFrameCount == 30) { + long endTimeMillis = System.currentTimeMillis(); + double secs = (endTimeMillis - startTimeMillis) / 1000.0; + double fps = 30.0 / secs; + double ppf = tileSize * tileSize * 2; + double mpps = ppf * fps / 1000000.0; + System.err.println("fps: " + fps + " polys/frame: " + ppf + " million polys/sec: " + mpps + + " DrawElements calls/frame: " + (numDrawElementsCalls / 30)); + profiledFrameCount = 0; + numDrawElementsCalls = 0; + startTimeMillis = System.currentTimeMillis(); } + } else { + startTimeMillis = System.currentTimeMillis(); + firstProfiledFrame = false; + } } + } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - // Unused routines - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - } // end class VARListener + // Unused routines + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} private void allocateBigArray(GL gl, boolean tryAgain) { float priority = .5f; @@ -721,14 +707,12 @@ public class VertexArrayRange { } } - private void runExit() { - quit = true; + private static void runExit(final Animator animator) { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking // routines cause a global AWT lock to be grabbed. Run the - // exit routine in another thread and cause this one to - // terminate by throwing an exception out of it. + // exit routine in another thread. new Thread(new Runnable() { public void run() { animator.stop(); diff --git a/src/demos/vertexBufferObject/VertexBufferObject.java b/src/demos/vertexBufferObject/VertexBufferObject.java index ef05b69..a217026 100644 --- a/src/demos/vertexBufferObject/VertexBufferObject.java +++ b/src/demos/vertexBufferObject/VertexBufferObject.java @@ -41,6 +41,7 @@ import javax.swing.*; import net.java.games.jogl.*; import net.java.games.jogl.util.*; +import demos.util.*; /** <P> A port of NVidia's [tm] Vertex Array Range demonstration to OpenGL[tm] for Java[tm], the Java programming language, and the @@ -65,7 +66,80 @@ import net.java.games.jogl.util.*; same data in system memory allows. </P> */ -public class VertexBufferObject { +public class VertexBufferObject implements GLEventListener { + public static void main(String[] args) { + boolean vboEnabled = true; + + if (args.length > 1) { + usage(); + } + + if (args.length == 1) { + if (args[0].equals("-slow")) { + vboEnabled = false; + } else { + usage(); + } + } + + GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + VertexBufferObject demo = new VertexBufferObject(); + demo.vboEnabled = vboEnabled; + canvas.addGLEventListener(demo); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + }); + + Frame frame = new Frame("Very Simple vertex_buffer_object demo"); + frame.setLayout(new BorderLayout()); + canvas.setSize(800, 800); + frame.add(canvas, BorderLayout.CENTER); + frame.pack(); + frame.show(); + canvas.requestFocus(); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + // Run this on another thread than the AWT event queue to + // make sure the call to Animator.stop() completes before + // exiting + new Thread(new Runnable() { + public void run() { + animator.stop(); + System.exit(0); + } + }).start(); + } + }); + + animator.start(); + } + + private static void usage() { + System.out.println("usage: java VertexBufferObject [-slow]"); + System.out.println("-slow flag starts up using data in the Java heap"); + System.exit(0); + } + + public VertexBufferObject() { + setFlag(' ', true); // animation on + setFlag('i', true); // infinite viewer and light + } + + public void setDemoListener(DemoListener listener) { + demoListener = listener; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private DemoListener demoListener; + private boolean initComplete; private boolean[] b = new boolean[256]; private static final int SIZEOF_FLOAT = 4; // private static final int STRIP_SIZE = 48; @@ -130,9 +204,6 @@ public class VertexBufferObject { private int numDrawElementsCalls; private long startTimeMillis; - private GLCanvas canvas = null; - private Animator animator; - static class PeriodicIterator { public PeriodicIterator(int arraySize, float period, @@ -187,67 +258,6 @@ public class VertexBufferObject { private int index; } - public static void usage(String className) { - System.out.println("usage: java " + className + " [-slow]"); - System.out.println("-slow flag starts up using data in the Java heap"); - System.exit(0); - } - - public static void main(String[] args) { - new VertexBufferObject().run(args); - } - - public void run(String[] args) { - if (args.length > 1) { - usage(getClass().getName()); - } - - if (args.length == 1) { - if (args[0].equals("-slow")) { - vboEnabled = false; - } else { - usage(getClass().getName()); - } - } - - setFlag(' ', true); // animation on - setFlag('i', true); // infinite viewer and light - - canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - VBOListener listener = new VBOListener(); - canvas.addGLEventListener(listener); - - animator = new Animator(canvas); - - Frame frame = new Frame("Very Simple NV_vertex_array_range demo"); - frame.setLayout(new BorderLayout()); - canvas.setSize(800, 800); - frame.add(canvas, BorderLayout.CENTER); - frame.pack(); - frame.show(); - canvas.requestFocus(); - - frame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - // Run this on another thread than the AWT event queue to - // make sure the call to Animator.stop() completes before - // exiting - new Thread(new Runnable() { - public void run() { - animator.stop(); - System.exit(0); - } - }).start(); - } - }); - - animator.start(); - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - private void setFlag(char key, boolean val) { b[((int) key) & 0xFF] = val; } @@ -262,420 +272,418 @@ public class VertexBufferObject { new Thread(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - runExit(); + demoListener.shutdownDemo(); } }).start(); throw new RuntimeException(message); } } - class VBOListener implements GLEventListener { - boolean exiting = false; - public void init(GLAutoDrawable drawable) { - // drawable.setGL(new TraceGL(drawable.getGL(), System.err)); - // drawable.setGL(new DebugGL(drawable.getGL())); + public void init(GLAutoDrawable drawable) { + initComplete = false; + // drawable.setGL(new TraceGL(drawable.getGL(), System.err)); + // drawable.setGL(new DebugGL(drawable.getGL())); - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - // Try and disable synch-to-retrace for fastest framerate - gl.setSwapInterval(0); + // Try and disable synch-to-retrace for fastest framerate + gl.setSwapInterval(0); - try { - initExtension(gl, "GL_ARB_vertex_buffer_object"); - } catch (RuntimeException e) { - quit = true; - throw (e); - } + try { + initExtension(gl, "GL_ARB_vertex_buffer_object"); + } catch (RuntimeException e) { + throw (e); + } - gl.glEnable(GL.GL_DEPTH_TEST); - - gl.glClearColor(0, 0, 0, 0); - - gl.glEnable(GL.GL_LIGHT0); - gl.glEnable(GL.GL_LIGHTING); - gl.glEnable(GL.GL_NORMALIZE); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, new float[] {.1f, .1f, 0, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {.6f, .6f, .1f, 1}, 0); - gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 1, 1, .75f, 1}, 0); - gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 128.f); - - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0}, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); - - // NOTE: it looks like GLUT (or something else) sets up the - // projection matrix in the C version of this demo. - gl.glMatrixMode(GL.GL_PROJECTION); - gl.glLoadIdentity(); - glu.gluPerspective(60, 1.0, 0.1, 100); - gl.glMatrixMode(GL.GL_MODELVIEW); - - allocateBigArray(gl); - allocateBuffers(gl); - - sinArray = new float[SIN_ARRAY_SIZE]; - cosArray = new float[SIN_ARRAY_SIZE]; - - for (int i = 0; i < SIN_ARRAY_SIZE; i++) { - double step = i * 2 * Math.PI / SIN_ARRAY_SIZE; - sinArray[i] = (float) Math.sin(step); - cosArray[i] = (float) Math.cos(step); - } + gl.glEnable(GL.GL_DEPTH_TEST); + + gl.glClearColor(0, 0, 0, 0); + + gl.glEnable(GL.GL_LIGHT0); + gl.glEnable(GL.GL_LIGHTING); + gl.glEnable(GL.GL_NORMALIZE); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, new float[] {.1f, .1f, 0, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE, new float[] {.6f, .6f, .1f, 1}, 0); + gl.glMaterialfv(GL.GL_FRONT_AND_BACK, GL.GL_SPECULAR, new float[] { 1, 1, .75f, 1}, 0); + gl.glMaterialf(GL.GL_FRONT_AND_BACK, GL.GL_SHININESS, 128.f); + + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0}, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + + // NOTE: it looks like GLUT (or something else) sets up the + // projection matrix in the C version of this demo. + gl.glMatrixMode(GL.GL_PROJECTION); + gl.glLoadIdentity(); + glu.gluPerspective(60, 1.0, 0.1, 100); + gl.glMatrixMode(GL.GL_MODELVIEW); + + allocateBigArray(gl); + allocateBuffers(gl); + + sinArray = new float[SIN_ARRAY_SIZE]; + cosArray = new float[SIN_ARRAY_SIZE]; + + for (int i = 0; i < SIN_ARRAY_SIZE; i++) { + double step = i * 2 * Math.PI / SIN_ARRAY_SIZE; + sinArray[i] = (float) Math.sin(step); + cosArray[i] = (float) Math.cos(step); + } - if (vboEnabled) { - bigArray = bigArrayVBO; - } else { - bigArray = bigArraySystem; - } - setupBuffers(); - gl.glEnableClientState(GL.GL_VERTEX_ARRAY); - gl.glEnableClientState(GL.GL_NORMAL_ARRAY); + if (vboEnabled) { + bigArray = bigArrayVBO; + } else { + bigArray = bigArraySystem; + } + setupBuffers(); + gl.glEnableClientState(GL.GL_VERTEX_ARRAY); + gl.glEnableClientState(GL.GL_NORMAL_ARRAY); - computeElements(gl); + computeElements(gl); - drawable.addKeyListener(new KeyAdapter() { - public void keyTyped(KeyEvent e) { - dispatchKey(e.getKeyChar()); - } - }); - } + drawable.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + dispatchKey(e.getKeyChar()); + } + }); + initComplete = true; + } - private void allocateBuffers(GL gl) { - buffers = new VBOBuffer[numBuffers]; - for (int i = 0; i < numBuffers; i++) { - buffers[i] = new VBOBuffer(); - } + private void allocateBuffers(GL gl) { + buffers = new VBOBuffer[numBuffers]; + for (int i = 0; i < numBuffers; i++) { + buffers[i] = new VBOBuffer(); } + } - private void setupBuffers() { - int sliceSize = bufferLength / numBuffers; - for (int i = 0; i < numBuffers; i++) { - int startIndex = i * sliceSize; - buffers[i].vertices = sliceBuffer(bigArray, startIndex, sliceSize); - buffers[i].normals = sliceBuffer(buffers[i].vertices, 3, - buffers[i].vertices.limit() - 3); - buffers[i].vertexOffset = startIndex * BufferUtils.SIZEOF_FLOAT; - buffers[i].normalOffset = (startIndex + 3) * BufferUtils.SIZEOF_FLOAT; - } + private void setupBuffers() { + int sliceSize = bufferLength / numBuffers; + for (int i = 0; i < numBuffers; i++) { + int startIndex = i * sliceSize; + buffers[i].vertices = sliceBuffer(bigArray, startIndex, sliceSize); + buffers[i].normals = sliceBuffer(buffers[i].vertices, 3, + buffers[i].vertices.limit() - 3); + buffers[i].vertexOffset = startIndex * BufferUtils.SIZEOF_FLOAT; + buffers[i].normalOffset = (startIndex + 3) * BufferUtils.SIZEOF_FLOAT; } + } - private void dispatchKey(char k) { - setFlag(k, !getFlag(k)); - // Quit on escape or 'q' - if ((k == (char) 27) || (k == 'q')) { - runExit(); - } + private void dispatchKey(char k) { + setFlag(k, !getFlag(k)); + // Quit on escape or 'q' + if ((k == (char) 27) || (k == 'q')) { + demoListener.shutdownDemo(); + return; + } - if (k == 'r') { - if (getFlag(k)) { - profiledFrameCount = 0; - numDrawElementsCalls = 0; - firstProfiledFrame = true; - } + if (k == 'r') { + if (getFlag(k)) { + profiledFrameCount = 0; + numDrawElementsCalls = 0; + firstProfiledFrame = true; } + } - if (k == 'w') { - if (getFlag(k)) { - primitive = GL.GL_LINE_STRIP; - } else { - primitive = GL.GL_QUAD_STRIP; - } + if (k == 'w') { + if (getFlag(k)) { + primitive = GL.GL_LINE_STRIP; + } else { + primitive = GL.GL_QUAD_STRIP; } + } - if (k == 'p') { - if (getFlag(k)) { - primitive = GL.GL_POINTS; - } else { - primitive = GL.GL_QUAD_STRIP; - } + if (k == 'p') { + if (getFlag(k)) { + primitive = GL.GL_POINTS; + } else { + primitive = GL.GL_QUAD_STRIP; } + } - if (k == 'v') { - toggleVBO = true; - } + if (k == 'v') { + toggleVBO = true; + } - if (k == 'd') { - toggleLighting = true; - } + if (k == 'd') { + toggleLighting = true; + } - if (k == 'i') { - toggleLightingModel = true; - } + if (k == 'i') { + toggleLightingModel = true; + } - if('h'==k) - hicoef += .005; - if('H'==k) - hicoef -= .005; - if('l'==k) - locoef += .005; - if('L'==k) - locoef -= .005; - if('1'==k) - lofreq += .1f; - if('2'==k) - lofreq -= .1f; - if('3'==k) - hifreq += .1f; - if('4'==k) - hifreq -= .1f; - if('5'==k) - phaseRate += .01f; - if('6'==k) - phaseRate -= .01f; - if('7'==k) - phase2Rate += .01f; - if('8'==k) - phase2Rate -= .01f; - - if('t'==k) { - if(tileSize < 864) { - tileSize += STRIP_SIZE; - recomputeElements = true; - System.err.println("tileSize = " + tileSize); - } + if('h'==k) + hicoef += .005; + if('H'==k) + hicoef -= .005; + if('l'==k) + locoef += .005; + if('L'==k) + locoef -= .005; + if('1'==k) + lofreq += .1f; + if('2'==k) + lofreq -= .1f; + if('3'==k) + hifreq += .1f; + if('4'==k) + hifreq -= .1f; + if('5'==k) + phaseRate += .01f; + if('6'==k) + phaseRate -= .01f; + if('7'==k) + phase2Rate += .01f; + if('8'==k) + phase2Rate -= .01f; + + if('t'==k) { + if(tileSize < 864) { + tileSize += STRIP_SIZE; + recomputeElements = true; + System.err.println("tileSize = " + tileSize); } + } - if('T'==k) { - if(tileSize > STRIP_SIZE) { - tileSize -= STRIP_SIZE; - recomputeElements = true; - System.err.println("tileSize = " + tileSize); - } + if('T'==k) { + if(tileSize > STRIP_SIZE) { + tileSize -= STRIP_SIZE; + recomputeElements = true; + System.err.println("tileSize = " + tileSize); } } + } - public void display(GLAutoDrawable drawable) { - // Don't try to do OpenGL operations if we're tearing things down - if (quit) { - return; - } + public void display(GLAutoDrawable drawable) { + if (!initComplete) { + return; + } - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - // Check to see whether to animate - if (getFlag(' ')) { - phase += phaseRate; - phase2 += phase2Rate; + // Check to see whether to animate + if (getFlag(' ')) { + phase += phaseRate; + phase2 += phase2Rate; - if (phase > (float) (20 * Math.PI)) { - phase = 0; - } - - if (phase2 < (float) (-20 * Math.PI)) { - phase2 = 0; - } + if (phase > (float) (20 * Math.PI)) { + phase = 0; } - PeriodicIterator loX = - new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase, (float) ((1.f/tileSize)*lofreq*Math.PI)); - PeriodicIterator loY = new PeriodicIterator(loX); - PeriodicIterator hiX = - new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase2, (float) ((1.f/tileSize)*hifreq*Math.PI)); - PeriodicIterator hiY = new PeriodicIterator(hiX); - - if (toggleVBO) { - vboEnabled = !vboEnabled; - if (!vboEnabled) { - bigArray = bigArraySystem; - setupBuffers(); - } - toggleVBO = false; + if (phase2 < (float) (-20 * Math.PI)) { + phase2 = 0; } + } - if (toggleLighting) { - if (getFlag('d')) { - gl.glDisable(GL.GL_LIGHTING); - } else { - gl.glEnable(GL.GL_LIGHTING); - } - toggleLighting = false; - } + PeriodicIterator loX = + new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase, (float) ((1.f/tileSize)*lofreq*Math.PI)); + PeriodicIterator loY = new PeriodicIterator(loX); + PeriodicIterator hiX = + new PeriodicIterator(SIN_ARRAY_SIZE, (float) (2 * Math.PI), phase2, (float) ((1.f/tileSize)*hifreq*Math.PI)); + PeriodicIterator hiY = new PeriodicIterator(hiX); - if (toggleLightingModel) { - if(getFlag('i')) { - // infinite light - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0 }, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); - } else { - gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, -.5f,1 }, 0); - gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 1); - } - toggleLightingModel = false; + if (toggleVBO) { + vboEnabled = !vboEnabled; + if (!vboEnabled) { + bigArray = bigArraySystem; + setupBuffers(); } + toggleVBO = false; + } - if (recomputeElements) { - computeElements(gl); - recomputeElements = false; + if (toggleLighting) { + if (getFlag('d')) { + gl.glDisable(GL.GL_LIGHTING); + } else { + gl.glEnable(GL.GL_LIGHTING); } + toggleLighting = false; + } - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + if (toggleLightingModel) { + if(getFlag('i')) { + // infinite light + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, .5f, 0 }, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + } else { + gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[] { .5f, 0, -.5f,1 }, 0); + gl.glLightModeli(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + } + toggleLightingModel = false; + } - gl.glPushMatrix(); + if (recomputeElements) { + computeElements(gl); + recomputeElements = false; + } - final float[] modelViewMatrix = new float[] { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, -1, 1 - }; - gl.glLoadMatrixf(modelViewMatrix, 0); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - // FIXME: add mouse interaction - // camera.apply_inverse_transform(); - // object.apply_transform(); + gl.glPushMatrix(); - int cur = 0; - int numSlabs = tileSize / STRIP_SIZE; + final float[] modelViewMatrix = new float[] { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, -1, 1 + }; + gl.glLoadMatrixf(modelViewMatrix, 0); - if (vboEnabled) { - gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, bigBufferObject); - } else { - gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0); - } + // FIXME: add mouse interaction + // camera.apply_inverse_transform(); + // object.apply_transform(); - for(int slab = numSlabs; --slab>=0; ) { - cur = slab % numBuffers; + int cur = 0; + int numSlabs = tileSize / STRIP_SIZE; - if (vboEnabled) { - ByteBuffer tmp = gl.glMapBufferARB(GL.GL_ARRAY_BUFFER_ARB, GL.GL_WRITE_ONLY_ARB); - if (tmp == null) { - throw new RuntimeException("Unable to map vertex buffer object"); - } - if (tmp != bigArrayVBOBytes) { - bigArrayVBOBytes = tmp; - bigArrayVBO = setupBuffer(tmp); - } - if (bigArray != bigArrayVBO) { - bigArray = bigArrayVBO; - setupBuffers(); - } - } + if (vboEnabled) { + gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, bigBufferObject); + } else { + gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, 0); + } - FloatBuffer v = buffers[cur].vertices; - int vertexIndex = 0; + for(int slab = numSlabs; --slab>=0; ) { + cur = slab % numBuffers; - if (vboEnabled) { - gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, BufferUtils.bufferOffset(buffers[cur].vertexOffset)); - gl.glNormalPointer( GL.GL_FLOAT, 6 * SIZEOF_FLOAT, BufferUtils.bufferOffset(buffers[cur].normalOffset)); - } else { - gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, v); - gl.glNormalPointer( GL.GL_FLOAT, 6 * SIZEOF_FLOAT, buffers[cur].normals); + if (vboEnabled) { + ByteBuffer tmp = gl.glMapBufferARB(GL.GL_ARRAY_BUFFER_ARB, GL.GL_WRITE_ONLY_ARB); + if (tmp == null) { + throw new RuntimeException("Unable to map vertex buffer object"); } - - for(int jj=STRIP_SIZE; --jj>=0; ) { - ysinlo[jj] = sinArray[loY.getIndex()]; - ycoslo[jj] = cosArray[loY.getIndex()]; loY.incr(); - ysinhi[jj] = sinArray[hiY.getIndex()]; - ycoshi[jj] = cosArray[hiY.getIndex()]; hiY.incr(); + if (tmp != bigArrayVBOBytes) { + bigArrayVBOBytes = tmp; + bigArrayVBO = setupBuffer(tmp); } - loY.decr(); - hiY.decr(); - - for(int i = tileSize; --i>=0; ) { - float x = xyArray[i]; - int loXIndex = loX.getIndex(); - int hiXIndex = hiX.getIndex(); - - int jOffset = (STRIP_SIZE-1)*slab; - float nx = locoef * -cosArray[loXIndex] + hicoef * -cosArray[hiXIndex]; - - // Help the HotSpot Client Compiler by hoisting loop - // invariant variables into locals. Note that this may be - // good practice for innermost loops anyway since under - // the new memory model operations like accidental - // synchronization may force any compiler to reload these - // fields from memory, destroying their ability to - // optimize. - float locoef_tmp = locoef; - float hicoef_tmp = hicoef; - float[] ysinlo_tmp = ysinlo; - float[] ysinhi_tmp = ysinhi; - float[] ycoslo_tmp = ycoslo; - float[] ycoshi_tmp = ycoshi; - float[] sinArray_tmp = sinArray; - float[] xyArray_tmp = xyArray; - - for(int j = STRIP_SIZE; --j>=0; ) { - float y; - - y = xyArray_tmp[j + jOffset]; - - float ny; - - v.put(vertexIndex, x); - v.put(vertexIndex + 1, y); - v.put(vertexIndex + 2, (locoef_tmp * (sinArray_tmp[loXIndex] + ysinlo_tmp[j]) + - hicoef_tmp * (sinArray_tmp[hiXIndex] + ysinhi_tmp[j]))); - v.put(vertexIndex + 3, nx); - ny = locoef_tmp * -ycoslo_tmp[j] + hicoef_tmp * -ycoshi_tmp[j]; - v.put(vertexIndex + 4, ny); - v.put(vertexIndex + 5, .15f); //.15f * (1.f - sqrt(nx * nx + ny * ny)); - vertexIndex += 6; - } - loX.incr(); - hiX.incr(); + if (bigArray != bigArrayVBO) { + bigArray = bigArrayVBO; + setupBuffers(); } - loX.reset(); - hiX.reset(); + } - if (vboEnabled) { - gl.glUnmapBufferARB(GL.GL_ARRAY_BUFFER_ARB); + FloatBuffer v = buffers[cur].vertices; + int vertexIndex = 0; + + if (vboEnabled) { + gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, BufferUtils.bufferOffset(buffers[cur].vertexOffset)); + gl.glNormalPointer( GL.GL_FLOAT, 6 * SIZEOF_FLOAT, BufferUtils.bufferOffset(buffers[cur].normalOffset)); + } else { + gl.glVertexPointer(3, GL.GL_FLOAT, 6 * SIZEOF_FLOAT, v); + gl.glNormalPointer( GL.GL_FLOAT, 6 * SIZEOF_FLOAT, buffers[cur].normals); + } + + for(int jj=STRIP_SIZE; --jj>=0; ) { + ysinlo[jj] = sinArray[loY.getIndex()]; + ycoslo[jj] = cosArray[loY.getIndex()]; loY.incr(); + ysinhi[jj] = sinArray[hiY.getIndex()]; + ycoshi[jj] = cosArray[hiY.getIndex()]; hiY.incr(); + } + loY.decr(); + hiY.decr(); + + for(int i = tileSize; --i>=0; ) { + float x = xyArray[i]; + int loXIndex = loX.getIndex(); + int hiXIndex = hiX.getIndex(); + + int jOffset = (STRIP_SIZE-1)*slab; + float nx = locoef * -cosArray[loXIndex] + hicoef * -cosArray[hiXIndex]; + + // Help the HotSpot Client Compiler by hoisting loop + // invariant variables into locals. Note that this may be + // good practice for innermost loops anyway since under + // the new memory model operations like accidental + // synchronization may force any compiler to reload these + // fields from memory, destroying their ability to + // optimize. + float locoef_tmp = locoef; + float hicoef_tmp = hicoef; + float[] ysinlo_tmp = ysinlo; + float[] ysinhi_tmp = ysinhi; + float[] ycoslo_tmp = ycoslo; + float[] ycoshi_tmp = ycoshi; + float[] sinArray_tmp = sinArray; + float[] xyArray_tmp = xyArray; + + for(int j = STRIP_SIZE; --j>=0; ) { + float y; + + y = xyArray_tmp[j + jOffset]; + + float ny; + + v.put(vertexIndex, x); + v.put(vertexIndex + 1, y); + v.put(vertexIndex + 2, (locoef_tmp * (sinArray_tmp[loXIndex] + ysinlo_tmp[j]) + + hicoef_tmp * (sinArray_tmp[hiXIndex] + ysinhi_tmp[j]))); + v.put(vertexIndex + 3, nx); + ny = locoef_tmp * -ycoslo_tmp[j] + hicoef_tmp * -ycoshi_tmp[j]; + v.put(vertexIndex + 4, ny); + v.put(vertexIndex + 5, .15f); //.15f * (1.f - sqrt(nx * nx + ny * ny)); + vertexIndex += 6; } + loX.incr(); + hiX.incr(); + } + loX.reset(); + hiX.reset(); + + if (vboEnabled) { + gl.glUnmapBufferARB(GL.GL_ARRAY_BUFFER_ARB); + } - if (getFlag('m')) { - // Elements merged into buffer object (doesn't seem to improve performance) - - int len = tileSize - 1; - gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, elementBufferObject); - for (int i = 0; i < len; i++) { - ++numDrawElementsCalls; - gl.glDrawElements(primitive, 2 * STRIP_SIZE, GL.GL_UNSIGNED_INT, - BufferUtils.bufferOffset(i * 2 * STRIP_SIZE * BufferUtils.SIZEOF_INT)); - if(getFlag('f')) { - gl.glFlush(); - } + if (getFlag('m')) { + // Elements merged into buffer object (doesn't seem to improve performance) + + int len = tileSize - 1; + gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, elementBufferObject); + for (int i = 0; i < len; i++) { + ++numDrawElementsCalls; + gl.glDrawElements(primitive, 2 * STRIP_SIZE, GL.GL_UNSIGNED_INT, + BufferUtils.bufferOffset(i * 2 * STRIP_SIZE * BufferUtils.SIZEOF_INT)); + if(getFlag('f')) { + gl.glFlush(); } - gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - } else { - for (int i = 0; i < elements.length; i++) { - ++numDrawElementsCalls; - gl.glDrawElements(primitive, elements[i].length, GL.GL_UNSIGNED_INT, elements[i], 0); - if(getFlag('f')) { - gl.glFlush(); - } + } + gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } else { + for (int i = 0; i < elements.length; i++) { + ++numDrawElementsCalls; + gl.glDrawElements(primitive, elements[i].length, GL.GL_UNSIGNED_INT, elements[i], 0); + if(getFlag('f')) { + gl.glFlush(); } } } + } - gl.glPopMatrix(); - - if (getFlag('r')) { - if (!firstProfiledFrame) { - if (++profiledFrameCount == 30) { - long endTimeMillis = System.currentTimeMillis(); - double secs = (endTimeMillis - startTimeMillis) / 1000.0; - double fps = 30.0 / secs; - double ppf = tileSize * tileSize * 2; - double mpps = ppf * fps / 1000000.0; - System.err.println("fps: " + fps + " polys/frame: " + ppf + " million polys/sec: " + mpps + - " DrawElements calls/frame: " + (numDrawElementsCalls / 30)); - profiledFrameCount = 0; - numDrawElementsCalls = 0; - startTimeMillis = System.currentTimeMillis(); - } - } else { + gl.glPopMatrix(); + + if (getFlag('r')) { + if (!firstProfiledFrame) { + if (++profiledFrameCount == 30) { + long endTimeMillis = System.currentTimeMillis(); + double secs = (endTimeMillis - startTimeMillis) / 1000.0; + double fps = 30.0 / secs; + double ppf = tileSize * tileSize * 2; + double mpps = ppf * fps / 1000000.0; + System.err.println("fps: " + fps + " polys/frame: " + ppf + " million polys/sec: " + mpps + + " DrawElements calls/frame: " + (numDrawElementsCalls / 30)); + profiledFrameCount = 0; + numDrawElementsCalls = 0; startTimeMillis = System.currentTimeMillis(); - firstProfiledFrame = false; } + } else { + startTimeMillis = System.currentTimeMillis(); + firstProfiledFrame = false; } } + } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - // Unused routines - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - } // end class VBOListener + // Unused routines + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} private void allocateBigArray(GL gl) { bigArraySystem = setupBuffer(ByteBuffer.allocateDirect(bufferSize)); @@ -745,14 +753,12 @@ public class VertexBufferObject { gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } - private void runExit() { - quit = true; + private static void runExit(final Animator animator) { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking // routines cause a global AWT lock to be grabbed. Run the - // exit routine in another thread and cause this one to - // terminate by throwing an exception out of it. + // exit routine in another thread. new Thread(new Runnable() { public void run() { animator.stop(); diff --git a/src/demos/vertexProgRefract/VertexProgRefract.java b/src/demos/vertexProgRefract/VertexProgRefract.java index 4811952..e3444cd 100644 --- a/src/demos/vertexProgRefract/VertexProgRefract.java +++ b/src/demos/vertexProgRefract/VertexProgRefract.java @@ -72,6 +72,7 @@ public class VertexProgRefract implements GLEventListener { public void shutdownDemo() { runExit(animator); } + public void repaint() {} }); Frame frame = new Frame("Refraction Using Vertex Programs"); @@ -92,7 +93,7 @@ public class VertexProgRefract implements GLEventListener { } public void setDemoListener(DemoListener listener) { - this.demoListener = listener; + demoListener = listener; } private DemoListener demoListener; diff --git a/src/demos/vertexProgWarp/VertexProgWarp.java b/src/demos/vertexProgWarp/VertexProgWarp.java index 4fbb345..3c5096b 100644 --- a/src/demos/vertexProgWarp/VertexProgWarp.java +++ b/src/demos/vertexProgWarp/VertexProgWarp.java @@ -54,8 +54,7 @@ import gleem.linalg.*; Ported to Java by Kenneth Russell */ -public class VertexProgWarp { - private GLCanvas canvas; +public class VertexProgWarp implements GLEventListener { private Frame frame; private Animator animator; private volatile boolean quit; @@ -69,12 +68,23 @@ public class VertexProgWarp { } public void run(String[] args) { - canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); - canvas.addGLEventListener(new Listener()); - - animator = new Animator(canvas); + GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities()); + VertexProgWarp demo = new VertexProgWarp(); + canvas.addGLEventListener(demo); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + }); - frame = new Frame(); + final Frame frame = new Frame(); + demo.setTitleSetter(new VertexProgWarp.TitleSetter() { + public void setTitle(String title) { + frame.setTitle(title); + } + }); frame.setLayout(new BorderLayout()); canvas.setSize(512, 512); frame.add(canvas, BorderLayout.CENTER); @@ -84,514 +94,528 @@ public class VertexProgWarp { frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { - // Run this on another thread than the AWT event queue to - // make sure the call to Animator.stop() completes before - // exiting - new Thread(new Runnable() { - public void run() { - animator.stop(); - System.exit(0); - } - }).start(); + runExit(animator); } }); animator.start(); } - class Listener implements GLEventListener { - // period of 4-term Taylor approximation to sin isn't quite 2*M_PI - private static final float SIN_PERIOD = 3.079f; - private static final int NUM_OBJS = 5; - private static final int NUM_PROGS = 7; - private int[] programs = new int[NUM_PROGS]; - private float zNear = 0.1f; - private float zFar = 10.0f; - private int program = 2; - private int obj = 2; - private boolean[] b = new boolean[256]; - private boolean wire = false; - private boolean toggleWire = false; - private boolean animating = true; - private boolean doViewAll = true; - - private Time time = new SystemTime(); - private float anim = 0.0f; - private float animScale = 7.0f; - private float amp = 0.05f; - private float freq = 8.0f; - private float d = 4.0f; - - private ExaminerViewer viewer; - - public void init(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - - float cc = 0.0f; - gl.glClearColor(cc, cc, cc, 1); - - gl.glColor3f(1,1,1); - gl.glEnable(GL.GL_DEPTH_TEST); - gl.glDisable(GL.GL_CULL_FACE); + public static abstract class TitleSetter { + public abstract void setTitle(String title); + } - try { - initExtension(gl, "GL_ARB_vertex_program"); - } catch (RuntimeException e) { - quit = true; - throw(e); - } + public void setTitleSetter(TitleSetter setter) { + titleSetter = setter; + } - for(int i=0; i<NUM_OBJS; i++) { - gl.glNewList(i+1, GL.GL_COMPILE); - drawObject(gl, glu, i); - gl.glEndList(); - } - - for(int i=0; i<NUM_PROGS; i++) { - int[] vtxProgTmp = new int[1]; - gl.glGenProgramsARB(1, vtxProgTmp, 0); - programs[i] = vtxProgTmp[0]; - gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, programs[i]); - gl.glProgramStringARB(GL.GL_VERTEX_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, programTexts[i].length(), programTexts[i]); - } + public void setDemoListener(DemoListener listener) { + demoListener = listener; + } + + private DemoListener demoListener; + private TitleSetter titleSetter; + private boolean initComplete; + + // period of 4-term Taylor approximation to sin isn't quite 2*M_PI + private static final float SIN_PERIOD = 3.079f; + private static final int NUM_OBJS = 5; + private static final int NUM_PROGS = 7; + private int[] programs = new int[NUM_PROGS]; + private float zNear = 0.1f; + private float zFar = 10.0f; + private int program = 2; + private int obj = 2; + private boolean[] b = new boolean[256]; + private boolean wire = false; + private boolean toggleWire = false; + private boolean animating = true; + private boolean doViewAll = true; + + private Time time = new SystemTime(); + private float anim = 0.0f; + private float animScale = 7.0f; + private float amp = 0.05f; + private float freq = 8.0f; + private float d = 4.0f; + + private ExaminerViewer viewer; + + public void init(GLAutoDrawable drawable) { + initComplete = false; + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); + + float cc = 0.0f; + gl.glClearColor(cc, cc, cc, 1); + + gl.glColor3f(1,1,1); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glDisable(GL.GL_CULL_FACE); + + try { + initExtension(gl, "GL_ARB_vertex_program"); + } catch (RuntimeException e) { + demoListener.shutdownDemo(); + throw(e); + } + + for(int i=0; i<NUM_OBJS; i++) { + gl.glNewList(i+1, GL.GL_COMPILE); + drawObject(gl, glu, i); + gl.glEndList(); + } + + for(int i=0; i<NUM_PROGS; i++) { + int[] vtxProgTmp = new int[1]; + gl.glGenProgramsARB(1, vtxProgTmp, 0); + programs[i] = vtxProgTmp[0]; + gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, programs[i]); + gl.glProgramStringARB(GL.GL_VERTEX_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, programTexts[i].length(), programTexts[i]); + } - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 0, 0.0f, 0.0f, 1.0f, 0.0f); // light position/direction - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 1, 0.0f, 1.0f, 0.0f, 0.0f); // diffuse color - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 2, 1.0f, 1.0f, 1.0f, 0.0f); // specular color + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 0, 0.0f, 0.0f, 1.0f, 0.0f); // light position/direction + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 1, 0.0f, 1.0f, 0.0f, 0.0f); // diffuse color + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 2, 1.0f, 1.0f, 1.0f, 0.0f); // specular color - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 3, 0.0f, 1.0f, 2.0f, 3.0f); // smoothstep constants + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 3, 0.0f, 1.0f, 2.0f, 3.0f); // smoothstep constants - // sin Taylor series constants - 1, 1/3!, 1/5!, 1/7! - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 4, 1.0f, 1.0f / (3*2), 1.0f / (5*4*3*2), 1.0f / (7*6*5*4*3*2)); + // sin Taylor series constants - 1, 1/3!, 1/5!, 1/7! + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 4, 1.0f, 1.0f / (3*2), 1.0f / (5*4*3*2), 1.0f / (7*6*5*4*3*2)); - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 5, 1.0f / (2.0f * SIN_PERIOD), 2.0f * SIN_PERIOD, SIN_PERIOD, SIN_PERIOD/2.0f); + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 5, 1.0f / (2.0f * SIN_PERIOD), 2.0f * SIN_PERIOD, SIN_PERIOD, SIN_PERIOD/2.0f); - // sin wave frequency, amplitude - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, 1.0f, 0.2f, 0.0f, 0.0f); + // sin wave frequency, amplitude + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, 1.0f, 0.2f, 0.0f, 0.0f); - // phase animation - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 7, 0.0f, 0.0f, 0.0f, 0.0f); + // phase animation + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 7, 0.0f, 0.0f, 0.0f, 0.0f); - // fisheye sphere radius - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 8, 1.0f, 0.0f, 0.0f, 0.0f); + // fisheye sphere radius + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 8, 1.0f, 0.0f, 0.0f, 0.0f); - setWindowTitle(); + setWindowTitle(); - b['p'] = true; + doViewAll = true; + + b['p'] = true; - drawable.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - dispatchKey(e.getKeyCode(), e.getKeyChar()); - } - }); - - // Register the window with the ManipManager - ManipManager manager = ManipManager.getManipManager(); - manager.registerWindow(drawable); - - viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); - viewer.setNoAltKeyMode(true); - viewer.setAutoRedrawMode(false); - viewer.attach(drawable, new BSphereProvider() { - public BSphere getBoundingSphere() { - return new BSphere(new Vec3f(0, 0, 0), 1.0f); - } - }); - viewer.setVertFOV((float) Math.toRadians(60)); - viewer.setZNear(zNear); - viewer.setZFar(zFar); - } + drawable.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + dispatchKey(e.getKeyCode(), e.getKeyChar()); + } + }); + + // Register the window with the ManipManager + ManipManager manager = ManipManager.getManipManager(); + manager.registerWindow(drawable); - public void display(GLAutoDrawable drawable) { - if (!firstRender) { - if (++frameCount == 30) { - timer.stop(); - System.err.println("Frames per second: " + (30.0f / timer.getDurationAsSeconds())); - timer.reset(); - timer.start(); - frameCount = 0; + viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); + viewer.setNoAltKeyMode(true); + viewer.setAutoRedrawMode(false); + viewer.attach(drawable, new BSphereProvider() { + public BSphere getBoundingSphere() { + return new BSphere(new Vec3f(0, 0, 0), 1.0f); } - } else { - firstRender = false; + }); + viewer.setVertFOV((float) Math.toRadians(60)); + viewer.setZNear(zNear); + viewer.setZFar(zFar); + initComplete = true; + } + + public void display(GLAutoDrawable drawable) { + if (!initComplete) { + return; + } + + if (!firstRender) { + if (++frameCount == 30) { + timer.stop(); + System.err.println("Frames per second: " + (30.0f / timer.getDurationAsSeconds())); + timer.reset(); timer.start(); + frameCount = 0; } + } else { + firstRender = false; + timer.start(); + } - time.update(); - - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); + time.update(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + GL gl = drawable.getGL(); + GLU glu = drawable.getGLU(); - if (toggleWire) { - wire = !wire; - if (wire) - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); - else - gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); - toggleWire = false; - } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glPushMatrix(); + if (toggleWire) { + wire = !wire; + if (wire) + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); + else + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); + toggleWire = false; + } - if (doViewAll) { - viewer.viewAll(gl); - doViewAll = false; - } + gl.glPushMatrix(); - if (animating) { - anim -= (float) (animScale * time.deltaT()); - } + if (doViewAll) { + viewer.viewAll(gl); + doViewAll = false; + } - viewer.update(gl); - ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); - ManipManager.getManipManager().render(drawable, gl); + if (animating) { + anim -= (float) (animScale * time.deltaT()); + } - gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, programs[program]); - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 7, anim, 0.0f, 0.0f, 0.0f); + viewer.update(gl); + ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); + ManipManager.getManipManager().render(drawable, gl); - if (program==6) - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, (float) Math.sin(anim)*amp*50.0f, 0.0f, 0.0f, 0.0f); - else - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, freq, amp, d, d+1); + gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, programs[program]); + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 7, anim, 0.0f, 0.0f, 0.0f); - if (b['p']) - gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); + if (program==6) + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, (float) Math.sin(anim)*amp*50.0f, 0.0f, 0.0f, 0.0f); + else + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 6, freq, amp, d, d+1); - gl.glDisable(GL.GL_TEXTURE_2D); - gl.glCallList(obj+1); + if (b['p']) + gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); - gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glCallList(obj+1); - gl.glPopMatrix(); - } + gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); - // Unused routines - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + gl.glPopMatrix(); + } - //---------------------------------------------------------------------- - // Internals only below this point - // - private void initExtension(GL gl, String glExtensionName) { - if (!gl.isExtensionAvailable(glExtensionName)) { - final String message = "OpenGL extension \"" + glExtensionName + "\" not available"; - new Thread(new Runnable() { - public void run() { - JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - runExit(); - } - }).start(); - throw new RuntimeException(message); - } + // Unused routines + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {} + + //---------------------------------------------------------------------- + // Internals only below this point + // + private void initExtension(GL gl, String glExtensionName) { + if (!gl.isExtensionAvailable(glExtensionName)) { + final String message = "OpenGL extension \"" + glExtensionName + "\" not available"; + new Thread(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); + demoListener.shutdownDemo(); + } + }).start(); + throw new RuntimeException(message); } + } - private void dispatchKey(int keyCode, char k) { - if (k < 256) - b[k] = !b[k]; - - switch (keyCode) { - case KeyEvent.VK_HOME: - case KeyEvent.VK_R: - anim = 0.0f; - amp = 0.05f; - freq = 8.0f; - d = 4.0f; - doViewAll = true; - break; - - case KeyEvent.VK_LEFT: - case KeyEvent.VK_KP_LEFT: - program--; - if (program < 0) - program = NUM_PROGS-1; - setWindowTitle(); - break; - - case KeyEvent.VK_RIGHT: - case KeyEvent.VK_KP_RIGHT: - program = (program + 1) % NUM_PROGS; - setWindowTitle(); - break; - - case KeyEvent.VK_F1: - case KeyEvent.VK_H: - String endl = System.getProperty("line.separator"); - endl = endl + endl; - String msg = ("F1/h - Help" + endl + - "Home - Reset" + endl + - "Left Button & Mouse - Rotate viewpoint" + endl + - "1..5 - Switch object (Sphere, Torus, Triceratop, Cube, Cylinder)" + endl + - "- / + - Change amplitude" + endl + - "[ / ] - Change frequency" + endl + - ", / . - Change square fisheye size" + endl + - "Left - Next vertex program" + endl + - "Right - Previous vertex program" + endl + - "W - Toggle wireframe" + endl + - "Space - Toggle animation" + endl + - "Esc/q - Exit program" + endl); - JOptionPane.showMessageDialog(null, msg, "Help", JOptionPane.INFORMATION_MESSAGE); - break; - - case KeyEvent.VK_ESCAPE: - case KeyEvent.VK_Q: - runExit(); - return; - - case KeyEvent.VK_W: - toggleWire = true; - break; - - case KeyEvent.VK_EQUALS: - case KeyEvent.VK_PLUS: - amp += 0.01; - break; - - case KeyEvent.VK_MINUS: - amp -= 0.01; - break; - - case KeyEvent.VK_CLOSE_BRACKET: - freq += 0.5; - break; - - case KeyEvent.VK_OPEN_BRACKET: - freq -= 0.5; - break; - - case KeyEvent.VK_PERIOD: - d += 0.1; - break; - - case KeyEvent.VK_COMMA: - d -= 0.1; - break; - - case KeyEvent.VK_SPACE: - // Could also start/stop Animator here - animating = !animating; - break; - - case KeyEvent.VK_1: - obj = 0; - break; - - case KeyEvent.VK_2: - obj = 1; - break; - - case KeyEvent.VK_3: - obj = 2; - break; - - case KeyEvent.VK_4: - obj = 3; - break; - - case KeyEvent.VK_5: - obj = 4; - break; - } - } + private void dispatchKey(int keyCode, char k) { + if (k < 256) + b[k] = !b[k]; + + switch (keyCode) { + case KeyEvent.VK_HOME: + case KeyEvent.VK_R: + anim = 0.0f; + amp = 0.05f; + freq = 8.0f; + d = 4.0f; + doViewAll = true; + break; + + case KeyEvent.VK_LEFT: + case KeyEvent.VK_KP_LEFT: + program--; + if (program < 0) + program = NUM_PROGS-1; + setWindowTitle(); + break; - private void setWindowTitle() { - frame.setTitle("SpaceWarp - " + programNames[program]); + case KeyEvent.VK_RIGHT: + case KeyEvent.VK_KP_RIGHT: + program = (program + 1) % NUM_PROGS; + setWindowTitle(); + break; + + case KeyEvent.VK_F1: + case KeyEvent.VK_H: + String endl = System.getProperty("line.separator"); + endl = endl + endl; + String msg = ("F1/h - Help" + endl + + "Home - Reset" + endl + + "Left Button & Mouse - Rotate viewpoint" + endl + + "1..5 - Switch object (Sphere, Torus, Triceratop, Cube, Cylinder)" + endl + + "- / + - Change amplitude" + endl + + "[ / ] - Change frequency" + endl + + ", / . - Change square fisheye size" + endl + + "Left - Next vertex program" + endl + + "Right - Previous vertex program" + endl + + "W - Toggle wireframe" + endl + + "Space - Toggle animation" + endl + + "Esc/q - Exit program" + endl); + JOptionPane.showMessageDialog(null, msg, "Help", JOptionPane.INFORMATION_MESSAGE); + break; + + case KeyEvent.VK_ESCAPE: + case KeyEvent.VK_Q: + demoListener.shutdownDemo(); + return; + + case KeyEvent.VK_W: + toggleWire = true; + break; + + case KeyEvent.VK_EQUALS: + case KeyEvent.VK_PLUS: + amp += 0.01; + break; + + case KeyEvent.VK_MINUS: + amp -= 0.01; + break; + + case KeyEvent.VK_CLOSE_BRACKET: + freq += 0.5; + break; + + case KeyEvent.VK_OPEN_BRACKET: + freq -= 0.5; + break; + + case KeyEvent.VK_PERIOD: + d += 0.1; + break; + + case KeyEvent.VK_COMMA: + d -= 0.1; + break; + + case KeyEvent.VK_SPACE: + // Could also start/stop Animator here + animating = !animating; + break; + + case KeyEvent.VK_1: + obj = 0; + break; + + case KeyEvent.VK_2: + obj = 1; + break; + + case KeyEvent.VK_3: + obj = 2; + break; + + case KeyEvent.VK_4: + obj = 3; + break; + + case KeyEvent.VK_5: + obj = 4; + break; } + } - private void drawObject(GL gl, GLU glu, int which) { - switch(which) { - case 0: - drawSphere(gl, 0.5f, 100, 100); - break; - - case 1: - drawTorus(gl, 0.25f, 0.5f, 100, 100); - break; - - case 2: - try { - Triceratops.drawObject(gl); - } catch (IOException e) { - runExit(); - throw new RuntimeException(e); - } - break; + private void setWindowTitle() { + titleSetter.setTitle("SpaceWarp - " + programNames[program]); + } - case 3: - drawCube(gl); - break; + private void drawObject(GL gl, GLU glu, int which) { + switch(which) { + case 0: + drawSphere(gl, 0.5f, 100, 100); + break; - case 4: - drawCylinder(gl, glu); - break; + case 1: + drawTorus(gl, 0.25f, 0.5f, 100, 100); + break; + + case 2: + try { + Triceratops.drawObject(gl); + } catch (IOException e) { + demoListener.shutdownDemo(); + throw new RuntimeException(e); } + break; + + case 3: + drawCube(gl); + break; + + case 4: + drawCylinder(gl, glu); + break; } + } - private void drawSphere(GL gl, float radius, int slices, int stacks) { - int J = stacks; - int I = slices; - for(int j = 0; j < J; j++) { - float v = j/(float) J; - float phi = (float) (v * 2 * Math.PI); - float v2 = (j+1)/(float) J; - float phi2 = (float) (v2 * 2 * Math.PI); - - gl.glBegin(GL.GL_QUAD_STRIP); - for(int i = 0; i < I; i++) { - float u = i/(I-1.0f); - float theta = (float) (u * Math.PI); - float x,y,z,nx,ny,nz; - - nx = (float) (Math.cos(theta)*Math.cos(phi)); - ny = (float) (Math.sin(theta)*Math.cos(phi)); - nz = (float) (Math.sin(phi)); - x = radius * nx; - y = radius * ny; - z = radius * nz; - - gl.glColor3f ( u, v, 0.0f); - gl.glNormal3f(nx, ny, nz); - gl.glVertex3f( x, y, z); - - nx = (float) (Math.cos(theta)*Math.cos(phi2)); - ny = (float) (Math.sin(theta)*Math.cos(phi2)); - nz = (float) (Math.sin(phi2)); - x = radius * nx; - y = radius * ny; - z = radius * nz; - - gl.glColor3f ( u, v+(1.0f/(J-1.0f)), 0.0f); - gl.glNormal3f(nx, ny, nz); - gl.glVertex3f( x, y, z); - } - gl.glEnd(); + private void drawSphere(GL gl, float radius, int slices, int stacks) { + int J = stacks; + int I = slices; + for(int j = 0; j < J; j++) { + float v = j/(float) J; + float phi = (float) (v * 2 * Math.PI); + float v2 = (j+1)/(float) J; + float phi2 = (float) (v2 * 2 * Math.PI); + + gl.glBegin(GL.GL_QUAD_STRIP); + for(int i = 0; i < I; i++) { + float u = i/(I-1.0f); + float theta = (float) (u * Math.PI); + float x,y,z,nx,ny,nz; + + nx = (float) (Math.cos(theta)*Math.cos(phi)); + ny = (float) (Math.sin(theta)*Math.cos(phi)); + nz = (float) (Math.sin(phi)); + x = radius * nx; + y = radius * ny; + z = radius * nz; + + gl.glColor3f ( u, v, 0.0f); + gl.glNormal3f(nx, ny, nz); + gl.glVertex3f( x, y, z); + + nx = (float) (Math.cos(theta)*Math.cos(phi2)); + ny = (float) (Math.sin(theta)*Math.cos(phi2)); + nz = (float) (Math.sin(phi2)); + x = radius * nx; + y = radius * ny; + z = radius * nz; + + gl.glColor3f ( u, v+(1.0f/(J-1.0f)), 0.0f); + gl.glNormal3f(nx, ny, nz); + gl.glVertex3f( x, y, z); } + gl.glEnd(); } + } - private void drawTorus(GL gl, float meridian_radius, float core_radius, - int meridian_slices, int core_slices) { - int J = meridian_slices; - int I = core_slices; - for(int j = 0; j < J-1; j++) { - float v = j/(J-1.0f); - float rho = (float) (v * 2.0f * Math.PI); - float v2 = (j+1)/(J-1.0f); - float rho2 = (float) (v2 * 2.0f * Math.PI); - gl.glBegin(GL.GL_QUAD_STRIP); - for(int i = 0; i < I; i++) { - float u = i/(I-1.0f); - float theta = (float) (u * 2.0f * Math.PI); - float x,y,z,nx,ny,nz; - - x = (float) (core_radius*Math.cos(theta) + meridian_radius*Math.cos(theta)*Math.cos(rho)); - y = (float) (core_radius*Math.sin(theta) + meridian_radius*Math.sin(theta)*Math.cos(rho)); - z = (float) (meridian_radius*Math.sin(rho)); - nx = (float) (Math.cos(theta)*Math.cos(rho)); - ny = (float) (Math.sin(theta)*Math.cos(rho)); - nz = (float) (Math.sin(rho)); - - gl.glColor3f ( u, v, 0.0f); - gl.glNormal3f(nx, ny, nz); - gl.glVertex3f( x, y, z); - - x = (float) (core_radius*Math.cos(theta) + meridian_radius*Math.cos(theta)*Math.cos(rho2)); - y = (float) (core_radius*Math.sin(theta) + meridian_radius*Math.sin(theta)*Math.cos(rho2)); - z = (float) (meridian_radius*Math.sin(rho2)); - nx = (float) (Math.cos(theta)*Math.cos(rho2)); - ny = (float) (Math.sin(theta)*Math.cos(rho2)); - nz = (float) (Math.sin(rho2)); - - gl.glColor3f ( u, v, 0.0f); - gl.glNormal3f(nx, ny, nz); - gl.glVertex3f( x, y, z); - } - gl.glEnd(); + private void drawTorus(GL gl, float meridian_radius, float core_radius, + int meridian_slices, int core_slices) { + int J = meridian_slices; + int I = core_slices; + for(int j = 0; j < J-1; j++) { + float v = j/(J-1.0f); + float rho = (float) (v * 2.0f * Math.PI); + float v2 = (j+1)/(J-1.0f); + float rho2 = (float) (v2 * 2.0f * Math.PI); + gl.glBegin(GL.GL_QUAD_STRIP); + for(int i = 0; i < I; i++) { + float u = i/(I-1.0f); + float theta = (float) (u * 2.0f * Math.PI); + float x,y,z,nx,ny,nz; + + x = (float) (core_radius*Math.cos(theta) + meridian_radius*Math.cos(theta)*Math.cos(rho)); + y = (float) (core_radius*Math.sin(theta) + meridian_radius*Math.sin(theta)*Math.cos(rho)); + z = (float) (meridian_radius*Math.sin(rho)); + nx = (float) (Math.cos(theta)*Math.cos(rho)); + ny = (float) (Math.sin(theta)*Math.cos(rho)); + nz = (float) (Math.sin(rho)); + + gl.glColor3f ( u, v, 0.0f); + gl.glNormal3f(nx, ny, nz); + gl.glVertex3f( x, y, z); + + x = (float) (core_radius*Math.cos(theta) + meridian_radius*Math.cos(theta)*Math.cos(rho2)); + y = (float) (core_radius*Math.sin(theta) + meridian_radius*Math.sin(theta)*Math.cos(rho2)); + z = (float) (meridian_radius*Math.sin(rho2)); + nx = (float) (Math.cos(theta)*Math.cos(rho2)); + ny = (float) (Math.sin(theta)*Math.cos(rho2)); + nz = (float) (Math.sin(rho2)); + + gl.glColor3f ( u, v, 0.0f); + gl.glNormal3f(nx, ny, nz); + gl.glVertex3f( x, y, z); } + gl.glEnd(); } + } - private void drawCube(GL gl) { - int cr = 40; - float scaleFactor = 0.5f; - - // back - gl.glColor3f(1.0f, 0.0f, 0.0f); - gl.glNormal3f(0.0f, 0.0f, -1.0f); - drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f); - - // front - gl.glColor3f(1.0f, 0.0f, 0.0f); - gl.glNormal3f(0.0f, 0.0f, 1.0f); - drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, 1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f); - - // left - gl.glColor3f(0.0f, 1.0f, 0.0f); - gl.glNormal3f(-1.0f, 0.0f, 0.0f); - drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f); - - // right - gl.glColor3f(0.0f, 0.0f, 1.0f); - gl.glNormal3f(1.0f, 0.0f, 0.0f); - drawGrid(gl, cr, cr, scaleFactor, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f); - - // bottom - gl.glColor3f(1.0f, 1.0f, 0.0f); - gl.glNormal3f(0.0f,-1.0f, 0.0f); - drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f); - - // top - gl.glColor3f(0.0f, 1.0f, 1.0f); - gl.glNormal3f(0.0f, 1.0f, 0.0f); - drawGrid(gl, cr, cr, scaleFactor, -1.0f, 1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f); - } + private void drawCube(GL gl) { + int cr = 40; + float scaleFactor = 0.5f; + + // back + gl.glColor3f(1.0f, 0.0f, 0.0f); + gl.glNormal3f(0.0f, 0.0f, -1.0f); + drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f); + + // front + gl.glColor3f(1.0f, 0.0f, 0.0f); + gl.glNormal3f(0.0f, 0.0f, 1.0f); + drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, 1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f); + + // left + gl.glColor3f(0.0f, 1.0f, 0.0f); + gl.glNormal3f(-1.0f, 0.0f, 0.0f); + drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f); + + // right + gl.glColor3f(0.0f, 0.0f, 1.0f); + gl.glNormal3f(1.0f, 0.0f, 0.0f); + drawGrid(gl, cr, cr, scaleFactor, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f); + + // bottom + gl.glColor3f(1.0f, 1.0f, 0.0f); + gl.glNormal3f(0.0f,-1.0f, 0.0f); + drawGrid(gl, cr, cr, scaleFactor, -1.0f, -1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f); + + // top + gl.glColor3f(0.0f, 1.0f, 1.0f); + gl.glNormal3f(0.0f, 1.0f, 0.0f); + drawGrid(gl, cr, cr, scaleFactor, -1.0f, 1.0f, -1.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f); + } - private void drawGrid(GL gl, int rows, int cols, - float scaleFactor, - float sx, float sy, float sz, - float ux, float uy, float uz, - float vx, float vy, float vz) { - int x, y; - - for(y=0; y<rows; y++) { - gl.glBegin(GL.GL_QUAD_STRIP); - for(x=0; x<=cols; x++) { - float u = x / (float) cols; - float v = y / (float) rows; - float v2 = v + (1.0f / (float) rows); - - gl.glTexCoord2f(u, v); - gl.glVertex3f(scaleFactor * (sx + (u*ux) + (v*vx)), - scaleFactor * (sy + (u*uy) + (v*vy)), - scaleFactor * (sz + (u*uz) + (v*vz))); - - gl.glTexCoord2f(u, v2); - gl.glVertex3f(scaleFactor * (sx + (u*ux) + (v2*vx)), - scaleFactor * (sy + (u*uy) + (v2*vy)), - scaleFactor * (sz + (u*uz) + (v2*vz))); - } - gl.glEnd(); + private void drawGrid(GL gl, int rows, int cols, + float scaleFactor, + float sx, float sy, float sz, + float ux, float uy, float uz, + float vx, float vy, float vz) { + int x, y; + + for(y=0; y<rows; y++) { + gl.glBegin(GL.GL_QUAD_STRIP); + for(x=0; x<=cols; x++) { + float u = x / (float) cols; + float v = y / (float) rows; + float v2 = v + (1.0f / (float) rows); + + gl.glTexCoord2f(u, v); + gl.glVertex3f(scaleFactor * (sx + (u*ux) + (v*vx)), + scaleFactor * (sy + (u*uy) + (v*vy)), + scaleFactor * (sz + (u*uz) + (v*vz))); + + gl.glTexCoord2f(u, v2); + gl.glVertex3f(scaleFactor * (sx + (u*ux) + (v2*vx)), + scaleFactor * (sy + (u*uy) + (v2*vy)), + scaleFactor * (sz + (u*uz) + (v2*vz))); } + gl.glEnd(); } + } - private void drawCylinder(GL gl, GLU glu) { - GLUquadric quad; + private void drawCylinder(GL gl, GLU glu) { + GLUquadric quad; - quad = glu.gluNewQuadric(); - glu.gluQuadricDrawStyle (quad, GLU.GLU_FILL); - glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE); - glu.gluQuadricNormals (quad, GLU.GLU_SMOOTH); - glu.gluQuadricTexture (quad, true); + quad = glu.gluNewQuadric(); + glu.gluQuadricDrawStyle (quad, GLU.GLU_FILL); + glu.gluQuadricOrientation(quad, GLU.GLU_OUTSIDE); + glu.gluQuadricNormals (quad, GLU.GLU_SMOOTH); + glu.gluQuadricTexture (quad, true); - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPushMatrix(); - gl.glTranslatef(-1.0f, 0.0f, 0.0f); - gl.glRotatef (90.0f, 0.0f, 1.0f, 0.0f); + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPushMatrix(); + gl.glTranslatef(-1.0f, 0.0f, 0.0f); + gl.glRotatef (90.0f, 0.0f, 1.0f, 0.0f); - glu.gluCylinder(quad, 0.25f, 0.25f, 2.0f, 60, 30); - gl.glPopMatrix(); + glu.gluCylinder(quad, 0.25f, 0.25f, 2.0f, 60, 30); + gl.glPopMatrix(); - glu.gluDeleteQuadric(quad); - } + glu.gluDeleteQuadric(quad); } private static final String[] programNames = new String[] { @@ -1010,8 +1034,7 @@ public class VertexProgWarp { "END\n" }; - private void runExit() { - quit = true; + private static void runExit(final Animator animator) { // Note: calling System.exit() synchronously inside the draw, // reshape or init callbacks can lead to deadlocks on certain // platforms (in particular, X11) because the JAWT's locking diff --git a/src/gleem/ExaminerViewer.java b/src/gleem/ExaminerViewer.java index f621ae7..4c854e0 100644 --- a/src/gleem/ExaminerViewer.java +++ b/src/gleem/ExaminerViewer.java @@ -78,7 +78,7 @@ public class ExaminerViewer { private boolean iOwnInteraction; private boolean noAltKeyMode; - private boolean autoRedrawMode; + private boolean autoRedrawMode = true; /** Simple state machine for computing distance dragged */ private boolean button1Down; |