From 8512ae5ab8a75fad8a75aec0b6e04e3fcd1d2c6f Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 9 May 2001 13:21:11 +0000 Subject: 2.7.2.0 swing and minor changes --- demos/HodglimsNeHe/Lesson10.html | 39 ++ demos/HodglimsNeHe/Lesson10.java | 640 +++++++++++++++++ demos/HodglimsNeHe/Lesson10_plugin13.html | 79 +++ demos/HodglimsNeHe/Lesson19.html | 44 ++ demos/HodglimsNeHe/Lesson19.java | 420 ++++++++++++ demos/HodglimsNeHe/Lesson19_plugin13.html | 75 ++ demos/HodglimsNeHe/data/world.txt | 160 +++++ demos/SwingDemos/factoryhack.txt | 16 + gl4java/swing/GLJPanel.java-directtest | 948 +++++++++++++++++++++++++ gl4java/swing/GLJPanel.java-graphicbuffer | 1062 +++++++++++++++++++++++++++++ 10 files changed, 3483 insertions(+) create mode 100644 demos/HodglimsNeHe/Lesson10.html create mode 100644 demos/HodglimsNeHe/Lesson10.java create mode 100644 demos/HodglimsNeHe/Lesson10_plugin13.html create mode 100644 demos/HodglimsNeHe/Lesson19.html create mode 100644 demos/HodglimsNeHe/Lesson19.java create mode 100644 demos/HodglimsNeHe/Lesson19_plugin13.html create mode 100644 demos/HodglimsNeHe/data/world.txt create mode 100644 demos/SwingDemos/factoryhack.txt create mode 100644 gl4java/swing/GLJPanel.java-directtest create mode 100644 gl4java/swing/GLJPanel.java-graphicbuffer 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 @@ + + +Lesson10 Applet: Loading And Moving Through A 3D World + + +
+

Loading And Moving Through A 3D World
+

+ + + + + +
+

+Keys

+

+ +PG_UP - Look Up
+PG_DOWN - Look Down
+UP - Move Fwd
+DOWN - Move Bwd
+LEFT - Move Left
+RIGHT - Move Right
+
+

+

Note: You must click inside the applet window before using these keys.

+

+ +Go back + +

+
+ + +
+
+ + 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 @@ + + +Lesson10 Applet: Loading And Moving Through A 3D World + + + +
+

+Loading And Moving Through A 3D World
+

+ + + + + +
+

+Keys

+

+ +PG_UP - Look Up
+PG_DOWN - Look Down
+UP - Move Fwd
+DOWN - Move Bwd
+LEFT - Move Left
+RIGHT - Move Right
+
+

+

Note: You must click inside the applet window before using these keys.

+

+ +Go back + +

+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + 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 @@ + + +Lesson19 Applet: Particle Engine Using Triangle Strips + + + +
+

+Particle Engine Using Triangle Strips
+

+ + + + + +
+

+Keys

+

+ +PG_UP - Zoom out
+PG_DOWN - Zoom in
+
+

+

Note: You must click inside the applet window before using these keys.

+

+ +Go back + +

+
+ + +
+
+ + 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 @@ + + +Lesson19 Applet: Particle Engine Using Triangle Strips + + + +
+

+Particle Engine Using Triangle Strips
+

+ + + + + +
+

+Keys

+

+ +PG_UP - Zoom out
+PG_DOWN - Zoom in
+
+

+

Note: You must click inside the applet window before using these keys.

+

+ +Go back + +

+
+ + + + + + + + + + + + + + + + + + + + +
+
+ + 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 ! + * + *

+ * + * If you are interessting in further Documentation and/or + * the history of GL4Java follow the following link. + * + *

+	The GL4Java Documentation
+ * 
+ *

+ * + * 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. + * + *

+ * If using the subclassing model, you should override the following + * methods for your needs: + *

+        preInit - initialisation before creating GLContext
+        init - 1st initialisation after creating GLContext
+        doCleanup - OGL cleanup prior to context deletion
+        display - render your frame
+	reshape - to reshape (window resize), gljResize() is allready invoked !
+ * 
+ * + * To check if you can use the GLContext and GL and GLU methods, + * use the function + *
+        cvsIsInit
+ * 
+ *

+ * IF you remove/release a GLJPanel, + * e.g. you want to close/dispose it´s Window (which contains this GLJPanel), + * you HAVE TO call: + * + *

+        cvsDispose
+ * 
+ * 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 ! + * + *

+ * We do override the following Canvas methods. + * + *

+        update
+        paint
+ * 
+ *

+ * + * @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 !). + * + *

+ * 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. + * + *

} + * If you use the subclassing model (as opposed to the + * GLEventListener model), your subclass will redefine this to + * perform its OpenGL drawing. + * + *

+ * 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. + * + *

+ * 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. + * + *

+ * 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. + * + *

+ * 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 ! + * + *

+ * + * If you are interessting in further Documentation and/or + * the history of GL4Java follow the following link. + * + *

+	The GL4Java Documentation
+ * 
+ *

+ * + * 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. + * + *

+ * If using the subclassing model, you should override the following + * methods for your needs: + *

+        preInit - initialisation before creating GLContext
+        init - 1st initialisation after creating GLContext
+        doCleanup - OGL cleanup prior to context deletion
+        display - render your frame
+	reshape - to reshape (window resize), gljResize() is allready invoked !
+ * 
+ * + * To check if you can use the GLContext and GL and GLU methods, + * use the function + *
+        cvsIsInit
+ * 
+ *

+ * IF you remove/release a GLJPanel, + * e.g. you want to close/dispose it´s Window (which contains this GLJPanel), + * you HAVE TO call: + * + *

+        cvsDispose
+ * 
+ * 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 ! + * + *

+ * We do override the following Canvas methods. + * + *

+        update
+        paint
+ * 
+ *

+ * + * @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 !). + * + *

+ * 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. + * + *

} + * If you use the subclassing model (as opposed to the + * GLEventListener model), your subclass will redefine this to + * perform its OpenGL drawing. + * + *

+ * 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. + * + *

+ * 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. + * + *

+ * 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. + * + *

+ * 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; + } + +} -- cgit v1.2.3