Rotating a vector

Started by
13 comments, last by DavidB 17 years, 8 months ago
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
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 ;)
.
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
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|
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
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.
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
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)
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
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.
.

This topic is closed to new replies.

Advertisement