[Solved] NullPointerException in AnimComposer

I made some progress with my animations and the code works fine with the stock ogre, however, when I try to load one of my own models I get:

Uncaught exception thrown in Thread[jME3 Main,5,main]
NullPointerException

I am thinking that there is something off with the model and/or animation.
That’s the most likely issue, right?

44     Spatial model = assetManager.loadModel("Models/hero.j3o");
45          model.center();
46       
47               animComposer = model.getControl(AnimComposer.class);
48               animComposer.setCurrentAction("idle");
49                      rootNode.attachChild(model);

StackTrace

Apr 27, 2022 10:12:04 AM com.jme3.app.LegacyApplication handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.NullPointerException
	at mygame.TestOgreAnim.simpleInitApp(TestOgreAnim.java:48)
	at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:239)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:130)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:211)
	at java.base/java.lang.Thread.run(Thread.java:834)

Thank you!

1 Like

For some models, the AnimComposer isn’t attached to the model’s root spatial. Perhaps “hero.j3o” is one of those models? It’s hardly unusual.

If you determine that it’s attached to (say) the model root’s 1st child, you can use

animComposer = ((Node)model).getChild(0).getControl(AnimComposer.class);

If you use multiple models, or are too lazy to analyze the model by hand, then you can use

List<AnimComposer> composers = MySpatial.listControls(model, AnimComposer.class, null);
assert composers.size() == 1;
animComposer = composers.get(0);

(The MySpatial class is included in the Heart library.)

2 Likes

Always give the full stack. That together with your code will tell the problem exactly!

2 Likes

thanks sgold I will mess around with this!

Oh duh thanks Toni! I will add it to my original post and for sure do it in the future iff anything ever doesn’t work :grin:

2 Likes

sgold this worked!! :exploding_head:

getChild(0) 

didn’t work but I decided to slap a 1 in there and then it worked :oooo
My brother is doin the blender work so I don’t know what’s going on here yet exactly but pretty cool!

thank you so much

1 Like

You will be better off in the long run if you figure out what the name of that child is and then search for the name instead of a magic index.

…even more bullet proof would be to search for the spatial with the control on it.

    public static <T extends Control> T findControl( Spatial s, Class<T> type ) {
        T result = s.getControl(type);
        if( result != null ) {
            return result;
        }
        if( s instanceof Node ) {
            for( Spatial child : ((Node)s).getChildren() ) {
                result = findControl(child, type);
                if( result != null ) {
                    return result;
                }
            }
        }
        return null;
    }

Then:
AnimComposer animComposer = findControl(model, AnimComposer.class);

2 Likes

ok yeah we will definitely do some detective work on this. :male_detective:
Thanks pspeed!

err so I am trying to be a detective but I don’t think I am doing it right- not sure where exactly to put this or if I need to modify anythin. Do I change the “T” value ??

public class Advice extends SimpleApplication {

        private AnimComposer animComposer;

    public static void main(String[] args) {
        Advice app = new Advice();
        app.start();
    }

    
    @Override
    public void simpleInitApp() {
        flyCam.setMoveSpeed(10f);
      cam.setLocation(new Vector3f(6.4013605f, 7.488437f, 12.843031f));
        cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f));  
        
        DirectionalLight dl = new DirectionalLight();
        dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal());
        dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f));
        rootNode.addLight(dl);
        
Spatial model = assetManager.loadModel("Models/WoodChop.j3o");
        model.center();
        
                animComposer = ((Node)model).getChild(1).getControl(AnimComposer.class);
                animComposer.setCurrentAction("wc");
                        rootNode.attachChild(model);
                        
        
                 
                 }
    
    public static <T extends Control> T findControl( Spatial s, Class<T> type ) {
        T result = s.getControl(type);
        if( result != null ) {
            return result;
        }
        if( s instanceof Node ) {
            for( Spatial child : ((Node)s).getChildren() ) {
                result = findControl(child, type);
                if( result != null ) {
                    return result;
                }
            }
        }
        return null;
    }
    
   }

It’s a method. You add it to the class like any other method.

In the above, you’ve pasted the body of the findControl() method inside your simpleInitApp() method. You can’t declare methods inside of methods.

You may want to wait to use the “findControl” way until you’ve learned more about Java. In the mean time, if you know the name of the node you can at least model.getChild(name) it.

2 Likes

Oh ok I was trying to put it outside. I’ll keep plugging away, thanks pspeed!