/* =============== CG_BuildAnimSkeleton Builds the skeleton for the current animation Also blends between the old and new skeletons if necessary =============== */ void CG_BuildAnimSkeleton( const lerpFrame_t *lf, refSkeleton_t *newSkeleton, const refSkeleton_t *oldSkeleton ) { if( !lf->animation || !lf->animation->handle ) { // initialize skeleton if animation handle is invalid int i; newSkeleton->type = refSkeletonType_t::SK_ABSOLUTE; newSkeleton->numBones = MAX_BONES; for( i = 0; i < MAX_BONES; i++ ) { newSkeleton->bones[i].parentIndex = -1; TransInit(&newSkeleton->bones[i].t); } return; } if ( !trap_R_BuildSkeleton( newSkeleton, lf->animation->handle, lf->oldFrame, lf->frame, 1 - lf->backlerp, lf->animation->clearOrigin ) ) { Log::Warn( "CG_BuildAnimSkeleton: Can't build skeleton" ); } // lerp between old and new animation if possible if ( lf->blendlerp >= 0.0f ) { if ( newSkeleton->type != refSkeletonType_t::SK_INVALID && oldSkeleton->type != refSkeletonType_t::SK_INVALID && newSkeleton->numBones == oldSkeleton->numBones ) { if ( !trap_R_BlendSkeleton( newSkeleton, oldSkeleton, lf->blendlerp ) ) { Log::Warn( "CG_BuildAnimSkeleton: Can't blend skeletons" ); return; } } } }
/* =============== CG_RunLerpFrame =============== */ void CG_RunLerpFrame(lerpFrame_t * lf, animation_t * anims, int animsNum, int newAnimation, float speedScale) { int f, numFrames; animation_t *anim; qboolean animChanged; // debugging tool to get no animations if(cg_animSpeed.integer == 0) { lf->oldFrame = lf->frame = lf->backlerp = 0; return; } // see if the animation sequence is switching if(newAnimation != lf->animationNumber || !lf->animation) { CG_SetLerpFrameAnimation(lf, anims, animsNum, newAnimation); if(!lf->animation) { memcpy(&lf->oldSkeleton, &lf->skeleton, sizeof(refSkeleton_t)); } animChanged = qtrue; } else { animChanged = qfalse; } // if we have passed the current frame, move it to // oldFrame and calculate a new frame if(cg.time >= lf->frameTime || animChanged) { if(animChanged) { lf->oldFrame = 0; lf->oldFrameTime = cg.time; } else { lf->oldFrame = lf->frame; lf->oldFrameTime = lf->frameTime; } // get the next frame based on the animation anim = lf->animation; if(!anim->frameTime) { return; // shouldn't happen } if(cg.time < lf->animationStartTime) { lf->frameTime = lf->animationStartTime; // initial lerp } else { lf->frameTime = lf->oldFrameTime + anim->frameTime; } f = (lf->frameTime - lf->animationStartTime) / anim->frameTime; f *= speedScale; // adjust for haste, etc numFrames = anim->numFrames; if(anim->flipflop) { numFrames *= 2; } if(f >= numFrames) { f -= numFrames; if(anim->loopFrames) { f %= anim->loopFrames; f += anim->numFrames - anim->loopFrames; } else { f = numFrames - 1; // the animation is stuck at the end, so it // can immediately transition to another sequence lf->frameTime = cg.time; } } if(anim->reversed) { lf->frame = anim->firstFrame + anim->numFrames - 1 - f; } else if(anim->flipflop && f >= anim->numFrames) { lf->frame = anim->firstFrame + anim->numFrames - 1 - (f % anim->numFrames); } else { lf->frame = anim->firstFrame + f; } if(cg.time > lf->frameTime) { lf->frameTime = cg.time; } } if(lf->frameTime > cg.time + 200) { lf->frameTime = cg.time; } if(lf->oldFrameTime > cg.time) { lf->oldFrameTime = cg.time; } // calculate current lerp value if(lf->frameTime == lf->oldFrameTime) { lf->backlerp = 0; } else { lf->backlerp = 1.0 - (float)(cg.time - lf->oldFrameTime) / (lf->frameTime - lf->oldFrameTime); } // blend old and current animation if(cg_animBlend.value <= 0.0f) { lf->blendlerp = 0.0f; } if((lf->blendlerp > 0.0f) && (cg.time > lf->blendtime)) { #if 0 // linear blending lf->blendlerp -= 0.025f; #else // exp blending lf->blendlerp -= lf->blendlerp / cg_animBlend.value; #endif if(lf->blendlerp <= 0.0f) lf->blendlerp = 0.0f; if(lf->blendlerp >= 1.0f) lf->blendlerp = 1.0f; lf->blendtime = cg.time + 10; } if(!trap_R_BuildSkeleton(&lf->skeleton, lf->animation->handle, lf->oldFrame, lf->frame, 1.0 - lf->backlerp, lf->animation->clearOrigin)) { CG_Printf("Can't build lf->skeleton\n"); } // lerp between old and new animation if possible if(lf->blendlerp > 0.0f) { if(!trap_R_BlendSkeleton(&lf->skeleton, &lf->oldSkeleton, lf->blendlerp)) { CG_Printf("Can't blend\n"); return; } } }