summaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/java/joglutils/model/examples/DisplayListRenderer.java568
-rw-r--r--src/net/java/joglutils/model/examples/ModelTest.java435
2 files changed, 1003 insertions, 0 deletions
diff --git a/src/net/java/joglutils/model/examples/DisplayListRenderer.java b/src/net/java/joglutils/model/examples/DisplayListRenderer.java
new file mode 100644
index 0000000..f297c24
--- /dev/null
+++ b/src/net/java/joglutils/model/examples/DisplayListRenderer.java
@@ -0,0 +1,568 @@
+/*
+ * DisplayListModel3D.java
+ *
+ * Created on February 27, 2008, 11:05 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package net.java.joglutils.model.examples;
+
+import net.java.joglutils.model.*;
+import com.sun.opengl.util.texture.Texture;
+import com.sun.opengl.util.texture.TextureCoords;
+import com.sun.opengl.util.texture.TextureIO;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import net.java.joglutils.model.ResourceRetriever;
+import net.java.joglutils.model.geometry.Bounds;
+import net.java.joglutils.model.geometry.Material;
+import net.java.joglutils.model.geometry.Mesh;
+import net.java.joglutils.model.geometry.Model;
+import net.java.joglutils.model.geometry.Vec4;
+import net.java.joglutils.model.iModel3DRenderer;
+
+/**
+ *
+ * @author RodgersGB
+ *
+ * modifications made by Brian Wood and Z-Knight
+ */
+public class DisplayListRenderer implements iModel3DRenderer {
+ private static DisplayListRenderer instance = new DisplayListRenderer();
+ private DisplayListCache listCache = new DisplayListCache();
+ private HashMap<Integer, Texture> texture;
+ private int modelBoundsList = -1;
+ private int objectBoundsList = 1;
+ private boolean isDebugging = true;
+
+ /** Creates a new instance of DisplayListModel3D */
+ public DisplayListRenderer() {
+ }
+
+ public static DisplayListRenderer getInstance() {
+ return instance;
+ }
+
+ public void debug(boolean value) {
+ this.isDebugging = value;
+ }
+
+ public void render(Object context, Model model)
+ {
+ GL gl = null;
+
+ if (context instanceof GL)
+ gl = (GL) context;
+
+ else if (context instanceof GLAutoDrawable)
+ gl = ((GLAutoDrawable) context).getGL();
+
+ if (gl == null) {
+ return;
+ }
+
+ if (model == null) {
+ return;
+ }
+
+ int displayList = listCache.get(model);
+
+ if(displayList < 0) {
+ displayList = initialize(gl, model);
+ if (this.isDebugging)
+ System.out.println("Initialized the display list for model: " + model.getSource());
+ }
+
+ // save some current state variables
+ boolean isTextureEnabled = gl.glIsEnabled(GL.GL_TEXTURE_2D);
+ boolean isLightingEnabled = gl.glIsEnabled(GL.GL_LIGHTING);
+ boolean isMaterialEnabled = gl.glIsEnabled(GL.GL_COLOR_MATERIAL);
+
+ // check texture
+ if (model.isUsingTexture()) { gl.glEnable(GL.GL_TEXTURE_2D); }
+ else { gl.glDisable(GL.GL_TEXTURE_2D); }
+
+ // check wireframe
+ if (model.isRenderingAsWireframe()) { gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); }
+ else { gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL); }
+
+ // check lighting
+ if (model.isUsingLighting()) { gl.glEnable(GL.GL_LIGHTING); }
+ else { gl.glDisable(GL.GL_LIGHTING); }
+
+ gl.glDisable(GL.GL_COLOR_MATERIAL);
+
+ gl.glPushMatrix();
+
+ // check for unit size model
+ if (model.isUnitizeSize()) {
+ float scale = 1.0f/model.getBounds().getRadius();
+ gl.glScalef(scale, scale, scale);
+ }
+
+ if (model.isCentered()) {
+ Vec4 center = model.getCenterPoint();
+ gl.glTranslatef(-center.x, -center.y, -center.z);
+ }
+
+ if (model.isRenderModel())
+ gl.glCallList(displayList);
+
+ // Disabled lighting for drawing the boundary lines so they are all white (or whatever I chose)
+ gl.glDisable(GL.GL_LIGHTING);
+ if (model.isRenderModelBounds())
+ gl.glCallList(modelBoundsList);
+ if (model.isRenderObjectBounds())
+ gl.glCallList(objectBoundsList);
+
+ gl.glPopMatrix();
+
+ // Reset the flags back for lighting and texture
+ if (isTextureEnabled) {
+ gl.glEnable(GL.GL_TEXTURE_2D);
+ } else {
+ gl.glDisable(GL.GL_TEXTURE_2D);
+ }
+
+ if (isLightingEnabled) {
+ gl.glEnable(GL.GL_LIGHTING);
+ } else {
+ gl.glDisable(GL.GL_LIGHTING);
+ }
+
+ if (isMaterialEnabled) {
+ gl.glEnable(GL.GL_COLOR_MATERIAL);
+ } else {
+ gl.glDisable(GL.GL_COLOR_MATERIAL);
+ }
+ }
+
+ /**
+ * Load the model and associated materials, etc
+ *
+ * @param gl
+ * @param file
+ * @return
+ */
+ private int initialize(GL gl, Model model)
+ {
+ if (this.isDebugging)
+ System.out.println("Initialize Model: " + model.getSource());
+
+ int numMaterials = model.getNumberOfMaterials();
+
+ if (this.isDebugging && numMaterials > 0) {
+ System.out.println("\n Loading " + numMaterials + " Materials:");
+ }
+
+ String file = model.getSource();
+ texture = new HashMap<Integer, Texture>();
+ for (int i=0; i<numMaterials; i++) {
+ // TODO:DELETE THIS OLD LINE loadTexture(materials.get(i).strFile, i);
+ // TODO:DELETE THIS OLD LINE materials.get(i).texureId = i;
+
+ String subFileName = "";
+
+ // If this is read from a jar file, then try to find the path relative to the model
+ int index = file.lastIndexOf('/');
+ if (index != -1) {
+ subFileName = file.substring(0,index+1);
+ } else {
+ // Else, the file path of the model was not from a jar file, so check maybe it
+ // was from a local file and get that path.
+ index = file.lastIndexOf('\\');
+
+ if (index != -1) {
+ subFileName = file.substring(0,index+1);
+ }
+ }
+
+ if (model.getMaterial(i).strFile != null) {
+ if (this.isDebugging)
+ System.out.print(" Material: " + subFileName + model.getMaterial(i).strFile);
+
+ URL result;
+ try {
+ result = ResourceRetriever.getResourceAsUrl(subFileName + model.getMaterial(i).strFile);
+ } catch(IOException e) {
+ if (this.isDebugging)
+ System.err.println(" ... failed");
+ continue;
+ }
+
+ if (result != null && !result.getPath().endsWith("/") && !result.getPath().endsWith("\\")) {
+ loadTexture(result, i);
+ model.getMaterial(i).textureId = i;
+ if (this.isDebugging)
+ System.out.println(" ... done. Texture ID: " + i);
+ } else if (this.isDebugging) {
+ System.out.println(" ... failed (no result for material)");
+ }
+ }
+ }
+
+ if (this.isDebugging && numMaterials > 0) {
+ System.out.println(" Load Materials: Done");
+ }
+
+ if (this.isDebugging)
+ System.out.println("\n Generate Lists:");
+ int compiledList = listCache.generateList(model, gl, 3);
+
+ if (this.isDebugging)
+ System.out.println(" Model List");
+ gl.glNewList(compiledList, GL.GL_COMPILE);
+ genList(gl, model);
+ gl.glEndList();
+
+ modelBoundsList = compiledList + 1;
+
+ if (this.isDebugging)
+ System.out.println(" Boundary List");
+ gl.glNewList(modelBoundsList, GL.GL_COMPILE);
+ genModelBoundsList(gl, model);
+ gl.glEndList();
+
+ objectBoundsList = compiledList + 2;
+
+ if (this.isDebugging)
+ System.out.println(" Object Boundary List");
+ gl.glNewList(objectBoundsList, GL.GL_COMPILE);
+ genObjectBoundsList(gl, model);
+ gl.glEndList();
+
+ if (this.isDebugging)
+ {
+ System.out.println(" Generate Lists: Done");
+ System.out.println("Load Model: Done");
+ }
+
+ return compiledList;
+ }
+
+ /**
+ * Load a texture given by the specified URL and assign it to the texture
+ * id that is passed in.
+ *
+ * @param url
+ * @param id
+ */
+ private void loadTexture(URL url, int id) {
+ if ( url != null ) {
+ BufferedImage bufferedImage = null;
+
+ try {
+ bufferedImage = ImageIO.read(url);
+ } catch (Exception e) {
+ System.err.println(" ... FAILED loading texture with exception: "+e.getMessage());
+ return;
+ }
+
+ texture.put(id, TextureIO.newTexture(bufferedImage, true));
+ }
+ }
+
+ /**
+ * Generate the model display list
+ *
+ * @param gl
+ */
+ private void genList(GL gl, Model model) {
+ TextureCoords coords;
+
+ for (int i=0; i<model.getNumberOfMeshes(); i++) {
+ Mesh tempObj = model.getMesh(i);
+
+ if (tempObj.numOfFaces == 0) {
+ System.err.println("Mesh: " +tempObj.name + " has no faces");
+ continue;
+ }
+
+ if(tempObj.hasTexture && texture.get(tempObj.materialID) != null) {
+ Texture t = texture.get(tempObj.materialID);
+
+ // switch to texture mode and push a new matrix on the stack
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPushMatrix();
+
+ // check to see if the texture needs flipping
+ if (t.getMustFlipVertically()) {
+ gl.glScaled(1, -1, 1);
+ gl.glTranslated(0, -1, 0);
+ }
+
+ // switch to modelview matrix and push a new matrix on the stack
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glPushMatrix();
+
+ // This is required to repeat textures...because some are not and so only
+ // part of the model gets filled in....Might be a way to check if this is
+ // required per object but I'm not sure...would need to research this.
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
+
+ // enable, bind and get texture coordinates
+ t.enable();
+ t.bind();
+ coords = t.getImageTexCoords();
+ }
+
+ for (int j=0; j<tempObj.numOfFaces; j++) {
+
+ // If the object has a texture, then do nothing till later...else
+ // apply the material property to it.
+ if(tempObj.hasTexture) {
+ // nothing
+
+ // Has no texture but has a material instead and this material is
+ // the FACES material, and not the OBJECTS material ID as being used
+ // incorrectly below...by specification, the materialID is associated
+ // with a FACE and not an OBJECT
+ } else {
+ if (tempObj.faces[j].materialID < model.getNumberOfMaterials()) {
+ float[] rgba = new float[4];
+
+ Material material = model.getMaterial(tempObj.faces[j].materialID);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, material.diffuseColor.getRGBComponents(rgba), 0);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, material.ambientColor.getRGBComponents(rgba), 0);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, material.specularColor.getRGBComponents(rgba), 0);
+ gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, material.shininess);
+ gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, material.emissive.getRGBComponents(rgba), 0);
+ }
+ }
+
+ int indexType = 0;
+ int vertexIndex = 0;
+ int normalIndex = 0;
+ int textureIndex = 0;
+ gl.glBegin(GL.GL_POLYGON);
+ //TODO: the number of vertices for a face is not always 3
+ for (int whichVertex=0; whichVertex<tempObj.faces[j].vertIndex.length; whichVertex++) {
+ vertexIndex = tempObj.faces[j].vertIndex[whichVertex];
+
+ try {
+ normalIndex = tempObj.faces[j].normalIndex[whichVertex];
+
+ indexType = 0;
+ gl.glNormal3f(tempObj.normals[normalIndex].x, tempObj.normals[normalIndex].y, tempObj.normals[normalIndex].z);
+
+ if (tempObj.hasTexture) {
+ if (tempObj.texCoords != null) {
+ textureIndex = tempObj.faces[j].coordIndex[whichVertex];
+ indexType = 1;
+ gl.glTexCoord2f(tempObj.texCoords[textureIndex].u, tempObj.texCoords[textureIndex].v);
+ }
+ }
+ indexType = 2;
+ gl.glVertex3f(tempObj.vertices[vertexIndex].x, tempObj.vertices[vertexIndex].y, tempObj.vertices[vertexIndex].z);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ switch (indexType) {
+ case 0:
+ System.err.println("Normal index " + normalIndex + " is out of bounds");
+ break;
+
+ case 1:
+ System.err.println("Texture index " + textureIndex + " is out of bounds");
+ break;
+
+ case 2:
+ System.err.println("Vertex index " + vertexIndex + " is out of bounds");
+ break;
+ }
+ }
+ }
+ gl.glEnd();
+ }
+
+ if (tempObj.hasTexture) {
+ Texture t = texture.get(tempObj.materialID);
+ if (t != null)
+ t.disable();
+
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPopMatrix();
+
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glPopMatrix();
+ }
+ }
+
+ // Try this clearing of color so it won't use the previous color
+ gl.glColor3f(1.0f, 1.0f, 1.0f);
+ }
+
+ /**
+ * Render the desired object of the model (specified by an id number of
+ * the object)
+ *
+ * @param gl
+ * @param id
+ */
+ public void renderBoundsOfObject(GL gl, int id, Model model) {
+ if (id >=0 && id <= model.getNumberOfMeshes()) {
+ if (model.getMesh(id).bounds != null) {
+ drawBounds(gl, model.getMesh(id).bounds);
+ }
+ }
+ }
+
+
+ /**
+ * Draw the boundary of the model (the large box representing the entire
+ * model and not the object in it)
+ *
+ * @param gLDrawable
+ */
+ private void genModelBoundsList(GLAutoDrawable gLDrawable, Model model) {
+ GL gl = gLDrawable.getGL();
+ drawBounds(gl, model.getBounds());
+ }
+
+ /**
+ * Draw the boundary of the model (the large box representing the entire
+ * model and not the object in it)
+ *
+ * @param gl
+ */
+ private void genModelBoundsList(GL gl, Model model) {
+ drawBounds(gl, model.getBounds());
+ }
+
+ /**
+ * Draw the boundaries over all of the objects of the model
+ *
+ * @param gLDrawable
+ */
+ private void genObjectBoundsList(GLAutoDrawable gLDrawable, Model model) {
+ GL gl = gLDrawable.getGL();
+ genObjectBoundsList(gl, model);
+ }
+
+ /**
+ * Draw the boundaries over all of the objects of the model
+ *
+ * @param gl
+ */
+ private void genObjectBoundsList(GL gl, Model model) {
+ for (int i=0; i<model.getNumberOfMeshes(); i++) {
+ if (model.getMesh(i).bounds != null) {
+ drawBounds(gl, model.getMesh(i).bounds);
+ }
+ }
+ }
+
+ /**
+ * Draws the bounding box of the object using the max and min extrema
+ * points.
+ *
+ * @param gl
+ * @param bounds
+ */
+ private void drawBounds(GL gl, Bounds bounds) {
+ // Front Face
+ gl.glBegin(GL.GL_LINE_LOOP);
+ gl.glVertex3f(bounds.min.x, bounds.min.y, bounds.min.z);
+ gl.glVertex3f(bounds.max.x, bounds.min.y, bounds.min.z);
+ gl.glVertex3f(bounds.max.x, bounds.max.y, bounds.min.z);
+ gl.glVertex3f(bounds.min.x, bounds.max.y, bounds.min.z);
+ gl.glEnd();
+
+ // Back Face
+ gl.glBegin(GL.GL_LINE_LOOP);
+ gl.glVertex3f(bounds.min.x, bounds.min.y, bounds.max.z);
+ gl.glVertex3f(bounds.max.x, bounds.min.y, bounds.max.z);
+ gl.glVertex3f(bounds.max.x, bounds.max.y, bounds.max.z);
+ gl.glVertex3f(bounds.min.x, bounds.max.y, bounds.max.z);
+ gl.glEnd();
+
+ // Connect the corners between the front and back face.
+ gl.glBegin(GL.GL_LINES);
+ gl.glVertex3f(bounds.min.x, bounds.min.y, bounds.min.z);
+ gl.glVertex3f(bounds.min.x, bounds.min.y, bounds.max.z);
+
+ gl.glVertex3f(bounds.max.x, bounds.min.y, bounds.min.z);
+ gl.glVertex3f(bounds.max.x, bounds.min.y, bounds.max.z);
+
+ gl.glVertex3f(bounds.max.x, bounds.max.y, bounds.min.z);
+ gl.glVertex3f(bounds.max.x, bounds.max.y, bounds.max.z);
+
+ gl.glVertex3f(bounds.min.x, bounds.max.y, bounds.min.z);
+ gl.glVertex3f(bounds.min.x, bounds.max.y, bounds.max.z);
+ gl.glEnd();
+ }
+
+ /**
+ * Convert an Unsigned byte to integer
+ *
+ * @param b
+ * @return
+ */
+ public int unsignedByteToInt(byte b) {
+ return (int) b & 0xFF;
+ }
+
+ /**
+ * Convert integer to float
+ *
+ * @param i
+ * @return
+ */
+ public float intToFloat(int i) {
+ return (float) i / 255.0f;
+ }
+
+ public class DisplayListCache {
+ private HashMap <Object, Integer>listCache;
+
+ /** Creates a new instance of WWDisplayListCache */
+ private DisplayListCache() {
+ listCache = new HashMap<Object, Integer>();
+ }
+
+ public void clear() {
+ listCache.clear();
+ }
+
+ public int get(Object objID) {
+ if (listCache.containsKey(objID))
+ return listCache.get(objID);
+ else
+ return -1;
+ }
+
+ public void remove(Object objID, GL gl, int howMany) {
+ Integer list = listCache.get(objID);
+
+ if(list != null)
+ gl.glDeleteLists(list, howMany);
+
+ listCache.remove(objID);
+ }
+
+ /**
+ * Returns an integer identifier for an OpenGL display list based on the
+ * object being passed in. If the object already has a display list
+ * allocated, the existing ID is returned.
+ */
+ public int generateList(Object objID, GL gl, int howMany) {
+ Integer list = null;
+
+ list = listCache.get(objID);
+ if(list == null){
+ list = new Integer(gl.glGenLists(howMany));
+ listCache.put(objID, list);
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/src/net/java/joglutils/model/examples/ModelTest.java b/src/net/java/joglutils/model/examples/ModelTest.java
new file mode 100644
index 0000000..d4f1f16
--- /dev/null
+++ b/src/net/java/joglutils/model/examples/ModelTest.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2006 Greg Rodgers All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * The names of Greg Rodgers, Sun Microsystems, Inc. or the names of
+ * contributors may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
+ * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. GREG RODGERS,
+ * SUN MICROSYSTEMS, INC. ("SUN"), AND SUN'S LICENSORS SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL GREG
+ * RODGERS, SUN, OR SUN'S LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT
+ * OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
+ * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
+ * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF GREG
+ * RODGERS OR SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use
+ * in the design, construction, operation or maintenance of any nuclear
+ * facility.
+ *
+ * Modifications made by Z-Knight
+ */
+
+package net.java.joglutils.model.examples;
+
+import net.java.joglutils.model.*;
+import com.sun.opengl.util.Animator;
+import java.awt.Frame;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import javax.media.opengl.GLCanvas;
+import javax.swing.*;
+import javax.swing.event.MouseInputAdapter;
+import java.awt.event.MouseEvent;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+import java.awt.*;
+import javax.media.opengl.glu.GLU;
+import net.java.joglutils.model.ModelFactory;
+import net.java.joglutils.model.ModelLoadException;
+import net.java.joglutils.model.geometry.Model;
+import net.java.joglutils.model.iModel3DRenderer;
+
+public class ModelTest {
+
+ /** Creates a new instance of Main */
+ public ModelTest() {
+ }
+
+ public static void main(String[] args)
+ {
+ Frame frame = new Frame();
+ GLCanvas canvas = new GLCanvas();
+ final Renderer renderer = new Renderer();
+
+ MouseHandler inputMouseHandler = new MouseHandler(renderer);
+ canvas.addMouseListener(inputMouseHandler);
+ canvas.addMouseMotionListener(inputMouseHandler);
+ canvas.addKeyListener(new KeyListener() {
+ public void keyTyped(KeyEvent e) {
+ Model model = renderer.getModel();
+ if (model == null)
+ return;
+
+ switch (e.getKeyChar()) {
+ case 'w':
+ model.setRenderAsWireframe(!model.isRenderingAsWireframe());
+ break;
+
+ case 'l':
+ model.setUseLighting(!model.isUsingLighting());
+ break;
+ }
+ }
+
+ public void keyPressed(KeyEvent e) {
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+ });
+
+ canvas.addGLEventListener(renderer);
+ frame.add(canvas);
+ frame.add(canvas);
+ frame.setSize(600, 600);
+ final Animator animator = new Animator(canvas);
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ // Run this on another thread than the AWT event queue to
+ // make sure the call to Animator.stop() completes before
+ // exiting
+ new Thread(new Runnable() {
+ public void run() {
+ animator.stop();
+ System.exit(0);
+ }
+ }).start();
+ }
+ });
+ frame.setVisible(true);
+ animator.start();
+ }
+
+ static class Renderer implements GLEventListener
+ {
+ private GLU glu = new GLU();
+ private Model model;
+ private iModel3DRenderer modelRenderer;
+
+ /** Scale Factor for zooming */
+ private float scaleAll = 1.0f;
+
+ /** Rotation factor around X */
+ private float rotX = 0.0f;
+
+ /** Rotation factor around Y */
+ private float rotY = 0.0f;
+
+ /** A mouse point */
+ private Point mousePoint = new Point();
+
+ /** The closest that one can zoom in to */
+ private static final float MIN_SCALE = 0.1f;
+
+ /** The farthest that one can zoom out to */
+ private static final float MAX_SCALE = 10000.9f;
+
+ /** The radius of the boundary of the model that is loaded */
+ private float radius = 1.0f;
+
+ /** Ambient light array */
+ float[] lightAmbient = {0.3f, 0.3f, 0.3f, 1.0f};
+
+ /** Diffuse light array */
+ float[] lightDiffuse = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ /** Specular light array */
+ float[] lightSpecular = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ /**
+ * Display method
+ *
+ * @param gLDrawable
+ */
+ public void display(GLAutoDrawable gLDrawable)
+ {
+ final GL gl = gLDrawable.getGL();
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ gl.glLoadIdentity();
+
+ glu.gluLookAt(0,0,10, 0,0,0, 0,1,0);
+
+ // Make sure the rotations don't keep growing
+ if (Math.abs(rotX) >= 360.0f) rotX = 0.0f;
+ if (Math.abs(rotY) >= 360.0f) rotY = 0.0f;
+
+ // Draw the scene (by default, the lighting, material and textures
+ // are enabled/disabled within the renderer for the model)
+ gl.glPushMatrix();
+ // Scale the model (used for zooming purposes)
+ gl.glScalef(scaleAll, scaleAll, scaleAll);
+
+ // Rotate the model based on mouse inputs
+ gl.glRotatef(rotY, 1.0f, 0.0f, 0.0f);
+ gl.glRotatef(rotX, 0.0f, 1.0f, 0.0f);
+
+ // Render the model
+ modelRenderer.render(gl, model);
+ gl.glPopMatrix();
+
+ gl.glFlush();
+ }
+
+
+ /** Called when the display mode has been changed. <B>!! CURRENTLY UNIMPLEMENTED IN JOGL !!</B>
+ * @param gLDrawable The GLDrawable object.
+ * @param modeChanged Indicates if the video mode has changed.
+ * @param deviceChanged Indicates if the video device has changed.
+ */
+ public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
+
+ /** Called by the drawable immediately after the OpenGL context is
+ * initialized for the first time. Can be used to perform one-time OpenGL
+ * initialization such as setup of lights and display lists.
+ * @param gLDrawable The GLDrawable object.
+ */
+ public void init(GLAutoDrawable gLDrawable)
+ {
+ final GL gl = gLDrawable.getGL();
+
+ try
+ {
+ // Get an instance of the display list renderer a renderer
+ modelRenderer = DisplayListRenderer.getInstance();
+
+ // Turn on debugging
+ modelRenderer.debug(true);
+
+ // Call the factory for a model from a local file
+ //model = ModelFactory.createModel("C:\\models\\apollo.3ds");
+
+ // Call the factory for a model from a jar file
+ model = ModelFactory.createModel("net/java/joglutils/model/examples/models/max3ds/apollo.3ds");
+ //model = ModelFactory.createModel("net/java/joglutils/model/examples/models/obj/penguin.obj");
+
+ // When loading the model, adjust the center to the boundary center
+ model.centerModelOnPosition(true);
+
+ model.setUseTexture(true);
+
+ // Render the bounding box of the entire model
+ model.setRenderModelBounds(false);
+
+ // Render the bounding boxes for all of the objects of the model
+ model.setRenderObjectBounds(false);
+
+ // Make the model unit size
+ model.setUnitizeSize(true);
+
+ // Get the radius of the model to use for lighting and view presetting
+ radius = model.getBounds().getRadius();
+
+ }
+ catch (ModelLoadException ex)
+ {
+ ex.printStackTrace();
+ }
+
+ // Set the light
+ float lightPosition[] = { 0, 50000000, 0, 1.0f };
+ float[] model_ambient = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, model_ambient, 0);
+ gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0);
+ gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lightDiffuse, 0);
+ gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lightAmbient, 0);
+ gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, lightSpecular, 0);
+
+ gl.glEnable(GL.GL_LIGHT0);
+ gl.glEnable(GL.GL_LIGHTING);
+ gl.glEnable(GL.GL_NORMALIZE);
+
+ gl.glEnable(GL.GL_CULL_FACE);
+ gl.glShadeModel(GL.GL_SMOOTH);
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ gl.glClearDepth(1.0f);
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ gl.glDepthFunc(GL.GL_LEQUAL);
+ gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
+ //gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, 0);
+
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glPushMatrix();
+ }
+
+
+ /** Called by the drawable during the first repaint after the component has
+ * been resized. The client can update the viewport and view volume of the
+ * window appropriately, for example by a call to
+ * GL.glViewport(int, int, int, int); note that for convenience the component
+ * has already called GL.glViewport(int, int, int, int)(x, y, width, height)
+ * when this method is called, so the client may not have to do anything in
+ * this method.
+ * @param gLDrawable The GLDrawable object.
+ * @param x The X Coordinate of the viewport rectangle.
+ * @param y The Y coordinate of the viewport rectanble.
+ * @param width The new width of the window.
+ * @param height The new height of the window.
+ */
+ public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height)
+ {
+ final GL gl = gLDrawable.getGL();
+
+ if (height <= 0) // avoid a divide by zero error!
+ height = 1;
+ final float h = (float)width / (float)height;
+ gl.glViewport(0, 0, width, height);
+ gl.glMatrixMode(GL.GL_PROJECTION);
+ gl.glLoadIdentity();
+ gl.glOrtho(-1, 1, -1, 1, -50, 50);
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glLoadIdentity();
+ }
+
+ /**
+ * Get the point at the start of the mouse drag
+ *
+ * @param MousePt
+ */
+ void startDrag( Point MousePt ) {
+ mousePoint.x = MousePt.x;
+ mousePoint.y = MousePt.y;
+ }
+
+ /**
+ * Calculate the delta and rotation values for the dragging of the mouse
+ * @param MousePt
+ */
+ void drag( Point MousePt ) {
+ Point delta = new Point();
+ delta.x = MousePt.x - mousePoint.x;
+ delta.y = MousePt.y - mousePoint.y;
+
+ mousePoint.x = MousePt.x;
+ mousePoint.y = MousePt.y;
+
+ rotX += delta.x * 2.0f / scaleAll;
+ rotY += delta.y * 2.0f / scaleAll;
+ }
+
+ /**
+ * Get the point at the start of the mouse zoom action
+ * @param MousePt
+ */
+ void startZoom( Point MousePt ) {
+ mousePoint.x = MousePt.x;
+ mousePoint.y = MousePt.y;
+ }
+
+ /**
+ * Caclaulte the scaling parameters for zooming while the zoom drag
+ * is ongoing
+ *
+ * @param MousePt
+ */
+ void zoom( Point MousePt ) {
+ Point delta = new Point();
+ delta.x = MousePt.x - mousePoint.x;
+ delta.y = MousePt.y - mousePoint.y;
+
+ mousePoint.x = MousePt.x;
+ mousePoint.y = MousePt.y;
+
+ float addition = -(delta.x + delta.y) / 250.0f;
+
+ if (addition < 0.0 && (scaleAll+addition) > MIN_SCALE) {
+ scaleAll += addition;
+ }
+
+ if (addition > 0.0 && (scaleAll+addition) < MAX_SCALE) {
+ scaleAll += addition;
+ }
+ }
+
+ public Model getModel() {
+ return model;
+ }
+
+ public void setModel(Model model) {
+ this.model = model;
+ }
+ }
+
+ /**
+ * Moue handler class that allows the user to rotate and zoom on the model
+ *
+ *
+ */
+ static class MouseHandler extends MouseInputAdapter {
+ private Renderer renderer;
+
+ /**
+ * Creates a new instance of the moouse handler
+ *
+ * @param renderer
+ */
+ public MouseHandler(Renderer renderer) {
+ //System.out.println(" Mouse Handler ");
+ this.renderer = renderer;
+ }
+
+
+ /**
+ * Handles the mouse click events
+ *
+ * @param e
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isRightMouseButton(e)) {
+ //System.out.println(" ---> RIGHT MOUSE BUTTON CLICKED ");
+ }
+ }
+
+
+ /**
+ * Handles the mouse press events
+ *
+ * @param mouseEvent
+ */
+ public void mousePressed(MouseEvent mouseEvent) {
+ if (SwingUtilities.isLeftMouseButton(mouseEvent)) {
+ //System.out.println(" ---> LEFT MOUSE BUTTON PRESSED ");
+ renderer.startDrag(mouseEvent.getPoint());
+ } else if (SwingUtilities.isMiddleMouseButton(mouseEvent)) {
+ //System.out.println(" ---> MIDDLE MOUSE BUTTON PRESSED ");
+ renderer.startZoom(mouseEvent.getPoint());
+ }
+ }
+
+
+ /**
+ * Handles the mouse drag events
+ *
+ * @param mouseEvent
+ */
+ public void mouseDragged(MouseEvent mouseEvent) {
+ if (SwingUtilities.isLeftMouseButton(mouseEvent)) {
+ //System.out.println(" ---> LEFT MOUSE BUTTON DRAGGED ");
+ renderer.drag(mouseEvent.getPoint());
+ } else if (SwingUtilities.isMiddleMouseButton(mouseEvent)) {
+ //System.out.println(" ---> MIDDLE MOUSE BUTTON DRAGGED ");
+ renderer.zoom(mouseEvent.getPoint());
+ }
+ }
+ }
+}