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