Assimp-based model import and the MonkeyWrench library

Here’s the October WIP screenshot in ortho(graphic) projection:

As @bloodwalker pointed out, the texture of the model of the left is smoother. I believe that’s due to a different min filter on the base-color texture.

  • The model on the viewer’s left was imported using MonkeyWrench. Its base-color texture uses a Trilinear min filter. (The texture description is
    CesiumMan/glTF/CesiumMan_img0.jpg (Flipped) (Mipmapped) mag:Bilinear min:Trilinear aniso:0 s:Repeat t:Repeat
  • The model on the viewer’s right was imported using jme3-plugins. Its base-color texture uses a NearestLinearMipMap min filter. (The texture description is
    CesiumMan/glTF/CesiumMan_img0.jpg mag:Bilinear min:NearestLinearMipMap aniso:0 s:Repeat t:Repeat

I’ll study the glTF file and try to determine which filter is more correct.

The model specifies a sampler with "minFilter": 9986

and the spec says that’s the value for NEAREST_MIPMAP_LINEAR.

Good catch!


I just noticed that the Assimp repo includes a Java binding named “jassimp”. Yet another approach to try in case LWJGL doesn’t work out for some reason …


Yeah, for example, if you want Android support, the lwjgl-based approach might not work. (?)


That’s a good point.

In most cases, model assets should be converted to J3O during game development, not while the game/application is actually loading/running. Since I don’t expect game development to take place on mobile devices, the capability to run MonkeyWrench on Android/iOS didn’t seem necessary.

However, one can imagine games that allow users to add custom content at runtime, in which case the limitation might prove inconvenient.


After solving many bugs in my material builder, MonkeyWrench now does a better job of converting materials than jme3-plugins does … but not for long!

I filed a few issues against jme3-plugins:

and already 2 of them have solutions in progress:

I’m always glad to see Engine improvements in the works. Thank you, @codex !

On some sample models, both loaders hit limitations of “PBRLighting.j3md”. Several glTF extensions currently not handled by jme3-plugins suggest a need for enhancements to the existing material definitions (or else new ones):

  • KHR_materials_clearcoat
  • KHR_materials_ior
  • KHR_materials_iridescence
  • KHR_materials_sheen
  • KHR_materials_transmission
  • KHR_materials_variants
  • KHR_materials_volume

Also, non-extended glTF expects some capabilities that “PBRLighting.j3md” doesn’t provide. For instance, selecting alternative texture coordinates (as seen in MultiUVTest).


i have looked at the gltf sample viewer sources and we are not going to be able to support that in the near future. at least for overlapping objects the result would be wrong.

They sample the framebuffer to mix the transmissive part and to sample the refraction point.


As for this: in an importer as in (load converto to j3o save) it would make sense. as a loader the only option i see is import the model n times and set cullmode to aways for the variants.


Thanks for considering my wild ideas for enhancing material definitions.

I hadn’t thought much about the distinction between importers and loaders. MonkeyWrench is written as a loader, but (as I explained) I envision it being used primarily as an importer.

Regarding “KHR_materials_variants”, perhaps we should add a simple scene-graph control to jme3-core, to select a material by name and apply it to the controlled spatial.

I like the control based implementation. We might even extent support for replacing sub geometries? Most likely users requireing such features have already there own management code in place for task like this.

Regarding IOR / ClearCoat / and Sheen i think it is doable.

Regaring the others, targeting tranparency, we maybe should/coud add them to the material, even if they are not supported by the engine. So we could engine support and have loaders to test in place.

I will check if the engine supports the basic needs for an order independent translucent filter

Edit: i think i can write a new filter with minimal changes to the core + material. it would be gl4+ because it requires separate blend functions for each rendertarget.

1 Like

I like the control based implementation. We might even extent support for replacing sub geometries?

I think “KHR_materials_variants” is specifically for materials. If there’s a use case for selecting geometries, that sounds to me like a separate control.

Regarding IOR / ClearCoat / and Sheen i think it is doable.

Edit: i think i can write a new filter with minimal changes to the core + material.

That’s great news!

I continue solving issues with MonkeyWrench. At the same time, I am documenting the jme3-plugins issues I find:

1 Like

I’m done (for now) testing the glTF-Sample-Models.

MonkeyWrench doesn’t pass all the tests, but it’s more-or-less competitive with jme3-plugins.

MonkeyWrench currently does a poor job with point lights, for which it needs the light’s range. According to comments in the source code, this information is stored in metadata, but so far I’ve been unable to access it.

MonkeyWrench also does a poor job with texture transforms. The comments that describe the data structure are ambiguous. I tried many, many implementations, but none of them passed TextureTransformMultiTest.

Visual comparison uncovered 4 more issues in jme3-plugins:


I wanted to test loading of IQE models, but soon realized that, while Assimp supports several Quake formats, it can’t read IQE format.

Next I tried importing models downloaded from Mixamo. Mixamo provides models in Collada (.dae) format plus 5 different flavors of Autodesk (.fbx) format. My experience so far is that, for Assimp, Collada works better than Autodesk.

It turns out Assimp supports only a narrow range (v7.1 to v7.4) of FBX file versions. Of the 5 download options offered by Mixamo, only the “FBX Binary” and “FBX 7.4” options fall in that range, and neither of those worked well in my tests.

So I’m focusing on Collada (.dae) format for now.


One thing Assimp does well is loading Draco-compressed meshes, so MonkeyWrench gets that capability for free. I’ve opened JME issue 2118 in the hope that jme3-plugins might someday acquire this capability.

One thing Assimp doesn’t do (apparently) is distinguish a model’s initial pose from its bind pose. Usually this isn’t a major issue, but it creates a hassle when dealing models downloaded from the Mixamo site. I haven’t decided yet what’s the best workaround.


It seems the best approach for importing Mixamo assets into JME is:

  • download characters and animations separately and
  • specify COLLADA (.dae) format.

I modified MonkeyWrench so it could import animations without meshes, but didn’t pursue this approach beyond that.

I tested MonkeyWrench on various free models downloaded from Sketchfab. The best download formats to use appear to be .gltf/.glb. Assets downloaded in their original format often lack important textures, specify the wrong names for textures, or trigger bugs in Assimp.

I also tested the Khronos sample models in the old glTF v1.0 file format, which jme3-plugins doesn’t even attempt to load. MonkeyWrench did a good job loading non-animated models, but had trouble with the animated ones. This might indicate another Assimp issue; I haven’t pursued this further.

Version 0.5.0 of the MonkeyWrench library has been released for testing. Detailed instructions are in the project’s README file.

I welcome constructive feedback.


When adding as proposed the native libraries are not added automatically.

I had to add:

runtimeOnly "org.lwjgl:lwjgl-assimp:3.3.3:natives-windows"

On the bistro scene i get an excpetion:

SEVERE: time=-0.292
Oct 23, 2023 9:41:31 PM handleError
SEVERE: Uncaught exception thrown in Thread[#34,jME3 Main,5,main]
java.lang.IllegalArgumentException: time must be greater than or equal to 0.000000.
	at jme3utilities.Validate.inRange(
	at jme3utilities.wes.TransformTrackBuilder.addTranslation(
	at com.github.stephengold.wrench.ConversionUtils.convertNodeAnim(
	at com.github.stephengold.wrench.ConversionUtils.convertAnimation(
	at com.github.stephengold.wrench.LwjglProcessor.addAnimComposer(
	at com.github.stephengold.wrench.LwjglProcessor.toSceneGraph(
	at com.github.stephengold.wrench.LwjglAssetLoader.loadScene(
	at com.github.stephengold.wrench.LwjglAssetLoader.load(

tested the original fbx, gltf and glb exports. always same exception


Thank you for your prompt and valuable feedback, @zzuegg!

  • The cross-platform build issue has been solved.
  • I’m unsure what’s the best way to handle keyframes with negative times. For now I’ve decided to skip those keyframes.

Please re-test using version 0.5.1 of MonkeyWrench:

implementation 'com.github.stephengold:MonkeyWrench:0.5.1'

Everything seems to be working now. Thank you for the effort and quick fix!

1 Like

The MonkeyWrench asset loader continues to make progress, with a new release of the library expected soon.

The “Zophrac” model is the main hold-up. To load it correctly, some high-impact changes may be required.

MonkeyWrench has recently been tested on some file formats that JME’s built-in loaders don’t handle, including:

  • 3D Studio Max (.3ds)
  • 3-D Manufacturing Format (.3mf)
  • Biovision Hierarchy (.bvh)
  • COLLADA (.dae)
  • LightWave Model (.lwo)
  • Polygon File Format (.ply)
  • Stereolithography (.stl)

Of these formats, perhaps .bvh and .dae are the most useful, but you never know.

Many bugs in v0.5.1 have been addressed, notably the extreme inefficiency of its virtual file system. So v0.5.2 should provide faster loading in most cases.

Along the way, I learned an easy way to load embedded WebP textures. The same trick could be used (in JME desktop apps) to load textures from SVGs and other image formats.

I also found and documented more issues with Assimp, for a total of 10. One of them is nearly solved. It’s a slow process.


After many frustrating days of effort, I finally gave up on loading the “zophrac” glTF asset (from Sketchfab) using MonkeyWrench. I truly believed I could make it work. I got it 90% of the way to loading correctly, but my changes interfered with loading other (validated) glTF models. Ultimately I replaced the failing assertion with an IOException and moved on. (On the bright side, jme-plugins still does a fine job of loading “zophrac”.)

MonkeyWrench v0.5.2 is now available for testing. I’d appreciate additional (constructive) feedback regarding it.

The most notable change in v0.5.2 is that verbose logging is now disabled by default. (In v0.5.1 it was enabled by default.)

Another nice change is you can specify a search path for texture assets, in case they’re not in the default location. Unfortunately, this feature isn’t well documented yet.

You can read about other library changes in the release log.

The CompareLoaders application has also received a lot of improvements.

It defines “asset groups” that streamline testing of free assets from:

CompareLoaders also empowers users to adjust lighting levels, visualize armatures and axes, and focus on specific animation clips and/or materials.

Here’s the updated Gradle snippet for those “in the know”:

implementation 'com.github.stephengold:MonkeyWrench:0.5.2'

As ever, detailed instructions for installing, building, and using MonkeyWrench can be found in the README file.


I am deeply indebted to @capdevon for introducing me to Mixamo and showing me how to use their characters with JMonkeyEngine.

Today I wrote a tool that uses MonkeyWrench to greatly simplify the conversion process.

I’ve begun uploading converted models to a separate GitHub repository.

I’m unsure how to license this repo.

The Mixamo FAQ says the characters and animations can be used royalty-free in personal, commercial, and non-profit projects, so it seems logical that converted assets ought to be usable in the same ways.