Пример #1
0
//------------------------------------------------------------------------------
//! Blends between 2 animations at a specific frame.
//! This is done by interpolating 2 frames of animA, then 2 frames of animB,
//! then blending the 2 resulting frames together according to the factor.
//! @param animA:   The first animation.
//! @param timeA:   A time hint for the first animation.
//! @param animB:   The second animation.
//! @param timeB:   A time hint for the second animation.
//! @param factor:  A blend factor to merge animA with animB.
//! @param dstPose: A pre-allocated pose into which to store the result.
void
Puppeteer::blendFrame(
   SkeletalAnimation* animA,
   float              timeA,
   SkeletalAnimation* animB,
   float              timeB,
   float              factor,
   SkeletalPose&      dstPose
)
{
   DBG_BLOCK( os_pup, "Puppeteer::blendFrame(" << animA << ", " << timeA << ", " << animB << ", " << timeB << ", " << factor << ")" );

   animA->makeRelative();
   animB->makeRelative();

   // Compute poses.
   SkeletalPose* pA0;
   SkeletalPose* pA1;
   float tA;
   SkeletalPose* pB0;
   SkeletalPose* pB1;
   float tB;

   animA->getPoses( timeA, pA0, pA1, tA );
   animB->getPoses( timeB, pB0, pB1, tB );

   DBG_MSG( os_pup, "A: " << timeA << " --> " << tA );
   DBG_MSG( os_pup, "B: " << timeB << " --> " << tB );

   const SkeletalPose::BoneContainer& bA0 = pA0->bones();
   const SkeletalPose::BoneContainer& bA1 = pA1->bones();
   const SkeletalPose::BoneContainer& bB0 = pB0->bones();
   const SkeletalPose::BoneContainer& bB1 = pB1->bones();

   //Reff refA = pA0->referential().slerp( pA1->referential(), tA );
   //Reff refB = pB0->referential().slerp( pB1->referential(), tB );
   //Reff ref  = refA.slerp( refB, factor );
   Reff refA = pA0->referential().nlerp( pA1->referential(), tA );
   Reff refB = pB0->referential().nlerp( pB1->referential(), tB );
   Reff ref  = refA.nlerp( refB, factor );

   dstPose.referential( ref );
   SkeletalPose::BoneContainer& dstBones = dstPose.bones();

   CHECK( bA0.size() == bB0.size() );
   CHECK( bA0.size() == dstBones.size() );
   const uint nBones = uint(dstBones.size());
   for( uint i = 0; i < nBones; ++i )
   {
      //Quatf sorient = bA0[i].slerp( bA1[i], tA );
      //Quatf eorient = bB0[i].slerp( bB1[i], tB );
      //Quatf orient  = sorient.slerp( eorient, factor );
      Quatf sorient = bA0[i].nlerp( bA1[i], tA );
      Quatf eorient = bB0[i].nlerp( bB1[i], tB );
      Quatf orient  = sorient.nlerp( eorient, factor );
      dstBones[i] = orient;
   }
}
Пример #2
0
//------------------------------------------------------------------------------
//!
RCP<SkeletalAnimation>
Puppeteer::blend(
   SkeletalAnimation* startAnim,
   SkeletalAnimation* endAnim
)
{
   DBG_BLOCK( os_pup, "Puppeteer::blend(" << startAnim << ", " << endAnim << ")" );
   RCP<SkeletalAnimation> anim = new SkeletalAnimation();
   anim->skeleton( startAnim->skeleton() );

   startAnim->makeRelative();
   endAnim->makeRelative();

   // Compute duration, rate and number of poses.
   float duration = (startAnim->duration() + endAnim->duration()) * 0.5f;
   float rate     = CGM::max( startAnim->rate(), endAnim->rate() );
   uint numPoses  = uint(rate*duration) + 1;

   anim->reservePoses( numPoses );
   anim->rate( rate );
   anim->velocity( (startAnim->velocity() + endAnim->velocity())*0.5f );
   anim->offset( (startAnim->offset() + endAnim->offset())*0.5f );

   // Compute poses.
   SkeletalPose* sp0;
   SkeletalPose* sp1;
   SkeletalPose* ep0;
   SkeletalPose* ep1;

   for( uint p = 0; p < numPoses; ++p )
   {
      float t = float(p) / float(numPoses-1);
      float st;
      float et;

      startAnim->getPosesClamped( startAnim->duration() * t, sp0, sp1, st );
      endAnim->getPosesClamped( endAnim->duration() * t, ep0, ep1, et );

      const SkeletalPose::BoneContainer& sb0 = sp0->bones();
      const SkeletalPose::BoneContainer& sb1 = sp1->bones();
      const SkeletalPose::BoneContainer& eb0 = ep0->bones();
      const SkeletalPose::BoneContainer& eb1 = ep1->bones();

      //Reff sref = sp0->referential().slerp( sp1->referential(), st );
      //Reff eref = ep0->referential().slerp( ep1->referential(), et );
      //Reff ref  = sref.slerp( eref, t );
      Reff sref = sp0->referential().nlerp( sp1->referential(), st );
      Reff eref = ep0->referential().nlerp( ep1->referential(), et );
      Reff ref  = sref.nlerp( eref, t );

      SkeletalPose* pose = anim->addPose( ref );
      pose->reserveBones( uint(sb0.size()) );
      for( uint i = 0; i < sb0.size(); ++i )
      {
         //Quatf sorient = sb0[i].slerp( sb1[i], st );
         //Quatf eorient = eb0[i].slerp( eb1[i], et );
         //Quatf orient  = sorient.slerp( eorient, t );
         Quatf sorient = sb0[i].nlerp( sb1[i], st );
         Quatf eorient = eb0[i].nlerp( eb1[i], et );
         Quatf orient  = sorient.nlerp( eorient, t );
         pose->addBone( orient );
      }
   }
   return anim;
}