Import animated model with normal maps

Hello everyone,

I have been trying the last few days to import an animated 3d model to jme 3.1 beta2 sdk. Let me share with you my results as below

1 - Blender importer.
Tangents not generated, animations imported however they don’t play ( model should be compatible with jme as per the documentation )
When generating tangents from sdk I think the result is the same as having the normals facing inside in blender , also saving the .j3o file ruins it as I can’t open it anymore.

2 - Ogre exporter
This one gives the best results with the normals. The tangents are correct despite some minor problems. Using a custom material loads it correctly. Animations don’t play. I see them all correctly however playing them gives an array out of bounds exception.

3 - xBuf
The only format which exports animations correctly. The tangents however are not correct. Seems it has a problem with mirrored UV’s and probably more than that.

Probably there are some fixes which I don’t know about. I can ignore the normals for now and use xBuf however I thought it would be nice to address these issues.

I am hoping for some advices btw.

Thanks in advance.

1 Like

You have to do it yourself:
Either by code :


Either in the sdk, right click on your model, and explore the popup menu, I do’nt remember exactly where, but you definitely have a “generate tangents” option.

xBuf is the most efficient way to get animated models into JME currently.

1 Like

Thanks @nehon for the response. I did it through code as well but its not viable as the normals are not generated correctly and it takes too much loading time. Generating from the sdk yelds the same results and if I save the file I can’t reopen it anymore as it gives a null pointer exception.

In my post I have explained all the use cases with all the exporters. ( I hope I have been clear enough :wink: )

1 Like

Ogre exporter does not export Normal Map (bump map). And that was the reason I migrated from Ogre exporter .

I am using Xbuf for a while and it works perfect for me.
In version 0.9.1 it exports normals directly from blender. You do not need to generate them.

1 Like

Can you post the stacktrace of the nullpointer?

1 Like

@Ali_RS Thanks for the hints.

Actually ogre is the only format which generates the tangents correctly. Using a custom defined material with the diffuse map and the normal map gives the correct results. What I have noticed from ogre exporter is that it would load only the first texture, so I exported only the normal map, using the custom material then helped to define both maps . The animations fail with an index out of bounds exception.

Error : Exception in Control, scene content removed.
java.lang.ArrayIndexOutOfBoundsException: -4

xBuf loads the animations correctly, but the tangents are not correct. I am using the SDK beta 2 version. I am pretty sure I am using the 0.9.1 version of the exporter, the only use case that I can think of right now is that the loader of jme3.1 is not at the same version or that it has a problem with mirrored UV’s.

@jayfella The stacktrace :

 java.lang.IllegalArgumentException: for uniform m_BoneMatrices: value cannot be null
    at com.jme3.shader.Uniform.setValue(
    at com.jme3.material.Material.updateShaderMaterialParameters(
    at com.jme3.material.Material.preload(
    at com.jme3.renderer.RenderManager.preloadScene(
    at com.jme3.renderer.RenderManager.preloadScene(
    at com.jme3.renderer.RenderManager.preloadScene(
    at com.jme3.animation.SkeletonControl.testHardwareSupported(
    at com.jme3.animation.SkeletonControl.controlRender(
    at com.jme3.scene.control.AbstractControl.render(
    at com.jme3.scene.Spatial.runControlRender(
    at com.jme3.renderer.RenderManager.renderSubScene(
    at com.jme3.renderer.RenderManager.renderSubScene(
    at com.jme3.renderer.RenderManager.renderSubScene(
    at com.jme3.renderer.RenderManager.renderScene(
    at com.jme3.renderer.RenderManager.renderViewPort(
    at com.jme3.renderer.RenderManager.render(
    at com.jme3.gde.core.scene.SceneApplication.update(
    at com.jme3.system.awt.AwtPanelsContext.updateInThread(
    at com.jme3.system.awt.AwtPanelsContext.access$100(
    at com.jme3.system.awt.AwtPanelsContext$AwtPanelsListener.update(
    at com.jme3.system.lwjgl.LwjglOffscreenBuffer.runLoop(
1 Like

This might be helpful

1 Like

@Ali_RS Thanks for the links, I had already seen it though, I can confirm that I have baked the animation and pushed it down as an NLA strip.

That doesn’t seem the case as I can correctly see the animations in the scene composer. When I press play it gives the exception. Probably there is something else I am missing?

1 Like

Yeah. ugh. Is it possible to provide a test case. I am particularly interested because model importing with animations are something I will be working toward myself.

1 Like

Sure, I will share my model for tests. I am posting a google drive link below :

You should find both textures and the .blend file.

@Ali_RS its worth mentioning that I have only used the .j3o generated from the SDK for xBuf, I have never tried to import the model directly, am doing now.


1 Like

when generating tangents did you check the “split mirrored uvs” check box?

1 Like

@Nehon I tried both ways, with the check box checked and unchecked. Also via code with the second parameter set to true and to false. I get the same result.

It would seem to me that the loader recognises the normals facing inside because the result I get with the tangents generated and setting the normals facing inside in blender is very similar.


This is the stacktrace I get from playing Ogre import animation.

java.lang.ArrayIndexOutOfBoundsException: -4
	at com.jme3.animation.CompactQuaternionArray.deserialize(
	at com.jme3.animation.CompactQuaternionArray.deserialize(
	at com.jme3.animation.CompactArray.get(
	at com.jme3.animation.BoneTrack.setTime(
	at com.jme3.animation.Animation.setTime(
	at com.jme3.animation.AnimChannel.update(
	at com.jme3.animation.AnimControl.controlUpdate(
	at com.jme3.scene.control.AbstractControl.update(
	at com.jme3.scene.Spatial.runControlUpdate(
	at com.jme3.scene.Spatial.updateLogicalState(
	at com.jme3.scene.Node.updateLogicalState(
	at com.jme3.scene.Node.updateLogicalState(
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(
1 Like

@engjellrraklli Are you sure that you are using beta2 and not something old?
If you can build the engine from source, try to see if this patch helps: sdk/FixHWSkinningSerialization.diff at 9a9a5dea76cee69156b11f5e0450988f9acacf66 · jMonkeyEngine/sdk · GitHub

It should be merged as of Pull-Request [522] (Also applying PR #501 on 3.1 by MeFisto94 · Pull Request #522 · jMonkeyEngine/jmonkeyengine · GitHub) though.

I am still posting this though, since there is the small possibility that MatParamsOverride (@Momoko_Fan) or the new Cloning System (@pspeed) is interfering here?

To xbuf: It could be that the SDKs XBufLoader is outdated, you can check that if it works in your test scene.

Some other tips: Try to see if the animation plays if you trigger the last animcontrol or all of them. That’s a problem with the blender importer, it adds multiple controls which xbuf does not.

What is the issue you are seeing with your tangents actually and how do you verify them? When you say the normals are facing inside, did you check that in blender by activating the normals by pressing n and clicking on that face symbol under normals?
And: Is it the models normals or your normal map which is faulty?

And just for a test you might be able to import the normal map manually (just like with xbuf): You need to copy the texture into your assets\Textures and then you can edit the Materials (which might be tricky if you can’t save the j3o, though). You could add them using a SceneGraphVisitor during the runtime though.

1 Like


I reconfirm about beta2. I will build from source and check if that helps.

xbuf : I didn’t have time to do that earlier, will make sure to test later on.

blender : You are actually correct, I did test this with Ogre but somehow I missed it in blender. The animation on the last node works just fine. ( Also, if you have a node named body the sdk doesn’t import the model at all, just so you know )

The normals are facing outside, I have checked in blender by clicking the face symbol. When I change that to inside and then check with the generated tangents in jme 3.1 the results look pretty similar.
Unfortunately I can’t tell where is the problem, worth to mention that with ogre the normals load just fine.

I have created a new material for the test, added the normal map and the diffuse map, I generated the tangents ( otherwise the model would be plain black ), added the new material in runtime to the model and still the same results ( This made me feel strongly that it is a tangent generation problem)

1 Like

Im in the middle of writing something at the today, but i’ll write a test case with your asset and see if I can find anything.

1 Like

I think there was a cloning related fix but it was attachment node related. It is on the tip of the 3.1 branch and will be in beta3 when next it is tagged.

1 Like

Note: my understanding is that the latest xbuff will import the tangents from Blender… which to me is the best of all worlds, all other things being equal. Blender has way more information to work from.

1 Like

So this seems to be a quite common problem with the empty bone matrices and for some reason the reports only come since a few days.

Maybe it is unrelated to my pull request? Maybe we just need some “if matrix null generate it” somewhere in testHardwareSupported? Or we need some special handling which treats that matrix as transient and as such isn’t null but not defined.

1 Like

I hope, I fixed a bug in the xbuf tangent export from blender. (see the body of the model)

Yesterday we got :


Today we have :

BTN computed from normal

by xbuf exporter (code in python), if uv map is NOT defined.


BTN computed by blender

if uv map is defined


I guess there are some issues with mirroring (UV for normal map), if I understoud your model, you share UV point between left and right.

1 Like

I think the UV is mirrored. I am not sure though, in any case the exporter should support it.

Note : @DarkChaos The null pointer exception when saving scene seems to happen only on scenes with animation and basically with any change.

1 Like