Java Universal Model Importer (JUMI) - Early Alpha

Hi everyone,

I’ve been working on and off on a library for importing 3D models from various formats and converting them into a single standard data structure for easy use and manipulation. So far I’ve been working on OBJ and FBX binary formats, with the intention of including FBX ASCII and Collada formats in the near future and then continue to build until I get sick of it basically. Work is pretty heavy going at the moment so development on this has slowed a bit, but since it seems to work pretty reliably I thought I’d release a rough build for people to play with and give feedback on. I’ve tested it with around 20 OBJ and FBX models downloaded from TF3DM so far.

An early build is available here: https://github.com/RGreenlees/JUMI-Java-Model-Importer

Unfortunately I don’t have a lot of time at the moment, so there’s no detailed documentation. This is top of my list of priorities but it might take a bit of time. It is capable of importing the following:

  • OBJ models (including parsing the material library). Can also handle relative index notation (with negative indices)
  • FBX binary models (SDK version 6.0 and up tested)
  • Vertices, UVs and normals
  • Texture information (including embedded texture data for FBX files)
  • Material data
  • Skeleton (FBX only)

Each mesh definition in the FBX file, and each group or object in the OBJ file will be treated as a separate mesh object with its own vertices, normals and UVs assigned, so to render the whole scene just batch up your models accordingly.

I have added some utility functions including the following:

  • Triangulate mesh (only supports quads at the moment)
  • Flip UVs (horizontal and vertical)
  • Scale mesh
  • Set the mesh’s max extent (i.e. The distance of the furthest point from the origin). Useful if you want the mesh to be a certain size.

Some example code:


JUMIScene scene = JUMILoader.loadModel("C:/models/sponza.obj"); // Let's load Crytek's Sponza model

JUMIMesh sampleMesh = scene.getMeshByIndex(0); // Grab the first mesh in the scene

System.out.println(sampleMesh);

JUMIMaterial sampleMaterial = sampleMesh.getMaterialByIndex(0); // Grab the first material defined on the mesh

System.out.println(sampleMaterial);

JUMITexture sampleTexture = sampleMesh.getDiffuseTexture(); // Let's look closer at this material's defined diffuse texture

System.out.println(sampleTexture);

for (JUMIMesh a : scene.getAllMeshes()) {
   a.triangulate(); // We want to render with GL_TRIANGLES
   a.setScale(0.1f); // Shrink it a little
   a.flipUVY(); // Our model uses DX coordinates so need to flip for OpenGL
}

// Begin loading geometry

float[] modelVerts = sampleMesh.getVertices();
float[] modelUVs = sampleMesh.getUVs();
float[] modelNormals = sampleMesh.getNormals();
int[] modelIndices = sampleMesh.getVertexIndices();

// Create buffers and load into VBO etc.


Your output from the above calls to println might look like this:

In this case OBJ models never have embedded texture data, but some FBX models have and if they do, you can retrieve the binary from the JUMITexture object.

This should hopefully prove useful to someone out there. I have kept it out of the WIP showcase as it is still very rough. Here are a list of features still missing:

  • Parsing animation data from FBX files. Might need some help as it’s bloody confusing and I’m not sure what it should look like in the JUMI structure
  • Associating diffuse/normal/specular textures to materials in FBX. Can’t see a way to determine that texture A is this material’s diffuse map. All textures get lumped into the “Unassociated textures” section for now
  • The code is messy in places, including a hideous series of if-else statements using instanceof. Once I’m happy with my data structures I’ll go back and tidy this up and make it all neat
  • Bone data is missing weights and vertex references. Until I sort out animation it’s kind of pointless anyway

Finally, some performance stats using my Quad-core i7:

OBJ

Sponza.obj (381 meshes, 184k vertices total) = 1.5s to create scene
Dragon.obj (1 Mesh, 439k vertices total) = 7.5s to create scene

FBX

Standard character mesh (1 mesh, 9k vertices total) = 0.3s to create scene
Detailed character mesh (10 meshes, 33k vertices total) = 0.4s to create scene

Thanks!

Please consider supporting OpenGEX! A unified solution that supports everything I need would be amazing.

Do you support skeleton animation?

I intend to add support for skeletal animation, it’s still a work in progress at the moment. My main issue is that I’m new to the technical implementation of skeletal animation, so I’m unsure how to structure the data. Any advice anyone can offer would be really appreciated, and it should help me interpret the data in the FBX file as well.

In the meantime, the bone structure is imported, so you can at least query the skeletal structure. There’s a bug which is preventing the weights being imported properly so I’ll fix that when I have time.

With regards to additional formats, I intend to support as many as possible. The only limitations are that if they are binary formats, I’ll need a specification of some sort to help parse it, as I don’t have the time right now to figure it out the hard way :frowning: Formats like 3DSMax and Maya are closed source, so trying to crack it will take a lot of trial and error. I’ll take a look at OpenGEX though :slight_smile:

Hi

A standalone JAR is enough for me especially if JUMI has no dependency, otherwise I advise you to use Maven, it would ease the use of your library.

Numerous engines support the WaveFront OBJ format and LibGDX fbx-conv supports FBX as its name implies. In my humble opinion, writing a parser for Collada is difficult and you should support a lot of formats if you want to drive your library really appealing. Assimp and OpenCTM can be good sources of inspiration. You can find some importers written in Java (MD2, MD3, MD5, LWO, ASE, 3DS, STL, PLY, Collada, Blender, Maya, BHV, MS3D, OFF, Ogre, X, …) in Unlicense-lib, JMonkeyEngine 2 & 3, LibGDX, JogAmp’s Ardor3D Continuation, Java3D, JOGL-Utils and Xith3D.

Someone else works on jassimp, maybe you could work together.

Your library can become a good source of inspiration to write importers for engines too (if you succeed :wink: ). Do you plan to implement the export too (for example to convert a single frame of a MD2 into an OBJ file)?

FBX is very famous and widely used but it has no public specification, it isn’t well defined, it is changing. Is it a good idea to focus on it?


Maybe xbuf might be useful too.

Hi gouessej,

Thanks for the feedback. I didn’t actually realise there were so many model libraries written in Java, I guess my Google-fu isn’t as strong as I thought! My ultimate vision, so to speak, is a standalone library with no dependencies (that is very important to me as well), that will load any kind of format you can think of and present it as a single, unified and consistent structure. The idea being that for anyone writing an engine, they only need to parse the JUMI format (which will be thoroughly documented) because JUMI itself will worry about the specifics of FBX, OBJ, MD2 etc.

Obviously that’s a big undertaking, so for now I’m just working on one format at a time. What I would like help with is understanding what the data should look like for animation. I understand the basic concepts of skeletal animation, but I could really use some help designing a data model that people will instantly recognise and is intuitive. Then I’d just convert whatever animation system the source format uses to that bespoke design. For older formats that don’t use skeletal animation (like MDL, MD2 etc.), JUMI would probably represent the keyframes as morph targets.

PS: I also want to handle exports too. By using that single data structure, it should then be easy to reverse the process and write back into any of the supported formats.

Ok but an interchange format (like U3D, OpenGEX, xbuf, Collada) doesn’t have the same constraint than a runtime asset format (GLTF). Then, you’ll have to make a decision.
I talked about using your library as a source of inspiration for engines because I thought that in this case, using the abstractions of an engine reduces the overhead. Actually, you will write lots of classes that we typically find in a 3D framework or engine. In my humble opinion, as a programmer responsible for engine support in the JogAmp community, I would be reluctant to put a third party library into an engine knowing that there is a lot of duplication.

There is an example of model using skeletal animation here.

Take care of basing your design on something flexible enough to support several formats. Designing a “better” format to use as an intermediary is very difficult too. Collada has become very complicated, especially since its version 1.4.

You’re right, this is what I did in JogAmp’s Ardor3D Continuation to export the meshes in WaveFront OBJ. I’m just a bit worried because some projects like MeshLab and Assimp are very time consuming, lots of people work on them. JMonkeyEngine 2 supports lots of formats but some importers weren’t correctly maintained. Why would you succeed in doing something that numerous motivated developers failed? I don’t try to discourage you but I see some pitfalls in your plan.

To sum up, if you don’t succeed in convincing the developers to use your “super” format (similar to the approach of OpenCTM), you’ll have to convince them to embed your library as is (similar to the approach of Assimp). If you fail, it will still be a good candidate to implement a viewing application similar to MeshLab but you can’t compete with 3D engines and frameworks developed by numerous developers except if you’re a genius. In my humble opinion, sticking to something less ambitious is more viable, for example by avoiding to design a “better” format than the Khronos Group, Adobe and the others, and by keeping your library extremely lightweight so that you have at least a vanishingly small chance to convince engine maintainers to use it (a very few Java developers use their own engines in 3D applications on the long term).

Another solution consists in contributing to those middle and high level APIs instead of working on a separate library. The developers of Unlicense-lib would be very glad to get some help to support much more formats. JogAmp’s Ardor3D Continuation is still compatible with ardor3d-openctm…

Damn, couldn’t you have released this 6 months ago, you made me write my own! hahaha this is cool! I could give some pointers about the animation, only problem is that I have to bake the animation to my skeleton before export, so it’s not really user friendly as it’s FK only.

Will you be supporting IQM? By far the best (super subjective).

IQE seems to be a bit easier to support. Excellent suggestion. Thank you.

Thanks, I’ll take a look. I think I’m partially limited by lack of time (30 minutes here and there on the train isn’t a great learning environment), and lack of sleep (2 kids…)

Based on the above and your other comments, perhaps instead of creating my own JUMI format, would it be worth adopting an existing format such as GLTF and look to create a library that can read from a series of formats and export to a choice of existing runtime formats, and/or change the JUMI structure to mimic that of GLTF for manipulation through code? That would appear to resolve a number of issues around trying to push a “better” format, duplication of existing engine structures like materials etc.

Why not? :wink: I’ll take a look once I’ve addressed gouessej’s points above and stabilised the target structure.

In my humble opinion, it’s an excellent idea, just choose the format to mimic very carefully, GLTF is a good candidate, OpenGEX too as it has some importers for Blender, Maya and 3D Studio Max. It depends on what you want to achieve. Look at this document, especially the page entitled “gltf pipeline - overview”. If you’d like to create a tool that targets the engines, choose gltf. If you’d like to create a tool that targets the modelers and some engines, choose Collada or OpenGEX. As far as I know, the Blender OpenGEX exporter exports the actions/animations unlike the Blender exporter that only exports the very first key frame :frowning: Collada is known to be bloated but it is very capable. Your architecture should support the common subset of features in OpenGEX and Collada. There is already a tool to convert the models from Collada to gltf. You could start by implementing a very simple WaveFront OBJ exporter and pick Collada and/or OpenGEX later.

The problem is that JMonkeyEngine 3 supports a very few formats (OBJ, Blend, OgreXML), I don’t know exactly how well it supports Collada. JogAmp’s Ardor3D Continuation supports Collada 1.3. LibGDX supports Collada in fbx-conv. That’s why Collada seems to be a good candidate to me.

IAFAK jMonkeyEngine 3 does not support Collada to any extent. It does not seem to be a big problem since many jME-developers use Blender and make the conversion in Blender. Then export to OgreXML or save as blend-files.
I think many developers have a similar pipeline, i.e. you read models into a modeling tool, touch up and make them fit the game/game engine you are using. So I would suggest to O.P. that one necessary step in having people adapt a new file format is that there must already be high quality exporters for popular modeling tools. Writing importers isn’t that big of a deal in your own code compared to not having an exporter for e.g. blender, maya, make human et c.

Someone tried to contribute but his plugin is no longer maintained :frowning:

It becomes less straightforward when you want to edit existing models whose formats aren’t supported by Blender. Since its version 2.50, tons of importers have been dropped and even Collada isn’t fully supported especially when exporting actions/animations. Blender Python API changes very often which drives the maintenance of external scripts very hard especially for someone with a little experience in Python :s

As far as I know, many computer artists use several tools to take advantage of all their features, the interchange formats are very important and the blend format isn’t a long term storage format, it is the format of an editing tool. OpenGEX has an excellent support of the most used modelers.

Hi Neoptolemus,

I am doing a port of Assimp, may be coordinates our efforts togethers?

I choose Assimp since is the most used importer out there and is open source.

I already wrote the md2 importer since I needed it. I am writing the validation part right now

What do you tell me?

Hi elect,

I was originally looking to do a port of Assimp, but I felt that it was enough work as it was learning the basics of how a 3D model is structured, and the file formats themselves, without also learning an existing library on top of it! You’re free to use any of my source code in your endeavours, just give me a credit somewhere if you do :slight_smile: Unfortunately I am currently unable to do any further development as RL stuff has meant I can’t really dedicate any time to this or JOML (which KaiHH has kindly taken over for me!).

Hi Neoptolemus,
sad to hear that you can’t join me contributing to JOML. You are always welcome to do so! :slight_smile:
However, it so far was a real pleasure and JOML has really come along ways since its early days, which is now more or less around half a year ago.
Big thanks for the vision and introducing JOML in the first place!
Looking forward to seeing some commits from you. :slight_smile:
Cheers,
Kai

Hi Neoptolemus,

thanks for your offer, but my idea is to keep sticking as much as possible to the Assimp structure in order to facilitate any Assimp dev switching and make it the easiest as possible (or to put in another way, less traumatic as possible ;D).
This will hopefully also reduce the admount of work in order to keep it update with Assimp.
Anyway, I will be glad to give you credits, at least for your attempt and your intent! It will go right into the wiki as soon as I find it is time to write it, feel free to modify it by yourself if you have some spare time :wink:

Thanks Kai :slight_smile: I would like to go back at some point, though I still need to brush up on my maths skills a bit!

Good luck! jAssimp will be awesome when it’s ready, as right now there are a dozen examples of a Java-based OBJ parser (including JUMI!) but pretty much none covering the other formats. The real benefit will come from animation, which I never quite managed to implement in JUMI. I think I could have done with a 20 minute session with someone knowledgeable on the subject to just explain the principles behind it, which would have helped when looking at the data structures. But good luck and I look forward to using jAssimp in the future :smiley:

Hi guys,

so I am done with most of the core stuff.

I am writing some post process effect now, such as triangulationMesh

I saw there is some interested people having a jAssimp, like here and here.

I decided now to start riching the readMe and asking for help.

Project is here, you are very welcome to help :slight_smile:

I still see only MD2 and nothing else. Am I wrong?