How to calculate a camera's lookat direction

This is a follow-up to a previous question (“Apply new camera world direction”) I asked last week. User tfoller explained some stuff to me that I thought I understood, but something is still missing in my understanding. In a sample code, my camera was at (500, 500, 3200). Because the camera is initially pointing in the (0, 0, -1) direction, I believe I can find a lookat point in the xy-plane (i.e., 3200 units away from the camera along z) as follows:

const forward = new THREE.Vector3(0, 0, -3200).applyQuaternion(camera.quaternion); 
const lookat = new THREE.Vector3().copy(camera.position).add(forward);

Or, more generally,

const forward = new THREE.Vector3(0, 0, -camera.position.z).applyQuaternion(camera.quaternion); 
const lookat = new THREE.Vector3().copy(camera.position).add(forward);

Indeed, doing that calculation returns the lookat to be (500, 500, 0), as expected.

Now let me move the camera by 500 units in the +x direction to (1000, 500, 3200). Then recalculating the lookat point returns (1000, 500, 0), also as expected.

But I want to now rotate the camera to be looking at the original lookat point, so I call

const original_lookat = THREE.Vector3(500, 500, 0);
camera.lookAt (original_lookat);

If I then recalculate the actual lookat using the code shown earlier, instead of the desired (500, 500, 0) I get (500.99, 500, 38.36). These differences in x and z seem to be more than just round-off error. And if I move the camera again, the errors accumulate. I think I don’t quite understand how to calculate the lookat point correctly. Can tfoller or anyone help my poor little brain figure this out?

Thanks.

Cameras have a getWorldDirection function that might be easier to use. Negate it, scale it by 3200 and add it to the camera position to see if you get what you expect. Also, one wouldn’t normally need to “calculate” a look-at point; instead, one would normally just set it to make the camera look at a point in the world.

Your confusion comes from the fact that there are vectors and there are points.

Unfortunately, THREE doesn’t have a class Point3, it uses Vector3 for both, the docs occasionally saying that something is a “a vector representing a position” (there is no such thing, strictly speaking).

A point represents a position in space, it has x,y,z coordinates for that (in Cartesian coordinate system). “Look at” is a point.

A vector represents a direction and a length (along that direction). A vector can be described by either two points (the start and the end), or by one point (the end), in this case the start point is assumed to be (0,0,0).

In THREE, Vector3(x, y, z) can either be a point (to look at, for example) or a vector that goes from (0,0,0) to (x,y,z).

The camera’s initial z-vector is (0,0,-1), starting from (0,0,0), going to (0,0,-1).

When you apply the quaternion to it, it rotates the vector along the camera’s current line of sight. This line of code should always be:

const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion); 

you can not put any other coordinates in this code, the quaternion should always rotate the original forward vector which is (0,0,-1).

If your camera is not at the origin, (you moved it), you need to move this vector as well, to re-attach it to the camera, if you like. The start point of this vector will be (camera.position), the end point (camera.position + forward).

All look at points will lie on this re-attached forward vector, for example you can choose (camera.position + forward) point to be the new look at point.

Originally, all look at points lie on the negative z-axis, you can not find them anywhere, they all lie on (forward) vector (0,0,-1).

When you call camera.lookAt(), all it does (-ish), it changes the camera quaternion. So after that, you need to update (forward) vector using the code above and then re-attach it to the camera, then everything will be in sync.

If it’s too much, you probably could find some video to explain how to work with vectors first, that will help to understand how to program them.

2 Likes

Thanks again. I have an out-of-town funeral to attend and will return to this stuff on Monday of next week.