Ejemplo n.º 1
0
// **************************************************
//            SETUP ANIMATIONS
// **************************************************
void TransitionCharacter_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pMesh = GetMesh();
  VVERIFY_OR_RET(pMesh);

  // idle animations
  m_spSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE]);

  // run animations
  m_spSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN]);

  // walk animations
  m_spSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK]);

  // turn animations
  m_spSkeletalSequenceList[ANIMID_TURN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN]);

  // walk backwards animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS]);

  m_bModelValid = true;
}
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);
}
Ejemplo n.º 3
0
// **************************************************
//            SETUP ANIMATIONS
// **************************************************
void TransitionBarbarian_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pModel = GetMesh();
  VVERIFY_OR_RET(pModel);

  m_pSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_IDLE]);

  m_pSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_WALK]);

  m_pSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_RUN]);

  m_bModelValid = true;
}
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);
}
Ejemplo n.º 5
0
void MergedModelFactory_cl::PreviewModel()
{
  DeleteModels();

  m_pPreviewModelEntities = new VisBaseEntity_cl*[BARBARIAN_MAX];
  m_pPreviewModelEntities[BARBARIAN_BODY] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Body.model");
  m_pPreviewModelEntities[BARBARIAN_ARM] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Arm.model");
  m_pPreviewModelEntities[BARBARIAN_SHOULDER] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Shoulder.model");
  m_pPreviewModelEntities[BARBARIAN_LEGS] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Legs.model");
  m_pPreviewModelEntities[BARBARIAN_KNEE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Knee.model");
  m_pPreviewModelEntities[BARBARIAN_ACCESSOIRE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Accessoire.model");
  m_pPreviewModelEntities[BARBARIAN_BELT] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Belt.model");
  m_pPreviewModelEntities[BARBARIAN_CLOTH] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Cloth.model");
  m_pPreviewModelEntities[BARBARIAN_BEARD] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Beard.model");
  m_pPreviewModelEntities[BARBARIAN_AXE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Axe.model");
  m_pPreviewModelEntities[BARBARIAN_SWORD] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Sword.model");

  // Setup animation system
  VDynamicMesh* pBodyMesh = m_pPreviewModelEntities[BARBARIAN_BODY]->GetMesh();
  VisSkeletalAnimSequence_cl* pSequence = static_cast<VisSkeletalAnimSequence_cl*>(pBodyMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL));

  // Create shared skeletal anim control to animate all models in sync
  VisSkeletalAnimControl_cl* pSkeletalAnimControl = 
    VisSkeletalAnimControl_cl::Create(pBodyMesh->GetSkeleton(), pSequence, VSKELANIMCTRL_DEFAULTS | VANIMCTRL_LOOP);

  for (int i = 0; i < BARBARIAN_MAX; i++)
  {
    // Create anim config per entity
    VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult = NULL;
    VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(m_pPreviewModelEntities[i]->GetMesh(), &pFinalSkeletalResult);
    pConfig->SetFlags(pConfig->GetFlags() | APPLY_MOTION_DELTA);

    // Anim config uses shared skeletal anim control as input
    pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);

    m_pPreviewModelEntities[i]->SetAnimConfig(pConfig);
    m_pPreviewModelEntities[i]->SetPosition(m_vPos);
    m_pPreviewModelEntities[i]->SetOrientation(m_vOri);
#ifndef _VISION_PSP2
    m_pPreviewModelEntities[i]->SetCastShadows(TRUE);
#endif
  }

  m_pCameraEntity->AttachToParent(m_pPreviewModelEntities[BARBARIAN_BODY]);
  m_pPlayerCamera->ResetOldPosition();
  m_pPlayerCamera->Follow = true;
  m_pPlayerCamera->Zoom = false;
  m_pPlayerCamera->InitialYaw = -90.f;

  
  UpdatePreview();
}
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.
}
BOOL VLineFollowerComponent::StartAnimation(const char *szAnimName)
{
  VisBaseEntity_cl* pOwner = (VisBaseEntity_cl *)GetOwner();
  if (!pOwner)
    return false;

  m_bPlayingAnim = false;

  // Check for animation sequences
  VDynamicMesh *pMesh = pOwner->GetMesh();
  if (!pMesh || !pMesh->GetSequenceSetCollection() || !pMesh->GetSequenceSetCollection()->GetSequenceSetCount())
    return false;

  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult = NULL;
  VisVertexAnimDeformer_cl* pVertexAnimDeformer = NULL;

  // Get the sequence(s) for vertex and skeletal animation
  VisSkeletalAnimSequence_cl* pAnimSequenceSkeletal = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_SKELETAL);
  VisVertexAnimSequence_cl* pAnimSequenceVertex = (VisVertexAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_VERTEX);

  // If no sequence with the given name is present
  if ((!pAnimSequenceSkeletal) && (!pAnimSequenceVertex))
  {
    VisAnimSequenceSet_cl * pSequenceSet =  pMesh->GetSequenceSetCollection()->GetSequenceSet(0);
    // Find the first skeletal or vertex animation and use it
    for (int i=0; i< pSequenceSet->GetSequenceCount(); ++i)
    {
      VisAnimSequence_cl* pTempAnimSequence = pSequenceSet->GetSequence(i);
      if (pTempAnimSequence->GetType() == VIS_MODELANIM_SKELETAL)
      {
        // If it is a skeletal animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);
        VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), (VisSkeletalAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
      else if (pTempAnimSequence->GetType() == VIS_MODELANIM_VERTEX)
      {
        // If it is a vertex animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);
        VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create((VisVertexAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
    }
    // If neither a skeletal nor a vertex animation has been found, report failure
    return false;
  }

  // If both a vertex and a skeletal animation with the given name has been found
  // create a combined config for skeletal and vertex animation.
  VisAnimConfig_cl* pConfig = NULL;
  if ((pAnimSequenceSkeletal) && (pAnimSequenceVertex))
    pConfig = VisAnimConfig_cl::CreateSkeletalVertexConfig(pMesh, &pFinalSkeletalResult, &pVertexAnimDeformer);

  // If it is just a skeletal animation, create a config for it
  if (pAnimSequenceSkeletal)
  {    
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

    // If a skeletal animation has been found create a control for it
    VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), pAnimSequenceSkeletal, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set it as the input for the final skeletal result
    pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
  }

  // If it is just a vertex animation, create a config for it
  if (pAnimSequenceVertex)
  {
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);

    // If a vertex animation has been found create a control for it
    VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create(pAnimSequenceVertex, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set add it to the vertex anim deformer
    pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
  }

  // Set the current config
  pOwner->SetAnimConfig(pConfig);

  // Make sure we get the motion delta from the animation
  pOwner->GetAnimConfig()->SetFlags(pOwner->GetAnimConfig()->GetFlags() | APPLY_MOTION_DELTA | MULTITHREADED_ANIMATION);

  // And report success
  m_bPlayingAnim = true;
  return true;
}
Ejemplo n.º 8
0
void AnimatedWarrior_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pMesh = GetMesh();
  VVERIFY_OR_RET(pMesh);
  VisAnimEventList_cl *pEventList = NULL;

  // idle animations
  m_spSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE]);
  m_spSkeletalSequenceList[ANIMID_IDLE_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle_Look_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE_TORCH]);

  // run animation
  m_spSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN]);
  pEventList = m_spSkeletalSequenceList[ANIMID_RUN]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.396f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // run with torch animation
  m_spSkeletalSequenceList[ANIMID_RUN_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN_TORCH]);
  pEventList = m_spSkeletalSequenceList[ANIMID_RUN_TORCH]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.396f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // walk animation
  m_spSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK]);
  pEventList = m_spSkeletalSequenceList[ANIMID_WALK]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.495f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // walk with torch animation
  m_spSkeletalSequenceList[ANIMID_WALK_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK_TORCH]);
  pEventList = m_spSkeletalSequenceList[ANIMID_WALK_TORCH]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.495f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);
 
  // turn animation
  m_spSkeletalSequenceList[ANIMID_TURN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN]);

  // turn with torch animation
  m_spSkeletalSequenceList[ANIMID_TURN_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN_TORCH]);

  // walk backwards animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD_V2", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS]);

  // walk backwards with torch animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD_Torch_V2", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS_TORCH]);

  // upper body animations (torch)
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Draw_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->GetLength(), EVENT_ANIM_UPPERBODY_ARMING_FINISHED);

  m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Holster_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->GetLength(), EVENT_ANIM_UPPERBODY_DISARMING_FINISHED);
   
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Strike_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->GetLength(), EVENT_ANIM_UPPERBODY_ATTACK_FINISHED);

  m_bModelValid = true;
}