Models with more than 127 bones

Hey guys,

I recently came accross a model that has more than 127 bones.
Because I used ByteBuffer as BoneIndex buffer I obviously got negative values in the buffer.
This of course caused IndexOutOfBoundsException during rendering.

Now I updated the blender loader so that it checkes the highest value of a bone index and decides if ByteBuffer or ShortBuffer should be used.
But I got a ClassCastException here:

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.ClassCastException: java.nio.DirectShortBufferU cannot be cast to java.nio.ByteBuffer
at com.jme3.animation.SkeletonControl.resetToBind(SkeletonControl.java:187)
at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:159)
at com.jme3.scene.control.AbstractControl.render(AbstractControl.java:119)
at com.jme3.scene.Spatial.runControlRender(Spatial.java:579)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:655)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:665)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:665)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:722)

Would it be possible to take ShortBuffer into consideration in SkeletonControl (and all other places that use this type of buffer) ?

Cheers,
Kaelthas

PS.
I also added IntBuffer for bone indexes but I am not sure if this is needed. Theoretically some freak might use python to generate a model with more than Shor.MAX_VALUE bones but this is really highly not gonna happen. :slight_smile:
Should I add IntBuffer or write a warning or throw an exception ?

How common is a model with more than 127 bones, likely to be? It probably should be justified with the amount of work that can potentially be involved.

Also an IntBuffer won’t work on android, but if they using that many bones, its probably expected to fail anyways :slight_smile:

I know sploreg recently changed IntBuffer to ShortBuffer for the terrain system depending on the index count.

http://code.google.com/p/jmonkeyengine/source/detail?r=10065

OK, so I can discard IntBuffer but still 128 bones is not much.
I found the model on blendswap and I am sure such situation, even though rare, can happen from time to time.

We actually support 256 bones. You might get negative values but these get converted to unsigned values during skinning so you don’t have to worry about that.

This is the error I got in the first place, without any changes in blender importer.

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.ArrayIndexOutOfBoundsException: -119
at com.jme3.animation.SkeletonControl.applySkinning(SkeletonControl.java:388)
at com.jme3.animation.SkeletonControl.softwareSkinUpdate(SkeletonControl.java:310)
at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:170)
at com.jme3.scene.control.AbstractControl.render(AbstractControl.java:119)
at com.jme3.scene.Spatial.runControlRender(Spatial.java:579)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:655)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:665)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:665)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)

It looks like the indices are not converted to unsigned bytes.
But I found a solution. In SkeletonControl in the method applySkinning in line 388 change this:
[java]
Matrix4f mat = offsetMatrices[indices[idxWeights++]];
[/java]
into this
[java]
Matrix4f mat = offsetMatrices[0xFF & indices[idxWeights++]];
[/java]

After that change everything worked fine and the model appeared :slight_smile:

2 Likes

Thanks, it was fixed in SVN

3 Likes