# Maths - lookAt function - discussion

 lookAt function By: Yosi Hakel (t0xin) - 2008-02-28 19:29 Hi,  I would really appreciate it if you could help me out regarding the lookAt() function here  https://www.euclideanspace.com/maths/algebra/vectors/lookat/index.htm    My situation is very simple  My camera is located at point (0,0,0)  I want to point it towards point (a,b,c) (i.e. orient the camera such that it looks at it)    My only means of pointing/orienting the camera are EULER ANGLES (this is dictated to me by third party libraries which I cannot change)    so my approach is very simple    1) Build a lookAt matrix using the code from said link:  lookAt(double a, double b, double c, matrix& m)  {  vector3 up(0, 1, 0);  vector3 z(a, b, c);   z.norm();   vector3 x( up * z ); // x = up cross z   x.norm();   vector3 y( z * x ); // y = z cross x   m.set_components(x,y,z );   }    2) Convert the lookAt matrix to Euler angles using the code from  https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm :  rotate(matrix m)   {  if (m.m10 > 0.998) { // singularity at north pole  heading = Math.atan2(m.m02,m.m22);  attitude = Math.PI/2;  bank = 0;  return;  }  if (m.m10 < -0.998) { // singularity at south pole  heading = Math.atan2(m.m02,m.m22);  attitude = -Math.PI/2;  bank = 0;  return;  }  heading = Math.atan2(-m.m20,m.m00);  bank = Math.atan2(-m.m12,m.m11);  attitude = Math.asin(m.m10);  }    But the Euler angles I get don't make sense to me  For example, using this code for the vector (0,0,1) (i.e. standing at (0,0,0) trying to look at (0, 0, 1)) produces:   heading = attitude = bank = 0     Whereas I'd expect :  heading = +/-180 degs  attitude = 0   bank = don't care  since we're basically looking in the direction of the Z axis    Another example, trying to look at the vector (1,1,1) (again standing at (0,0,0)) produces  heading = attitude = 0  bank= ~35 degs    Again I don't understand it, I would expect something like  heading = 135 degs  attitude= -45 degs  bank= don't care  Since we're looking at a vector symmetrical to all axes (thus 45 and 90+45 degs)    I'm probably missing something and/or doing something wrong, so again, I would appreciate your help  Thanks a lot in advance,  Ohad    P.S. I am aware that there's a problem when the up vector (0, 1, 0) is parallel to the vector I want to look at, but I'll cross that bridge when I get to it (or at least try to...)

 RE: lookAt function By: nhughes (nhughes) - 2008-02-28 23:00 what software package are you using that only allows you to point your camera with Euler angles?  Noel Hughes

 RE: lookAt function By: nhughes (nhughes) - 2008-02-28 23:15 Are you using the standard aerospace definitions of heading, attitude and bank angles? This convention defines the heading, or yaw, angle as the first rotation, about the +Z or vertical down axis, the attitude, or pitch, angle as the second rotation about the +Y or the "out the right wing" axis and roll as the third rotation about the +X or the "out the nose" axis. If so, looking at (0 0 1) will give you an attitude angle of -90, the roll and yaw angles will affect the orientation of the camera, but won't affect its line of sight. This assumes that the camera line of sight is defined as the camera X axis. If the camera line of sight is the Y axis, looking at (0 0 1) would be accomplished by a roll angle of 90 degrees. If the camera axis is the Z axis, no rotation is necessary, it is already looking at (0 0 1).    I'd be glad to provide more insight into the problem if you can give me more details.  Noel Hughes

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-02-29 01:26 The software package I use is called Tiltan TRLib/Tview:  http://www.tiltan-se.co.il/page.asp?cat=183&lang=2&type=2  I get support from their chief programmer, so if there was a way to avoid Euler angles I'd know about it. But even if there were such way, I'd still need the Euler angles for the DIS (Distributed Interactive Simulation) broadcast (it's in the protocol, can't be changed). And the use of both the package and the standard is 100% set in stone.    Regarding the standards, my apologies - I probably should have mentioned I'm using the same ones Martin does as described here:  https://www.euclideanspace.com/maths/standards/index.htm    They are the same as what you described, only the axis you call 'Z' I call 'Y' and vice versa. Also judging by your angles you seem to be using a left-handed coordinate system whereas Martin's standards assume a right handed one (I mean it in the sense that if the thumb of the right hand indicates the direction of the positive rotation axis then the fingers show the positive direction of rotation). Finally, the camera line of sight is indeed defined as the X axis.    Please take a look at Martin's sample orientations at the bottom of: https://www.euclideanspace.com/maths/geometry/rotations/index.htm   They illustrate said standards very well, just to be sure we're on the same page (since my explanation probably sucked :) )    Back to the issue at hand, in Martin's standards when I write (0,0,1) that means (0,1,0) in your standards, so you can see why I'd expect a heading of -90 (my previous writing of +/-180 was in error, I also meant heading = -45, attitude = 45 degs in the second example - sorry!), actually 90 in your case (since your system is left handed). The vector you think of as (0, 0, 1) is actually (0, 1, 0) for me, and yes I would expect an attitude of 90 (again this is the same as your -90 due to the right handed system) in that case. However, like I mentioned in my original post that specific vector is problematic with my chosen 'up' vector since it's parallel (identical, actually) to it, but I'd prefer to think about that singularity later, and solve the main issue first.     Well, as you can see this is a little confusing, so perhaps you could indulge me and conform to Martin's standards in following messages? This matter is confusing enough for me as it is :)    Thanks again for your help !

 RE: lookAt function By: nhughes (nhughes) - 2008-02-29 14:27 The coordinate system I described is a RIGHT handed system! Thinking of an airplane, X forward through the nose, Y out the right wing - when you cross X into Y - fingers of the right hand start at X and curl into Y - your thumb is DOWN. If this software package uses a coordinate system as you describe and forces you to use only Euler angles, I hope you didn't pay good money for it. I recommend you dump it immediately.    Good Luck.    Noel Hughes

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-02-29 17:06 I meant right/left handedness in the sense of the positive direction of rotation about an axis. Just take a look at martin's https://www.euclideanspace.com/maths/geometry/rotations/euler/index.htm  https://www.euclideanspace.com/maths/standards/index.htm  That's the same system I use    In any case, like I said there is no possibility for me to dump that software and even if there were I'd still need to broadcast the Euler angles in the DIS protocol (which is even less likely to change). These are simply not my shots to call (I'm just a lowly programmer...)    The thing is, using the code Martin put on his site my rotations (be it via quaternions or matrices) work great and so do the conversions back to Euler    My only problem is with the lookAt function, and since it's on the site for many years I assume it does work, and it's just me who doesn't understand its proper usage... that's basically all I'm asking here (for now ;) )    Even if you don't know the answer to that, you still helped me understand the situation better through your questions, so I thank you for that    I do hope, however, that someone here can help me with my original problem (Martin/Minorlogic?)    Thanks again,  Ohad

 RE: lookAt function By: Martin Baker (martinbaker) - 2008-02-29 19:09 Hi Ohad,    If I understand Minorlogics code, what its doing is setting up 3 mutually perpendicular basis vectors to form a rotation matrix, so with the values you put in I would expect it to produce:    z = (0,0,1) for your first example  x = (0,1,0)x(0,0,1) = (1,0,0)  y = (0,0,1)x(1,0,0) = (0,1,0)    so this would give a matrix like:    1 0 0  0 1 0  0 0 1    which indeed is zero rotation  I guess it must be assuming that the camera is already pointing along the z axis in the positive direction?    second case:  z = (1,1,1)/1.732 = (0.577,0.577,0.577)  x = (0,1,0)x(0.577,0.577,0.577) = (0.577,0,-0.577) normalising gives (0.707,0,-0.707)  y = (0,0,1)x(0.707,0,-0.707) = (-1,0.707,0) normalising gives (-0.816,0.612,0)    so this would give a matrix like:    0.707 -0.816 0.577  0 0.612 0.577  -0.707 0 0.577    again I assume this would be the rotation of the camera from pointing along the z axis in the positive direction to point to 1,1,1  I may have made an error I'm very rusty at arithmetic (perhaps I should setup a javascript calculator for this on the webpage?)  Do you get anything like this for the matrix?  I haven't calculated the euler angles, as you say I would expect one of them to be 45deg but I don't think I agree with the 135 degs (because the far corner of a 1,1,1 box is further away).    Martin

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-02-29 19:42 You're right, the angles I mentioned in my first post were wrong, they should be:    First example - (0,0,1)  heading = -90  attitude = 0  bank = anything    Second example - (1, 1, 1)  heading = -45  attitude = 45  bank = anything    Regarding the camera looking along the Z axis, that still would not explain the results I got for (1,1,1), namely:  heading = attitude = 0  bank = ~35 degs    So I'm not really sure what's going on    The interesting thing is that MinorLogic's code is the same as the internal code for D3DXMatrixLookatRH:  http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_summer_03/directx/graphics/reference/d3dx/functions/math/d3dxmatrixlookatrh.asp    So I'm guessing the code is good, I just don't understand how to use it properly in my context

 RE: lookAt function By: Martin Baker (martinbaker) - 2008-03-01 07:35 I'm not sure I agree with the angles:  heading = -45  attitude = 45    I think the angles should be more like:  45 and 35    Imaging you are in a cuboid room, you on the floor of one corner looking along along the base of one wall. You turn through 45deg and you are now looking at the base of the diagonal corner. You now want to look up to the top of the diagonal side. This forms a triangle where the adjacent side is sqrt(2) and the opposite side is 1. So the angle is arctan(0.7071)=35deg.    So I think the 35deg is right, I suspect there must be a bug in your program for the heading and attitude. Are you getting the same matrix as I worked out?    Martin

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-03-01 12:53 You're right, one would think I'd have the sense of not trusting my so called intuition in these matters. So the 35 degrees does make sense, I'll be in the office tomorrow and I will check my program and matrix and report back    Thanks for your time,  Ohad

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-03-02 20:31 Hi Martin, you were right on both accounts !    1) I had a bug in my code  2) Once I fixed it, I indeed received values that would have been good if my camera were placed on the Z axis    The interesting is that by switching the roles of the z and x axes in the code (simply replace any appearance of 'z' with 'x' and vice versa) the same code produces the right values for a camera lying on the X axis. Since your site assumes orientation zero is the X axis (all your examples show it like that) I kindly suggest you change the code that way if you get the time    So a big thank you - but perhaps you could help me further ?    The thing is, that code assumes the camera is currently with orientation zero (i.e. on the X axis).. but most times my camera would be in all sorts of orientations, and I want to know what's the orientation delta from the current orientation to the desired one. What I do now is multiply(from the left) said lookAt matrix by the inverse of the current rotation matrix. That way, when the current orientation matrix is multiplied by it, the desired final orientation is produced (because the current orientation is canceled out) and therefore it must represent the change.. I think ?? It seems to work, but even so, it doesn't strike me as exceptionally efficient so I was wondering if you had any thoughts on the matter.    Another problem is that the code will always produce bank 0, but obviously I would want different banks in different situations. What I do now is, unoriginally, multiply the altered lookAt matrix (from the previous paragraph, the one that cancels out the current orientation), from the right this time, by the rotation matrix of my desired bank. The soundness of this step seems more likely, but at the very least it still seems inefficient.    So just to make things clear, this is my final lookAt matrix:  finalLookAt = inverse(currentOrientationMatrix) * lookAt * desiredBankMatrix;  since multiplying the current orientation matrix by it produces the desired final orientation (including bank), I assume it must represent the "change" in orientation, and so I can interpolate/restrict that change according to angular velocities / gimbal limits    I would gladly hear any insights you have into the matter    Ohad

 RE: lookAt function By: Martin Baker (martinbaker) - 2008-03-03 08:38 Hi Ohad,    I have changed the web page, at the moment I've only put a comment about assuming the initial orientation of the camera is along the z direction, I'm tempted to have 3 versions for initial orientations of x,y and z (representing side,front and top cameras). As you suggest it would be good to also have a version which allows any initial orientation and this can be worked out by:  inputs: current target and required target.  calculate lookat matrix for both these vectors.  multiply required target lookat by transpose of current target lookat.    I don't know if this could be simplified by having the 'up' vector the same in both cases, my instinct tells me that it should be possible to get some simplification! (danger signal) I'll have to think about it.    As I understand it, it is the 'up' vector which determines the third angle, i.e. the angle around the axis that the camera is pointing along. I have problems getting a precise definition of this 'up' vector. I think it would be something like: the up direction when looking through the viewfinder of the camera.    Martin

 RE: lookAt function By: Yosi Hakel (t0xin) - 2008-03-03 20:34 LOL, my example made it to the site :)    RE the assumption of the initial orientation of the camera, I don't know if 3 versions are needed (It sure wouldn't hurt), but nevertheless I'd clarify the current explanation a bit more, maybe something along the lines of "if you want the initial direction to be along the x or y axis then swap their order when setting the components: m.set_components(z,y,x) or m.set_components(x,z,y) accordingly" just to be sure a layman would understand exactly what he needs to do (Just my personal opinion of course, And I might be dumber than the average user of your site :) )    I'll be in the office Wednesday and check MinorLogic's code for the rotation matrix between 2 vectors (hopefully the quaternion result too, the one for the lookAt diverged pretty bad for me), as well as your suggestion regarding the up vector    Again your help is greatly appreciated,  Ohad