4

I'm trying to figure out how to make the camera in directx move based on the direction it's facing.

Right now the way I move the camera is by passing the camera's current position and rotation to a class called PositionClass. PositionClass takes keyboard input from another class called InputClass and then updates the position and rotation values for the camera, which is then passed back to the camera class.

I've written some code that seems to work great for me, using the cameras pitch and yaw I'm able to get it to go in the direction I've pointed the camera.

However, when the camera is looking straight up (pitch=90) or straight down (pitch=-90), it still changes the cameras X and Z position (depending on the yaw).

The expected behavior is while looking straight up or down it will only move along the Y axis, not along the X or Z axis.

Here's the code that calculates the new camera position

void PositionClass::MoveForward(bool keydown)
{
float radiansY, radiansX;


// Update the forward speed movement based on the frame time
// and whether the user is holding the key down or not.
if(keydown)
{
    m_forwardSpeed += m_frameTime * m_acceleration;

    if(m_forwardSpeed > (m_frameTime * m_maxSpeed))
    {
        m_forwardSpeed = m_frameTime * m_maxSpeed;
    }
}
else
{
    m_forwardSpeed -= m_frameTime * m_friction;

    if(m_forwardSpeed < 0.0f)                                                               
    {
        m_forwardSpeed = 0.0f;
    }
}

// ToRadians() just multiplies degrees by 0.0174532925f
radiansY = ToRadians(m_rotationY); //yaw
radiansX = ToRadians(m_rotationX); //pitch

// Update the position.
m_positionX += sinf(radiansY) * m_forwardSpeed;
m_positionY += -sinf(radiansX) * m_forwardSpeed;
m_positionZ += cosf(radiansY) * m_forwardSpeed;

return;
 }

The significant portion is where the position is updated at the end.

So far I've only been able to deduce that I have horrible math skills.

So, can anyone help me with this dilemma? I've created a fiddle to help test out the math.

Edit: The fiddle uses the same math I used in my MoveForward function, if you set pitch to 90 you can see that the Z axis is still being modified

Andy
  • 875
  • 9
  • 15
  • http://stackoverflow.com/questions/16136466/how-can-i-make-my-camera-move-in-the-direction-im-facing/16137191#16137191 – didierc Apr 24 '13 at 21:54

2 Answers2

6

Thanks to Chaosed0's answer, I was able to figure out the correct formula to calculate movement in a specific direction.

The fixed code below is basically the same as above but now simplified and expanded to make it easier to understand.


First we determine the amount by which the camera will move, in my case this was m_forwardSpeed, but here I will define it as offset.

float offset = 1.0f;

Next you will need to get the camera's X and Y rotation values (in degrees!)

float pitch = camera_rotationX;
float yaw   = camera_rotationY;

Then we convert those values into radians

float pitchRadian = pitch * (PI / 180); // X rotation
float yawRadian   = yaw   * (PI / 180); // Y rotation

Now here is where we determine the new position:

float newPosX = offset *  sinf( yawRadian ) * cosf( pitchRadian );
float newPosY = offset * -sinf( pitchRadian );
float newPosZ = offset *  cosf( yawRadian ) * cosf( pitchRadian );

Notice that we only multiply the X and Z positions by the cosine of pitchRadian, this is to negate the direction and offset of your camera's yaw when it's looking straight up (90) or straight down (-90).

And finally, you need to tell your camera the new position, which I won't cover because it largely depends on how you've implemented your camera. Apparently doing it this way is out of the norm, and possibly inefficient. However, as Chaosed0 said, it's what makes the most sense to me!

Andy
  • 875
  • 9
  • 15
4

To be honest, I'm not entirely sure I understand your code, so let me try to provide a different perspective.

The way I like to think about this problem is in spherical coordinates, basically just polar in 3D. Spherical coordinates are defined by three numbers: a radius and two angles. One of the angles is yaw, and the other should be pitch, assuming you have no roll (I believe there's a way to get phi if you have roll, but I can't think of how currently). In conventional mathematics notation, theta is your yaw and phi is your pitch, with radius being your move speed, as shown below.

Spherical coordinates

Note that phi and theta are defined differently, depending on where you look.

Basically, the problem is to obtain a point m_forwardSpeed away from your camera, with the right pitch and yaw. To do this, we set the "origin" to your camera position, obtain a spherical coordinate, convert it to cartesian, and then add it to your camera position:

float radius = m_forwardSpeed;
float theta = m_rotationY;
float phi = m_rotationX

//These equations are from the wikipedia page, linked above
float xMove = radius*sinf(phi)*cosf(theta);
float yMove = radius*sinf(phi)*sinf(theta);
float zMove = radius*cosf(phi);

m_positionX += xMove;
m_positionY += yMove;
m_positionZ += zMove;

Of course, you can condense a lot of this code, but I expanded it for clarity.

You can think about this like drawing a sphere around your camera. Each of the points on the sphere is a potential position in the next timestep, depending on the camera's rotation.

This is probably not the most efficient way to do it, but in my opinion it's certainly the easiest way to think about it. It actually looks like this is nearly exactly what you're trying to do in your code, but the operations on the angles are just a little bit off.

Community
  • 1
  • 1
Chaosed0
  • 949
  • 1
  • 10
  • 20
  • First off, thank you so much for your time! Secondly, while the wiki article provided lots of helpful information, the formula you provided from it didn't work, but, after lots of playing with it and thinking, I came up with the solution, which I'll post right now for any other people with the same problem. Thanks again Chaosed0! – Andy Apr 24 '13 at 23:24
  • Alright, no problem. Sorry it didn't work - was just doing it off the top of my head, but I'm glad you got it working. Sometimes you just need the right technical jargon to express what you're looking for. – Chaosed0 Apr 24 '13 at 23:35
  • No worries mate and thanks a million, you got me thinking in the right terms to solve it! – Andy Apr 25 '13 at 00:08
  • This didnt quite work for me. But I'm also using different base orientations. The working code for me is: https://pastebin.com/32cavLKq Basically I got rid of the inversions. Not sure if your code was designed for DirectX orientations, but it works great in OpenGL/OpenTK. – Krythic Apr 13 '18 at 06:09