// calculate single bone with key blending and callbck calling void CKinematicsAnimated::CLBone(const CBoneData* bd,CBoneInstance& BONE_INST,const Fmatrix *parent,const CBlendInstance::BlendSVec &Blend, u8 channel_mask /*= (1<<0)*/) { u16 SelfID = bd->GetSelfID(); if (LL_GetBoneVisible(SelfID)){ if (BONE_INST.Callback_overwrite){ if (BONE_INST.Callback) BONE_INST.Callback(&BONE_INST); } else { CKey R[MAX_CHANNELS][MAX_BLENDED]; //all keys CKey BK[MAX_CHANNELS][MAX_BLENDED]; //base keys float BA[MAX_CHANNELS][MAX_BLENDED]; //all factors int b_counts[MAX_CHANNELS] = {0,0,0,0}; //channel counts //float BCA[MAX_CHANNELS] = {0,0,0,0}; //channel factors BlendSVecCIt BI; for (BI=Blend.begin(); BI!=Blend.end(); BI++) { CBlend* B = *BI; int &b_count = b_counts[B->channel]; CKey* D = &R[B->channel][b_count]; if(!(channel_mask&(1<<B->channel))) continue; u8 channel = B->channel; BA[channel][b_count] = B->blendAmount; //BCA[channel] += B->blendAmount; CMotion &M =*LL_GetMotion(B->motionID,SelfID); Dequantize(*D,*B,M); QR2Quat( M._keysR[0], BK[channel][b_count].Q ); if(M.test_flag(flTKeyPresent)) QT2T(M._keysT[0] ,M ,BK[channel][b_count].T ); else BK[channel][b_count].T.set(M._initT); ++b_count; /// PSGP.blerp (D,&K1,&K2,delta); } // Blend them together CKey channels[MAX_CHANNELS]; float BC [MAX_CHANNELS]; u16 ch_count = 0; for(u16 j= 0;MAX_CHANNELS>j;++j) { if(j!=0&&b_counts[j]==0) continue; //data for channel mix cycle based on ch_count CKey &C = channels[ch_count]; BC[ch_count] = channel_factors[j];//3.f;//BCA[j]* if(j != 0) keys_substruct(R[j],BK[j],b_counts[j]); MixInterlerp( C, R[j], BA[j], b_counts[j] ); ++ch_count; } CKey Result; //Mix channels //MixInterlerp(Result,channels,BCA,ch_count); MixChannels( Result, channels, BC, ch_count ); Fmatrix RES; RES.mk_xform (Result.Q,Result.T); BONE_INST.mTransform.mul_43(*parent,RES); #ifdef DEBUG if(!check_scale(RES)) { VERIFY(check_scale(BONE_INST.mTransform)); } /* if(!is_similar(BONE_INST.mPrevTransform,RES,0.3f)) { Msg("bone %s",*bd->name) ; } BONE_INST.mPrevTransform.set(RES); */ #endif /* if(BONE_INST.mTransform.c.y>10000) { Log("BLEND_INST",BLEND_INST.Blend.size()); Log("Bone",LL_BoneName_dbg(SelfID)); Msg("Result.Q %f,%f,%f,%f",Result.Q.x,Result.Q.y,Result.Q.z,Result.Q.w); Log("Result.T",Result.T); Log("lp parent",(u32)parent); Log("parent",*parent); Log("RES",RES); Log("mT",BONE_INST.mTransform); CBlend* B = *BI; CMotion& M = *LL_GetMotion(B->motionID,SelfID); float time = B->timeCurrent*float(SAMPLE_FPS); u32 frame = iFloor(time); u32 count = M.get_count(); float delta = time-float(frame); Log("flTKeyPresent",M.test_flag(flTKeyPresent)); Log("M._initT",M._initT); Log("M._sizeT",M._sizeT); // translate if (M.test_flag(flTKeyPresent)) { CKeyQT* K1t = &M._keysT[(frame+0)%count]; CKeyQT* K2t = &M._keysT[(frame+1)%count]; Fvector T1,T2,Dt; T1.x = float(K1t->x)*M._sizeT.x+M._initT.x; T1.y = float(K1t->y)*M._sizeT.y+M._initT.y; T1.z = float(K1t->z)*M._sizeT.z+M._initT.z; T2.x = float(K2t->x)*M._sizeT.x+M._initT.x; T2.y = float(K2t->y)*M._sizeT.y+M._initT.y; T2.z = float(K2t->z)*M._sizeT.z+M._initT.z; Dt.lerp (T1,T2,delta); Msg("K1t %d,%d,%d",K1t->x,K1t->y,K1t->z); Msg("K2t %d,%d,%d",K2t->x,K2t->y,K2t->z); Log("count",count); Log("frame",frame); Log("T1",T1); Log("T2",T2); Log("delta",delta); Log("Dt",Dt); }else { D->T.set (M._initT); } VERIFY(0); } */ if (BONE_INST.Callback) BONE_INST.Callback(&BONE_INST); } BONE_INST.mRenderTransform.mul_43(BONE_INST.mTransform,bd->m2b_transform); } }