Jump to content
The Dark Mod Forums

Converting Spherical Coordinates Into A 3d Vector


sparhawk

Recommended Posts

Maybe some math crack is reading here and can help me with a problem. :)

 

I have a camera that is rotating around a centerpoint. The movement of this camera can be determined by two angles because I'm only moving on the 2D surface of the sphere.

Now in order to convert these two angles into a 3D vector I use the following formula:

 

	x = cos(phi)*cos(theta);
y = cos(phi)*sin(theta);
z = sin(phi);

 

This works fine for most angles. However I experience a strange thing when I move in the forward direction and theta is approach 90 degree and 270 degree (with phi being 0 all the time to make it easier). Whenever these angles are approached the camera starts to flip 180 degree and moves in the other direction and I don't know why. Any idea whats wrong with it? I also tried to switch the camera direction which works, but I have an ugly jump when it happens.

Actually the flipping of the camera already starts when 80 degree is reached. So it starts to shift sideways, at 90 degree it flips, and continues to shift until 100 degree. From this point on everything works fine again and the movement is just straight up/down.

 

I uploaded a video in case someone wants to take a look at what I mean (about 10MB):

 

http://208.49.149.118/TheDarkMod/Files/rotation.zip

Gerhard

Link to comment
Share on other sites

My guess is that the cos() and sin() functions expect values between 0 and 2*pi, and not "real" degree values that are in the range between 0 and 360.

 

I think you have to convert your degrees into radian: rad = deg*pi/180

Link to comment
Share on other sites

A camera actually needs two vectors - the direction vector and the up vector. My guess is that as you approach the vertical position, the camera tries to orient itself so that both the up vector and the direction vector are pointing "upwards", thus causing the rotation. Once you are past the vertical, the camera would in fact be upside down so it flips over so that the up vector is still pointing "upwards".

 

There is a problem that sounds a bit like this in Blender, when you extrude a profile along a path and it approaches a point where it is travelling vertically and then back on itself - the profile will flip 180 degrees as the up direction gets changed.

Link to comment
Share on other sites

Usually one of the angles in spherical coords only goes up to 180 degrees / pi rad, and isn't meant to go beyond that. (I think this would be Phi in your example). If you think about it, you can trace out all points on a sphere with one angle that goes up to 360 and one angle that goes up to 180, you don't need both to go to 360. I don't know if this helps at all. :) [Edit: No it does not help. Sorry.]

Link to comment
Share on other sites

Usually one of the angles in spherical coords only goes up to 180 degrees / pi rad, and isn't meant to go beyond that. (I think this would be Phi in your example). If you think about it, you can trace out all points on a sphere with one angle that goes up to 360 and one angle that goes up to 180, you don't need both to go to 360. I don't know if this helps at all. :) [Edit: No it does not help. Sorry.]

 

It is a related issue actually - as you say the camera does not need to go past the vertical in the "pitch" direction in order to address every point on the sphere, so generally this does not become a problem.

 

I imagine you could get round this problem by ensuring that whatever transformation is applied to the direction vector is also applied to the up vector.

Link to comment
Share on other sites

My guess is that the cos() and sin() functions expect values between 0 and 2*pi, and not "real" degree values that are in the range between 0 and 360.

 

I think you have to convert your degrees into radian: rad = deg*pi/180

 

No, this is not the problem. The function is written to accept deg, so this is defintely not the problem.

Gerhard

Link to comment
Share on other sites

A camera actually needs two vectors - the direction vector and the up vector. My guess is that as you approach the vertical position, the camera tries to orient itself so that both the up vector and the direction vector are pointing "upwards", thus causing the rotation. Once you are past the vertical, the camera would in fact be upside down so it flips over so that the up vector is still pointing "upwards".

 

That is the problem. Because I added a bit of code to flip the up vector to -1 between 90 and 270 degrees. This works to some extent, because the rotation is then going in the correct direction. However there is still the small area where the flip occurs between 80-100 and 260-280. I guess I have to compensate for the rotation, but I don't know how.

Gerhard

Link to comment
Share on other sites

It is a related issue actually - as you say the camera does not need to go past the vertical in the "pitch" direction in order to address every point on the sphere, so generally this does not become a problem.

 

I imagine you could get round this problem by ensuring that whatever transformation is applied to the direction vector is also applied to the up vector.

 

I assumed as much, but how do I do that? The position vector is calculated by the above formula. That is why I use the angles instead of a rotation matrix. I would assume that I have to adjust the up vector also by some sin or cos but how?

Gerhard

Link to comment
Share on other sites

However there is still the small area where the flip occurs between 80-100 and 260-280. I guess I have to compensate for the rotation, but I don't know how.

 

Can you continuously modify the up vector along with the direction vector, so that it is always at right angles? I am not good enough at visualising vector spaces to come up with a formula but I imagine it would look similar to the one you are using to calculate <x, y, z> for the direction vector (but with the odd minus sign and swapped sin/cos).

Link to comment
Share on other sites

Can you continuously modify the up vector along with the direction vector, so that it is always at right angles?

 

Sure I can do this. I just need to know the formula. :) The code for the up vector is in the same place as the calculation as well, so I can do it easily.

 

I am not good enough at visualising vector spaces to come up with a formula but I imagine it would look similar to the one you are using to calculate <x, y, z> for the direction vector (but with the odd minus sign and swapped sin/cos).

 

I'm not that good with this either. :) But at least it gives me a start. :)

Gerhard

Link to comment
Share on other sites

It might be something like:

 

x_up = - x_dir;

y_up = y_dir - 1;

z_up = 1 - cos(pitch);

 

Assuming that y goes into the screen and z goes upwards which i think it does from your example.

 

EDIT: very unsure about x and y, z looks reasonable though I think.

Link to comment
Share on other sites

Don't try it too hard, I am almost certain my x and y formulae are wrong. In fact I am not sure you can use a linear transformation of the direction vector, it might need separate trig functions.

 

Ishtvan seems good with this stuff, maybe he would know how to do this?

Link to comment
Share on other sites

I don't know much about cameras though, so I'm not sure what you guys mean by direction vector and up vector. I assume it's two perpendicular vectors, where the direction defines which way the camera is pointing, and the up vector defines the "roll" of the camera?

 

Since you already have the code to get a new direction vector, and need an up vector to match, I think you could try this:

 

[EDIT - STUPIDITY REMOVED ]

 

To be absolutely certain, I would make a rotation matrix C for your camera rotation, and then apply it to both x and z,

i.e., z' = C z, x' = C x

 

Where you've assumed that x [1 0 0] is your un-rotated direction vector and z [0 0 1] is your un rotated up vector

Link to comment
Share on other sites

Okay, I think this might be it, so you don't have to bother with the rotation matrix:

 

Assume the pitch (theta), yaw (phi), roll convention, with roll = 0

 

The reference below gives the big nasty rotation matrix for general rotations. For the direction vector, we're just rotating x, [1 0 0], which should yield something similar to the formula you have (but different because I don't think your theta and phi are pitch and yaw exactly):

 

x' = [cos(theta) * cos(phi) , -sin(phi) , sin(theta) * cos(phi) ]

 

Now for the "up" vector, multiply the big nasty rotation matrix by [0 0 1], and you get:

 

z' = [ -sin(theta) , 0, cos(theta) ]

 

Note that strict definitions of theta and phi for this formula: Theta is the pitch measured from the xy plane, pitching up toward the z axis is positive, down negative. Phi is the yaw measured clockwise from the x axis.

 

I'm not sure what definition of theta and phi you're using, and where you get them from in the code, but you'll have to adapt them to those conventions if you want this formula to work correctly.

 

We can test this out by rotating a point [1 0 0] (x) up to z, which is a pitch up of 90 deg, or theta = +90 deg, phi = 0. We get x' = [0, 0, 1], which is z (correct). For z', we get [-1, 0, 0], or the negative x direction, which is correct if you draw it out and think about what happens to z when you pitch x up by +90 (z also pitches by +90 which puts it in the -x direction).

 

Reference: http://mathworld.wolfram.com/EulerAngles.html

Link to comment
Share on other sites

I just wanted to mention that there are script functions to convert a set of Euler angles to up/right/forward vectors. Those sound like exactly what you want; since they're already written, perhaps you could look at their code.

 

// Returns a forward vector for the given Euler angles.
scriptEvent	vector	angToForward( vector angles );

// Returns a right vector for the given Euler angles.
scriptEvent	vector	angToRight( vector angles );

// Returns an up vector for the given Euler angles.
scriptEvent	vector	angToUp( vector angles );

Link to comment
Share on other sites

I don't know much about cameras though, so I'm not sure what you guys mean by direction vector and up vector. I assume it's two perpendicular vectors, where the direction defines which way the camera is pointing, and the up vector defines the "roll" of the camera?

 

Basically yes, although the up vector does not have to be perpendicular to the direction vector. In fact for most purposes you would never touch the up vector, it would always be [0 0 1], but it is necessary to change it if you want the camera to pitch past the vertical.

Link to comment
Share on other sites

Now for the "up" vector, multiply the big nasty rotation matrix by [0 0 1], and you get:

 

z' = [ -sin(theta) , 0, cos(theta) ]

 

Note that strict definitions of theta and phi for this formula: Theta is the pitch measured from the xy plane, pitching up toward the z axis is positive, down negative. Phi is the yaw measured clockwise from the x axis.

 

I don't quite see how the y component can be identically 0 - surely the up vector must have all three components since it is perpendicular to the direction vector which can point anywhere?

 

E.g. with a direction vector of [0 1 0], start tilting backwards. The up vector will start to point in the negative y direction.

Link to comment
Share on other sites

Maybe my original idea was not properly phrased. I don't think that the up vector needs to be adjusted at all. The kind of movement that I want to achieve is like a satellite flying around earth. You can steer in two directions forward/backward and left/right and then earth below it would appear to be rotating accordingly. I think with the above formulas this seem not to be the case for arbitrary angles.

Gerhard

Link to comment
Share on other sites

Basically yes, although the up vector does not have to be perpendicular to the direction vector. In fact for most purposes you would never touch the up vector, it would always be [0 0 1], but it is necessary to change it if you want the camera to pitch past the vertical.

 

You're probably right, since I can think of a roll/pitch combination that would rotate the Z axis into the untransformed Y axis. Unfortunately the wolfram site with the formulation of the matrix I was using appears to be down so I can't try and find the mistake at the moment.

 

@Sparhawk: It seems like if you took a camera, didn't roll it and moved it up along a sphere surface, it should flip upside-down when it gets to the top and goes on to the other side. Maybe you could use your existing formula and manually flip the up vector of the camera when the pitch angle is between 90 and 270?

 

Also, it might be helpful to draw out a diagram of what the angles are and scan it or something. I'm still not sure if you're measuring pitch from the XY plane or from the Z axis?

Link to comment
Share on other sites

I created an axis model with the names of the axis. This made it much easier to debug it and now it works. Not as a like it but at least a bit. :)

 

Currently I can now rotate correctly around the axis, but not copmpletely free. If you are looking along the Z axis with the current code, and then try to rotate left/right, it is rotating around the Z axis still instead of the X or Y axis as it should. It means that I have to transform the rotation accordingly so that it is always rotated relative to the screen instead relative to the object as it is now. At least the annoying flipping effect is now gone. :)

Gerhard

Link to comment
Share on other sites

Currently I can now rotate correctly around the axis, but not copmpletely free. If you are looking along the Z axis with the current code, and then try to rotate left/right, it is rotating around the Z axis still instead of the X or Y axis as it should. It means that I have to transform the rotation accordingly so that it is always rotated relative to the screen instead relative to the object as it is now. At least the annoying flipping effect is now gone. :)

OK, I don't quite know what your rotation code looks like, but this could be solved by using the appropriate rotation matrix. (I can't quite visualise what's going on here, since some of the phrasing is confusing and I can't be bothered to find a codec to work with that video.)

 

The equation does have to change if you want to rotate along different fixed axes. In Matlab matrix notation (where semicolons start new lines in a matrix)...

 

Rx(ang1) = [1, 0, 0 ; 0, cos(ang1), -sin(ang1) ; 0, sin(ang1), cos(ang1)]

 

Ry(ang2) = [cos(ang2), 0, sin(ang2) ; 0, 1, 0 ; -sin(ang2), 0, cos(ang2)]

 

Rz(ang3) = [cos(ang3), -sin(ang3), 0 ; sin(ang3), cos(ang3), 0 ; 0, 0, 1]

 

Again, I don't know what your code looks like, so I don't know if this helps. But it sounds like you think you need to rotate around a different axis, and these do that. There is also a formula (I sort of remember) for rotation about a general axis, but I don't think you want that. :P

Link to comment
Share on other sites

Matrix M;
Matrix MR;
Matrix MT;

M.SetIdentity();
MR.SetIdentity();
MT.SetIdentity();

MR.SetRotate(SideAngle,ForwardAngle,0);
MT.SetTranslate(0,0,CamDist);
M=MR*MT;

CamPos = M.T;
camera.SetFOV(60);
camera.SetPosition(CamPos);
camera.SetUp(MR.YAxis.x, MR.YAxis.y, MR.YAxis.z);
camera.SetTransition(0);

 

What I mean is this. The code currently uses the Y as up/down, X is left/right and Z is forward/backward (when moving along the axis). Now when you rotate such that the Y is swapping the position with the Z axis the current code still rotates around the Y axis, but it should be rotating around Z, because Z became the new up/down because of the rotation.

 

I give your matrix a testrun. It's really frustrating that I have such a hard time doing this math things. :(

Gerhard

Link to comment
Share on other sites

  • 2 years later...

What you are experiencing is called "Gimbal lock". Because the engine uses Euler angles to determine the facing, it gets confused when you look straight up or down.

 

As far as I know, the only way to fix it would be to mod the engine to use Quaternions instead.

 

Gimbal Lock

Euler Angles

Quaternions

 

Edit: Unless you're talking about turning along the z axis, in which case, you shouldn't have any problems.

Edited by killhour
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recent Status Updates

    • taffernicus

      i am so euphoric to see new FMs keep coming out and I am keen to try it out in my leisure time, then suddenly my PC is spouting a couple of S.M.A.R.T errors...
      tbf i cannot afford myself to miss my network emulator image file&progress, important ebooks, hyper-v checkpoint & hyper-v export and the precious thief & TDM gamesaves. Don't fall yourself into & lay your hands on crappy SSD
       
      · 1 reply
    • OrbWeaver

      Does anyone actually use the Normalise button in the Surface inspector? Even after looking at the code I'm not quite sure what it's for.
      · 7 replies
    • Ansome

      Turns out my 15th anniversary mission idea has already been done once or twice before! I've been beaten to the punch once again, but I suppose that's to be expected when there's over 170 FMs out there, eh? I'm not complaining though, I love learning new tricks and taking inspiration from past FMs. Best of luck on your own fan missions!
      · 4 replies
    • The Black Arrow

      I wanna play Doom 3, but fhDoom has much better features than dhewm3, yet fhDoom is old, outdated and probably not supported. Damn!
      Makes me think that TDM engine for Doom 3 itself would actually be perfect.
      · 6 replies
    • Petike the Taffer

      Maybe a bit of advice ? In the FM series I'm preparing, the two main characters have the given names Toby and Agnes (it's the protagonist and deuteragonist, respectively), I've been toying with the idea of giving them family names as well, since many of the FM series have named protagonists who have surnames. Toby's from a family who were usually farriers, though he eventually wound up working as a cobbler (this serves as a daylight "front" for his night time thieving). Would it make sense if the man's popularly accepted family name was Farrier ? It's an existing, though less common English surname, and it directly refers to the profession practiced by his relatives. Your suggestions ?
      · 9 replies
×
×
  • Create New...