Rotating a Vector

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Rotating a Vector

Post by Lonesome Ducky »

I have two 3d vectors originating from the same point. What I want to do is rotate the top vector by a certain angle along the axis between the vectors. Let me show a diagram: (Red lines are the original vector, green is the angle I want to rotate, and orange is the final vector)

Image

Keep in mind they are 3d vectors, not 2d. Does anyone know the math to do this?
ChaiRuiPeng
Posts: 363
Joined: Thu Dec 16, 2010 8:50 pm
Location: Somewhere in the clouds.. drinking pink lemonade and sunshine..

Post by ChaiRuiPeng »

assuming you normalize the vectors. maybe you could do something like:

Code: Select all


//! pseudo code

btVector3 first; //first vect
btVector3 middle_vect; //middle vect
btVector3 dotproduct = /* ... */;

newx = first.x+2*middle_vect.x*dotproduct;
newy = first.y+2*middle_vect.y*dotproduct;
newz = first.z+2*middle_vect.z*dotproduct;
ent1ty wrote: success is a matter of concentration and desire
Butler Lampson wrote: all problems in Computer Science can be solved by another level of indirection
at a cost measure in computer resources ;)
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

The dot product of the two vectors would give me the angle between them, so I don't believe your code would give me the correct position. (It also doesn't consider the angle I want to rotate it by).

EDIT: On trying it out, yours only pushes the point down one of the already known vectors.
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Post by Mikhail9 »

If v1 and v2 are not colinear, they define a plane, and I think you are saying you want to rotate v1 in that plane. One way would be to find orthogonal unit vectors in that plane and go from there.

v1.normalize is the first unit vector
(v1 - v1.dot(v2)).normalize is the second unit vector

Now you can rotate v1 through theta radians by using those orthogonal unit vectors:

Code: Select all

v1new = ( v1.normalize * cos(theta) + (v1 - v1.dot(v2)).normalize * sin(theta) ) * v1.length()
You could also define a matrix transformation, but this is equivalent. Note that it will fail if v1 and v2 are colinear (no rotation will occur).
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

Yep, that's exactly what I want to do. Though on trying your code, it's not rotating it at the angle I tell it to. (Yes, I'm using radians)

EDIT again: After much searching, I found this:

Code: Select all

		irr::core::vector3df axis = centerVec.crossProduct(lineVec).normalize();
		irr::core::vector3df res = axis.dotProduct(centerVec)*axis + centerVec.crossProduct(axis)*sin(-offAng) + (centerVec - axis.dotProduct(centerVec)*axis)*cos(-offAng);
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Post by Mikhail9 »

Did you fix my error when you tested it? That second unit vector was a little off. It is supposed to be whatever part of v2 doesn't point along v1.

a1 = v1.normalize is the first unit vector
a2 = (v2 - v2.dot(a1) * a1).normalize is the second unit vector

Now you can rotate v1 through theta radians by using those orthogonal unit vectors:

Code: Select all

v1new = (a1 * cos(theta) + a2 * sin(theta)) * v1.length()
Note that theta = 0 gives you only the a1 term, which points in the direction of v1 (no rotation), as expected.
Xaryl
Posts: 90
Joined: Sat Apr 30, 2011 11:54 pm

Post by Xaryl »

I would try to get the a2 this way:

(Let "x" denote cross product)
Since the normal of the plane the circle is on is (v1 x v2)
a2 would be (v1 x (v1 x v2)).normalize or maybe ((v1 x v2) x v1).normalize

It eludes me at the moment which one is correct, since Irrlicht uses (I think) left hand coordinate system.
spacetime
Posts: 15
Joined: Mon Feb 14, 2011 12:24 am

Post by spacetime »

Try this, as found in this thread:
http://irrlicht.sourceforge.net/phpBB2/ ... 191beefadd
simplified

Code: Select all

void rotateVectorAroundAxis(vector3df & vector, const vector3df & axis, f32 radians)
{
   quaternion MrQuaternion;
   matrix4 MrMatrix;
   (void)MrQuaternion.fromAngleAxis(radians, axis);
   MrQuaternion.getMatrix(MrMatrix);
   MrMatrix.rotateVect(vector); 
}

void rotate()
{
    vector3df vectorToRotate = vector3df(1,1,1); //your vector
    vector3df axis = vector3df(0,1,0); // axis of rotation, in this case Y
    f32 rad = 1.f; // angle in radians
       // prints vector values
        printf("vectorToRotate X: %f \n", vectorToRotate.X);
        printf("vectorToRotate Y: %f \n", vectorToRotate.Y);
        printf("vectorToRotate Z: %f \n", vectorToRotate.Z);
    rotateVectorAroundAxis(vectorToRotate, axis, radians);
        //prints values after rotation
        printf("vectorToRotate X: %f \n", vectorToRotate.X);
        printf("vectorToRotate Y: %f \n", vectorToRotate.Y);
        printf("vectorToRotate Z: %f \n", vectorToRotate.Z);
}
all credits go to rogeborg
Mikhail9
Posts: 54
Joined: Mon Jun 29, 2009 8:41 am

Post by Mikhail9 »

Xaryl wrote:I would try to get the a2 this way:

(Let "x" denote cross product)
Since the normal of the plane the circle is on is (v1 x v2)
a2 would be (v1 x (v1 x v2)).normalize
Yep, look up the vector identity for repeated cross products and you'll see it reduces to the form for a2 that I gave. Fewer multiplies in the end, if you care about that kind of thing.

But the RogerBorg snippet looks like an elegant way to go that uses Irrlicht built-ins.

And yes, I'm replying multiple messages after the Ducky said he found some code. Vector math rocks!
Post Reply