Move spatial in local space by same amount as linear velocity of the ship

Hi,
i have little frustrating problem. I know linear velocity of the ship and its direction. i would like to move spatial inside ship’s local space by same amount as linear velocity. but spatial have local translation and linear velocity is world translation, i cannot figure out, how to move spatial in local space in same direction as linear velocity in world space :frowning:

i have particle effect around ship to simulate some debris (particle emitter attached directly to ship’s node). and if ship accelerates, i want to move particle emitter in that direction by some amount, so more debris is created in front of the linear velocity

ascaria

Why don’t you do it in local space then, using a node thats attached to the ship?

Converting a velocity vector from world coordinates to local coordinates can involve both rotation and scaling.
You can obtain the scaling factor from:
[java]
Vector3f worldScale = ship.getWorldScale();
[/java]
and the rotation quaternion from:
[java]
Quaternion worldRotation = ship.getWorldRotation();
[/java]
Assuming uniform scaling (worldScale.x == worldScale.y && worldScale.y == worldScale.z) , you would then divide world velocity by both quantities. For instance:
[java]
float scale = worldScale.x;
Vector3f scaledVelocity = worldVelocity.divide(scale);
Vector3f localVeclocity = worldRotation.inverse().mult(scaledVelocity);
[/java]

1 Like

This should also work:

[java]
Vector3f worlLinearVel = …
Vector3f rel = spatial.getLocalTranslation().add(worldLinearVel);
Vector3f localLinearVel = spatial.worldToLocal(rel);
[/java]

…and takes care of scaling for you.

1 Like

normen i dont know what you mean :slight_smile:

i workaround it this way: i attached emitter directly into the scene at origin, not ship, and then simply
[java]spatial.setLocalTranslation(aligner.getPhysicsLocation().add(aligner.getLinearVelocity()));[/java]

solution by sgold worked like charm, thanks a lot man :slight_smile: im ignoring scaling for now, so i made it like this:
[java]
public class AlignByVelocityControl extends ControlAdapter {

protected PhysicsRigidBody rigidBody;
protected float sensivity = 1f;

public AlignByVelocityControl(PhysicsRigidBody rigidBody, float sensivity) {
    this.rigidBody = rigidBody;
    this.sensivity = sensivity;
}

@Override
protected void controlUpdate(float tpf) {
    Quaternion invRot = rigidBody.getPhysicsRotation().inverse();
    if(null != invRot) {
        spatial.setLocalTranslation(invRot.multLocal(rigidBody.getLinearVelocity().mult(sensivity)));
    }
}

}
[/java]
and emitter is now attached to ship.

solution by pspeed didnt work for me, at line 3, worldtolocal wants 2 args, and spatial.worldToLocal(rel, null); nor spatial.worldToLocal(rel, new Vector3f()); didnt make desired results :frowning:

thank you very much for your efforts :slight_smile:
ascaria

1 Like

I’m glad you got it working.

@Ascaria said: solution by pspeed didnt work for me, at line 3, worldtolocal wants 2 args, and spatial.worldToLocal(rel, null); nor spatial.worldToLocal(rel, new Vector3f()); didnt make desired results :(

Well, yes the second arg could be null or new Vector3f(). I’m glad you got things working but something else must have been wrong because sgold was essentially manually doing exactly what my code did. Anyway, if you don’t have to worry about scaling then the inverse rotation is simpler.

@pspeed said: Well, yes the second arg could be null or new Vector3f(). I'm glad you got things working but something else must have been wrong because sgold was essentially manually doing exactly what my code did. Anyway, if you don't have to worry about scaling then the inverse rotation is simpler.

tried again, i tried to get spatial’s world translation instead of local on your 2. line and it works :slight_smile:

so final version is:
[java]public class AlignByVelocityControl extends ControlAdapter {

protected PhysicsRigidBody rigidBody;
protected float sensivity = 1f;

protected Vector3f locLinVel = new Vector3f();
protected Vector3f rel = new Vector3f();

public AlignByVelocityControl(PhysicsRigidBody rigidBody, float sensivity) {
    this.rigidBody = rigidBody;
    this.sensivity = sensivity;
}

@Override
protected void controlUpdate(float tpf) {
    spatial.getWorldTranslation().add(rigidBody.getLinearVelocity(), rel);
    spatial.worldToLocal(rel, locLinVel);
    spatial.setLocalTranslation(locLinVel.multLocal(sensivity));
}

}[/java]

thanks :slight_smile:

Ooops. A typo. Sorry about that.

Note that since you don’t care about scaling, sgold’s approach is more straight forward I guess.

name of method worldToLocal seems to be good straight forward for me, it doing what i expect. also it is good to know, what is behind the scenes and you said it is essentially the same. i had same idea as sgold, use inverted (also negated, or opposite) world rotation so cancelling it out, but cannot figure out what method and in what order to use. i feel smarter now :smiley:

ascaria

1 Like