From 880653d31a8f1ff8384fdbc75b84934bceecfdb8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 18 Nov 2000 06:43:49 +0000 Subject: Initial revision --- demos/RonsDemos/shadowvol.java | 458 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 demos/RonsDemos/shadowvol.java (limited to 'demos/RonsDemos/shadowvol.java') diff --git a/demos/RonsDemos/shadowvol.java b/demos/RonsDemos/shadowvol.java new file mode 100644 index 0000000..f40f20b --- /dev/null +++ b/demos/RonsDemos/shadowvol.java @@ -0,0 +1,458 @@ +/** + * @(#) shadowvol.java + * @(#) author: Tom McReynolds, SGI (converted to Java by Ron Cemer) + */ + +/* Shadows: Shadow maps */ +/* Demonstrate shadow volumes */ + +import java.applet.*; +import java.awt.*; +import java.awt.event.*; +import java.lang.*; +import java.util.*; +import java.io.*; +import java.util.*; +import gl4java.GLContext; +import gl4java.awt.GLCanvas; + +public class shadowvol extends Applet +{ + private static final int SPHERE = 1, CONE = 2, LIGHT = 3, SHADOWVOL = 4; + private static final int X = 0, Y = 1, Z = 2; + private static final int NONE = 0, NOLIGHT = 1, VOLUME = 2, SHADOW = 3; + private static final int TEXDIM = 256; + + shadowvolCanvas canvas = null; + + + /* Initialize the applet */ + + + public void init() + { + Dimension d = getSize(); + setLayout(new BorderLayout()); + canvas = new shadowvolCanvas(d.width, d.height); + add("Center", canvas); + } + + + /* Start the applet */ + + + public void start() + { + } + + + /* Stop the applet */ + + + public void stop() + { + } + + + /* Destroy the applet */ + + + public void destroy() + { + canvas.cvsDispose(); + } + + private class ShadObj + { + float[] vertices; + float[] normal; + int n; + } + + + /* Local GLCanvas extension class */ + + + private class shadowvolCanvas extends GLCanvas implements MouseListener + { + private float shadVerts[] = + { + 30.0f, 30.0f, -350.0f, + 60.0f, 20.0f, -340.0f, + 40.0f, 40.0f, -400.0f + }; + private float shadNormal[] = + { + 1.0f, 10.f, 1.0f + }; + private float leftwallshadow[] = new float[16]; + private float floorshadow[] = new float[16]; + private float lightpos[] = { 50.0f, 50.0f, -340.0f, 1.0f }; + private ShadObj shadower = new ShadObj(); + private int rendermode = SHADOW; + + public shadowvolCanvas(int w, int h) + { + super(w, h); + GLContext.gljNativeDebug = false; + GLContext.gljClassDebug = false; + } + + public void preInit() + { + doubleBuffer = true; + stereoView = false; + stencilBits = 3; + } + + public void init() + { + System.out.println("init(): " + this); + reshape(getSize().width, getSize().height); + + byte tex[]; + int sphere, cone, base; + float sphere_mat[] = {1.0f, 0.5f, 0.0f, 1.0f}; + float cone_mat[] = {0.0f, 0.5f, 1.0f, 1.0f}; + + /* turn on features */ + gl.glEnable(GL_DEPTH_TEST); + gl.glEnable(GL_LIGHTING); + gl.glEnable(GL_LIGHT0); + gl.glEnable(GL_CULL_FACE); + + /* place light 0 in the right place */ + gl.glLightfv(GL_LIGHT0, GL_POSITION, lightpos); + + /* remove back faces to speed things up */ + gl.glCullFace(GL_BACK); + + gl.glTexParameteri + (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + /* make display lists for sphere and cone; for efficiency */ + + gl.glNewList(SPHERE, GL_COMPILE); + sphere = glu.gluNewQuadric(); + gl.glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat); + glu.gluSphere(sphere, 20.0f, 20, 20); + glu.gluDeleteQuadric(sphere); + gl.glEndList(); + + gl.glNewList(CONE, GL_COMPILE); + cone = glu.gluNewQuadric(); + base = glu.gluNewQuadric(); + gl.glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat); + gl.glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + glu.gluDisk(base, 0., 20., 20, 1); + glu.gluCylinder(cone, 20., 0., 60., 20, 20); + glu.gluDeleteQuadric(cone); + glu.gluDeleteQuadric(base); + gl.glEndList(); + + gl.glNewList(LIGHT, GL_COMPILE); + sphere = glu.gluNewQuadric(); + gl.glPushMatrix(); + gl.glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]); + gl.glDisable(GL_LIGHTING); + gl.glColor3f(0.9f, 0.9f, 0.6f); + glu.gluSphere(sphere, 5.0f, 20, 20); + gl.glEnable(GL_LIGHTING); + gl.glPopMatrix(); + glu.gluDeleteQuadric(sphere); + gl.glEndList(); + + /* load pattern for current 2d texture */ + tex = make_texture(TEXDIM, TEXDIM); + gl.glTexImage2D + (GL_TEXTURE_2D, + 0, + 1, + TEXDIM, + TEXDIM, + 0, + GL_RED, + GL_UNSIGNED_BYTE, + tex); + tex = null; + + shadower.vertices = shadVerts; + shadower.normal = shadNormal; + shadower.n = shadVerts.length/3; + + makeShadowVolume(shadower, lightpos, 10.f, SHADOWVOL); + + glj.gljCheckGL(); + + addMouseListener(this); + } + + public void cvsDispose() + { + System.out.println("destroy(): " + this); + removeMouseListener(this); + super.cvsDispose(); + } + + public void reshape(int width, int height) + { + gl.glViewport(0,0,width,height); + /* draw a perspective scene */ + gl.glMatrixMode(GL_PROJECTION); + gl.glFrustum(-100.0f, 100.0f, -100.0f, 100.0f, 320.0f, 640.0f); + gl.glMatrixMode(GL_MODELVIEW); + } + + public void display() + { + if (glj.gljMakeCurrent() == false) return; + + + + + gl.glClear + (GL_COLOR_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT); + switch (rendermode) + { + case NONE: + render(shadower); + break; + case NOLIGHT: + gl.glDisable(GL_LIGHT0); + render(shadower); + gl.glEnable(GL_LIGHT0); + break; + case VOLUME: + render(shadower); + gl.glCallList(SHADOWVOL); + break; + case SHADOW: + gl.glColorMask(false, false, false, false); + render(shadower); /* render scene in depth buffer */ + gl.glEnable(GL_STENCIL_TEST); + gl.glDepthMask(false); + gl.glStencilFunc(GL_ALWAYS, 0, 0); + gl.glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + gl.glCullFace(GL_BACK); /* increment using front face of shadow volume */ + gl.glCallList(SHADOWVOL); + gl.glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); + gl.glCullFace(GL_FRONT); /* increment using front face of shadow volume */ + gl.glCallList(SHADOWVOL); + gl.glDepthMask(true); + gl.glColorMask(true, true, true, true); + gl.glCullFace(GL_BACK); + gl.glDepthFunc(GL_LEQUAL); + gl.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + gl.glStencilFunc(GL_EQUAL, 1, 1); /* draw shadowed part */ + gl.glDisable(GL_LIGHT0); + render(shadower); + gl.glStencilFunc(GL_EQUAL, 0, 1); /* draw lit part */ + gl.glEnable(GL_LIGHT0); + render(shadower); + gl.glDepthFunc(GL_LESS); + gl.glDisable(GL_STENCIL_TEST); + break; + } + + glj.gljSwap(); + glj.gljCheckGL(); + glj.gljFree(); + } + + // Methods required for the implementation of MouseListener + public void mouseEntered( MouseEvent evt ) + { + } + + public void mouseExited( MouseEvent evt ) + { + } + + public void mousePressed( MouseEvent evt ) + { + rendermode++; + if (rendermode > SHADOW) rendermode = NONE; + repaint(); + } + + public void mouseReleased( MouseEvent evt ) + { + } + + public void mouseClicked( MouseEvent evt ) + { + } + + private byte[] make_texture(int maxs, int maxt) + { + byte texture[] = new byte[maxs*maxt]; + for (int t = 0; t < maxt; t++) + { + for (int s = 0; s < maxs; s++) + { + texture[s + maxs * t] = + ( (((s >> 4) & 0x1) != 0) ^ (((t >> 4) & 0x1) != 0) ) ? + (byte)0xff : + (byte)0; + } + } + return texture; + } + + /* simple way to extend a point to build shadow volume */ + private void extend(float newvertex[], float light[], float vertex[], float t) + { + float delta[] = new float[3]; + + delta[X] = vertex[X] - light[X]; + delta[Y] = vertex[Y] - light[Y]; + delta[Z] = vertex[Z] - light[Z]; + + newvertex[X] = light[X] + delta[X] * t; + newvertex[Y] = light[Y] + delta[Y] * t; + newvertex[Z] = light[Z] + delta[Z] * t; + } + + /* Create a shadow volume in a display list */ + /* XXX light should have 4 compoents */ + void makeShadowVolume(ShadObj shadower, float light[], float t, int dlist) + { + float v[] = new float[3], newv[] = new float[3]; + int j; + + gl.glNewList(dlist, GL_COMPILE); + gl.glDisable(GL_LIGHTING); + gl.glBegin(GL_QUADS); + /* for debugging */ + gl.glColor3f(0.2f, 0.8f, 0.4f); + for (int i = 0; i < shadower.n; i++) + { + j = ((i + 1) % shadower.n); + v[0] = shadower.vertices[i * 3]; + v[1] = shadower.vertices[(i * 3) + 1]; + v[2] = shadower.vertices[(i * 3) + 2]; + gl.glVertex3fv(v); + extend(newv, light, v, t); + gl.glVertex3fv(newv); + v[0] = shadower.vertices[j * 3]; + v[1] = shadower.vertices[(j * 3) + 1]; + v[2] = shadower.vertices[(j * 3) + 2]; + extend(newv, light, v, t); + gl.glVertex3fv(newv); + gl.glVertex3fv(v); + } + gl.glEnd(); + gl.glEnable(GL_LIGHTING); + gl.glEndList(); + } + + private void sphere() + { + gl.glPushMatrix(); + gl.glTranslatef(60.0f, -50.0f, -360.0f); + gl.glCallList(SPHERE); + gl.glPopMatrix(); + } + + private void cone() + { + gl.glPushMatrix(); + gl.glTranslatef(-40.0f, -40.0f, -400.0f); + gl.glCallList(CONE); + gl.glPopMatrix(); + } + + /* render while jittering the shadows */ + private void render(ShadObj obj) + { + float shad_mat[] = {10.f, 0.1f, 0.1f, 1.0f}; + float v[] = new float[3]; + /* material properties for objects in scene */ + float wall_mat[] = {1.0f, 1.0f, 1.0f, 1.0f}; + /* Note: wall vertices are ordered so they are all + front facing this lets me do back face culling to + speed things up. */ + + gl.glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat); + + /* floor */ + /* make the floor textured */ + gl.glEnable(GL_TEXTURE_2D); + + /* Since we want to turn texturing on for floor only, we have + to make floor a separate glBegin()/glEnd() sequence. You + can't turn texturing on and off between begin and end calls */ + gl.glBegin(GL_QUADS); + gl.glNormal3f(0.0f, 1.0f, 0.0f); + gl.glTexCoord2i(0, 0); + gl.glVertex3f(-100.0f, -100.0f, -320.0f); + gl.glTexCoord2i(1, 0); + gl.glVertex3f(100.0f, -100.0f, -320.0f); + gl.glTexCoord2i(1, 1); + gl.glVertex3f(100.0f, -100.0f, -520.0f); + gl.glTexCoord2i(0, 1); + gl.glVertex3f(-100.0f, -100.0f, -520.0f); + gl.glEnd(); + + gl.glDisable(GL_TEXTURE_2D); + + /* walls */ + + gl.glBegin(GL_QUADS); + /* left wall */ + gl.glNormal3f(1.0f, 0.0f, 0.0f); + gl.glVertex3f(-100.0f, -100.0f, -320.0f); + gl.glVertex3f(-100.0f, -100.0f, -520.0f); + gl.glVertex3f(-100.0f, 100.0f, -520.0f); + gl.glVertex3f(-100.0f, 100.0f, -320.0f); + + /* right wall */ + gl.glNormal3f(-1.0f, 0.0f, 0.0f); + gl.glVertex3f(100.0f, -100.0f, -320.0f); + gl.glVertex3f(100.0f, 100.0f, -320.0f); + gl.glVertex3f(100.0f, 100.0f, -520.0f); + gl.glVertex3f(100.0f, -100.0f, -520.0f); + + /* ceiling */ + gl.glNormal3f(0.0f, -1.0f, 0.0f); + gl.glVertex3f(-100.0f, 100.0f, -320.0f); + gl.glVertex3f(-100.0f, 100.0f, -520.0f); + gl.glVertex3f(100.0f, 100.0f, -520.0f); + gl.glVertex3f(100.0f, 100.0f, -320.0f); + + /* back wall */ + gl.glNormal3f(0.0f, 0.0f, 1.0f); + gl.glVertex3f(-100.0f, -100.0f, -520.0f); + gl.glVertex3f(100.0f, -100.0f, -520.0f); + gl.glVertex3f(100.0f, 100.0f, -520.0f); + gl.glVertex3f(-100.0f, 100.0f, -520.0f); + + gl.glEnd(); + + cone(); + + sphere(); + + gl.glCallList(LIGHT); + + /* draw shadowing object */ + gl.glMaterialfv + (GL_FRONT_AND_BACK, + GL_AMBIENT_AND_DIFFUSE, + shad_mat); + gl.glBegin(GL_POLYGON); + gl.glNormal3fv(obj.normal); + for (int i = 0; i < obj.n; i++) + { + int j = i * 3; + v[0] = obj.vertices[j]; + v[1] = obj.vertices[j+1]; + v[2] = obj.vertices[j+2]; + gl.glVertex3fv(v); + } + gl.glEnd(); + } + } +} -- cgit v1.2.3