Ryan Walter
Ryan Walter

Reputation: 271

Cross Product Confusion

I have a question regarding a tutorial that I have been following on the rotation of the camera's view direction in OpenGL.

Whilst I appreciate that prospective respondents are not the authors of the tutorial, I think that this is likely to be a situation which most intermediate-experienced graphics programmers have encountered before so I will seek the advice of members on this topic.

Here is a link to the video to which I refer: https://www.youtube.com/watch?v=7oNLw9Bct1k.

The goal of the tutorial is to create a basic first person camera which the user controls via movement of the mouse.

Here is the function that handles cursor movement (with some variables/members renamed to conform with my personal conventions):

glm::vec2 Movement { OldCursorPosition - NewCursorPosition };

// camera rotates on y-axis when mouse moved left/right (orientation is { 0.0F, 1.0F, 0.0F }):

MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.x) / 2, MVP.view.orientation) 
                   * glm::vec4(MVP.view.direction, 0.0F);

glm::vec3 RotateAround { glm::cross(MVP.view.direction, MVP.view.orientation) };

/* why is camera rotating around cross product of view direction and view orientation 
rather than just rotating around x-axis when mouse is moved up/down..? : */

MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, RotateAround) 
                   * glm::vec4(MVP.view.direction, 0.0F);

OldCursorPosition = NewCursorPosition;

What I struggle to understand is why obtaining the cross product is even required. What I would naturally expect is for the camera to rotate around the y-axis when the mouse is moved from left to right, and for the camera to rotate around the x-axis when the mouse is moved up and down. I just can't get my head around why the cross product is even relevant.

From my understanding, the cross product will return a vector which is perpendicular to two other vectors; in this case that is the cross product of the view direction and view orientation, but why would one want a cross product of these two vectors? Shouldn't the camera just rotate on the x-axis for up/down movement and then on the y-axis for left/right movement...? What am I missing/overlooking here?

Finally, when I run the program, I can't visually detect any rotation on the z-axis despite the fact that the rotation scalar 'RotateAround' has a z-value greater than or less than 0 on every call to the the function subsequent to the first (which suggests that the camera should rotate at least partially on the z-axis).

Perhaps this is just due to my lack of intuition, but if I change the line:

MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, RotateAround)
                   * glm::vec4(MVP.view.direction, 0.0F);

To:

MVP.view.direction = glm::rotate(glm::mat4(1.0F), glm::radians(Movement.y) / 2, glm::vec3(1.0F, 0.0F, 0.0F))
                   * glm::vec4(MVP.view.direction, 0.0F);

So that the rotation only happens on the x-axis rather than partially on the x-axis and partially on the z-axis, and then run the program, I can't really notice much of a difference to the workings of the camera. It feels like maybe there is a difference but I can't articulate what this is.

Upvotes: 1

Views: 779

Answers (2)

clocksw
clocksw

Reputation: 78

You have to do the cross product because after multiple mouse moves the camera is now differently oriented. The original x-axis you wanted to rotate around is NOT the same x-axis you want to rotate around now. You must calculate the vector that is currently pointed straight out the side of the camera and rotate around that. This is considered the "right" vector. This is the cross product of the view and up vectors, where view is the "target" vector (down the camera's z axis, where you are looking) and up is straight up out of the camera up the camera's y-axis. These axes must be updated as the camera moves. Calculating the view and up vectors does not require a cross product as you should be applying rotations to these depending on your movements along the way. The view and up should update by rotations, but if you want to rotate around the x-axis (pitch) you must do a cross product.

Upvotes: 0

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

The problem here is frame of reference.

rather than just rotating around x-axis when mouse is moved up/down..?

What you consider x axis? If that's an axis of global frame of reference or paralleled one, then yes. If that's x axis for frame of reference, partially constricted by camera's position, then, in general answer is no. Depends on order of rotations are done and if MVP gets saved between movements.

Provided that in code her MVP gets modified by rotation, this means it gets changed. If Camera would make 180 degrees around x axis, the direction of x axis would change to opposite one.

If camera would rotate around y axis (I assume ISO directions for ground vehicle), direction would change as well. If camera would rotate around global y by 90 degrees, then around global x by 45 degrees, in result you'll see that view had been tilted by 45 degrees sideways.

Order of rotation around constrained frame of reference for ground-bound vehicles (and possibly, for character of classic 3d shooter) is : around y, around x, around z. For aerial vehicles with airplane-like controls it is around z, around x, around y. In orbital space z and x are inverted, if I remember right (z points down).

Upvotes: 1

Related Questions