AnimControl NullPointer when importing blender 2.68a model

I recently made a Blender (version 2.68a) model of a human male to be imported into JME3 (version 3.0). I used vertex groups connected to bones to allow bone animations. When I imported the file into JME3, it loaded properly. However, when I attempted to run the following code to test if the animations would work, I received a NullPointerException on the line “control.addListener(this);”

Here is the code I am using:

package myGame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

/** Sample 7 - how to load an OgreXML model and play an animation,

  • using channels, a controller, and an AnimEventListener. */
    public class Main extends SimpleApplication implements AnimEventListener
    {
    private AnimChannel channel;
    private AnimControl control;
    Node player;

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

@Override
public void simpleInitApp()
{
viewPort.setBackgroundColor(ColorRGBA.LightGray);
initKeys();
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());
rootNode.addLight(dl);
//player = (Node) assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
player = (Node) assetManager.loadModel(“Models/human_malev4c2a3v10t5/human_malev4c2a3v10t5.j3o”);
player.setLocalScale(0.5f);
rootNode.attachChild(player);
control = player.getControl(AnimControl.class);
control.addListener(this); //NullPointerException here
channel = control.createChannel();
channel.setAnim(“stand”);
}

public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName)
{
if (animName.equals(“Walk”))
{
channel.setAnim(“stand”, 0.50f);
channel.setLoopMode(LoopMode.DontLoop);
channel.setSpeed(1f);
}
}

public void onAnimChange(AnimControl control, AnimChannel channel, String animName)
{
// unused
}

/** Custom Keybinding: Map named actions to inputs. */
private void initKeys() {
inputManager.addMapping(“Walk”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(actionListener, “Walk”);
}
private ActionListener actionListener = new ActionListener()
{
public void onAction(String name, boolean keyPressed, float tpf)
{
if (name.equals(“Walk”) && !keyPressed)
{
if (!channel.getAnimationName().equals(“Walk”))
{
channel.setAnim(“Walk”, 0.50f);
channel.setLoopMode(LoopMode.Loop);
}
}
}
};
}

This code is the same as that found in the HelloAnimation tutorial, except with the loaded model changing. By running a few tests, I found out that I am getting the NullPointerException because the line control = player.getControl(AnimControl.class); returned null. I also tried to export as an Ogre file, but this yielded the same result.

I have my animations on one strip in the Blender NLA editor. The model has a root bone properly positioned.

I have searched through various other sources (JME3 documentation, Blender and JME3 tutorials, forum posts, and videos) and I have yet seen any solution to the problem.

So my question is this: How do you set up a model in Blender so that JME3 understands how to retrieve an AnimControl from it?

Thanks!

Because control is null.

Your model may not have an AnimControl… or it may be on the children. You will have to do some poking in the scene explorer to see for sure.

Thanks for your help.

SceneExplorer does not show an AnimControl. I understand that that is why
control = player.getControl(AnimControl.class);
does not work to initialize it. However, is there a way for me to add an AnimControl in JME3 that will access my model’s animations, or do I have to redo my Blender file?

Can you upload your model so I can check ?

PS:
Please put your code in Preformatted text by selecting your code and hit Ctrl + K :
so it looks more readable by others.

package myGame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;

/** Sample 7 - how to load an OgreXML model and play an animation,
 * using channels, a controller, and an AnimEventListener. */
public class Main extends SimpleApplication implements AnimEventListener 
{
  private AnimChannel channel;
  private AnimControl control;
  Node player;

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

  @Override
  public void simpleInitApp() 
  {
    viewPort.setBackgroundColor(ColorRGBA.LightGray);
    initKeys();
    DirectionalLight dl = new DirectionalLight();
    dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());
    rootNode.addLight(dl);
    //player = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
    player = (Node) assetManager.loadModel("Models/human_malev4c2a3v10t5/human_malev4c2a3v10t5.j3o");
    player.setLocalScale(0.5f);
    rootNode.attachChild(player);
    control = player.getControl(AnimControl.class);
    control.addListener(this); //NullPointerException here
    channel = control.createChannel();
    channel.setAnim("stand");
  }

  public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) 
  {
    if (animName.equals("Walk")) 
    {
      channel.setAnim("stand", 0.50f);
      channel.setLoopMode(LoopMode.DontLoop);
      channel.setSpeed(1f);
    }
  }

  public void onAnimChange(AnimControl control, AnimChannel channel, String animName) 
  {
    // unused
  }

  /** Custom Keybinding: Map named actions to inputs. */
  private void initKeys() {
    inputManager.addMapping("Walk", new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addListener(actionListener, "Walk");
  }
  private ActionListener actionListener = new ActionListener() 
  {
    public void onAction(String name, boolean keyPressed, float tpf) 
    {
      if (name.equals("Walk") && !keyPressed) 
      {
        if (!channel.getAnimationName().equals("Walk")) 
        {
          channel.setAnim("Walk", 0.50f);
          channel.setLoopMode(LoopMode.Loop);
        }
      }
    }
  };
}

I did not have my armature modifier applied. However, I still saw the same error after applying the modifier and rerunning the code.

I was unable to upload the .blend file (only image files were allowed), so I uploaded a screenshots of the important views of the model (NLA, Outliner, Action Editor, and 3D view).

few

Thanks your reply ad for the tip on formatting code, I will do that from now on.

I could get this from the screen shots.

And yes you can not upload .blend here. I meant you may upload it to somewhere like Dropbox , Google drive or … .
I think i can fix it .

Thanks

Also JME 3.1 has more better support for blender models than 3.0.

Also do not get AnimControl like this :

because controller might be in child nodes of it.

I use something like this method to play animation on my complex models :

public static void playAnimation(Spatial model, String animationName) {
        SceneGraphVisitor visitor = new SceneGraphVisitor() {

            @Override
            public void visit(Spatial spatial) {

                if (spatial instanceof Node && spatial.getControl(AnimControl.class) != null) {

                    AnimControl control = spatial.getControl(AnimControl.class);
                    AnimChannel channel;
                    if (control.getNumChannels() > 0) {
                        channel = control.getChannel(0);

                    } else {
                        channel = control.createChannel();
                    }
                    channel.setAnim(animationName);
                    channel.setLoopMode(LoopMode.Loop);

                }
            }

        };

        model.depthFirstTraversal(visitor);
    }

Thanks for that example, I will try to use it.
I do not have a DropBox account (and for now I think it would be better to avoid trying to work out file-sharing), so for now I think I will try to consult more online sources (and perhaps try to animate a simpler model to get the basics first) to work towards fixing my problems. It is likely that I simply mis-modelled a part of my mesh, and that a second, more simple attempt will not encounter the same error.

Also, do you have any troubleshooting advice for the model? Even though I can’t upload the file now, I would be open to any suggestions as to where to start debugging the model.
Thanks again!

It is not an troubleshooting advise but as I see your model is human model so
My Suggestions is :
For your human models you can freely rig and animate them automatically in Mixamo without too much efforts.
I made video tutorials for it . you may watch them from part 2 :

And if you want to do them manually in blender so first learn basic tutorials in blender also the tutorials in JME Wiki page .