org.lwjgl.util Model

Hi there !
I was designing my own 3d animated model file when I remember the Princec’s post about the org.lwjgl.util package… So I grabbed it and just go through the source…
First thing I can say : It’s very well designed ! I don’t think it is fully optimized but it looks great !
So I plan to use this package for my project (so as I won’t loose time doing another loader) but I can’t find any demo or example on how to use it…
Does anyone made an application example about using the model thing ?

Chman

Well, what’s there in CVS is purely an internal storage format (ie. it’s for loading into memory and keeping there). It can be loaded from XML but currently there’s no XML exporter available for any tools, nor any converter to XML from any known format :slight_smile:

…and what’s more I haven’t finished the example renderer code that draws a model but it really is just example code. Once you’ve got your model in memory you’ve probably got your own ideas about how to render it. Essentially you need the notion of a “3D sprite” - something with persistent state which can be used to draw the model at a particular frame of animation in a particular location.

The bone-based animation version is a bit more, er, hairy and requires some thinking and maths to use.

So in summary what we’ve got in CVS is just a small part of the Big Old How To Draw 3D Models Problem:

tool->exporter->XML->loader->LWJGL Model->Renderable Model->drawing code

Cas :slight_smile:

i just went through the code, looks very nice. Just one small thing; Your using DOM to load the XML, is there a reason to choose it instead of SAX?

Because I’m a n00b and DOM is easier.

Cas :slight_smile:

accurate reason ;D

Sax is so much boring …

By all means someone please write a SAX loader. But the primary sensible way to deploy models in a final application is probably to load them in and serialize the object at compile time and deploy it like that.

Cas :slight_smile:

[quote]Because I’m a n00b and DOM is easier.
[/quote]
That can’t be furthur from the truth. Just look below:


public class TileMap {
      ProcessTileMap ptm;
      public TileMap(String src) {
            File f = new File(src);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setValidating(false);
            ptm = new ProcessTileMap();
            try {
                  SAXParser parser = factory.newSAXParser();
                  parser.parse(f, ptm);
            } catch (ParserConfigurationException pce) {
                  pce.printStackTrace();
            } catch (SAXException spe) {
                  spe.printStackTrace();
            } catch (IOException ioe) {
                  ioe.printStackTrace();
            }
      }
      
      public TileMapHolder getTileMap() {
            return ptm.tm;
      }
      
}
class ProcessTileMap extends DefaultHandler {
      public TileMapHolder tm;
      public ProcessTileMap() {
            tm = new TileMapHolder();
      }
      public void startElement(String uri, String localname, String qName,
                  Attributes attrib) {
            
            if (qName.equalsIgnoreCase("map")) {
                  int width = Integer.parseInt(attrib.getValue("width"));
                  int height = Integer.parseInt(attrib.getValue("height"));
                  tm.initialiseMap(width, height);
            }else if (qName.equalsIgnoreCase("image")) {
                  String name = attrib.getValue("name");
                  String src = attrib.getValue("src");
                  tm.addImage(name, src);
            }else if (qName.equalsIgnoreCase("tileProperties")) {
                  float width = Float.parseFloat(attrib.getValue("width"));
                  float height = Float.parseFloat(attrib.getValue("height"));
                  tm.setTileDimension(width, height);
            }else if (qName.equalsIgnoreCase("tile")) {
                  int x = Integer.parseInt(attrib.getValue("x"));
                  int y = Integer.parseInt(attrib.getValue("y"));
                  String value = attrib.getValue("image");
                  tm.setTileValue(value, x, y);
            }
            
      }
}

couldn’t get any simpler and faster!

Except if you write it in groovy where last method could look like

tm.initaliseMap(xml.map.width$,xml.map.height$)
xml.image.every {tm.addImage(it.name$,it.src$) }
xml.tile.every {tm.setTileValue(it.image$,it.x$,it.y$ }

IMHO, groovy/GPath is only way to read xml which does not suck. I have tried 5 or 6 other APIs and in all cases I have ended with a lot more noise of dispatch/casting/if ladders than actual logic.

The only problem I’ve noticed with Java and SAX is that SAX is a “sequential construction” API whereas Java is a “one-shot fire-and-forget” system.

(This, incidentally, is one of the many areas where java is a bitch to write good library code, because only being allowed to do the constructor in a single method call is too restrictive for many real life cases.)

I would use DOM except that:

  • names of classes and interfaces in API suck (irritatingly confusing)
  • API is unwieldy (I struggle to believe that such a system had to have such a complex API)
  • doesn’t SEEM (am I wrong here?) well-suited to debugging and sequential development

SAX is conceptually incredibly simple to use (indeed, the S stands for SIMPLE does it not?) and I find other coders who haven’t used it are able to view edit and maintain source with no learning curve (since it follows the traditional “recipe style” algorithm: you just write down what you want it to do sequentially, triggered off events).

OTOH Sun have shafted SAX a bit by providing an implementation in 1.4 which can’t handle exceptions properly (nb: try throwing a nullpointerexception in some SAX code, and see what exception the java runtime then reports. hint: it throws away all the info on what exception actually occurred and where, due to a bug in the exception chaining)

[yes, I did log the bug with Sun a looooong time ago (and they accepted it). I’m pretty sure that it’s still not fixed though…]

These two problems are fixed by jdom (http://jdom.org/) I find it’s API quite reasonable. Problem is rather with java - similar to lack of operator overloading (which would do magic for readibility of non-primitive math code) - there is no way of expressing syntax which would make xml parsing concise.

Maybe some kind of annotation magic combined with reflection will do the trick and we won’t have to write any xml parsing code at all ?

sry to revive this thread from the dead. But Jme has a fully functional XML model format which can be converted to binary to reduce size.

We can convert from 3ds, md2, ms3d, msascii to the jme format. And it loads faster than md2 files!

Both animation types are supported, vertex deformation and joint animation. Others are forthcoming.

I have written a MaxScript to export any model from max to the xml format, so modeling becomes alot easier.

DP

Jme thats an engine right?

http://www.mojomonkeycoding.com

jME can turn XML into binary code to be read by the engine. For example, DarkProphet wrote an extreamly small export script for 3ds that exports animations directly into jME format. The jME binary code can also directly port back to XML.

I used SAX and a stack to keep track of my position in the code. It’s a lot easier than DOM and pretty slick if I say so myself :slight_smile: Definantly a model for how I would code any SAX in the future.

But yea, jME supports turning 3ds, obj, md2, md3, ms3d, ase all into XML format with animations and material states to be read by the engine. An XML format for modeling is the way to go, as long as it’s simple to use. It allows people using Blender, Maya, Max to export directly into your game with easy to write scripts.