Rotating a Vector
-
- Competition winner
- Posts: 1123
- Joined: Sun Jun 10, 2007 11:14 pm
Rotating a Vector
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)
Keep in mind they are 3d vectors, not 2d. Does anyone know the math to do this?
Keep in mind they are 3d vectors, not 2d. Does anyone know the math to do this?
-
- Posts: 363
- Joined: Thu Dec 16, 2010 8:50 pm
- Location: Somewhere in the clouds.. drinking pink lemonade and sunshine..
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
at a cost measure in computer resourcesButler Lampson wrote: all problems in Computer Science can be solved by another level of indirection
-
- Competition winner
- Posts: 1123
- Joined: Sun Jun 10, 2007 11:14 pm
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:
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).
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()
-
- Competition winner
- Posts: 1123
- Joined: Sun Jun 10, 2007 11:14 pm
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:
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);
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:
Note that theta = 0 gives you only the a1 term, which points in the direction of v1 (no rotation), as expected.
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()
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.
(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.
Try this, as found in this thread:
http://irrlicht.sourceforge.net/phpBB2/ ... 191beefadd
simplified
all credits go to rogeborg
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);
}
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.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
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!