Brand new to jMonkey, and I’m trying to move from working with geometry translations, which I seem to have down, to node translations, which seem to…well, go insane.
If you look in the updateLocalTranslation() method of my MobileObject class, the first two lines use geometry translations. Using WASD keys I can nicely move the human cube around with continuous drifting, in any of the Y and/or Z directions.
When I comment those two lines out and uncomment the last two which use node translations, I had thought it’d work exactly the same. Instead, within milliseconds of pressing one of the 4 keys, the System.out.println("MobileObject.updateLocalTranslation(): translationVelocities: "+translationVelocities); statement clearly shows that the velocity for that direction climbs to infinity. I can scroll up the log to see it progressing from 0 to infinity in the proper direction. So, why is there this immense difference in velocities between geometry and node translations? Thanks!
Notes:
- MyApplication is just a copy/paste of SimpleApplication, from which I’ve removed the FlyByCam and just use cam instead.
- Human extends MobileObject, and right now simply calls the super constructors, so no need to include.
[java]package mygame;
import mygame.MobileObjects.*;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.scene.shape.Box;
public class Main extends MyApplication {
//Class level variables
protected Geometry playerBody;
protected Node playerNode;
CameraNode cameraNode;
Geometry geom;
Boolean isRunning = true;
Spaceship spaceship;
Human human;
public static void main(String[] args) {
Main app = new Main();
app.start();
}
/**
- Initializes the scene components */
@Override
public void simpleInitApp() {
initCamera();
initGeometry();
initKeys();
}
@Override
public void simpleUpdate(float tpf) {
human.updateVelocity(tpf);
}
/**
- Set up the custom keybindings for the scene */
private void initKeys() {
// You can map one or several inputs to one named action
inputManager.addMapping("Pause", new KeyTrigger(KeyInput.KEY_P));
inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE));
// Add the names to the action listener.
inputManager.addListener(actionListener, new String[]{"Pause"});
inputManager.addListener(analogListener, new String[]{"Left", "Right", "Rotate", "Up", "Down"});
}
private ActionListener actionListener = new ActionListener() {
public void onAction(String name, boolean keyPressed, float tpf) {
if (name.equals("Pause") && !keyPressed) {
isRunning = !isRunning;
}
}
};
private AnalogListener analogListener = new AnalogListener() {
public void onAnalog(String name, float value, float ftp) {
if (isRunning) {
if (name.equals("Rotate")) {
human.updateVelocity(null, new Vector3f(0,1,0), ftp);
}
if (name.equals("Right")) {
human.updateVelocity(new Vector3f(-value, 0, 0), null, ftp);
}
if (name.equals("Left")) {
human.updateVelocity(new Vector3f(value, 0, 0), null, ftp);
}
if (name.equals("Up")) {
human.updateVelocity(new Vector3f(0, 0, value), null, ftp);
}
if (name.equals("Down")) {
human.updateVelocity(new Vector3f(0, 0, -value), null, ftp);
}
} else {
System.out.println("Press P to unpause.");
}
}
};
/**
- Set up the camera for the scene */
private void initCamera(){
cameraNode = new CameraNode("cameraNode", cam);
cameraNode.setControlDir(ControlDirection.SpatialToCamera);
}
/**
- Sets up the geometry for the scene /
private void initGeometry() {
//Create a red “player body”
Box playerBox = new Box(Vector3f.ZERO, 1, 1, 1);
playerBody = new Geometry(“Player”, playerBox);
Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);
mat.setColor(“Color”, ColorRGBA.Red);
playerBody.setMaterial(mat);
//attach the player geometry to it’s own node, and attach that to the root node
playerNode = new Node(“playerNode”);
rootNode.attachChild(playerNode);
playerNode.attachChild(playerBody);
human = new Human(playerBody, playerNode);
//attach the camera to the player’s node
playerNode.attachChild(cameraNode);
cameraNode.setLocalTranslation(0, 0, -40);
playerBody.setLocalTranslation(0, 0, 5);
//Create green “ground”
Box ground = new Box(Vector3f.ZERO, 1000, 0, 1000);
Geometry groundGeom = new Geometry(“Box2”, ground);
Material mat3 = new Material(assetManager, “Common/MatDefs/Misc/SolidColor.j3md”);
mat3.setColor(“m_Color”, ColorRGBA.Green);
groundGeom.setMaterial(mat3);
rootNode.attachChild(groundGeom);
groundGeom.setLocalTranslation(0, -10, 0);
}
}
[/java]
[java]/
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package mygame.MobileObjects;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
/**
*
-
@author Jonathan Lamb
*/
public class MobileObject {
public Geometry geometry;
public Node parentNode;
private Vector3f translationVelocities;
private Vector3f rotationVelocities;
protected MobileObject(){
}
public MobileObject(Geometry geometry, Node parentNode) {
this.geometry = geometry;
this.parentNode = parentNode;
this.translationVelocities = parentNode.getLocalTranslation();
//this.translationVelocities.z = .0001f;
this.rotationVelocities = new Vector3f();
}
//update location with any new changes
public void updateVelocity(float timePerFrame){
updateVelocity(null, null, timePerFrame);
}
public void updateVelocity(Vector3f translationVelocityChanges, Vector3f rotationVelocityChanges, float timePerFrame) {
if (rotationVelocityChanges != null){
this.rotationVelocities.x += rotationVelocityChanges.x * timePerFrame;
this.rotationVelocities.y += rotationVelocityChanges.y * timePerFrame;
this.rotationVelocities.z += rotationVelocityChanges.z * timePerFrame;
}
updateLocalRotation();
if (translationVelocityChanges != null){
this.translationVelocities.x += translationVelocityChanges.x * timePerFrame;
this.translationVelocities.y += translationVelocityChanges.y * timePerFrame;
this.translationVelocities.z += translationVelocityChanges.z * timePerFrame;
}
updateLocalTranslation();
}
public void updateNoVelocity(float timePerFrame){
updateVelocity(null, null, timePerFrame);
}
public void updateNoVelocity(Vector3f translationChanges, Vector3f rotationChanges, float timePerFrame){
if (rotationChanges != null){
this.rotationVelocities.x = rotationChanges.x * timePerFrame;
this.rotationVelocities.y = rotationChanges.y * timePerFrame;
this.rotationVelocities.z = rotationChanges.z * timePerFrame;
}
updateLocalRotation();
if (translationChanges != null){
this.translationVelocities.x = translationChanges.x * timePerFrame;
this.translationVelocities.y = translationChanges.y * timePerFrame;
this.translationVelocities.z = translationChanges.z * timePerFrame;
}
updateLocalTranslation();
}
//update location based on current location
private void updateLocalTranslation(){
//Vector3f localTranslation = geometry.getLocalTranslation();
//geometry.setLocalTranslation(localTranslation.x + translationVelocities.x, localTranslation.y + translationVelocities.y, localTranslation.z + translationVelocities.z);
System.out.println("MobileObject.updateLocalTranslation(): translationVelocities: "+translationVelocities);
Vector3f localTranslation = parentNode.getLocalTranslation();
parentNode.setLocalTranslation(localTranslation.x + translationVelocities.x, localTranslation.y + translationVelocities.y, localTranslation.z + translationVelocities.z);
}
//update rotation based on current rotation
private void updateLocalRotation() {
geometry.rotate(rotationVelocities.x, rotationVelocities.y, rotationVelocities.z);
}
}
[/java]