A friend gave me some code that creates a matrix that rotates from one vector to another vector. Very useful for pointing things at one another.
An issue that's come up is, often the matrix will do odd flips in its rotating. I.E. I'll end up with a result that's rotated correctly-- but is upside down in Z, or something like that.
Is there a way to add an up-vector to this code, to force the matrix to avoid rotating around the axis of the up-direction if possible?
Here's the code:
Matrix& Matrix::VectorToVector(Vector theV1, Vector theV2)
{
theV1.Normalize();
theV2.Normalize();
float aDot=theV1.Dot(theV2);
if (gMath.Abs(aDot)>=1.0f-gMath.mMachineEpsilon)
{
if (aDot<0)
{
Vector aPerp=theV1.Perp(); // We don't care which perp, we just need a perp
RotateAroundAxis3D(aPerp,180);
}
}
else
{
Vector aAxis;
float aAngle=0;
aAxis=gMath.Cross(theV1,theV2);
aAngle=gMath.Deg((float)acos(gMath.Dot(theV1,theV2)));
RotateAroundAxis3D(aAxis,aAngle);
}
return *this;
}
Edit: Added the code for the RotateAroundAxis3D function...
Matrix& Matrix::RotateAroundAxis3D(Vector theVector, float theAngle)
{
//
// Multiply the angle by -1 to put it into Raptis Space.
//
theAngle=180-theAngle;
theVector.Normalize();
Matrix aMat;
float aSin=gMath.Sin(theAngle);
float aCos=gMath.Cos(theAngle);
aMat.m00=(1.0f - aCos) * theVector.mX * theVector.mX + aCos;
aMat.m10=(1.0f - aCos) * theVector.mX * theVector.mY - aSin * theVector.mZ;
aMat.m20=(1.0f - aCos) * theVector.mX * theVector.mZ + aSin * theVector.mY;
aMat.m01=(1.0f - aCos) * theVector.mY * theVector.mX + aSin * theVector.mZ;
aMat.m11=(1.0f - aCos) * theVector.mY * theVector.mY + aCos;
aMat.m21=(1.0f - aCos) * theVector.mY * theVector.mZ - aSin * theVector.mX;
aMat.m02=(1.0f - aCos) * theVector.mZ * theVector.mX - aSin * theVector.mY;
aMat.m12=(1.0f - aCos) * theVector.mZ * theVector.mY + aSin * theVector.mX;
aMat.m22=(1.0f - aCos) * theVector.mZ * theVector.mZ + aCos;
return Multiply(&aMat);
}