# How To: Rotate a vector, not using matrix

## Recommended Posts

x452Alba    126
Hey Hey, I’m trying to make a simple camera class. How do I rotate the walking forward direction vector in the X Z plane? ie. the y component does not came into play. Here was make humble and lame attempt:
void Camera::WalkRotate(float r)
{
walk_forward[x] = ?  //cosf(r) * walk_forward[z] - sinf(r) * walk_forward[z];
walk_forward[z] = ? //sinf(r) * walk_forward[x] + cosf(r) * walk_forward[x];

walk_forward.Normalize();

walk_right = vec3::Cross(walk_forward, walk_up);
walk_right.Normalize();

return;
}


I just want it to rotate left and right. And I DO NOT want to use a matrix approach - this should be very simple without the need for matrix infrastructure. Alas it is late and I need to sleep. Thanks in advance.

##### Share on other sites
Zipster    2365
walk_forward[x] = cosf(r);
walk_forward[y] = 0.0f;
walk_forward[z] = sinf(r);

walk_right[x] = walk_forward[z];
walk_right[y] = 0.0f;
walk_right[z] = -walk_forward[x];

You can simplify the cross product because the forward vector is always in the XZ plane and the up vector is presumably always (0,1,0). You can also fiddle around the signs in front of cosf/sinf to get the starting orientation (when r = 0) and the direction of rotation.

##### Share on other sites
x452Alba    126
Yes, well, that is a correct answer. But I was looking for a technique that did not require me to store the angle of rotation eg. "in situ". Sorry for not making that clear. How can I do that? TIA.

##### Share on other sites
Zipster    2365
My bad, I should have recognized you were looking for a delta rotation from your original attempt :)

walk_forward[x] = cosf(r) * walk_forward[x] - sinf(r) * walk_forward[z];
walk_forward[y] = 0.0f;
walk_forward[z] = cosf(r) * walk_forward[z] + sinf(r) * walk_forward[x];

walk_forward.Normalize();

walk_right[x] = walk_forward[z];
walk_right[y] = 0.0f;
walk_right[z] = -walk_forward[x];

So your first attempt was almost correct. The math behind this is pretty simple so it's worth explaining. Usually when you do a rotation relative to the X-axis, you assume that the X-axis is (1,0) and the Y-axis is (0,1). The rotation is then cos*(1,0) + sin*(0,1). When you're doing a rotation relative to the current vector, the "X-axis" is (x,z) and the "Y-axis" is the perpendicular vector (-z,x). Then the rotation is cos*(x,z) + sin*(-z,x). You also have to normalize after each rotation since the imprecise floating-point math deteriorates your values over time if you don't.

##### Share on other sites
Zongo    208
Quote:
 walk_forward[x] = cosf(r) * walk_forward[x] - sinf(r) * walk_forward[z];walk_forward[y] = 0.0f;walk_forward[z] = cosf(r) * walk_forward[z] + sinf(r) * walk_forward[x];

You may want to put the result of the rotation in temporary variables. When you set Z on the third line, you use the modified X value you computed on the first line.

##### Share on other sites
Zipster    2365
Quote:
 Original post by ZongoYou may want to put the result of the rotation in temporary variables. When you set Z on the third line, you use the modified X value you computed on the first line.

Absolutely right, I wasn't thinking. I'm used to a vector/matrix library doing all the heavy lifting :) x452Alba, if your vector library supports addition and scalar multiplication, then you'd really want to do it this way:

vec3 xaxis(walk_forward[x], 0.0f, walk_forward[z]);
vec3 yaxis(-walk_forward[z], 0.0f, walk_forward[x]);

walk_forward = cosf(r) * xaxis + sinf(r) * yaxis;

// etc.

For one, you can avoid silly errors like mine, and you don't have to explicitly use temporary variables since all that stuff is hidden in the operators.

[Edited by - Zipster on March 4, 2007 2:17:49 PM]

##### Share on other sites
x452Alba    126
Thanks mate. Worked like a gem.