How can one load an OBJ file?

Started by elias4444, January 27, 2005, 00:13:05

Previous topic - Next topic

elias4444

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?
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

elias4444

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?
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

Fool Running

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: )
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

elias4444

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/
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

elias4444

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.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

elias4444

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.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

CaseyB

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

crash0veride007

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();
   }
}

CaseyB

@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!

elias4444

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
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

CaseyB

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!

elias4444

=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

crash0veride007

hey elias when can we expect to see mesh animation support added?  :wink:  he he

elias4444

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.
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

Evil-Devil

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

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