diff options
author | Kenneth Russel <[email protected]> | 2009-06-15 23:12:27 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2009-06-15 23:12:27 +0000 |
commit | 41cd6c47b23975098cd155517790e018670785e7 (patch) | |
tree | 247333528ad674d427ba96b1e05810f7961d609e /src/demos/vertexProgWarp/VertexProgWarp.java | |
parent | 935d2596c13371bb745d921dbcb9f05b0c11a010 (diff) |
Copied JOGL_2_SANDBOX r350 on to trunk; JOGL_2_SANDBOX branch is now closed
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@352 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
Diffstat (limited to 'src/demos/vertexProgWarp/VertexProgWarp.java')
-rw-r--r-- | src/demos/vertexProgWarp/VertexProgWarp.java | 1086 |
1 files changed, 1086 insertions, 0 deletions
diff --git a/src/demos/vertexProgWarp/VertexProgWarp.java b/src/demos/vertexProgWarp/VertexProgWarp.java new file mode 100644 index 0000000..e6dbca7 --- /dev/null +++ b/src/demos/vertexProgWarp/VertexProgWarp.java @@ -0,0 +1,1086 @@ +/* + * Portions Copyright (C) 2003 Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * + * COPYRIGHT NVIDIA CORPORATION 2003. ALL RIGHTS RESERVED. + * BY ACCESSING OR USING THIS SOFTWARE, YOU AGREE TO: + * + * 1) ACKNOWLEDGE NVIDIA'S EXCLUSIVE OWNERSHIP OF ALL RIGHTS + * IN AND TO THE SOFTWARE; + * + * 2) NOT MAKE OR DISTRIBUTE COPIES OF THE SOFTWARE WITHOUT + * INCLUDING THIS NOTICE AND AGREEMENT; + * + * 3) ACKNOWLEDGE THAT TO THE MAXIMUM EXTENT PERMITTED BY + * APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* AND + * THAT NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, + * EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED + * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY + * SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES + * WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS + * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS + * INFORMATION, OR ANY OTHER PECUNIARY LOSS), INCLUDING ATTORNEYS' + * FEES, RELATING TO THE USE OF OR INABILITY TO USE THIS SOFTWARE, + * EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package demos.vertexProgWarp; + +import demos.common.Demo; +import demos.common.DemoListener; +import demos.util.DurationTimer; +import demos.util.SystemTime; +import demos.util.Time; +import demos.util.Triceratops; +import gleem.BSphere; +import gleem.BSphereProvider; +import gleem.ExaminerViewer; +import gleem.ManipManager; +import gleem.MouseButtonHelper; +import gleem.linalg.Vec3f; +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.awt.AWTGLAutoDrawable; +import javax.media.opengl.awt.GLCanvas; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.GLUquadric; +import com.sun.opengl.util.Animator; +import com.sun.opengl.util.BufferUtil; +import javax.swing.JOptionPane; + + + +/** + Simple space-warp/distortion vertex program demo<br> + (Press the space bar to switch through programs)<br><p> + + [email protected] 9/2000, based on Cass's vtxprog_silhouette<br><p> + + Ported to Java by Kenneth Russell +*/ + +public class VertexProgWarp extends Demo { + private Frame frame; + private Animator animator; + private volatile boolean quit; + + private GLAutoDrawable drawable; + private DurationTimer timer = new DurationTimer(); + private boolean firstRender = true; + private int frameCount; + + public static void main(String[] args) { + new VertexProgWarp().run(args); + } + + public void run(String[] args) { + + VertexProgWarp demo = new VertexProgWarp(); + GLCanvas canvas = new GLCanvas(); + canvas.addGLEventListener(demo); + + canvas.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + dispatchKey(e.getKeyCode(), e.getKeyChar()); + } + }); + + final Animator animator = new Animator(canvas); + demo.setDemoListener(new DemoListener() { + public void shutdownDemo() { + runExit(animator); + } + public void repaint() {} + }); + + 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); + frame.pack(); + frame.setVisible(true); + canvas.requestFocus(); + + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + runExit(animator); + } + }); + + animator.start(); + } + + public static abstract class TitleSetter { + public abstract void setTitle(String title); + } + + public void setTitleSetter(TitleSetter setter) { + titleSetter = setter; + } + + 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 GLU glu = new GLU(); + private ExaminerViewer viewer; + + public void init(GLAutoDrawable drawable) { + initComplete = false; + GL2 gl = drawable.getGL().getGL2(); + + 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_vertex_program"); + } catch (RuntimeException e) { + shutdownDemo(); + throw(e); + } + + for(int i=0; i<NUM_OBJS; i++) { + gl.glNewList(i+1, GL2.GL_COMPILE); + drawObject(gl, 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(GL2.GL_VERTEX_PROGRAM_ARB, programs[i]); + gl.glProgramStringARB(GL2.GL_VERTEX_PROGRAM_ARB, GL2.GL_PROGRAM_FORMAT_ASCII_ARB, programTexts[i].length(), + programTexts[i]); + } + + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 0, 0.0f, 0.0f, 1.0f, 0.0f); // light position/direction + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 1, 0.0f, 1.0f, 0.0f, 0.0f); // diffuse color + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 2, 1.0f, 1.0f, 1.0f, 0.0f); // specular color + + gl.glProgramEnvParameter4fARB(GL2.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(GL2.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(GL2.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(GL2.GL_VERTEX_PROGRAM_ARB, 6, 1.0f, 0.2f, 0.0f, 0.0f); + + // phase animation + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 7, 0.0f, 0.0f, 0.0f, 0.0f); + + // fisheye sphere radius + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 8, 1.0f, 0.0f, 0.0f, 0.0f); + + setWindowTitle(); + + doViewAll = true; + + b['p'] = true; + + // Register the window with the ManipManager + ManipManager manager = ManipManager.getManipManager(); + manager.registerWindow((AWTGLAutoDrawable) drawable); + this.drawable = drawable; + + viewer = new ExaminerViewer(MouseButtonHelper.numMouseButtons()); + viewer.setNoAltKeyMode(true); + viewer.setAutoRedrawMode(false); + viewer.attach((AWTGLAutoDrawable) 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); + initComplete = true; + } + + public void dispose(GLAutoDrawable drawable) { + } + + 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(); + + GL2 gl = drawable.getGL().getGL2(); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + if (toggleWire) { + wire = !wire; + if (wire) + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_LINE); + else + gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL2.GL_FILL); + toggleWire = false; + } + + gl.glPushMatrix(); + + if (doViewAll) { + viewer.viewAll(gl); + doViewAll = false; + } + + if (animating) { + anim -= (float) (animScale * time.deltaT()); + } + + viewer.update(gl); + ManipManager.getManipManager().updateCameraParameters((AWTGLAutoDrawable) drawable, viewer.getCameraParameters()); + ManipManager.getManipManager().render((AWTGLAutoDrawable) drawable, gl); + + gl.glBindProgramARB(GL2.GL_VERTEX_PROGRAM_ARB, programs[program]); + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 7, anim, 0.0f, 0.0f, 0.0f); + + if (program==6) + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 6, (float) Math.sin(anim)*amp*50.0f, 0.0f, 0.0f, 0.0f); + else + gl.glProgramEnvParameter4fARB(GL2.GL_VERTEX_PROGRAM_ARB, 6, freq, amp, d, d+1); + + if (b['p']) + gl.glEnable(GL2.GL_VERTEX_PROGRAM_ARB); + + gl.glDisable(GL.GL_TEXTURE_2D); + gl.glCallList(obj+1); + + gl.glDisable(GL2.GL_VERTEX_PROGRAM_ARB); + + 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) {} + + //---------------------------------------------------------------------- + // Internals only below this point + // + public void shutdownDemo() { + ManipManager.getManipManager().unregisterWindow((AWTGLAutoDrawable) drawable); + drawable.removeGLEventListener(this); + super.shutdownDemo(); + } + + private void initExtension(GL2 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); + } + } + + 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: + 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 setWindowTitle() { + titleSetter.setTitle("SpaceWarp - " + programNames[program]); + } + + private void drawObject(GL2 gl, 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) { + shutdownDemo(); + throw new RuntimeException(e); + } + break; + + case 3: + drawCube(gl); + break; + + case 4: + drawCylinder(gl); + break; + } + } + + private void drawSphere(GL2 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(GL2.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(GL2 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(GL2.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(GL2 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(GL2 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(GL2.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(GL2 gl) { + 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); + + gl.glMatrixMode(GL2ES1.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.gluDeleteQuadric(quad); + } + + private static final String[] programNames = new String[] { + "Normal", + "Pulsate", + "Wave", + "Square fisheye", + "Spherical fisheye", + "Ripple", + "Twist" + }; + + private static final String programSetup = + "PARAM mvp [4] = { state.matrix.mvp }; # modelview projection matrix\n" + + "PARAM mvit[4] = { state.matrix.modelview.invtrans }; # modelview matrix inverse transpose\n" + + "PARAM mv [4] = { state.matrix.modelview }; # modelview matrix\n" + + "PARAM proj[4] = { state.matrix.projection }; # projection matrix\n" + + "PARAM lightPos = program.env[0]; # light position/direction\n" + + "PARAM diffuseCol = program.env[1]; # diffuse color\n" + + "PARAM specularCol = program.env[2]; # specular color\n" + + "PARAM smoothstep = program.env[3]; # smoothstep constants\n" + + "PARAM sinTaylorConst1 = program.env[4]; # sin Taylor series constants 1 of 2\n" + + "PARAM sinTaylorConst2 = program.env[5]; # sin Taylor series constants 2 of 2\n" + + "PARAM sinFreqAmplitude = program.env[6]; # sin wave frequency, amplitude\n" + + "PARAM phaseAnim = program.env[7]; # phase animation\n" + + "PARAM fisheyeRadius = program.env[8]; # fisheye sphere radius\n" + + "\n" + + "# Per vertex inputs\n" + + "ATTRIB iPos = vertex.position; # position\n" + + "ATTRIB iTex = vertex.texcoord; # tex coord\n" + + "ATTRIB iNorm = vertex.normal; # normal\n" + + "\n" + + "# Outputs\n" + + "OUTPUT oPos = result.position; # position\n" + + "OUTPUT oCol0 = result.color; # color\n" + + "OUTPUT oTex0 = result.texcoord; # tex coord\n" + + "\n" + + "# Temporaries\n" + + "TEMP r0;\n" + + "TEMP r1;\n" + + "TEMP r2;\n" + + "TEMP r3;\n" + + "TEMP r4;\n"; + + private static final String[] programTexts = new String[] { + // + // Transform with diffuse lighting + // + "!!ARBvp1.0\n" + + "#Simple transform and diffuse lighting\n" + + programSetup + + "DP4 oPos.x, mvp[0], iPos ; # object x MVP -> clip\n" + + "DP4 oPos.y, mvp[1], iPos ;\n" + + "DP4 oPos.z, mvp[2], iPos ;\n" + + "DP4 oPos.w, mvp[3], iPos ;\n" + + "\n" + + "DP3 r1.x, mvit[0], iNorm ; # normal x MV-1T -> lighting normal\n" + + "DP3 r1.y, mvit[1], iNorm ;\n" + + "DP3 r1.z, mvit[2], iNorm ;\n" + + "\n" + + "DP3 r0, lightPos, r1 ; # L.N\n" + + "MUL oCol0.xyz, r0, diffuseCol ; # col = L.N * diffuse\n" + + "MOV oTex0, iTex;\n" + + "END\n", + + // + // Pulsate + // + "!!ARBvp1.0\n" + + "#Displace geometry along normal based on sine function of distance from origin\n" + + "#(in object space)\n" + + "#sinFreqAmplitude.x = wave frequency\n" + + "#sinFreqAmplitude.y = wave amplitude\n" + + "#sinTaylorConst2 = PI constants\n" + + "#sinTaylorConst1 = Taylor series constants (see below)\n" + + "\n" + + programSetup + + "MOV r0, iPos; \n" + + "\n" + + "#calculate distance from (0, 0, 0)\n" + + "DP3 r3.x, r0, r0;\n" + + "RSQ r3.x, r3.x;\n" + + "RCP r3.x, r3.x;\n" + + "\n" + + "MUL r3.x, r3.x, sinFreqAmplitude.x; # wave frequency\n" + + "ADD r3.x, r3.x, phaseAnim.x; # phase animation\n" + + "\n" + + "#reduce to period of 2*PI\n" + + "MUL r2, r3.x, sinTaylorConst2.x;\n" + + "EXP r4, r2.x; # r4.y = r2.x - floor(r2.x)\n" + + "MUL r3.x, r4.y, sinTaylorConst2.y;\n" + + "\n" + + "# offset to -PI - PI\n" + + "ADD r3.x, r3.x, -sinTaylorConst2.z;\n" + + "\n" + + "#Sine approximation using Taylor series (accurate between -PI and PI) :\n" + + "#sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...\n" + + "#sin(x) ~= x*(1 - (x^2)*(1/3! - (x^2)(1/5! - (x^2)/7! )))\n" + + "# = x * (a - y*(b - y*(c - y*d)))\n" + + "#where\n" + + "#a = 1.0 sinTaylorConst1.x\n" + + "#b = 1/3! sinTaylorConst1.y\n" + + "#c = 1/5! sinTaylorConst1.z\n" + + "#d = 1/7! sinTaylorConst1.w\n" + + "#y = x^2 r2\n" + + "\n" + + "#r1.x = sin(r3.x);\n" + + "\n" + + "MUL r2, r3.x, r3.x;\n" + + "MAD r1, -r2, sinTaylorConst1.w, sinTaylorConst1.z;\n" + + "MAD r1, r1, -r2, sinTaylorConst1.y;\n" + + "MAD r1, r1, -r2, sinTaylorConst1.x;\n" + + "MUL r1, r1, r3.x;\n" + + "\n" + + "#displace vertex along normal\n" + + "MUL r1.x, r1.x, sinFreqAmplitude.y;\n" + + "MAX r1.x, r1.x, smoothstep.x; # r1.x = max(r1.x, 0.0);\n" + + "MUL r2.xyz, iNorm, r1.x;\n" + + "ADD r0.xyz, r0, r2;\n" + + "\n" + + "#simple lighting\n" + + "DP3 r1.x, mvit[0], iNorm ; # normal x MV-1T -> lighting normal\n" + + "DP3 r1.y, mvit[1], iNorm ;\n" + + "DP3 r1.z, mvit[2], iNorm ;\n" + + "\n" + + "DP3 r2, lightPos, r1 ; # light position DOT normal\n" + + "MUL oCol0.xyz, r2, diffuseCol ; # col = ldotn * diffuse\n" + + "\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "DP4 oPos.x, mvp[0], r0 ; # object x MVP -> clip\n" + + "DP4 oPos.y, mvp[1], r0 ;\n" + + "DP4 oPos.z, mvp[2], r0 ;\n" + + "DP4 oPos.w, mvp[3], r0 ;\n" + + "\n" + + "END\n", + + // + // Wave + // + "!!ARBvp1.0\n" + + "# Perturb vertices in clip space with sine wave\n" + + "# x += sin((y*freq)+anim) * amp\n" + + programSetup + + "DP4 r0.x, mvp[0], iPos ;\n" + + "DP4 r0.y, mvp[1], iPos ;\n" + + "DP4 r0.z, mvp[2], iPos ;\n" + + "DP4 r0.w, mvp[3], iPos ;\n" + + "\n" + + "MUL r3.x, r0.y, sinFreqAmplitude.x; # wave frequency\n" + + "ADD r3.x, r3.x, phaseAnim.x; # phase animation\n" + + "\n" + + "# reduce to period of 2*PI\n" + + "MUL r2, r3.x, sinTaylorConst2.x;\n" + + "EXP r4, r2.x; # r4.y = r2.x - floor(r2.x)\n" + + "MUL r3.x, r4.y, sinTaylorConst2.y;\n" + + "\n" + + "# offset to -PI - PI\n" + + "ADD r3.x, r3.x, -sinTaylorConst2.z;\n" + + "\n" + + "# r1.x = sin(r3.x);\n" + + "MUL r2, r3.x, r3.x;\n" + + "MAD r1, -r2, sinTaylorConst1.w, sinTaylorConst1.z;\n" + + "MAD r1, r1, -r2, sinTaylorConst1.y;\n" + + "MAD r1, r1, -r2, sinTaylorConst1.x;\n" + + "MUL r1, r1, r3.x;\n" + + "\n" + + "MAD r0.x, r1.x, sinFreqAmplitude.y, r0.x;\n" + + "\n" + + "# simple lighting\n" + + "DP3 r1.x, mvit[0], iNorm ; # normal x MV-1T -> lighting normal\n" + + "DP3 r1.y, mvit[1], iNorm ;\n" + + "DP3 r1.z, mvit[2], iNorm ;\n" + + "DP3 r2, lightPos, r1 ; # light position DOT normal\n" + + "MUL oCol0.xyz, r2, diffuseCol ; # col = ldotn * diffuse\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "MOV oPos, r0;\n" + + "\n" + + "END\n", + + // + // Fisheye + // + "!!ARBvp1.0\n" + + "#Fisheye distortion based on function:\n" + + "#f(x)=(d+1)/(d+(1/x))\n" + + "#maps the [0,1] interval monotonically onto [0,1]\n" + + "\n" + + "#sinFreqAmplitude.z = d\n" + + "#sinFreqAmplitude.w = d+1\n" + + programSetup + + "\n" + + "DP4 r0.x, mvp[0], iPos ;\n" + + "DP4 r0.y, mvp[1], iPos ;\n" + + "DP4 r0.z, mvp[2], iPos ;\n" + + "DP4 r0.w, mvp[3], iPos ;\n" + + "\n" + + "# do perspective divide\n" + + "RCP r1, r0.w;\n" + + "MUL r0, r0, r1.w;\n" + + "\n" + + "MAX r1, r0, -r0; # r1 = abs(r0)\n" + + "\n" + + "SLT r2, r0, smoothstep.x; # r2 = (r0 < 0.0) ? 1.0 : 0.0\n" + + "SGE r3, r0, smoothstep.x; # r3 = (r0 >= 0.0) ? 1.0 : 0.0\n" + + "\n" + + "# distort x\n" + + "# h(x)=(d+1)/(d+(1/x))\n" + + "RCP r1.x, r1.x; # r1 = 1 / r1\n" + + "ADD r1.x, r1.x, sinFreqAmplitude.z; # r1 += d\n" + + "RCP r1.x, r1.x; # r1 = 1 / r1\n" + + "MUL r1.x, r1.x, sinFreqAmplitude.w; # r1 *= d + 1\n" + + "\n" + + "# distort y\n" + + "RCP r1.y, r1.y; # r1 = 1 / r1\n" + + "ADD r1.y, r1.y, sinFreqAmplitude.z; # r1 += d\n" + + "RCP r1.y, r1.y; # r1 = 1 / r1\n" + + "MUL r1.y, r1.y, sinFreqAmplitude.w; # r1 *= d + 1\n" + + "\n" + + "# handle negative cases\n" + + "MUL r4.xy, r1, r3; # r4 = r1 * r3\n" + + "MAD r1.xy, r1, -r2, r4; # r1 = r1 * -r2 + r4\n" + + "\n" + + "# simple lighting\n" + + "DP3 r2.x, mvit[0], iNorm ; # normal x MV-1T -> lighting normal\n" + + "DP3 r2.y, mvit[1], iNorm ;\n" + + "DP3 r2.z, mvit[2], iNorm ;\n" + + "DP3 r3, lightPos, r2 ; # light position DOT normal\n" + + "MUL oCol0.xyz, r3, diffuseCol ; # col = ldotn * diffuse\n" + + "\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "MOV oPos, r1;\n" + + "\n" + + "END\n", + + // + // Spherize + // + "!!ARBvp1.0\n" + + "# Spherical fish-eye distortion\n" + + "# in clip space\n" + + programSetup + + "DP4 r0.x, mvp[0], iPos;\n" + + "DP4 r0.y, mvp[1], iPos;\n" + + "DP4 r0.z, mvp[2], iPos;\n" + + "DP4 r0.w, mvp[3], iPos;\n" + + "\n" + + "# do perspective divide\n" + + "RCP r1.x, r0.w;\n" + + "MUL r2, r0, r1.x;\n" + + "\n" + + "# calculate distance from centre\n" + + "MUL r1.x, r2.x, r2.x;\n" + + "MAD r1.x, r2.y, r2.y, r1.x;\n" + + "RSQ r1.x, r1.x; # r1.x = 1 / sqrt(x*x+y*y)\n" + + "\n" + + "# calculate r3 = normalized direction vector\n" + + "MUL r3.xy, r0, r1.x;\n" + + "\n" + + "RCP r1.x, r1.x; # r1.x = actual distance\n" + + "MIN r1.x, r1.x, smoothstep.y; # r1.x = min(r1.x, 1.0)\n" + + "\n" + + "# remap based on: f(x) = sqrt(1-x^2)\n" + + "ADD r1.x, smoothstep.y, -r1.x;\n" + + "MAD r1.x, -r1.x, r1.x, smoothstep.y;\n" + + "RSQ r1.x, r1.x;\n" + + "RCP r1.x, r1.x;\n" + + "\n" + + "# move vertex to new distance from centre\n" + + "MUL r0.xy, r3, r1.x;\n" + + "\n" + + "# simple lighting\n" + + "DP3 r2.x, mvit[0], iNorm; # normal x MV-1T -> lighting normal\n" + + "DP3 r2.y, mvit[1], iNorm;\n" + + "DP3 r2.z, mvit[2], iNorm;\n" + + "DP3 r3, lightPos, r2 ; # light position DOT normal\n" + + "MUL oCol0.xyz, r3, diffuseCol ; # col = ldotn * diffuse\n" + + "\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "MOV oPos, r0;\n" + + "\n" + + "END\n", + + // + // Ripple + // + "!!ARBvp1.0\n" + + "# Ripple distortion\n" + + programSetup + + "DP4 r0.x, mvp[0], iPos;\n" + + "DP4 r0.y, mvp[1], iPos;\n" + + "DP4 r0.z, mvp[2], iPos;\n" + + "DP4 r0.w, mvp[3], iPos;\n" + + "\n" + + "# do perspective divide\n" + + "RCP r1.x, r0.w;\n" + + "MUL r4, r0, r1.x;\n" + + "\n" + + "# calculate distance from centre\n" + + "MUL r1.x, r4.x, r4.x;\n" + + "MAD r1.x, r4.y, r4.y, r1.x;\n" + + "RSQ r1.x, r1.x;\n" + + "\n" + + "RCP r1.x, r1.x;\n" + + "\n" + + "MUL r1.x, r1.x, sinFreqAmplitude.x; # wave frequency\n" + + "ADD r1.x, r1.x, phaseAnim.x; # phase animation\n" + + "\n" + + "# reduce to period of 2*PI\n" + + "MUL r2, r1.x, sinTaylorConst2.x; # r2 = r1 / 2.0 * PI\n" + + "EXP r4, r2.x; # r4.y = r2.x - floor(r2.x)\n" + + "MUL r1.x, r4.y, sinTaylorConst2.y;\n" + + "\n" + + "# offset to -PI - PI\n" + + "ADD r1.x, r1.x, -sinTaylorConst2.z;\n" + + "\n" + + "# r3.x = sin(r1.x)\n" + + "MUL r2, r1.x, r1.x;\n" + + "MAD r3, -r2, sinTaylorConst1.w, sinTaylorConst1.z;\n" + + "MAD r3, r3, -r2, sinTaylorConst1.y;\n" + + "MAD r3, r3, -r2, sinTaylorConst1.x;\n" + + "MUL r3, r3, r1.x;\n" + + "\n" + + "MUL r3.x, r3.x, sinFreqAmplitude.y;\n" + + "\n" + + "# move vertex towards centre based on distance\n" + + "MAD r0.xy, r0, -r3.x, r0;\n" + + "\n" + + "# lighting\n" + + "DP3 r2.x, mvit[0], iNorm; # normal x MV-1T -> lighting normal\n" + + "DP3 r2.y, mvit[1], iNorm;\n" + + "DP3 r2.z, mvit[2], iNorm;\n" + + "DP3 r3, lightPos, r2; # light position DOT normal\n" + + "MUL oCol0.xyz, r3, diffuseCol; # col = ldotn * diffuse\n" + + "\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "MOV oPos, r0;\n" + + "\n" + + "END\n", + + // + // Twist + // + "!!ARBvp1.0\n" + + "# Twist\n" + + programSetup + + "MOV r0, iPos;\n" + + "\n" + + "MUL r1.x, r0.x, sinFreqAmplitude.x; # frequency\n" + + "\n" + + "# calculate sin(angle) and cos(angle)\n" + + "ADD r1.y, r1.x, -sinTaylorConst2.w; # r1.y = r1.x + PI/2.0\n" + + "\n" + + "# reduce to period of 2*PI\n" + + "MUL r2, r1, sinTaylorConst2.x; # r2 = r1 / 2.0 * PI\n" + + "EXP r3.y, r2.x; # r2.y = r2.x - floor(r2.x)\n" + + "MOV r3.x, r3.y;\n" + + "EXP r3.y, r2.y; # r2.y = r2.x - floor(r2.x)\n" + + "MAD r2, r3, sinTaylorConst2.y, -sinTaylorConst2.z; # r2 = (r3 * 2.0*PI) - M_PI\n" + + "\n" + + "# r4.x = sin(r2.x);\n" + + "# r4.y = cos(r2.y);\n" + + "# parallel taylor series\n" + + "MUL r3, r2, r2;\n" + + "MAD r4, -r3, sinTaylorConst1.w, sinTaylorConst1.z;\n" + + "MAD r4, r4, -r3, sinTaylorConst1.y;\n" + + "MAD r4, r4, -r3, sinTaylorConst1.x;\n" + + "MUL r4, r4, r2;\n" + + "\n" + + "# x y z w\n" + + "# R:\n" + + "# 1 0 0 0\n" + + "# 0 c -s 0\n" + + "# 0 s c 0\n" + + "# 0 0 0 1\n" + + "\n" + + "# c = cos(a)\n" + + "# s = sin(a)\n" + + "\n" + + "# calculate rotation around X\n" + + "MOV r1, r0;\n" + + "\n" + + "MUL r1.y, r0.y, r4.y;\n" + + "MAD r1.y, r0.z, -r4.x, r1.y; # ny = y*cos(a) - z*sin(a)\n" + + "\n" + + "MUL r1.z, r0.y, r4.x;\n" + + "MAD r1.z, r0.z, r4.y, r1.z; # nz = y*sin(a) + z*cos(a)\n" + + "\n" + + "DP4 oPos.x, mvp[0], r1; # object x MVP -> clip\n" + + "DP4 oPos.y, mvp[1], r1;\n" + + "DP4 oPos.z, mvp[2], r1;\n" + + "DP4 oPos.w, mvp[3], r1;\n" + + "\n" + + "# rotate normal\n" + + "MOV r2, iNorm;\n" + + "MUL r2.y, iNorm.y, r4.y;\n" + + "MAD r2.y, iNorm.z, -r4.x, r2.y; # ny = y*cos(a) - z*sin(a)\n" + + "\n" + + "MUL r2.z, iNorm.y, r4.x;\n" + + "MAD r2.z, iNorm.z, r4.y, r2.z; # nz = y*sin(a) + z*cos(a)\n" + + "\n" + + "# diffuse lighting\n" + + "DP3 r1.x, mvit[0], r2; # normal x MV-1T -> lighting normal\n" + + "DP3 r1.y, mvit[1], r2;\n" + + "DP3 r1.z, mvit[2], r2;\n" + + "\n" + + "DP3 r3, lightPos, r1; # light position DOT normal\n" + + "MUL oCol0.xyz, r3, diffuseCol; # col = ldotn * diffuse\n" + + "\n" + + "MOV oTex0, iTex;\n" + + "\n" + + "END\n" + }; + + 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. Instead run + // the exit routine in another thread. + new Thread(new Runnable() { + public void run() { + animator.stop(); + System.exit(0); + } + }).start(); + } +} |