• Advertisement
Sign in to follow this  

Rotating a vector

This topic is 4178 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Probably this is a simple question for you, but I'm a disaster with math. I have a vector (a normal). I want to rotate it 90 degrees up,down,left or right. Uhmm... that's it. How to do that? The Y+ axis is upwards in my case by the way. [edit] Maybe I should give some extra details. The code is used for rendering a hemicube. I know a camera and a direction(the normal). I put the camera on that point, and first I render "forward". forward==normal. But I also need to take a snapshot from the left/right/up and down from that vector. Greetings, Rick

Share this post


Link to post
Share on other sites
Advertisement
The way is use a rotation matrix. The rotation matrix is composed of the direction vectors for the x,y,z axes. If you are using DirectX, OpenGL or another engine you can use the functions of the API/engine...functions like D3DXMatrixYawPitchRoll() of d3dx can do this work.

Build the rotation matrix and then its just multiply it by the vector:
Rotation Matrix:
|Rxx Ryx Rzx|
|Rxy Ryy Rzy|
|Rxz Ryz Rzz|

The first colum is the x,y,z direction of the X axis, the 2nd is the y and the 3rd is the Z.

|Rxx Ryx Rzx| |vx|
|Rxy Ryy Rzy|* |vy|
|Rxz Ryz Rzz| |vz|

Multiply line by collum.

you'll get the rotated vector:

[Rxx*vx + Ryx*vy + Rzx*vz, Rxy*vx + Ryy*vy + Rzy*vz, Rxz*vx + Ryz*vy + Rzz*vz]

This is the way to go...using this method you can rotate your vector in any angle in any axis. Its just build the rotation matrix and the multiply it by the vector.

Hope this helps and also hope I didnt say anything wrong ;)

Share this post


Link to post
Share on other sites
I can use OpenGL multMatrix, but I like to calculate the rotated vector without. So, if I understand it right, my code should look like this:

result.x = Rxx*normal.x + Ryx*normal.y + Rzx*normal.z;
result.y = Rxy*normal.x + Ryy*normal.y + Rzy*normal.z;
result.z = Rxz*normal.x + Ryz*normal.y + Rzz*normal.z;

Where result is the final direction for the camera.

However, I don't know what to fill for those Rxx,Rxy etc. values. Sorry, I'm not good in this stuff!

For example, I want to rotate to the left. Rxx,Rxy and Rxz represent the X-axis. Does that mean:
Rxx = -1
Rxy = 0
Rxz = 0
Assuming that normally Y+ is up, Z+ is forwards, and X+ is to the right? Ifso, what to fill for the other 2 axises?

Thanks for helping!
Rick

Share this post


Link to post
Share on other sites
These matrices will rotate the vector clockwise, just multiply it to the correct matrix.

2d:

|cos(theta) sin(theta) |
|-sin(theta) cos(theta)|





3d:

(around the x axis)
|1 0 0 |
|0 cos(theta) sin(theta)|
|0 -sin(theta) cos(theta)|

(around the y axis)
|cos(theta) 0 -sin(theta)|
|0 1 0|
|sin(theta) 0 cos(theta)|

(around the z axis)
|cos(theta) sin(theta) 0|
|-sin(theta) cos(theta) 0|
| 0 0 1|


Share this post


Link to post
Share on other sites
I think I'm still doing it wrong. I got this function:

function rotateVector( const dir : vector3f; const facing : integer ) : vector3f;
begin
case facing of
C_FORWARD : result := dir;
C_RIGHT : begin
result[0] := 1*dir[0] + 0 *dir[1] + 0 *dir[2];
result[1] := 0*dir[0] + cos(90) *dir[1] + sin(90)*dir[2];
result[2] := 0*dir[0] + -sin(90)*dir[1] + cos(90)*dir[2];
end;
C_LEFT : begin
result[0] := 1*dir[0] + 0 *dir[1] + 0 *dir[2];
result[1] := 0*dir[0] + cos(-90) *dir[1] + sin(-90)*dir[2];
result[2] := 0*dir[0] + -sin(-90)*dir[1] + cos(-90)*dir[2];
end;
C_DOWN : begin
result[0] := cos(90))*dir[0] + 0*dir[1] + -sin(90)*dir[2];
result[1] := 0 *dir[0] + 1*dir[1] + 0 *dir[2];
result[2] := sin(90) *dir[0] + 0*dir[1] + cos(90) *dir[2];
end;
C_UP : begin
result[0] := cos(-90)*dir[0] + 0*dir[1] + -sin(-90)*dir[2];
result[1] := 0 *dir[0] + 1*dir[1] + 0 *dir[2];
result[2] := sin(-90)*dir[0] + 0*dir[1] + cos(-90) *dir[2];
end;
end;
end; // rotateVector

Notice that cos and sin use radians, but I removed the conversion so its easier to read.

Probably I'm using it wrong, or doing the multiplication wrong. For examply, if i want to rotate the vector {1,0,0} 90 degrees to the "left" (90 degrees counter clockwise around X axis), I get the same result as facing forward or to the right.

Left/right/up/down are a little bit strange of course. What is "left"? I mean the left side of the hemicube I try to render.

Greetings,
Rick

Share this post


Link to post
Share on other sites
Note that cos(90), sin(90), cos(-90) and sin(-90) are constants so you can simply write 0, 1, 0, -1 instead.
I find quite difficult to understand what you mean with up, right... There are 6 direction of rotation in 3d but in your code there are only 4 of these.

Share this post


Link to post
Share on other sites
Sorry, its difficult for me to explain.

I'm trying to render a hemiCube. This cube has 5 faces (front,left,right,top,bottom). To be more precise, I'm trying to make a tool that generates radiosity lightmaps. So for each patch in the world, I need to measure the surrounding area. I do that by using hemiCubes.

I render this cube by placing the camera on some point. That's simple. First I render the front face. That's simple as well. For each point, I also got a normal. So I simply use that normal as the camera viewing direction. But now I need to rotate that direction if I want to render left,right,top and bottom.

Thanks for helping everybody!
Rick

Share this post


Link to post
Share on other sites
So if I understand correctly your front face is oriented in the direction of the normal and the other face in the direction of up, left, right vectors... You don't need to do rotations. You need to define an up or a left vector. You can use the cross product to find all the vectors you need.
For example if you define the normal and the up vectors you can find all the other vectors with these formulas:
left = cross(up, normal)
right = cross(normal, up)
down = cross(left, normal)

Share this post


Link to post
Share on other sites
Thanks for the help! But... It's still not correct. When the normal is {0,0,1}, the result seems to be correct. But when I try with another vector, for example {1,0,0} as normal, the right,up and down are exactly the same vectors. These are the results with normal {1,0,0}:

forward = {1,0, 0} // correct
left = {0,0,-1} // correct
right = {0,0,+1} // correct
up = {0,0, 0}
down = {0,0, 0}

So, up and down are not correct in this case. This is my code now:

glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(90, 1, 0.01, 1000);
glMatrixMode(GL_MODELVIEW);

{ dir = the normal, pos = camera position }
case facing of
C_FORWARD : target := dir;
C_LEFT : target := cross( vector(0,1,0) , dir );
C_RIGHT : target := cross( dir, vector(0,1,0) );
C_UP : target := cross( dir, vector(1,0,0) );
C_DOWN : target := cross( vector(1,0,0) , dir );
end;

glLoadIdentity;
camera.Direction := target;
camera.Position := pos;
camera.Apply;

// Cross product function:
function cross( const v1, v2 : vector3f ) : vector3f;
begin
result[X] := v1[Y]*v2[Z] - v1[Z]*v2[Y];
result[Y] := v1[Z]*v2[X] - v1[X]*v2[Z];
result[Z] := v1[X]*v2[Y] - v1[Y]*v2[X];
end;


Maybe I use the wrong up/left vector? But in that case, how to know the proper up/left vector?

Greetings,
Rick

Share this post


Link to post
Share on other sites
Quote:
Original post by spek
I can use OpenGL multMatrix, but I like to calculate the rotated vector without. So, if I understand it right, my code should look like this:



result.x = Rxx*normal.x + Ryx*normal.y + Rzx*normal.z;

result.y = Rxy*normal.x + Ryy*normal.y + Rzy*normal.z;

result.z = Rxz*normal.x + Ryz*normal.y + Rzz*normal.z;


Where result is the final direction for the camera.


It is correct.
The rotation matrix is composed of three vectors where they're all perpendicular. It is like the axis of the world origin x,y,z but you can rotate it...think about rotate the world axis, it is what you do with rotation matrices: you rotate the three vectors in a way that they're always perpendicular. There're several ways of rotate a matrix: create a rotation matrix for the rotation in each axis and then multiply them, rotate a matrix by a deirection vector axis, rotate a matrix by a quaternion...google for and you'll find out how to create these kinds of rotation matrices. I'll explain the most basic one: rotate by x axis and then by y and then by z axis and finally multiply each one.

To rotate by the X axis you must do:

| 1 0 0 |
| 0 cos a -sin a |
| 0 sin a cos a |


By the Y axis

| cos a 0 sin a |
| 0 1 0 |
| -sin a 0 cos a |


By the Z axis

| cos a -sin a 0 |
| sin a cos a 0 |
| 0 0 1 |


I've written it by analizing how it works so I hope theres nothing wrong :P...Did you understand? Play with these matrices for you to know how them work. create some situations to rotate a matrix and do the computations by hand and see the results. I'm sure you'll understand how it works this way...it is funny ;)!...

lets supose you want to rotate a matrix in 30 degrees in the Y axis (yaw) and then by 60 degrees in the X axis(pitch). Remeber that the rotations are local here soh rotate by Y and then by X is different of rotate by X and then by Y. Its just build the matrices the way I've shown above and then multiply then in the correct order: Y * X, and you'll get the rotation matrix. if you multiply it by the vector you'll rotate the vector by the matrix.

I dont know what more should I talk but I hope the things I talked are usefull and I hope you've understand how it works.

Share this post


Link to post
Share on other sites
Thanks again for your detailed help!

I looked into one of my vector math libraries, and saw functions as "vectorRotateAroundX Y or Z". The code was pretty much the same as you said, so I should be using the right stuff now.

It still doesn't work, so I think I'm doing something else wrong. For example, what goes wrong all the time (also with the cross functions like apatriarca said), is rotating with the given normal {1,0,0}. I want to rotate it 90 degrees upwards(or downwards) but that results in {0,0,-1} or {0,0,0}. My code is:

// vectorRotateAroundY with 90 degrees:
Result[x] := cos(90)*normal[0] + sin(90)*normal[2];
Result[y] := normal[1];
Result[z] := -sin(90)*normal[0] + cos(90)*normal[2];
..filling in the values:
Result[x] := 0*1 + 1*0 = 0
Result[y] := 0 = 0
Result[z] := -1*1 + 0*0= -1

// or doing it with the cross function:
// cross( left, normal ) where left={1,0,0} and normal={1,0,0}
Result[x] := v1[y]*v2[z] - v1[z]*v2[y];
Result[y] := v1[z]*v2[x] - v1[x]*v2[z];
Result[z] := v1[x]*v2[y] - v1[y]*v2[x];
..filling in the values:
Result[x] := 0*0 - 0*0 = 0
Result[y] := 0*1 - 1*0 = 0
Result[z] := 1*0 - 0*1 = 0

The function are correct, but they give not the result I want. Obviously, I'm using the wrong parameter for cross, and probably I call the wrong axis to rotate for the first solution. But how to know what to pass/call, judging on the given normal? Like I said before, with normal {0,0,1} both approaches work fine.

Greetings,
Rick

Share this post


Link to post
Share on other sites
Quote:



// vectorRotateAroundY with 90 degrees:

Result[x] := cos(90)*normal[0] + sin(90)*normal[2];

Result[y] := normal[1];

Result[z] := -sin(90)*normal[0] + cos(90)*normal[2];

..filling in the values:

Result[x] := 0*1 + 1*0 = 0

Result[y] := 0 = 0

Result[z] := -1*1 + 0*0= -1


The calculations are all correct and the result is also correct. Think about that 'XYZ axis tripod'(left handed coords system). Using your left hand ,point your thumb in the direction of the Y axis(positive direction: up) and look to where the another fingers are pointing: this is the direction for positive rotations for that axis. The same also apply to the X and Z axis.

I think you think that the vector [1,0,0] should rotate in a 'counter clockwise' direction(looking in the top of the axis tripod) with a positive angle by the y axis. but its is not correct. positive rotations in the y axis goes in a clockwise direction.

Hope I could make you understand ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by spek
Thanks for the help! But... It's still not correct. When the normal is {0,0,1}, the result seems to be correct. But when I try with another vector, for example {1,0,0} as normal, the right,up and down are exactly the same vectors. These are the results with normal {1,0,0}:

forward = {1,0, 0} // correct
left = {0,0,-1} // correct
right = {0,0,+1} // correct
up = {0,0, 0}
down = {0,0, 0}


This is because I say you need the up vector too (or any other vector)...
For example if you have the normal vector (1 0 0) and the up vector (0 1 0) you obtain the other vectors in this way:

left = cross(up, normal) = (0 1 0) x (1 0 0) = (0 0 -1)
right = cross(normal, up) = (1 0 0) x (0 1 0) = (0 0 1)
down = cross(left, normal) = (0 0 -1) x (1 0 0) = (0 -1 0)

If you want to rotate a vector you need an angle and an axis. If you only have an angle you can't do a rotation. The rotations around the x(yz)-axis aren't the rotations you need if I understand correctly what you want to do.

Note that you don't need to do all the cross products I show you. You can use this equalities to optimize all the calculations:
right = -left
down = -up

[Edited by - apatriarca on August 17, 2006 9:49:09 AM]

Share this post


Link to post
Share on other sites
Thanks for the help everyone!

I make a test application and start rotating until I'm dizy, that's the best way to learn it further I think.

Greetings,
Rick

Share this post


Link to post
Share on other sites
Perhaps some pictures would help:

Rotation Transformation

The pictures on this page may not be exactly what you want; the exact rotation and the notation might differ from yours, but they may help you as you determine your own transformation matrix.

Regards,


David

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement