Getting camera rotation from unit vector

Started by
5 comments, last by Bacterius 11 years, 8 months ago
To start off, i am NOT talking about gluLookAt() to specify the camera rotation, so dont suggest i use it. I'm glRotatef to alter camera rotation.

So far i'v been using angle xrot,yrot,zrot (in degrees) to specify the camera rotation.
ei:

glRotatef(xrot,1.0,0.0,0.0);
glRotatef(yrot,0.0,1.0,0.0);
glRotatef(zrot,0.0,0.0,1.0);


My problem, say i have a unit vector (0.3433, 0.4243, 0.242) and i want to find the appropriate xrot,yrot,zrot to get the camera rotation according the given vector?

I was thinking to solve, say the xrot, i could take do ->angleBetween( (0.3433,0,0), (1,0,0) ) would give the xrot, and so on for the yrot,zrot.
Advertisement
A single unit vector isn't enough to obtain a three-dimensional camera basis, it'll only give you two angles (azimuth and inclination) which can be extracted via spherical coordinates, but not the third (rotation around the view vector).

It's fairly easy to understand why intuitively: if you are looking in a given direction, you can't tell whether your head is tilted left, right, or you are standing on your hands with your head upside down - the direction vector remains the same in all cases. You need more information.

From a mathematical point of view, a normalized 3D vector only has two degrees of freedom, since z = sqrt(x^2 + y^2), so the third component effectively adds no information. It should then be obvious that it is impossible to uniquely translate this vector to a representation which includes three degrees of freedom, i.e. your three angles.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

But if you think about the about an eye being the camera, your eye points in a direction just as the camera, so assuming an up-vector of always (0,1,0), there is no reason why you shouldn't be able to come up with the camera rotation angle from any nonzero vector (x,y,z)
To convert an orthogonal coordinate frame (identified by front and up directions) to a Euler rotation triplet, first construct an orthonormal matrix (a 'rotation matrix') that represents that coordinate frame, then decompose the matrix into a sequence of three rotation matrices about the cardinal axis sequence you prefer.

For reference, see e.g. MathGeoLib's float3x3 -> Euler conversion routines. (Code here). The derivations for the extractions are straightforward matrix algebra, but to make them robust requires a bit of thought. David Eberly's pdf is good reference for this.
But if you think about the about an eye being the camera, your eye points in a direction just as the camera, so assuming an up-vector of always (0,1,0), there is no reason why you shouldn't be able to come up with the camera rotation angle from any nonzero vector (x,y,z)[/quote]
Absolutely, if you assume a constant up vector then you can compute your orthonormal basis as follows, where [eqn]\hat{v}[/eqn] is your unit vector and [eqn]\hat{p} = (0, 1, 0)[/eqn]:

"Lateral" basis vector [eqn]\hat{b_x} = \hat{v} \times \hat{p}[/eqn]
"Vertical" basis vector [eqn]\hat{b_y} = \hat{v} \times \hat{b_x}[/eqn]
"Forward" basis vector [eqn]\hat{b_z} = \hat{v}[/eqn]

Or in pseudocode:

up = (0, 1, 0);
basisX = normalize(cross(v, up)); // "lateral"
basisY = normalize(cross(v, basisX)); // "vertical"
basisZ = v; // "forward"


(Note this is assuming a Y-up, Z-forward coordinate system, which is the one I'm most familiar with but is unfortunately not the one used by OpenGL, so shuffle the axes as needed)

I believe you can then extract each angle by dotting each basis vector with its corresponding axis, but I could be wrong (probably am, it's late).

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

unless your vector is pointing directly upwards or downwards (v=(0,+-1,0))

unless your vector is pointing directly upwards or downwards (v=(0,y,0))

Good point, the orthonormal basis is undefined in this case. Note the vector is normalized so it's going to be [eqn](0, \pm 1, 0)[/eqn].

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

This topic is closed to new replies.

Advertisement