Hey Weytant! I don’t know if this is the exact code, but it’s derivative of this:
sfquat LookAt(sfvec3f target,sfvec3f current, sfvec3f eye,sfvec3f up) {
// turn vectors into unit vectors
n1 = (current - eye).norm();
n2 = (target - eye).norm();
d = sfvec3f.dot(n1,n2);
// if no noticable rotation is available return zero rotation
// this way we avoid Cross product artifacts
if( d > 0.9998 ) return new sfquat( 0, 0, 1, 0 );
// in this case there are 2 lines on the same axis
if(d < -0.9998){
n1 = n1.Rotx( 0.5f );
// there are an infinite number of normals
// in this case. Anyone of these normals will be
// a valid rotation (180 degrees). so rotate the curr axis by 0.5 radians this way we get one of these normals
}
sfvec3f axis = n1;
axis.cross(n2);
sfquat pointToTarget= new sfquat(1.0 + d,axis.x,axis.y,axis.z);
pointToTarget.norm();
// now twist around the target vector, so that the ‘up’ vector points along the z axis
sfmatrix projectionMatrix=new sfmatrix();
double a = pointToTarget.x;
double b = pointToTarget.y;
double c = pointToTarget.z;
projectionMatrix.m00 = bb+cc;
projectionMatrix.m01 = -ab;
projectionMatrix.m02 = -ac;
projectionMatrix.m10 = -ba;
projectionMatrix.m11 = aa+cc;
projectionMatrix.m12 = -bc;
projectionMatrix.m20 = -ca;
projectionMatrix.m21 = -cb;
projectionMatrix.m22 = aa+bb;
sfvec3f upProjected = projectionMatrix.transform(up);
sfvec3f yaxisProjected = projectionMatrix.transform(new sfvec(0,1,0);
d = sfvec3f.dot(upProjected,yaxisProjected);
// so the axis of twist is n2 and the angle is arcos(d)
//convert this to quat as follows
double s=Math.sqrt(1.0 - dd);
sfquat twist=new sfquat(d,n2s,n2s,n2s);
return sfquat.mul(pointToTarget,twist);
There are a ton of small equations used, that generates the arcos dot product.
Now, this one returns quaternions, there is a simpler LookAt function in mathematics, however it does not apply rotation and assumes a standard starting point. This is almost never applicable in games since the starting point needs to be anywhere.