// asw - test always advancing the frames void C_ASW_Alien::ASWUpdateClientSideAnimation() { if ( GetSequence() != -1 ) { // latch old values //OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR ); // move frame forward //FrameAdvance( 0.0f ); // 0 means to use the time we last advanced instead of a constant CStudioHdr *hdr = GetModelPtr(); float cyclerate = hdr ? GetSequenceCycleRate( hdr, GetSequence() ) : 1.0f; float addcycle = gpGlobals->frametime * cyclerate * m_flPlaybackRate; float flNewCycle = GetCycle() + addcycle; m_flAnimTime = gpGlobals->curtime; if ( (flNewCycle < 0.0f) || (flNewCycle >= 1.0f) ) { if (flNewCycle >= 1.0f) // asw ReachedEndOfSequence(); // asw if ( IsSequenceLooping( hdr, GetSequence() ) ) { flNewCycle -= (int)(flNewCycle); } else { flNewCycle = (flNewCycle < 0.0f) ? 0.0f : 1.0f; } } SetCycle( flNewCycle ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_NPC_Puppet::AccumulateLayers( CStudioHdr *hdr, Vector pos[], Quaternion q[], float poseparam[], float currentTime, int boneMask ) { if ( m_hAnimationTarget == NULL ) return; C_BaseAnimatingOverlay *pTarget = dynamic_cast<C_BaseAnimatingOverlay *>( m_hAnimationTarget->GetBaseAnimating() ); if ( pTarget == NULL ) return; // resort the layers int layer[MAX_OVERLAYS]; int i; for (i = 0; i < MAX_OVERLAYS; i++) { layer[i] = MAX_OVERLAYS; } for (i = 0; i < pTarget->m_AnimOverlay.Count(); i++) { if (pTarget->m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS) { layer[pTarget->m_AnimOverlay[i].m_nOrder] = i; } } int j; for (j = 0; j < MAX_OVERLAYS; j++) { i = layer[ j ]; if (i < pTarget->m_AnimOverlay.Count()) { float fWeight = pTarget->m_AnimOverlay[i].m_flWeight; if (fWeight > 0) { const char *pSequenceName = pTarget->GetSequenceName( pTarget->m_AnimOverlay[i].m_nSequence ); int nSequence = LookupSequence( pSequenceName ); if ( nSequence >= 0 ) { float fCycle = pTarget->m_AnimOverlay[ i ].m_flCycle; fCycle = ClampCycle( fCycle, IsSequenceLooping( nSequence ) ); if (fWeight > 1) fWeight = 1; AccumulatePose( hdr, NULL, pos, q, nSequence, fCycle, poseparam, boneMask, fWeight, currentTime ); #if _DEBUG if (Q_stristr( hdr->pszName(), r_sequence_debug.GetString()) != NULL) { DevMsgRT( "%6.2f : %30s : %5.3f : %4.2f : %1d\n", currentTime, hdr->pSeqdesc( nSequence ).pszLabel(), fCycle, fWeight, i ); } #endif } } } } }
bool C_BaseViewModel::Interpolate( float currentTime ) { CStudioHdr *pStudioHdr = GetModelPtr(); // Make sure we reset our animation information if we've switch sequences UpdateAnimationParity(); bool bret = BaseClass::Interpolate( currentTime ); // Hack to extrapolate cycle counter for view model float elapsed_time = currentTime - m_flAnimTime; C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); // Predicted viewmodels have fixed up interval if ( GetPredictable() || IsClientCreated() ) { Assert( pPlayer ); float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime; elapsed_time = curtime - m_flAnimTime; // Adjust for interpolated partial frame if ( !engine->IsPaused() ) { elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL ); } } // Prediction errors? if ( elapsed_time < 0 ) { elapsed_time = 0; } float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() ) * GetPlaybackRate(); if ( dt >= 1.0f ) { if ( !IsSequenceLooping( GetSequence() ) ) { dt = 0.999f; } else { dt = fmod( dt, 1.0f ); } } SetCycle( dt ); return bret; }
void C_BaseAnimatingOverlay::AccumulateLayers( CStudioHdr *hdr, Vector pos[], Quaternion q[], float poseparam[], float currentTime, int boneMask ) { BaseClass::AccumulateLayers( hdr, pos, q, poseparam, currentTime, boneMask ); int i; // resort the layers int layer[MAX_OVERLAYS]; for (i = 0; i < MAX_OVERLAYS; i++) { layer[i] = MAX_OVERLAYS; } for (i = 0; i < m_AnimOverlay.Count(); i++) { if (m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS) { /* Assert( layer[m_AnimOverlay[i].m_nOrder] == MAX_OVERLAYS ); layer[m_AnimOverlay[i].m_nOrder] = i; */ // hacky code until initialization of new layers is finished if (layer[m_AnimOverlay[i].m_nOrder] != MAX_OVERLAYS) { m_AnimOverlay[i].m_nOrder = MAX_OVERLAYS; } else { layer[m_AnimOverlay[i].m_nOrder] = i; } } } CheckForLayerChanges( hdr, currentTime ); int nSequences = hdr->GetNumSeq(); // add in the overlay layers int j; for (j = 0; j < MAX_OVERLAYS; j++) { i = layer[ j ]; if (i < m_AnimOverlay.Count()) { if ( m_AnimOverlay[i].m_nSequence >= nSequences ) { continue; } /* DevMsgRT( 1 , "%.3f %.3f %.3f\n", currentTime, fWeight, dadt ); debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -j - 1, 0, "%2d(%s) : %6.2f : %6.2f", m_AnimOverlay[i].m_nSequence, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence )->pszLabel(), m_AnimOverlay[i].m_flCycle, m_AnimOverlay[i].m_flWeight ); */ float fWeight = m_AnimOverlay[i].m_flWeight; if (fWeight > 0) { // check to see if the sequence changed // FIXME: move this to somewhere more reasonable // do a nice spline interpolation of the values // if ( m_AnimOverlay[i].m_nSequence != m_iv_AnimOverlay.GetPrev( i )->nSequence ) float fCycle = m_AnimOverlay[ i ].m_flCycle; fCycle = ClampCycle( fCycle, IsSequenceLooping( m_AnimOverlay[i].m_nSequence ) ); if (fWeight > 1) fWeight = 1; AccumulatePose( hdr, m_pIk, pos, q, m_AnimOverlay[i].m_nSequence, fCycle, poseparam, boneMask, fWeight, currentTime ); #if _DEBUG if (Q_stristr( hdr->pszName(), r_sequence_debug.GetString()) != NULL) { if (1) { DevMsgRT( "%6.2f : %30s : %5.3f : %4.2f : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i ); } else { int iHead, iPrev1, iPrev2; m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 ); // fake up previous cycle values. float t0; C_AnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 ); // reset previous float t1; C_AnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 ); // reset previous previous float t2; C_AnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 ); if ( pHead && pPrev1 && pPrev2 ) { DevMsgRT( "%6.2f : %30s %6.2f (%6.2f:%6.2f:%6.2f) : %6.2f (%6.2f:%6.2f:%6.2f) : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle, fWeight, (float)pPrev2->m_flWeight, (float)pPrev1->m_flWeight, (float)pHead->m_flWeight, i ); } else { DevMsgRT( "%6.2f : %30s %6.2f : %6.2f : %1d\n", currentTime, hdr->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i ); } } } #endif } } } }
void C_BaseAnimatingOverlay::CheckForLayerChanges( CStudioHdr *hdr, float currentTime ) { CDisableRangeChecks disableRangeChecks; // FIXME: damn, there has to be a better way than this. int i; for (i = 0; i < m_iv_AnimOverlay.Count(); i++) { CDisableRangeChecks disableRangeChecks; int iHead, iPrev1, iPrev2; m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 ); // fake up previous cycle values. float t0; C_AnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 ); // reset previous float t1; C_AnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 ); // reset previous previous float t2; C_AnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 ); if ( pHead && pPrev1 && pHead->m_nSequence != pPrev1->m_nSequence ) { #if _DEBUG if (Q_stristr( hdr->pszName(), r_sequence_debug.GetString()) != NULL) { DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t0, hdr->pSeqdesc( pHead->m_nSequence ).pszLabel(), (float)pHead->m_flCycle, (float)pHead->m_flWeight, i ); DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t1, hdr->pSeqdesc( pPrev1->m_nSequence ).pszLabel(), (float)pPrev1->m_flCycle, (float)pPrev1->m_flWeight, i ); if (pPrev2) DevMsgRT( "(%5.2f : %30s : %5.3f : %4.2f : %1d)\n", t2, hdr->pSeqdesc( pPrev2->m_nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev2->m_flWeight, i ); } #endif if (pPrev1) { pPrev1->m_nSequence = pHead->m_nSequence; pPrev1->m_flCycle = pHead->m_flPrevCycle; pPrev1->m_flWeight = pHead->m_flWeight; } if (pPrev2) { float num = 0; if ( fabs( t0 - t1 ) > 0.001f ) num = (t2 - t1) / (t0 - t1); pPrev2->m_nSequence = pHead->m_nSequence; float flTemp; if (IsSequenceLooping( hdr, pHead->m_nSequence )) { flTemp = LoopingLerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle ); } else { flTemp = Lerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle ); } pPrev2->m_flCycle = flTemp; pPrev2->m_flWeight = pHead->m_flWeight; } /* if (stricmp( r_seq_overlay_debug.GetString(), hdr->name ) == 0) { DevMsgRT( "(%30s %6.2f : %6.2f : %6.2f)\n", hdr->pSeqdesc( pHead->nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle ); } */ m_iv_AnimOverlay[i].SetLooping( IsSequenceLooping( hdr, pHead->m_nSequence ) ); m_iv_AnimOverlay[i].Interpolate( currentTime ); // reset event indexes m_flOverlayPrevEventCycle[i] = pHead->m_flPrevCycle - 0.01; } } }
void C_BaseAnimatingOverlay::DoAnimationEvents( CStudioHdr *pStudioHdr ) { MDLCACHE_CRITICAL_SECTION(); if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() ) return; int nSequences = pStudioHdr->GetNumSeq(); BaseClass::DoAnimationEvents( pStudioHdr ); bool watch = false; // Q_strstr( hdr->name, "rifle" ) ? true : false; CheckForLayerChanges( pStudioHdr, gpGlobals->curtime ); // !!! int j; for (j = 0; j < m_AnimOverlay.Count(); j++) { if ( m_AnimOverlay[j].m_nSequence >= nSequences ) { continue; } // Don't bother with 0-weight layers if ( m_AnimOverlay[j].m_flWeight == 0.0f || m_AnimOverlay[j].m_nOrder == MAX_OVERLAYS ) { continue; } mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[j].m_nSequence ); if ( seqdesc.numevents == 0 ) continue; // stalled? if (m_AnimOverlay[j].m_flCycle == m_flOverlayPrevEventCycle[j]) continue; bool bLoopingSequence = IsSequenceLooping( m_AnimOverlay[j].m_nSequence ); bool bLooped = false; //in client code, m_flOverlayPrevEventCycle is set to -1 when we first start an overlay, looping or not if ( bLoopingSequence && m_flOverlayPrevEventCycle[j] > 0.0f && m_AnimOverlay[j].m_flCycle <= m_flOverlayPrevEventCycle[j] ) { if (m_flOverlayPrevEventCycle[j] - m_AnimOverlay[j].m_flCycle > 0.5) { bLooped = true; } else { // things have backed up, which is bad since it'll probably result in a hitch in the animation playback // but, don't play events again for the same time slice return; } } mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); // This makes sure events that occur at the end of a sequence occur are // sent before events that occur at the beginning of a sequence. if (bLooped) { for (int i = 0; i < (int)seqdesc.numevents; i++) { // ignore all non-client-side events if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM ) { if ( !(pevent[i].type & AE_TYPE_CLIENT) ) continue; } else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system continue; if ( pevent[i].cycle <= m_flOverlayPrevEventCycle[j] ) continue; if ( watch ) { Msg( "%i FE %i Looped cycle %f, prev %f ev %f (time %.3f)\n", gpGlobals->tickcount, pevent[i].Event(), pevent[i].cycle, (float)m_flOverlayPrevEventCycle[j], (float)m_AnimOverlay[j].m_flCycle, gpGlobals->curtime ); } FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() ); } // Necessary to get the next loop working m_flOverlayPrevEventCycle[j] = -0.01; } for (int i = 0; i < (int)seqdesc.numevents; i++) { if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM ) { if ( !(pevent[i].type & AE_TYPE_CLIENT) ) continue; } else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system continue; bool bStartedSequence = ( m_flOverlayPrevEventCycle[j] > m_AnimOverlay[j].m_flCycle || m_flOverlayPrevEventCycle[j] == 0 ); if ( ( ( pevent[i].cycle > m_flOverlayPrevEventCycle[j] || bStartedSequence && pevent[i].cycle == 0 ) && pevent[i].cycle <= m_AnimOverlay[j].m_flCycle) ) { if ( watch ) { Msg( "%i (seq: %d) FE %i Normal cycle %f, prev %f ev %f (time %.3f)\n", gpGlobals->tickcount, (int)m_AnimOverlay[j].m_nSequence, (int)pevent[i].Event(), (float)pevent[i].cycle, (float)m_flOverlayPrevEventCycle[j], (float)m_AnimOverlay[j].m_flCycle, gpGlobals->curtime ); } FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() ); } } m_flOverlayPrevEventCycle[j] = m_AnimOverlay[j].m_flCycle; } }
//#define DEBUG_TF2_OVERLAYS void C_BaseAnimatingOverlay::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime ) { BaseClass::AccumulateLayers( boneSetup, pos, q, currentTime ); int i; // resort the layers int layer[MAX_OVERLAYS]; for (i = 0; i < MAX_OVERLAYS; i++) { layer[i] = MAX_OVERLAYS; } for (i = 0; i < m_AnimOverlay.Count(); i++) { if (m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS) { /* Assert( layer[m_AnimOverlay[i].m_nOrder] == MAX_OVERLAYS ); layer[m_AnimOverlay[i].m_nOrder] = i; */ // hacky code until initialization of new layers is finished if ( layer[m_AnimOverlay[i].m_nOrder] != MAX_OVERLAYS ) { m_AnimOverlay[i].SetOrder( MAX_OVERLAYS ); } else { layer[m_AnimOverlay[i].m_nOrder] = i; } } } CheckForLayerChanges( boneSetup.GetStudioHdr(), currentTime ); int nSequences = boneSetup.GetStudioHdr()->GetNumSeq(); // add in the overlay layers int j; for (j = 0; j < MAX_OVERLAYS; j++) { i = layer[ j ]; if ( i >= m_AnimOverlay.Count() ) { #if defined( DEBUG_TF2_OVERLAYS ) engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", " ", 0.f, 0.f, i ); #endif continue; } if ( m_AnimOverlay[i].m_nSequence >= nSequences ) continue; /* DevMsgRT( 1 , "%.3f %.3f %.3f\n", currentTime, fWeight, dadt ); debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -j - 1, 0, "%2d(%s) : %6.2f : %6.2f", m_AnimOverlay[i].m_nSequence, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence )->pszLabel(), m_AnimOverlay[i].m_flCycle, m_AnimOverlay[i].m_flWeight ); */ float fWeight = m_AnimOverlay[i].m_flWeight; if ( fWeight <= 0.0f ) { #if defined( DEBUG_TF2_OVERLAYS ) engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", " ", 0.f, 0.f, i ); #endif continue; } // check to see if the sequence changed // FIXME: move this to somewhere more reasonable // do a nice spline interpolation of the values // if ( m_AnimOverlay[i].m_nSequence != m_iv_AnimOverlay.GetPrev( i )->nSequence ) float fCycle = m_AnimOverlay[ i ].m_flCycle; fCycle = ClampCycle( fCycle, IsSequenceLooping( m_AnimOverlay[i].m_nSequence ) ); if (fWeight > 1.0f) { fWeight = 1.0f; } boneSetup.AccumulatePose( pos, q, m_AnimOverlay[i].m_nSequence, fCycle, fWeight, currentTime, m_pIk ); #if defined( DEBUG_TF2_OVERLAYS ) engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i ); #endif #if 1 // _DEBUG if (r_sequence_debug.GetInt() == entindex()) { if (1) { DevMsgRT( "%8.4f : %30s : %5.3f : %4.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i ); } else { int iHead, iPrev1, iPrev2; m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 ); // fake up previous cycle values. float t0; CAnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 ); // reset previous float t1; CAnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 ); // reset previous previous float t2; CAnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 ); if ( pHead && pPrev1 && pPrev2 ) { DevMsgRT( "%6.2f : %30s %6.2f (%6.2f:%6.2f:%6.2f) : %6.2f (%6.2f:%6.2f:%6.2f) : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle, fWeight, (float)pPrev2->m_flWeight, (float)pPrev1->m_flWeight, (float)pHead->m_flWeight, i ); } else { DevMsgRT( "%6.2f : %30s %6.2f : %6.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i ); } } } #endif } }