Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have a camera position (Vec3) and camera horizontal/vertical angle. Now I want to translate my camera position toward the current camera orientation - what is the best way to do that? I am sure it's simple but the logic escapes me.

(I am using GLM math lib btw)

share|improve this question
    
"I have a camera position (Vec3) and camera horizontal/vertical angle." Stop treating the camera as "angles". Treat it as an orientation, which points in a direction. –  Nicol Bolas Mar 16 '13 at 1:09
    
@NicolBolas. In practice it doesn't really matter whether you store the view direction as angles or as vector. Either way there must be a point in your implementation where you convert between them. Be it in the function where you apply rotating or in the matrix calculation. Storing the view direction as two angles works well, see my answer. –  danijar Mar 16 '13 at 11:57
    
@sharethis: I never said to store it as a vector; I said as an orientation. An orientation is more than just a direction. –  Nicol Bolas Mar 16 '13 at 12:25

2 Answers 2

The best way to do that is to generate a vector in the direction your camera is pointing. The simplest way to do it would be to rotate it around the corresponding axes:

Vec3 GetCameraDir(float horiz, float vert) {

    // Start out pointing to the right
    Vec3 dir = Vec3 (1, 0, 0);

    // Rotate dir around the Y axis by your horizontal angle
    dir = RotateY(dir, horiz);

    // Rotate dir around the X axis by your vertical angle
    dir = RotateX(dir, vert);

    return dir;
}

Once you have this vector, you can translate your camera by some amount along this direction:

// Translate the camera's position by your time-step times the speed in the
// direction that your camera is pointing
Vec3 newCamPos = camPos + dT * speed * GetCameraDir(horiz, vert);

That being said, you may want to take a look at this question:

Camera rotation - First Person Camera using GLM

share|improve this answer
    
is RotateX/Y a GLM function? –  KaiserJohaan Mar 15 '13 at 23:40
    
@KaiserJohaan: No, but neither is any of his other code. –  Nicol Bolas Mar 16 '13 at 1:08

Given your description, your camera representation might look like this. I also included the headers of your maths library GLM needed for the following implementation.

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/constants.hpp>
using namespace glm;

struct Camera
{
    vec3 Position;
    vec2 Angles;
    mat4 View, Projection;
};

Camera cam;

To more your camera, you can first calculate the vector for the directions forward and sidewards (in this implementation to the right side). Then update the position based on that vector, the speed of movement, and the elapsed time Delta. Relying on the time is important to make the movement independent from the FPS of your game. Otherwise the camera rotation would be faster on faster machines and vise versa.

Calculating the forward vector is just basic trigonometry. If you have no basic understanding of sine and cosine you can look it up on Wikipedia or somewhere else. After computing the forward vector, we can derive the sidewards vector like shown in the code.

void Move(vec3 Amount, float Delta, float Speed = 10.f)
{
    vec3 forward = vec3(sinf(cam.Angles.x), 0, cosf(cam.Angles.x));
    vec3 right = vec3(-forward.z, 0, forward.x);

    cam.Position   += forward * Amount.x * Speed * Delta;
    cam.Position.y +=           Amount.y * Speed * Delta;
    cam.Position   += right   * Amount.z * Speed * Delta;
}

As you can see we only depend on the view direction for the X and Z coordinate. Otherwise the player could fly if the player walks facing the sky.

Because you haven't especially asked about rotation, I guess you already implemented that. But as a reference this might help other users. The negation because of the different direction of the world coordinates and the mouse coordinates.

void Rotate(ivec2 Amount, float Delta, float Speed = .08f)
{
    cam.Angles += vec2(-Amount.x, -Amount.y) * Speed * Delta;
}

The last step is to create the view matrix. Since you use GLM you can use its lookAt function to do so. Before, I wrap the horizontal angle if it exceeds 360 degrees and I limit the maximum vertical angle a bit. So the player wouldn't loose orientation if he looks straight to the top or to the bottom and rotate the camera then.

void Calculate()
{
    const float pi = glm::pi<float>();
    if      (cam.Angles.x < -pi) cam.Angles.x += pi*2;
    else if (cam.Angles.x >  pi) cam.Angles.x -= pi*2;

    const float margin = 0.2f;
    if      (cam.Angles.y < -pi/2+margin) cam.Angles.y = -pi/2+margin;
    else if (cam.Angles.y >  pi/2-margin) cam.Angles.y =  pi/2-margin;

    vec3 lookat(
        sinf(cam.Angles.x) * cosf(cam.Angles.y),
                             sinf(cam.Angles.y),
        cosf(cam.Angles.x) * cosf(cam.Angles.y)
    );

    cam.View = lookAt(cam.Position, cam.Position + lookat, vec3(0, 1, 0));
}

If you still have questions about that, feel free to ask.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.