//===========================================================================// // File: AnimIterator.cpp // Project: MechWarrior 4 // Contents: // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 07/01/98 JSE Initial coding, //---------------------------------------------------------------------------// // Copyright (C) 1998, Fasa Interactive, Inc. // All Rights reserved worldwide // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //===========================================================================// #include //############################################################################# //####################### AnimIterator ######################### //############################################################################# using namespace MW4Animation; AnimIterator::AnimIterator(AnimInstance *animation_instance): Plug(DefaultData) { Check_Object(animation_instance); animationInstance = animation_instance; Check_Pointer(animation_instance->animData); animationData = animation_instance->animData; currentTime = animationData->animHeaderBlock->startTime; gos_PushCurrentHeap(g_AnimIteratorHeap); nextFrame = new BYTE[animationData->GetChannelCount()]; Register_Pointer(nextFrame); gos_PopCurrentHeap(); // we set all of them to invalid. // you must reset the system to the start/end or // set it to a position. skipChannels = false; velocityScale = 1.0f; blendValue = 1.0f; for (int i = 0; i < animationData->GetChannelCount(); ++i) { nextFrame[i] = MaxKeyFrame; } } // //############################################################################# //############################################################################# // AnimIterator::~AnimIterator() { Unregister_Pointer(nextFrame); delete[] nextFrame; } // //############################################################################# //############################################################################# // int AnimIterator::ToAbsoluteChannel( BYTE joint_number, BYTE channel_number ) { Verify(joint_number < animationData->GetJointCount()); Verify(channel_number < animationData->animJointBlock[joint_number].channelsUsed); return animationData->animJointBlock[joint_number].firstChannel + channel_number; } // //############################################################################# //############################################################################# // void AnimIterator::FromAbsoluteChannel( int absolute_channel_number, BYTE& joint_number, BYTE& channel_number ) { Verify(absolute_channel_number < animationData->GetChannelCount()); joint_number = animationData->animChannelBlock[absolute_channel_number].jointNumber; Verify(joint_number < animationData->GetJointCount()); channel_number = (BYTE) (absolute_channel_number - animationData->animJointBlock[joint_number].firstChannel); Verify(channel_number < animationData->animJointBlock[joint_number].channelsUsed); return; } // //############################################################################# //############################################################################# // // -1 means that there are no more keyframes in that direction int AnimIterator::GetForwardFrameIndex(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); #ifdef _ARMOR if (nextFrame[absolute_channel_number] != MaxKeyFrame) { Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount); Verify(nextFrame[absolute_channel_number] >= 0); } #endif // this will be set when there are no "next" keyframes. // once that happens, we don't animate this joint anymore. return nextFrame[absolute_channel_number]; } // //############################################################################# //############################################################################# // int AnimIterator::GetReverseFrameIndex(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); #ifdef _ARMOR if (nextFrame[absolute_channel_number] != MaxKeyFrame) { Verify(nextFrame[absolute_channel_number] >= 0); } #endif if( nextFrame[absolute_channel_number] != 0) { Verify(nextFrame[absolute_channel_number] - 1 < animationData->animChannelBlock[absolute_channel_number].keyframeCount); return nextFrame[absolute_channel_number] - 1; } return MaxKeyFrame; } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetForwardKeyFrame(int absolute_channel_number) { if (nextFrame[absolute_channel_number] == MaxKeyFrame) { return NULL; } Verify(absolute_channel_number < animationData->GetChannelCount()); #ifdef _ARMOR if (nextFrame[absolute_channel_number] != MaxKeyFrame) { Verify(nextFrame[absolute_channel_number] >= 0); Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount); } #endif size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + (animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey * nextFrame[absolute_channel_number]); return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + offset); } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetReverseKeyFrame(int absolute_channel_number) { if (nextFrame[absolute_channel_number] == MaxKeyFrame) { // if there is no next that means it is the "last" keyframe size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + ((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey); return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + offset); } Verify(absolute_channel_number < animationData->GetChannelCount()); #ifdef _ARMOR if (nextFrame[absolute_channel_number] != MaxKeyFrame) { Verify(nextFrame[absolute_channel_number] >= 0); } #endif if( nextFrame[absolute_channel_number] != 0) { Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount); size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + (animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey * (nextFrame[absolute_channel_number] - 1)); return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + offset); } return NULL; } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetFirstKeyFrame(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + animationData->animChannelBlock[absolute_channel_number].offsetToKeyData); } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetLastKeyFrame(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + ((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey); return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + offset); } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetStartKeyFrame(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } BaseKeyframeTime* key = NULL; BaseKeyframe* ret_key = NULL; for (int i = 0; i < animationData->animChannelBlock[absolute_channel_number].keyframeCount; ++i) { key = GetKeyFrameTime(absolute_channel_number, i); if (key->timeOfFrame > animationData->animHeaderBlock->startTime) { ret_key = GetKeyFrame(absolute_channel_number, i); break; } } return ret_key; } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetStopKeyFrame(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } BaseKeyframeTime* key = NULL; BaseKeyframe* ret_key = NULL; for (int i = animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1;i >= 0; --i) { key = GetKeyFrameTime(absolute_channel_number, i); if (key->timeOfFrame < animationData->animHeaderBlock->endTime) { ret_key = GetKeyFrame(absolute_channel_number, i); break; } } return ret_key; } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetKeyFrame(int absolute_channel_number, int index) { Verify(absolute_channel_number < animationData->GetChannelCount()); Verify( index < animationData->animChannelBlock[absolute_channel_number].keyframeCount); Verify( index >= 0); size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyData + (index * animationData->animChannelBlock[absolute_channel_number].sizeOfOneKey); return (BaseKeyframe*) ((BYTE*)animationData->animKeyBlock + offset); } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetForwardKeyFrameTime(int absolute_channel_number) { if (nextFrame[absolute_channel_number] == MaxKeyFrame) { return NULL; } Verify(absolute_channel_number < animationData->GetChannelCount()); Verify(nextFrame[absolute_channel_number] >= 0); Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount); size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + (4 * nextFrame[absolute_channel_number]); return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + offset); } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetReverseKeyFrameTime(int absolute_channel_number) { if (nextFrame[absolute_channel_number] == MaxKeyFrame) { // if there is no next that means it is the "last" keyframe size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + ((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * 4); return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + offset); } Verify(absolute_channel_number < animationData->GetChannelCount()); Verify(nextFrame[absolute_channel_number] >= 0); if( nextFrame[absolute_channel_number] != 0) { Verify(nextFrame[absolute_channel_number] < animationData->animChannelBlock[absolute_channel_number].keyframeCount); size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + (4 * (nextFrame[absolute_channel_number] - 1)); return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + offset); } return NULL; } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetFirstKeyFrameTime(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData); } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetLastKeyFrameTime(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + ((animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1) * 4); return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + offset); } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetStartKeyFrameTime(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } BaseKeyframeTime* key = NULL; for (int i = 0; i < animationData->animChannelBlock[absolute_channel_number].keyframeCount; ++i) { key = GetKeyFrameTime(absolute_channel_number, i); if (key->timeOfFrame > animationData->animHeaderBlock->startTime) { key = GetKeyFrameTime(absolute_channel_number, i); } } return key; } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetStopKeyFrameTime(int absolute_channel_number) { Verify(absolute_channel_number < animationData->GetChannelCount()); if (animationData->animChannelBlock[absolute_channel_number].keyframeCount == 0) { return NULL; } BaseKeyframeTime* key = NULL; for (int i = animationData->animChannelBlock[absolute_channel_number].keyframeCount - 1;i >= 0; --i) { key = GetKeyFrameTime(absolute_channel_number, i); if (key->timeOfFrame < animationData->animHeaderBlock->endTime) { key = GetKeyFrameTime(absolute_channel_number, i); } } return key; } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetKeyFrameTime(int absolute_channel_number, int index) { Verify(absolute_channel_number < animationData->GetChannelCount()); Verify( index < animationData->animChannelBlock[absolute_channel_number].keyframeCount); Verify( index >= 0); size_t offset = animationData->animChannelBlock[absolute_channel_number].offsetToKeyTimeData + (index * 4); return (BaseKeyframeTime*) ((BYTE*)animationData->animKeyTimeBlock + offset); } // //############################################################################# //############################################################################# // void AnimIterator::ResetStart() { currentTime = animationData->animHeaderBlock->startTime; for (int i = 0; i < animationData->GetChannelCount(); ++i) { nextFrame[i] = 0; } } // //############################################################################# //############################################################################# // void AnimIterator::ResetEnd() { currentTime = animationData->animHeaderBlock->endTime; for (int i = 0; i < animationData->GetChannelCount(); ++i) { nextFrame[i] = (BYTE)(animationData->animChannelBlock[i].keyframeCount - 1); } } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverTime() { if (currentTime >= animationData->animHeaderBlock->endTime) { return GetCarryOverTimeForward(); } else if (currentTime <= animationData->animHeaderBlock->startTime) { return GetCarryOverTimeReverse(); } else { //Abort_Program("AnimIterator::GetCarryOverTime() - Should never reach here"); } return 0.0f; } // //############################################################################# //############################################################################# // int AnimIterator::GetCarryOverFrame(int frames_per_second) { return (int)(GetCarryOverTime() * frames_per_second); } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverPosition() { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar percent = GetCarryOverTime() / (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime); Verify(percent > 0.0f); Verify(percent <= 1.0f); return percent; } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverTimeForward() { Verify((currentTime - animationData->animHeaderBlock->endTime) >= 0.0f); return currentTime - animationData->animHeaderBlock->endTime; } // //############################################################################# //############################################################################# // int AnimIterator::GetCarryOverFrameForward(int frames_per_second) { return (int)(GetCarryOverTimeForward() * frames_per_second); } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverPositionForward() { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar percent = GetCarryOverTimeForward() / (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime); Verify(percent > 0.0f); Verify(percent <= 1.0f); return percent; } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverTimeReverse() { Verify((currentTime - animationData->animHeaderBlock->startTime) <= 0.0f); return currentTime - animationData->animHeaderBlock->startTime; } // //############################################################################# //############################################################################# // int AnimIterator::GetCarryOverFrameReverse(int frames_per_second) { return (int)(GetCarryOverTimeReverse() * frames_per_second); } // //############################################################################# //############################################################################# // Stuff::Scalar AnimIterator::GetCarryOverPositionReverse() { Verify((animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) != 0.0f); Stuff::Scalar percent = GetCarryOverTimeReverse() / (animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime); Verify(percent > 0.0f); Verify(percent <= 1.0f); return percent; } // //############################################################################# //############################################################################# // void AnimIterator::SetTime(Stuff::Scalar time) { //SPEW(("jerryeds", "SetTime %f", time)); // Calling bullshit on expensive calls if (time <= 0.0f) { ResetStart(); return; } else if (time >= animationData->animHeaderBlock->endTime - animationData->animHeaderBlock->startTime) { ResetEnd(); return; } // We have to be "IN" the animation, on out of range // you CAN NOT ANIMATE out of range keyframes! They // are mearly helper keys. // time 0 is startTime, for simplicity time += animationData->animHeaderBlock->startTime; // this allows for animations that start somewhere other than 0 Verify(time >= animationData->animHeaderBlock->startTime); Verify(time <= animationData->animHeaderBlock->endTime); currentTime = time; // lets get busy.... // binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 for (int channel_count = 0; channel_count < animationData->GetChannelCount(); ++channel_count) { if (skipChannels) { if (! (animationData->animChannelBlock[channel_count].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || animationData->animChannelBlock[channel_count].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType )) { continue; } } nextFrame[channel_count] = MaxKeyFrame; if (animationData->animChannelBlock[channel_count].keyframeCount > 0 && animationInstance->jointToIndex[animationData->animChannelBlock[channel_count].jointNumber]!=MaxKeyFrame) { // pretty sure this will skip 0 int left = 1; int right = animationData->animChannelBlock[channel_count].keyframeCount-1; int x; while(right >= left) { x = (left+right)/2; if (x == animationData->animChannelBlock[channel_count].keyframeCount) break; BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, x); // the "next" keyframe is always greater, the last keyframe // can be the same. We are always "going forward". // lowest keyframe we get is 1. BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, x-1); if ((last_keyframe->timeOfFrame <= time) && (keyframe->timeOfFrame > time)) { // this is the keyframe, set it up and leave nextFrame[channel_count] = (BYTE)x; break; } else if (time < keyframe->timeOfFrame) { right = x-1; } else { left = x+1; } } // we didn't find one... if ( nextFrame[channel_count] == MaxKeyFrame) { BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, 0); BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, animationData->animChannelBlock[channel_count].keyframeCount-1); if ((keyframe->timeOfFrame) > time) { // this is the keyframe, set it up and leave nextFrame[channel_count] = 0; } else if (last_keyframe->timeOfFrame <= time) { nextFrame[channel_count] = MaxKeyFrame; } else { //animationData->animChannelBlock[absolute_channel_number].keyframeCount Verify(0); } } #if defined(MW4_ANIMATION_DEBUG) if ( nextFrame[channel_count] != MaxKeyFrame) { if (nextFrame[channel_count] >= 1) { BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]); BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]-1); Verify(keyframe->timeOfFrame > time); Verify(last_keyframe->timeOfFrame <= time); } else { BaseKeyframeTime *keyframe = GetKeyFrameTime( channel_count, nextFrame[channel_count]); Verify(keyframe->timeOfFrame > time); } } else { BaseKeyframeTime *last_keyframe = GetKeyFrameTime( channel_count, animationData->animChannelBlock[channel_count].keyframeCount-1); Verify(last_keyframe->timeOfFrame <= time); } #endif } } } // //############################################################################# //############################################################################# // bool AnimIterator::MoveTime(Stuff::Scalar time_slice) { if (time_slice > 0.0f) { return IncrementTime(time_slice); } else if (time_slice < 0.0f) { return DecrementTime(time_slice); } else { // no movement return false; } } // //############################################################################# //############################################################################# // bool AnimIterator::IncrementTime(Stuff::Scalar time_slice) { Min_Clamp(time_slice, 0.0f); Verify(time_slice >= 0.0f); currentTime += time_slice; Verify(currentTime >= animationData->animHeaderBlock->startTime); //Verify(currentTime <= animationData->animHeaderBlock->endTime); if (currentTime >= animationData->animHeaderBlock->endTime) { //DEBUG_STREAM << "******ct:" << currentTime << " ts:" << time_slice << " et:" << animationData->animHeaderBlock->endTime << endl; // set last positions we are over return true; } for (int i = 0; i < animationData->GetChannelCount(); ++i) { if (skipChannels) { if (! (animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType )) { continue; } } if (animationData->animChannelBlock[i].keyframeCount > 0 && animationInstance->jointToIndex[animationData->animChannelBlock[i].jointNumber]!=MaxKeyFrame) { // it is already at the end so go on if (nextFrame[i] == MaxKeyFrame) { continue; } int frame_count = nextFrame[i]; BaseKeyframeTime *keyframe = GetKeyFrameTime( i, frame_count); while(keyframe != NULL) { if(keyframe->timeOfFrame > currentTime) { //DEBUG_STREAM << "K: " << keyframe->timeOfFrame << endl; // this key frame is next' nextFrame[i] = (BYTE)frame_count; break; } ++frame_count; if (frame_count < animationData->animChannelBlock[i].keyframeCount) { keyframe = GetKeyFrameTime( i, frame_count); } else { nextFrame[i] = MaxKeyFrame; break; } } } if (nextFrame[i] != MaxKeyFrame) { Verify(nextFrame[i] < animationData->animChannelBlock[i].keyframeCount); } } return false; } // //############################################################################# //############################################################################# // bool AnimIterator::DecrementTime(Stuff::Scalar time_slice) { // // Reverse is kind of weird. // The way keyframes work is by having a "next" keyframe. // so if you are at the begging of the animation the next keyframe is the first. // if you are at the end the next keyframe is -1. This means that no more animation // data remains for the key. // // this is what the interpolation engine does with the indexes... // frameindex -1 = no animation // frameindex 0 = current position to first frame // frameindex x = x-1 to x interpolation // For reverse this is a little diffrent. // The interpolation engine detect backwards by the negative time motion as does the move time commands. // The diffrence is -1 does not really apply to the backwards lerping. // // if time is negative // frameindex -1 = INVALID // frameindex 0 = no animation // frameindex x = x to x-1 interpolation // frameindex lastframe = current positoin to last frame //Verify(time_slice < 0); currentTime += time_slice; if (currentTime <= animationData->animHeaderBlock->startTime) { // set last positions we are over return true; } Verify(currentTime >= animationData->animHeaderBlock->startTime); Verify(currentTime <= animationData->animHeaderBlock->endTime); for (int i = 0; i < animationData->GetChannelCount(); ++i) { if (skipChannels) { if (! (animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::VelocityChannelType || animationData->animChannelBlock[i].channelType != MW4Animation::ChannelAnimData::AngularVelocityChannelType )) { continue; } } if (animationData->animChannelBlock[i].keyframeCount > 0 && animationInstance->jointToIndex[animationData->animChannelBlock[i].jointNumber]!=MaxKeyFrame) { // it is already at the end so go on if (nextFrame[i] == MaxKeyFrame) { continue; } int frame_count = nextFrame[i]; BaseKeyframeTime *keyframe = GetKeyFrameTime( i, frame_count); while(keyframe != NULL) { if(keyframe->timeOfFrame < currentTime) { // this key frame is next' nextFrame[i] = (BYTE)frame_count; break; } --frame_count; if (frame_count >= 0) { keyframe = GetKeyFrameTime( i, frame_count); } else { nextFrame[i] = 0; break; } } } } return false; } // //############################################################################# //############################################################################# // BaseKeyframe * AnimIterator::GetKeyFrameAtTime(int absolute_channel_number, Stuff::Scalar time) { // We have to be "IN" the animation, on out of range // you CAN NOT ANIMATE out of range keyframes! They // are mearly helper keys. // time 0 is startTime, for simplicity time += animationData->animHeaderBlock->startTime; // this allows for animations that start somewhere other than 0 Verify(time >= animationData->animHeaderBlock->startTime); Verify(time <= animationData->animHeaderBlock->endTime); currentTime = time; // lets get busy.... // binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 if (animationData->animChannelBlock[absolute_channel_number].keyframeCount > 0) { // pretty sure this will skip 0 int left = 1; int right = animationData->animChannelBlock[absolute_channel_number].keyframeCount; int x; while(right >= left) { x = (left+right)/2; BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, x); // the "next" keyframe is always greater, the last keyframe // can be the same. We are always "going forward". // lowest keyframe we get is 1. BaseKeyframeTime *last_keyframe = GetKeyFrameTime( absolute_channel_number, x-1); if ((last_keyframe->timeOfFrame) > time && (keyframe->timeOfFrame <= time)) { // this is the keyframe, set it up and leave BaseKeyframe *ret_key = GetKeyFrame( absolute_channel_number, x); return ret_key; } else if (time < keyframe->timeOfFrame) { right = x-1; } else { left = x+1; } } // we didn't find one... BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, 0); if ((keyframe->timeOfFrame) > time) { BaseKeyframe *ret_key = GetKeyFrame( absolute_channel_number, 0); return ret_key; } } return NULL; } // //############################################################################# //############################################################################# // BaseKeyframeTime * AnimIterator::GetKeyFrameTimeAtTime(int absolute_channel_number, Stuff::Scalar time) { // We have to be "IN" the animation, on out of range // you CAN NOT ANIMATE out of range keyframes! They // are mearly helper keys. // time 0 is startTime, for simplicity time += animationData->animHeaderBlock->startTime; // this allows for animations that start somewhere other than 0 Verify(time >= animationData->animHeaderBlock->startTime); Verify(time <= animationData->animHeaderBlock->endTime); currentTime = time; // lets get busy.... // binary "divide-and-conquer" search from Sedgewick - "Algorithms in C++" pg. 198 if (animationData->animChannelBlock[absolute_channel_number].keyframeCount > 0) { // pretty sure this will skip 0 int left = 1; int right = animationData->animChannelBlock[absolute_channel_number].keyframeCount; int x; while(right >= left) { x = (left+right)/2; BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, x); // the "next" keyframe is always greater, the last keyframe // can be the same. We are always "going forward". // lowest keyframe we get is 1. BaseKeyframeTime *last_keyframe = GetKeyFrameTime( absolute_channel_number, x-1); if ((last_keyframe->timeOfFrame) > time && (keyframe->timeOfFrame <= time)) { // this is the keyframe, set it up and leave return keyframe; } else if (time < keyframe->timeOfFrame) { right = x-1; } else { left = x+1; } } // we didn't find one... BaseKeyframeTime *keyframe = GetKeyFrameTime( absolute_channel_number, 0); if ((keyframe->timeOfFrame) > time) { return keyframe; } } return NULL; } // //############################################################################# //############################################################################# //