diff options
author | Kenneth Russel <[email protected]> | 2005-10-24 19:21:28 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2005-10-24 19:21:28 +0000 |
commit | 6873f65775af236ed270fcbd08661f5b53ba3598 (patch) | |
tree | 6fcefdc3a9429d7d3071b1464c11d40fa7bc3ab9 /src/demos/vertexProgRefract/VertexProgRefract.java | |
parent | 538be101e7bce7788c82e1b254a66deb5d35bb56 (diff) |
Merged JSR-231 branch on to the main JOGL trunk. The main trunk now
contains the evolving JSR-231 Reference Implementation and the JSR-231
branch is permanently closed.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@144 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
Diffstat (limited to 'src/demos/vertexProgRefract/VertexProgRefract.java')
-rw-r--r-- | src/demos/vertexProgRefract/VertexProgRefract.java | 897 |
1 files changed, 455 insertions, 442 deletions
diff --git a/src/demos/vertexProgRefract/VertexProgRefract.java b/src/demos/vertexProgRefract/VertexProgRefract.java index e9c6905..63b4a59 100644 --- a/src/demos/vertexProgRefract/VertexProgRefract.java +++ b/src/demos/vertexProgRefract/VertexProgRefract.java @@ -43,8 +43,11 @@ import javax.imageio.*; import javax.imageio.stream.*; import javax.swing.*; -import net.java.games.jogl.*; -import net.java.games.jogl.util.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.sun.opengl.utils.*; +import com.sun.opengl.utils.*; +import demos.common.*; import demos.util.*; import gleem.*; import gleem.linalg.*; @@ -61,21 +64,19 @@ import gleem.linalg.*; Ported to Java and ARB_fragment_program by Kenneth Russell */ -public class VertexProgRefract { - private boolean useRegisterCombiners; - private GLCanvas canvas; - private Animator animator; - private volatile boolean quit; - +public class VertexProgRefract extends Demo { public static void main(String[] args) { - new VertexProgRefract().run(args); - } - - 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()); + VertexProgRefract demo = new VertexProgRefract(); + canvas.addGLEventListener(demo); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + public void repaint() {} + }); Frame frame = new Frame("Refraction Using Vertex Programs"); frame.setLayout(new BorderLayout()); @@ -87,44 +88,40 @@ public class VertexProgRefract { 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 { - private int vtxProg; - private int fragProg; - private int cubemap; - private int bunnydl; - private int obj; + private boolean useRegisterCombiners; + private boolean initComplete; + private boolean firstRender = true; + private int vtxProg; + private int fragProg; + private int cubemap; + private int bunnydl; + private int obj; - private GLUT glut = new GLUT(); + private GLU glu = new GLU(); + private GLUT glut = new GLUT(); - private ExaminerViewer viewer; - private boolean doViewAll = true; + private GLAutoDrawable drawable; + private ExaminerViewer viewer; + private boolean doViewAll = true; - private Time time = new SystemTime(); - private float animRate = (float) Math.toRadians(-6.0f); // Radians / sec + private Time time = new SystemTime(); + private float animRate = (float) Math.toRadians(-6.0f); // Radians / sec - private float refract = 1.1f; // ratio of indicies of refraction - private float wavelengthDelta = 0.05f; // difference in refraction for each "wavelength" (R,G,B) - private float fresnel = 2.0f; // Fresnel multiplier + private float refract = 1.1f; // ratio of indicies of refraction + private float wavelengthDelta = 0.05f; // difference in refraction for each "wavelength" (R,G,B) + private float fresnel = 2.0f; // Fresnel multiplier - private boolean wire = false; - private boolean toggleWire = false; + private boolean wire = false; + private boolean toggleWire = false; - private static final String transformRefract = + private static final String transformRefract = "!!ARBvp1.0\n" + "# Refraction\n" + "\n" + @@ -226,82 +223,89 @@ public class VertexProgRefract { "\n" + "END\n"; - public void init(GLDrawable drawable) { - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - float cc = 1.0f; - gl.glClearColor(cc, cc, cc, 1); - gl.glColor3f(1,1,1); - gl.glEnable(GL.GL_DEPTH_TEST); - - try { - initExtension(gl, "GL_ARB_vertex_program"); - initExtension(gl, "GL_ARB_multitexture"); - if (!gl.isExtensionAvailable("GL_ARB_fragment_program")) { - if (gl.isExtensionAvailable("GL_NV_register_combiners")) { - useRegisterCombiners = true; - } else { - final String message = "This demo requires either the GL_ARB_fragment_program\n" + - "or GL_NV_register_combiners extension"; - new Thread(new Runnable() { - public void run() { - JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); - runExit(); - } - }).start(); - throw new RuntimeException(message); - } + public void init(GLAutoDrawable drawable) { + initComplete = false; + GL gl = drawable.getGL(); + float cc = 1.0f; + gl.glClearColor(cc, cc, cc, 1); + gl.glColor3f(1,1,1); + gl.glEnable(GL.GL_DEPTH_TEST); + + try { + initExtension(gl, "GL_ARB_vertex_program"); + initExtension(gl, "GL_VERSION_1_3"); // For multitexturing support + if (!gl.isExtensionAvailable("GL_ARB_fragment_program")) { + if (gl.isExtensionAvailable("GL_NV_register_combiners")) { + useRegisterCombiners = true; + } else { + final String message = "This demo requires either the GL_ARB_fragment_program\n" + + "or GL_NV_register_combiners extension"; + new Thread(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(null, message, "Unavailable extension", JOptionPane.ERROR_MESSAGE); + shutdownDemo(); + } + }).start(); + throw new RuntimeException(message); } - } catch (RuntimeException e) { - quit = true; - throw(e); } + } catch (RuntimeException e) { + shutdownDemo(); + throw(e); + } - b[' '] = true; // animate by default + b[' '] = true; // animate by default - int[] vtxProgTmp = new int[1]; - gl.glGenProgramsARB(1, vtxProgTmp); - vtxProg = vtxProgTmp[0]; - gl.glBindProgramARB (GL.GL_VERTEX_PROGRAM_ARB, vtxProg); - gl.glProgramStringARB(GL.GL_VERTEX_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, transformRefract.length(), transformRefract); + int[] vtxProgTmp = new int[1]; + gl.glGenProgramsARB(1, vtxProgTmp, 0); + vtxProg = vtxProgTmp[0]; + gl.glBindProgramARB (GL.GL_VERTEX_PROGRAM_ARB, vtxProg); + gl.glProgramStringARB(GL.GL_VERTEX_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, transformRefract.length(), transformRefract); - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 0, 0.0f, 0.0f, 0.0f, 1.0f); // eye position + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 0, 0.0f, 0.0f, 0.0f, 1.0f); // eye position - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 1, fresnel, fresnel, fresnel, 1.0f); // fresnel multiplier + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 1, fresnel, fresnel, fresnel, 1.0f); // fresnel multiplier - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 2, 1.0f, -1.0f, 1.0f, 0.0f); // texture scale - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 3, 0.0f, 1.0f, 2.0f, 3.0f); // misc constants + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 2, 1.0f, -1.0f, 1.0f, 0.0f); // texture scale + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 3, 0.0f, 1.0f, 2.0f, 3.0f); // misc constants - int[] cubemapTmp = new int[1]; - gl.glGenTextures(1, cubemapTmp); - cubemap = cubemapTmp[0]; - gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP_ARB, cubemap); + int[] cubemapTmp = new int[1]; + gl.glGenTextures(1, cubemapTmp, 0); + cubemap = cubemapTmp[0]; + gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP, cubemap); - gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP_ARB, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); - gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP_ARB, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_CUBE_MAP, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR); - try { - loadPNGCubemap(gl, glu, "demos/data/cubemaps/uffizi", true); - } catch (IOException e) { - runExit(); - throw new RuntimeException(e); - } + try { + loadPNGCubemap(gl, "demos/data/cubemaps/uffizi", true); + } catch (IOException e) { + shutdownDemo(); + throw new RuntimeException(e); + } - gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); - gl.glDisable(GL.GL_CULL_FACE); + gl.glDisable(GL.GL_CULL_FACE); - if (useRegisterCombiners) { - initCombiners(gl); - } else { - initFragmentProgram(gl); - } + if (useRegisterCombiners) { + initCombiners(gl); + } else { + initFragmentProgram(gl); + } - try { - bunnydl = Bunny.gen3DObjectList(gl); - } catch (IOException e) { - throw new RuntimeException(e); - } + try { + bunnydl = Bunny.gen3DObjectList(gl); + } catch (IOException e) { + throw new RuntimeException(e); + } + + doViewAll = true; + + // Do this only once per drawable, not once each time the OpenGL + // context is created + if (firstRender) { + firstRender = false; drawable.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent e) { @@ -312,282 +316,293 @@ public class VertexProgRefract { // Register the window with the ManipManager ManipManager manager = ManipManager.getManipManager(); manager.registerWindow(drawable); + this.drawable = 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); - } - }); + public BSphere getBoundingSphere() { + return new BSphere(new Vec3f(0, 0, 0), 1.0f); + } + }); viewer.setVertFOV((float) (15.0f * Math.PI / 32.0f)); viewer.setZNear(0.1f); viewer.setZFar(10.0f); } - public void display(GLDrawable drawable) { - if (quit) { - return; - } + initComplete = true; + } - time.update(); + public void display(GLAutoDrawable drawable) { + if (!initComplete) { + return; + } - GL gl = drawable.getGL(); - GLU glu = drawable.getGLU(); - gl.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT); + time.update(); - if (doViewAll) { - viewer.viewAll(gl); - doViewAll = false; - } + GL gl = drawable.getGL(); + gl.glClear(GL.GL_COLOR_BUFFER_BIT|GL.GL_DEPTH_BUFFER_BIT); - if (getFlag(' ')) { - viewer.rotateAboutFocalPoint(new Rotf(Vec3f.Y_AXIS, (float) (time.deltaT() * animRate))); - } + if (doViewAll) { + viewer.viewAll(gl); + doViewAll = false; + } - if (toggleWire) { - toggleWire = false; - 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); - } - } + if (getFlag(' ')) { + viewer.rotateAboutFocalPoint(new Rotf(Vec3f.Y_AXIS, (float) (time.deltaT() * animRate))); + } - // draw background - gl.glDisable(GL.GL_DEPTH_TEST); - drawSkyBox(gl, glu); - gl.glEnable(GL.GL_DEPTH_TEST); - - gl.glPushMatrix(); - - viewer.update(gl); - ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); - ManipManager.getManipManager().render(drawable, gl); - - gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, vtxProg); - - gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 62, fresnel, fresnel, fresnel, 1.0f); - - // set texture transforms - gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); - gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP_ARB, cubemap); - gl.glEnable(GL.GL_TEXTURE_CUBE_MAP_ARB); - gl.glMatrixMode(GL.GL_TEXTURE); - gl.glLoadIdentity(); - gl.glScalef(1.0f, -1.0f, 1.0f); - viewer.updateInverseRotation(gl); - - gl.glActiveTextureARB(GL.GL_TEXTURE1_ARB); - gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP_ARB, cubemap); - gl.glEnable(GL.GL_TEXTURE_CUBE_MAP_ARB); - gl.glMatrixMode(GL.GL_TEXTURE); - gl.glLoadIdentity(); - gl.glScalef(1.0f, -1.0f, 1.0f); - viewer.updateInverseRotation(gl); - - if (useRegisterCombiners) { - gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); + if (toggleWire) { + toggleWire = false; + wire = !wire; + if (wire) { + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); } else { - gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); } + } - gl.glColor3f(1.0f, 1.0f, 1.0f); + // draw background + gl.glDisable(GL.GL_DEPTH_TEST); + drawSkyBox(gl); + gl.glEnable(GL.GL_DEPTH_TEST); + + gl.glPushMatrix(); + + viewer.update(gl); + ManipManager.getManipManager().updateCameraParameters(drawable, viewer.getCameraParameters()); + ManipManager.getManipManager().render(drawable, gl); + + gl.glBindProgramARB(GL.GL_VERTEX_PROGRAM_ARB, vtxProg); + + gl.glEnable(GL.GL_VERTEX_PROGRAM_ARB); + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 62, fresnel, fresnel, fresnel, 1.0f); + + // set texture transforms + gl.glActiveTexture(GL.GL_TEXTURE0); + gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP, cubemap); + gl.glEnable(GL.GL_TEXTURE_CUBE_MAP); + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glLoadIdentity(); + gl.glScalef(1.0f, -1.0f, 1.0f); + viewer.updateInverseRotation(gl); + + gl.glActiveTexture(GL.GL_TEXTURE1); + gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP, cubemap); + gl.glEnable(GL.GL_TEXTURE_CUBE_MAP); + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glLoadIdentity(); + gl.glScalef(1.0f, -1.0f, 1.0f); + viewer.updateInverseRotation(gl); + + if (useRegisterCombiners) { + gl.glEnable(GL.GL_REGISTER_COMBINERS_NV); + } else { + gl.glBindProgramARB(GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glEnable(GL.GL_FRAGMENT_PROGRAM_ARB); + } - if (getFlag('s')) { - // single pass - setRefraction(gl, refract); - drawObj(gl, glu, obj); + gl.glColor3f(1.0f, 1.0f, 1.0f); - } else { - // red pass - gl.glColorMask(true, false, false, false); - setRefraction(gl, refract); - drawObj(gl, glu, obj); - - gl.glDepthMask(false); - gl.glDepthFunc(GL.GL_EQUAL); - - // green pass - gl.glColorMask(false, true, false, false); - setRefraction(gl, refract + wavelengthDelta); - drawObj(gl, glu, obj); - - // blue pass - gl.glColorMask(false, false, true, false); - setRefraction(gl, refract + (wavelengthDelta * 2)); - drawObj(gl, glu, obj); - - gl.glDepthMask(true); - gl.glDepthFunc(GL.GL_LESS); - gl.glColorMask(true, true, true, false); - } + if (getFlag('s')) { + // single pass + setRefraction(gl, refract); + drawObj(gl, obj); - if (useRegisterCombiners) { - gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); - } else { - gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); - } - gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); + } else { + // red pass + gl.glColorMask(true, false, false, false); + setRefraction(gl, refract); + drawObj(gl, obj); + + gl.glDepthMask(false); + gl.glDepthFunc(GL.GL_EQUAL); + + // green pass + gl.glColorMask(false, true, false, false); + setRefraction(gl, refract + wavelengthDelta); + drawObj(gl, obj); + + // blue pass + gl.glColorMask(false, false, true, false); + setRefraction(gl, refract + (wavelengthDelta * 2)); + drawObj(gl, obj); + + gl.glDepthMask(true); + gl.glDepthFunc(GL.GL_LESS); + gl.glColorMask(true, true, true, false); + } - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glPopMatrix(); + if (useRegisterCombiners) { + gl.glDisable(GL.GL_REGISTER_COMBINERS_NV); + } else { + gl.glDisable(GL.GL_FRAGMENT_PROGRAM_ARB); } + gl.glDisable(GL.GL_VERTEX_PROGRAM_ARB); - // Unused routines - public void reshape(GLDrawable drawable, int x, int y, int width, int height) {} - public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {} - - //---------------------------------------------------------------------- - // Internals only below this point - // - private boolean[] b = new boolean[256]; - private void dispatchKey(char k) { - setFlag(k, !getFlag(k)); - // Quit on escape or 'q' - if ((k == (char) 27) || (k == 'q')) { - runExit(); - return; - } + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPopMatrix(); + } - switch (k) { - case '1': - obj = 0; - break; + // 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 + // + public void shutdownDemo() { + ManipManager.getManipManager().unregisterWindow(drawable); + drawable.removeGLEventListener(this); + super.shutdownDemo(); + } - case '2': - obj = 1; - break; + private boolean[] b = new boolean[256]; + private void dispatchKey(char k) { + setFlag(k, !getFlag(k)); - case '3': - obj = 2; - break; + // Quit on escape or 'q' + if ((k == (char) 27) || (k == 'q')) { + shutdownDemo(); + return; + } - case '4': - obj = 3; - break; + switch (k) { + case '1': + obj = 0; + break; - case 'v': - doViewAll = true; - break; + case '2': + obj = 1; + break; - case 'w': - toggleWire = true; - break; + case '3': + obj = 2; + break; - default: - break; - } - } + case '4': + obj = 3; + break; - private void setFlag(char key, boolean val) { - b[((int) key) & 0xFF] = val; - } + case 'v': + doViewAll = true; + break; - private boolean getFlag(char key) { - return b[((int) key) & 0xFF]; - } + case 'w': + toggleWire = true; + break; - // FIXME: note we found that we had to swap the negy and posy portions of the cubemap. - // Not sure why this is the case. Vertical flip in the image read? Possible, but doesn't - // appear to be the case (have tried this and produced wrong results at the time). - String[] suffixes = { "posx", "negx", "negy", "posy", "posz", "negz" }; - int[] targets = { GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB }; - private void loadPNGCubemap(GL gl, GLU glu, String baseName, boolean mipmapped) throws IOException { - for (int i = 0; i < suffixes.length; i++) { - String resourceName = baseName + "_" + suffixes[i] + ".png"; - // Note: use of BufferedInputStream works around 4764639/4892246 - BufferedImage img = ImageIO.read(new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(resourceName))); - if (img == null) { - throw new RuntimeException("Error reading PNG image " + resourceName); - } - makeRGBTexture(gl, glu, img, targets[i], mipmapped); - } + default: + break; } + } - private void makeRGBTexture(GL gl, GLU glu, BufferedImage img, int target, boolean mipmapped) { - switch (img.getType()) { - case BufferedImage.TYPE_3BYTE_BGR: - case BufferedImage.TYPE_CUSTOM: { - byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData(); - if (mipmapped) { - glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, - GL.GL_UNSIGNED_BYTE, data); - } else { - gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, - GL.GL_RGB, GL.GL_UNSIGNED_BYTE, data); - } - break; - } + private void setFlag(char key, boolean val) { + b[((int) key) & 0xFF] = val; + } - case BufferedImage.TYPE_INT_RGB: { - int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); - if (mipmapped) { - glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, - GL.GL_UNSIGNED_BYTE, data); - } else { - gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, - GL.GL_RGB, GL.GL_UNSIGNED_BYTE, data); - } - break; - } + private boolean getFlag(char key) { + return b[((int) key) & 0xFF]; + } + + // FIXME: note we found that we had to swap the negy and posy portions of the cubemap. + // Not sure why this is the case. Vertical flip in the image read? Possible, but doesn't + // appear to be the case (have tried this and produced wrong results at the time). + String[] suffixes = { "posx", "negx", "negy", "posy", "posz", "negz" }; + int[] targets = { GL.GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL.GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; + private void loadPNGCubemap(GL gl, String baseName, boolean mipmapped) throws IOException { + for (int i = 0; i < suffixes.length; i++) { + String resourceName = baseName + "_" + suffixes[i] + ".png"; + // Note: use of BufferedInputStream works around 4764639/4892246 + BufferedImage img = ImageIO.read(new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(resourceName))); + if (img == null) { + throw new RuntimeException("Error reading PNG image " + resourceName); + } + makeRGBTexture(gl, img, targets[i], mipmapped); + } + } - default: - throw new RuntimeException("Unsupported image type " + img.getType()); + private void makeRGBTexture(GL gl, BufferedImage img, int target, boolean mipmapped) { + switch (img.getType()) { + case BufferedImage.TYPE_3BYTE_BGR: + case BufferedImage.TYPE_CUSTOM: { + byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData(); + if (mipmapped) { + glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, + GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap(data)); + } else { + gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, + GL.GL_RGB, GL.GL_UNSIGNED_BYTE, ByteBuffer.wrap(data)); } + break; } - 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); + case BufferedImage.TYPE_INT_RGB: { + int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); + if (mipmapped) { + glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), GL.GL_RGB, + GL.GL_UNSIGNED_BYTE, IntBuffer.wrap(data)); + } else { + gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, + GL.GL_RGB, GL.GL_UNSIGNED_BYTE, IntBuffer.wrap(data)); } + break; } - // initalize texture combiners to compute: - // refraction*(1-fresnel) + reflection*fresnel - private void initCombiners(GL gl) { - gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 1); + default: + throw new RuntimeException("Unsupported image type " + img.getType()); + } + } + + 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); + shutdownDemo(); + } + }).start(); + throw new RuntimeException(message); + } + } + + // initalize texture combiners to compute: + // refraction*(1-fresnel) + reflection*fresnel + private void initCombiners(GL gl) { + gl.glCombinerParameteriNV(GL.GL_NUM_GENERAL_COMBINERS_NV, 1); - // combiner 0 - // a*b+c*d - gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0_ARB, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_PRIMARY_COLOR_NV, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE1_ARB, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_PRIMARY_COLOR_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - - // output: - // (stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum) - gl.glCombinerOutputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); + // combiner 0 + // a*b+c*d + gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_A_NV, GL.GL_TEXTURE0, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_B_NV, GL.GL_PRIMARY_COLOR_NV, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); + gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_C_NV, GL.GL_TEXTURE1, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glCombinerInputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_VARIABLE_D_NV, GL.GL_PRIMARY_COLOR_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + + // output: + // (stage, portion, abOutput, cdOutput, sumOutput, scale, bias, abDotProduct, cdDotProduct, muxSum) + gl.glCombinerOutputNV(GL.GL_COMBINER0_NV, GL.GL_RGB, GL.GL_DISCARD_NV, GL.GL_DISCARD_NV, GL.GL_SPARE0_NV, GL.GL_NONE, GL.GL_NONE, false, false, false); - // final combiner - // output: Frgb = A*B + (1-A)*C + D - // (variable, input, mapping, componentUsage); - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - gl.glFinalCombinerInputNV(GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); - } + // final combiner + // output: Frgb = A*B + (1-A)*C + D + // (variable, input, mapping, componentUsage); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_A_NV, GL.GL_SPARE0_NV, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_B_NV, GL.GL_ZERO, GL.GL_UNSIGNED_INVERT_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_C_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + gl.glFinalCombinerInputNV(GL.GL_VARIABLE_D_NV, GL.GL_ZERO, GL.GL_UNSIGNED_IDENTITY_NV, GL.GL_RGB); + } - private void initFragmentProgram(GL gl) { - int[] fragProgTmp = new int[1]; - gl.glGenProgramsARB(1, fragProgTmp); - fragProg = fragProgTmp[0]; - String combineFragProg = + private void initFragmentProgram(GL gl) { + int[] fragProgTmp = new int[1]; + gl.glGenProgramsARB(1, fragProgTmp, 0); + fragProg = fragProgTmp[0]; + String combineFragProg = "!!ARBfp1.0\n" + "# compute refraction*(1-fresnel) + reflection*fresnel\n" + "TEMP texSamp0, texSamp1;\n" + @@ -602,135 +617,133 @@ public class VertexProgRefract { "MOV result.color, texSamp0;\n" + "END"; - gl.glBindProgramARB (GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); - gl.glProgramStringARB(GL.GL_FRAGMENT_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, - combineFragProg.length(), combineFragProg); - int[] errPos = new int[1]; - gl.glGetIntegerv(GL.GL_PROGRAM_ERROR_POSITION_ARB, errPos); - if (errPos[0] >= 0) { - System.out.println("Fragment program failed to load:"); - String errMsg = gl.glGetString(GL.GL_PROGRAM_ERROR_STRING_ARB); - if (errMsg == null) { - System.out.println("[No error message available]"); - } else { - System.out.println("Error message: \"" + errMsg + "\""); - } - System.out.println("Error occurred at position " + errPos[0] + " in program:"); - int endPos = errPos[0]; - while (endPos < combineFragProg.length() && combineFragProg.charAt(endPos) != '\n') { - ++endPos; - } - System.out.println(combineFragProg.substring(errPos[0], endPos)); + gl.glBindProgramARB (GL.GL_FRAGMENT_PROGRAM_ARB, fragProg); + gl.glProgramStringARB(GL.GL_FRAGMENT_PROGRAM_ARB, GL.GL_PROGRAM_FORMAT_ASCII_ARB, + combineFragProg.length(), combineFragProg); + int[] errPos = new int[1]; + gl.glGetIntegerv(GL.GL_PROGRAM_ERROR_POSITION_ARB, errPos, 0); + if (errPos[0] >= 0) { + System.out.println("Fragment program failed to load:"); + String errMsg = gl.glGetString(GL.GL_PROGRAM_ERROR_STRING_ARB); + if (errMsg == null) { + System.out.println("[No error message available]"); + } else { + System.out.println("Error message: \"" + errMsg + "\""); + } + System.out.println("Error occurred at position " + errPos[0] + " in program:"); + int endPos = errPos[0]; + while (endPos < combineFragProg.length() && combineFragProg.charAt(endPos) != '\n') { + ++endPos; } + System.out.println(combineFragProg.substring(errPos[0], endPos)); } + } - private void drawSkyBox(GL gl, GLU glu) { - // Compensates for ExaminerViewer's modification of modelview matrix - gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glLoadIdentity(); + private void drawSkyBox(GL gl) { + // Compensates for ExaminerViewer's modification of modelview matrix + gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glLoadIdentity(); - gl.glActiveTextureARB(GL.GL_TEXTURE1_ARB); - gl.glDisable(GL.GL_TEXTURE_CUBE_MAP_ARB); + gl.glActiveTexture(GL.GL_TEXTURE1); + gl.glDisable(GL.GL_TEXTURE_CUBE_MAP); - gl.glActiveTextureARB(GL.GL_TEXTURE0_ARB); - gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP_ARB, cubemap); - gl.glEnable(GL.GL_TEXTURE_CUBE_MAP_ARB); - - // This is a workaround for a driver bug on Mac OS X where the - // normals are not being sent down to the hardware in - // GL_NORMAL_MAP_EXT texgen mode. Temporarily enabling lighting - // causes the normals to be sent down. Thanks to Ken Dyke. - gl.glEnable(GL.GL_LIGHTING); - - gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP_EXT); - gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP_EXT); - gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP_EXT); - - gl.glEnable(GL.GL_TEXTURE_GEN_S); - gl.glEnable(GL.GL_TEXTURE_GEN_T); - gl.glEnable(GL.GL_TEXTURE_GEN_R); - - gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); - - gl.glMatrixMode(GL.GL_TEXTURE); - gl.glPushMatrix(); - gl.glLoadIdentity(); - gl.glScalef(1.0f, -1.0f, 1.0f); - viewer.updateInverseRotation(gl); + gl.glActiveTexture(GL.GL_TEXTURE0); + gl.glBindTexture(GL.GL_TEXTURE_CUBE_MAP, cubemap); + gl.glEnable(GL.GL_TEXTURE_CUBE_MAP); + + // This is a workaround for a driver bug on Mac OS X where the + // normals are not being sent down to the hardware in + // GL_NORMAL_MAP texgen mode. Temporarily enabling lighting + // causes the normals to be sent down. Thanks to Ken Dyke. + gl.glEnable(GL.GL_LIGHTING); + + gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_NORMAL_MAP); + + gl.glEnable(GL.GL_TEXTURE_GEN_S); + gl.glEnable(GL.GL_TEXTURE_GEN_T); + gl.glEnable(GL.GL_TEXTURE_GEN_R); + + gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE); + + gl.glMatrixMode(GL.GL_TEXTURE); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glScalef(1.0f, -1.0f, 1.0f); + viewer.updateInverseRotation(gl); - glut.glutSolidSphere(glu, 5.0, 40, 20); + glut.glutSolidSphere(5.0, 40, 20); - gl.glDisable(GL.GL_LIGHTING); + gl.glDisable(GL.GL_LIGHTING); - gl.glPopMatrix(); - gl.glMatrixMode(GL.GL_MODELVIEW); + gl.glPopMatrix(); + gl.glMatrixMode(GL.GL_MODELVIEW); - gl.glDisable(GL.GL_TEXTURE_GEN_S); - gl.glDisable(GL.GL_TEXTURE_GEN_T); - gl.glDisable(GL.GL_TEXTURE_GEN_R); - } + gl.glDisable(GL.GL_TEXTURE_GEN_S); + gl.glDisable(GL.GL_TEXTURE_GEN_T); + gl.glDisable(GL.GL_TEXTURE_GEN_R); + } - private void drawObj(GL gl, GLU glu, int obj) { - switch(obj) { - case 0: - gl.glCallList(bunnydl); - break; + private void drawObj(GL gl, int obj) { + switch(obj) { + case 0: + gl.glCallList(bunnydl); + break; - case 1: - glut.glutSolidSphere(glu, 0.5, 64, 64); - break; + case 1: + glut.glutSolidSphere(0.5, 64, 64); + break; - case 2: - glut.glutSolidTorus(gl, 0.25, 0.5, 64, 64); - break; + case 2: + glut.glutSolidTorus(0.25, 0.5, 64, 64); + break; - case 3: - drawPlane(gl, 1.0f, 1.0f, 50, 50); - break; - } + case 3: + drawPlane(gl, 1.0f, 1.0f, 50, 50); + break; } + } - private void setRefraction(GL gl, float index) { - gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 4, index, index*index, 0.0f, 0.0f); - } + private void setRefraction(GL gl, float index) { + gl.glProgramEnvParameter4fARB(GL.GL_VERTEX_PROGRAM_ARB, 4, index, index*index, 0.0f, 0.0f); + } + + // draw square subdivided into quad strips + private void drawPlane(GL gl, float w, float h, int rows, int cols) { + int x, y; + float vx, vy, s, t; + float ts, tt, tw, th; + + ts = 1.0f / cols; + tt = 1.0f / rows; + + tw = w / cols; + th = h / rows; + + gl.glNormal3f(0.0f, 0.0f, 1.0f); + + for(y=0; y<rows; y++) { + gl.glBegin(GL.GL_QUAD_STRIP); + for(x=0; x<=cols; x++) { + vx = tw * x -(w/2.0f); + vy = th * y -(h/2.0f); + s = ts * x; + t = tt * y; + + gl.glTexCoord2f(s, t); + gl.glColor3f(s, t, 0.0f); + gl.glVertex3f(vx, vy, 0.0f); - // draw square subdivided into quad strips - private void drawPlane(GL gl, float w, float h, int rows, int cols) { - int x, y; - float vx, vy, s, t; - float ts, tt, tw, th; - - ts = 1.0f / cols; - tt = 1.0f / rows; - - tw = w / cols; - th = h / rows; - - gl.glNormal3f(0.0f, 0.0f, 1.0f); - - for(y=0; y<rows; y++) { - gl.glBegin(GL.GL_QUAD_STRIP); - for(x=0; x<=cols; x++) { - vx = tw * x -(w/2.0f); - vy = th * y -(h/2.0f); - s = ts * x; - t = tt * y; - - gl.glTexCoord2f(s, t); - gl.glColor3f(s, t, 0.0f); - gl.glVertex3f(vx, vy, 0.0f); - - gl.glColor3f(s, t + tt, 0.0f); - gl.glTexCoord2f(s, t + tt); - gl.glVertex3f(vx, vy + th, 0.0f); - } - gl.glEnd(); + gl.glColor3f(s, t + tt, 0.0f); + gl.glTexCoord2f(s, t + tt); + gl.glVertex3f(vx, vy + th, 0.0f); } + gl.glEnd(); } } - 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 |