Spatial.lookAt confused by parent node transform


If you do Spatial.lookAt() at a location while the spatial is in a transformed (rotated) node then the spatial does not look at the correct location but instead looks where the location would be if transformed.

Simple test case:
[java]public class LookAtTestCase extends SimpleApplication {

public static void main(String[] args){
    LookAtTestCase app = new LookAtTestCase();
    app.start(); // start the game

Geometry g1, g2;

public void simpleInitApp() {
    Torus t1 = new Torus(10, 10, 1.5f, 2.5f);
    g1 = new Geometry("T1", t1);
    Material mat = new Material(assetManager,
    mat.setColor("Color", ColorRGBA.Blue);
    g1.setLocalTranslation(-5, 0, 0);
    Node n = new Node("Rotated");
    n.setLocalTranslation(5, 0, 0);
    n.rotate(0, FastMath.HALF_PI, 0);
    Torus t2 = new Torus(10, 10, 1.5f, 2.5f);
    g2 = new Geometry("T2", t2);
    mat = new Material(assetManager,
    mat.setColor("Color", ColorRGBA.Red);

public void simpleUpdate(float tpf) {
    Vector3f camPos = cam.getLocation();
    g1.lookAt(camPos, Vector3f.UNIT_Y);
    g2.lookAt(camPos, Vector3f.UNIT_Y);


Run the app, you see a blue and a red torus. Move around using flycam and you can see they turn towards you but despite both doing a lookAt to the camera location one is always looking in a different direction due to the rotation of the node it is attached to.

1 Like

Thanks, we’ll check it out.

Right, but this is a long time… I found a workaround if you wish…
Quaternion tmp = null;
tmp = getParent().getLocalRotation().inverse(); // compute compensation first
lookAt(target.getWorldTranslation(), Vector3f.UNIT_Y); // aim
tmp.multLocal(getLocalRotation()); // combinate

I did that in a control to have a camera tracking some target.

Hope that helps.


Actually we had the same issue with billboard controls before.
And the fix was almost to the letter what @yang71 suggests

1 Like

Thanks @yang71, I’ve already worked around it in my code (attached them to the root node…scene graph is a bit more disorganised but actually it made a certain amount of sense in the case of these objects so I don’t really mind. Thanks for posting the code though.

I think you can even simplify it a bit actually. You should get the same result by just multiplying the target vector by the inverse rotation and then feeding that into lookAt - which will cancel out the problem rotation and you will be fine. You should also use parent getWorldRotation just in case its nested several transformed nodes deep in your scene graph.

Still it’s worth getting the bug fixed :slight_smile:

:? I don’t understand what takes a long time or if anybody thinks this is fixed as I have trouble understanding the comments. At any instance, Spatial.lookAt should work globally in the scenegraph, no matter where the spatials are and how they are related parent/child-wise. If it doesn’t that has to be fixed.

It’s fixed.
@yang71 you may want to remove your workaround though now

Thanks @Nehon. I’ll remove my workaround tomorrow, after downloading the latest nightly build…

Sorry @Normen if I’ve not been understandable enough, it’s quite late here and english is not my native language.

@yang71 No worries, it might really be that I am a bit sleep-deprived ^^

go sleep! your no use to us tired :), j/k <3