summaryrefslogtreecommitdiffstats
path: root/src/demos/vertexProgWarp
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2003-06-25 09:05:29 +0000
committerKenneth Russel <[email protected]>2003-06-25 09:05:29 +0000
commit2179980ed660ef66a9c064d153c5de7994d431ab (patch)
tree926fa0ccc31737ad9753a64bf0451dd818652d1b /src/demos/vertexProgWarp
parent1a1ad3a33b2932187410bc8bb4bf44362a26c8b0 (diff)
Split up net.java.games.util; moved GLUT and BufferUtils into
net.java.games.jogl.util, and moved demo-specific utility classes into jogl-demos project under demos.util. Added nearly all JavaOne demos into jogl-demos project; rewrote where necessary to use ClassLoader.getResourceAsStream() instead of flat files, put into packages and added to Makefile. Added gleem to jogl-demos project. Added jogl.jar build rule. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/jogl-demos/trunk@3 3298f667-5e0e-4b4a-8ed4-a3559d26a5f4
Diffstat (limited to 'src/demos/vertexProgWarp')
-rw-r--r--src/demos/vertexProgWarp/VertexProgWarp.java979
1 files changed, 979 insertions, 0 deletions
diff --git a/src/demos/vertexProgWarp/VertexProgWarp.java b/src/demos/vertexProgWarp/VertexProgWarp.java
new file mode 100644
index 0000000..729d044
--- /dev/null
+++ b/src/demos/vertexProgWarp/VertexProgWarp.java
@@ -0,0 +1,979 @@
+/*
+ * 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 java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+import javax.swing.*;
+
+import net.java.games.jogl.*;
+import demos.util.*;
+import gleem.*;
+import gleem.linalg.*;
+
+/**
+ 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 {
+ private GLCanvas canvas;
+ private Frame frame;
+ private Animator animator;
+ private volatile boolean quit;
+
+ 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) {
+ canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
+ canvas.addGLEventListener(new Listener());
+
+ animator = new Animator(canvas);
+
+ frame = new Frame();
+ frame.setLayout(new BorderLayout());
+ canvas.setSize(512, 512);
+ frame.add(canvas, BorderLayout.CENTER);
+ frame.pack();
+ frame.show();
+ canvas.requestFocus();
+
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ animator.stop();
+ System.exit(0);
+ }
+ });
+
+ 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(GLDrawable 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);
+
+ try {
+ initExtension(gl, "GL_NV_vertex_program");
+ } catch (RuntimeException e) {
+ runExit();
+ 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.glGenProgramsNV(1, vtxProgTmp);
+ programs[i] = vtxProgTmp[0];
+ gl.glBindProgramNV(GL.GL_VERTEX_PROGRAM_NV, programs[i]);
+ gl.glLoadProgramNV(GL.GL_VERTEX_PROGRAM_NV, programs[i], programTexts[i].length(), programTexts[i]);
+ }
+
+ gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 0, GL.GL_MODELVIEW_PROJECTION_NV, GL.GL_IDENTITY_NV);
+ gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 4, GL.GL_MODELVIEW, GL.GL_INVERSE_TRANSPOSE_NV);
+ gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 8, GL.GL_MODELVIEW, GL.GL_IDENTITY_NV);
+ gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 12, GL.GL_PROJECTION, GL.GL_IDENTITY_NV);
+
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 32, 0.0f, 0.0f, 1.0f, 0.0f); // light position/direction
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 35, 0.0f, 1.0f, 0.0f, 0.0f); // diffuse color
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 36, 1.0f, 1.0f, 1.0f, 0.0f); // specular color
+
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 64, 0.0f, 1.0f, 2.0f, 3.0f); // smoothstep constants
+
+ // sin Taylor series constants - 1, 1/3!, 1/5!, 1/7!
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 63, 1.0f, 1.0f / (3*2), 1.0f / (5*4*3*2), 1.0f / (7*6*5*4*3*2));
+
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 62, 1.0f / (2.0f * SIN_PERIOD), 2.0f * SIN_PERIOD, SIN_PERIOD, SIN_PERIOD/2.0f);
+
+ // sin wave frequency, amplitude
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 61, 1.0f, 0.2f, 0.0f, 0.0f);
+
+ // phase animation
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 60, 0.0f, 0.0f, 0.0f, 0.0f);
+
+ // fisheye sphere radius
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 59, 1.0f, 0.0f, 0.0f, 0.0f);
+
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 58, 0.0f, 0.0f, -2.0f / (zFar - zNear), -(zFar+zNear)/(zFar-zNear) );
+ setWindowTitle();
+
+ 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.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);
+ }
+
+ public void display(GLDrawable drawable) {
+ 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();
+
+ 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, GL.GL_LINE);
+ else
+ gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.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(drawable, viewer.getCameraParameters());
+ ManipManager.getManipManager().render(drawable, gl);
+
+ gl.glBindProgramNV(GL.GL_VERTEX_PROGRAM_NV, programs[program]);
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 60, anim, 0.0f, 0.0f, 0.0f);
+
+ if (program==6)
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 61, (float) Math.sin(anim)*amp*50.0f, 0.0f, 0.0f, 0.0f);
+ else
+ gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 61, freq, amp, d, d+1);
+
+ if (b['p'])
+ gl.glEnable(GL.GL_VERTEX_PROGRAM_NV);
+
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ gl.glCallList(obj+1);
+
+ gl.glDisable(GL.GL_VERTEX_PROGRAM_NV);
+
+ gl.glPopMatrix();
+ }
+
+ // 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 void initExtension(GL gl, String glExtensionName) {
+ if (!gl.isExtensionAvailable(glExtensionName)) {
+ throw new RuntimeException("OpenGL extension \"" + glExtensionName + "\" not available");
+ }
+ }
+
+ 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 setWindowTitle() {
+ frame.setTitle("SpaceWarp - " + programNames[program]);
+ }
+
+ 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;
+
+ 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 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 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;
+
+ 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);
+
+ 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[] programTexts = new String[] {
+ //
+ // Transform with diffuse lighting
+ //
+ "!!VP1.0\n" +
+ "#Simple transform and diffuse lighting\n" +
+ "\n" +
+ "DP4 o[HPOS].x, c[0], v[OPOS] ; # object x MVP -> clip\n" +
+ "DP4 o[HPOS].y, c[1], v[OPOS] ;\n" +
+ "DP4 o[HPOS].z, c[2], v[OPOS] ;\n" +
+ "DP4 o[HPOS].w, c[3], v[OPOS] ;\n" +
+ "\n" +
+ "DP3 R1.x, c[4], v[NRML] ; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R1.y, c[5], v[NRML] ;\n" +
+ "DP3 R1.z, c[6], v[NRML] ;\n" +
+ "\n" +
+ "DP3 R0, c[32], R1 ; # L.N\n" +
+ "MUL o[COL0].xyz, R0, c[35] ; # col = L.N * diffuse\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "END",
+
+ //
+ // Pulsate
+ //
+ "!!VP1.0\n" +
+ "#Displace geometry along normal based on sine function of distance from origin\n" +
+ "#(in object space)\n" +
+ "#c[61].x = wave frequency\n" +
+ "#c[61].y = wave amplitude\n" +
+ "#c[62] = PI constants\n" +
+ "#c[63] = Taylor series constants (see below)\n" +
+ "\n" +
+ "MOV R0, v[OPOS]; \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, c[61].x; # wave frequency\n" +
+ "ADD R3.x, R3.x, c[60].x; # phase animation\n" +
+ "\n" +
+ "#reduce to period of 2*PI\n" +
+ "MUL R2, R3.x, c[62].x;\n" +
+ "EXP R4, R2.x; # R4.y = R2.x - floor(R2.x)\n" +
+ "MUL R3.x, R4.y, c[62].y;\n" +
+ "\n" +
+ "# offset to -PI - PI\n" +
+ "ADD R3.x, R3.x, -c[62].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 c[63].x\n" +
+ "#b = 1/3! c[63].y\n" +
+ "#c = 1/5! c[63].z\n" +
+ "#d = 1/7! c[63].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, c[63].w, c[63].z;\n" +
+ "MAD R1, R1, -R2, c[63].y;\n" +
+ "MAD R1, R1, -R2, c[63].x;\n" +
+ "MUL R1, R1, R3.x;\n" +
+ "\n" +
+ "#displace vertex along normal\n" +
+ "MUL R1.x, R1.x, c[61].y;\n" +
+ "MAX R1.x, R1.x, c[64].x; # r1.x = max(r1.x, 0.0);\n" +
+ "MUL R2.xyz, v[NRML], R1.x;\n" +
+ "ADD R0.xyz, R0, R2;\n" +
+ "\n" +
+ "#simple lighting\n" +
+ "DP3 R1.x, c[4], v[NRML] ; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R1.y, c[5], v[NRML] ;\n" +
+ "DP3 R1.z, c[6], v[NRML] ;\n" +
+ "\n" +
+ "DP3 R2, c[32], R1 ; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R2, c[35] ; # col = ldotn * diffuse\n" +
+ "\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "DP4 o[HPOS].x, c[0], R0 ; # object x MVP -> clip\n" +
+ "DP4 o[HPOS].y, c[1], R0 ;\n" +
+ "DP4 o[HPOS].z, c[2], R0 ;\n" +
+ "DP4 o[HPOS].w, c[3], R0 ;\n" +
+ "\n" +
+ "END",
+
+ //
+ // Wave
+ //
+ "!!VP1.0\n" +
+ "# Perturb vertices in clip space with sine wave\n" +
+ "# x += sin((y*freq)+anim) * amp\n" +
+ "DP4 R0.x, c[0], v[OPOS] ;\n" +
+ "DP4 R0.y, c[1], v[OPOS] ;\n" +
+ "DP4 R0.z, c[2], v[OPOS] ;\n" +
+ "DP4 R0.w, c[3], v[OPOS] ;\n" +
+ "\n" +
+ "MUL R3.x, R0.y, c[61].x; # wave frequency\n" +
+ "ADD R3.x, R3.x, c[60].x; # phase animation\n" +
+ "\n" +
+ "# reduce to period of 2*PI\n" +
+ "MUL R2, R3.x, c[62].x;\n" +
+ "EXP R4, R2.x; # R4.y = R2.x - floor(R2.x)\n" +
+ "MUL R3.x, R4.y, c[62].y;\n" +
+ "\n" +
+ "# offset to -PI - PI\n" +
+ "ADD R3.x, R3.x, -c[62].z;\n" +
+ "\n" +
+ "# R1.x = sin(R3.x);\n" +
+ "MUL R2, R3.x, R3.x;\n" +
+ "MAD R1, -R2, c[63].w, c[63].z;\n" +
+ "MAD R1, R1, -R2, c[63].y;\n" +
+ "MAD R1, R1, -R2, c[63].x;\n" +
+ "MUL R1, R1, R3.x;\n" +
+ "\n" +
+ "MAD R0.x, R1.x, c[61].y, R0.x;\n" +
+ "\n" +
+ "# simple lighting\n" +
+ "DP3 R1.x, c[4], v[NRML] ; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R1.y, c[5], v[NRML] ;\n" +
+ "DP3 R1.z, c[6], v[NRML] ;\n" +
+ "DP3 R2, c[32], R1 ; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R2, c[35] ; # col = ldotn * diffuse\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "MOV o[HPOS], R0;\n" +
+ "\n" +
+ "END",
+
+ //
+ // Fisheye
+ //
+ "!!VP1.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" +
+ "#c[61].z = d\n" +
+ "#c[61].w = d+1\n" +
+ "\n" +
+ "DP4 R0.x, c[0], v[OPOS] ;\n" +
+ "DP4 R0.y, c[1], v[OPOS] ;\n" +
+ "DP4 R0.z, c[2], v[OPOS] ;\n" +
+ "DP4 R0.w, c[3], v[OPOS] ;\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, c[64].x; # r2 = (r0 < 0.0) ? 1.0 : 0.0\n" +
+ "SGE R3, R0, c[64].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, c[61].z; # r1 += d\n" +
+ "RCP R1.x, R1.x; # r1 = 1 / r1\n" +
+ "MUL R1.x, R1.x, c[61].w; # r1 *= d + 1\n" +
+ "\n" +
+ "# distort y\n" +
+ "RCP R1.y, R1.y; # r1 = 1 / r1\n" +
+ "ADD R1.y, R1.y, c[61].z; # r1 += d\n" +
+ "RCP R1.y, R1.y; # r1 = 1 / r1\n" +
+ "MUL R1.y, R1.y, c[61].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, c[4], v[NRML] ; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R2.y, c[5], v[NRML] ;\n" +
+ "DP3 R2.z, c[6], v[NRML] ;\n" +
+ "DP3 R3, c[32], R2 ; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R3, c[35] ; # col = ldotn * diffuse\n" +
+ "\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "MOV o[HPOS], R1;\n" +
+ "\n" +
+ "END",
+
+ //
+ // Spherize
+ //
+ "!!VP1.0\n" +
+ "# Spherical fish-eye distortion\n" +
+ "# in clip space\n" +
+ "DP4 R0.x, c[0], v[OPOS];\n" +
+ "DP4 R0.y, c[1], v[OPOS];\n" +
+ "DP4 R0.z, c[2], v[OPOS];\n" +
+ "DP4 R0.w, c[3], v[OPOS];\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, c[64].y; # r1.x = min(r1.x, 1.0)\n" +
+ "\n" +
+ "# remap based on: f(x) = sqrt(1-x^2)\n" +
+ "ADD R1.x, c[64].y, -R1.x;\n" +
+ "MAD R1.x, -R1.x, R1.x, c[64].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, c[4], v[NRML]; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R2.y, c[5], v[NRML];\n" +
+ "DP3 R2.z, c[6], v[NRML];\n" +
+ "DP3 R3, c[32], R2 ; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R3, c[35] ; # col = ldotn * diffuse\n" +
+ "\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "MOV o[HPOS], R0;\n" +
+ "\n" +
+ "END",
+
+ //
+ // Ripple
+ //
+ "!!VP1.0\n" +
+ "# Ripple distortion\n" +
+ "DP4 R0.x, c[0], v[OPOS];\n" +
+ "DP4 R0.y, c[1], v[OPOS];\n" +
+ "DP4 R0.z, c[2], v[OPOS];\n" +
+ "DP4 R0.w, c[3], v[OPOS];\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" +
+ "RCP R1.x, R1.x; " +
+ "\n" +
+ "MUL R1.x, R1.x, c[61].x; # wave frequency\n" +
+ "ADD R1.x, R1.x, c[60].x; # phase animation\n" +
+ "\n" +
+ "# reduce to period of 2*PI\n" +
+ "MUL R2, R1.x, c[62].x; # R2 = R1 / 2.0 * PI\n" +
+ "EXP R4, R2.x; # R4.y = R2.x - floor(R2.x)\n" +
+ "MUL R1.x, R4.y, c[62].y;\n" +
+ "\n" +
+ "# offset to -PI - PI\n" +
+ "ADD R1.x, R1.x, -c[62].z;\n" +
+ "\n" +
+ "# R3.x = sin(R1.x)\n" +
+ "MUL R2, R1.x, R1.x;\n" +
+ "MAD R3, -R2, c[63].w, c[63].z;\n" +
+ "MAD R3, R3, -R2, c[63].y;\n" +
+ "MAD R3, R3, -R2, c[63].x;\n" +
+ "MUL R3, R3, R1.x;\n" +
+ "\n" +
+ "MUL R3.x, R3.x, c[61].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, c[4], v[NRML]; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R2.y, c[5], v[NRML];\n" +
+ "DP3 R2.z, c[6], v[NRML];\n" +
+ "DP3 R3, c[32], R2; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R3, c[35]; # col = ldotn * diffuse\n" +
+ "\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "MOV o[HPOS], R0;\n" +
+ "\n" +
+ "END",
+
+ //
+ // Twist
+ //
+ "!!VP1.0 # Twist\n" +
+ "MOV R0, v[OPOS];\n" +
+ "\n" +
+ "MUL R1.x, R0.x, c[61].x; # frequency\n" +
+ "\n" +
+ "# calculate sin(angle) and cos(angle)\n" +
+ "ADD R1.y, R1.x, -c[62].w; # R1.y = R1.x + PI/2.0\n" +
+ "\n" +
+ "# reduce to period of 2*PI\n" +
+ "MUL R2, R1, c[62].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, c[62].y, -c[62].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, c[63].w, c[63].z;\n" +
+ "MAD R4, R4, -R3, c[63].y;\n" +
+ "MAD R4, R4, -R3, c[63].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 o[HPOS].x, c[0], R1; # object x MVP -> clip\n" +
+ "DP4 o[HPOS].y, c[1], R1;\n" +
+ "DP4 o[HPOS].z, c[2], R1;\n" +
+ "DP4 o[HPOS].w, c[3], R1;\n" +
+ "\n" +
+ "# rotate normal\n" +
+ "MOV R2, v[NRML];\n" +
+ "MUL R2.y, v[NRML].y, R4.y;\n" +
+ "MAD R2.y, v[NRML].z, -R4.x, R2.y; # ny = y*cos(a) - z*sin(a)\n" +
+ "\n" +
+ "MUL R2.z, v[NRML].y, R4.x;\n" +
+ "MAD R2.z, v[NRML].z, R4.y, R2.z; # nz = y*sin(a) + z*cos(a)\n" +
+ "\n" +
+ "# diffuse lighting\n" +
+ "DP3 R1.x, c[4], R2; # normal x MV-1T -> lighting normal\n" +
+ "DP3 R1.y, c[5], R2;\n" +
+ "DP3 R1.z, c[6], R2;\n" +
+ "\n" +
+ "DP3 R3, c[32], R1; # light position DOT normal\n" +
+ "MUL o[COL0].xyz, R3, c[35]; # col = ldotn * diffuse\n" +
+ "\n" +
+ "MOV o[TEX0], v[TEX0];\n" +
+ "\n" +
+ "END"
+ };
+
+ private void runExit() {
+ quit = true;
+ // 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();
+ }
+}