void SimpleSkeletalAnimatedObject_cl::LayerTwoAnimations() { // Layer two animations (using a LayerMixer node). We use this to fade-in an upper body animation // on top of a full body animation. The mixer gets the two animation controls as input and generates // the layered result. The animation tree looks as follows: // // - FinalSkeletalResult // - LayerMixerNode // - SkeletalAnimControl (WalkDagger Animation; influences full body) // - SkeletalAnimControl (RunDagger Animation: influences upper body only) // // The weight of the layered upper body animation is set on the mixer instance. // // Create a new AnimConfig instance VDynamicMesh *pMesh = GetMesh(); VisSkeleton_cl *pSkeleton = pMesh->GetSkeleton(); VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult; VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult); // get skeletal animation sequence VisSkeletalAnimSequence_cl* pAnimSequenceWalkDagger = static_cast<VisSkeletalAnimSequence_cl*>( pMesh->GetSequence("Walk_Dagger", VIS_MODELANIM_SKELETAL)); VisSkeletalAnimSequence_cl* pAnimSequenceDrawDagger = static_cast<VisSkeletalAnimSequence_cl*>( pMesh->GetSequence("Draw_Dagger", VIS_MODELANIM_SKELETAL)); if (pAnimSequenceWalkDagger == NULL || pAnimSequenceDrawDagger == NULL) return; // Create the two animation controls: WalkDagger: full body animation; DrawDagger: upper body animation. // Use a helper function to create the animation controls. VSmartPtr<VisSkeletalAnimControl_cl> spWalkDaggerAnimControl = VisSkeletalAnimControl_cl::Create( pMesh->GetSkeleton(), pAnimSequenceWalkDagger, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true); VSmartPtr<VisSkeletalAnimControl_cl> spDrawDaggerAnimControl = VisSkeletalAnimControl_cl::Create( pMesh->GetSkeleton(), pAnimSequenceDrawDagger, VSKELANIMCTRL_DEFAULTS, 1.0f, true); // create the layer node which layers the two animations m_spLayerMixerNode = new VisAnimLayerMixerNode_cl(pMesh->GetSkeleton()); m_spLayerMixerNode->AddMixerInput(spWalkDaggerAnimControl, 1.0f); int iMixerInputDrawDagger = m_spLayerMixerNode->AddMixerInput(spDrawDaggerAnimControl, 0.0f); // set a per bone weighting list for the DrawDagger (upper body) slot in the mixer. It shall overlay the // upper body of the character and thus only influence the upper body bones. int iBoneCount = pSkeleton->GetBoneCount(); VASSERT(iBoneCount < 256); float fPerBoneWeightingList[256]; memset(fPerBoneWeightingList, 0, sizeof(float)*iBoneCount); pSkeleton->SetBoneWeightRecursive(1.f, pSkeleton->GetBoneIndexByName("skeleton1:Spine"), fPerBoneWeightingList); m_spLayerMixerNode->ApplyPerBoneWeightingMask(iMixerInputDrawDagger, iBoneCount, fPerBoneWeightingList); // finally set the mixer as the root animation node pFinalSkeletalResult->SetSkeletalAnimInput(m_spLayerMixerNode); SetAnimConfig(pConfig); // fade-in the upper body animation //m_spLayerMixerNode->EaseIn(iMixerInputDrawDagger, 0.4f, true); }
void SimpleSkeletalAnimatedObject_cl::ClearData() { SetAnimConfig(NULL); m_spNormalizeMixerNode = NULL; m_spLayerMixerNode = NULL; m_spSingleAnimControl = NULL; m_spBoneModifierNode = NULL; m_fBoneHighlightDuration = 0.f; V_SAFE_REMOVE(m_pLookAtTarget); m_fLookAtRotationPhase = 0.f; }
void AnimatedWarrior_cl::SetEnabled(bool bEnabled) { if (m_bEnabled == bEnabled) return; m_bEnabled = bEnabled; if (!m_bModelValid) return; #if defined(USE_HAVOK) // Turn on/off character controller if (m_pCharacterController != NULL) m_pCharacterController->SetEnabled(bEnabled ? TRUE : FALSE); #endif VisAnimConfig_cl* pAnimConfig = GetAnimConfig(); if (bEnabled) { m_spAnimConfig = GetAnimConfig(); if (m_spAnimConfig == NULL) { m_spAnimConfig = VisAnimConfig_cl::CreateSkeletalConfig(GetMesh()); SetAnimConfig(m_spAnimConfig); } if (m_spAnimConfig->GetFinalResult() != NULL) m_spAnimConfig->GetFinalResult()->SetSkeletalAnimInput(m_spLayerMixer); // Resume animation controls for (int i = 0; i < UPPERBODY_CONTROLCOUNT; i++) m_spUpperBodyControls[i]->Resume(); for (int i = 0; i < m_FullBodyControlList.Count(); i++) m_FullBodyControlList.GetAt(i)->Resume(); } else { // Pause animation controls for (int i = 0; i < UPPERBODY_CONTROLCOUNT; i++) m_spUpperBodyControls[i]->Pause(); for (int i = 0; i < m_FullBodyControlList.Count(); i++) m_FullBodyControlList.GetAt(i)->Pause(); if (m_spAnimConfig != NULL && m_spAnimConfig->GetFinalResult() != NULL) m_spAnimConfig->GetFinalResult()->SetSkeletalAnimInput(NULL); } }
void SimpleSkeletalAnimatedObject_cl::SetActivate(bool bStatus) { SetCastShadows(bStatus); SetVisibleBitmask(bStatus ? 0xffffffff : 0); if (m_pLookAtTarget != NULL) m_pLookAtTarget->SetVisibleBitmask(bStatus ? 0xffffffff : 0); if (bStatus) { SetMode(m_eSampleMode); } else { SetAnimConfig(NULL); } }
void SimpleSkeletalAnimatedObject_cl::ForwardKinematics() { // Apply forward kinematics to the head "Neck" bone, using a bone modifier node. The bone modifier // gets a skeletal animation as input, modifies the translation of the neck bone and generates the // combined result. The animation tree looks as follows: // // - FinalSkeletalResult // - BoneModifierNode (modifies the neck bone) // - SkeletalAnimControl (Walk Animation) // // The translation of the neck bone is set on the bone modifier node. // // Create a new AnimConfig instance VDynamicMesh *pMesh = GetMesh(); VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult; VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult); // Get skeletal animation sequence. VisSkeletalAnimSequence_cl* pAnimSequenceWalk = static_cast<VisSkeletalAnimSequence_cl*>(pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL)); if (pAnimSequenceWalk == NULL) return; // Create the animation control to play the walk animation (via a helper function). VSmartPtr<VisSkeletalAnimControl_cl> spWalkAnimControl = VisSkeletalAnimControl_cl::Create( pMesh->GetSkeleton(), pAnimSequenceWalk, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true); // Create the bone modifier node that translates the head bone. Set the animation control instance // as the input for this node. m_spBoneModifierNode = new VisAnimBoneModifierNode_cl(pMesh->GetSkeleton()); m_spBoneModifierNode->SetModifierInput(spWalkAnimControl); hkvQuat customBoneRotation; // set the neck bone translation on the bone modifier node m_iNeckBoneIndex = pMesh->GetSkeleton()->GetBoneIndexByName("skeleton1:Neck"); customBoneRotation.setFromEulerAngles (0, -45, 0); m_spBoneModifierNode->SetCustomBoneRotation(m_iNeckBoneIndex, customBoneRotation, VIS_MODIFY_BONE); // finally set the bone modifier as the root animation node pFinalSkeletalResult->SetSkeletalAnimInput(m_spBoneModifierNode); SetAnimConfig(pConfig); // The bone modifier node is now part of the animation tree. You can at any time update the translation // on the bone modifier. The animation system will take care of generating the proper final result. }
void SimpleSkeletalAnimatedObject_cl::BlendTwoAnimations() { // Blend two animations using a NormalizeMixer node. The mixer gets the two animations as input // and generates the blended result. The animation tree looks as follows: // // - FinalSkeletalResult // - NormalizeMixerNode // - SkeletalAnimControl (Walk Animation) // - SkeletalAnimControl (Run Animation) // // The weights of the two animations are set on the mixer instance. // // create a new AnimConfig instance VDynamicMesh *pMesh = GetMesh(); VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult; VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult); // get skeletal animation sequence VisSkeletalAnimSequence_cl* pAnimSequenceWalk = static_cast<VisSkeletalAnimSequence_cl*>( pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL)); VisSkeletalAnimSequence_cl* pAnimSequenceRun = static_cast<VisSkeletalAnimSequence_cl*>( pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL)); if(pAnimSequenceWalk == NULL || pAnimSequenceRun == NULL) return; // create two animation controls: walk and run (use a helper function for creating them) VSmartPtr<VisSkeletalAnimControl_cl> spWalkAnimControl = VisSkeletalAnimControl_cl::Create( pMesh->GetSkeleton(), pAnimSequenceWalk, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true); VSmartPtr<VisSkeletalAnimControl_cl> spRunAnimControl = VisSkeletalAnimControl_cl::Create( pMesh->GetSkeleton(), pAnimSequenceRun, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true); // create the mixer node that blends the two animations // (set initial weight to show walk animation only) m_spNormalizeMixerNode = new VisAnimNormalizeMixerNode_cl(pMesh->GetSkeleton()); m_iMixerInputWalk = m_spNormalizeMixerNode->AddMixerInput(spWalkAnimControl, 1.0f); m_iMixerInputRun = m_spNormalizeMixerNode->AddMixerInput(spRunAnimControl, 0.0f); // finally set the mixer as the root animation node pFinalSkeletalResult->SetSkeletalAnimInput(m_spNormalizeMixerNode); SetAnimConfig(pConfig); // blend from walk to run SetBlendWalkToRun(true); }
bool ClothEntity_cl::SetMeshModel(const char *szModelfile, const hkvVec3& vScaling, VString *pszError) { VThreadedTask *pTask = GetPreparationTask(); WAIT_UNTIL_FINISHED(pTask); m_vCurrentScaling = vScaling; bool bStatus = true; if (!szModelfile || !szModelfile[0]) { m_spMesh = NULL; SetPreparationTask(NULL); V_SAFE_DELETE(pTask); return true; } else { const char *szCurrentModel = ""; if (GetMesh()) szCurrentModel = GetMesh()->GetFilename(); // set new API model if (_stricmp(szCurrentModel,szModelfile)!=0) SetMesh(szModelfile); m_spMesh = new VClothMesh(); if (!m_spMesh->CreateFromEntityModel(this,m_vCurrentScaling)) { m_spMesh = NULL; bStatus = false; } } //// model changed so we need to create a new anim config VisAnimConfig_cl *pAnimConfig = new VisAnimConfig_cl(GetMesh()); // add modifier to vertex deformer stacks VisVertexDeformerStack_cl *pVertexDeformerStack = new VisVertexDeformerStack_cl(); pAnimConfig->SetVertexDeformerStack(pVertexDeformerStack); VisClothDeformer_cl* pClothDeformer = new VisClothDeformer_cl(pVertexDeformerStack, m_spMesh,this); pVertexDeformerStack->AddDeformer(pClothDeformer); SetAnimConfig(pAnimConfig); #if defined(_VISION_PSP2) pAnimConfig->SetSkinningMode(VIS_SKINNINGMODE_SOFTWARE); #endif if (m_spMesh) SetCurrentVisBoundingBox(m_spMesh->GetBoundingBox()); if (!bStatus && pszError) *pszError = VClothMesh::GetLastError(); if (pTask!=NULL) { WAIT_UNTIL_FINISHED(pTask); SetPreparationTask(NULL); V_SAFE_DELETE(pTask); } SetPreparationTask(new ClothMeshPhysicsTask_cl(m_spMesh)); return bStatus; }