How To: Rotate a vector, not using matrix

Started by
5 comments, last by x452Alba 17 years, 1 month ago
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.
Advertisement
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.
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.
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.
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.

Quote:Original post by Zongo
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.

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]
Thanks mate. Worked like a gem.

This topic is closed to new replies.

Advertisement