Advertisement

quaternion from two directions, optimization

Started by February 26, 2003 09:22 AM
1 comment, last by minorlogic 21 years, 11 months ago
I try to write the quaternion from two directions, (directions is unit vectors) and found the solution that use: We can find CosAngle as DotProduct of dir vectors SinHalfAngle = sqrt(0.5 * (1.0 - CosAngle) ); CosHalfAngle = sqrt(0.5 * (1.0 + CosAngle) ); But it takes 2 sqrts. We easy know the SinAngleSqared ( from CrossProduct ) , and CosAngle, Can we do it faster ? void QuaternionFromTwoDirs( quaternion& quat, vector3& UnitFrom, vector3& UnitTo) { float CosA = Dot(UnitFrom,UnitTo); vector3 Cross( Cross(UnitFrom,UnitTo) ); // rotation Axe // here we can find Cross.len_sqared() fast Cross.norm(); // half-angle formulae (sin^2 t = ( 1 - cos (2t) ) /2) Cross *= (float)sqrt(0.5f * (1.0f - CosA)); quat.x = Cross.x; quat.y = Cross.y; quat.z = Cross.z; // cos^2 t = ( 1 + cos (2t) ) / 2 quat.w = (float)sqrt(0.5f * (1.0f + CosA)); }
Second version:

inline void QuaternionFromTwoDirs2( quaternion& quat,
const vector3& UnitFrom,
const vector3& UnitTo){
float CosA = UnitFrom%UnitTo;
if( CosA < - 0.99999f ){ // angle close to PI

vector3 Cross( 0, UnitFrom.x, -UnitFrom.y );
if( (UnitFrom.z*UnitFrom.z) > (UnitFrom.y*UnitFrom.y) ) // if (0, 1, 0) Cross > (1, 0, 0) Cross
Cross.set( -UnitFrom.z, 0, UnitFrom.x );
Cross.norm();
quat.set( Cross.x, Cross.y, Cross.z, 0.0f );
}else{
vector3 Bisect( UnitFrom + UnitTo );
Bisect.norm();
float HalfCosA = UnitFrom%Bisect;
vector3 BCross( UnitFrom*Bisect );
quat.set( BCross.x, BCross.y, BCross.z, HalfCosA );
}
}
Advertisement
3d version:

inline void QuaternionFromTwoDirs2( quaternion& quat,
const vector3& UnitFrom,
const vector3& UnitTo){
float CosA = Dot(UnitFrom, UnitTo );
if( CosA < - 0.99999f ){ // angle close to PI

vector3 Cross( 0, UnitFrom.x, -UnitFrom.y );
if( (UnitFrom.z*UnitFrom.z) > (UnitFrom.y*UnitFrom.y) ) // if (0, 1, 0) Cross > (1, 0, 0) Cross
Cross.set( -UnitFrom.z, 0, UnitFrom.x );
Cross.norm();
quat.set( Cross.x, Cross.y, Cross.z, 0.0f );
}else{
vector3 Bisect( UnitFrom + UnitTo );
Bisect.norm();
float HalfCosA = Dot(UnitFrom%Bisect);
vector3 BCross( Cross(UnitFrom, Bisect) );
quat.set( BCross.x, BCross.y, BCross.z, HalfCosA );
}
}

//---------------------
Trying to write some thing like lookat for quternion , using up vector too , but still can''t do faster the matrix->lookat -> quaternion

This topic is closed to new replies.

Advertisement