/* ================ idDict::Copy copy all key value pairs without removing existing key/value pairs not present in the other dict ================ */ void idDict::Copy( const idDict &other ) { int i, n, *found; idKeyValue kv; // check for assignment to self if ( this == &other ) { return; } n = other.args.Num(); if ( args.Num() ) { found = (int *) _alloca16( other.args.Num() * sizeof( int ) ); for ( i = 0; i < n; i++ ) { found[i] = FindKeyIndex( other.args[i].GetKey() ); } } else { found = NULL; } for ( i = 0; i < n; i++ ) { if ( found && found[i] != -1 ) { // first set the new value and then free the old value to allow proper self copying const idPoolStr *oldValue = args[found[i]].value; args[found[i]].value = globalValues.CopyString( other.args[i].value ); globalValues.FreeString( oldValue ); } else { kv.key = globalKeys.CopyString( other.args[i].key ); kv.value = globalValues.CopyString( other.args[i].value ); argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) ); } } }
bool ApplyInterpolator(float aTarget[], int aWidth, int aCount, const float aKeys[], float aTime, int &aHint) { // get stride const int aStride = aWidth + 1; // get the key index int index = FindKeyIndex(aStride, aCount, aKeys, aTime, aHint); if (index < 0) return false; // update hint index aHint = index; // interpolate the value const float * __restrict key = aKeys + index * aStride; const float time0 = key[0]; const float * __restrict data0 = &key[1]; const float time1 = key[aStride]; const float * __restrict data1 = &key[aStride + 1]; const float t = (aTime - time0) / (time1 - time0 + FLT_EPSILON); for (int element = 0; element < aWidth; element++) { aTarget[element] = Lerp(data0[element], data1[element], t); } return true; }
/* ================ idDict::Set ================ */ void idDict::Set( const char *key, const char *value ) { int i; idKeyValue kv; if ( key == NULL || key[0] == '\0' ) { return; } i = FindKeyIndex( key ); if ( i != -1 ) { // first set the new value and then free the old value to allow proper self copying const idPoolStr *oldValue = args[i].value; args[i].value = globalValues.AllocString( value ); globalValues.FreeString( oldValue ); } else { kv.key = globalKeys.AllocString( key ); kv.value = globalValues.AllocString( value ); argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) ); } }
bool ApplyInterpolatorConstant(float aTarget[], int aWidth, int aCount, const float aKeys[], float aTime, int &aHint) { // get stride const int aStride = aWidth + 1; // get the key index int index = FindKeyIndex(aStride, aCount, aKeys, aTime, aHint); if (index < 0) return false; // update hint index aHint = index; // use the first value const float * __restrict key = aKeys + index * aStride; const float * __restrict data0 = &key[1]; for (int element = 0; element < aWidth; element++) { aTarget[element] = data0[element]; } return true; }
/* ================ idDict::Set ================ */ void idDict::Set( const char *key, const char *value ) { int i; idKeyValue kv; // RAVEN BEGIN // jnewquist: Tag scope and callees to track allocations using "new". MEM_SCOPED_TAG(tag,MA_STRING); // RAVEN END if ( key == NULL || key[0] == '\0' ) { return; } i = FindKeyIndex( key ); if ( i != -1 ) { // first set the new value and then free the old value to allow proper self copying const idPoolStr *oldValue = args[i].value; args[i].value = globalValues.AllocString( value ); globalValues.FreeString( oldValue ); } else { kv.key = globalKeys.AllocString( key ); kv.value = globalValues.AllocString( value ); argHash.Add( argHash.GenerateKey( kv.GetKey(), false ), args.Append( kv ) ); } }
/** * Reconstructs a bone atom from key-reduced tracks. */ void UAnimSequence::ReconstructBoneAtom(FBoneAtom& OutAtom, const FTranslationTrack& TranslationTrack, const FRotationTrack& RotationTrack, FLOAT SequenceLength, FLOAT Time, UBOOL bLooping) { OutAtom.Scale = 1.f; // Bail out (with rather wacky data) if data is empty for some reason. if( TranslationTrack.PosKeys.Num() == 0 || TranslationTrack.Times.Num() == 0 || RotationTrack.RotKeys.Num() == 0 || RotationTrack.Times.Num() == 0 ) { //debugf( TEXT("UAnimSequence::ReconstructBoneAtom(reduced) : No anim data in AnimSequence!") ); OutAtom.Rotation = FQuat::Identity; OutAtom.Translation = FVector(0.f, 0.f, 0.f); return; } // Check for before-first-frame case. if( Time <= 0.f ) { OutAtom.Translation = TranslationTrack.PosKeys(0); OutAtom.Rotation = RotationTrack.RotKeys(0); return; } // Check for after-last-frame case. const INT LastPosIndex = TranslationTrack.PosKeys.Num() - 1; const INT LastRotIndex = RotationTrack.RotKeys.Num() - 1; if( Time >= SequenceLength ) { OutAtom.Translation = TranslationTrack.PosKeys(LastPosIndex); OutAtom.Rotation = RotationTrack.RotKeys(LastRotIndex); return; } // Find the "starting" key indices. const INT PosIndex0 = FindKeyIndex( Time, TranslationTrack.Times ); const INT RotIndex0 = FindKeyIndex( Time, RotationTrack.Times ); /////////////////////// // Translation. INT PosIndex1; FLOAT PosAlpha; // If we have gone over the end, do different things in case of looping. if ( PosIndex0 == LastPosIndex ) { // If looping, interpolate between last and first frame. if( bLooping ) { PosIndex1 = 0; // @todo DB: handle looping with variable-length keys. PosAlpha = 0.5f; } // If not looping - hold the last frame. else { PosIndex1 = PosIndex0; PosAlpha = 1.f; } } else { // Find the "ending" key index and alpha. PosIndex1 = PosIndex0+1; const FLOAT DeltaTime = TranslationTrack.Times(PosIndex1) - TranslationTrack.Times(PosIndex0); PosAlpha = (Time - TranslationTrack.Times(PosIndex0))/DeltaTime; } OutAtom.Translation = Lerp( TranslationTrack.PosKeys(PosIndex0), TranslationTrack.PosKeys(PosIndex1), PosAlpha ); /////////////////////// // Rotation. INT RotIndex1; FLOAT RotAlpha; // If we have gone over the end, do different things in case of looping. if ( RotIndex0 == LastRotIndex ) { // If looping, interpolate between last and first frame. if( bLooping ) { RotIndex1 = 0; // @todo DB: handle looping with variable-length keys. RotAlpha = 0.5f; } // If not looping - hold the last frame. else { RotIndex1 = RotIndex0; RotAlpha = 1.f; } } else { // Find the "ending" key index and alpha. RotIndex1 = RotIndex0+1; const FLOAT DeltaTime = RotationTrack.Times(RotIndex1) - RotationTrack.Times(RotIndex0); RotAlpha = (Time - RotationTrack.Times(RotIndex0))/DeltaTime; } #if !USE_SLERP // Fast linear quaternion interpolation. // To ensure the 'shortest route', we make sure the dot product between the two keys is positive. if( (RotationTrack.RotKeys(RotIndex0) | RotationTrack.RotKeys(RotIndex1)) < 0.f ) { // To clarify the code here: a slight optimization of inverting the parametric variable as opposed to the quaternion. OutAtom.Rotation = (RotationTrack.RotKeys(RotIndex0) * (1.f-RotAlpha)) + (RotationTrack.RotKeys(RotIndex1) * -RotAlpha); } else { OutAtom.Rotation = (RotationTrack.RotKeys(RotIndex0) * (1.f-RotAlpha)) + (RotationTrack.RotKeys(RotIndex1) * RotAlpha); } #else OutAtom.Rotation = SlerpQuat( RotationTrack.RotKeys(RotIndex0), RotationTrack.RotKeys(RotIndex1), RotAlpha ); #endif OutAtom.Rotation.Normalize(); }