Search code examples
vectorthree.jslinear-algebra

Three.js - how do up vectors work with lookAt()?


I'm trying to understand how up vectors and lookAt() work together in three.js. I'm setting the up vector of this axisHelper, so that the Y axis always points at the target geo, which marks the position of the up vector. It works as expected for X and Y, rotating the axes around the Z axis; and when I try to adjust the Z value of the up vector I would expect the axes to rotate around the X axis, but nothing happens.

http://jsfiddle.net/68p5r/4/ [Edit: I've added geo to show the up target position.]

I have a dat.gui interface manipulating the up vector to demonstrate, but the problem exists when I set the vector manually as well.

I suspect the problem is around line 74:

zControl.onChange(function(value) {
  axes.up.set(this.object.x, this.object.y, value);
  axes.lookAt(new THREE.Vector3(0, 0, 1));
});

When I update the up vector, I instruct the axisHelper to update its orientation onscreen by redoing its lookAt() down its Z axis. Changing the X and Y works as expected, why not the Z?

(This is also the case if I use geo instead of an axisHelper: http://jsfiddle.net/68p5r/5/)

rotated axisHelper


Solution

  • When you call Object.lookAt( vector ), the object is rotated so that its internal z-axis points toward the target vector.

    But that is not sufficient to specify the object's orientation, because the object itself can still be "spun" on its z-axis.

    So the object is then "spun" so that its internal y-axis is in the plane of its internal z-axis and the up vector.

    The target vector and the up vector are, together, sufficient to uniquely specify the object's orientation.

    three.js r.63


    Tip: An axis in three.js should always have unit length; be sure to call axis.normalize() in your code.