NPE when merging hardware skinned models

Hi,

if I try to merge hardware skinned models with GeometryBatchFactory.optimize(), I got an Null Pointer Exception.
It works with disabled hardware skinning

setHardwareSkinningPreferred(false);

code example:

Node node1 = (Node) assetManager.loadModel("model1.j3o");
model.attachChild(node1);

Node node2 = (Node) assetManager.loadModel("model2.j3o");
model.attachChild(node2);

mat = assetManager.loadMaterial("material.j3m");
model.setMaterial(mat);

skeletonControl = model.getControl(SkeletonControl.class);
skeletonControl.setHardwareSkinningPreferred(true);

model = (Node) GeometryBatchFactory.optimize(model);

Stacktrace

Mär 02, 2016 12:55:17 AM com.jme3.app.Application handleError
SCHWERWIEGEND: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.NullPointerException
	at com.jme3.scene.Mesh.prepareForAnim(Mesh.java:399)
	at com.jme3.animation.SkeletonControl.switchToHardware(SkeletonControl.java:127)
	at com.jme3.animation.SkeletonControl.testHardwareSupported(SkeletonControl.java:159)
	at com.jme3.animation.SkeletonControl.controlRender(SkeletonControl.java:276)
	at com.jme3.scene.control.AbstractControl.render(AbstractControl.java:119)
	at com.jme3.scene.Spatial.runControlRender(Spatial.java:681)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:673)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
	at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:662)
	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1019)
	at com.jme3.renderer.RenderManager.render(RenderManager.java:1078)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:260)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:192)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
	at java.lang.Thread.run(Thread.java:745)

Pretty sure that animated models cannot be batched. Most likely, the thing that detects this works properly for software skinning but not hardware skinning.

…just a guess though.

Why should it not be possible? What could be the reason? The NPE is thrown for the first time when trying to setup the HWBoneIndex buffers

//if HWBoneIndex and HWBoneWeight are empty, we setup them as direct
//buffers with software anim buffers data 
VertexBuffer indicesHW = getBuffer(Type.HWBoneIndex);
if (indicesHW.getData() == null) {

I think it is better then to throw an exception with some more informations about the reason or so.

Edit: It seams that its possible with Ogre3D to batch hardware skinned models. So it should also be possible with jmonkey (source: http://www.ogre3d.org/forums/viewtopic.php?f=5&t=62846)

It’s never mentioned in that thread that batching hardware skinned models actually worked.

Based on the current design of how hardware skinning is done in jME3 and Ogre3D it is not actually possible to batch animated models. There’s a limit of 256 bones that you can have on a single batch which you’ll run out of pretty quickly if you were to batch many models.

Ah ok thank you. What I am want to do is batching the players model into one object. It consits of hands, arms, torso, head, legs and feets. So batching would reduce the draw calls for the player from 6 to 1 in many cases. I try this way to save some vertices and avoid clipping problems if the player is wearing gloves or boots and so on.

Is there a better way to do this or is batching software skinned models the way to go?

Please can someone tell me a more detailed reason why batching hardware skinned models technically doesn’t work? I am very interesseted to learn more about hardware skinning and why is it a problem to merge that buffers and so on :blush:

Batching won’t solve this.

This is the one case where I wouldn’t recommend to batch. It doesn’t matter… You have one player on screen,
6 or 1 geom is not a big deal.
Btaching is interesting when you have dozens of geoms Batched into one.

First, batching hasn’t been designed with animated models in mind. So you may have some conrner cases where it’s completely broken.
Even if it was, it would only worl with software skinning. Software skinning modifies the mesh buffer on the CPU. So in theory this could work with batched models because it’s just a matter of index in the buffer to update the right vertex transforms.
Hardware skinning however, let’s the buffer intact, and instead sends all the bones transforms to the shader to transform the vertex at render time in the shader.
The problem is that you have a limitation on how many uniforms you can send to a shader, and you basically can send a limited numbe rof bones. (as an example on android it’s less than 100, on desktop I never really tested and it depends on the hardware, but IMO even with latest ardware you can’t go above 500 or 700 bones (this can be precisely calculated). With batched models you’ll reach this limit pretty fast. A classic models with hands entirely rigged will have around a hundred bones so if you batch 10 of them…you’re done… and it won’t make it really faster.

1 Like

thank you nehon, now its more clear :blush: But I think its still better to throw an exception with a detailed answer instead of a NPE

That’s right, but as said, i guess it just hasn’t been tested.