JOGL (JSR-231) Model Loaders and Utility Demos

I see that one of the most often asked questions for JOGL is where can I get model loader or is there any example code for doing
I am in the process of writing a few loaders and utilities for JOGL (JSR-231) which will be used in my personal java.net project JGLMark.
JGLMark (https://jglmark.dev.java.net/) is open source and I intend it to be a Java OpenGL benchmark.
I will make regular update posts here as I progress with the loaders and utlities in hopes that I can receive FeedBack from the community on them and so that I may best optimize them as well as give something back to help improve the community as a whole.
I am also always looking for good help to join the JGLMark team as well… :wink:

NEW
I have ported some of the RedBook examples to JOGL (JSR-231), additionally I am adding some examples using the code snipets throughout the book which were never formed into full .c examples. An example is the primitives from chapter 2, the primitves are explained and there are a few code examples of them but nothing as a full example. For more info see below…

So on to the good stuff…
The code can be downloaded from JGLMarks Downloads section here:
https://jglmark.dev.java.net/servlets/ProjectDocumentList?folderID=5582&expandFolder=5582&folderID=0

The Main Entry point is GLDemoApp. For now to fire up the different Listeners, modify this line:
canvas.addGLEventListener();

The Code thus far:

PACKAGE---------------------------------------------------------------------------------------------------------------------------------------------------
GL.JOGL

Textures
Status: Done
Listener: SimpleTextureListener
Dependent Utility Classes: none
Desciption: Example of loading and using Textures in JOGL (JSR-231)

GLSL
Status: Done
Listener: SimpleGLSLListener
Dependent Utility Classes: GLSLShaderUtil
Desciption: Example of loading and using GLSL Vertex and Fragment Shaders in JOGL (JSR-231)

JOGL OBJ Model Loader
Status: In Progress
Listener: SimpleOBJModelListener
Dependent Utility Classes: OBJModel, OBJModelVBO
Desciption: Example of loading and using OBJ Models in JOGL (JSR-231)
So Far I have implemented loading and handling of:

  1. Vertex data
  2. 3D texture coordinate data
  3. Normal Data
  4. Load models using Vertex Arrays (OBJModel)
  5. Load models using VBO’s (OBJModelVBO)
  6. draw the model
    TO BE DONE…
  7. Implement support for OBJ Groups
  8. Implement support for OBJ Materials and Textures
  9. Implement support for OBJ Mesh Smooth Groups

Vertex Buffer Objects (VBO)
Status: Done
Listener: SimpleVBOListener
Dependent Utility Classes: none
Desciption: Very Simple Example of using VBO’s in JOGL JSR-231

Lighting and Materials
Status: Done
Listener: LitTeapotListener
Dependent Utility Classes: OBJModelVBO
Desciption: Very Simple Example of using Lighting and Materials in JOGL JSR-231

PACKAGE---------------------------------------------------------------------------------------------------------------------------------------------------
GL.LWJGL

Textures
Status: In Progress
Class:
Dependent Utility Classes: none
Desciption: Example of loading and using Textures in LWJGL

GLSL
Status: In Progress
Class:
Dependent Utility Classes: GLSLShaderUtil
Desciption: Example of loading and using GLSL Vertex and Fragment Shaders in LWJGL

LWJGL OBJ Model Loader
Status: In Progress
Class: OBJModelDemo
Dependents Utility Classes: OBJModelVBO
Desciption: Example of loading and using OBJ Models in LWJGL
So Far I have implemented loading and handling of:

  1. Vertex data
  2. 3D texture coordinate data
  3. Normal Data
  4. Load models using VBO’s (OBJModelVBO)
  5. draw the model
    TO BE DONE…
  6. Implement support for OBJ Groups
  7. Implement support for OBJ Materials and Textures
  8. Implement support for OBJ Mesh Smooth Groups

Vertex Buffer Objects (VBO)
Status: In Progress
Class:
Dependent Utility Classes:
Desciption: Very Simple Example of using VBO’s in LWJGL

NEW
OpenGL Programming Guide (RedBook) examples as well as code snipets from the book formed to full examples
Status: In Progress
Package: RedBook.zip

Please post or Email me your suggestions, feedback, and or if you’d like to volunteer to help the effort/Join the JGLMark team.

Package updated to now contain LWJGL demos as well

i really like the idea of generic loaders. I was interested in the Collada loader that was developed for the Xith project, but I don’t want to use Xith just to get that utility! I think the loaders should be generic and people should write backends into Xith, JME, etc, or thier own engine.

Good luck with your project :slight_smile:

Updated
05/30/06

Added JOGL (JSR-231) OpenGL Redbook examples as well as code snipets from the book formed to full examples.

Hello !

I’ve glanced over your code, and I noticed your OBJ loader also implements the display() method, from the GLEventListener interface. It’s really only a detail, but in working this way, I believe you’re not taking the OO principle to its extreme. In a perfect world, I think the concern of loading some geometry should be separated from the in-game object that is responsible for state like direction, size, and other attributes, and of course the responsability of actually drawing the thing :slight_smile:
Since you’re not separating the parsing, and the drawing of your geometry, you’re forced to write a new parser for every combination of 3D-format, and 3D library. If you wish to support 10 3D file formats, and 4 3D libraries, you’ll need 10 * 4 classes. If you separate your concerns, ideally you should only need 10 + 4 classes.

I’ve been fantasizing about a generic, plug-and-play library to read/load/write any type of model file, and here’s my $.2:

  • My immediate inspiration is the SAX XML parser interface. If you know how that works, this should sound very familiar
  • For every imagineable model file, we would need 2 classes. One to read the model, and one to write it. So there would be a OBJReader, a OBJWriter, a 3DSReader and a 3DSWriter, etc etc
  • each of the Readers have constructors that take 2 arguments: an inputstream and a writer interface. If we model our readers after the java.io package, it will become easy to read a model from a file, an internal URL, a resource stream, etc.
  • a writer has constructors with arguments according to its function. For example, a OBJWriter, 3DSWriter, etc are supposed to write to a stream, so they could have an outputstream as argument. But “special” writers could be writubg to store a file in memory, in your own propietary format, or immediately into a compiled display list!
  • every writer implements the same interface. It contains all “entities” you could ever find in a 3D model file, and it would look something like this:

public interface ModelWriter {
  public void foundVertexCoord(string id, double x, double y, double z);
  public void foundTexCoord(string id, double v, double t);
  public void foundNormalCoord(string id, double x, double y, double z);

  public void beginTriangleStrip(String id);
  public void endTriangleStrip(String id);

  public void beginGroup(String id);
  public void endGroup();
}

  • In order to read a 3DS model and store it into an OBJ file, your code would look like this:

OBJWriter out = new OBJWriter(new FileOutputStream(new File("example.obj")));
3DSReader in = new 3DSReader(new FileInputStream(new File("example.3ds")), out);
in.parse();
out.close();

  • A reader would call the appropriate methods on the interface, each time it discovers one of those entities in the source file. In case of the OBJReader, for example, if the line starts with “V”, it would call ModelWriter.foundVertexCoord() with the appropriate coordinates (since obj files don’t have explicit id’s, you can “autogenerate” one: id “1” for the first v found, “2” for the second, etc)
  • The OBJWriter, on the other hand, implements the ModelWriter interface. Each time the method foundVertexCoord() was called, it would write “v $x $y $z” to the outputstream

Does that make sense?
Personally, I think designing the ModelWriter interface will be the hardest. But the pay-off would be huge: the next time you wish to read some models into your own program, you simply need to write one class: one that implements the ModelWriter interface. After you’ve done that, you can parse every single format a Reader has been defined for!

Unfortunately, I know very little of graphics file formats, so I’m not sure if one interface could capture all possibilities inside all possible 3D files. I could contribute, by setting up an example interface and an OBJReader and OBJWriter, but that’s about the only format I know (and I’m excluding the smooth curves data, here), and it’s probably enough of a commitment for me :wink:

[quote]I’ve glanced over your code, and I noticed your OBJ loader also implements the display() method, from the GLEventListener interface. It’s really only a detail, but in working this way, I believe you’re not taking the OO principle to its extreme. In a perfect world, I think the concern of loading some geometry should be separated from the in-game object that is responsible for state like direction, size, and other attributes, and of course the responsability of actually drawing the thing
[/quote]
I could not agree with you more… The loader is that way for that example case, the long run plans are to do exactly as you propose.

[quote]immediately into a compiled display list!
[/quote]
VBO would be the best way to go for this Optus has been working on and has pretty much perfected Immeadiate VBO for this…
Ex:
scheme.add(new Interleavable(Interleavable.Type.TexCoord, 2, 4));
scheme.add(new Interleavable(Interleavable.Type.Normal, 3, 4));
scheme.add(new Interleavable(Interleavable.Type.Vertex, 3, 4));
Interleavable stc1 = new Interleavable(Interleavable.Type.TexCoord, 2, 4);
stc1.setUnitId( 0);
new InterleavedVBO(scheme, GL_QUADS, count, draw_mode);
ivbo.bind (texture unit, texture id);
ivbo.begin();
ivbo.texcoord(texture unit, U, V);
ivbo.normal(X, Y, Z);
ivbo.vertex(X, Y, Z);
ivbo.end();

[quote]every writer implements the same interface. It contains all “entities” you could ever find in a 3D model file, and it would look something like this:
[/quote]
The difficulty will be dealing with the way each individual format’s handling of translating it’s so called “standard” respective V,T,N coord’s into face data.

Overall I like your proposal, and we will certainly take any help we can get shoot me a mail and we can maul over the details.

I’d love to, but why don’t we write it out here, in this thread? With any luck, someone stumbles in here and gives some valid comments as well :smiley:

I don’t know too much about VBO’s. I’m reading up on it now 8)

Really? How? We overload the different datatypes (integer, float, and double coordinates) just like openGL does. Is there another difference in coordinates?

By face data/ data format I mean mainly the format by which it is interpreted. Take for example an OBJ file…

–> header

ASCII

Wavefront OBJ file

num_vertices: 8

num_vertex_normals: 8

num_uvs: 36

num_faces: 12

num_groups: 1

–> Material file
mtllib box.mtl

Vertice data
v -10.200000 -10.345192 -10.138821

Normal data
vn -0.666667 -0.666667 -0.333333

Tex coord data
vt 0.000000 0.833468

–> begin a group
g Box

–> which material to use
usemtl Box

–> now comes the face data (this is where formats differ the most… How do we interpret a geometric face from the V, T, N data
f 8/1/8 7/2/7 6/3/6

So for this example we see that we have vertex, normal and tex coord data and that the first three V,T,N coords are:
Vertex entry #8, tex coord entry #1, and normal entry #8… and so on… This is where the difficulty comes in of interpreting the various formats, they all seem to have a different way of handling the face data…

I’m with you so far. How different can it be in other 3D formats? I assume they also have a way to tell you that a face exists of three normals, with their V, T and N coordinates.

Our generic java interface should simply provide a method to define this face. A naive way to do this would be:


public void defineFace(Point3D V[], Point3D T[], Point3D N[]);

So the class that is responsable for OBJ files, would look for lines that start with “f …”, parse the indices, look up the coordinates for these indices, and put them in the arrays. Then it would call the defineFace() method.

The class responsable for 3DS files, would look into a binary file at offset such and such, read a couple bytes, determine that it needs to define a face. Then lookup all the vertices for this face at offset such and so, and finally call the same defineFace() method.

Here’s my 2 cents:
I think making a general enough interface is going to be very difficult. You should propably look at the most general format you can find/want to support (collada?) as a basis for defining your interface. Obj is probably too limited for this, since IIRC it doesn’t support things like animation, shaders, …
From a performance point of view, I would not try to resolve the vertex/tex coord/normal indices at load time. Retaining the data tables and the indices will save quite some memory and will probably gain you some rendering performance as well. Also, this will allow you to read for instance an obj file and later write back an identical file. If you resolve data at load time the obj file you produce might possibly contain many duplicated vertices and be quite a bit larger than the original version was.

Hej hej!

What is the good work doing, what is the current status?
Is there already a way to take advantage of one of the model loaders for JOGL? :smiley:

A big fan waiting for something like this!
Eric

A project has been started to address extended JOGL functionality as mentioned above, and to try and eliminate further “re-inventions of the wheel”. I am merging my examples and utilities into this project.
https://joglutils.dev.java.net/

Stay Tuned…