import java.io.*; import org.lwjgl.*; import org.lwjgl.opengl.*; import org.lwjgl.opengl.glu.*; import idx3d.*; // to store and draw 3DS mesh objects /** * Store and render a textured mesh. Can load 3DS and OBJ formats. *

* NOTE: OBJ doesn't load texture coords. Need to debug. *

* Uses the IDX3D library to load and hold 3DS meshes. See http://www.idx3d.ch * for the complete pure-java 3D library by Peter Walser. *

* napier at potatoland dot org */ public class GLModel { // Used when allocating native buffers for data types public static final int SIZE_DOUBLE = 8; public static final int SIZE_FLOAT = 4; public static final int SIZE_INT = 4; public static final int SIZE_BYTE = 1; // // holds the mesh data (uses the IDX3D library) idx3d_Object obj; // // hold the texture handle int textureHandle; // // How to tile textures on mesh public static float tileFactorVert = 1f; // how many times to repeat texture public static float tileFactorHoriz = 1f; // how many times to repeat texture // // holds the mesh as a display list (optional) int displayListID; public GLModel() { } public GLModel(String filename) { loadMesh(filename); } public void loadMesh(String filename) { if (filename.toUpperCase().endsWith(".3DS")) { idx3d_3ds_Importer importer = new idx3d_3ds_Importer(); InputStream in = getInputStream(filename); obj = importer.importFromStream(in); } else if (filename.toUpperCase().endsWith(".OBJ")) { idx3d_OBJ_Importer importer = new idx3d_OBJ_Importer(); InputStream in = getInputStream(filename); obj = importer.importFromStream(in); } } /******************************************************************* * * Functions to alter mesh size, position, orientation. Not to be * confused with glRotate() glScale() glTranslate(). These functions * operate on the mesh data, not the coordinate system. They can be * used to modify a mesh permanently (see commitChanges()) so that * the changes will be "baked in" to the mesh. * *******************************************************************/ public void scale(float dx, float dy, float dz) { if (obj != null) { obj.scale(dx,dy,dz); } } public void translate(float dx, float dy, float dz) { if (obj != null) { obj.shift(dx,dy,dz); } } public void rotate(float dx, float dy, float dz) { if (obj != null) { obj.rotate(dx,dy,dz); // degrees or radians? } } public void commitChanges() { if (obj != null) { obj.matrixMeltdown(); // convert the mesh permanently } } /******************************************************************* * * Functions to render this mesh. * *******************************************************************/ /** * How many times to repeat texture horizontally and vertically. */ public void setTextureTile(float horizontalTile, float verticalTile) { tileFactorHoriz = horizontalTile; tileFactorVert = verticalTile; } /** * Set texture for mesh. */ public void setTexture(int textureHandle) { this.textureHandle = textureHandle; } /** * Draw this mesh with current texture */ public void render() { if (displayListID > 0) { //glCalllist(displayListId); } else if (obj != null) { if (textureHandle > 0) { renderMesh(obj,textureHandle); } else { renderMesh(obj); } } } /** * Compile the mesh into display list */ public void makeDisplayList() { //displayListId = } public void calculateNormals() { if (obj != null) { obj.regenerate(); } } public void sortTriangles() { if (obj != null) { obj.triangle = sortTriangles(obj.triangle, 0, obj.triangle.length-1); } } //======================================================================== // Functions to render meshes. Specific to IDX3D libe. // //======================================================================== /** * Render a mesh with the given texture.
* Must include these lines in init() for textures to appear:
* GL11.glEnable(GL11.GL_TEXTURE_2D);
* GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
* * @param o * @param textureHandle */ public static void renderMesh(idx3d_Object o, int textureHandle) { GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle); renderMesh(o); } /** * Basic mesh render function, using current color, material and texture. * @param o */ public static void renderMesh(idx3d_Object o) { idx3d_Triangle t; GL11.glBegin(GL11.GL_TRIANGLES); for (int j = 0; j < o.triangle.length; j++) { // draw all triangles in object t = o.triangle[j]; GL11.glTexCoord2f(tileFactorHoriz*t.p1.u, tileFactorVert*t.p1.v); GL11.glNormal3f(t.p1.n.x, t.p1.n.y, t.p1.n.z); GL11.glVertex3f( (float)t.p1.pos.x, (float)t.p1.pos.y, (float)t.p1.pos.z); GL11.glTexCoord2f(tileFactorHoriz*t.p2.u, tileFactorVert*t.p2.v); GL11.glNormal3f(t.p2.n.x, t.p2.n.y, t.p2.n.z); GL11.glVertex3f( (float)t.p2.pos.x, (float)t.p2.pos.y, (float)t.p2.pos.z); GL11.glTexCoord2f(tileFactorHoriz*t.p3.u, tileFactorVert*t.p3.v); GL11.glNormal3f(t.p3.n.x, t.p3.n.y, t.p3.n.z); GL11.glVertex3f( (float)t.p3.pos.x, (float)t.p3.pos.y, (float)t.p3.pos.z); } GL11.glEnd(); } /** * Render OBJ mesh (may have multiple texture coords per vert!!??!!) * @param o */ public static void renderMeshOBJ(idx3d_Object o, int textureHandle) { idx3d_Triangle t; GL11.glBindTexture(GL11.GL_TEXTURE_2D,textureHandle); GL11.glBegin(GL11.GL_TRIANGLES); for (int j = 0; j < o.triangle.length; j++) { // draw all triangles in object t = o.triangle[j]; GL11.glTexCoord2f(tileFactorHoriz*t.uvw1.x, tileFactorVert*t.uvw1.y); GL11.glNormal3f(t.p1.n.x, t.p1.n.y, t.p1.n.z); GL11.glVertex3f( (float)t.p1.pos.x, (float)t.p1.pos.y, (float)t.p1.pos.z); GL11.glTexCoord2f(tileFactorHoriz*t.uvw2.x, tileFactorVert*t.uvw2.y); GL11.glNormal3f(t.p2.n.x, t.p2.n.y, t.p2.n.z); GL11.glVertex3f( (float)t.p2.pos.x, (float)t.p2.pos.y, (float)t.p2.pos.z); GL11.glTexCoord2f(tileFactorHoriz*t.uvw3.x, tileFactorVert*t.uvw3.y); GL11.glNormal3f(t.p3.n.x, t.p3.n.y, t.p3.n.z); GL11.glVertex3f( (float)t.p3.pos.x, (float)t.p3.pos.y, (float)t.p3.pos.z); } GL11.glEnd(); } /** * Sort an array of triangles by Z depth. Before sorting, some routine * has to set triangle.dist (average Z depth of triangle) for all triangles. * Triangle Z depth will change as viewpoint/mesh move. *

* To use: sortTriangles(triangleArray, 0, triangleArray.length-1); *

*/ public static idx3d_Triangle[] sortTriangles(idx3d_Triangle[] tri, int L, int R) { float m=(tri[L].dist+tri[R].dist)/2; int i=L; int j=R; idx3d_Triangle temp; do { while (tri[i].dist>m) i++; while (tri[j].dist=i); if (Li) sortTriangles(tri,i,R); return tri; } /** * Render a unit cube, using current color, texture and material. */ public static void renderCube() { GL11.glBegin(GL11.GL_QUADS); // Front Face GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad // Back Face GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad // Top Face GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad // Bottom Face GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad // Right face GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad // Left Face GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad GL11.glEnd(); } /** * Render a unit sphere at the origin, using current color, texture and material. */ public static void renderSphere() { new Sphere().draw(1, 16, 16); } /** * Open a file InputStream and trap errors. * @param filenameOrURL * @return */ public static InputStream getInputStream(String filename) { InputStream in = null; try { in = new FileInputStream(filename); } catch (IOException ioe) { System.out.println("GLApp.getInputStream (" + filename + "): " + ioe); if (in != null) { try { in.close(); in = null; } catch (Exception e) {} } } catch (Exception e) { System.out.println("GLApp.getInputStream (" + filename + "): " + e); } return in; } }