2
votes

I have a basic question, but I could not find the answer.

I noticed that the following code:

const p = new THREE.Vector3();
const q = new THREE.Quaternion();
const s = new THREE.Vector3();

function setPositionAndRotation(o) {
  o.position.set(1, 1, -1);
  o.lookAt(0, 0, 0);
  o.updateMatrix();
  o.matrix.decompose(p, q, s);
  console.log(JSON.stringify(q));
}
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, .01, 1000);
var mesh = new THREE.Mesh(new THREE.Geometry(), new THREE.MeshBasicMaterial());
setPositionAndRotation(camera);
setPositionAndRotation(mesh);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>

produces different quaternions for Camera and Object3D:

{"_x":-0.11591689595929515,"_y":0.8804762392171493,"_z":0.27984814233312133,"_w":0.36470519963100095}

{"_x":0.27984814233312133,"_y":-0.3647051996310009,"_z":0.11591689595929516,"_w":

(These are two quaternions pointing into opposite directions on Z axis.)

The problems lies in the bahavior of the lookAt function. I dug into source code of Object3d and I found this if https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L331

if ( this.isCamera ) {

    m1.lookAt( position, target, this.up );

} else {

    m1.lookAt( target, position, this.up );

}

As you can see Object3D is handled differently than Camera. target and position are swapped.

Object3D's documentation says:

lookAt ( x : Float, y : Float, z : Float ) : null

Rotates the object to face a point in world space.

but the code does the opposite. It uses Matrix4's lookAt function

lookAt ( eye : Vector3, center : Vector3, up : Vector3, ) : this

Constructs a rotation matrix, looking from eye towards center oriented by the up vector.

putting target into eye, and position into center.

I can deal with that, but it is weird. Is there anybody able to explain why it is so?

r.97

1
I just discover the same issue now, when I try to use calculation on objected as a base for camera movement. WEIRDpery mimon
you save my day . to fix the LookAt I just add object3d.isCamera = truepery mimon

1 Answers

3
votes

In three.js, an unrotated object is considered to face its local positive-z axis.

The exception is a camera, which faces its local negative-z axis.

This design decision followed OpenGL convention.