Cannot move/rotate mesh

I was trying to move and rotate the Oto mesh(that came with jMonkeyEngine) and got a error.
[java]java.lang.NullPointerException
at Main.robotmovetest$1.onAnalog(robotmovetest.java:44)
at com.jme3.input.InputManager.invokeAnalogs(InputManager.java:245)
at com.jme3.input.InputManager.invokeUpdateActions(InputManager.java:215)
at com.jme3.input.InputManager.update(InputManager.java:882)
at com.jme3.app.Application.update(Application.java:604)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:231)
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)[/java]

Here is my code:
[java]package Main;

import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.input.controls.AnalogListener;

public class robotmovetest extends SimpleApplication {
public static void main(String[] args){
robotmovetest app = new robotmovetest();
app.start(); // start the game
}
protected Spatial robot;
@Override
public void simpleInitApp() {
Spatial robot = assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
rootNode.attachChild(robot);
robot.setLocalScale(0.3f, 0.3f, 0.3f);
robotInput();
//Add light
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal());
rootNode.addLight(sun);
}
public void robotInput() {
inputManager.addMapping(“MoveL”, new KeyTrigger(KeyInput.KEY_J));
inputManager.addMapping(“MoveR”, new KeyTrigger(KeyInput.KEY_K));
inputManager.addMapping(“RotateL”, new KeyTrigger(KeyInput.KEY_U));
inputManager.addMapping(“RotateR”, new KeyTrigger(KeyInput.KEY_I));
inputManager.addListener(analogListener, new String[]{“MoveL”, “MoveR”, “RotateL”, “RotateR”});
}
private AnalogListener analogListener = new AnalogListener() {
public void onAnalog(String name, float value, float tpf) {
if (name.equals(“RotateL”)) {
robot.rotate(0, valuespeed, 0);
}
if (name.equals(“RotateR”)) {
robot.rotate(0, value
speed, 0);
}
if (name.equals(“MoveL”)) {
Vector3f v = robot.getLocalTranslation();
robot.setLocalTranslation(v.x + valuespeed, v.y, v.z);
}
if (name.equals(“MoveR”)) {
Vector3f v = robot.getLocalTranslation();
robot.setLocalTranslation(v.x - value
speed, v.y, v.z);
}
}
};
}[/java]

The robot field of robotmovetest is null.

The SDK was probably warning you that you have a local variable that hides a field on line 19. That’s what it means.

Sorry, I didn’t understand what you said.
I checked, line 16 is like it is in the Input tutorial, line 19 is like it is in the Animation tutorial(I actually checked and changed it to …robot = (Node) assetManager… and imported com.jme3.scene.Node, didn’t help the problem). I’m not using the SDK, I’m using Eclipse and the Nightly builds.

Translation of what was stated above:

[java]
Spatial robot = assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
[/java]

is local in scope to simpleInitApp. Trying to reference robot in any other method is going to produce a NullPointerException, because your not setting the global field… you’re declaring a local variable with the same name.

1 Like

Your class has two different ‘robot’ :

  • local variable in function SImpleInitApp() (line 19)
  • field (line 16)

When you set it in line 19, only the local variable is set. Not the field…

You should really learn how to program in Java before learning JME. This is only the first trouble you are to run into…

Oh, I understand now. The robot mesh is only defined in the simpleInitApp, and the analogListener code doesn’t see it.
Thanks t0neg0d, you’ve been really helpful.
Also, be nice yang, this is a public forum.

@MasterEric said:Also, be nice yang, this is a public forum.
He didn't say anything wrong. You should in fact learn java before learning jME. The content of this post is meant to be read as a straight information or question without an implicit dismissive stance or interest in having the other party feel offended unless there's emotes that hint otherwise or there's an increased use of exclamation marks and all-capital words.
@MasterEric said: Also, be nice yang, this is a public forum.

I was very nice… I could have said this much more crudely ;-).
I even took time to explain what the problem was…

This was no insult; this was a mere advice. Learning both proves to be very hard. My students can confirm this !

1 Like

It was an easily over-lookable mistake.
Anyway, I’m trying to figure out how to load the model and still use it in the other methods, and can’t do it.
I’ve tried taking it out of the method(gives a nullpointerexception at the app.start(); line), putting it in its own method(still gives a nullpointerexception at the analogListener method). Nothing works.
Is there something I’m missing?

This, maybe?

[java]package Main;

import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.input.controls.AnalogListener;

public class robotmovetest extends SimpleApplication {
public static void main(String[] args){
robotmovetest app = new robotmovetest();
app.start(); // start the game
}
protected Node robot;
@Override
public void simpleInitApp() {
robot = (Node)assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
rootNode.attachChild(robot);
robot.setLocalScale(0.3f, 0.3f, 0.3f);
robotInput();
//Add light
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal());
rootNode.addLight(sun);
}
public void robotInput() {
inputManager.addMapping(“MoveL”, new KeyTrigger(KeyInput.KEY_J));
inputManager.addMapping(“MoveR”, new KeyTrigger(KeyInput.KEY_K));
inputManager.addMapping(“RotateL”, new KeyTrigger(KeyInput.KEY_U));
inputManager.addMapping(“RotateR”, new KeyTrigger(KeyInput.KEY_I));
inputManager.addListener(analogListener, new String[]{“MoveL”, “MoveR”, “RotateL”, “RotateR”});
}
private AnalogListener analogListener = new AnalogListener() {
public void onAnalog(String name, float value, float tpf) {
if (name.equals(“RotateL”)) {
robot.rotate(0, valuespeed, 0);
}
if (name.equals(“RotateR”)) {
robot.rotate(0, value
speed, 0);
}
if (name.equals(“MoveL”)) {
Vector3f v = robot.getLocalTranslation();
robot.setLocalTranslation(v.x + valuespeed, v.y, v.z);
}
if (name.equals(“MoveR”)) {
Vector3f v = robot.getLocalTranslation();
robot.setLocalTranslation(v.x - value
speed, v.y, v.z);
}
}
};
}[/java]

1 Like

Declaring it outside the method then specifying it inside simpleInitApp seems like it would work, but Node gives me an error. I think you have the gist of what I need to do though.
Do I import com.jme3.scene.Node(which gives an error for the file path in the assetManager bit) or com.bulletphysics.collision.broadphase.Dbvt.Node(which gives an error at the file path and attaching to rootNode and scaling).

You can ignore the node part and just do it like you were before with Spatial. Im not sure why you would get a file path error now if it worked before, unless you changed something else. Perhaps post the stack trace output. Also almost 100% of the time you would want com.jme3.scene.Node fyi

Yes, the Dbvt thing is something you should not play with (except if you want to look into the working of the physics engine…). Stick to the com.jme3.scene.Node, as told by @wezrule.

But you can also use a spatial, as you did previously.
The only difference is you won’t be able to get children of your model so easily. But you don’t seem to need it…

Edit : Sorry, reading the Wezrule post again, I see I don’t add much more.
I think there is no stack trace, it should not even compile without the proper imports…