bool BOTAI_WillHomingMissileHit(VECTOR * MyPos) { float Cos; float Angle; VECTOR DirVector; VECTOR TmpVec; QUATLERP qlerp; SECONDARYWEAPONBULLET MissCopy = SecBulls[ HomingMissile ]; // direction vector from missile to me DirVector.x = MyPos->x - MissCopy.Pos.x; DirVector.y = MyPos->y - MissCopy.Pos.y; DirVector.z = MyPos->z - MissCopy.Pos.z; NormaliseVector( &DirVector ); // angle difference between the missile's current vector and wanted vector Cos = DotProduct( &DirVector, &MissCopy.DirVector ); // set the parameters to perform a linear interpolation on two quaternions QuatFrom2Vectors( &qlerp.end, &Forward, &DirVector ); qlerp.start = MissCopy.DirQuat; qlerp.crnt = &MissCopy.DirQuat; qlerp.dir = QuatDotProduct( &qlerp.start, &qlerp.end ); // bound angle difference if( Cos < -1.0F ) Cos = -1.0F; else if ( Cos > 1.0F ) Cos = 1.0F; // get angle difference in radians Angle = (float) acos( Cos ); // calculate the amount of angle to turn if( Angle ) qlerp.time = ( ( D2R( MissCopy.TurnSpeed ) * framelag ) / Angle ); else qlerp.time = 1.0F; if( qlerp.time > 1.0F ) qlerp.time = 1.0F; // perform quat interpolation QuatInterpolate( &qlerp ); QuatToMatrix( &MissCopy.DirQuat, &MissCopy.Mat ); ApplyMatrix( &MissCopy.Mat, &Forward, &MissCopy.DirVector ); ApplyMatrix( &MissCopy.Mat, &SlideUp, &MissCopy.UpVector ); // will missile hit? if(RaytoSphere2(MyPos, SHIP_RADIUS, &MissCopy.Pos, &MissCopy.DirVector, &TmpVec, &TmpVec )) { DebugPrintf("homing missile will hit\n"); return true; } else { DebugPrintf("safe from homing missile\n"); return false; } }
/*------------------------------------------------------------------- Procedure : Quaternion Spherical Interpolation (Slerp) Input : double alpha ( interpolation parameter (0 to 1) ) : QUAT * a ( start unit quaternions ) : QUAT * b ( end unit quaternions ) : QUAT * q ( output interpolated quaternion ) : int16 spin ( number of extra spin rotations ) Output : Nothing -------------------------------------------------------------------*/ void Quaternion_Slerp( float alpha, QUAT * a, QUAT * b, QUAT * q, int spin ) { float beta; /* complementary interp parameter */ float theta; /* angle between A and B */ float sin_t, cos_t; /* sine, cosine of theta */ float phi; /* theta plus spins */ int bflip; /* use negation of B? */ cos_t = QuatDotProduct( a, b ); /* if B is on opposite hemisphere from A, use -B instead */ if( cos_t < 0.0F ) { cos_t = -cos_t; bflip = TRUE; } else { bflip = FALSE; } /* if B is (within precision limits) the same as A, * just linear interpolate between A and B. * Can't do spins, since we don't know what direction to spin. */ if( ( 1.0F - cos_t ) < EPS ) { beta = ( 1.0F - alpha ); } else { /* normal case */ theta = ( (float) acos( cos_t ) ); phi = ( theta + ( spin * M_PI ) ); sin_t = ( (float) sin( theta ) ); beta = ( (float) sin( theta - ( alpha * phi ) ) / sin_t ); alpha = ( (float) sin( alpha * phi ) / sin_t ); } if( bflip ) alpha = -alpha; /* interpolate */ q->x = ( ( beta * a->x ) + ( alpha * b->x ) ); q->y = ( ( beta * a->y ) + ( alpha * b->y ) ); q->z = ( ( beta * a->z ) + ( alpha * b->z ) ); q->w = ( ( beta * a->w ) + ( alpha * b->w ) ); }