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;
@Override
public void simpleInitApp() {
Torus t1 = new Torus(10, 10, 1.5f, 2.5f);
g1 = new Geometry("T1", t1);
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
g1.setMaterial(mat);
g1.setLocalTranslation(-5, 0, 0);
rootNode.attachChild(g1);
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,
"Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Red);
g2.setMaterial(mat);
n.attachChild(g2);
rootNode.attachChild(n);
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camPos = cam.getLocation();
g1.lookAt(camPos, Vector3f.UNIT_Y);
g2.lookAt(camPos, Vector3f.UNIT_Y);
}
}[/java]
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.
Right, but this is a long time… I found a workaround if you wish…
[java]
Quaternion tmp = null;
tmp = getParent().getLocalRotation().inverse(); // compute compensation first
lookAt(target.getWorldTranslation(), Vector3f.UNIT_Y); // aim
tmp.multLocal(getLocalRotation()); // combinate
setLocalRotation(tmp);
[/java]
I did that in a control to have a camera tracking some target.
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.
:? 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.