## Camera rotation based on Camera.view > target vector

**category:**general [glöplog]

I really thing= I really think

cameras are nightmare i have a nice slids about them from gfx course i'll dig my pc for it brb

So yeah, the code on the first post just needed this:

Thanks a lot guys! Don't know how I couldn't see the relation of rotationZ and camera roll myself at first :S

**Code:**

`rotationZ = 0;`

Thanks a lot guys! Don't know how I couldn't see the relation of rotationZ and camera roll myself at first :S

I strongly recommend not to use angles for camera or object manipulation. Never, unless it's mandatory for some obscure reason. The best is to use vectors, like what rydi posted (like gluLookAt). Angles and trigonometry should be forbidden in cg and algebra, it makes it all more difficult, confusing,unstable and slow. Signed by the "never angles, just vectors guy".

That will be on the next iteration/project, seemed easier to mess with angles than with matrices at the moment :) Also is not much of a change to move from one to another.

Do you know if matrices are actually faster than angles? They seem like more operations per vertex to me.

Do you know if matrices are actually faster than angles? They seem like more operations per vertex to me.

I'm sorry iq, but I don't agree with you. After you understand everything and you have all the math knowledge, then it is true what you say.

But, to learn, I believe the way trace is doing it is a good one - as good as any other way. In the secondary school we all learn a bit about angles, so the concept is more or less clear. But, at least in my school, we did nothing about matrices. We did a bit about vectors, but the true applications of vectors were not as clear and meaningful as angles.

At the end, the matrix rotation and the angle based rotations are the same thing. I believe the best way to learn is just to do it with the tool you feel more comfortable. After that, you can learn new ways and implement it again.

@trace:

It will be about the same number of operations, just depends on how you code it.

Always remember that you are coding in Flash, and that what works good for Flash doesn't have to work fine for C code, and vice versa.

Any advice from a C coder won't be very useful in Flash. Speed depends on the operations run time, and it is very different from one language to another - and also compiler and machine dependant. Just try to reduce the operations to the minimum. Just one example: in C atan is dozens of times slower than a sum or a muliplication. In Flash it doesn't have to be true. I'm sure atan is slower than a sum of multiplication in Flash, but it might be only a bit slower... So, well... just try and see differences...

But, to learn, I believe the way trace is doing it is a good one - as good as any other way. In the secondary school we all learn a bit about angles, so the concept is more or less clear. But, at least in my school, we did nothing about matrices. We did a bit about vectors, but the true applications of vectors were not as clear and meaningful as angles.

At the end, the matrix rotation and the angle based rotations are the same thing. I believe the best way to learn is just to do it with the tool you feel more comfortable. After that, you can learn new ways and implement it again.

@trace:

It will be about the same number of operations, just depends on how you code it.

Always remember that you are coding in Flash, and that what works good for Flash doesn't have to work fine for C code, and vice versa.

Any advice from a C coder won't be very useful in Flash. Speed depends on the operations run time, and it is very different from one language to another - and also compiler and machine dependant. Just try to reduce the operations to the minimum. Just one example: in C atan is dozens of times slower than a sum or a muliplication. In Flash it doesn't have to be true. I'm sure atan is slower than a sum of multiplication in Flash, but it might be only a bit slower... So, well... just try and see differences...

I don't agree Texel. How can a rotateX(), rotateY(), rotateZ() and tranlsate() and all the angle order conventions (xyz, -zxz, yzx, ...) be more simple than gluLookat( fromHere, toHere, roll );

iq: I think the point texel is trying to make is that while it is easier to do gluLookat, doing it the hard way is a good way to learn how things fit together.

I'll agree with iq that rotations and translations are a complete headfuck compared to gluLookAt. If you have a much simpler situation (i.e. camera hovering over 2D planes, camera rotates around an object in circle) then I suppose the rotations and translations are as simple...

I don't have gluLookat in flash. In fact, that's exactly what I was trying to code!

then use the code ryui posted in the previus page, that's exactly what gluLookAt does.

Also, the day you need to do camera path interpolations you better have gluLookAt kind of camera. Interpolating angles (for rotateX() and so on) is complex and it well deservers a doctoral thesis (no joke at all). Interpolating a camera position and a target position is straightforward and that's what you are intuitively used to do anyway in max or maya. Angles are an invention of mathematicians, don't really make sense!

Also, the day you need to do camera path interpolations you better have gluLookAt kind of camera. Interpolating angles (for rotateX() and so on) is complex and it well deservers a doctoral thesis (no joke at all). Interpolating a camera position and a target position is straightforward and that's what you are intuitively used to do anyway in max or maya. Angles are an invention of mathematicians, don't really make sense!

the code that 216 posted also does that, his post answered perfectly my question in this thread. I now have a lookat function that is coded with angles. And seems like I can interpolate camera and target positions without problems.

i agree with you that some parts of the projections using angles are too complex, but I'm just giving it a try and see if it's faster like this.

i agree with you that some parts of the projections using angles are too complex, but I'm just giving it a try and see if it's faster like this.

Understand what's called gimbal lock here and try to build a single matrix from your transformation-mess.

as a rule of thumb, anything with acos asin atan means you've got it wrong somewhere...

lazy-san: doesn't the gimbal lock also happen with matrices. I thought that's what quaternions were for.

if it works and you are happy, then it's ok.

I like matrices cause they are a simple way to pack the three (usually perpendicular) projection vectors. The vertex transformation is done by projection the vertex in eaxh of the three coordinate axes (with a substraction and a dot product). So, that's 9 muls and 9 adds per vertex, the fastest method to transform vertices.

That's my preferred method. So, my code looks like what rydi posted:

I like matrices cause they are a simple way to pack the three (usually perpendicular) projection vectors. The vertex transformation is done by projection the vertex in eaxh of the three coordinate axes (with a substraction and a dot product). So, that's 9 muls and 9 adds per vertex, the fastest method to transform vertices.

That's my preferred method. So, my code looks like what rydi posted:

**Code:**

```
void cameraLookAt( float *matrix, const vec3 & pos, const vec3 & tar, const vec3 & up )
{
// compute the three camera coordinate system axes
const vec3 w = normalize( tar - pos );
const vec3 u = normalize( cross(up,w) );
const vec3 v = normalize( cross(w, u) );
// pack them into a matrix, and precompute the position projection (dots)
matrix[ 0] = u.x;
matrix[ 1] = u.y;
matrix[ 2] = u.z;
matrix[ 3] = -dot( pos, u );
matrix[ 4] = v.x;
matrix[ 5] = v.y;
matrix[ 6] = v.z;
matrix[ 7] = -dot( pos, v );
matrix[ 8] = w.z;
matrix[ 9] = w.z;
matrix[10] = w.z;
matrix[11] = -dot( pos, w );
}
then you can use like this:
// compute modelview matrix
float mat[12];
cameraLookAt( mat, camaPosition, camTarget, vec3(0.0f,1.0f,0.0f) );
// transform all vertices of a mesh
for( int i=0; i<mesh.mNumVertices; i++ )
{
vec3 v = vec3( dot( mesh.mVertex[i], vec3(mat[0],mat[1],mat[ 2]) ) + mat[ 3],
dot( mesh.mVertex[i], vec3(mat[4],mat[5],mat[ 6]) ) + mat[ 7],
dot( mesh.mVertex[i], vec3(mat[8],mat[9],mat[10]) ) + mat[11] );
...
}
```

Oh, I'm not btw advocating using euler angles for anything (except maybe when you have a robot that happens to implement those). But hey, you asked:)

Rule number 1: You don't need angles. *)

Rule number 2 (for experts only): If you really need them, you don't want euler angles. **)

Rule number 3: Seriously, how often you model such robots? Don't you want to do something more generic instead like supporting four joints instead of theree?

*) You might need "cosine of an angle" or somesuch, but that's not an angle.

**) Axis,angle may come handy if you're working with angular momentum..

Rule number 1: You don't need angles. *)

Rule number 2 (for experts only): If you really need them, you don't want euler angles. **)

Rule number 3: Seriously, how often you model such robots? Don't you want to do something more generic instead like supporting four joints instead of theree?

*) You might need "cosine of an angle" or somesuch, but that's not an angle.

**) Axis,angle may come handy if you're working with angular momentum..

agree, dot product (cosines of angles, measure of parallelism) and cross products (sines of angles, measure for perpendicularity) are the thing. I seriously hate Euler angles too, although I can use (axis,angle) or quaternions when there isn't any other choice. Btw, robotics must be fun.

**Quote:**

doesn't the gimbal lock also happen with matrices.

I thought that's what quaternions were for.

You run into problems when building a matrix using "lookat" and the view-vector (tar-pos, see iq's snippet) becomes parallel to the up-vector; but in that case you specified a wrong up-vector anyways - it's not a general problem of matrices.

Quaternions are for interpolating rotations (see here). Generally you can describe any orientation as a quaternion (or axis/angle), but they're less intuitive to specify manually than position and target.

I'd also like to mention that your example should crash with e.g. vector = (1, 0, 0), as atan2(0, 0) is not defined.

Without checking it though, I also seriously doubt that your algorithm gives good results for all non-degenerated examples (where atan2 exists). You might check your algorithm with vectors close to (1, 0, 0), e.g. vector = (1, 0.001, 0.01*sin(time)). I wouldn't be too surprised if your camera starts spinning like no tomorrow even though the look direction is always very similar.

I assume here that (1,0,0) is not your "up". If it is, vectors similar to (0,1,0) should give you the same problems.

I'd suggest to google euler view direction.

Without checking it though, I also seriously doubt that your algorithm gives good results for all non-degenerated examples (where atan2 exists). You might check your algorithm with vectors close to (1, 0, 0), e.g. vector = (1, 0.001, 0.01*sin(time)). I wouldn't be too surprised if your camera starts spinning like no tomorrow even though the look direction is always very similar.

I assume here that (1,0,0) is not your "up". If it is, vectors similar to (0,1,0) should give you the same problems.

I'd suggest to google euler view direction.

**Quote:**

doesn't the gimbal lock also happen with matrices.

If all you're doing is creating a world->camera matrix from three angles and a position, then you have the same gimbal lock issues, and the same order-of-rotation issues as you do if you just perform the three rotations on every point you want to transform. The real benefits are in not having to think about rotations and angles at all (except when a transformation is explicitly a rotation by a certain angle, etc.). That's how you get rid of gimbal lock for good.

Imagine you're doing a flight simulator. The plane (and thus the camera) is expressed in terms of its rotation about the world x, y and z axes, plus an offset from the world origin. This is equivalent to what you're doing now. And now you want the plane to roll 0.1 radians clockwise. So which of the three angles do you change, and by how much? The point is that it's a very tricky thing to work out, and it depends on the order in which the x, y and z rotations are applied later, and you'll always have special cases to deal with.

Now imagine instead that the orientation of the plane is defined by a forward vector, an up vector and a right vector. These automatically describe the world->camera transformation you need to do, which is nice, but more importantly, to roll the plane all you need to do is rotate the up and the right vector around the forward vector. There are quaternion and matrix ways to do this very easily, and if you think about it, all you need to do is rotate the vectors (1,0,0) and (0,1,0) around (0,0,1), then map the resulting two vectors into the local object space for the plane, however the plane happens to be located, and then you have your rotated up and right vectors.

It generalises to a matrix-matrix multiplication and everything gets very neat and tidy that way, plus you save clock cycles by not doing unnecessary arithmetic, but the real benefit is in not having to deal with angles/polar coordinates.

**Quote:**

I think the point texel is trying to make is that while it is easier to do gluLookat, doing it the hard way is a good way to learn how things fit together.

I think you learn the wrong things, though. Using angles isn't easier than not using angles, and it's not more efficient. It's not simpler to wrap your head around, and it's not even faster to code. You need to know some basics about rotation, but the sooner you get into the mindset of local coordinate systems, the better.

yes, angles are bad!

almost every time you see trigonometric function in your code, you should replace it with vector notation. it will become simpler and faster.

only exceptions are when you need angles as input or output. i am talking of input and output of the whole program, not of a function. if it's a function, you can change the interface to vectors easily. the main mistake here is to have an angle in some important intermediate data structure, so you think you need an angle, but actually you don't.

so convert from angle to vector as fast as possible and never convert back, unless you actually have to print it on screen. there might be exceptions, but most of the time all the trigonometric functions you'll ever need are for building matrices from euler angles and using sine for aesthetic reasons.

the dot product is your best friend <3

almost every time you see trigonometric function in your code, you should replace it with vector notation. it will become simpler and faster.

only exceptions are when you need angles as input or output. i am talking of input and output of the whole program, not of a function. if it's a function, you can change the interface to vectors easily. the main mistake here is to have an angle in some important intermediate data structure, so you think you need an angle, but actually you don't.

so convert from angle to vector as fast as possible and never convert back, unless you actually have to print it on screen. there might be exceptions, but most of the time all the trigonometric functions you'll ever need are for building matrices from euler angles and using sine for aesthetic reasons.

the dot product is your best friend <3

Uhm... I think there are no more coder gods around to try to convince me. Haha :D

I guess this is going to be a long night then. Thanks a lot guys :)

I guess this is going to be a long night then. Thanks a lot guys :)

My oldie camera code:

http://www.javiercampos.info/files/code/camera.cs

Can't bother reading the thread so... :)

http://www.javiercampos.info/files/code/camera.cs

Can't bother reading the thread so... :)

**Quote:**

Do you know if matrices are actually faster than angles? They seem like more operations per vertex to me.

er. since the first thing any graphics api does is convert from angles to matrices: nope. in fact, you're paying extra for the trig. and you're doing it twice - once to convert from your direction vector to angles, and then again to convert from the angles back to.. your direction vector (plus two orthogonal vectors), which is what ends up in the matrix.