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 CKinematics::LL_Validate() { // check breakable BOOL bCheckBreakable = FALSE; for (u16 k=0; k<LL_BoneCount(); k++){ if (LL_GetData(k).IK_data.ik_flags.is(SJointIKData::flBreakable)&&(LL_GetData(k).IK_data.type!=jtNone)) { bCheckBreakable = TRUE; break; } } if (bCheckBreakable){ BOOL bValidBreakable = TRUE; #pragma todo("container is created in stack!") xr_vector<xr_vector<u16> > groups; LL_GetBoneGroups (groups); #pragma todo("container is created in stack!") xr_vector<u16> b_parts(LL_BoneCount(),BI_NONE); CBoneData* root = &LL_GetData(LL_GetBoneRoot()); u16 last_id = 0; iBuildGroups (root,b_parts,0,last_id); for (u16 g=0; g<(u16)groups.size(); ++g){ xr_vector<u16>& group = groups[g]; u16 bp_id = b_parts[group[0]]; for (u32 b=1; b<groups[g].size(); b++) if (bp_id!=b_parts[groups[g][b]]){ bValidBreakable = FALSE; break; } } if (bValidBreakable==FALSE){ for (u16 k=0; k<LL_BoneCount(); k++){ CBoneData& BD = LL_GetData(k); if (BD.IK_data.ik_flags.is(SJointIKData::flBreakable)) BD.IK_data.ik_flags.set(SJointIKData::flBreakable,FALSE); } #ifdef DEBUG Msg ("! ERROR: Invalid breakable object: '%s'",*dbg_name); #endif } } }
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); }