0
\$\begingroup\$

I have a hierarchical node system. Given a world space transform, I need to obtain the transform for a specific node in local space.

My Node class has the following method.

public void worldToLocal(Matrix4 world, Matrix4 local) {
    if (dirty) update();
    local.set(worldInverse).mul(world);
}

worldInverse is the inverse of the node's world transformation matrix.

I'm using LibGDX, so this is equivalent to doing:

LOCAL = T^-1 * WORLD

T^-1 being the inverse of the node's world transform. However, this doesn't seem to be working correctly.

Let's say we have a node at (2, 4, 0) rotated 180 degrees along its Z axis.

    Node node = new Node();
    node.setPosition(2.0f, 4.0f, 0.0f);
    node.rotate(new Vector3(0.0f, 0.0f, 1.0f), 180.0f);

Now, the point (1, 7, 0) should be (2, 1, 0) in local space for that node.

    Matrix4 local = new Matrix4();
    Matrix4 world = new Matrix4();
    Vector3 pos = new Vector3();

    world.translate(1.0f, 7.0f, 0.0f);
    node.worldToLocal(world, local);
    local.getTranslation(pos);

However, I get (1, -3, 0).

I'm using this operation to translate from world space Bullet body transforms to local node transforms.

\$\endgroup\$
2
\$\begingroup\$

It's a bit vague what you want to do and what you have. But this should help:

Vector3 pos = new Vector3();
Matrix4 nodeTransform = new Matrix4();
nodeTransform.setToTranslation(2,  4,  0).rotate(Vector3.Z, 180f);
nodeTransform.getTranslation(pos);
Gdx.app.log("Node pos", pos.toString());
Matrix4 modelTransform = new Matrix4();
modelTransform.setToTranslation(1, 7, 0);
Matrix4 worldTransform = new Matrix4();
worldTransform.set(modelTransform).mul(nodeTransform);
worldTransform.getTranslation(pos);
Gdx.app.log("World pos", pos.toString());
Matrix4 invModelTransform = new Matrix4().set(modelTransform).inv();
nodeTransform.set(invModelTransform).mul(worldTransform);
nodeTransform.getTranslation(pos);
Gdx.app.log("Recalculated node pos", pos.toString());

which prints:

Node pos: (2.0,4.0,0.0)
World pos: (3.0,11.0,0.0)
Recalculated node pos: (2.0,4.0,0.0)

The nodeTransform holds the transformation of the node and it is assumed that it is a root node (or it included the parent transform). The modelTransform holds the transformation of the model (e.g. it is ModelInstance#transform). worldTransform holds the resulting matrix (e.g. it is the resulting Renderable#worldTransform value and what is used in the shader). invModelTransform is the inverse of the modelTransform which can be used to recalculate the nodeTransform when given the worldTransform.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.