BVB Source Codes

CRYENGINE Show PoseAligner.cpp Source code

Return Download CRYENGINE: download PoseAligner.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include <CryExtension/CryCreateClassInstance.h>
  6. #include <CryExtension/ClassWeaver.h>
  7. #include <CryAnimation/ICryAnimation.h>
  8.  
  9. #include "PoseAligner.h"
  10.  
  11. #define UNKNOWN_GROUND_HEIGHT -1E10f
  12.  
  13. namespace {
  14.  
  15. bool GetGroundFromEntity(const IEntity& entity, float& height, Vec3& normal)
  16. {
  17.  
  18.         height = entity.GetWorldPos().z;
  19.         normal = Vec3(0.0f, 0.0f, 1.0f);
  20.  
  21.         IPhysicalEntity* pPhysEntity = entity.GetPhysics();
  22.         bool bHeightValid = false;
  23.         if (pPhysEntity && pPhysEntity->GetType() == PE_LIVING)
  24.         {
  25.                 pe_status_living status;
  26.                 pPhysEntity->GetStatus(&status);
  27.                 height = status.groundHeight;
  28.                 normal = status.groundSlope;
  29.                 bHeightValid = (height != UNKNOWN_GROUND_HEIGHT) && (height != -1e-10f);
  30.         }
  31.  
  32.         return bHeightValid;
  33. }
  34.  
  35. Vec3 ComputeAnimationMovementPlaneNormal(const ISkeletonAnim& skeletonAnim, const Vec3& defaultNormal)
  36. {
  37.         const QuatT movement = skeletonAnim.GetRelMovement();
  38.         if (movement.t.GetLengthSquared() > 0.0001f)
  39.         {
  40.                 Vec3 movementDirection = movement.t.GetNormalized();
  41.                 if (::fabs(movementDirection.z) > 0.0001f)
  42.                 {
  43.                         Vec3 v(movementDirection.x, movementDirection.y, 0.0f);
  44.                         v.Normalize();
  45.  
  46.                         Vec3 normal = movementDirection.Cross(v).GetNormalized().Cross(movementDirection);
  47.                         if (normal.z < 0.0f)
  48.                                 normal = -normal;
  49.                         return normal;
  50.                 }
  51.         }
  52.         return defaultNormal;
  53. }
  54.  
  55. class CProceduralBlend
  56. {
  57. public:
  58.         CProceduralBlend() :
  59.                 m_elevation(0.3f),
  60.                 m_elevationScale(1.0f / 0.3f),
  61.                 m_rangeStart(0.0f),
  62.                 m_rangeEnd(0.2f)
  63.         {
  64.         }
  65.  
  66. public:
  67.         float ComputeBlendWeight(float value) const
  68.         {
  69.                 float w = (value - m_rangeStart) / (m_rangeEnd - m_rangeStart) * m_elevationScale;
  70.                 return clamp_tpl(1.0f - w, 0.0f, 1.0f);
  71.         }
  72.  
  73. public:
  74.         float m_elevation;
  75.         float m_elevationScale;
  76.         float m_rangeStart;
  77.         float m_rangeEnd;
  78. };
  79.  
  80. } // namespace
  81.  
  82. namespace PoseAligner {
  83.  
  84. CVars::CVars()
  85. {
  86.         REGISTER_CVAR2("a_poseAlignerEnable", &m_enable, 1, VF_NULL, "Enable PoseAligner.");
  87.         REGISTER_CVAR2("a_poseAlignerDebugDraw", &m_debugDraw, 0, VF_NULL, "Enable PoseAligner debug drawing.");
  88.         REGISTER_CVAR2("a_poseAlignerForceTargetSmoothing", &m_forceTargetSmoothing, 0, VF_NULL, "PoseAligner forces smoothing of target position and normal.");
  89.         REGISTER_CVAR2("a_poseAlignerForceNoRootOffset", &m_forceNoRootOffset, 0, VF_NULL, "PoseAligner forces no root offset.");
  90.         REGISTER_CVAR2("a_poseAlignerForceNoIntersections", &m_forceNoIntersections, 0, VF_NULL, "PoseAligner forces no intersections, might make animation more 'poppy'.");
  91.         REGISTER_CVAR2("a_poseAlignerForceLock", &m_forceLock, 0, VF_NULL, "PoseAligner force lock.");
  92.         REGISTER_CVAR2("a_poseAlignerForceWeightOne", &m_forceWeightOne, 0, VF_NULL, "PoseAligner forces targeting weight to always be one.");
  93.  
  94. }
  95.  
  96. /*
  97.    CContactRaycast
  98.  */
  99.  
  100. CContactRaycast::CContactRaycast(IEntity& entity) :
  101.         m_pEntity(&entity),
  102.         m_length(3.0f)
  103. {
  104. }
  105.  
  106. //
  107.  
  108. bool CContactRaycast::Update(Vec3& position, Vec3& normal)
  109. {
  110.         QuatT location(m_pEntity->GetWorldRotation(), m_pEntity->GetWorldPos());
  111.  
  112.         Vec3 positionPrevious = position;
  113.         Vec3 positionPreviousGlobal = positionPrevious;
  114.  
  115.         Vec3 rayPosition = positionPreviousGlobal;
  116.         rayPosition.z += m_length;
  117.  
  118.         IPhysicalEntity* pEntityPhysics = m_pEntity->GetPhysics();
  119.         ray_hit hit;
  120.         int hitCount = 0;
  121.         const int MAX_SKIP_ENT = 4;
  122.         IPhysicalEntity* pSkipEntities[MAX_SKIP_ENT];
  123.  
  124.         // Always include self
  125.         pSkipEntities[0] = pEntityPhysics;
  126.  
  127.         if (IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_pEntity ? m_pEntity->GetId() : -1))
  128.         {
  129.                 // Always include self + any other optional entities actor would like to ignore
  130.                 int nSkip = pActor->GetPhysicalSkipEntities(pEntityPhysics ? &pSkipEntities[1] : pSkipEntities, pEntityPhysics ? MAX_SKIP_ENT - 1 : MAX_SKIP_ENT);
  131.                 if (pEntityPhysics)
  132.                 {
  133.                         ++nSkip;
  134.                 }
  135.  
  136.                 hitCount = gEnv->pPhysicalWorld->RayWorldIntersection(
  137.                   rayPosition, Vec3(0.0f, 0.0f, -m_length * 2.0f),
  138.                   ent_rigid | ent_sleeping_rigid | ent_static | ent_terrain,
  139.                   rwi_stop_at_pierceable,
  140.                   &hit, 1, pSkipEntities, nSkip);
  141.         }
  142.         else
  143.         {
  144.                 hitCount = gEnv->pPhysicalWorld->RayWorldIntersection(
  145.                   rayPosition, Vec3(0.0f, 0.0f, -m_length * 2.0f),
  146.                   ent_rigid | ent_sleeping_rigid | ent_static | ent_terrain,
  147.                   rwi_stop_at_pierceable,
  148.                   &hit, 1, &pEntityPhysics, pEntityPhysics ? 1 : 0);
  149.         }
  150.  
  151.         if (hitCount > 0)
  152.         {
  153.                 position.z = hit.pt.z;
  154.                 normal = Vec3(hit.n.x, hit.n.y, fabsf(hit.n.z));
  155.                 normal.NormalizeSafe(Vec3(0.0f, 0.0f, 1.0f));
  156.         }
  157.  
  158.         //
  159.  
  160. #ifndef _RELEASE
  161.         if (CVars::GetInstance().m_debugDraw)
  162.         {
  163.                 SAuxGeomRenderFlags flags = gEnv->pRenderer->GetIRenderAuxGeom()->GetRenderFlags();
  164.                 flags.SetDepthTestFlag(e_DepthTestOff);
  165.                 gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(flags);
  166.  
  167.                 gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(hit.pt, 0.05f, ColorB(0xff, 0xff, 0x00, 0xff));
  168.                 gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(positionPreviousGlobal, 0.05f, ColorB(0xff, 0x00, 0xff, 0xff));
  169.  
  170.                 gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(
  171.                   rayPosition, ColorB(0xff, 0xff, 0xff, 0xff),
  172.                   rayPosition + Vec3(0.0f, 0.0f, -m_length * 2.0f), ColorB(0xff, 0xff, 0xff, 0xff));
  173.  
  174.                 //              Plane plane = Plane::CreatePlane(
  175.                 //                      location.q * (normal * location.q),
  176.                 //                      location * (location.GetInverted() * position));
  177.                 //              Ray ray(rayPosition, Vec3(0.0f, 0.0f, -m_length * 2.0f));
  178.                 //              Vec3 p;
  179.                 //              if (Intersect::Ray_Plane(ray, plane, p))
  180.                 //              {
  181.                 ////                    gEnv->pRenderer->GetIRenderAuxGeom()->DrawCone(
  182.                 ////                            p, normal, 0.1f, 0.5f, ColorB(0xff, 0xff, 0x00, 0xff), true);
  183.                 //              }
  184.         }
  185. #endif //_RELEASE
  186.  
  187.         return hitCount > 0;
  188. }
  189.  
  190. /*
  191.    CChain
  192.  */
  193.  
  194. CChainPtr CChain::Create(const SChainDesc& desc)
  195. {
  196.         if (!desc.IsValid())
  197.                 return CChainPtr();
  198.  
  199.         CChainPtr chain = new CChain();
  200.         chain->m_desc = desc;
  201.         return chain;
  202. }
  203.  
  204. CChain::CChain()
  205. {
  206.         m_targetPositionAnimation = QuatT(IDENTITY);
  207.         Reset();
  208. }
  209.  
  210. //
  211.  
  212. void CChain::Reset()
  213. {
  214.         m_targetPosition = Vec3(-99999.0f, -99999.0f, -99999.0f);
  215.         m_targetPositionFiltered = Vec3(-99999.0f, -99999.0f, -99999.0f);
  216.         m_targetPositionFilteredSmoothRate = Vec3(ZERO);
  217.  
  218.         m_targetNormal = Vec3(0.0f, 0.0f, 1.0f);
  219.         m_targetNormalFiltered = Vec3(0.0f, 0.0f, 1.0f);
  220.         m_targetNormalFilteredSmoothRate = Vec3(ZERO);
  221.  
  222.         m_targetBlendWeight = 0.0f;
  223.         m_targetBlendWeightAnimated = 0.0f;
  224.         m_targetBlendWeightFiltered = 0.0f;
  225.         m_targetBlendWeightFilteredSmoothRate = 0.0f;
  226.  
  227.         m_targetDelta = Vec3(ZERO);
  228.  
  229.         m_bTargetIntersecting = false;
  230.  
  231.         m_bTargetLock = false;
  232.  
  233.         m_bTargetForceWeightOne = false;
  234.  
  235.         m_animationSlopeNormal = Vec3(0.0f, 0.0f, 1.0f);
  236.         m_animationSlopeNormalFiltered = m_animationSlopeNormal;
  237.         m_animationSlopeNormalFilteredSmoothRate = Vec3(ZERO);
  238. }
  239.  
  240. void CChain::UpdateFromAnimations(ICharacterInstance& character, const QuatT& location, const float time)
  241. {
  242.         m_animationSlopeNormal = ComputeAnimationMovementPlaneNormal(*character.GetISkeletonAnim(), Vec3(0.0f, 0.0f, 1.0f));
  243.         SmoothCD(m_animationSlopeNormalFiltered, m_animationSlopeNormalFilteredSmoothRate, time, m_animationSlopeNormal, 0.01f);
  244.         m_animationSlopeNormalFiltered.NormalizeSafe(Vec3(0.0f, 0.0f, 1.0f));
  245. }
  246.  
  247. void CChain::FindContact(const QuatT& location)
  248. {
  249.         Vec3 targetPositionPrevious = m_targetPosition;
  250.  
  251.         m_targetPosition = location * m_targetPositionAnimation.t;
  252.         m_targetNormal = Vec3(0.0f, 0.0f, 1.0f);
  253.  
  254.         float projectedDifference = (Vec2(m_targetPosition) - Vec2(targetPositionPrevious)).GetLength();
  255.         if (projectedDifference < 0.05f)
  256.         {
  257.                 m_targetPosition.x = targetPositionPrevious.x;
  258.                 m_targetPosition.y = targetPositionPrevious.y;
  259.         }
  260.  
  261.         if (!m_desc.pContactReporter)
  262.         {
  263.                 m_targetBlendWeight = 0.0f;
  264.                 return;
  265.         }
  266.  
  267.         Vec3 targetPositionNew = m_targetPosition;
  268.         Vec3 targetNormalNew(0.0f, 0.0f, 1.0f);
  269.         bool bContact = m_desc.pContactReporter->Update(targetPositionNew, targetNormalNew);
  270.  
  271.         if (bContact)
  272.         {
  273.                 targetPositionNew += m_animationSlopeNormalFiltered * m_animationSlopeNormalFiltered.Dot(m_targetPositionAnimation.t);
  274.  
  275.                 m_bTargetIntersecting = m_targetPosition.z < targetPositionNew.z;
  276.                 if (m_bTargetIntersecting)
  277.                 {
  278.                         m_targetBlendWeight = 1.0f;
  279.                 }
  280.                 else if (m_desc.bBlendProcedural)
  281.                 {
  282.                         CProceduralBlend proceduralBlend;
  283.                         m_targetBlendWeight = proceduralBlend.ComputeBlendWeight(m_targetPositionAnimation.t.z);
  284.                 }
  285.  
  286.                 m_targetDelta.z = targetPositionNew.z - m_targetPosition.z;
  287.         }
  288.         else
  289.         {
  290.                 m_targetBlendWeight = 0.0f;
  291.                 m_bTargetIntersecting = false;
  292.                 targetPositionNew.z = location.t.z;
  293.                 m_targetDelta.z = 0.0f;
  294.         }
  295.  
  296. #if 1
  297.         // TODO: Better code to handle custom slope angle limits!
  298.         Vec3 proj = Vec3(targetNormalNew.x, targetNormalNew.y, 0);
  299.         if (proj.GetLength() > 0.1f)
  300.         {
  301.                 f32 slopeAngleMax = DEG2RAD(30.0f);
  302.                 proj.Normalize();
  303.                 f32 slopeAngle = acos_tpl(targetNormalNew.z);
  304.                 Vec3 cross = (Vec3(0.0f, 0.0f, 1.0f) % targetNormalNew).GetNormalized();
  305.                 if (slopeAngle > slopeAngleMax)
  306.                         targetNormalNew = Quat::CreateRotationAA(slopeAngleMax, cross) * Vec3(0.0f, 0.0f, 1.0f);
  307.         }
  308. #endif
  309.  
  310.         m_targetPosition = targetPositionNew;
  311.         m_targetNormal = targetNormalNew;
  312. }
  313.  
  314. void CChain::FilterTargetLocation(const float time)
  315. {
  316.         const float smoothTime = m_targetPosition.z > m_targetPositionFiltered.z ? 0.08f : 0.1f;
  317.  
  318.         SmoothCD(m_targetNormalFiltered, m_targetNormalFilteredSmoothRate, time, m_targetNormal, smoothTime);
  319.         m_targetNormal.NormalizeSafe(Vec3(0.0f, 0.0f, 1.0f));
  320.  
  321.         if (!m_desc.bTargetSmoothing && !CVars::GetInstance().m_forceTargetSmoothing)
  322.         {
  323.                 m_targetPositionFiltered = m_targetPosition;
  324.                 m_targetPositionFilteredSmoothRate = ZERO;
  325.  
  326.                 return;
  327.         }
  328.  
  329.         SmoothCD(m_targetPositionFiltered, m_targetPositionFilteredSmoothRate, time, m_targetPosition, smoothTime);
  330. }
  331.  
  332. float CChain::ComputeTargetBlendValue(ISkeletonPose& skeletonPose, const float time, const float weight)
  333. {
  334.         m_targetBlendWeightAnimated = -1.0f;
  335.         if (m_desc.targetBlendJointIndex > -1)
  336.         {
  337.                 const QuatT& transformation = skeletonPose.GetRelJointByID(m_desc.targetBlendJointIndex);
  338.                 m_targetBlendWeightAnimated = transformation.t.x;
  339.         }
  340.  
  341.         // Force the target to always be in a non-intersected state with the traced
  342.         // environment. Might result in animation popping.
  343.         const bool bTargetForceWeightOne = m_bTargetForceWeightOne || CVars::GetInstance().m_forceWeightOne;
  344.         if ((m_bTargetIntersecting && (m_desc.bForceNoIntersection || CVars::GetInstance().m_forceNoIntersections)) ||
  345.             bTargetForceWeightOne)
  346.         {
  347.                 m_targetBlendWeight = 1.0f;
  348.                 m_targetBlendWeightFiltered = m_targetBlendWeight;
  349.                 m_targetBlendWeightFilteredSmoothRate = 0.0f;
  350.                 return m_targetBlendWeight;
  351.         }
  352.  
  353.         if (m_targetBlendWeightAnimated > -0.5f)
  354.         {
  355.                 m_targetBlendWeight = clamp_tpl(m_targetBlendWeightAnimated, 0.0f, 1.0f);
  356.                 m_targetBlendWeightFiltered = m_targetBlendWeight;
  357.                 m_targetBlendWeightFilteredSmoothRate = 0.0f;
  358.         }
  359.  
  360.         SmoothCD(m_targetBlendWeightFiltered, m_targetBlendWeightFilteredSmoothRate, time, m_targetBlendWeight, 0.1f);
  361.         m_targetBlendWeightFiltered *= weight;
  362.         return m_targetBlendWeightFiltered;
  363. }
  364.  
  365. bool CChain::ComputeRootOffsetExtents(float& offsetMin, float& offsetMax)
  366. {
  367.         offsetMin = m_targetDelta.z - m_desc.offsetMin.z;
  368.         if (offsetMin < -m_desc.offsetMax.z)
  369.                 offsetMin = -m_desc.offsetMax.z;
  370.  
  371.         offsetMax = m_targetDelta.z - m_desc.offsetMax.z;
  372.         if (offsetMax > -m_desc.offsetMin.z)
  373.                 offsetMax = -m_desc.offsetMin.z;
  374.  
  375.         return true;
  376. }
  377.  
  378. bool CChain::SetupStoreOperators(IAnimationOperatorQueue& operatorQueue)
  379. {
  380.         operatorQueue.PushComputeAbsolute();
  381.         operatorQueue.PushStoreAbsolute(m_desc.contactJointIndex, m_targetPositionAnimation);
  382.         return true;
  383. }
  384.  
  385. bool CChain::SetupTargetPoseModifiers(const QuatT& location, const Vec3& limitOffset, ISkeletonAnim& skeletonAnim)
  386. {
  387.         bool bTargetLock = m_bTargetLock || CVars::GetInstance().m_forceLock;
  388.         if (!(m_targetBlendWeightFiltered > 0.0f) && !bTargetLock)
  389.                 return true;
  390.  
  391.         if (!m_pPoseAlignerChain)
  392.                 ::CryCreateClassInstance<IAnimationPoseAlignerChain>("AnimationPoseModifier_PoseAlignerChain", m_pPoseAlignerChain);
  393.         if (!m_pPoseAlignerChain)
  394.                 return false;
  395.  
  396.         const Vec3& planeNormal = (m_targetNormalFiltered * location.q).GetNormalized();
  397.         Plane plane = Plane::CreatePlane(planeNormal, location.GetInverted() * m_targetPositionFiltered);
  398.  
  399.         m_pPoseAlignerChain->Initialize(m_desc.solver, m_desc.contactJointIndex);
  400.         IAnimationPoseAlignerChain::STarget target;
  401.         target.plane = plane;
  402.         target.distance = 6.0f;
  403.         target.offsetMin = m_desc.offsetMin.z + limitOffset.z;
  404.         target.offsetMax = m_desc.offsetMax.z + limitOffset.z;
  405.         target.targetWeight = bTargetLock ? 1.0f : m_targetBlendWeightFiltered;
  406.         target.alignWeight = target.targetWeight;
  407.  
  408.         m_pPoseAlignerChain->SetTarget(target);
  409.         m_pPoseAlignerChain->SetTargetLock(bTargetLock ?
  410.                                            IAnimationPoseAlignerChain::eLockMode_Apply : IAnimationPoseAlignerChain::eLockMode_Store);
  411.         skeletonAnim.PushPoseModifier(0, m_pPoseAlignerChain);
  412.         return true;
  413. }
  414.  
  415. void CChain::DrawDebug(const QuatT& location)
  416. {
  417.         float offsetMin, offsetMax;
  418.         ComputeRootOffsetExtents(offsetMin, offsetMax);
  419.         offsetMin = min(offsetMin, 0.0f);
  420.         offsetMax = max(offsetMax, 0.0f);
  421.         IRenderAuxText::DrawLabelF(m_targetPosition, 1.5f,
  422.                                    "w %.2f a: %.2f\n"
  423.                                    "min %.2f\n"
  424.                                    "max %.2f\n",
  425.                                    m_targetBlendWeightFiltered, m_targetBlendWeightAnimated,
  426.                                    offsetMin,
  427.                                    offsetMax);
  428.  
  429.         gEnv->pRenderer->GetIRenderAuxGeom()->DrawCone(
  430.           m_targetPosition, location.q * m_animationSlopeNormalFiltered, 0.05f, 1.0f, ColorB(0xff, 0xff, 0xff, 0xff));
  431. }
  432.  
  433. /*
  434.    CPose
  435.  */
  436.  
  437. CPose::CPose()
  438. {
  439.         CryCreateClassInstance("AnimationPoseModifier_OperatorQueue", m_operatorQueue);
  440.  
  441.         Clear();
  442. }
  443.  
  444. CPose::~CPose()
  445. {
  446. }
  447.  
  448. //
  449.  
  450. void CPose::Reset()
  451. {
  452.         m_rootOffsetSmoothed = 0.0f;
  453.         m_rootOffsetSmoothedRate = 0.0f;
  454.  
  455.         uint chainCount = uint(m_chains.size());
  456.         for (uint i = 0; i < chainCount; ++i)
  457.                 m_chains[i]->Reset();
  458.  
  459.         m_blendWeight = 1.0f;
  460. }
  461.  
  462. void CPose::Clear()
  463. {
  464.         RemoveAllChains();
  465.  
  466.         m_pEntity = NULL;
  467.         m_pSkeletonAnim = NULL;
  468.         m_pSkeletonPose = NULL;
  469.  
  470.         m_rootJointIndex = -1;
  471.  
  472.         m_bRootOffset = true;
  473.         m_bRootOffsetAverage = false;
  474.         m_rootOffsetDirection = Vec3(0.0f, 0.0f, 1.0f);
  475.         m_rootOffsetAdditional = ZERO;
  476.         m_rootOffsetMin = 0.0f;
  477.         m_rootOffsetMax = 0.0f;
  478.  
  479.         Reset();
  480.  
  481.         // TEMP
  482.         m_bInitialized = false;
  483. }
  484.  
  485. bool CPose::Initialize(IEntity& entity, int rootJointIndex)
  486. {
  487.         Clear();
  488.  
  489.         if (!m_operatorQueue)
  490.                 return false;
  491.         if (rootJointIndex < 0)
  492.                 return false;
  493.  
  494.         ICharacterInstance* pCharacter = entity.GetCharacter(0);
  495.         if (!pCharacter)
  496.                 return false;
  497.  
  498.         m_pEntity = &entity;
  499.         m_pSkeletonAnim = pCharacter->GetISkeletonAnim();
  500.         m_pSkeletonPose = pCharacter->GetISkeletonPose();
  501.  
  502.         m_rootJointIndex = rootJointIndex;
  503.  
  504.         return true;
  505. }
  506.  
  507. CChainPtr CPose::CreateChain(const SChainDesc& desc)
  508. {
  509.         SChainDesc chainDesc = desc;
  510.         if (!chainDesc.pContactReporter)
  511.                 chainDesc.pContactReporter = new CContactRaycast(*m_pEntity);
  512.  
  513.         CChainPtr chain = CChain::Create(chainDesc);
  514.         if (chain)
  515.                 m_chains.push_back(chain);
  516.         return chain;
  517. }
  518.  
  519. void CPose::RemoveAllChains()
  520. {
  521.         m_chains.clear();
  522. }
  523.  
  524. //
  525.  
  526. void CPose::Update(const QuatT& location, const float time)
  527. {
  528.         CRY_ASSERT(m_pEntity);
  529.  
  530.         if (!CVars::GetInstance().m_enable)
  531.                 return;
  532.  
  533.         ICharacterInstance* pCharacter = m_pEntity->GetCharacter(0);
  534.         if (!pCharacter)
  535.                 return;
  536.  
  537.         m_pSkeletonAnim = pCharacter->GetISkeletonAnim();
  538.         if (m_pSkeletonAnim == NULL)
  539.                 return;
  540.         m_pSkeletonPose = pCharacter->GetISkeletonPose();
  541.         if (m_pSkeletonPose == NULL)
  542.                 return;
  543.  
  544.         if (!m_pSkeletonAnim->GetNumAnimsInFIFO(0))
  545.                 return;
  546.  
  547.         uint chainCount = uint(m_chains.size());
  548.         if (!chainCount)
  549.                 return;
  550.  
  551.         m_blendWeight = clamp_tpl(m_blendWeight, 0.0f, 1.0f);
  552.  
  553.         float groundHeight = 0.0f;
  554.         Vec3 groundNormal(0.0f, 0.0f, 1.0f);
  555.         bool bGroundHeightValid = GetGroundFromEntity(*m_pEntity, groundHeight, groundNormal);
  556.  
  557.         //
  558.  
  559.         float chainOffsetMin = 0.0f;
  560.         float chainOffsetMax = 0.0f;
  561.         for (uint i = 0; i < chainCount; ++i)
  562.         {
  563.                 CChain& chain = *m_chains[i];
  564.  
  565.                 chain.UpdateFromAnimations(*pCharacter, location, time);
  566.                 chain.FindContact(location);
  567.                 chain.FilterTargetLocation(time);
  568.                 chain.ComputeTargetBlendValue(*m_pSkeletonPose, time, m_blendWeight);
  569.  
  570.                 float offsetMin, offsetMax;
  571.                 chain.ComputeRootOffsetExtents(offsetMin, offsetMax);
  572.                 chainOffsetMin = min(chainOffsetMin, offsetMin);
  573.                 chainOffsetMax = max(chainOffsetMax, offsetMax);
  574.  
  575.                 if (CVars::GetInstance().m_debugDraw)
  576.                         chain.DrawDebug(location);
  577.         }
  578.  
  579.         float rootOffset = 0.0f;
  580.         if (m_bRootOffset && !CVars::GetInstance().m_forceNoRootOffset)
  581.         {
  582.                 rootOffset = chainOffsetMin;
  583.                 if (m_bRootOffsetAverage)
  584.                 {
  585.                         rootOffset = (chainOffsetMin + chainOffsetMax) * 0.5f;
  586.                 }
  587.                 else if (abs(chainOffsetMax) > abs(chainOffsetMin))
  588.                 {
  589.                         rootOffset = chainOffsetMax;
  590.                 }
  591.                 rootOffset = clamp_tpl(rootOffset, m_rootOffsetMin, m_rootOffsetMax);
  592.         }
  593.  
  594.         //
  595.  
  596.         static const float SMOOTH_RATE = 0.10f;
  597.         SmoothCD(m_rootOffsetSmoothed, m_rootOffsetSmoothedRate, time, rootOffset, SMOOTH_RATE);
  598.         m_rootOffsetSmoothed *= m_blendWeight;
  599.  
  600.         //
  601.  
  602.         SetupPoseModifiers(location);
  603.         DrawDebug(location, groundNormal);
  604. }
  605.  
  606. void CPose::SetupPoseModifiers(const QuatT& location)
  607. {
  608.         uint chainCount = uint(m_chains.size());
  609.         if (!chainCount)
  610.                 return;
  611.  
  612.         for (uint i = 0; i < chainCount; ++i)
  613.                 m_chains[i]->SetupStoreOperators(*m_operatorQueue.get());
  614.  
  615.         QuatT chainsLocation = location;
  616.         float rootOffset = m_rootOffsetSmoothed + m_rootOffsetAdditional.z;
  617.  
  618.         if (rootOffset != 0.0f)
  619.         {
  620.                 m_operatorQueue->PushPosition(
  621.                   m_rootJointIndex, IAnimationOperatorQueue::eOp_Additive,
  622.                   m_rootOffsetDirection * rootOffset);
  623.                 m_operatorQueue->PushComputeAbsolute();
  624.         }
  625.  
  626.         m_pSkeletonAnim->PushPoseModifier(0, m_operatorQueue);
  627.  
  628.         for (uint i = 0; i < chainCount; ++i)
  629.                 m_chains[i]->SetupTargetPoseModifiers(chainsLocation, m_rootOffsetDirection * rootOffset, *m_pSkeletonAnim);
  630. }
  631.  
  632. void CPose::DrawDebug(const QuatT& location, const Vec3& groundNormal)
  633. {
  634.         if (!CVars::GetInstance().m_debugDraw)
  635.                 return;
  636.  
  637.         Vec3 groundPosition = location.t;
  638.         groundPosition += m_rootOffsetDirection * m_rootOffsetSmoothed;
  639.         SAuxGeomRenderFlags flags;
  640.         flags.SetAlphaBlendMode(e_AlphaBlended);
  641.         flags.SetCullMode(e_CullModeNone);
  642.         flags.SetDepthTestFlag(e_DepthTestOn);
  643.         gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(flags);
  644.         gEnv->pRenderer->GetIRenderAuxGeom()->DrawCylinder(
  645.           groundPosition, groundNormal, 1.0f, 0.005f, ColorB(0x00, 0x00, 0x00, 0x40), true);
  646.  
  647.         IRenderAuxText::DrawLabelF(location * m_pSkeletonPose->GetAbsJointByID(m_rootJointIndex).t, 1.5f,
  648.                                    "h %.2f\n"
  649.                                    "w %.2f\n",
  650.                                    m_rootOffsetSmoothed,
  651.                                    m_blendWeight);
  652.         gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(location.t, 0.125f, ColorB(uint8((1.0f - m_blendWeight) * 255.0f), 0xff, 0xff, 0xff), true);
  653. }
  654.  
  655. } // namespace PoseAligner
  656.  
downloadPoseAligner.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top