void CKinematicsAnimated::BoneChain_Calculate (const CBoneData* bd, CBoneInstance &bi, u8 mask_channel, bool ignore_callbacks) { u16 SelfID = bd->GetSelfID(); CBlendInstance& BLEND_INST = LL_GetBlendInstance(SelfID); CBlendInstance::BlendSVec &Blend = BLEND_INST.blend_vector(); //ignore callbacks BoneCallback bc = bi.Callback; BOOL ow = bi.Callback_overwrite; if(ignore_callbacks) { bi.Callback = 0; bi.Callback_overwrite =0; } // if(SelfID==LL_GetBoneRoot()) { CLBone(bd, bi, &Fidentity, Blend, mask_channel); //restore callback bi.Callback = bc; bi.Callback_overwrite =ow; // return; } u16 ParentID = bd->GetParentID(); CBoneData* ParrentDT = &LL_GetData(ParentID); CBoneInstance parrent_bi = LL_GetBoneInstance(ParentID); BoneChain_Calculate(ParrentDT, parrent_bi, mask_channel, ignore_callbacks); CLBone(bd, bi, &parrent_bi.mTransform, Blend, mask_channel); //restore callback bi.Callback = bc; bi.Callback_overwrite =ow; // }
void CKinematicsAnimated::Bone_Calculate(CBoneData* bd, Fmatrix *parent) { u16 SelfID = bd->GetSelfID(); CBlendInstance& BLEND_INST = LL_GetBlendInstance(SelfID); CBoneInstance& BONE_INST = LL_GetBoneInstance(SelfID); CLBone(bd,BONE_INST,parent,BLEND_INST.blend_vector(),u8(-1)); // Calculate children for (xr_vector<CBoneData*>::iterator C=bd->children.begin(); C!=bd->children.end(); C++) Bone_Calculate(*C,&BONE_INST.mTransform); }
void CKinematics::RenderWallmark(intrusive_ptr<CSkeletonWallmark> wm, FVF::LIT* &V) { VERIFY(wm); VERIFY(V); VERIFY2(bones,"Invalid visual. Bones already released."); VERIFY2(bone_instances,"Invalid visual. bone_instances already deleted."); if ((wm == 0) || (0==bones) || (0==bone_instances)) return; // skin vertices for (u32 f_idx=0; f_idx<wm->m_Faces.size(); f_idx++){ CSkeletonWallmark::WMFace F = wm->m_Faces[f_idx]; float w = (Device.fTimeGlobal-wm->TimeStart())/LIFE_TIME; for (u32 k=0; k<3; k++){ Fvector P; if (F.bone_id[k][0]==F.bone_id[k][1]){ // 1-link Fmatrix& xform0 = LL_GetBoneInstance(F.bone_id[k][0]).mRenderTransform; xform0.transform_tiny (P,F.vert[k]); }else{ // 2-link Fvector P0,P1; Fmatrix& xform0 = LL_GetBoneInstance(F.bone_id[k][0]).mRenderTransform; Fmatrix& xform1 = LL_GetBoneInstance(F.bone_id[k][1]).mRenderTransform; xform0.transform_tiny (P0,F.vert[k]); xform1.transform_tiny (P1,F.vert[k]); P.lerp (P0,P1,F.weight[k]); } wm->XFORM()->transform_tiny (V->p,P); V->t.set (F.uv[k]); int aC = iFloor ( w * 255.f); clamp (aC,0,255); V->color = color_rgba(128,128,128,aC); V++; } } wm->XFORM()->transform_tiny(wm->m_Bounds.P,wm->m_LocalBounds.P); }
void CKinematicsAnimated::Bone_GetAnimPos(Fmatrix& pos,u16 id,u8 mask_channel, bool ignore_callbacks) { CBoneInstance bi = LL_GetBoneInstance(id); BoneChain_Calculate(&LL_GetData(id),bi,mask_channel,ignore_callbacks); pos.set(bi.mTransform); }
void CKinematics::AddWallmark(const Fmatrix* parent_xform, const Fvector3& start, const Fvector3& dir, ref_shader shader, float size) { Fvector S,D,normal = {0,0,0}; // transform ray from world to model Fmatrix P; P.invert (*parent_xform); P.transform_tiny (S,start); P.transform_dir (D,dir); // find pick point float dist = flt_max; BOOL picked = FALSE; DEFINE_VECTOR (Fobb,OBBVec,OBBVecIt); OBBVec cache_obb; cache_obb.resize (LL_BoneCount()); for (u16 k=0; k<LL_BoneCount(); k++){ CBoneData& BD = LL_GetData(k); if (LL_GetBoneVisible(k)&&!BD.shape.flags.is(SBoneShape::sfNoPickable)){ Fobb& obb = cache_obb[k]; obb.transform (BD.obb,LL_GetBoneInstance(k).mTransform); if (CDB::TestRayOBB(S,D, obb)) for (u32 i=0; i<children.size(); i++) if (LL_GetChild(i)->PickBone(normal,dist,S,D,k)) picked=TRUE; } } if (!picked) return; // calculate contact point Fvector cp; cp.mad (S,D,dist); // collect collide boxes Fsphere test_sphere; test_sphere.set (cp,size); U16Vec test_bones; test_bones.reserve (LL_BoneCount()); for (k=0; k<LL_BoneCount(); k++){ CBoneData& BD = LL_GetData(k); if (LL_GetBoneVisible(k)&&!BD.shape.flags.is(SBoneShape::sfNoPickable)){ Fobb& obb = cache_obb[k]; if (CDB::TestSphereOBB(test_sphere, obb)) test_bones.push_back(k); } } // find similar wm for (u32 wm_idx=0; wm_idx<wallmarks.size(); wm_idx++){ intrusive_ptr<CSkeletonWallmark>& wm = wallmarks[wm_idx]; if (wm->Similar(shader,cp,0.02f)){ if (wm_idx<wallmarks.size()-1) wm = wallmarks.back(); wallmarks.pop_back(); break; } } // ok. allocate wallmark intrusive_ptr<CSkeletonWallmark> wm = xr_new<CSkeletonWallmark>(this,parent_xform,shader,cp,Device.fTimeGlobal); wm->m_LocalBounds.set (cp,size*2.f); wm->XFORM()->transform_tiny (wm->m_Bounds.P,cp); wm->m_Bounds.R = wm->m_Bounds.R; Fvector tmp; tmp.invert (D); normal.add(tmp).normalize (); // build UV projection matrix Fmatrix mView,mRot; BuildMatrix (mView,1/(0.9f*size),normal,cp); mRot.rotateZ (::Random.randF(deg2rad(-20.f),deg2rad(20.f))); mView.mulA_43 (mRot); // fill vertices for (u32 i=0; i<children.size(); i++){ CSkeletonX* S = LL_GetChild(i); for (U16It b_it=test_bones.begin(); b_it!=test_bones.end(); b_it++) S->FillVertices (mView,*wm,normal,size,*b_it); } wallmarks.push_back (wm); }