// given a model, bonelist and bonename, lets pause an anim if it's playing. qboolean G2_Pause_Bone_Anim_Index( boneInfo_v &blist, const int boneIndex, const int currentTime,int numFrames) { if (boneIndex>=0&&boneIndex<blist.size()) { // are we pausing or un pausing? if (blist[boneIndex].pauseTime) { int startFrame, endFrame, flags; float currentFrame, animSpeed; // figure out what frame we are on now if (G2_Get_Bone_Anim_Index( blist, boneIndex, blist[boneIndex].pauseTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed,numFrames)) { // reset start time so we are actually on this frame right now G2_Set_Bone_Anim_Index( blist, boneIndex, startFrame, endFrame, flags, animSpeed, currentTime, currentFrame, 0,numFrames); // no pausing anymore blist[boneIndex].pauseTime = 0; } else { return qfalse; } } // ahh, just pausing, the easy bit else { blist[boneIndex].pauseTime = currentTime; } return qtrue; } assert(0); return qfalse; }
// given a model, bonelist and bonename, return the current frame, startframe and endframe of the current animation // NOTE if we aren't running an animation, then qfalse is returned qboolean G2_Get_Bone_Anim(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName, const int currentTime, float *currentFrame, int *startFrame, int *endFrame, int *flags, float *retAnimSpeed) { int index = G2_Find_Bone(ghlInfo, blist, boneName); if (index==-1) { return qfalse; } assert(ghlInfo->aHeader); if (G2_Get_Bone_Anim_Index(blist, index, currentTime, currentFrame, startFrame, endFrame, flags, retAnimSpeed,ghlInfo->aHeader->numFrames)) { assert(*startFrame>=0&&*startFrame<ghlInfo->aHeader->numFrames); assert(*endFrame>0&&*endFrame<=ghlInfo->aHeader->numFrames); assert(*currentFrame>=0.0f&&((int)(*currentFrame))<ghlInfo->aHeader->numFrames); return qtrue; } return qfalse; }
// given a model, bone name, a bonelist, a start/end frame number, a anim speed and some anim flags, set up or modify an existing bone entry for a new set of anims qboolean G2_Set_Bone_Anim_Index(boneInfo_v &blist, const int index, const int startFrame, const int endFrame, const int flags, const float animSpeed, const int currentTime, const float setFrame, const int AblendTime,int numFrames) { int modFlags = flags; int blendTime=AblendTime; if (r_Ghoul2BlendMultiplier) { if (r_Ghoul2BlendMultiplier->value!=1.0f) { if (r_Ghoul2BlendMultiplier->value<=0.0f) { modFlags&=~BONE_ANIM_BLEND; } else { blendTime=ceil(float(AblendTime)*r_Ghoul2BlendMultiplier->value); } } } if (index<0||index >= blist.size()||blist[index].boneNumber<0) { return qfalse; } // sanity check to see if setfram is within animation bounds if (setFrame != -1) { assert((setFrame >= startFrame) && (setFrame < endFrame)); } // since we already existed, we can check to see if we want to start some blending if (modFlags & BONE_ANIM_BLEND) { float currentFrame, animSpeed; int startFrame, endFrame, flags; // figure out where we are now if (G2_Get_Bone_Anim_Index(blist, index, currentTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed,numFrames)) { if (blist[index].blendStart == currentTime) //we're replacing a blend in progress which hasn't started { // set the amount of time it's going to take to blend this anim with the last frame of the last one blist[index].blendTime = blendTime; } else { if (animSpeed<0.0f) { blist[index].blendFrame = floor(currentFrame); blist[index].blendLerpFrame = floor(currentFrame); } else { blist[index].blendFrame = currentFrame; blist[index].blendLerpFrame = currentFrame+1; // cope with if the lerp frame is actually off the end of the anim if (blist[index].blendFrame >= blist[index].endFrame ) { // we only want to lerp with the first frame of the anim if we are looping if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) { blist[index].blendFrame = blist[index].startFrame; } // if we intend to end this anim or freeze after this, then just keep on the last frame else { assert(blist[index].endFrame>0); blist[index].blendFrame = blist[index].endFrame -1; } } // cope with if the lerp frame is actually off the end of the anim if (blist[index].blendLerpFrame >= blist[index].endFrame ) { // we only want to lerp with the first frame of the anim if we are looping if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) { blist[index].blendLerpFrame = blist[index].startFrame; } // if we intend to end this anim or freeze after this, then just keep on the last frame else { assert(blist[index].endFrame>0); blist[index].blendLerpFrame = blist[index].endFrame - 1; } } } // set the amount of time it's going to take to blend this anim with the last frame of the last one blist[index].blendTime = blendTime; blist[index].blendStart = currentTime; } } // hmm, we weren't animating on this bone. In which case disable the blend else { blist[index].blendFrame = blist[index].blendLerpFrame = 0; blist[index].blendTime = 0; // we aren't blending, so remove the option to do so modFlags &= ~BONE_ANIM_BLEND; //return qfalse; } } else { blist[index].blendFrame = blist[index].blendLerpFrame = 0; blist[index].blendTime = blist[index].blendStart = 0; // we aren't blending, so remove the option to do so modFlags &= ~BONE_ANIM_BLEND; } // yes, so set the anim data and flags correctly blist[index].endFrame = endFrame; blist[index].startFrame = startFrame; blist[index].animSpeed = animSpeed; blist[index].pauseTime = 0; assert(blist[index].blendFrame>=0&&blist[index].blendFrame<numFrames); assert(blist[index].blendLerpFrame>=0&&blist[index].blendLerpFrame<numFrames); // start up the animation:) if (setFrame != -1) { blist[index].startTime = (currentTime - (((setFrame - (float)startFrame) * 50.0)/ animSpeed)); /* setFrame = bone.startFrame + ((currentTime - bone.startTime) / 50.0f * animSpeed); (setFrame - bone.startFrame) = ((currentTime - bone.startTime) / 50.0f * animSpeed); (setFrame - bone.startFrame)*50/animSpeed - currentTime = - bone.startTime; currentTime - (setFrame - bone.startFrame)*50/animSpeed = bone.startTime; */ } else { blist[index].startTime = currentTime; } blist[index].flags &= ~(BONE_ANIM_TOTAL); blist[index].flags |= modFlags; #if DEBUG_G2_TIMING if (index>-10) { const boneInfo_t &bone=blist[index]; char mess[1000]; if (bone.flags&BONE_ANIM_BLEND) { sprintf(mess,"sab[%2d] %5d %5d (%5d-%5d) %4.2f %4x bt(%5d-%5d) %7.2f %5d\n", index, currentTime, bone.startTime, bone.startFrame, bone.endFrame, bone.animSpeed, bone.flags, bone.blendStart, bone.blendStart+bone.blendTime, bone.blendFrame, bone.blendLerpFrame ); } else { sprintf(mess,"saa[%2d] %5d %5d (%5d-%5d) %4.2f %4x\n", index, currentTime, bone.startTime, bone.startFrame, bone.endFrame, bone.animSpeed, bone.flags ); } OutputDebugString(mess); } #endif // assert(blist[index].startTime <= currentTime); return qtrue; }
// given a model, bone name, a bonelist, a start/end frame number, a anim speed and some anim flags, set up or modify an existing bone entry for a new set of anims qboolean G2_Set_Bone_Anim_Index( boneInfo_v &blist, const int index, const int startFrame, const int endFrame, const int flags, const float animSpeed, const int currentTime, const float setFrame, const int blendTime) { int modFlags = flags; if ((index >= blist.size()) || (blist[index].boneNumber == -1)) { // we are attempting to set a bone override that doesn't exist assert(0); return qfalse; } if (setFrame != -1) { assert((setFrame >= startFrame) && (setFrame <= endFrame)); } if (flags & BONE_ANIM_BLEND) { float currentFrame, animSpeed; int startFrame, endFrame, flags; // figure out where we are now if (G2_Get_Bone_Anim_Index(blist, index, currentTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed, NULL, 0)) { if (blist[index].blendStart == currentTime) //we're replacing a blend in progress which hasn't started { // set the amount of time it's going to take to blend this anim with the last frame of the last one blist[index].blendTime = blendTime; } else { if (animSpeed<0.0f) { blist[index].blendFrame = floor(currentFrame); blist[index].blendLerpFrame = floor(currentFrame); } else { blist[index].blendFrame = currentFrame; blist[index].blendLerpFrame = currentFrame+1; // cope with if the lerp frame is actually off the end of the anim if (blist[index].blendFrame >= endFrame ) { // we only want to lerp with the first frame of the anim if we are looping if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) { blist[index].blendFrame = startFrame; } // if we intend to end this anim or freeze after this, then just keep on the last frame else { // assert(endFrame>0); if (endFrame <= 0) { blist[index].blendLerpFrame = 0; } else { blist[index].blendFrame = endFrame -1; } } } // cope with if the lerp frame is actually off the end of the anim if (blist[index].blendLerpFrame >= endFrame ) { // we only want to lerp with the first frame of the anim if we are looping if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) { blist[index].blendLerpFrame = startFrame; } // if we intend to end this anim or freeze after this, then just keep on the last frame else { // assert(endFrame>0); if (endFrame <= 0) { blist[index].blendLerpFrame = 0; } else { blist[index].blendLerpFrame = endFrame - 1; } } } } // set the amount of time it's going to take to blend this anim with the last frame of the last one blist[index].blendTime = blendTime; blist[index].blendStart = currentTime; } } // hmm, we weren't animating on this bone. In which case disable the blend else { blist[index].blendFrame = blist[index].blendLerpFrame = 0; blist[index].blendTime = 0; modFlags &= ~(BONE_ANIM_BLEND); } } else { blist[index].blendFrame = blist[index].blendLerpFrame = 0; blist[index].blendTime = blist[index].blendStart = 0; // we aren't blending, so remove the option to do so modFlags &= ~BONE_ANIM_BLEND; } // yes, so set the anim data and flags correctly blist[index].endFrame = endFrame; blist[index].startFrame = startFrame; blist[index].animSpeed = animSpeed; blist[index].pauseTime = 0; // start up the animation:) if (setFrame != -1) { blist[index].lastTime = blist[index].startTime = (currentTime - (((setFrame - (float)startFrame) * 50.0)/ animSpeed)); } else { blist[index].lastTime = blist[index].startTime = currentTime; } blist[index].flags &= ~(BONE_ANIM_TOTAL); blist[index].flags |= modFlags; #if DEBUG_G2_TIMING if (index==2) { const boneInfo_t &bone=blist[index]; char mess[1000]; if (bone.flags&BONE_ANIM_BLEND) { sprintf(mess,"sab[%2d] %5d %5d (%5d-%5d) %4.2f %4x bt(%5d-%5d) %7.2f %5d\n", index, currentTime, bone.startTime, bone.startFrame, bone.endFrame, bone.animSpeed, bone.flags, bone.blendStart, bone.blendStart+bone.blendTime, bone.blendFrame, bone.blendLerpFrame ); } else { sprintf(mess,"saa[%2d] %5d %5d (%5d-%5d) %4.2f %4x\n", index, currentTime, bone.startTime, bone.startFrame, bone.endFrame, bone.animSpeed, bone.flags ); } OutputDebugString(mess); } #endif return qtrue; }