/*
* 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.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 javax.media.opengl.util.BufferUtil;
import javax.swing.JOptionPane;
/**
Simple space-warp/distortion vertex program demo
(Press the space bar to switch through programs)
sgreen@nvidia.com 9/2000, based on Cass's vtxprog_silhouette
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 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();
}
}