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 only just started learning OpenGL and even things like vector maths etc a couple of days ago, so I am having a bit of trouble figuring out exactly what to do to implement an arcball camera system.

I am using GLM to do things like get the cross product of two vectors etc, and I am using the glm::lookAt(position, target, up) method to set the view matrix.

I have looked around on Google and the search on this site and even StackOverflow but since I am new to this I'm not exactly sure what I'm doing wrong (probably a lot of things) and what I should be searching for.

At the moment I am trying to follow the general steps outlined in this answer: How can I rotate a camera about it's target point?

But I am not sure if I am doing it correctly (well, actually, I know I'm not doing it correctly because it's not working).

I can get the camera's normalized up and right vectors without any problem, and I can get a vector from the camera's target point to the camera position.

I can then easily decide the angle of rotation in radians, but my main points of trouble come after that; creating a new vector to translate the camera with from a rotation matrix and then actually translating camera to get a new camera position.

I'm not sure exactly what information you would need to help me, but here is a general overview.

Currently I have a cube that is drawn around the origin, three glm::vec3 objects which describe camera position, camera target and camera up, and the usual projection, view and model matrices which are multiplied together and given to glUniformMatrix4fv().

Apart from glUniformMatrix4fv() this is all declared before the main loop.

glm::mat4 projection_matrix = glm::perspective(45.f, 4.f / 3.f, 0.1f, 100.f);

glm::vec3 camera_position = glm::vec3(0.f, 1.f, 5.f);
glm::vec3 camera_target = glm::vec3(0.f, 0.f, 0.f);
glm::vec3 camera_up_vector = glm::vec3(0.f, 1.f, 0.f);

glm::mat4 view_matrix = glm::lookAt(
    camera_position,
    camera_target,
    camera_up_vector
);

glm::mat4 model_matrix = glm::mat4(1.f);

glm::mat4 mvp = projection_matrix * view_matrix * model_matrix;

Just before the main loop I also declare two glm::mat4 matrices to rotate with yaw and pitch and two more glm::vec3 objects to store the target to camera and camera right vectors, since that was one of the steps in the answer I linked above.

glm::vec3 target_to_camera_vector;
glm::vec3 camera_right_vector;

glm::mat4 rotate_yaw_matrix = glm::mat4(1.f);
glm::mat4 rotate_pitch_matrix = glm::mat4(1.f);

Now, within the main loop I re-calculate the target_to_camera_vector, camera_right_vector and camera_up_vector before I try to do any more calculations.

target_to_camera_vector = camera_position - camera_target;
camera_right_vector = glm::normalize(glm::cross(target_to_camera_vector, camera_up_vector));
camera_up_vector = glm::normalize(glm::cross(camera_right_vector, target_to_camera_vector));

After this is where I think I am going horribly wrong.

The answer I linked above says:

Create two rotation matrices. The 1st rotation matrix will use the up of the camera as the axis and yaw angle that you decided. The 2nd rotation matrix will use the right of the camera as the axis and pitch angle that you decided.

So I try to rotate the two glm::mat4 matrices I had created earlier, even though I'm not 100% sure this is how you do it in GLM.

rotate_yaw_matrix = glm::rotate(rotate_yaw_matrix, yaw_angle_radians, camera_up_vector);
rotate_pitch_matrix = glm::rotate(rotate_pitch_matrix, pitch_angle_radians, camera_right_vector);

The answer linked above then says:

Now rotate the camFocusVector with the new rotation matrices. This is now your new position of the camera relative to the origin. We of course, want it to be relative to the focus point...

This is where I am really just guessing what to do.

target_to_camera_vector = glm::vec3(rotate_yaw_matrix * glm::vec4(target_to_camera_vector, 0.f));
target_to_camera_vector = glm::vec3(rotate_pitch_matrix * glm::vec4(target_to_camera_vector, 0.f));

After that it says:

Add the focus point position to camFocusVector. This is now your camera's new position. Translate your camera accordingly.

So, once again, since I'm not exactly sure what this means, I guess, of course.

target_to_camera_vector += camera_target;

And having no idea how I should use this result to translate the vector, I make the, most likely wrong, assumption that I am supposed to do this.

camera_position += target_to_camera_vector;

Afterwards I use the glm::lookAt() method and recalculate the model view projection matrix to pass to glUniformMatrix4fv().

view_matrix = glm::lookAt(
    camera_position,
    camera_target,
    camera_up_vector
);

mvp = projection_matrix * view_matrix * model_matrix;

As I said, I only just started learning about OpenGL and 3D/Vector maths a couple of days ago, so a lot of my learning at this stage is experimenting and guessing etc. But I think I mostly went wrong around the point where I had to rotate the matrices and translate the camera position.

So my question is (finally), am I following the right path to implement an arcball camera (it seems like it should be ok), and if so, how can I properly implement the steps to rotate the target_to_camera_vector and then use that to translate the camera_position?

Any help would be appreciated.

share|improve this question
    
c# example Written in c#, but you can easily convert the code to c++ –  user1075940 Apr 5 '13 at 9:15
add comment

1 Answer

up vote 5 down vote accepted

Place your camera target at the center of the arc rotation (That's usually where you want the camera to look anyway). Then simply transform the camera's position around the target with a rotation that uses the appropriate axis.

pseudo code:
//some angle & some other angle = only the amount you want the camera to rotate since last frame.

//pitch
position = (Rotate(some angle, cameraRight) * (position - target)) + target;


//yaw, Y-up system
position = (rotate(some other angle, (0,1,0) * (position - target)) + target;

view = LookAt(position, target, up);
share|improve this answer
    
Now that I can see some nice, simple pseudo code I can't believe I didn't understand this before. It seems so simple now. Thank you for your time! –  Sour Lemon Apr 5 '13 at 13:44
add comment

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.