aboutsummaryrefslogtreecommitdiffstats
path: root/demos/HodglimsNeHe/Lesson10.java
diff options
context:
space:
mode:
Diffstat (limited to 'demos/HodglimsNeHe/Lesson10.java')
-rw-r--r--demos/HodglimsNeHe/Lesson10.java640
1 files changed, 640 insertions, 0 deletions
diff --git a/demos/HodglimsNeHe/Lesson10.java b/demos/HodglimsNeHe/Lesson10.java
new file mode 100644
index 0000000..af009be
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson10.java
@@ -0,0 +1,640 @@
+/**
+ * Lesson10.java
+ *
+ * Author: Mattias Ekstrand
+ * Date: 09/04/2001
+ *
+ * Port of the NeHe OpenGL Tutorial (Lesson 10: "Moving Bitmaps In 3D Space")
+ * to Java using the GL4Java interface to OpenGL. Much of the code is reused
+ * from Darren Hodges port of Lession 9. :)
+ *
+ */
+
+
+import java.applet.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.util.StringTokenizer;
+
+//GL4Java classes
+import gl4java.GLContext;
+import gl4java.awt.GLAnimCanvas;
+import gl4java.utils.textures.*;
+
+
+public class Lesson10 extends Applet
+{
+ //Our rendering canvas
+ //We are using GLAnimCanvas because we want the canvas
+ //to be constantly redrawn
+ renderCanvas canvas = null;
+
+
+ /**
+ * void init()
+ *
+ * Initialise the applet.
+ */
+
+ public void init()
+ {
+ //We will use BorderLayout to layout the applet components
+ setLayout(new BorderLayout());
+
+ //Create our canvas and add it to the center of the applet
+ canvas = new renderCanvas(getSize().width, getSize().height);
+ add("Center", canvas);
+ }
+
+
+ /**
+ * void start()
+ *
+ * Start the applet.
+ */
+ public void start()
+ {
+ //Start animating the canvas
+ canvas.start();
+ }
+
+
+ /**
+ * void stop()
+ *
+ * Stop the applet.
+ */
+ public void stop()
+ {
+ //Stop animating the canvas
+ canvas.stop();
+ }
+
+
+ /**
+ * void destroy()
+ *
+ * Destroy the applet.
+ */
+ public void destroy()
+ {
+ //Stop animating the canvas
+ canvas.stop();
+ //Destroy the canvas
+ canvas.destroy();
+ }
+
+
+
+ private class renderCanvas extends GLAnimCanvas implements KeyListener
+ {
+ boolean light = true; //Lighting ON/OFF
+ boolean lp = false; //L Pressed?
+ boolean fp = false; //F Pressed?
+ boolean blend = true; //Blending ON/OFF
+ boolean bp = false; //B Pressed?
+
+ final float piover180 = 0.0174532925f;
+ float heading;
+ float xpos;
+ float zpos;
+
+ float yrot = 0.0f; //Y Rotation
+ float walkbias = 0.0f;
+ float walkbiasangle = 0.0f;
+ float lookupdown = 0.0f;
+ float z = -8.0f; //Depth Into The Screen
+
+ //Ambient light
+ float[] LightAmbient = { 0.5f, 0.5f, 0.5f, 1.0f };
+
+ //Diffuse light
+ float[] LightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+ //Light position
+ float[] LightPosition = { 0.0f, 0.0f, 2.0f, 1.0f };
+
+ int filter = 0; //Which Filter To Use
+
+ int[] texture = new int[3]; //Storage for 3 textures
+
+ Sector sector1;
+
+
+ /**
+ * renderCanvas(int w, int h)
+ *
+ * Constructor.
+ */
+ public renderCanvas(int w, int h)
+ {
+ super(w, h);
+
+ //Registers this canvas to process keyboard events
+ addKeyListener(this);
+ }
+
+
+ /**
+ * void preInit()
+ *
+ * Called just BEFORE the GL-Context is created.
+ */
+ public void preInit()
+ {
+ //We want double buffering
+ doubleBuffer = true;
+ //But we dont want stereo view
+ stereoView = false;
+ }
+
+ void SetupWorld() {
+ float x, y, z, u, v;
+ int numtriangles;
+
+ try {
+ String line;
+
+ URL world = new URL(getCodeBase() + "data/world.txt");
+
+ DataInputStream dis = new DataInputStream(world.openStream());
+
+ while ((line = dis.readLine()) != null) {
+ if (line.trim().length() == 0 || line.trim().startsWith("//"))
+ continue;
+
+ if (line.startsWith("NUMPOLLIES")) {
+ int numTriangles;
+
+ numTriangles = Integer.parseInt(line.substring(line.indexOf("NUMPOLLIES") + "NUMPOLLIES".length() + 1));
+ sector1 = new Sector(numTriangles);
+
+ break;
+ }
+ }
+
+ for (int i = 0; i < sector1.numTriangles; i++) {
+ for (int vert = 0; vert < 3; vert++) {
+
+ while ((line = dis.readLine()) != null) {
+ if (line.trim().length() == 0 || line.trim().startsWith("//"))
+ continue;
+
+ break;
+ }
+
+ if (line != null) {
+ StringTokenizer st = new StringTokenizer(line, " ");
+
+ sector1.triangles[i].vertex[vert].x = Float.valueOf(st.nextToken()).floatValue();
+ sector1.triangles[i].vertex[vert].y = Float.valueOf(st.nextToken()).floatValue();
+ sector1.triangles[i].vertex[vert].z = Float.valueOf(st.nextToken()).floatValue();
+ sector1.triangles[i].vertex[vert].u = Float.valueOf(st.nextToken()).floatValue();
+ sector1.triangles[i].vertex[vert].v = Float.valueOf(st.nextToken()).floatValue();
+ }
+ }
+ }
+
+ dis.close();
+
+ } catch (MalformedURLException me) {
+ System.out.println("MalformedURLException: " + me);
+ } catch (IOException ioe) {
+ System.out.println("IOException: " + ioe);
+ }
+ }
+
+
+
+ /**
+ * void LoadGLTextures()
+ *
+ * Load textures.
+ */
+ public void LoadGLTextures()
+ {
+ PngTextureLoader texLoader = new PngTextureLoader(gl, glu);
+ texLoader.readTexture(getCodeBase(), "data/crate.png");
+
+ //Full Brightness, 50% Alpha
+ gl.glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+
+ //Blending Function For Translucency Based On Source Alpha Value
+ gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+ if(texLoader.isOk())
+ {
+ //Create Nearest Filtered Texture
+ gl.glGenTextures(3, texture);
+ gl.glBindTexture(GL_TEXTURE_2D, texture[0]);
+
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ gl.glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ 3,
+ texLoader.getImageWidth(),
+ texLoader.getImageHeight(),
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ texLoader.getTexture());
+
+ //Create Linear Filtered Texture
+ gl.glBindTexture(GL_TEXTURE_2D, texture[1]);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ gl.glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ 3,
+ texLoader.getImageWidth(),
+ texLoader.getImageHeight(),
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ texLoader.getTexture());
+
+
+ //Create MipMapped Texture (Only with GL4Java 2.1.2.1 and later!)
+ gl.glBindTexture(GL_TEXTURE_2D, texture[2]);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+
+ glu.gluBuild2DMipmaps(GL_TEXTURE_2D,
+ 3,
+ texLoader.getImageWidth(),
+ texLoader.getImageHeight(),
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ texLoader.getTexture());
+ }
+ }
+
+
+ /**
+ * void init()
+ *
+ * Called just AFTER the GL-Context is created.
+ */
+ public void init()
+ {
+ //Load The Texture(s)
+ LoadGLTextures();
+
+ //Enable Texture Mapping
+ gl.glEnable(GL_TEXTURE_2D);
+
+ //This Will Clear The Background Color To Black
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ //Enables Clearing Of The Depth Buffer
+ gl.glClearDepth(1.0);
+
+ //The Type Of Depth Test To Do
+ gl.glDepthFunc(GL_LESS);
+ //Enables Depth Testing
+ gl.glEnable(GL_DEPTH_TEST);
+
+ //Enables Smooth Color Shading
+ gl.glShadeModel(GL_SMOOTH);
+
+ //Select The Projection Matrix
+ gl.glMatrixMode(GL_PROJECTION);
+
+ //Reset The Projection Matrix
+ gl.glLoadIdentity();
+
+ //Calculate The Aspect Ratio Of The Window
+ glu.gluPerspective(45.0f, (float)getSize().width / (float)getSize().height, 0.1f, 100.0f);
+
+ //Select The Modelview Matrix
+ gl.glMatrixMode(GL_MODELVIEW);
+
+ //Lights
+ gl.glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
+ gl.glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
+ gl.glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
+
+ //Enable light
+ gl.glEnable(GL_LIGHT1);
+ gl.glEnable(GL_LIGHTING);
+
+ //Load world
+ SetupWorld();
+ }
+
+
+ /**
+ * void destroy()
+ *
+ * Destroy the canvas.
+ */
+ public void destroy()
+ {
+ //Destroy the GLContext
+ cvsDispose();
+ }
+
+
+ /**
+ * void reshape(int width, int height)
+ *
+ * Called after the first paint command.
+ */
+ public void reshape(int width, int height)
+ {
+ //Reset The Current Viewport And Perspective Transformation
+ gl.glViewport(0, 0, width, height);
+
+ //Select The Projection Matrix
+ gl.glMatrixMode(GL_PROJECTION);
+
+ //Reset The Projection Matrix
+ gl.glLoadIdentity();
+
+ //Calculate The Aspect Ratio Of The Window
+ glu.gluPerspective(45.0f, (float)getSize().width / (float)getSize().height, 0.1f, 100.0f);
+
+ //Select The Modelview Matrix
+ gl.glMatrixMode(GL_MODELVIEW);
+ }
+
+
+ /**
+ * void display()
+ *
+ * Draw to the canvas.
+ */
+ public void display()
+ {
+ //Ensure GL is initialised correctly
+ if (glj.gljMakeCurrent(true) == false)
+ return;
+
+ //Clear The Screen And The Depth Buffer
+ gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ //Reset The View
+ gl.glLoadIdentity();
+
+ float x, y, z, u, v;
+ float xtrans = -xpos;
+ float ztrans = -zpos;
+ float ytrans = -walkbias-0.25f;
+ float sceneroty = 360.0f - yrot;
+
+ gl.glRotatef(lookupdown,1.0f,0,0);
+ gl.glRotatef(sceneroty,0,1.0f,0);
+
+ gl.glTranslatef(xtrans, ytrans, ztrans);
+ gl.glBindTexture(GL_TEXTURE_2D, texture[filter]);
+
+ // Process Each Triangle
+ for (int i = 0; i < sector1.numTriangles; i++) {
+ gl.glBegin(GL_TRIANGLES);
+ gl.glNormal3f( 0.0f, 0.0f, 1.0f);
+ x = sector1.triangles[i].vertex[0].x;
+ y = sector1.triangles[i].vertex[0].y;
+ z = sector1.triangles[i].vertex[0].z;
+ u = sector1.triangles[i].vertex[0].u;
+ v = sector1.triangles[i].vertex[0].v;
+ gl.glTexCoord2f(u,v); gl.glVertex3f(x,y,z);
+
+ x = sector1.triangles[i].vertex[1].x;
+ y = sector1.triangles[i].vertex[1].y;
+ z = sector1.triangles[i].vertex[1].z;
+ u = sector1.triangles[i].vertex[1].u;
+ v = sector1.triangles[i].vertex[1].v;
+ gl.glTexCoord2f(u,v); gl.glVertex3f(x,y,z);
+
+ x = sector1.triangles[i].vertex[2].x;
+ y = sector1.triangles[i].vertex[2].y;
+ z = sector1.triangles[i].vertex[2].z;
+ u = sector1.triangles[i].vertex[2].u;
+ v = sector1.triangles[i].vertex[2].v;
+ gl.glTexCoord2f(u,v); gl.glVertex3f(x,y,z);
+ gl.glEnd();
+ }
+
+ //Swap buffers
+ glj.gljSwap();
+ glj.gljFree();
+ }
+
+
+ /**
+ * void keyTyped(KeyEvent e)
+ *
+ * Invoked when a key has been typed. This event occurs when a key press is followed by a key release.
+ */
+ public void keyTyped(KeyEvent e)
+ {
+ }
+
+
+ /**
+ * void keyPressed(KeyEvent e)
+ *
+ * Invoked when a key has been pressed.
+ */
+ public void keyPressed(KeyEvent e)
+ {
+ switch(e.getKeyCode())
+ {
+ //Switch ON/OFF light when L is pressed
+ case KeyEvent.VK_L:
+ {
+ if(!lp)
+ {
+ lp = true;
+ //Toggle light
+ light = !light;
+
+ if(!light)
+ gl.glDisable(GL_LIGHTING);
+ else
+ gl.glEnable(GL_LIGHTING);
+ }
+
+ break;
+ }
+
+ //Switch filter when F is pressed
+ case KeyEvent.VK_F:
+ {
+ if(!fp)
+ {
+ fp = true;
+ //Change filter
+ filter += 1;
+ if(filter > 2)
+ filter = 0;
+ }
+
+ break;
+ }
+
+ //Switch blending when B is pressed
+ case KeyEvent.VK_B:
+ {
+ if(!bp)
+ {
+ bp = true;
+ //Toggle blending
+ blend = !blend;
+
+ if(blend)
+ {
+ gl.glEnable(GL_BLEND); //Turn Blending On
+ gl.glDisable(GL_DEPTH_TEST); //Turn Depth Testing Off
+ }
+ else
+ {
+ gl.glDisable(GL_BLEND); //Turn Blending Off
+ gl.glEnable(GL_DEPTH_TEST); //Turn Depth Testing On
+ }
+ }
+
+ break;
+ }
+
+ case KeyEvent.VK_PAGE_UP:
+ {
+ z -= 0.2f;
+ lookupdown-= 1.0f;
+
+ break;
+ }
+
+ case KeyEvent.VK_PAGE_DOWN:
+ {
+ z += 0.2f;
+ lookupdown+= 1.0f;
+
+ break;
+ }
+
+ case KeyEvent.VK_UP:
+ {
+ xpos -= (float)Math.sin(heading*piover180) * 0.05f;
+ zpos -= (float)Math.cos(heading*piover180) * 0.05f;
+ if (walkbiasangle >= 359.0f)
+ {
+ walkbiasangle = 0.0f;
+ }
+ else
+ {
+ walkbiasangle+= 10;
+ }
+ walkbias = (float)Math.sin(walkbiasangle * piover180)/20.0f;
+
+ break;
+ }
+
+ case KeyEvent.VK_DOWN:
+ {
+ xpos += (float)Math.sin(heading*piover180) * 0.05f;
+ zpos += (float)Math.cos(heading*piover180) * 0.05f;
+ if (walkbiasangle <= 1.0f)
+ {
+ walkbiasangle = 359.0f;
+ }
+ else
+ {
+ walkbiasangle-= 10;
+ }
+ walkbias = (float)Math.sin(walkbiasangle * piover180)/20.0f;
+
+ break;
+ }
+
+ //Increase Y rotation speed when user presses RIGHT
+ case KeyEvent.VK_RIGHT:
+ {
+ heading -= 1.0f;
+ yrot = heading;
+
+ break;
+ }
+
+ //Decrease Y rotation speed when user presses LEFT
+ case KeyEvent.VK_LEFT:
+ {
+ heading += 1.0f;
+ yrot = heading;
+
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * void keyReleased(KeyEvent e)
+ *
+ * Invoked when a key has been released.
+ */
+ public void keyReleased(KeyEvent e)
+ {
+ switch(e.getKeyCode())
+ {
+ //Key has been released
+ case KeyEvent.VK_L:
+ {
+ lp = false;
+ break;
+ }
+
+ //Key has been released
+ case KeyEvent.VK_F:
+ {
+ fp = false;
+ break;
+ }
+
+ //Key has been released
+ case KeyEvent.VK_B:
+ {
+ bp = false;
+ break;
+ }
+ }
+ }
+ }
+
+ public class Sector {
+ int numTriangles;
+ Triangle[] triangles;
+
+ public Sector (int numTriangles) {
+ this.numTriangles = numTriangles;
+ triangles = new Triangle[numTriangles];
+
+ for (int i = 0; i < numTriangles; i++)
+ triangles[i] = new Triangle();
+ }
+ }
+
+ public class Triangle {
+ Vertex[] vertex;
+
+ public Triangle () {
+ vertex = new Vertex[3];
+
+ for (int i = 0; i < 3; i++)
+ vertex[i] = new Vertex();
+ }
+ }
+
+ public class Vertex {
+ float x, y, z; // 3D Coordinates
+ float u, v; // Texture Coordinates
+
+ public Vertex () {
+ }
+ }
+}