void CKinematicsAnimated::IBlendSetup(CBlend& B,u16 part,u8 channel, MotionID motion_ID, BOOL bMixing, float blendAccrue, float blendFalloff, float Speed, BOOL noloop, PlayCallback Callback, LPVOID CallbackParam) { VERIFY(B.channel<MAX_CHANNELS); // Setup blend params if (bMixing) { B.blend = CBlend::eAccrue; B.blendAmount = EPS_S; } else { //B.blend = CBlend::eFixed; B.blend = CBlend::eAccrue; B.blendAmount = 1; } B.blendAccrue = blendAccrue; B.blendFalloff = 0; // blendFalloff used for previous cycles B.blendPower = 1; B.speed = Speed; B.motionID = motion_ID; B.timeCurrent = 0; B.timeTotal = m_Motions[B.motionID.slot].bone_motions[LL_GetBoneRoot()]->at(motion_ID.idx).GetLength(); B.bone_or_part = part; B.stop_at_end = noloop; B.playing = TRUE; B.Callback = Callback; B.CallbackParam= CallbackParam; B.channel = channel; B.fall_at_end = B.stop_at_end && (channel != 0); }
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 CKinematics::Load(const char* N, IReader *data, u32 dwFlags) { //Msg ("skeleton: %s",N); inherited::Load (N, data, dwFlags); pUserData = NULL; m_lod = NULL; // loading lods IReader* LD = data->open_chunk(OGF_S_LODS); if (LD) { string_path short_name; strcpy_s (short_name,sizeof(short_name),N); if (strext(short_name)) *strext(short_name)=0; // From stream { string_path lod_name; LD->r_string (lod_name, sizeof(lod_name)); //. strconcat (sizeof(name_load),name_load, short_name, ":lod:", lod_name.c_str()); m_lod = ::Render->model_CreateChild(lod_name, NULL); VERIFY3(m_lod,"Cant create LOD model for", N); //. VERIFY2 (m_lod->Type==MT_HIERRARHY || m_lod->Type==MT_PROGRESSIVE || m_lod->Type==MT_NORMAL,lod_name.c_str()); /* strconcat (name_load, short_name, ":lod:1"); m_lod = ::Render->model_CreateChild(name_load,LD); VERIFY (m_lod->Type==MT_SKELETON_GEOMDEF_PM || m_lod->Type==MT_SKELETON_GEOMDEF_ST); */ } LD->close (); } #ifndef _EDITOR // User data IReader* UD = data->open_chunk(OGF_S_USERDATA); pUserData = UD?xr_new<CInifile>(UD,FS.get_path("$game_config$")->m_Path):0; if (UD) UD->close(); #endif // Globals bone_map_N = xr_new<accel> (); bone_map_P = xr_new<accel> (); bones = xr_new<vecBones> (); bone_instances = NULL; // Load bones #pragma todo("container is created in stack!") xr_vector<shared_str> L_parents; R_ASSERT (data->find_chunk(OGF_S_BONE_NAMES)); visimask.zero (); int dwCount = data->r_u32(); // Msg ("!!! %d bones",dwCount); // if (dwCount >= 64) Msg ("!!! More than 64 bones is a crazy thing! (%d), %s",dwCount,N); VERIFY3 (dwCount < 64, "More than 64 bones is a crazy thing!",N); for (; dwCount; dwCount--) { string256 buf; // Bone u16 ID = u16(bones->size()); data->r_stringZ (buf,sizeof(buf)); strlwr(buf); CBoneData* pBone = CreateBoneData(ID); pBone->name = shared_str(buf); pBone->child_faces.resize (children.size()); bones->push_back (pBone); bone_map_N->push_back (mk_pair(pBone->name,ID)); bone_map_P->push_back (mk_pair(pBone->name,ID)); // It's parent data->r_stringZ (buf,sizeof(buf)); strlwr(buf); L_parents.push_back (buf); data->r (&pBone->obb,sizeof(Fobb)); visimask.set (u64(1)<<ID,TRUE); } std::sort (bone_map_N->begin(),bone_map_N->end(),pred_sort_N); std::sort (bone_map_P->begin(),bone_map_P->end(),pred_sort_P); // Attach bones to their parents iRoot = BI_NONE; for (u32 i=0; i<bones->size(); i++) { shared_str P = L_parents[i]; CBoneData* B = (*bones)[i]; if (!P||!P[0]) { // no parent - this is root bone R_ASSERT (BI_NONE==iRoot); iRoot = u16(i); B->SetParentID(BI_NONE); continue; } else { u16 ID = LL_BoneID(P); R_ASSERT (ID!=BI_NONE); (*bones)[ID]->children.push_back(B); B->SetParentID(ID); } } R_ASSERT (BI_NONE != iRoot); // Free parents L_parents.clear(); // IK data IReader* IKD = data->open_chunk(OGF_S_IKDATA); if (IKD){ for (u32 i=0; i<bones->size(); i++) { CBoneData* B = (*bones)[i]; u16 vers = (u16)IKD->r_u32(); IKD->r_stringZ (B->game_mtl_name); IKD->r (&B->shape,sizeof(SBoneShape)); B->IK_data.Import(*IKD,vers); Fvector vXYZ,vT; IKD->r_fvector3 (vXYZ); IKD->r_fvector3 (vT); B->bind_transform.setXYZi(vXYZ); B->bind_transform.translate_over(vT); B->mass = IKD->r_float(); IKD->r_fvector3 (B->center_of_mass); } // calculate model to bone converting matrix (*bones)[LL_GetBoneRoot()]->CalculateM2B(Fidentity); IKD->close(); } // after load process { for (u16 child_idx=0; child_idx<(u16)children.size(); child_idx++) LL_GetChild(child_idx)->AfterLoad (this,child_idx); } // unique bone faces { for (u32 bone_idx=0; bone_idx<bones->size(); bone_idx++) { CBoneData* B = (*bones)[bone_idx]; for (u32 child_idx=0; child_idx<children.size(); child_idx++){ CBoneData::FacesVec faces = B->child_faces[child_idx]; std::sort (faces.begin(),faces.end()); CBoneData::FacesVecIt new_end = std::unique(faces.begin(),faces.end()); faces.erase (new_end,faces.end()); B->child_faces[child_idx].clear_and_free(); B->child_faces[child_idx] = faces; } } } // reset update_callback Update_Callback = NULL; // reset update frame wm_frame = u32(-1); LL_Validate (); }