LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: elias4444 on January 27, 2005, 00:13:05

Title: How can one load an OBJ file?
Post by: elias4444 on January 27, 2005, 00:13:05
I know you guys are probably tired of my constant questions, but is there a way to load an OBJ file, other than having to write my own loader/translator for the file format?
Title: How can one load an OBJ file?
Post by: funsheep on January 27, 2005, 00:24:10
you will probably have your own datastructure to represent 3d models, so you will have to write an specific obj loader.

you should adapt one of the various loader tutorials on the web.
some are collected here:
http://www.j3d.org/utilities/loaders.html
Title: How can one load an OBJ file?
Post by: Matzon on January 27, 2005, 06:23:56
or check out one of the game engines on this page:
http://lwjgl.org/links.php
Title: How can one load an OBJ file?
Post by: elias4444 on January 27, 2005, 21:59:21
OK.... Here it is.
This is crude...
this is uncommented...
this has got to be some of the craziest and ugliest coding I've ever done.

BUT, I've wanted to find a way to say thank you to those on the board for all their help... SO, here's my simple object loader. It loads and assists in drawing .obj files. I can't guarantee anything, but it's worked for me on every obj file I've thrown at it so far. It supports coordinates, normals, and texture coordinates. Please be kind, as this has taken me all day to program (mostly trying to decipher the obj spec), and I'm too tired to go back through and clean-up/optimize it right now. Feel free to delete all the System.out.println commands.  :P

**Updated: August 8, 2005
Notice that now you pass a BufferedReader object into the class. This way you can handle your own file loading and error routines on a per program basis.

/*
* Modified on August 8, 2005
*/
package tools;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;

import org.lwjgl.opengl.GL11;

/**
* @author Jeremy Adams (elias4444)
*
* Use these lines if reading from a file
* FileReader fr = new FileReader(ref);
* BufferedReader br = new BufferedReader(fr);

* Use these lines if reading from within a jar
* InputStreamReader fr = new InputStreamReader(new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(ref)));
* BufferedReader br = new BufferedReader(fr);
*/

public class Object3D {


private ArrayList vertexsets = new ArrayList(); // Vertex Coordinates
private ArrayList vertexsetsnorms = new ArrayList(); // Vertex Coordinates Normals
private ArrayList vertexsetstexs = new ArrayList(); // Vertex Coordinates Textures
private ArrayList faces = new ArrayList(); // Array of Faces (vertex sets)
private ArrayList facestexs = new ArrayList(); // Array of of Faces textures
private ArrayList facesnorms = new ArrayList(); // Array of Faces normals

private int objectlist;
private int numpolys = 0;

//// Statisitcs for drawing ////
public float toppoint = 0; // y+
public float bottompoint = 0; // y-
public float leftpoint = 0; // x-
public float rightpoint = 0; // x+
public float farpoint = 0; // z-
public float nearpoint = 0; // z+

public Object3D(BufferedReader ref, boolean centerit) {
loadobject(ref);
if (centerit) {
centerit();
}
opengldrawtolist();
numpolys = faces.size();
cleanup();
}

private void cleanup() {
vertexsets.clear();
vertexsetsnorms.clear();
vertexsetstexs.clear();
faces.clear();
facestexs.clear();
facesnorms.clear();
}

private void loadobject(BufferedReader br) {
int linecounter = 0;
try {

String newline;
boolean firstpass = true;

while (((newline = br.readLine()) != null)) {
linecounter++;
newline = newline.trim();
if (newline.length() > 0) {
if (newline.charAt(0) == 'v' && newline.charAt(1) == ' ') {
float[] coords = new float[4];
String[] coordstext = new String[4];
coordstext = newline.split("\\s+");
for (int i = 1;i < coordstext.length;i++) {
coords[i-1] = Float.valueOf(coordstext[i]).floatValue();
}
//// check for farpoints ////
if (firstpass) {
rightpoint = coords[0];
leftpoint = coords[0];
toppoint = coords[1];
bottompoint = coords[1];
nearpoint = coords[2];
farpoint = coords[2];
firstpass = false;
}
if (coords[0] > rightpoint) {
rightpoint = coords[0];
}
if (coords[0] < leftpoint) {
leftpoint = coords[0];
}
if (coords[1] > toppoint) {
toppoint = coords[1];
}
if (coords[1] < bottompoint) {
bottompoint = coords[1];
}
if (coords[2] > nearpoint) {
nearpoint = coords[2];
}
if (coords[2] < farpoint) {
farpoint = coords[2];
}
/////////////////////////////
vertexsets.add(coords);
}
if (newline.charAt(0) == 'v' && newline.charAt(1) == 't') {
float[] coords = new float[4];
String[] coordstext = new String[4];
coordstext = newline.split("\\s+");
for (int i = 1;i < coordstext.length;i++) {
coords[i-1] = Float.valueOf(coordstext[i]).floatValue();
}
vertexsetstexs.add(coords);
}
if (newline.charAt(0) == 'v' && newline.charAt(1) == 'n') {
float[] coords = new float[4];
String[] coordstext = new String[4];
coordstext = newline.split("\\s+");
for (int i = 1;i < coordstext.length;i++) {
coords[i-1] = Float.valueOf(coordstext[i]).floatValue();
}
vertexsetsnorms.add(coords);
}
if (newline.charAt(0) == 'f' && newline.charAt(1) == ' ') {
String[] coordstext = newline.split("\\s+");
int[] v = new int[coordstext.length - 1];
int[] vt = new int[coordstext.length - 1];
int[] vn = new int[coordstext.length - 1];

for (int i = 1;i < coordstext.length;i++) {
String fixstring = coordstext[i].replaceAll("//","/0/");
String[] tempstring = fixstring.split("/");
v[i-1] = Integer.valueOf(tempstring[0]).intValue();
if (tempstring.length > 1) {
vt[i-1] = Integer.valueOf(tempstring[1]).intValue();
} else {
vt[i-1] = 0;
}
if (tempstring.length > 2) {
vn[i-1] = Integer.valueOf(tempstring[2]).intValue();
} else {
vn[i-1] = 0;
}
}
faces.add(v);
facestexs.add(vt);
facesnorms.add(vn);
}
}
}

} catch (IOException e) {
System.out.println("Failed to read file: " + br.toString());
//System.exit(0);
} catch (NumberFormatException e) {
System.out.println("Malformed OBJ (on line " + linecounter + "): " + br.toString() + "\r \r" + e.getMessage());
//System.exit(0);
}

}

private void centerit() {
float xshift = (rightpoint-leftpoint) /2f;
float yshift = (toppoint - bottompoint) /2f;
float zshift = (nearpoint - farpoint) /2f;

for (int i=0; i < vertexsets.size(); i++) {
float[] coords = new float[4];

coords[0] = ((float[])(vertexsets.get(i)))[0] - leftpoint - xshift;
coords[1] = ((float[])(vertexsets.get(i)))[1] - bottompoint - yshift;
coords[2] = ((float[])(vertexsets.get(i)))[2] - farpoint - zshift;

vertexsets.set(i,coords); // = coords;
}

}

public float getXWidth() {
float returnval = 0;
returnval = rightpoint - leftpoint;
return returnval;
}

public float getYHeight() {
float returnval = 0;
returnval = toppoint - bottompoint;
return returnval;
}

public float getZDepth() {
float returnval = 0;
returnval = nearpoint - farpoint;
return returnval;
}

public int numpolygons() {
return numpolys;
}

public void opengldrawtolist() {

this.objectlist = GL11.glGenLists(1);

GL11.glNewList(objectlist,GL11.GL_COMPILE);
for (int i=0;i<faces.size();i++) {
int[] tempfaces = (int[])(faces.get(i));
int[] tempfacesnorms = (int[])(facesnorms.get(i));
int[] tempfacestexs = (int[])(facestexs.get(i));

//// Quad Begin Header ////
int polytype;
if (tempfaces.length == 3) {
polytype = GL11.GL_TRIANGLES;
} else if (tempfaces.length == 4) {
polytype = GL11.GL_QUADS;
} else {
polytype = GL11.GL_POLYGON;
}
GL11.glBegin(polytype);
////////////////////////////

for (int w=0;w<tempfaces.length;w++) {
if (tempfacesnorms[w] != 0) {
float normtempx = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[0];
float normtempy = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[1];
float normtempz = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[2];
GL11.glNormal3f(normtempx, normtempy, normtempz);
}

if (tempfacestexs[w] != 0) {
float textempx = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[0];
float textempy = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[1];
float textempz = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[2];
GL11.glTexCoord3f(textempx,1f-textempy,textempz);
}

float tempx = ((float[])vertexsets.get(tempfaces[w] - 1))[0];
float tempy = ((float[])vertexsets.get(tempfaces[w] - 1))[1];
float tempz = ((float[])vertexsets.get(tempfaces[w] - 1))[2];
GL11.glVertex3f(tempx,tempy,tempz);
}


//// Quad End Footer /////
GL11.glEnd();
///////////////////////////


}
GL11.glEndList();
}

public void opengldraw() {
GL11.glCallList(objectlist);
}

}
Title: How can one load an OBJ file?
Post by: funsheep on January 28, 2005, 08:30:01
we are also using obj files. and it had turned out, that in java 1.4 the switch case blocks are for such things faster than the if then else if then else ... statements.

and

when you are going to read mtl files there are several commands, beginning with the same character, what do you do then?
ok: use switch case blocks to determine the first character and than proove with if else statements which command it is :)

happy hacking
Title: How can one load an OBJ file?
Post by: elias4444 on January 28, 2005, 15:53:24
I'm actually not too worried about the if-then statements. They're primarily used in the loading sequence, which I traditionally do before the game actually begins. The drawing sequence doesn't seem to be effected as much as the information is already in memory and is simply looped through.
Title: How can one load an OBJ file?
Post by: napier on February 08, 2005, 03:58:58
Hey elias4444,

I need to load obj files too and have played some with your loader.  

I found a few models that look like they're not loading right (I don't think I'm messing them up in my code).  A few of the triangles drop out, leaving holes in the model.  

If you're interested try the obj file here: http://potatoland.com/code/objloader/p51_mustang.obj

I'm planning to debug but thought I'd let you know.

I also found a loader by Karl Berg that looks decent but is written in C++. Might be useful for reference:

http://potatoland.com/code/objloader/ModelType.cpp
http://potatoland.com/code/objloader/ModelType.h

napier
Title: How can one load an OBJ file?
Post by: elias4444 on February 08, 2005, 05:06:17
Right... make sure you grab the code again from the previous post (I've updated it a couple of times). I hadn't done anything with textures, so I didn't realize I was setting the texture coordinates out of order. It seems to work now with just about everything I've thrown at it (including custom objects exported from Maya). Keep in mind though, I'm only using faces (no curves or anything yet - I just don't know how to do those in openGL yet). BTW, that's a cool p51 model.  :)
Title: How can one load an OBJ file?
Post by: elias4444 on February 08, 2005, 05:33:38
Here's a site with some fun free objects to test with:

http://o.ffrench.free.fr/meshbank/

Also for fun, I've made what I call a "texture tester" for the guy doing my 3D graphics for me. Feel free to use it (whenever my webserver is actually up):

//www.tommytwisters.com/texture/texture.jnlp
To use it, find the "tommytwisters" folder under your user directory (on windows - c:\documents and settings\userid\tommytwisters\), and drop in an object file named "object.obj" and a texture file named "texture.png" (you can use other image types, but it must be named "texture.png" - even if it's a gif or something) to see what it looks like. It'll tell you how many faces the object has and a simple FPS benchmark for it. Also, you can use the following keys for testing:

L = turn dynamic lighting on and off
S = turn spheremapping on and off
R = lock the light to the camera position (and unlock)
I = "zoom in" = scale your object larger
O = "zoom out" = scale your object smaller
T,F,G,H = move the object around.
Arrow Keys = move the camera around.

It uses my most up-to-date version of the object reader code above. I also experienced missing triangles, but it turned out to be an older version of my code and the way I had the texture mapping setup. It seems to be fixed now.
Title: How can one load an OBJ file?
Post by: napier on February 09, 2005, 03:25:16
Hmmm.....  I grabbed the most recent code above but get the same result (several triangles are missing).   The model has verts, normals and faces.  It also has smoothing groups (I thing that's what 'g' and 's' are about).  Maybe that's related.  

QuoteBTW, that's a cool p51 model.

I'd love to take credit but can't.  I found it on the web, I think it's part of the Java 3D demos.  If it was my own I'd be more suspicious that I screwed up the model and that's what's causing render problems  :)

Anyhoo I can't debug for two days or so.  If you do get to it let me know and I'll test.  

BTW Thanks for the loader!
Title: How can one load an OBJ file?
Post by: elias4444 on February 09, 2005, 18:26:17
I'm noticing some missing triangles in the cockpit windshield for the model, although I'm not sure it's a bug in my code (although it could be that the object file is using something I haven't implemented yet). Are you having problems with any other models? I've been downloading some pretty complex models from the web and haven't found any with the same problem yet.

I'll have a friend load it into Maya and see what he gets.
Title: How can one load an OBJ file?
Post by: elias4444 on February 09, 2005, 19:27:16
Mmmm... Yummy humble pie!!!

Yep, I left a line out of my code up there. It should work just fine for you now.
Title: How can one load an OBJ file?
Post by: napier on February 10, 2005, 04:54:21
Very cool.  Now it works.  

Thanks!
Title: How can one load an OBJ file?
Post by: elias4444 on March 11, 2005, 15:23:24
Figured I better point out that I updated the code (posted above). It's about 30% faster now. I convert the arraylists to arrays in order to avoid casting everything on every draw. Also, the constructor now supports a boolean variable that specifies whether you want the object automatically centered around an origin or not. There's also some extra functions to get the different dimensions and number of polygons used.

Hope that helps!
Title: How can one load an OBJ file?
Post by: elias4444 on March 14, 2005, 19:30:25
Well, the joy keeps coming with this one... I just implemented genlists... with a 35,000 face count, I went from 35fps to 120+ fps in my tester app. Enjoy the upgrade!
Title: How can one load an OBJ file?
Post by: jam007 on March 21, 2005, 21:49:46
Great :D

Reading this I realised that your loader class together with Java XML support will be perfect to make new ice boat types in our game without having to make any new classes or code. Just filling in a XML-file and making 3D-model Objects.

It really solved a big problem for us in making the ice boats modifiable by non java/OpenGL "enabled" users.

Anders
Title: How can one load an OBJ file?
Post by: ordoc on March 22, 2005, 01:28:36
you can eliminate casting in the 1.5 JDK with generic types.
ArrayList<float[]> vertexsets = new ArrayList<float[]>();

also if any of the ArrayLists are gonna have a good number of elements in them, you might want to instantiate them with something other than the default value of 10.

However I am not sure how much faster this will make your code if at all :) You can always test it out though.
Title: How can one load an OBJ file?
Post by: tomb on March 22, 2005, 03:09:06
Quote from: "ordoc"you can eliminate casting in the 1.5 JDK with generic types.
ArrayList<float[]> vertexsets = new ArrayList<float[]>();

No, you don't eliminate the cast. It executes exactly as 1.4 code.
Title: How can one load an OBJ file?
Post by: ordoc on March 22, 2005, 07:30:02
Right, you eliminate the cast in your code to make it more readable, but it just becomes implicit.


I was more refering to the arraylist instantiations when it came to speed.
Title: How can one load an OBJ file?
Post by: jam007 on March 22, 2005, 10:01:34
and use the Scanner class to read the file. (Java 1.5)
using 1.5 types eliminates the irritating warning about unsafe bla bla
Still, elias4444 has made a great job!

Anders
Title: How can one load an OBJ file?
Post by: elias4444 on March 22, 2005, 16:20:22
Good comments everyone! I love feedback!  :D

I've been trying to avoid being locked into Java 1.5, but I'm seriously considering a full on move to it (the guy who does my graphics is on a Mac though, which doesn't have 1.5 available yet). Once Apple decides to go 1.5, I don't think I'll have an excuse anymore.

At one point, I actually switched the code over to using Arrays rather than ArrayLists, but it made it more complex, and I realized that it didn't make any difference in speed once I started using OpenGL Display Lists to accelerate rendering. My only other thought was to use Vertex Buffer Objects rather than Display Lists, but I learned that there wasn't any speed improvement with that either.  :P

Things left that I'm considering:
*Manually calculating Vertex Normals - but as I've learned, graphic artists sometimes like to do "weird" things with their lighting normals, so thus far, I've left it out.

*Read in material groups - although this would require the user to pass in an array of textures to use for the materials as well. Is it just easier to create a seperate object with a different texture mapped onto it? My sprites can actually accept an array of objects and textures, and then "glue" them all together, so I'm not sure this is needed (which is also why I made the auto-centering of the object optional with the boolean flag).

...So, anyway... Anyone know about Apple's plans to move to Java 1.5? Also, if there's anything else you guys are interested in, please let me know and I'll take my best shot at it.
Title: How can one load an OBJ file?
Post by: ordoc on March 22, 2005, 20:02:19
rumors of April I hear...
Title: How can one load an OBJ file?
Post by: jam007 on March 22, 2005, 20:54:52
Just that your class (when you think itÃ,´s ready) will be part of the lwjgl.util package. So I wont have to paste copy and ... it :wink:

Anders
Title: How can one load an OBJ file?
Post by: elias4444 on April 20, 2005, 19:42:23
Ok, just a quick refresh of the OBJ loader. I've set it up now so that you pass the constructor your own BufferedReader object (the sample code is in the comments at the top of the class). This way, I'm doing things closer to the "right" way, and you can handle your own file-loading and error routines the way you'd like.
Title: How can one load an OBJ file?
Post by: kappa on April 22, 2005, 08:57:47
does the loader support textures?
Title: How can one load an OBJ file?
Post by: elias4444 on April 22, 2005, 14:13:45
It supports texture coordinates. I didn't want to build the texturing into the loader, as some people (including myself) like to do "funny" things with textures. Basically, you can use the class something like a GLU object:


GL11.glPushMatrix();
texture.bind();
GL11.glTranslatef(x, y, z);
GL11.glColor4f(1,1,1,1);
theobject.opengldraw();
GL11.glPopMatrix();


I prefer keeping things as componentized as possible to allow for the greatest amount of flexibility.
Title: How can one load an OBJ file?
Post by: oNyx on June 18, 2005, 22:02:20
Ok... fixed the code... if you ever write test code... be sure that it actually checks the correct stuff :lol:

I just took your loader and removed all regex stuff in that loadobject method... String.split and String.replaceAll are using regex under the hood and are therefore somewhat slow.

[old] 4.940987751 seconds
[new] 2.025095927 seconds
[old] 4.930706557 seconds
[new] 1.948526977 seconds
[old] 4.904319683 seconds
[new] 1.940505009 seconds


See? Quite the difference huh? (I used a 2mb file for benching) And all I did was replacing String.split with StringTokenizer (the api says one should use String.split instead yadda yadda... I don't care... it's slower). And that replaceAll was replaced with some "toCharArray loop StringBuffer"-voodoo (and voodoo it is... guess where the bug was hidden :D).

Here is the method... from my testing the in-mem-data was exactly the same (now I'm sure). Feel free to give it a try ;)

private void loadobject2(BufferedReader br) {
try {

String newline;
boolean firstpass = true;

while (((newline = br.readLine()) != null)) {
if (newline.length() > 0) {
newline = newline.trim();
if (newline.startsWith("v ")){
float[] coords = new float[4];
String[] coordstext = new String[4];
newline = newline.substring(2,newline.length());
StringTokenizer st=new StringTokenizer(newline," ");
for(int i=0;st.hasMoreTokens();i++)
coords[i] = Float.parseFloat(st.nextToken());
//// check for farpoints ////
if (firstpass) {
rightpoint = coords[0];
leftpoint = coords[0];
toppoint = coords[1];
bottompoint = coords[1];
nearpoint = coords[2];
farpoint = coords[2];
firstpass = false;
}
if (coords[0] > rightpoint) {
rightpoint = coords[0];
}
if (coords[0] < leftpoint) {
leftpoint = coords[0];
}
if (coords[1] > toppoint) {
toppoint = coords[1];
}
if (coords[1] < bottompoint) {
bottompoint = coords[1];
}
if (coords[2] > nearpoint) {
nearpoint = coords[2];
}
if (coords[2] < farpoint) {
farpoint = coords[2];
}
/////////////////////////////
vertexsets.add(coords);
}
else if (newline.startsWith("vt")){
float[] coords = new float[4];
String[] coordstext = new String[4];
newline = newline.substring(3,newline.length());
StringTokenizer st=new StringTokenizer(newline," ");
for(int i=0;st.hasMoreTokens();i++)
coords[i] = Float.parseFloat(st.nextToken());
vertexsetstexs.add(coords);
}
else if (newline.startsWith("vn")){
float[] coords = new float[4];
String[] coordstext = new String[4];
newline = newline.substring(3,newline.length());
StringTokenizer st=new StringTokenizer(newline," ");
for(int i=0;st.hasMoreTokens();i++)
coords[i] = Float.parseFloat(st.nextToken());
vertexsetsnorms.add(coords);
}
else if (newline.startsWith("f ")){

newline = newline.substring(2,newline.length());
StringTokenizer st=new StringTokenizer(newline," ");
int count=st.countTokens();
int[] v = new int[count];
int[] vt = new int[count];
int[] vn = new int[count];

for(int i=0;i<count;i++) {
char []chars=st.nextToken().toCharArray();
StringBuffer sb=new StringBuffer();
char lc='x';
for(int k=0;k<chars.length;k++) {
if(chars[k]=='/') {
if(lc=='/')
sb.append('0');
}
lc=chars[k];
sb.append(lc);
}
StringTokenizer st2=new StringTokenizer(sb.toString(),"/");
int num=st2.countTokens();
v[i] = Integer.parseInt(st2.nextToken());
if (num > 1) {
vt[i] = Integer.parseInt(st2.nextToken());
} else {
vt[i] = 0;
}
if (num > 2) {
vn[i] = Integer.parseInt(st2.nextToken());
} else {
vn[i] = 0;
}
}
faces.add(v);
facestexs.add(vt);
facesnorms.add(vn);
}
}
}

} catch (IOException e) {
System.out.println("Failed to read file: " + br.toString());
//System.exit(0);
} catch (NumberFormatException e) {
System.out.println("Malformed OBJ file: " + br.toString() + "\r \r" + e.getMessage());
//System.exit(0);
}

}
Title: How can one load an OBJ file?
Post by: oNyx on June 19, 2005, 04:57:57
FYI "fixed the code" referred to my code (as seen above). I edited that post, but in retrospect it looks a bit misleading...

Well, there is something weird with that loader...

*poke* *poke*

Hm... ok... if I change this line:

GL11.glTexCoord3f(textempx, textempy, textempz);

like this:

GL11.glTexCoord3f(textempx, 1f-textempy, textempz);

Then the texturing seems to be ok.

The simplest test model+texture:
http://kaioa.com/k/dice.zip (~2kb)
Title: How can one load an OBJ file?
Post by: elias4444 on June 21, 2005, 20:29:25
I think it just depends on how you implement your texturing system. But I'm glad to see someone using it/having fun with it.
Title: How can one load an OBJ file?
Post by: oNyx on June 21, 2005, 21:04:43
Ye, its either wrong way up or not... dunno how to avoid that whole issue, but it isn't really a problem with the loader itself. I think I should have pointed that out somehow.

Tried my alternate loadobject method?
Title: How can one load an OBJ file?
Post by: elias4444 on June 24, 2005, 21:28:47
Yours definitely speeds things up, but I'm being a stickler for Java standards. I did go ahead and tighten up the code a bit though, so it'll now be a bit kinder about misformated OBJ files (and if there is an error, it'll tell you what line of OBJ file it's on).

The big thing I'd like to see done is a routine that automatically computes the vertex normals (make it optional of course, like the centering routine). I've found places that say it's easy, but they act as if all an OBJ file ever contains is triangles. Anyone up for the challenge?
Title: How can one load an OBJ file?
Post by: elias4444 on August 04, 2005, 18:29:56
QuoteHm... ok... if I change this line:
GL11.glTexCoord3f(textempx, textempy, textempz);
like this:
GL11.glTexCoord3f(textempx, 1f-textempy, textempz);
Then the texturing seems to be ok.
I wonder why that is? I've been trying to figure it out. Does the OBJ spec expect the texture to be flipped or something? Anyone know?
Title: hmmmmmmmm
Post by: Fool Running on August 05, 2005, 13:39:49
Aren't OpenGl textures upside down? (I'm probably wrong  :lol: ) So the Obj file is fine, OpenGL just has the texture upside down. (Assuming I'm right  :roll: )
Title: How can one load an OBJ file?
Post by: elias4444 on August 08, 2005, 17:59:17
BTW, for those interested, I found a really nice tool for converting different types of 3D models, as well as doing different transformations on them (would you like face or vertex normals with that sir?):

http://user.txcyber.com/~sgalls/
Title: How can one load an OBJ file?
Post by: elias4444 on August 09, 2005, 20:12:35
And once again, for those interested:

I've created a version of the OBJ loader that also handles corresponding MTL (material) files. The code is quite a bit longer, so I didn't want to post it here in the forum. For an example of it though, use the following link:

//www.tommytwisters.com/texture/texture.jnlp

Place the OBJ, MTL, and texture files in your %userpath%/TommyTwisters/ folder to access them.

If anyone is interested in the code for this, please let me know. I'm just not sure how to distribute it, as it requires code for OBJ handling, MTL handling, and texture handling.
Title: How can one load an OBJ file?
Post by: elias4444 on August 10, 2005, 15:41:20
OK, I just released several upgrades to that texture-tester app in the previous post. It should be a bit more user-friendly now. :)

Also, if you're interested in the code, please send me a private message with where to e-mail the zip file. Like I said, I'd post it on the forums, but it's a bit much.
Title: How can one load an OBJ file?
Post by: CaseyB on August 22, 2005, 22:00:14
I played with the loader that you posted and it's very good work!  I would definate be interested in seeing the new and improved code!  Could you email it to TheBeast.13<at>gmail<dot>com??  Again, Good Work!!
Title: How can one load an OBJ file?
Post by: crash0veride007 on August 31, 2005, 03:57:17
Mad Props to elias4444 for the great .OBJ loader! Great Work! Just thought I'd give back to the community, below is a basic LWJGL program which will load an OBJ mesh and display/spin it.

package JavaGL;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.glu.GLU;

//MAD PROPZ to elias4444 @ LWJGL forums for the great OBJ LOADER
import tools.Object3D;

public class MeshPolys {
   public static boolean done = false;
   public static String windowTitle = "Crash0veride007 JavaGL";
   public static DisplayMode displayMode;
   public static Object3D mesh;
   public static float angle =0.0f;
   
   public static void main(String[] args) {
       MeshPolys runit = new MeshPolys();
       runit.run();
   }
   
   public void run() {
       long startTime = System.currentTimeMillis() + 5000;
       long fps = 0;
       try {
           init();
           while (!done) {
               MainLoop();
               Display.update();
               if (startTime > System.currentTimeMillis()) {
                   fps++;
               } else {
                   long timeUsed = 5000 + (startTime - System.currentTimeMillis());
                   startTime = System.currentTimeMillis() + 5000;
                   String outdata = fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = "+ (fps / (timeUsed / 1000f))+" FPS";
                   System.out.println( outdata );
                   Display.setTitle(windowTitle + " " + outdata);
                   fps = 0;
               }
           }
           cleanup();
           System.exit(0);
       } catch (Exception e) {
           e.printStackTrace();
           System.exit(0);
       }
   }
   
   public void MainLoop() {
       rendershit();
       if(Display.isCloseRequested()) {
           done = true;
       }
   }
   
   public void createWindow() throws Exception {
       DisplayMode d[] = Display.getAvailableDisplayModes();
       for (int i = 0; i < d.length; i++) {
           if (d.getWidth() == 1024
                   && d.getHeight() == 768
                   && d.getBitsPerPixel() == 32) {
               displayMode = d;
               break;
           }
       }
       Display.setDisplayMode(displayMode);
       Display.setTitle(windowTitle);
       Display.create();
   }
   
   public void init() throws Exception {
       createWindow();
       initGL();
       loadmesh();
   }
   
   public void initGL() {
       GL11.glShadeModel(GL11.GL_SMOOTH);
       GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
       GL11.glClearDepth(1.0);
       GL11.glEnable(GL11.GL_DEPTH_TEST);
       GL11.glDepthFunc(GL11.GL_LEQUAL);
       GL11.glMatrixMode(GL11.GL_PROJECTION);
       GL11.glLoadIdentity();
       GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
       GLU.gluPerspective(80.0f,(float) displayMode.getWidth() / (float) displayMode.getHeight(),0.1f,1000.0f);
       GL11.glMatrixMode(GL11.GL_MODELVIEW);
       GL11.glLoadIdentity();
       GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
       GLU.gluLookAt(0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
   }
   
   public void loadmesh() {
       //FileReader f_read;
       String path ="mesh/skull.obj";
       String matpath = "mesh/";
       try {
           InputStream r_path = getClass().getResourceAsStream(path);
           BufferedReader b_read = new BufferedReader(new InputStreamReader(r_path));
           //f_read = new FileReader(r_path);
           //BufferedReader b_read = new BufferedReader(f_read);
           mesh = new Object3D(b_read,true, matpath);
           r_path.close();
           b_read.close();
       } catch (IOException e) {
           System.out.println("Could not open file: " + path);
       }
   }
   
   public void rendershit() {
       GL11.glColor3f(0.0f, 1.0f, 0.0f);
       GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
       GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
       GL11.glPushMatrix();
       GL11.glRotatef(angle, 1.0f, .0f, 0.0f);
       GL11.glRotatef(angle, 0.0f, 1.0f, 0.0f);
       GL11.glRotatef(angle, 0.0f, 0.0f, 1.0f);
       GL11.glPushMatrix();
       GL11.glScalef(10.0f,10.0f,10.0f);
       mesh.opengldraw();
       GL11.glPopMatrix();
       angle  = (angle+1.0f)%360;
       GL11.glPopMatrix();
       GL11.glFlush();
   }
   
   public void cleanup() {
       Display.destroy();
   }
}
Title: How can one load an OBJ file?
Post by: CaseyB on September 01, 2005, 06:20:09
@elias4444 Great work on the FontTranslator!  That is awesome!  It took one of the more difficult things about OpenGL and made it trivial!  That's the sign of a good tool!  I did make a couple of tweaks to it to better suit what I'm doing, nothing major.  Hope you don't mind!
Title: How can one load an OBJ file?
Post by: elias4444 on September 01, 2005, 14:54:36
Oh yeah, I forgot all about that one. I've actually got a very seriously updated version of it now... maybe I should update that and post it too. I just figured that's what everyone was already doing.  :P
Title: How can one load an OBJ file?
Post by: CaseyB on September 01, 2005, 15:19:04
I would love to see the updated version!  Perhaps it is what everyone is alredy doing, but I am new to all of this so I am still very excited about it!
Title: How can one load an OBJ file?
Post by: elias4444 on September 01, 2005, 15:29:16
As you wish...
http://lwjgl.org/forum/viewtopic.php?p=8362#8362
Title: How can one load an OBJ file?
Post by: crash0veride007 on September 02, 2005, 17:24:26
hey elias when can we expect to see mesh animation support added?  :wink:  he he
Title: How can one load an OBJ file?
Post by: elias4444 on September 02, 2005, 17:46:31
LOL... when it loads something other than OBJ files.  :P

OBJ files are fairly static things, but to do an animation, you can either do cartoon framing (load several versions of the same OBJ in different positions and then flip through them), or manipulate the loaded data from a single OBJ file (although I currently use display lists, so you'd have to retool the loader to use VBO's instead).

I'll probably look into more serious animation techniques with my next game.
Title: How can one load an OBJ file?
Post by: Evil-Devil on December 20, 2005, 18:04:12
Does someone know how to deal with the smoothing group fields that may encoutered within an obj file?

My obj loader works fine with loading the model and the assigned materials retrieved from the mtl file. Example pictures (http://home.pages.at/evil-devil/evil-devil.com/index.php?menu=projects&hasRoot=false)

But i like to add smoothing group support to my loader and don't know how to deal with them. I read something about smoothing groups in the OpenGL Redbook but i lost with questions.

Any ideas?

Evil
Title: How can one load an OBJ file?
Post by: napier on December 21, 2005, 17:29:46
I used code from this tutorial:  http://www.xmission.com/~nate/smooth.html
to smooth models.  Worked well, and gave me some ideas about how to handle smoothing.  

This code doesn't do groups, it smooths the entire model and preserves sharp edges (ie. 90 degree edges), but I suppose you could smooth sets of verts instead of the whole model.
Title: How can one load an OBJ file?
Post by: elias4444 on December 21, 2005, 18:08:42
Smoothing is really just a trick with the normals. I've noticed that with different objects, artists like to use different smoothing techniques for different parts of it. What I do now is just edit my objects in something like poseray first, and then use the object loader in this thread (well, ok, I actually use an updated one). That way, I can get different vertex normals for each vertice if I want to.
Title: How can one load an OBJ file?
Post by: Achilleterzo on January 12, 2006, 21:04:23
Hi all, i'm glad to talk with you.
I have some "cathodic" how-to:

1) Enabling textures into the above elia's class.
2) Using bump or more complex maps like normal.

Many and in advance, thanks.

the GLModel class (very ugly, uncommented code):


package Engine;

import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.lwjgl.opengl.GL11;

public class GLModel
{

   private ArrayList vertexsets;
   private ArrayList vertexsetsnorms;
   private ArrayList vertexsetstexs;
   private ArrayList faces;
   private ArrayList facestexs;
   private ArrayList facesnorms;
   private int objectlist;
   private int numpolys;
   public float toppoint;
   public float bottompoint;
   public float leftpoint;
   public float rightpoint;
   public float farpoint;
   public float nearpoint;

   public GLModel(BufferedReader ref, boolean centerit)
   {
       vertexsets = new ArrayList();
       vertexsetsnorms = new ArrayList();
       vertexsetstexs = new ArrayList();
       faces = new ArrayList();
       facestexs = new ArrayList();
       facesnorms = new ArrayList();
       numpolys = 0;
       toppoint = 0.0F;
       bottompoint = 0.0F;
       leftpoint = 0.0F;
       rightpoint = 0.0F;
       farpoint = 0.0F;
       nearpoint = 0.0F;
       loadobject(ref);
       if(centerit)
           centerit();
       opengldrawtolist();
       numpolys = faces.size();
       cleanup();
   }

   private void cleanup()
   {
       vertexsets.clear();
       vertexsetsnorms.clear();
       vertexsetstexs.clear();
       faces.clear();
       facestexs.clear();
       facesnorms.clear();
   }

   private void loadobject(BufferedReader br)
   {
       try
       {
           boolean firstpass = true;
           String newline;
           while((newline = br.readLine()) != null)
               if(newline.length() > 0)
               {
                   newline = newline.trim();
                   if(newline.startsWith("v "))
                   {
                       float coords[] = new float[4];
                       String coordstext[] = new String[4];
                       newline = newline.substring(2, newline.length());
                       StringTokenizer st = new StringTokenizer(newline, " ");
                       for(int i = 0; st.hasMoreTokens(); i++)
                           coords[i] = Float.parseFloat(st.nextToken());

                       if(firstpass)
                       {
                           rightpoint = coords[0];
                           leftpoint = coords[0];
                           toppoint = coords[1];
                           bottompoint = coords[1];
                           nearpoint = coords[2];
                           farpoint = coords[2];
                           firstpass = false;
                       }
                       if(coords[0] > rightpoint)
                           rightpoint = coords[0];
                       if(coords[0] < leftpoint)
                           leftpoint = coords[0];
                       if(coords[1] > toppoint)
                           toppoint = coords[1];
                       if(coords[1] < bottompoint)
                           bottompoint = coords[1];
                       if(coords[2] > nearpoint)
                           nearpoint = coords[2];
                       if(coords[2] < farpoint)
                           farpoint = coords[2];
                       vertexsets.add(coords);
                   } else
                   if(newline.startsWith("vt"))
                   {
                       float coords[] = new float[4];
                       String coordstext[] = new String[4];
                       newline = newline.substring(3, newline.length());
                       StringTokenizer st = new StringTokenizer(newline, " ");
                       for(int i = 0; st.hasMoreTokens(); i++)
                           coords[i] = Float.parseFloat(st.nextToken());

                       vertexsetstexs.add(coords);
                   } else
                   if(newline.startsWith("vn"))
                   {
                       float coords[] = new float[4];
                       String coordstext[] = new String[4];
                       newline = newline.substring(3, newline.length());
                       StringTokenizer st = new StringTokenizer(newline, " ");
                       for(int i = 0; st.hasMoreTokens(); i++)
                           coords[i] = Float.parseFloat(st.nextToken());

                       vertexsetsnorms.add(coords);
                   } else
                   if(newline.startsWith("f "))
                   {
                       newline = newline.substring(2, newline.length());
                       StringTokenizer st = new StringTokenizer(newline, " ");
                       int count = st.countTokens();
                       int v[] = new int[count];
                       int vt[] = new int[count];
                       int vn[] = new int[count];
                       for(int i = 0; i < count; i++)
                       {
                           char chars[] = st.nextToken().toCharArray();
                           StringBuffer sb = new StringBuffer();
                           char lc = 'x';
                           for(int k = 0; k < chars.length; k++)
                           {
                               if(chars[k] == '/' && lc == '/')
                                   sb.append('0');
                               lc = chars[k];
                               sb.append(lc);
                           }

                           StringTokenizer st2 = new StringTokenizer(sb.toString(), "/");
                           int num = st2.countTokens();
                           v[i] = Integer.parseInt(st2.nextToken());
                           if(num > 1)
                               vt[i] = Integer.parseInt(st2.nextToken());
                           else
                               vt[i] = 0;
                           if(num > 2)
                               vn[i] = Integer.parseInt(st2.nextToken());
                           else
                               vn[i] = 0;
                       }

                       faces.add(v);
                       facestexs.add(vt);
                       facesnorms.add(vn);
                   }
               }
       }
       catch(IOException e)
       {
           System.out.println("Failed to read file: " + br.toString());
       }
       catch(NumberFormatException e)
       {
           System.out.println("Malformed OBJ file: " + br.toString() + "\r \r" + e.getMessage());
       }
   }

   private void centerit()
   {
       float xshift = (rightpoint - leftpoint) / 2.0F;
       float yshift = (toppoint - bottompoint) / 2.0F;
       float zshift = (nearpoint - farpoint) / 2.0F;
       for(int i = 0; i < vertexsets.size(); i++)
       {
           float coords[] = new float[4];
           coords[0] = ((float[])vertexsets.get(i))[0] - leftpoint - xshift;
           coords[1] = ((float[])vertexsets.get(i))[1] - bottompoint - yshift;
           coords[2] = ((float[])vertexsets.get(i))[2] - farpoint - zshift;
           vertexsets.set(i, coords);
       }

   }

   public float getXWidth()
   {
       float returnval = 0.0F;
       returnval = rightpoint - leftpoint;
       return returnval;
   }

   public float getYHeight()
   {
       float returnval = 0.0F;
       returnval = toppoint - bottompoint;
       return returnval;
   }

   public float getZDepth()
   {
       float returnval = 0.0F;
       returnval = nearpoint - farpoint;
       return returnval;
   }

   public int numpolygons()
   {
       return numpolys;
   }

   public void opengldrawtolist()
   {
       objectlist = GL11.glGenLists(1);
       GL11.glNewList(objectlist, 4864);
       for(int i = 0; i < faces.size(); i++)
       {
           int tempfaces[] = (int[])faces.get(i);
           int tempfacesnorms[] = (int[])facesnorms.get(i);
           int tempfacestexs[] = (int[])facestexs.get(i);
           int polytype;
           if(tempfaces.length == 3)
               polytype = 4;
           else
           if(tempfaces.length == 4)
               polytype = 7;
           else
               polytype = 9;
           GL11.glBegin(polytype);
           for(int w = 0; w < tempfaces.length; w++)
           {
               if(tempfacesnorms[w] != 0)
               {
                   float normtempx = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[0];
                   float normtempy = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[1];
                   float normtempz = ((float[])vertexsetsnorms.get(tempfacesnorms[w] - 1))[2];
                   GL11.glNormal3f(normtempx, normtempy, normtempz);
               }
               if(tempfacestexs[w] != 0)
               {
                   float textempx = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[0];
                   float textempy = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[1];
                   float textempz = ((float[])vertexsetstexs.get(tempfacestexs[w] - 1))[2];
                   GL11.glTexCoord3f(textempx, 1.0F - textempy, textempz);
               }
               float tempx = ((float[])vertexsets.get(tempfaces[w] - 1))[0];
               float tempy = ((float[])vertexsets.get(tempfaces[w] - 1))[1];
               float tempz = ((float[])vertexsets.get(tempfaces[w] - 1))[2];
               GL11.glVertex3f(tempx, tempy, tempz);
           }

           GL11.glEnd();
       }
       GL11.glEndList();
   }

   public void opengldraw()
   {
       GL11.glCallList(objectlist);
   }
}
Title: How can one load an OBJ file?
Post by: Achilleterzo on January 12, 2006, 21:07:13
Main class init and render section:


   private void init() throws Exception
   {
       display = new EngineDisplay();
       display.createWindow(false, "Game");
       display.initGL();
       IL.create();
       input = new EngineInput();
       input.initInput(display.displayMode);
       
       camera = new GLCamera();
       camera.setCameraPosition();
       
       String path = "models/p51_mustang.obj";
       try
       {
           FileInputStream r_path = new FileInputStream(path);
           BufferedReader b_read = new BufferedReader(new InputStreamReader(r_path));
           modello = new GLModel(b_read, true);
           r_path.close();
           b_read.close();
       }
       catch(IOException e)
       {
           System.out.println("Could not open file: " + path);
       }
       
       textures = new GLTextures();
       textures.loadTextures();
       
       light = new GLLight();
       light.setLight();
   }

   private boolean render()
   {
       GL11.glClear(16640);
       GL11.glEnable(3553);
       GL11.glShadeModel(7425);
       GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
       GL11.glClearDepth(1.0D);
       GL11.glEnable(2929);
       GL11.glDepthFunc(515);
       GL11.glMatrixMode(5888);
       GL11.glLoadIdentity();
       GL11.glTranslatef(0.0F, 0.0F, z);
       GL11.glRotatef(xrot, 1.0F, 0.0F, 0.0F);
       GL11.glRotatef(yrot, 0.0F, 1.0F, 0.0F);
       GL11.glRotatef(360F - camera.cameraRotation, 0.0F, 1.0F, 0.0F);
       GLCamera _tmp = camera;
       GLCamera _tmp1 = camera;
       GLCamera _tmp2 = camera;
       GL11.glTranslatef(-GLCamera.cameraPos[0], -GLCamera.cameraPos[1], -GLCamera.cameraPos[2]);
       
       // Qui renderizzo il piano:
       GL11.glPushMatrix();
       GL11.glTranslatef(0.0F, -2.1F, 0.0F);
       GL11.glScalef(10F, 0.01F, 10F);
       GL11.glBindTexture(3553, textures.texture[filter]);
       renderCube();
       GL11.glPopMatrix();

       //Qui faccio il rendering dell'oggetto
       GL11.glPushMatrix();
       GL11.glBindTexture(3553, textures.texture[filter]);
       modello.opengldraw();
       GL11.glPopMatrix();
       
       xrot += xspeed;
       yrot += yspeed;
       return true;
   }
Title: very nice
Post by: duodecimo on March 01, 2006, 16:04:30
I came in just now, and only want to thank Elias for this very nice code.
Title: Re: How can one load an OBJ file?
Post by: guillaumesmo on September 07, 2007, 20:33:55
Could someone here please reply to the topic I posted here :

http://lwjgl.org/forum/index.php/topic,2417.0.html

Thank you!
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 07, 2007, 22:32:47
For those interested, I went ahead and updated the sample jar with my newest incarnation of the OBJ loader and TrueType Font Renderer.

www.tommytwisters.com/texturetester.jar (http://www.tommytwisters.com/texturetester.jar)
Title: Re: How can one load an OBJ file?
Post by: tronador on September 24, 2007, 02:53:42
I tried to load objects using the loader but i get the message:

"Your system is not capable of running this game. Please make sure your video drivers are current."

What's wrong?? How i can solve this problem??  :( :( :( :( :(

Any other alternative to load OBJ or any other kind of models in lwjgl ???


Best regards
Title: Re: How can one load an OBJ file?
Post by: Matzon on September 24, 2007, 05:50:55
Quote from: tronador on September 24, 2007, 02:53:42
"Your system is not capable of running this game. Please make sure your video drivers are current."

What's wrong?? How i can solve this problem??  :( :( :( :( :(
I'm guessing that you could try and make your video drivers current  ::)
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 24, 2007, 14:28:23
What kind of video card do you have?
Title: Re: How can one load an OBJ file?
Post by: tronador on September 26, 2007, 03:56:21
Is a  MSI  nVidia 6200 256MB, i download the last drivers but dont works :(
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 26, 2007, 15:44:24
Strange, I've never seen a problem with an Nvidia card before. What OS are you running on? (Please include version, etc..)

Title: Re: How can one load an OBJ file?
Post by: tronador on September 27, 2007, 03:07:17
Quote from: elias4444 on September 26, 2007, 15:44:24
Strange, I've never seen a problem with an Nvidia card before. What OS are you running on? (Please include version, etc..)



Windows XP SP2 [Versión 5.1.2600] (Spanish)
I Have last version of LWJGL
Title: Re: How can one load an OBJ file?
Post by: Matzon on September 27, 2007, 10:08:26
do any of the other lwjgl demoes work ?
Title: Re: How can one load an OBJ file?
Post by: tronador on September 28, 2007, 01:49:07
Quote from: Matzon on September 27, 2007, 10:08:26
do any of the other lwjgl demoes work ?

Yes, all works ok.
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 28, 2007, 13:47:28
Can you run: www.tommytwisters.com/spaceops/spaceops.jnlp (http://www.tommytwisters.com/spaceops/spaceops.jnlp) ?

This is a beta of my current project and uses very similar screen initialization code.
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 28, 2007, 14:29:18
Ok... I've been looking through the code again (been a while). That error specifically comes up when it can't generate a texture ID. Have you tried other lwjgl demos that use textures? Do you know how much memory your card has?

Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 28, 2007, 14:36:46
I also just found this link that mentions several people having similar issues with certain Nvidia card and motherboard combinations: http://forums.nvidia.com/index.php?showtopic=22336 (http://forums.nvidia.com/index.php?showtopic=22336).

Out of curiosity, what kind of motherboard/chipset/processor do you have?

Title: Re: How can one load an OBJ file?
Post by: tronador on September 29, 2007, 00:48:41
Motherboard Intel Pentium D101G, Processor Intel Pentium 4 HT

The spaceops beta works 100% ok, load all textures ok
Title: Re: How can one load an OBJ file?
Post by: elias4444 on September 30, 2007, 17:27:36
Ok, I've updated the texturetester to my latest screen code, so feel free to try it again and let me know how it goes. I've also updated the source code at www.tommytwisters.com/texturetester.jar (http://www.tommytwisters.com/texturetester.jar) with the changes.
Title: Re: How can one load an OBJ file?
Post by: tronador on October 06, 2007, 21:48:33
Trying to run i get this message:
Exception in thread "main" java.lang.NoClassDefFoundError: javolution/util/FastMap
Title: Re: How can one load an OBJ file?
Post by: tronador on October 06, 2007, 22:24:25
I'm getting information the error and i think that this is the problem:

GL11.glGenTextures and GL11.glGenLists produces a Exception

Trying to run another loader (MD2 Loader by Kevin Glass) i get this exception:

java.lang.NullPointerException
at org.lwjgl.opengl.GL11.glNewList(GL11.java:2196)

i read in a mailing list that is because it can't allocate memory on video card to create new display list  :-\ :-\ :-\



Is possible test it in software mode or solve my problem???

Solved: The trouble was that i try to load a model before initialize GL

Title: Re: How can one load an OBJ file?
Post by: elias4444 on October 07, 2007, 02:07:38
QuoteTrying to run i get this message:
Exception in thread "main" java.lang.NoClassDefFoundError: javolution/util/FastMap

Ugh... I downloaded a newer javolution library and it got mixed into the last build. I've updated it now. It should work.

Title: Re: How can one load an OBJ file?
Post by: nicolasbol on August 11, 2008, 03:33:39
That's an old thread but It may interest someone, I wrote a JAVA OBJ loader with MTL and texture support, rendition is LWJGL based.

http://fabiensanglard.net/Mykaruga/index.php

(http://fabiensanglard.net/Mykaruga/ScreenShot5Mini.png)