Changes to animations loading in blender importer (IMPORTANT for importer users)

@Kaelthas said: in your blender model I am unable to play animations in 3D view. Probably there is some setting that disables it - do you know which one ?

Armature Properties / Object Data / Skeleton / Rest Position, perhaps?

@Kaelthas said: @sgold I guess it happens when you try to run your animation. Remember to add your animation. For example: [java] blenderKey.addSkeletonAnimation("bob", "trail.R"); [/java]

I did not get NPE and loaded the animations correctly.

I’ve added animations to the Blender key, but I still get the NPE during loadModel():
[java]
BlenderKey key = new BlenderKey(sourceAssetPath);
key.addSkeletonAnimation(“bob”, “balanced-neutral”);
key.addSkeletonAnimation(“bob”, “right-lift”);
key.addSkeletonAnimation(“bob”, “right-trail”);
key.addSkeletonAnimation(“bob”, “left-lift”);
key.addSkeletonAnimation(“bob”, “left-trail”);
Spatial spatial = assetManager.loadModel(key);
[/java]

Try this one

[java]
modelKey.addSkeletonAnimation(“testcharacter1Jacket”, “testcamina1”);
modelKey.addSkeletonAnimation(“testcharacter1Jacket”, “testavatar_run”);
[/java]

The first argument is the name of the node you are animating and the other one is the action you want it to play. You do not name the animation bone by bone :wink:

But when you play the actions you will see that your model does not yet animate well.
You can fix it temporarily by removing the ‘Limit rotation’ constraint on your bones.

Yesterday I found a bug that caused that some constraints were not loaded. I fixed that and now apparently there are issues with ‘Limit rotation’ constraint.

I will try to fix that as soon as possible :wink:

@Kaelthas said: Try this one

[java]
modelKey.addSkeletonAnimation(“testcharacter1Jacket”, “testcamina1”);
modelKey.addSkeletonAnimation(“testcharacter1Jacket”, “testavatar_run”);
[/java]

The first argument is the name of the node you are animating and the other one is the action you want it to play. You do not name the animation bone by bone :wink:

But when you play the actions you will see that your model does not yet animate well.
You can fix it temporarily by removing the ‘Limit rotation’ constraint on your bones.

Yesterday I found a bug that caused that some constraints were not loaded. I fixed that and now apparently there are issues with ‘Limit rotation’ constraint.

I will try to fix that as soon as possible :wink:

Thank you for responding, @Kaelthas, and for all the work you’ve done on the importer.

I’m still puzzled, since I wasn’t naming any bones. The name of my node is “bob”, and I want it to be able to play the five animations “balanced-neutral”, “right-lift”, and so on. I don’t understand what I did wrong, nor what I should do to avoid the NPE.

@sgold

sorry my bad. I was using another model for that.
Please upload me your model and I will take a lok on it :slight_smile:

Thanks for the offer. Go to https://code.google.com/p/bats-game/source/browse/trunk/assets/Models/units/bob/bob.blend and click on “View raw file”.

@sgold

I have downloaded your model but I did not get any NPE.

Could you post a full code where you load the model and run it ?
The loading for me worked fine and I was able to run the animations you defined.

@Kaelthas said: @sgold

I have downloaded your model but I did not get any NPE.

Could you post a full code where you load the model and run it ?
The loading for me worked fine and I was able to run the animations you defined.

Well, my AssetProcessor application is already online, but it’s part of a big fat game project so I wrote the following test app to illustrate the NPE:

[java]
package bats;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.BlenderKey;
import com.jme3.system.JmeContext;

public class Test
extends SimpleApplication {

public static void main(String[] arguments) {
    Test application = new Test();
    application.start(JmeContext.Type.Headless);
}

@Override
public void simpleInitApp() {
    processModel("units/bob/bob");
}

private void processModel(String path) {
    String sourceAssetPath = String.format("Models/%s.blend", path);
    BlenderKey key = new BlenderKey(sourceAssetPath);
    key.addSkeletonAnimation("bob", "balanced-neutral");
    key.addSkeletonAnimation("bob", "right-lift");
    key.addSkeletonAnimation("bob", "right-trail");
    key.addSkeletonAnimation("bob", "left-lift");
    key.addSkeletonAnimation("bob", "left-trail");
    assetManager.loadModel(key);
}

}
[/java]

My JME libraries are built from trunk rev 11007 by the way. Let me know if I should be using a different rev.

@sgold
Hey, I took a look into your model, but I think the problem is not with the importer but with the
[java]
public Spatial clone(boolean cloneMaterial);
[/java]
in Spatial class.

First it makes a clone of the spatial at line 1150:
[java]
Spatial clone = (Spatial) super.clone();
[/java]
The ‘clone’ is fine, but later something like this is made (it begins at line 1183):

[java]
clone.controls = new SafeArrayList(Control.class);
for (int i = 0; i < controls.size(); i++) {
Control newControl = controls.get(i).cloneForSpatial(clone);
newControl.setSpatial(clone);
clone.controls.add(newControl);
}
[/java]

The ‘clone.controls’ list is replaced with an empty one.
And later in ‘cloneForSpatial’ method implemented by SkeletonControl
we have:

[java]
public Control cloneForSpatial(Spatial spatial) {
Node clonedNode = (Node) spatial;
AnimControl ctrl = spatial.getControl(AnimControl.class);//!!! HERE IS THE PROBLEM !!!
SkeletonControl clone = new SkeletonControl();

    clone.skeleton = ctrl.getSkeleton();//!!!! AND HERE WE GET NPE !!!!
    //...

}
[/java]

The spatial has no controls because the control array had been replaced a moment before.

So I think that the author of this class should take a look into it :wink:

1 Like
@Kaelthas said: The spatial has no controls because the control array had been replaced a moment before.

So I think that the author of this class should take a look into it :wink:

Thanks for investigating and providing a detailed explanation of the bug.

I’ll take a look at the source code of Spatial. In the mean time, can you suggest a workaround?

@Kaelthas said: The spatial has no controls because the control array had been replaced a moment before.

This is not really true. It has the controls that were added in earlier iterations of the loop. So if the AnimControl is added before the SkeletonControl then it should still work.

What order is the blender plugin adding them?

@pspeed

I do not think that the order of adding the controls really matters here.
If you flatten the code a bit you will have something like this:

[java]
Spatial clone = (Spatial) super.clone();
//…
clone.controls = new SafeArrayList(Control.class);

//… the list named ‘controls’ is not changed

AnimControl ctrl = clone.getControl(AnimControl.class);
//you will never fetch AnimControl from an empty list
[/java]

@Kaelthas said: @pspeed

I do not think that the order of adding the controls really matters here.
If you flatten the code a bit you will have something like this:

[java]
Spatial clone = (Spatial) super.clone();
//…
clone.controls = new SafeArrayList(Control.class);

//… the list named ‘controls’ is not changed

AnimControl ctrl = clone.getControl(AnimControl.class);
//you will never fetch AnimControl from an empty list
[/java]

?

  1. creates a new list.

  2. adds a control to the list.

If the AnimControl is first then it will already be in the list by the time the SkeletonControl tries to access it. getControl(AnimControl.class) will return the previously added control.

You read it wrong @Kaelthas

@Kaelthas said: @pspeed

I do not think that the order of adding the controls really matters here.
If you flatten the code a bit you will have something like this:

[java]
Spatial clone = (Spatial) super.clone();
//…
clone.controls = new SafeArrayList(Control.class);

//… the list named ‘controls’ is not changed

AnimControl ctrl = clone.getControl(AnimControl.class);
//you will never fetch AnimControl from an empty list
[/java]


The list is filled with the controls added in the previous iteration, The AnimControl MUST be before the SkeletonControl, not only for cloning, but in order for them to work properly.
The clone() should throw a more explicit error though.

@nehon
@pspeed

OK, I see it now that the order of the controls matters.
I swapped the controls so that the AnimControl is the first one on the list and did not get NPE.
Instead the application hanged :frowning:

The model is imported and the cloneForSpatial method is executed so I passed the point that crashed before.
But the scene did not appear.

I added this piece of code to AnimationHelper after the line 138:

[java]
SkeletonControl skeletonControl = node.getControl(SkeletonControl.class);
if(skeletonControl != null) {
node.removeControl(SkeletonControl.class);
node.addControl(skeletonControl);
}
[/java]

Could someone take a look at it please and see why the app does not want to show up ??

1 Like

I’ll try too look into it.

@Kaelthas said: @nehon @pspeed

OK, I see it now that the order of the controls matters.
I swapped the controls so that the AnimControl is the first one on the list and did not get NPE.
Instead the application hanged :frowning:

The model is imported and the cloneForSpatial method is executed so I passed the point that crashed before.
But the scene did not appear.

I added this piece of code to AnimationHelper after the line 138:

[java]
SkeletonControl skeletonControl = node.getControl(SkeletonControl.class);
if(skeletonControl != null) {
node.removeControl(SkeletonControl.class);
node.addControl(skeletonControl);
}
[/java]

Could someone take a look at it please and see why the app does not want to show up ??

The Test.java I posted is a headless application. It never opens a view port to display the model.

With the 5-line patch to AnimationHelper.java, I was able to convert my Blender model successfully to J3O, so I think you should commit that patch.

Thanks for all the help.

@nehon did you have a chance to take a look into this hanging problem ???

I’d love to commit the patch, but it looks like it still causes problems :confused:

Nope I didn’t, i’ll try asap

I’m confused. What “hanging problem” are you referring to, @Kaelthas? My bob model loaded fine with the 5-line patch.

I have a new request, however. I’ve noticed that if I load a blender model using an invalid key, the error is reported as an NPE. For instance, key.addSkeletonAnimation(“bob”, “nonexistent-action”); gives an NPE in om.jme3.animation.SkeletonControl.cloneForSpatial() when assetManager.loadModel() is invoked.

Would you please add a checks and a descriptive error message for these sorts of situations? It seems to me they’re likely to be a common sort of “pilot error” going forward.