[Solved] Transform a force direction vector into local space

I need guidance on how to transform a force vector from world space to a geometry’s local space.

Basically, I am generating a force vector each tick and applying it to a specific point on each triangle of a mesh.

All of this is relative to world space, but using applyForce() from bullet’s rigidbody takes a force vector and a relative position vector, so I need to transform both my force vector and it’s position of application vector into the Geometry’s local space.

Geometry’s worldToLocal() method seems to work as expected for the position at which the force is actually applied, but does not work similarly on the force vector.

I suspect I am missing something in treating the force as a direction vector rather than a position vector, like properly transforming normals when a vertex moves.
(I thought about multiplying the force by the inverse transpose of the Geometry’s world transform matrix, but I use only uniform scaling on the geom, if any scaling at all)

I am currently using the worldspace force vector with the Geometry-transformed local position, which works to move the rigidbody as expected, until the body rotates away from being aligned with it’s local rotation.

For example, if I apply upward force to the front while in initial position, the front will lift… but if I first rotate the rigidbody by 180 degrees around the Y axis (using setPhysicsRotation()), that same upward force at that same local position will lift the rear.

I did try worldToLocal() on the force vector, and I have also tried multiplying the force by the Geometry’s world rotation, but both of those results were even worse.

Does anyone have any insight into how to preserve the relationship of a world force at a world point, when the world point has been transformed into local space?

1 Like

The location where the force is applied is (I believe) specified in the local coordinates of the rigid body. To convert a location from physics-space to local coordinates, you would first subtract the body’s translation, then apply its inverse rotation. (I’m hoping there’s no scaling involved.)

JME’s math library is (to put it mildly) tricky to use. Here’s roughly how this might look:

    Vector3f  translatedLocation = location.subtract(body.getPhysicsLocation());
    Quaternion inverseRotation = body.getPhysicsRotation().inverse();
    Vector3f localLocation = inverseRotation.mult(translatedLocation, null);

I’m unsure whether the applied force is specified in physics-space coordinates or in the local coordinates of the rigid body. If transformation is needed, it’s probably rotation only with no translation or scaling, something like this:

    Quaternion inverseRotation = body.getPhysicsRotation().inverse();
    Vector3f localForce = inverseRotation.mult(physicsSpaceForce, null);
1 Like

Just to explain, worldToLocal() won’t work on a force vector because the force vector is not a position… therefore cannot be a “world position” to translate into “local position”.

The rotation multiplication was close… but as sgold mentions, you’d want to do the inverse. A spatial’s world rotation is for going from local to world space… so you need the “inverse” of that… which is conveniently called “inverse()” in this case.

1 Like

ok, I multiplied my force vectors by the inverse of the geometry’s rotation, but I am still getting unexpected behavior, so I must have an error somewhere in calculating the force or the position.

I will continue multiplying my forces by the inverse of the rotation and try to troubleshoot how I am generating those vectors.

Thanks for the prompt response.

I found my silly mistake, you guys were right.
After transforming my point of force application from world space into local space, I needed to multiply that result by the rigidBodyControl’s physics rotation.
No more phantom forces.

1 Like