示例#1
0
//*****************************************************************************
//
//! Computes the angle between two quaternions
//!
//! \param pfQIn1 is a source quaternion in W,X,Y,Z form
//! \param pfQIn2 is a source quaternion in W,X,Y,Z form
//!
//! This function computes the angle between two quaternions.
//!
//! \return Returns the angle, in radians, between the two quaternions.
//
//*****************************************************************************
float
QuaternionAngle(float pfQIn1[4], float pfQIn2[4])
{
    float pfQInv[4];
    float pfQProd[4];

    //
    // Let Q1 and Q2 be two quaternions having components w,x,y,z.  The angle
    // between the orientations represented by Q1 and Q2 can be calculated
    // with:
    //
    // angle = arccos( (Q2 * Q1').w ) * 2.0;
    //
    // where Q1' is the inverse of Q1
    //

    //
    // Calculate the inverse of Q1
    //
    QuaternionInverse(pfQInv, pfQIn1);

    //
    // Find the product of Q2 x Q1`
    //
    QuaternionMult(pfQProd, pfQIn2, pfQInv);

    //
    // calculate the arccos of the w component of the previous product.
    //
    return(acosf(pfQProd[Q_W]) * 2.0);
}
void  C_NPC_Hydra::StandardBlendingRules( Vector pos[], Quaternion q[], float currentTime, int boneMask )
{
	VPROF( "C_NPC_Hydra::StandardBlendingRules" );

	studiohdr_t *hdr = GetModelPtr();
	if ( !hdr )
	{
		return;
	}

	int i;

	// check for changing model memory requirements
	bool bNewlyInited = false;
	if (m_numHydraBones != hdr->numbones)
	{
		m_numHydraBones = hdr->numbones;

		// build root animation
		float	poseparam[MAXSTUDIOPOSEPARAM];
		for (i = 0; i < hdr->numposeparameters; i++)
		{
			poseparam[i] = 0;
		}
		CalcPose( hdr, NULL, pos, q, 0.0f, 0.0f, poseparam, BONE_USED_BY_ANYTHING );

		// allocate arrays
		if (m_boneLength)
		{
			delete[] m_boneLength;
		}
		m_boneLength = new float [m_numHydraBones];

		if (m_vecPos)
		{
			delete[] m_vecPos;
		}
		m_vecPos = new Vector [m_numHydraBones];
		
		if (m_iv_vecPos)
		{
			delete m_iv_vecPos;
		}
		m_iv_vecPos = new CInterpolatedVar< Vector >[m_numHydraBones];
		for ( i = 0; i < m_numHydraBones; i++ )
		{
			m_iv_vecPos[ i ].Setup( &m_vecPos[ i ], LATCH_SIMULATION_VAR | EXCLUDE_AUTO_LATCH | EXCLUDE_AUTO_INTERPOLATE );
		}

		// calc models bone lengths
		m_maxPossibleLength = 0;
		for (i = 0; i < m_numHydraBones-1; i++)
		{
			m_boneLength[i] = (pos[i+1] - pos[i]).Length();
			m_maxPossibleLength += m_boneLength[i];
		}
		m_boneLength[i] = 0.0f;

		bNewlyInited = true;
	}

	// calc new bone setup if networked.
	if (m_bNewChain)
	{
		CalcBoneChain( m_vecPos, m_vecChain );
		for (i = 0; i < m_numHydraBones; i++)
		{
		//	debugoverlay->AddLineOverlay( m_vecPos[i], m_vecPos[i<m_numHydraBones-1?i+1:m_numHydraBones-1], 0, 255, 0, false, 0.1 );
			m_vecPos[i] = m_vecPos[i] - GetAbsOrigin();
			m_iv_vecPos[i].NoteChanged( this, m_fLatchFlags, currentTime );
		}
		m_bNewChain = false;
	}

	// if just allocated, initialize bones
	if (bNewlyInited)
	{

		for (i = 0; i < m_numHydraBones; i++)
		{
			m_iv_vecPos[i].Reset();
		}
	}

	for (i = 0; i < m_numHydraBones; i++)
	{
		m_iv_vecPos[i].Interpolate( this, currentTime );
		pos[ i ] = m_vecPos[ i ]; 
	}

	// calculate bone angles
	CalcBoneAngles( pos, q );

	// rotate the last bone of the hydra 90 degrees since it's oriented differently than the others
	Quaternion qTmp;
	AngleQuaternion( QAngle( 0, -90, 0) , qTmp );
	QuaternionMult( q[m_numHydraBones - 1], qTmp, q[m_numHydraBones - 1] );
}