How to calculate the quaternion from/and axis angle having parent and target position (camera and its target)?

4.2k Views Asked by At

I want to calculate the orientation (quaternion) of the virtual 3d camera that is looking at some point in 3d space.

The illustration: enter image description here

According to this explanation the quaternion be calculated from axis-angle:

qx = axis.x * sin(angle/2)
qy = axis.y * sin(angle/2)
qz = axis.z * sin(angle/2)
qw = cos(angle/2)

I calculate the axis angle this way (it's a pseudo code):

Point3D axis = normalize(target.position - camera.position); //direction
angle = 0;

But of course the quaternion will be [0, 0, 0, 1] for any given target.position and camera.position (sin(0) = 0). Which is wrong.

I guess that axis-angle to quaternion formula is ok.

Then maybe the axis angle should be calculated differently?

I thought about axis-angle as "the direction in which the object is pointing + the angle around that direction". Maybe it's more like "rotate the object around given direction by this angle"? But if so, axis-angle would not cover all possible 3d orientations.

How to calculate the axis angle having target.position and camera.position?

I work on left-handed coordinate system, but the solution should be quite analogical for right-handed one.


Edit, clarification based on @anon request:

I'm not a mathematician (more a programmer) and some parts of quaternion math looks complicated to me. But I will try to explain what I've meant by "orientation of the camera".

In almost any 3d software (e.g. 3ds max, Blender) or game engine (e.g. Unity) you have two main components for each object: position (x,y,z) and orientation (quaternion x,y,z,w). To get the object in right place you rotate it first by orientation and then translate by position to place in the 3d scene before rendering.

By orientation of camera I mean that, common for 3d software, "object orientation" (on the illustration you can see that camera is rotated and translated from the center of the scene). Precisely speaking, in left-handed coordinate system, with y axis pointing "up".

Let's assume we remove the camera's target from an image for a moment. I should be able to restore the camera by: placing un-rotated camera object in [0,0,0], rotating it by my orientation (which I want to calculate) and then translating by position (which I already have).

2

There are 2 best solutions below

0
On

The orientation quaternion of the camera describes the rotation needed to make the camera have a new orientation relative to some other orientation.

This other, original orientation is usually some reference orientation: for instance, camera pointing upward the z-direction, camera right along the x-direction, and camera down along the y-direction.

You haven't fully specified the orientation desired of the camera. For instance, once the camera points to the target object, you could spin the camera along that axis and that would be equally valid.

Nevertheless, the angle you need to use for your quaternion is not 0--rather, it should at least be the angle between the reference direction of the camera and the line between the camera and the target.

Edit: moreover, the axis about which you would rotate the camera to point toward the target is not the direction from the camera to the target. Rather, it should be the direction that is perpendicular to that line as well as perpendicular to the current direction of the camera (that is, you want to rotate in the plane of the camera direction and the target's direction). This is accomplished by using the cross product, for example.

0
On

You did not describe what the "original" orientation of the camera actually is, that is, what the unrotated camera looks like. I'll suppose that the camera would be pointing along the positive $x$-axis and that a vector from the center to the "top" of the camera would point in the direction of the positive $z$-axis.

Now let's say you want the camera pointing downward at a $45$-degree angle in the $x,z$ plane, that is, the axis of the camera will be in the direction of the vector $\left[\frac{\sqrt2}{2}, 0, -\frac{\sqrt2}{2}\right]$, and that the direction to the "top" of the camera will also still be in the $x,z$, plane, in the direction $\left[\frac{\sqrt2}{2}, 0, \frac{\sqrt2}{2}\right]$.

You get the camera into this orientation by rotating it $45$ degrees ($\pi/4$ radians) around the $y$-axis, that is, using the rotation quaternion $\left[0, \sin\left(\frac\pi8\right), 0, \cos\left(\frac\pi8\right)\right]$ (or maybe that should be $-\sin\left(\frac\pi8\right)$ instead of $\sin\left(\frac\pi8\right)$; it depends on which way is a "positive" rotation around the axis).

In short, the axis of rotation that turns your camera to the desired orientation is usually nowhere near the axis along which the camera ends up pointing.

The axis and angle to achieve a general orientation is not usually as obvious as in this simple case. Rather than trying to guess it directly, you are probably better off performing a series of simple rotations, for example elevate or depress the angle of the camera and then rotate it around the vertical axis (the $z$ axis in my example, or whichever of the axes is vertical in your system). If you also want the camera to be "twisted" around its own axis, then you might want to rotate it about that axis before the other two rotations.

To represent a sequence of rotations, you multiply together the quaternions for each rotation. You then have a single quaternion that represents a single rotation taking the camera from its original orientation to the desired orientation.