Using .getWorldTranslation() resets mesh translation [SOLVED]

Hi.

When I use the code snippet below, the mesh argument for some reason resets its translation to 0,0,0. Can anyone explain me why this keeps happening?

public ThrownGrenade(SimpleApplication app, Weapon weapon, Vector3f direction, Spatial mesh) {
	mesh.getWorldTranslation();}

No, that’s not what’s happening.

…but you haven’t included any relevant code so that’s about all I can say.

I think that’s the relevant snippet but nonetheless what is happening?

Ok. So since you aren’t doing anything with the results of that call, how do you know it changed? Changed from what? Where did you set it?

I mean… you’ve given us nothing but “hey something is going wrong somewhere but here is the line where the symptom happens.”

“I’m holding a piece of red curly string. How long is it?”

I see how it changes in debug mode.


Yes, but it’s the world transform and it will be recalculated to be the latest world transform when needed. So what’s the parent doing? What’s the local translation?

This code is working fine. Only your assumptions are messed up and they are in a ton of code we can’t see.

I can show the code, I just thought that one statement would be enough.

@Override
public void onAnimCycleDone(AnimControl comntrol, AnimChannel channel, String anim) {
	// TODO Auto-generated method stub
	if(anim.equals("detachingPin")){
		projectilesList.add(new ThrownGrenade(app, this, player.getCamNode().getCamera().getDirection(), mesh));
		rootNode.detachChild(mesh);
		super.primaryFire();
	}
}

public Projectile(SimpleApplication app, Weapon weapon, Vector3f direction, Spatial mesh) { this.app = app; this.weapon = weapon; rootNode = this.app.getRootNode(); assetManager = this.app.getAssetManager(); speed = ProjectileData.speed[weapon.getWeaponId()]; length = ProjectileData.length[weapon.getWeaponId()]; this.mesh = (Node) mesh; this.direction = direction.normalize(); }

public class ThrownGrenade extends Projectile {

private RigidBodyControl rigidBody;
private Node mesh;
private float speed, length;
private Vector3f direction;
private Boolean exploded = false, primed = false;

public ThrownGrenade(SimpleApplication app, Weapon weapon, Vector3f direction, Spatial mesh) {
	super(app, weapon, direction, mesh);
	this.length = super.getLength();
	this.speed = super.getSpeed();
	this.direction = super.getDirection();
	this.mesh = (Node)assetManager.loadModel(WeaponData.weaponMeshPath[weapon.getWeaponId()]);
	mesh.getWorldTranslation();
	//this.mesh.setLocalTranslation(worldPos);
	//this.mesh.setLocalRotation(worldRot);
	Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
	mat.setTexture("DiffuseMap", assetManager.loadTexture(WeaponData.weaponMeshTexPath[weapon.getWeaponId()]));
	this.mesh.setMaterial(mat);
	rootNode.attachChild(this.mesh);
	BulletAppState bas = app.getStateManager().getState(BulletAppState.class);
	CylinderCollisionShape shape = new CylinderCollisionShape(new Vector3f(1, 2, 1).mult(.25f), 1);
	rigidBody = new RigidBodyControl(shape, WeaponData.mass[weapon.getWeaponId()]);
	this.mesh.addControl(rigidBody);
	bas.getPhysicsSpace().add(rigidBody);
	rigidBody.setCcdSweptSphereRadius(.01f);
	rigidBody.setCcdMotionThreshold(.0001f);
	rigidBody.setLinearVelocity(this.direction.mult(25));
}

}

“mesh” is not attached when you call getWorldTranslation().

And now I wonder how you produced those logs with that code…

You understand that the line above on its own is doing nothing except recalculating the current world translation, right? You don’t get the result or anything. I’m not sure why it’s even there.

The model you loaded shouldn’t have even had a world translation. It’s not written or read in the j3o. (Assuming you are loading a j3o.) At best maybe you somehow managed to corrupt the original that is cloned upon repeated loading.

So as soon as you call getWorldTranslation() it’s going to calculate the latest world translation as a combination of the parent transform (which there is none) and the local translation (which you haven’t set and maybe isn’t set in the model)… thus 0, 0, 0.

Edit: and that is the extent of time I can devote to this thread. Hopefully others can help now… but it took 5 posts in to even see relevant code and that used up all of my free support time for this.

That line was just to test if it would cause the problem.

The mesh variable is initialized and attached to the root node in the super class. So I don’t understand why it would become unparented.

public class Grenade extends Weapon implements AnimEventListener{

private Player player;
private AnimControl control;
private AnimChannel channel;
private ArrayList<Projectile> projectilesList = new ArrayList<>();
private Node mesh;

public Grenade(SimpleApplication app, BulletAppState bas, int weaponId,Player player) {
	super(app, bas, weaponId, player);
	this.player=super.player;
	mesh=super.getMesh();
	control=super.control;
	channel=super.channel;
	control.addListener(this);
}

public void primaryFire(){
	channel.setAnim("detachingPin");
	channel.setSpeed(4);
	channel.setLoopMode(LoopMode.DontLoop);
}

@Override
public void onAnimChange(AnimControl arg0, AnimChannel arg1, String arg2) {
	// TODO Auto-generated method stub
	
}

@Override
public void onAnimCycleDone(AnimControl comntrol, AnimChannel channel, String anim) {
	// TODO Auto-generated method stub
	if(anim.equals("detachingPin")){
		projectilesList.add(new ThrownGrenade(app, this, player.getCamNode().getCamera().getDirection(), mesh));
		rootNode.detachChild(mesh);
		super.primaryFire();
	}
}

}
public class Weapon {

protected AssetManager assetManager;
protected Node rootNode;
protected BulletAppState bas;
private Node mesh;
protected ParticleEmitter particleEmitter;
protected PointLight muzzleFlashPointLight;
protected AnimControl control;
protected AnimChannel channel;
private AudioNode sound;
private int shots, weaponId, clipAmmo, reserveAmmo, altClipAmmo, altReserveAmmo;
private float mass;
protected long lastShotTime;
private Boolean automatic, dropped = false, firingAutomatically = false;
private ArrayList<Projectile> projectiles = new ArrayList<Projectile>();
private RigidBodyControl rigidBody;
protected Player player;
protected SimpleApplication app;

public Weapon(SimpleApplication app, BulletAppState bas, int weaponId, Player player) {
	this.app = app;
	this.player = player;
	assetManager = this.app.getAssetManager();
	rootNode = this.app.getRootNode();
	this.bas = bas;
	this.weaponId = weaponId;
	mass = WeaponData.mass[weaponId];
	automatic = WeaponData.automatic[weaponId];
	clipAmmo = WeaponData.clipAmmo[weaponId];
	altClipAmmo = WeaponData.altClipAmmo[weaponId];
	reserveAmmo = WeaponData.reserveAmmo[weaponId];
	altReserveAmmo = WeaponData.altReserveAmmo[weaponId];
	mesh = (Node) assetManager.loadModel(WeaponData.weaponMeshPath[weaponId]);
	Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
	mat.setTexture("DiffuseMap",
			this.assetManager.loadTexture(new TextureKey(WeaponData.weaponMeshTexPath[weaponId], true)));
	mesh.setMaterial(mat);
	control = mesh.getControl(AnimControl.class);
	channel = control.createChannel();
	channel.setLoopMode(LoopMode.DontLoop);
	try {
		sound = new AudioNode(assetManager, WeaponData.soundPath[weaponId], false);
		sound.setVolume(1);
		sound.setPositional(false);
		// sound.setDirectional(true);
		rootNode.attachChild(sound);
	} catch (NullPointerException e) {
	}
	SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
	Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
	mat1.setColor("Color", ColorRGBA.Green);
	mat1.getAdditionalRenderState().setDepthTest(false);
	skeletonDebug.setMaterial(mat1);
	mesh.attachChild(skeletonDebug);
}}

you do understand that this line in throwGrenade assigns your mesh variable to a new instance, right?

this.mesh = (Node)assetManager.loadModel(WeaponData.weaponMeshPath[weapon.getWeaponId()]);

Yes, that’s the point because I’ve experimented with some algorithms and this one works as I want it, had it not been for the problem why I posted this thread.

The problem isn’t even with this.mesh but rather mesh. I pass it as an argument from Grenade class as spatial casted to a node but the problem persists when I use .getWorldTranslation().

Well… seems it doesn’t since you’re here.

so that basically this you are doing:

MyObject myObject = new MyObject ();
myObject.setSomeStuff(someStuff);
myObject = new MyObject ();
newStuff = myObject.getSomeStuff();//why the fuck newStuff is not someStuff??

Do you get it now?

I understand your example but even if try to do this:

    public ThrownGrenade(SimpleApplication app, Weapon weapon, Vector3f direction, Spatial mesh) {
	super(app, weapon, direction, mesh);
	this.length = super.getLength();
	this.speed = super.getSpeed();
	this.direction = super.getDirection();
	Vector3f pos= mesh.getWorldTranslation();
	this.mesh = (Node)assetManager.loadModel(WeaponData.weaponMeshPath[weapon.getWeaponId()]);
	//this.mesh.setLocalTranslation(worldPos);
	//this.mesh.setLocalRotation(worldRot);
	Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
	mat.setTexture("DiffuseMap", assetManager.loadTexture(WeaponData.weaponMeshTexPath[weapon.getWeaponId()]));
	this.mesh.setMaterial(mat);
	rootNode.attachChild(this.mesh);
	BulletAppState bas = app.getStateManager().getState(BulletAppState.class);
	CylinderCollisionShape shape = new CylinderCollisionShape(new Vector3f(1, 2, 1).mult(.25f), 1);
	rigidBody = new RigidBodyControl(shape, WeaponData.mass[weapon.getWeaponId()]);
	this.mesh.addControl(rigidBody);
	bas.getPhysicsSpace().add(rigidBody);
	rigidBody.setCcdSweptSphereRadius(.01f);
	rigidBody.setCcdMotionThreshold(.0001f);
	rigidBody.setLinearVelocity(this.direction.mult(25));
}

Variable pos is still 0,0,0 when I use .getWorldTranslation() despite the fact that mesh is parented in the beginning, has a global translation that’s not 0,0,0 and pos is initialized before this.mesh.

Prove it.

If I add System.out.println("Pos: "+pos); like you can see in the source code, it outputs Pos: (0.0, 0.0, 0.0)

        public ThrownGrenade(SimpleApplication app, Weapon weapon, Vector3f direction, Spatial mesh) {
	super(app, weapon, direction, mesh);
	this.length = super.getLength();
	this.speed = super.getSpeed();
	this.direction = super.getDirection();
	Vector3f pos= mesh.getWorldTranslation();
	System.out.println("Pos: "+pos);
	this.mesh = (Node)assetManager.loadModel(WeaponData.weaponMeshPath[weapon.getWeaponId()]);
	//this.mesh.setLocalTranslation(worldPos);
	//this.mesh.setLocalRotation(worldRot);
	Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
	mat.setTexture("DiffuseMap", assetManager.loadTexture(WeaponData.weaponMeshTexPath[weapon.getWeaponId()]));
	this.mesh.setMaterial(mat);
	rootNode.attachChild(this.mesh);
	BulletAppState bas = app.getStateManager().getState(BulletAppState.class);
	CylinderCollisionShape shape = new CylinderCollisionShape(new Vector3f(1, 2, 1).mult(.25f), 1);
	rigidBody = new RigidBodyControl(shape, WeaponData.mass[weapon.getWeaponId()]);
	this.mesh.addControl(rigidBody);
	bas.getPhysicsSpace().add(rigidBody);
	rigidBody.setCcdSweptSphereRadius(.01f);
	rigidBody.setCcdMotionThreshold(.0001f);
	rigidBody.setLinearVelocity(this.direction.mult(25));
}

That proves one thing: it’s set to 0 either before you get into that method either in you super…but we can’t tell because we can’t see the code

sigh. I don’t even know why I’m wasting my time on this thread. It’s like pulling teeth.

In this:

Where that red line is, put the following statements:

System.out.println("mesh local translation:" + mesh.getLocalTranslation());
System.out.println("mesh parent:" + mesh.getParent());
System.out.println("parent local translation:" + mesh.getParent().getLocalTranslation());
System.out.println("parent world translation:" +  mesh.getParent().getWorldTranslation());

Personally, my money is on an NPE in the third line… but we’ll see.

Edit: oh, and then paste back the code and the output. If you post only one then you are on your own.