aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/HodglimsNeHe/Lesson10.html39
-rw-r--r--demos/HodglimsNeHe/Lesson10.java640
-rw-r--r--demos/HodglimsNeHe/Lesson10_plugin13.html79
-rw-r--r--demos/HodglimsNeHe/Lesson19.html44
-rw-r--r--demos/HodglimsNeHe/Lesson19.java420
-rw-r--r--demos/HodglimsNeHe/Lesson19_plugin13.html75
-rw-r--r--demos/HodglimsNeHe/data/world.txt160
-rw-r--r--demos/SwingDemos/factoryhack.txt16
-rw-r--r--gl4java/swing/GLJPanel.java-directtest948
-rw-r--r--gl4java/swing/GLJPanel.java-graphicbuffer1062
10 files changed, 3483 insertions, 0 deletions
diff --git a/demos/HodglimsNeHe/Lesson10.html b/demos/HodglimsNeHe/Lesson10.html
new file mode 100644
index 0000000..ea9bce2
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson10.html
@@ -0,0 +1,39 @@
+<HTML>
+<HEAD>
+<TITLE>Lesson10 Applet: Loading And Moving Through A 3D World</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+<CENTER>
+<P><FONT SIZE="+1">Loading And Moving Through A 3D World</FONT><BR>
+</P>
+<TABLE WIDTH="100%">
+<TR>
+<TD WIDTH="30%" ALIGN="LEFT" VALIGN="TOP">
+<P>
+<FONT SIZE="1" FACE="Verdana"><B><U>Keys</U></B></FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<B>PG_UP</B> - Look Up<BR>
+<B>PG_DOWN</B> - Look Down<BR>
+<B>UP</B> - Move Fwd<BR>
+<B>DOWN</B> - Move Bwd<BR>
+<B>LEFT</B> - Move Left<BR>
+<B>RIGHT</B> - Move Right<BR>
+</FONT>
+</P>
+<P><FONT SIZE="1" FACE="Verdana"><B>Note:</B> You must click inside the applet window before using these keys.</FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<A HREF="index.html">Go back</A>
+</FONT>
+</P>
+</TD>
+<TD WIDTH="70%" ALIGN="CENTER" VALIGN="TOP">
+<APPLET CODE="Lesson10.class" WIDTH="400" HEIGHT="400">
+</APPLET>
+</TD>
+</TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
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 () {
+ }
+ }
+}
diff --git a/demos/HodglimsNeHe/Lesson10_plugin13.html b/demos/HodglimsNeHe/Lesson10_plugin13.html
new file mode 100644
index 0000000..b83fb68
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson10_plugin13.html
@@ -0,0 +1,79 @@
+<HTML>
+<HEAD>
+<TITLE>Lesson10 Applet: Loading And Moving Through A 3D World</TITLE>
+<STYLE TYPE="text/css">
+<!--
+A:link { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:visited { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:active { color: Yellow; TEXT-DECORATION: none }
+A:hover { color: Yellow; TEXT-DECORATION: none }
+-->
+</STYLE>
+</HEAD>
+<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#e6e6ff">
+<CENTER>
+<P>
+<FONT SIZE="+1">Loading And Moving Through A 3D World</FONT><BR>
+</P>
+<TABLE WIDTH="100%">
+<TR>
+<TD WIDTH="30%" ALIGN="LEFT" VALIGN="TOP">
+<P>
+<FONT SIZE="1" FACE="Verdana"><B><U>Keys</U></B></FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<B>PG_UP</B> - Look Up<BR>
+<B>PG_DOWN</B> - Look Down<BR>
+<B>UP</B> - Move Fwd<BR>
+<B>DOWN</B> - Move Bwd<BR>
+<B>LEFT</B> - Move Left<BR>
+<B>RIGHT</B> - Move Right<BR>
+</FONT>
+</P>
+<P><FONT SIZE="1" FACE="Verdana"><B>Note:</B> You must click inside the applet window before using these keys.</FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<A HREF="index.html">Go back</A>
+</FONT>
+</P>
+</TD>
+<TD WIDTH="70%" ALIGN="CENTER" VALIGN="TOP">
+<!--"CONVERTED_APPLET"-->
+<!-- CONVERTER VERSION 1.3 -->
+<SCRIPT LANGUAGE="JavaScript"><!--
+ var _info = navigator.userAgent; var _ns = false;
+ var _ie = (_info.indexOf("MSIE") > 0 && _info.indexOf("Win") > 0 && _info.indexOf("Windows 3.1") < 0);
+//--></SCRIPT>
+<COMMENT><SCRIPT LANGUAGE="JavaScript1.1"><!--
+ var _ns = (navigator.appName.indexOf("Netscape") >= 0 && ((_info.indexOf("Win") > 0 && _info.indexOf("Win16") < 0 && java.lang.System.getProperty("os.version").indexOf("3.5") < 0) || (_info.indexOf("Sun") > 0) || (_info.indexOf("Linux") > 0)));
+//--></SCRIPT></COMMENT>
+
+<SCRIPT LANGUAGE="JavaScript"><!--
+ if (_ie == true) document.writeln('<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" WIDTH = "400" HEIGHT = "400" codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0"><NOEMBED><XMP>');
+ else if (_ns == true) document.writeln('<EMBED type="application/x-java-applet;version=1.3" CODE = "Lesson10.class" WIDTH = "400" HEIGHT = "400" scriptable=false pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html"><NOEMBED><XMP>');
+//--></SCRIPT>
+<APPLET CODE = "Lesson10.class" WIDTH = "400" HEIGHT = "400"></XMP>
+<PARAM NAME = CODE VALUE = "Lesson10.class" >
+
+<PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
+<PARAM NAME="scriptable" VALUE="false">
+
+</APPLET>
+
+</NOEMBED></EMBED></OBJECT>
+
+
+<!--
+<APPLET CODE = "Lesson10.class" WIDTH = "400" HEIGHT = "400">
+
+
+</APPLET>
+-->
+<!--"END_CONVERTED_APPLET"-->
+
+</TD>
+</TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
diff --git a/demos/HodglimsNeHe/Lesson19.html b/demos/HodglimsNeHe/Lesson19.html
new file mode 100644
index 0000000..8bf9be2
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson19.html
@@ -0,0 +1,44 @@
+<HTML>
+<HEAD>
+<TITLE>Lesson19 Applet: Particle Engine Using Triangle Strips</TITLE>
+<STYLE TYPE="text/css">
+<!--
+A:link { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:visited { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:active { color: Yellow; TEXT-DECORATION: none }
+A:hover { color: Yellow; TEXT-DECORATION: none }
+-->
+</STYLE>
+</HEAD>
+<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#e6e6ff">
+<CENTER>
+<P>
+<FONT SIZE="+1">Particle Engine Using Triangle Strips</FONT><BR>
+</P>
+<TABLE WIDTH="100%">
+<TR>
+<TD WIDTH="30%" ALIGN="LEFT" VALIGN="TOP">
+<P>
+<FONT SIZE="1" FACE="Verdana"><B><U>Keys</U></B></FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<B>PG_UP</B> - Zoom out<BR>
+<B>PG_DOWN</B> - Zoom in<BR>
+</FONT>
+</P>
+<P><FONT SIZE="1" FACE="Verdana"><B>Note:</B> You must click inside the applet window before using these keys.</FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<A HREF="index.html">Go back</A>
+</FONT>
+</P>
+</TD>
+<TD WIDTH="70%" ALIGN="CENTER" VALIGN="TOP">
+<APPLET CODE="Lesson19.class" WIDTH="400" HEIGHT="400">
+</APPLET>
+</TD>
+</TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
diff --git a/demos/HodglimsNeHe/Lesson19.java b/demos/HodglimsNeHe/Lesson19.java
new file mode 100644
index 0000000..85828e3
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson19.java
@@ -0,0 +1,420 @@
+/**
+ * Lesson19.java
+ *
+ * Author: Mattias Ekstrand
+ * Date: 18/04/2001
+ *
+ * Port of the NeHe OpenGL Tutorial (Lesson 19: "Particle Engine Using Triangle Strips")
+ * 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.*;
+
+//GL4Java classes
+import gl4java.GLContext;
+import gl4java.awt.GLAnimCanvas;
+import gl4java.utils.textures.*;
+
+
+public class Lesson19 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();
+ }
+
+
+
+ static final float[][] colors = { // Rainbow Of Colors
+ {1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
+ {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
+ {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
+ };
+
+ private class renderCanvas extends GLAnimCanvas implements KeyListener {
+ static final int RAND_MAX = 32767;
+ static final int MAX_PARTICLES = 500;
+
+ boolean rainbow = true; // Rainbow Mode?
+ boolean sp = false; //Spacebar Pressed?
+ boolean rp = false; // Return Key Pressed?
+
+ float slowdown=2.0f; // Slow Down Particles
+ float xspeed; // Base X Speed (To Allow Keyboard Direction Of Tail)
+ float yspeed; // Base Y Speed (To Allow Keyboard Direction Of Tail)
+ float zoom=-40.0f; // Used To Zoom Out
+
+ int col; // Current Color Selection
+ int delay; // Rainbow Effect Delay
+ int[] texture = new int[1]; // Storage For Our Particle Texture
+
+ Particle[] particles = new Particle[MAX_PARTICLES]; // Particle Array (Room For Particle Info)
+
+
+ public renderCanvas(int w, int h) {
+ super(w, h);
+
+ //Registers this canvas to process keyboard events
+ addKeyListener(this);
+ }
+
+ public void preInit() {
+ //We want double buffering
+ doubleBuffer = true;
+ //But we dont want stereo view
+ stereoView = false;
+ }
+
+ public float rand() {
+ return ((float) Math.random()*RAND_MAX);
+ }
+
+ public void LoadTextures() {
+ PngTextureLoader texLoader=new PngTextureLoader(gl, glu);
+
+ texLoader.readTexture(getCodeBase(), "data/star.png");
+
+ if(texLoader.isOk()) {
+ gl.glGenTextures(1, texture);
+
+ //Create Linear Filtered Texture
+ gl.glBindTexture(GL_TEXTURE_2D, texture[0]);
+ 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());
+ }
+ }
+
+ public void init() {
+ LoadTextures();
+ gl.glShadeModel(GL_SMOOTH); //Enables Smooth Color Shading
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //This Will Clear The Background Color To Black
+ gl.glClearDepth(1.0f); //Enables Clearing Of The Depth Buffer
+ gl.glDisable(GL_DEPTH_TEST); //Disables Depth Testing
+ gl.glEnable(GL_BLEND); //Enable Blending
+ gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Type Of Blending To Perform
+ gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Really Nice Perspective Calculations
+ gl.glHint(GL_POINT_SMOOTH_HINT,GL_NICEST); // Really Nice Point Smoothing
+ gl.glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
+ gl.glBindTexture(GL_TEXTURE_2D,texture[0]); // Select Our Texture
+
+ for (int i=0; i < MAX_PARTICLES; i++) { // Initials All The Textures
+ particles[i] = new Particle();
+ particles[i].active = true; // Make All The Particles Active
+ particles[i].life = 1.0f; // Give All The Particles Full Life
+
+ particles[i].fade = rand()%100/1000.0f+0.003f; // Random Fade Speed
+
+ particles[i].r=colors[i%12][0]; // Select Red Rainbow Color
+ particles[i].g=colors[i%12][1]; // Select Green Rainbow Color
+ particles[i].b=colors[i%12][2]; // Select Blue Rainbow Color
+
+ particles[i].xi=((rand()%50)-26.0f)*10.0f; // Random Speed On X Axis
+ particles[i].yi=((rand()%50)-25.0f)*10.0f; // Random Speed On Y Axis
+ particles[i].zi=((rand()%50)-25.0f)*10.0f; // Random Speed On Z Axis
+
+ particles[i].xg=0.0f; // Set Horizontal Pull To Zero
+ particles[i].yg=-0.8f; // Set Vertical Pull Downward
+ particles[i].zg=0.0f;
+ }
+ }
+
+ public void destroy() {
+ //Destroy the GLContext
+ cvsDispose();
+ }
+
+ 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, getSize().width/(float)getSize().height, 0.1f, 200.0f);
+ //Select The Modelview Matrix
+ gl.glMatrixMode(GL_MODELVIEW);
+ }
+
+ 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();
+
+ //Select texture
+ gl.glBindTexture(GL_TEXTURE_2D, texture[0]);
+
+ for (int i=0; i < MAX_PARTICLES; i++) { // i Through All The Particles
+
+ if (particles[i].active) { // If The Particle Is Active
+
+ float x=particles[i].x; // Grab Our Particle X Position
+ float y=particles[i].y; // Grab Our Particle Y Position
+ float z=particles[i].z+zoom; // Particle Z Pos + Zoom
+
+ // Draw The Particle Using Our RGB Values, Fade The Particle Based On It's Life
+ gl.glColor4f(particles[i].r,particles[i].g,particles[i].b,particles[i].life);
+
+ gl.glBegin(GL_TRIANGLE_STRIP); // Build Quad From A Triangle Strip
+ gl.glTexCoord2d(1,1); gl.glVertex3f(x+0.5f,y+0.5f,z); // Top Right
+ gl.glTexCoord2d(0,1); gl.glVertex3f(x-0.5f,y+0.5f,z); // Top Left
+ gl.glTexCoord2d(1,0); gl.glVertex3f(x+0.5f,y-0.5f,z); // Bottom Right
+ gl.glTexCoord2d(0,0); gl.glVertex3f(x-0.5f,y-0.5f,z); // Bottom Left
+ gl.glEnd();
+
+ particles[i].x+=particles[i].xi/(slowdown*1000); // Move On The X Axis By X Speed
+ particles[i].y+=particles[i].yi/(slowdown*1000); // Move On The Y Axis By Y Speed
+ particles[i].z+=particles[i].zi/(slowdown*1000); // Move On The Z Axis By Z Speed
+
+ particles[i].xi+=particles[i].xg; // Take Pull On X Axis Into Account
+ particles[i].yi+=particles[i].yg; // Take Pull On Y Axis Into Account
+ particles[i].zi+=particles[i].zg; // Take Pull On Z Axis Into Account
+
+ particles[i].life-=particles[i].fade; // Reduce Particles Life By 'Fade'
+
+ if (particles[i].life < 0.0f) { // If Particle Is Burned Out
+ particles[i].life=1.0f; // Give It New Life
+ particles[i].fade=rand()%100/1000.0f+0.003f; // Random Fade Value
+
+ particles[i].x=0.0f; // Center On X Axis
+ particles[i].y=0.0f; // Center On Y Axis
+ particles[i].z=0.0f; // Center On Z Axis
+
+ particles[i].xi=xspeed+((rand()%60)-32.0f); // X Axis Speed And Direction
+ particles[i].yi=yspeed+((rand()%60)-30.0f); // Y Axis Speed And Direction
+ particles[i].zi=((rand()%60)-30.0f); // Z Axis Speed And Direction
+
+ particles[i].r=colors[col][0]; // Select Red From Color Table
+ particles[i].g=colors[col][1]; // Select Green From Color Table
+ particles[i].b=colors[col][2]; // Select Blue From Color Table
+ }
+
+ }
+
+
+ }
+
+ if (rainbow && delay > 25) {
+ delay=0;
+ col++;
+
+ if (col > 11)
+ col=0; // If Color Is To High Reset It
+ }
+
+ delay++;
+
+ //Swap buffers
+ glj.gljSwap();
+ glj.gljFree();
+ }
+
+ public void keyTyped(KeyEvent e) {
+ //We are not handling any keyboard events yet
+ }
+ public void keyPressed(KeyEvent e) {
+
+ switch(e.getKeyCode()) {
+ //Switch ON/OFF light when L is pressed
+
+ // If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwards
+ case KeyEvent.VK_UP:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (particles[i].yg < 1.5f)
+ particles[i].yg+=0.01f;
+ }
+ break;
+
+ // If Number Pad 2 And Y Gravity Is Greater Than 1.5 Increase Pull Downwards
+ case KeyEvent.VK_DOWN:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (particles[i].yg > 1.5f)
+ particles[i].yg-=0.01f;
+ }
+ break;
+
+ // If Number Pad 6 And X Gravity Is Less Than 1.5 Increase Pull Right
+ case KeyEvent.VK_RIGHT:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (particles[i].xg < 1.5f)
+ particles[i].xg+=0.01f;
+ }
+ break;
+
+ // If Number Pad 4 And X Gravity Is Greater Than 1.5 Increase Pull Left
+ case KeyEvent.VK_LEFT:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (particles[i].xg > 1.5f)
+ particles[i].xg-=0.01f;
+ }
+ break;
+
+ case KeyEvent.VK_TAB: // Tab Key Causes A Burst
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ particles[i].x=0.0f; // Center On X Axis
+ particles[i].y=0.0f; // Center On Y Axis
+ particles[i].z=0.0f; // Center On Z Axis
+ particles[i].xi=((rand()%50)-26.0f)*10.0f; // Random Speed On X Axis
+ particles[i].yi=((rand()%50)-25.0f)*10.0f; // Random Speed On Y Axis
+ particles[i].zi=((rand()%50)-25.0f)*10.0f; // Random Speed On Z Axis
+ }
+ break;
+
+ case KeyEvent.VK_ADD:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (slowdown > 1.0f)
+ slowdown-=0.01f; // Speed Up Particles
+ }
+ break;
+
+ case KeyEvent.VK_SUBTRACT:
+ for (int i = 0; i < MAX_PARTICLES; i++) {
+ if (slowdown < 1.0f)
+ slowdown+=0.01f; // Slow Up Particles
+ }
+ break;
+
+ case KeyEvent.VK_PAGE_UP:
+ zoom+=1.0f; // Zoom in
+ break;
+
+ case KeyEvent.VK_PAGE_DOWN:
+ zoom-=1.0f; // Zoom out
+ break;
+
+ case KeyEvent.VK_ENTER:
+ if (!rp) {
+ rp = true;
+ rainbow = !rainbow;
+ }
+ break;
+
+ case KeyEvent.VK_SPACE:
+ rainbow = false;
+ sp=true; // Set Flag Telling Us Space Is Pressed
+ delay=0; // Reset The Rainbow Color Cycling Delay
+ col++; // Change The Particle Color
+
+ if (col > 11)
+ col=0; // If Color Is To High Reset It
+
+ break;
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ switch(e.getKeyCode()) {
+ //Key has been released
+ case KeyEvent.VK_SPACE:
+ sp = false;
+ break;
+ //Key has been released
+ case KeyEvent.VK_ENTER:
+ rp = false;
+ break;
+ }
+ }
+ }
+
+ public class Particle {
+ boolean active; // Active (Yes/No)
+ float life; // Particle Life
+ float fade; // Fade Speed
+
+ float r; // Red Value
+ float g; // Green Value
+ float b; // Blue Value
+
+
+ float x; // X Position
+ float y; // Y Position
+ float z; // Z Position
+
+ float xi; // X Direction
+ float yi; // Y Direction
+ float zi; // Z Direction
+
+ float xg; // X Gravity
+ float yg; // Y Gravity
+ float zg; // Z Gravity
+
+ public Particle() {
+ }
+ }
+}
diff --git a/demos/HodglimsNeHe/Lesson19_plugin13.html b/demos/HodglimsNeHe/Lesson19_plugin13.html
new file mode 100644
index 0000000..4dda366
--- /dev/null
+++ b/demos/HodglimsNeHe/Lesson19_plugin13.html
@@ -0,0 +1,75 @@
+<HTML>
+<HEAD>
+<TITLE>Lesson19 Applet: Particle Engine Using Triangle Strips</TITLE>
+<STYLE TYPE="text/css">
+<!--
+A:link { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:visited { COLOR: #9C9AB1; TEXT-DECORATION: none }
+A:active { color: Yellow; TEXT-DECORATION: none }
+A:hover { color: Yellow; TEXT-DECORATION: none }
+-->
+</STYLE>
+</HEAD>
+<BODY LINK="#0000ff" VLINK="#800080" BGCOLOR="#e6e6ff">
+<CENTER>
+<P>
+<FONT SIZE="+1">Particle Engine Using Triangle Strips</FONT><BR>
+</P>
+<TABLE WIDTH="100%">
+<TR>
+<TD WIDTH="30%" ALIGN="LEFT" VALIGN="TOP">
+<P>
+<FONT SIZE="1" FACE="Verdana"><B><U>Keys</U></B></FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<B>PG_UP</B> - Zoom out<BR>
+<B>PG_DOWN</B> - Zoom in<BR>
+</FONT>
+</P>
+<P><FONT SIZE="1" FACE="Verdana"><B>Note:</B> You must click inside the applet window before using these keys.</FONT></P>
+<P>
+<FONT SIZE="1" FACE="Verdana">
+<A HREF="index.html">Go back</A>
+</FONT>
+</P>
+</TD>
+<TD WIDTH="70%" ALIGN="CENTER" VALIGN="TOP">
+<!--"CONVERTED_APPLET"-->
+<!-- CONVERTER VERSION 1.3 -->
+<SCRIPT LANGUAGE="JavaScript"><!--
+ var _info = navigator.userAgent; var _ns = false;
+ var _ie = (_info.indexOf("MSIE") > 0 && _info.indexOf("Win") > 0 && _info.indexOf("Windows 3.1") < 0);
+//--></SCRIPT>
+<COMMENT><SCRIPT LANGUAGE="JavaScript1.1"><!--
+ var _ns = (navigator.appName.indexOf("Netscape") >= 0 && ((_info.indexOf("Win") > 0 && _info.indexOf("Win16") < 0 && java.lang.System.getProperty("os.version").indexOf("3.5") < 0) || (_info.indexOf("Sun") > 0) || (_info.indexOf("Linux") > 0)));
+//--></SCRIPT></COMMENT>
+
+<SCRIPT LANGUAGE="JavaScript"><!--
+ if (_ie == true) document.writeln('<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" WIDTH = "400" HEIGHT = "400" codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0"><NOEMBED><XMP>');
+ else if (_ns == true) document.writeln('<EMBED type="application/x-java-applet;version=1.3" CODE = "Lesson19.class" WIDTH = "400" HEIGHT = "400" scriptable=false pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html"><NOEMBED><XMP>');
+//--></SCRIPT>
+<APPLET CODE = "Lesson19.class" WIDTH = "400" HEIGHT = "400"></XMP>
+<PARAM NAME = CODE VALUE = "Lesson19.class" >
+
+<PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
+<PARAM NAME="scriptable" VALUE="false">
+
+</APPLET>
+
+</NOEMBED></EMBED></OBJECT>
+
+
+<!--
+<APPLET CODE = "Lesson19.class" WIDTH = "400" HEIGHT = "400">
+
+
+</APPLET>
+-->
+<!--"END_CONVERTED_APPLET"-->
+
+</TD>
+</TR>
+</TABLE>
+</CENTER>
+</BODY>
+</HTML>
diff --git a/demos/HodglimsNeHe/data/world.txt b/demos/HodglimsNeHe/data/world.txt
new file mode 100644
index 0000000..767385e
--- /dev/null
+++ b/demos/HodglimsNeHe/data/world.txt
@@ -0,0 +1,160 @@
+
+NUMPOLLIES 36
+
+// Floor 1
+-3.0 0.0 -3.0 0.0 6.0
+-3.0 0.0 3.0 0.0 0.0
+ 3.0 0.0 3.0 6.0 0.0
+
+-3.0 0.0 -3.0 0.0 6.0
+ 3.0 0.0 -3.0 6.0 6.0
+ 3.0 0.0 3.0 6.0 0.0
+
+// Ceiling 1
+-3.0 1.0 -3.0 0.0 6.0
+-3.0 1.0 3.0 0.0 0.0
+ 3.0 1.0 3.0 6.0 0.0
+-3.0 1.0 -3.0 0.0 6.0
+ 3.0 1.0 -3.0 6.0 6.0
+ 3.0 1.0 3.0 6.0 0.0
+
+// A1
+
+-2.0 1.0 -2.0 0.0 1.0
+-2.0 0.0 -2.0 0.0 0.0
+-0.5 0.0 -2.0 1.5 0.0
+-2.0 1.0 -2.0 0.0 1.0
+-0.5 1.0 -2.0 1.5 1.0
+-0.5 0.0 -2.0 1.5 0.0
+
+// A2
+
+ 2.0 1.0 -2.0 2.0 1.0
+ 2.0 0.0 -2.0 2.0 0.0
+ 0.5 0.0 -2.0 0.5 0.0
+ 2.0 1.0 -2.0 2.0 1.0
+ 0.5 1.0 -2.0 0.5 1.0
+ 0.5 0.0 -2.0 0.5 0.0
+
+// B1
+
+-2.0 1.0 2.0 2.0 1.0
+-2.0 0.0 2.0 2.0 0.0
+-0.5 0.0 2.0 0.5 0.0
+-2.0 1.0 2.0 2.0 1.0
+-0.5 1.0 2.0 0.5 1.0
+-0.5 0.0 2.0 0.5 0.0
+
+// B2
+
+ 2.0 1.0 2.0 2.0 1.0
+ 2.0 0.0 2.0 2.0 0.0
+ 0.5 0.0 2.0 0.5 0.0
+ 2.0 1.0 2.0 2.0 1.0
+ 0.5 1.0 2.0 0.5 1.0
+ 0.5 0.0 2.0 0.5 0.0
+
+// C1
+
+-2.0 1.0 -2.0 0.0 1.0
+-2.0 0.0 -2.0 0.0 0.0
+-2.0 0.0 -0.5 1.5 0.0
+-2.0 1.0 -2.0 0.0 1.0
+-2.0 1.0 -0.5 1.5 1.0
+-2.0 0.0 -0.5 1.5 0.0
+
+// C2
+
+-2.0 1.0 2.0 2.0 1.0
+-2.0 0.0 2.0 2.0 0.0
+-2.0 0.0 0.5 0.5 0.0
+-2.0 1.0 2.0 2.0 1.0
+-2.0 1.0 0.5 0.5 1.0
+-2.0 0.0 0.5 0.5 0.0
+
+// D1
+
+2.0 1.0 -2.0 0.0 1.0
+2.0 0.0 -2.0 0.0 0.0
+2.0 0.0 -0.5 1.5 0.0
+2.0 1.0 -2.0 0.0 1.0
+2.0 1.0 -0.5 1.5 1.0
+2.0 0.0 -0.5 1.5 0.0
+
+// D2
+
+2.0 1.0 2.0 2.0 1.0
+2.0 0.0 2.0 2.0 0.0
+2.0 0.0 0.5 0.5 0.0
+2.0 1.0 2.0 2.0 1.0
+2.0 1.0 0.5 0.5 1.0
+2.0 0.0 0.5 0.5 0.0
+
+// Upper hallway - L
+-0.5 1.0 -3.0 0.0 1.0
+-0.5 0.0 -3.0 0.0 0.0
+-0.5 0.0 -2.0 1.0 0.0
+-0.5 1.0 -3.0 0.0 1.0
+-0.5 1.0 -2.0 1.0 1.0
+-0.5 0.0 -2.0 1.0 0.0
+
+// Upper hallway - R
+0.5 1.0 -3.0 0.0 1.0
+0.5 0.0 -3.0 0.0 0.0
+0.5 0.0 -2.0 1.0 0.0
+0.5 1.0 -3.0 0.0 1.0
+0.5 1.0 -2.0 1.0 1.0
+0.5 0.0 -2.0 1.0 0.0
+
+// Lower hallway - L
+-0.5 1.0 3.0 0.0 1.0
+-0.5 0.0 3.0 0.0 0.0
+-0.5 0.0 2.0 1.0 0.0
+-0.5 1.0 3.0 0.0 1.0
+-0.5 1.0 2.0 1.0 1.0
+-0.5 0.0 2.0 1.0 0.0
+
+// Lower hallway - R
+0.5 1.0 3.0 0.0 1.0
+0.5 0.0 3.0 0.0 0.0
+0.5 0.0 2.0 1.0 0.0
+0.5 1.0 3.0 0.0 1.0
+0.5 1.0 2.0 1.0 1.0
+0.5 0.0 2.0 1.0 0.0
+
+
+// Left hallway - Lw
+
+-3.0 1.0 0.5 1.0 1.0
+-3.0 0.0 0.5 1.0 0.0
+-2.0 0.0 0.5 0.0 0.0
+-3.0 1.0 0.5 1.0 1.0
+-2.0 1.0 0.5 0.0 1.0
+-2.0 0.0 0.5 0.0 0.0
+
+// Left hallway - Hi
+
+-3.0 1.0 -0.5 1.0 1.0
+-3.0 0.0 -0.5 1.0 0.0
+-2.0 0.0 -0.5 0.0 0.0
+-3.0 1.0 -0.5 1.0 1.0
+-2.0 1.0 -0.5 0.0 1.0
+-2.0 0.0 -0.5 0.0 0.0
+
+// Right hallway - Lw
+
+3.0 1.0 0.5 1.0 1.0
+3.0 0.0 0.5 1.0 0.0
+2.0 0.0 0.5 0.0 0.0
+3.0 1.0 0.5 1.0 1.0
+2.0 1.0 0.5 0.0 1.0
+2.0 0.0 0.5 0.0 0.0
+
+// Right hallway - Hi
+
+3.0 1.0 -0.5 1.0 1.0
+3.0 0.0 -0.5 1.0 0.0
+2.0 0.0 -0.5 0.0 0.0
+3.0 1.0 -0.5 1.0 1.0
+2.0 1.0 -0.5 0.0 1.0
+2.0 0.0 -0.5 0.0 0.0 \ No newline at end of file
diff --git a/demos/SwingDemos/factoryhack.txt b/demos/SwingDemos/factoryhack.txt
new file mode 100644
index 0000000..7f621ad
--- /dev/null
+++ b/demos/SwingDemos/factoryhack.txt
@@ -0,0 +1,16 @@
+
+ //Set up the GUI.
+ GLCapabilities caps = new GLCapabilities();
+ Canvas cvs = null;
+ GLDrawableFactory gldf = GLDrawableFactory.getFactory();
+ if(gldf instanceof SunJDK13GLDrawableFactory)
+ {
+ SunJDK13GLDrawableFactory sgldf =
+ (SunJDK13GLDrawableFactory)gldf;
+ GraphicsConfiguration grcfg =
+ sgldf.getGraphicsConfiguration(caps);
+ cvs = new Canvas (grcfg);
+ } else {
+ cvs = new Canvas ();
+ }
+ cvs.
diff --git a/gl4java/swing/GLJPanel.java-directtest b/gl4java/swing/GLJPanel.java-directtest
new file mode 100644
index 0000000..9e4d9fd
--- /dev/null
+++ b/gl4java/swing/GLJPanel.java-directtest
@@ -0,0 +1,948 @@
+package gl4java.swing;
+
+import gl4java.*;
+import gl4java.drawable.*;
+import gl4java.drawable.utils.*;
+
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+/**
+ * This is meant as an base class writing
+ * easy render functions. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented in GLAnimJPanel !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * There are two ways of using a GLJPanel: the {@link
+ * gl4java.GLEventListener} model or the subclassing model. Earlier
+ * versions of the system only supported the subclassing model. The
+ * default implementations of {@link #init}, {@link #display},
+ * {@link #reshape} and {@link #doCleanup}
+ * now send events to GLEventListeners; they can
+ * still be overridden as before to support the subclassing model.
+ *
+ * <p>
+ * If using the subclassing model, you should override the following
+ * methods for your needs:
+ * <pre>
+ <a href="GLJPanel.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLJPanel.html#init()">init - 1st initialisation after creating GLContext</a>
+ <a href="GLJPanel.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLJPanel.html#display()">display - render your frame</a>
+ <a href="GLJPanel.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
+ * </pre>
+ *
+ * To check if you can use the GLContext and GL and GLU methods,
+ * use the function
+ * <pre>
+ <a href="GLJPanel.html#cvsIsInit()">cvsIsInit</a>
+ * </pre>
+ * <p>
+ * IF you remove/release a GLJPanel,
+ * e.g. you want to close/dispose it�s Window (which contains this GLJPanel),
+ * you HAVE TO call:
+ *
+ * <pre>
+ <a href="GLJPanel.html#cvsDispose()">cvsDispose</a>
+ * </pre>
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * <p>
+ * We do override the following Canvas methods.
+ *
+ * <pre>
+ <a href="GLJPanel.html#update(java.awt.Graphics)">update</a>
+ <a href="GLJPanel.html#paint(java.awt.Graphics)">paint</a>
+ * </pre>
+ * <p>
+ *
+ * @see gl4java.swing.GLAnimJPanel
+ * @see gl4java.awt.GLCanvas
+ *
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ * */
+public class GLJPanel extends JPanel
+ implements GLEnum, GLUEnum,
+ ComponentListener, WindowListener, MouseListener,
+ GLDrawable
+{
+ Component compHeavy = null;
+
+ protected GLContext glj = null;
+ public GLFunc gl = null;
+ public GLUFunc glu = null;
+
+ protected Dimension size = null;
+ protected boolean mustResize = false;
+ protected boolean mustMove = false;
+
+ protected boolean needCvsDispose = false;
+
+ /**
+ * Visual pre-set for doubleBuffer, default: true
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean doubleBuffer = false;
+
+ /**
+ * Visual pre-set for stencil-bit number, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected int stencilBits = 0;
+
+ /**
+ * Visual pre-set for accumulator buffer size, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * This value has a special behavior.
+ * For input - within the contructor,
+ * it is the value for each component !
+ *
+ * The output value, after the constructor returns,
+ * it is the summary of all accumulation bits of all components !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected int accumSize = 0;
+
+ /**
+ * Visual pre-set for stereoView, default: false
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean stereoView = false;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean rgba = true;
+
+ protected GLCapabilities capabilities = null;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected boolean createOwnWindow = false;
+
+ /**
+ * The context with wich display lists and textures will be shared.
+ *
+ * @see gl4java.awt.GLCanvas#preInit
+ * @see gl4java.awt.GLCanvas#paint
+ */
+ protected GLContext sharedGLContext;
+
+ /**
+ * The data to hold the offscreen pixels on the java side !
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected BufferedImage offImage = null;
+ protected Point absCoord = null;
+ protected int offImageWidth = 0;
+ protected int offImageHeight= 0;
+ protected int glFormat=0;
+ protected int glType=0;
+ protected int glComps=0;
+ protected int awtFormat=0;
+
+
+ /**
+ * The custom set offscreen Size
+ *
+ * If this is set to != null,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#setOffScreenSize
+ * @see gl4java.swing.GLJPanel#getOffScreenSize
+ */
+ protected Dimension offScrnSize = null;
+ protected boolean customOffScrnSize=false;
+ protected boolean offScrnSizeChanged=false;
+
+ // The list of GLEventListeners
+ private GLEventListenerList listeners = new GLEventListenerList();
+
+ static {
+ GLContext.gljNativeDebug = true;
+ GLContext.gljClassDebug = true;
+ if(GLContext.doLoadNativeLibraries("GL4JavaJauGljJNI12", null, null)==false)
+ System.out.println("GLJPanel could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( String gl_Name,
+ String glu_Name,
+ LayoutManager layout, boolean isDoubleBuffered
+ )
+ {
+ super( layout, isDoubleBuffered );
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+
+ setOpaque(false);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( LayoutManager layout, boolean isDoubleBuffered )
+ {
+ this(null, null, layout, isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ */
+ public GLJPanel( boolean isDoubleBuffered )
+ {
+ this(null, null, new FlowLayout(), isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param layout the layout manager
+ */
+ public GLJPanel(LayoutManager layout)
+ {
+ this(null, null, layout, true);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ */
+ public GLJPanel( )
+ {
+ this(null, null, new FlowLayout(), true);
+ }
+
+ /**
+ * Used to return the created GLContext
+ */
+ public final GLContext getGLContext() { return glj; }
+
+ /**
+ * Safe the toplevel window
+ */
+ protected Window topLevelWindow = null;
+
+ /**
+ *
+ * This function returns the found TopLevelWindow,
+ * which contains this Canvas ..
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ public final Window getTopLevelWindow()
+ { return topLevelWindow; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#offScrnSize
+ * @see gl4java.swing.GLJPanel#setOffScreenSize
+ */
+ public Dimension getOffScreenSize()
+ { return offScrnSize; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#offScrnSize
+ * @see gl4java.swing.GLJPanel#getOffScreenSize
+ */
+ public void setOffScreenSize(Dimension size)
+ {
+ if((size!=null && size.equals(offScrnSize)==false) ||
+ size!=offScrnSize
+ )
+ {
+ offScrnSizeChanged=true;
+ offScrnSize=size;
+ customOffScrnSize=offScrnSize!=null;
+ }
+ }
+
+ /**
+ * this function overrides the Canvas paint method !
+ *
+ * For the first paint,
+ * the user function preInit is called, a GLContext is created
+ * and the user function init is called !
+ *
+ * Also, if a GL Context exist, GLJPanel's sDisplay-method will be called
+ * to do OpenGL-rendering.
+ *
+ * The sDisplay method itself calls the display-method !
+ * sDisplay is needed to be thread-safe, to manage
+ * the resize functionality and to safe the time per frame.
+ *
+ * To define your rendering, you should overwrite the display-method
+ * in your derivation.
+ *
+ * @see gl4java.GLContext#GLContext
+ * @see gl4java.swing.GLJPanel#cvsIsInit
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.swing.GLJPanel#display
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#init
+ */
+ public synchronized final void paintComponent(Graphics g)
+ {
+ if(glj == null || ( !glj.gljIsInit() && isGLEnabled() ) )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLCanvas create GLContext (recreate="+
+ (glj != null) +")");
+ preInit();
+
+ if(glj!=null) glj=null;
+
+ compHeavy = this;
+
+ // fetch the heavy peer component in temporary var. comp
+ while(compHeavy!=null &&
+ (compHeavy.getPeer() instanceof java.awt.peer.LightweightPeer)
+ )
+ compHeavy=compHeavy.getParent();
+
+ if (capabilities != null )
+ {
+ glj = new GLContext ( this, gl, glu,
+ capabilities,
+ sharedGLContext );
+ } else {
+ glj = new GLContext ( this, gl, glu,
+ createOwnWindow,
+ doubleBuffer, stereoView,
+ rgba, stencilBits, accumSize,
+ sharedGLContext );
+ }
+
+ if(glj!=null)
+ {
+ createOwnWindow = glj.isOwnWindowCreated();
+ doubleBuffer = glj.isDoubleBuffer();
+ stencilBits = glj.getStencilBitNumber();
+ accumSize = glj.getAccumSize();
+ stereoView = glj.isStereoView();
+ rgba = glj.isRGBA();
+ }
+
+ init();
+
+ // fetch the top-level window ,
+ // to add us as the windowListener
+ //
+ Container _c = getParent();
+ Container c = null;
+
+ while(_c!=null)
+ {
+ c = _c;
+ _c = _c.getParent();
+ }
+
+ if(c instanceof Window) {
+ topLevelWindow = (Window)c;
+ topLevelWindow.addComponentListener(this);
+ } else {
+ topLevelWindow = null;
+ System.out.println("toplevel is not a Window: "+c);
+ }
+
+ if(topLevelWindow!=null)
+ {
+ topLevelWindow.addWindowListener(this);
+ } else {
+ System.out.println("no parent found for "+getName());
+ System.out.flush();
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+ addMouseListener(this);
+
+ /* force a reshape, to be sure .. */
+ mustResize = true;
+ }
+ gr = g;
+ sDisplay();
+ super.paintComponent(g);
+ }
+
+ Graphics gr = null;
+ DataBufferInt dbInt = null;
+ DataBufferUShort dbUShort = null;
+ DataBufferByte dbByte = null;
+
+ /**
+ *
+ * This is the thread save rendering-method called by paint.
+ * The actual thread will be set to highes priority befor calling
+ * 'display'. After 'display' the priority will be reset !
+ *
+ * 'gljFree' will be NOT called after 'display'.
+ *
+ * We tested the above to use multi-threading and
+ * for the demonstration 'glDemos' it works ;-)) !
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#display
+ * @see gl4java.drawable.GLEventListener#preDisplay
+ * @see gl4java.drawable.GLEventListener#display
+ * @see gl4java.drawable.GLEventListener#postDisplay
+ */
+ public synchronized final void sDisplay()
+ {
+ boolean ok = true;
+
+ if(!cvsIsInit())
+ return;
+
+ absCoord = getAbsoluteCoord();
+ int absX = (int)absCoord.getX();
+ int absY = (int)absCoord.getY();
+
+ listeners.sendPreDisplayEvent(this);
+
+ if( glj.gljMakeCurrent() == false ) {
+ System.out.println("GLJPanel: problem in use() method");
+ return;
+ }
+
+ if( mustResize )
+ {
+ Dimension hsize = compHeavy.getSize();
+ Dimension size = getSize();
+ glj.gljResize( hsize.width, hsize.height ) ;
+ resize(absX, hsize.height-absY-size.height, size.width, size.height);
+ mustResize = false;
+ invalidate();
+ //repaint(100);
+ }
+ if( mustMove )
+ {
+ Dimension hsize = compHeavy.getSize();
+ resize(absX, hsize.height-absY-size.height, size.width, size.height);
+ mustMove = false;
+ invalidate();
+ }
+
+ long _s = System.currentTimeMillis();
+
+ if(ok)
+ {
+ display();
+ listeners.sendPostDisplayEvent(this);
+ }
+
+ glj.gljFree();
+ glj.gljSwap();
+
+ _f_dur = System.currentTimeMillis()-_s;
+
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint !).
+ *
+ * <p>
+ * The default implementation of display() sends display events to
+ * all {@link gl4java.GLEventListener}s associated with this
+ * GLJPanel, and automatically calls {@link
+ * gl4java.GLContext#gljMakeCurrent} and {@link
+ * gl4java.GLContext#gljFree} as necessary.
+ *
+ * <p>}
+ * If you use the subclassing model (as opposed to the
+ * GLEventListener model), your subclass will redefine this to
+ * perform its OpenGL drawing.
+ *
+ * <p>
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay !
+ *
+ * 'sDisplay' manages a semaphore to avoid reentrance of
+ * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.drawable.GLEventListener#display
+ */
+ public void display()
+ {
+ listeners.sendDisplayEvent(this);
+ }
+
+ /**
+ *
+ * This is your pre-init method.
+ * preInit is called just BEFORE the GL-Context is created.
+ * You should override preInit, to initialize your visual-stuff,
+ * like the protected vars: doubleBuffer and stereoView
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#stereoView
+ * @see gl4java.swing.GLJPanel#rgba
+ * @see gl4java.swing.GLJPanel#stencilBits
+ * @see gl4java.swing.GLJPanel#accumSize
+ */
+ public void preInit()
+ {
+ }
+
+ /**
+ *
+ * init is called right after the GL-Context is initialized.
+ * The default implementation calls init() on all of this
+ * component's GLEventListeners.
+ *
+ * <p>
+ * If using the subclassing model, you can override this to
+ * perform one-time OpenGL initializations such as setting up
+ * lights and display lists.
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.drawable.GLEventListener#init
+ */
+ public void init()
+ {
+ listeners.sendInitEvent(this);
+ }
+
+ /**
+ * This method is used to clean up any OpenGL stuff (delete textures
+ * or whatever) prior to actually deleting the OpenGL context.
+ * You should override this with your own version, if you need to do
+ * any cleanup work at this phase.
+ * This functions is called within cvsDispose
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#cvsDispose
+ * @see gl4java.drawable.GLEventListener#cleanup
+ */
+ public void doCleanup()
+ {
+ listeners.sendCleanupEvent(this);
+ }
+
+ /**
+ * This function returns, if everything is init: the GLContext,
+ * the and the users init function
+ * This value is set in the paint method!
+ *
+ * @return boolean
+ *
+ * @see gl4java.awt.GLCanvas#paint
+ * @see gl4java.awt.GLCanvas#init
+ */
+ public boolean cvsIsInit()
+ {
+ if(glj!=null)
+ return glj.gljIsInit();
+ return false;
+ }
+
+ /**
+ * This function queries, if the GL-Context is enabled !
+ *
+ * @return boolean
+ *
+ * @see gl4java.GLContext#isEnabled
+ * @see gl4java.GLContext#gljMakeCurrent
+ */
+ public boolean isGLEnabled()
+ {
+ if(glj!=null)
+ return glj.isEnabled();
+ return false;
+ }
+
+ protected long _f_dur = 0;
+
+ /**
+ *
+ * This �reshape� method will be invoked after the first paint command
+ * after GLCanvas.componentResize is called AND only if �gljMakeCurrent� was
+ * successful (so a call of gljMakeCurrent is redundant).
+ * �reshape� is not an overloading of java.awt.Component.reshape,
+ * �reshape� is more like �glut�-reshape.
+ *
+ * <p>
+ * GLCanvas.reshape already has a simple default implementation,
+ * which calls �gljResize� and �glViewport�. It also sends the
+ * reshape() event to all GLEventListeners. If using the
+ * GLEventListener model, it may not be necessary to do anything
+ * in your event listener's reshape() method; if using the
+ * subclassing model, it may not be necessary to override this.
+ *
+ * <p>
+ * The needed call to �gljResize� is done by the invoker paint !
+ *
+ * @param width the new width
+ * @param height the new height
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.drawable.GLEventListener#reshape
+ */
+ public void reshape( int width, int height )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::reshape bounds("+getBounds()+")");
+ gl.glViewport(0,0, width, height);
+ listeners.sendReshapeEvent(this, width, height);
+ }
+
+ public void resize( int x, int y, int width, int height )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::reshape bounds("+getBounds()+")");
+ gl.glViewport(x,y, width, height);
+ }
+
+ /**
+ *
+ * �componentResized� is the componentListeners event handler.
+ *
+ * This method sets the variable �mustResize� to true,
+ * so the upcoming �paint� method-call will invoke �reshape� !
+ *
+ * This little look-alike complicating thing is done,
+ * to avoid an Exception by using the glContext from more than
+ * one concurrent thread�s !
+ *
+ * You cannot override this implementation, it is final
+ * - override �reshape' instead !
+ *
+ * @param e the element, which is resized
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#reshape
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::componentResized("+e.getComponent()+")");
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustResize = true;
+ //repaint();
+ }
+ }
+
+ public void componentMoved(ComponentEvent e)
+ {
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::componentMoved("+e.getComponent()+")");
+
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustMove = true;
+ //repaint();
+ }
+ }
+
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+ public void componentHidden(ComponentEvent e)
+ {
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ }
+ public void mouseEntered(MouseEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::mouseEntered("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+ public void mouseExited(MouseEvent e)
+ {}
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ /**
+ *
+ * �windowClosing� is the windowListeners event handler
+ * for the topLevelWindow of this Canvas !
+ *
+ * This methods free�s AND destroy�s
+ * the GL Context with �glj.gljDestroy� !
+ *
+ * @return void
+ *
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ cvsDispose();
+ }
+ }
+
+ /**
+ *
+ * �windowClosed� is the windowListeners event handler.
+ *
+ * @return void
+ *
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ if (needCvsDispose) cvsDispose();
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ *
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.swing.GLJPanel#doCleanup
+ */
+ public void cvsDispose()
+ {
+ if (glj != null)
+ {
+ if (glj.gljIsInit())
+ {
+ /* Sometimes the Microsoft VM calls the
+ Applet.stop() method but doesn't have
+ permissions to do J/Direct calls, so
+ this whole block of code will throw a
+ security exception. If this happens,
+ however, windowClosing() will still
+ call us again later and we will have
+ another opportunity to shut down the
+ context, so it all works out fine. */
+ try
+ {
+ glj.gljFree();
+ doCleanup();
+ //locks and free's GLContext
+ glj.setEnabled(false);
+ glj.gljDestroy();
+ needCvsDispose = false;
+ }
+ catch (Exception ex)
+ {
+ needCvsDispose = true;
+ }
+ }
+ }
+
+ // Setting glj to null will simply cause paint() to re-initialize.
+ // We don't want that to happen, so we will leave glj non-null.
+ }
+
+ public Dimension getSize()
+ {
+ if(customOffScrnSize)
+ return offScrnSize;
+ return super.getSize();
+ }
+
+ /**
+ * get methods
+ */
+ public final int cvsGetWidth() {
+ return getSize().width;
+ }
+ public final int cvsGetHeight() {
+ return getSize().height;
+ }
+
+ //----------------------------------------------------------------------
+ // Implementation of GLDrawable
+ //
+
+ public void addGLEventListener(GLEventListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeGLEventListener(GLEventListener listener) {
+ listeners.remove(listener);
+ }
+
+ public GLFunc getGL() {
+ return gl;
+ }
+
+ public GLUFunc getGLU() {
+ return glu;
+ }
+
+ public Point getAbsoluteCoord()
+ {
+ Container obj = this;
+ Container next = obj.getParent();
+ Point _absCoord = this.getLocation();
+ Point p = null;
+
+ //System.out.println("\nADDING START :"+obj);
+
+ while ( next instanceof JComponent )
+ {
+ obj = next;
+ next = obj.getParent();
+
+ //System.out.println("\nADDING :"+obj);
+ p = obj.getLocation();
+ _absCoord.x+=p.x;
+ _absCoord.y+=p.y;
+ }
+ return _absCoord;
+ }
+
+}
diff --git a/gl4java/swing/GLJPanel.java-graphicbuffer b/gl4java/swing/GLJPanel.java-graphicbuffer
new file mode 100644
index 0000000..7903303
--- /dev/null
+++ b/gl4java/swing/GLJPanel.java-graphicbuffer
@@ -0,0 +1,1062 @@
+package gl4java.swing;
+
+import gl4java.*;
+import gl4java.drawable.*;
+import gl4java.drawable.utils.*;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+/**
+ * This is meant as an base class writing
+ * easy render functions. A clean usage of multi-threading compatible
+ * with JAVA2 is implemented in GLAnimJPanel !
+ *
+ * <p>
+ *
+ * If you are interessting in further Documentation and/or
+ * the history of GL4Java follow the following link.
+ *
+ * <pre>
+ <a href="../../GL4Java.html">The GL4Java Documentation</a>
+ * </pre>
+ * <p>
+ *
+ * There are two ways of using a GLJPanel: the {@link
+ * gl4java.GLEventListener} model or the subclassing model. Earlier
+ * versions of the system only supported the subclassing model. The
+ * default implementations of {@link #init}, {@link #display},
+ * {@link #reshape} and {@link #doCleanup}
+ * now send events to GLEventListeners; they can
+ * still be overridden as before to support the subclassing model.
+ *
+ * <p>
+ * If using the subclassing model, you should override the following
+ * methods for your needs:
+ * <pre>
+ <a href="GLJPanel.html#init()">preInit - initialisation before creating GLContext</a>
+ <a href="GLJPanel.html#init()">init - 1st initialisation after creating GLContext</a>
+ <a href="GLJPanel.html#doCleanup()">doCleanup - OGL cleanup prior to context deletion</a>
+ <a href="GLJPanel.html#display()">display - render your frame</a>
+ <a href="GLJPanel.html#reshape(int, int)">reshape - to reshape (window resize), gljResize() is allready invoked !</a>
+ * </pre>
+ *
+ * To check if you can use the GLContext and GL and GLU methods,
+ * use the function
+ * <pre>
+ <a href="GLJPanel.html#cvsIsInit()">cvsIsInit</a>
+ * </pre>
+ * <p>
+ * IF you remove/release a GLJPanel,
+ * e.g. you want to close/dispose it�s Window (which contains this GLJPanel),
+ * you HAVE TO call:
+ *
+ * <pre>
+ <a href="GLJPanel.html#cvsDispose()">cvsDispose</a>
+ * </pre>
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * <p>
+ * We do override the following Canvas methods.
+ *
+ * <pre>
+ <a href="GLJPanel.html#update(java.awt.Graphics)">update</a>
+ <a href="GLJPanel.html#paint(java.awt.Graphics)">paint</a>
+ * </pre>
+ * <p>
+ *
+ * @see gl4java.swing.GLAnimJPanel
+ * @see gl4java.awt.GLCanvas
+ *
+ * @version 2.0, 21. April 1999
+ * @author Sven Goethel
+ * */
+public class GLJPanel extends JPanel
+ implements GLEnum, GLUEnum,
+ ComponentListener, WindowListener, MouseListener,
+ GLDrawable
+{
+ protected GLContext glj = null;
+ public GLFunc gl = null;
+ public GLUFunc glu = null;
+
+ protected boolean mustResize = false;
+
+ protected boolean cvsInitialized=false;
+
+ protected boolean needCvsDispose = false;
+
+ /**
+ * Visual pre-set for stencil-bit number, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected int stencilBits = 0;
+
+ /**
+ * Visual pre-set for accumulator buffer size, default: 0
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected int accumSize = 0;
+
+ /**
+ * Visual pre-set for stereoView, default: false
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected boolean stereoView = false;
+
+ /**
+ * Visual pre-set for RGBA usage, default: true - of course ;-)
+ * This value is updated after a GLContext is created with the
+ * original updated value of GLContext !
+ *
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected boolean rgba = true;
+
+ /**
+ * The context with witch display lists and textures will be shared.
+ *
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected GLContext sharedGLContext;
+
+ /**
+ * The data to hold the offscreen pixels on the java side !
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ protected BufferedImage offImage = null;
+ protected Point absCoord = null;
+ protected int offImageWidth = 0;
+ protected int offImageHeight= 0;
+ protected int glFormat=0;
+ protected int glType=0;
+ protected int glComps=0;
+ protected int awtFormat=0;
+
+
+ /**
+ * The custom set offscreen Size
+ *
+ * If this is set to != null,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#setOffScreenSize
+ * @see gl4java.swing.GLJPanel#getOffScreenSize
+ */
+ protected Dimension offScrnSize = null;
+ protected boolean customOffScrnSize=false;
+ protected boolean offScrnSizeChanged=false;
+
+ // The list of GLEventListeners
+ private GLEventListenerList listeners = new GLEventListenerList();
+
+ static {
+ if(GLContext.doLoadNativeLibraries(null, null, null)==false)
+ System.out.println("GLJPanel could not load def. native libs.");
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param gl_Name The name of the GLFunc implementation
+ * If gl_Name==null, the default class will be used !
+ *
+ * @param glu_Name The name of the GLUFunc implementation
+ * If gl_LibName==null, the default class will be used !
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( String gl_Name,
+ String glu_Name,
+ LayoutManager layout, boolean isDoubleBuffered
+ )
+ {
+ super( layout, isDoubleBuffered );
+
+ if( (gl=GLContext.createGLFunc(gl_Name)) ==null)
+ {
+ System.out.println("GLFunc implementation "+gl_Name+" not created");
+ }
+ if( (glu=GLContext.createGLUFunc(glu_Name)) ==null)
+ {
+ System.out.println("GLUFunc implementation "+glu_Name+" not created");
+ }
+
+ /* to be able for RESIZE event's */
+ addComponentListener(this);
+
+ setOpaque(true);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * @param layout the layout manager
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ *
+ */
+ public GLJPanel( LayoutManager layout, boolean isDoubleBuffered )
+ {
+ this(null, null, layout, isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param isDoubleBuffered the flag indicates,
+ * if double buffer should be used
+ */
+ public GLJPanel( boolean isDoubleBuffered )
+ {
+ this(null, null, new FlowLayout(), isDoubleBuffered);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ * @param layout the layout manager
+ */
+ public GLJPanel(LayoutManager layout)
+ {
+ this(null, null, layout, true);
+ }
+
+ /**
+ *
+ * Constructor
+ *
+ * Uses the default GLFunc and GLUFunc implementation !
+ *
+ */
+ public GLJPanel( )
+ {
+ this(null, null, new FlowLayout(), true);
+ }
+
+ /**
+ * Used to return the created GLContext
+ */
+ public final GLContext getGLContext() { return glj; }
+
+ /**
+ * Safe the toplevel window
+ */
+ protected Window topLevelWindow = null;
+
+ /**
+ *
+ * This function returns the found TopLevelWindow,
+ * which contains this Canvas ..
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ */
+ public final Window getTopLevelWindow()
+ { return topLevelWindow; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#offScrnSize
+ * @see gl4java.swing.GLJPanel#setOffScreenSize
+ */
+ public Dimension getOffScreenSize()
+ { return offScrnSize; }
+
+ /**
+ * The customers offscreen Size
+ *
+ * If this is set,
+ * the offscreen pixmap is used in this size,
+ * not in the components-size (-> faster if smaller)
+ *
+ * @see gl4java.swing.GLJPanel#offScrnSize
+ * @see gl4java.swing.GLJPanel#getOffScreenSize
+ */
+ public void setOffScreenSize(Dimension size)
+ {
+ if((size!=null && size.equals(offScrnSize)==false) ||
+ size!=offScrnSize
+ )
+ {
+ offScrnSizeChanged=true;
+ offScrnSize=size;
+ customOffScrnSize=offScrnSize!=null;
+ }
+ }
+
+ /**
+ * this function overrides the Canvas paint method !
+ *
+ * For the first paint,
+ * the user function preInit is called, a GLContext is created
+ * and the user function init is called !
+ *
+ * Also, if a GL Context exist, GLJPanel's sDisplay-method will be called
+ * to do OpenGL-rendering.
+ *
+ * The sDisplay method itself calls the display-method !
+ * sDisplay is needed to be thread-safe, to manage
+ * the resize functionality and to safe the time per frame.
+ *
+ * To define your rendering, you should overwrite the display-method
+ * in your derivation.
+ *
+ * @see gl4java.GLContext#GLContext
+ * @see gl4java.swing.GLJPanel#cvsIsInit
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.swing.GLJPanel#display
+ * @see gl4java.swing.GLJPanel#preInit
+ * @see gl4java.swing.GLJPanel#init
+ public synchronized final void paint(Graphics g)
+ */
+ public synchronized final void paintComponent(Graphics g)
+ {
+ if(glj == null ||
+ (mustResize && !customOffScrnSize) || offScrnSizeChanged )
+ {
+ if(mustResize)
+ {
+ cvsDispose();
+ }
+ preInit();
+ glj = GLContext.createOffScreenCtx ( this, gl, glu,
+ stereoView,
+ rgba, stencilBits, accumSize,
+ sharedGLContext,
+ offScrnSize
+ );
+
+ if(glj!=null)
+ {
+ /*
+ createOwnWindow = glj.isOwnWindowCreated();
+ doubleBuffer = glj.isDoubleBuffer();
+ */
+ stencilBits = glj.getStencilBitNumber();
+ accumSize = glj.getAccumSize();
+ stereoView = glj.isStereoView();
+ rgba = glj.isRGBA();
+ }
+ if(offImage!=null)
+ offImage.flush();
+ offImage=null;
+ offScrnSizeChanged=false;
+
+ init();
+ Dimension size = size=getSize();
+ reshape(size.width, size.height);
+
+ // fetch the top-level window ,
+ // to add us as the windowListener
+ //
+ Container _c = getParent();
+ Container c = null;
+
+ while(_c!=null)
+ {
+ c = _c;
+ _c = _c.getParent();
+ }
+
+ if(c instanceof Window) {
+ topLevelWindow = (Window)c;
+ topLevelWindow.addComponentListener(this);
+ topLevelWindow.addMouseListener(this);
+ } else {
+ topLevelWindow = null;
+ System.out.println("toplevel is not a Window: "+c);
+ }
+
+ if(topLevelWindow!=null)
+ {
+ topLevelWindow.addWindowListener(this);
+ } else {
+ System.out.println("no parent found for "+getName());
+ System.out.flush();
+ }
+ if(glj!=null && glj.gljIsInit())
+ cvsInitialized=true;
+ }
+ gr = g;
+ sDisplay();
+ }
+
+ Graphics gr = null;
+ DataBufferInt dbInt = null;
+ DataBufferUShort dbUShort = null;
+ DataBufferByte dbByte = null;
+
+ /**
+ *
+ * This is the thread save rendering-method called by paint.
+ * The actual thread will be set to highes priority befor calling
+ * 'display'. After 'display' the priority will be reset !
+ *
+ * 'gljFree' will be NOT called after 'display'.
+ *
+ * We tested the above to use multi-threading and
+ * for the demonstration 'glDemos' it works ;-)) !
+ *
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay -- OR YOU MUST KNOW WHAT YOU ARE DOING THEN !
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#display
+ * @see gl4java.drawable.GLEventListener#preDisplay
+ * @see gl4java.drawable.GLEventListener#display
+ * @see gl4java.drawable.GLEventListener#postDisplay
+ */
+ public synchronized final void sDisplay()
+ {
+ boolean ok = true;
+
+ long _s = System.currentTimeMillis();
+
+ if(!cvsIsInit())
+ return;
+
+ listeners.sendPreDisplayEvent(this);
+
+ if( glj.gljMakeCurrent() == false ) {
+ System.out.println("GLJPanel: problem in use() method");
+ return;
+ }
+
+ if(mustResize)
+ {
+ mustResize=false;
+ Dimension size = null;
+
+ if(customOffScrnSize)
+ size=offScrnSize;
+ else
+ size=getSize();
+
+ reshape(size.width, size.height);
+ /*
+ invalidate();
+ repaint(100);
+ */
+ }
+
+ if(ok)
+ {
+ display();
+ _f_dur_self = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_self_sum+=_f_dur_self;
+ glj.gljCheckGL();
+ }
+
+ Dimension size = null;
+ Dimension csize = null;
+ Point cloc = null;
+
+ int absX = 0;
+ int absY = 0;
+
+ if(customOffScrnSize)
+ size=offScrnSize;
+ else
+ size=getSize();
+ int w=size.width;
+ int h=size.height;
+
+ long _s_tst = System.currentTimeMillis();
+
+ sun.awt.image.BufferedImageGraphics2D big2d =
+ (sun.awt.image.BufferedImageGraphics2D) gr;
+
+ cloc = getLocation(null);
+
+ Rectangle2D rect = new Rectangle2D.Float();
+ rect.setRect(0, 0, w, h);
+ ((Graphics2D)gr).clip(rect);
+
+ /*
+ if(offImage==null ||
+ offImage.getHeight()!=h || offImage.getWidth()!=w)
+ if(true)
+ */
+ if(offImage!=big2d.bufImg)
+ {
+ offImage = big2d.bufImg;
+ awtFormat = offImage.getType();
+
+ absCoord = getAbsoluteCoord(null);
+ absX = (int)absCoord.getX();
+ absY = (int)absCoord.getY();
+
+ csize = getSize();
+ offImageWidth = offImage.getWidth();
+ offImageHeight= offImage.getHeight();
+
+ System.out.println("c size= "+csize);
+ System.out.println("c loc = "+cloc);
+ System.out.println("abs pos ="+absX+"/"+absY);
+
+ System.out.println("bufImg size ="+offImageWidth+"x"+offImageHeight);
+
+ dbByte=null;
+ dbUShort=null;
+ dbInt=null;
+
+ switch (awtFormat)
+ {
+ case BufferedImage.TYPE_3BYTE_BGR:
+ System.out.println("awt=3BYTE_BGR, gl=BGR,UNSIGNED_BYTE");
+ glFormat = GL_BGR;
+ glType = GL_UNSIGNED_BYTE;
+ glComps = 3;
+ dbByte = (DataBufferByte)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ System.out.println("awt=4BYTE_ABGR, gl=BGRA,UNSIGNED_INT_8_8_8_8");
+ glFormat = GL_BGRA;
+ glType = GL_UNSIGNED_INT_8_8_8_8;
+ glComps = 4;
+ dbByte = (DataBufferByte)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_INT_RGB:
+ System.out.println("awt=INT_RGB, gl=BGRA,UNSIGNED_INT_8_8_8_8_REV");
+ glFormat = GL_BGRA;
+ glType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ glComps = 4;
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_INT_ARGB:
+ System.out.println("awt=INT_ARGB, gl=BGRA,INT_8_8_8_8_REV");
+ glFormat = GL_BGRA;
+ glType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ glComps = 4;
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_INT_BGR:
+ System.out.println("awt=INT_BGR, gl=BGRA,UNSIGNED_INT_8_8_8_8");
+ glFormat = GL_BGRA;
+ glType = GL_UNSIGNED_INT_8_8_8_8;
+ glComps = 4;
+ dbInt = (DataBufferInt)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ System.out.println("awt=USHORT_555_RGB, gl=RGBA,UNSIGNED_INT_5_5_5_1");
+ glFormat = GL_RGBA;
+ glType = GL_UNSIGNED_SHORT_5_5_5_1;
+ glComps = 2;
+ dbUShort = (DataBufferUShort)
+ offImage.getRaster().getDataBuffer();
+ break;
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ System.out.println("awt=USHORT_565_RGB, gl=RGB,UNSIGNED_INT_5_6_5");
+ glFormat = GL_RGB;
+ glType = GL_UNSIGNED_SHORT_5_6_5;
+ glComps = 2;
+ dbUShort = (DataBufferUShort)
+ offImage.getRaster().getDataBuffer();
+ break;
+ }
+ } else {
+ absCoord = getAbsoluteCoord(getRootPane());
+ absX = (int)absCoord.getX();
+ absY = (int)absCoord.getY();
+ }
+
+ if(dbByte!=null)
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,glType,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ dbByte.getData());
+ else if(dbUShort!=null)
+ glj.gljReadPixelGL2AWT(0,0,w,h,glFormat,glType,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ dbUShort.getData());
+ else if(dbInt!=null)
+ glj.gljReadPixelGL2AWT(offImageWidth,
+ absX, absY,
+ 0, 0, w, h,
+ glFormat,glType,
+ glj.isDoubleBuffer()?GL_BACK:GL_FRONT,
+ dbInt.getData());
+
+ //glj.gljSwap(); // no true swapping with offscreen buffers ..
+
+ if(GLContext.gljClassDebug)
+ _f_dur_tst_sum+=System.currentTimeMillis()-_s_tst;
+
+ if(GLContext.gljClassDebug)
+ glj.gljCheckGL();
+ glj.gljFree(); // enable ctx for threads ...
+
+ /*
+ if(!customOffScrnSize)
+ gr.drawImage(offImage, 0, 0, this);
+ else {
+ size=super.getSize();
+ gr.drawImage(offImage, 0, 0, size.width, size.height, this);
+ }
+ */
+
+ _f_dur_total = System.currentTimeMillis()-_s;
+ if(GLContext.gljClassDebug)
+ {
+ _f_dur_total_sum+=_f_dur_total;
+ if(++_f_dur_times==100)
+ {
+ System.out.println("self p 100: "+
+ (double)(_f_dur_self_sum/100)/1000.0+" s");
+
+ System.out.println("tst p 100: "+
+ (double)(_f_dur_tst_sum/100)/1000.0+" s");
+
+ System.out.println("gl-bitblit p 100: "+
+ (double)((_f_dur_total_sum-_f_dur_self_sum)/100)/1000.0+" s");
+ System.out.println("total p 100: "+
+ (double)(_f_dur_total_sum/100)/1000.0+" s");
+
+ _f_dur_self_sum=0;
+ _f_dur_tst_sum=0;
+ _f_dur_total_sum=0;
+ _f_dur_times=0;
+ }
+ }
+ }
+ listeners.sendPostDisplayEvent(this);
+ }
+
+ /**
+ *
+ * This is the rendering-method called by sDisplay
+ * (and sDisplay is called by paint !).
+ *
+ * <p>
+ * The default implementation of display() sends display events to
+ * all {@link gl4java.GLEventListener}s associated with this
+ * GLJPanel, and automatically calls {@link
+ * gl4java.GLContext#gljMakeCurrent} and {@link
+ * gl4java.GLContext#gljFree} as necessary.
+ *
+ * <p>}
+ * If you use the subclassing model (as opposed to the
+ * GLEventListener model), your subclass will redefine this to
+ * perform its OpenGL drawing.
+ *
+ * <p>
+ * BE SURE, if you want to call 'display' by yourself
+ * (e.g. in the run method for animation)
+ * YOU HAVE TO CALL sDisplay !
+ *
+ * 'sDisplay' manages a semaphore to avoid reentrance of
+ * the display function !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.drawable.GLEventListener#display
+ */
+ public void display()
+ {
+ listeners.sendDisplayEvent(this);
+ }
+
+ /**
+ *
+ * This is your pre-init method.
+ * preInit is called just BEFORE the GL-Context is created.
+ * You should override preInit, to initialize your visual-stuff,
+ * like the protected vars: doubleBuffer and stereoView
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#stereoView
+ * @see gl4java.swing.GLJPanel#rgba
+ * @see gl4java.swing.GLJPanel#stencilBits
+ * @see gl4java.swing.GLJPanel#accumSize
+ */
+ public void preInit()
+ {
+ }
+
+ /**
+ *
+ * init is called right after the GL-Context is initialized.
+ * The default implementation calls init() on all of this
+ * component's GLEventListeners.
+ *
+ * <p>
+ * If using the subclassing model, you can override this to
+ * perform one-time OpenGL initializations such as setting up
+ * lights and display lists.
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.drawable.GLEventListener#init
+ */
+ public void init()
+ {
+ listeners.sendInitEvent(this);
+ }
+
+ /**
+ * This method is used to clean up any OpenGL stuff (delete textures
+ * or whatever) prior to actually deleting the OpenGL context.
+ * You should override this with your own version, if you need to do
+ * any cleanup work at this phase.
+ * This functions is called within cvsDispose
+ *
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#cvsDispose
+ * @see gl4java.drawable.GLEventListener#cleanup
+ */
+ public void doCleanup()
+ {
+ listeners.sendCleanupEvent(this);
+ }
+
+ /**
+ * This function returns, if everything is init: the GLContext,
+ * the and the users init function
+ * This value is set in the paint method!
+ *
+ * @return boolean
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#init
+ */
+ public boolean cvsIsInit()
+ {
+ return cvsInitialized;
+ }
+
+ protected long _f_dur_self = 0;
+ protected long _f_dur_self_sum = 0;
+ protected long _f_dur_tst_sum = 0;
+ protected long _f_dur_total = 0;
+ protected long _f_dur_total_sum = 0;
+ protected int _f_dur_times = 0;
+
+ /**
+ *
+ * This �reshape� method will be invoked after the first paint command
+ * after GLCanvas.componentResize is called AND only if �gljMakeCurrent� was
+ * successful (so a call of gljMakeCurrent is redundant).
+ * �reshape� is not an overloading of java.awt.Component.reshape,
+ * �reshape� is more like �glut�-reshape.
+ *
+ * <p>
+ * GLCanvas.reshape already has a simple default implementation,
+ * which calls �gljResize� and �glViewport�. It also sends the
+ * reshape() event to all GLEventListeners. If using the
+ * GLEventListener model, it may not be necessary to do anything
+ * in your event listener's reshape() method; if using the
+ * subclassing model, it may not be necessary to override this.
+ *
+ * <p>
+ * The needed call to �gljResize� is done by the invoker paint !
+ *
+ * @param width the new width
+ * @param height the new height
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#sDisplay
+ * @see gl4java.drawable.GLEventListener#reshape
+ */
+ public void reshape( int width, int height )
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::reshape bounds("+getBounds()+")");
+ gl.glViewport(0,0, width, height);
+ listeners.sendReshapeEvent(this, width, height);
+ }
+
+ /**
+ *
+ * �componentResized� is the componentListeners event handler.
+ *
+ * This method sets the variable �mustResize� to true,
+ * so the upcoming �paint� method-call will invoke �reshape� !
+ *
+ * This little look-alike complicating thing is done,
+ * to avoid an Exception by using the glContext from more than
+ * one concurrent thread�s !
+ *
+ * You cannot override this implementation, it is final
+ * - override �reshape' instead !
+ *
+ * @param e the element, which is resized
+ * @return void
+ *
+ * @see gl4java.swing.GLJPanel#paint
+ * @see gl4java.swing.GLJPanel#reshape
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ if(GLContext.gljClassDebug)
+ System.out.println("GLJPanel::componentResized("+e.getComponent()+")");
+ if(glj!=null && glj.gljIsInit() && e.getComponent()==this )
+ {
+ mustResize = true;
+ //repaint();
+ }
+ }
+
+ public void componentMoved(ComponentEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::componentMoved("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+
+ public void componentShown(ComponentEvent e)
+ {
+ }
+
+ public void componentHidden(ComponentEvent e)
+ {
+ }
+
+ public void mouseClicked(MouseEvent e)
+ {
+ }
+ public void mouseEntered(MouseEvent e)
+ {
+ /*
+ if(GLContext.gljClassDebug)
+ System.out.print("GLJPanel::mouseEntered("+e.getComponent()+")");
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ repaint();
+ }
+ */
+ }
+ public void mouseExited(MouseEvent e)
+ {}
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+
+ public void windowOpened(WindowEvent e)
+ {
+ }
+
+ /**
+ *
+ * �windowClosing� is the windowListeners event handler
+ * for the topLevelWindow of this Canvas !
+ *
+ * This methods free�s AND destroy�s
+ * the GL Context with �glj.gljDestroy� !
+ *
+ * @return void
+ *
+ */
+ public void windowClosing(WindowEvent e)
+ {
+ if(e.getComponent().equals(topLevelWindow))
+ {
+ cvsDispose();
+ }
+ }
+
+ /**
+ *
+ * �windowClosed� is the windowListeners event handler.
+ *
+ * @return void
+ *
+ */
+ public void windowClosed(WindowEvent e)
+ {
+ if (needCvsDispose) cvsDispose();
+ }
+
+ public void windowIconified(WindowEvent e)
+ {
+ }
+
+ public void windowDeiconified(WindowEvent e)
+ {
+ }
+
+ public void windowActivated(WindowEvent e)
+ {
+ }
+
+ public void windowDeactivated(WindowEvent e)
+ {
+ }
+
+ /**
+ * You should call this before releasing/dispose this Window !
+ * Also you can overwrite this class,
+ * to dispose your own elements, e.g. a Frame etc. -
+ * but be shure that you call
+ * cvsDispose implementation call this one !
+ *
+ * This function calls gljDestroy of GLContext !
+ *
+ * @see gl4java.GLContext#gljDestroy
+ * @see gl4java.swing.GLJPanel#doCleanup
+ */
+ public void cvsDispose()
+ {
+ cvsInitialized = false;
+ if (glj != null)
+ {
+ if (glj.gljIsInit())
+ {
+ /* Sometimes the Microsoft VM calls the
+ Applet.stop() method but doesn't have
+ permissions to do J/Direct calls, so
+ this whole block of code will throw a
+ security exception. If this happens,
+ however, windowClosing() will still
+ call us again later and we will have
+ another opportunity to shut down the
+ context, so it all works out fine. */
+ try
+ {
+ glj.gljFree();
+ doCleanup();
+ //locks and free's GLContext
+ glj.setEnabled(false);
+ glj.gljDestroy();
+ needCvsDispose = false;
+ }
+ catch (Exception ex)
+ {
+ needCvsDispose = true;
+ }
+ }
+ }
+
+ // Setting glj to null will simply cause paint() to re-initialize.
+ // We don't want that to happen, so we will leave glj non-null.
+ }
+
+ public Dimension getSize()
+ {
+ if(customOffScrnSize)
+ return offScrnSize;
+ return super.getSize();
+ }
+
+ /**
+ * get methods
+ */
+ public final int cvsGetWidth() {
+ return getSize().width;
+ }
+ public final int cvsGetHeight() {
+ return getSize().height;
+ }
+
+ //----------------------------------------------------------------------
+ // Implementation of GLDrawable
+ //
+
+ public void addGLEventListener(GLEventListener listener) {
+ listeners.add(listener);
+ }
+
+ public void removeGLEventListener(GLEventListener listener) {
+ listeners.remove(listener);
+ }
+
+ public GLFunc getGL() {
+ return gl;
+ }
+
+ public GLUFunc getGLU() {
+ return glu;
+ }
+
+ public Point getAbsoluteCoord(JRootPane rp)
+ {
+ Container obj = this;
+ Container next = obj.getParent();
+ Point _absCoord = this.getLocation();
+ Point p = null;
+
+ //System.out.println("\nADDING START :"+obj);
+
+ while ( next instanceof JComponent )
+ {
+ obj = next;
+ next = obj.getParent();
+
+ if ( next instanceof JComponent )
+ {
+ //System.out.println("\nADDING :"+obj);
+ p = obj.getLocation();
+ _absCoord.x+=p.x;
+ _absCoord.y+=p.y;
+ }
+ if(obj==rp) break;
+ }
+ return _absCoord;
+ }
+
+}