zoukankan      html  css  js  c++  java
  • [UE4][Custom Animation Graph Node]Evaluate Pose by Curve

    转自:http://www.cnblogs.com/corgi/p/5405447.html

    目的:根据曲线值获得当前动作帧。用于实现各种通过曲线同步的功能。

    方法:继承FAnimNode_Base创建自定义动画节点。重写Evaluate部分。创建相应的AnimGraphNode。

    Evaluate : 1. 根据曲线Value(Y轴)值获得Time(X轴)值。

    曲线KeyArray所在位置。AnimSequenceBase : RawCurveData.

    类型AnimCurveTypes.h:FRawCurveTracks

    曲线记录是TArray<FRichCurveKey>。每个key中存有Time和Value。根据输入的CurveValue,遍历Array查找Value最接近的Key,返回Time。

    2.根据Time值获得动画POS

    AnimSequence->GetAnimationPose(…, Time, …)输出Pose。

    /*! 
     * file AnimNode_EvaluatePose.h 
     * date 2016/03/29 17:45 
     * 
     * author: Jia Zhipeng 
     * Contact: jiazhipeng@pwrd.com 
     * 
     * rief: 根据曲线获得当前Pose. Get Pose based on curve value. 
     * 
     * 
    ote:  
    */  
    #pragma once  
    #include "Animation/AnimNodeBase.h"  
    //#include "AnimNode_SkeletalControlBase.h"  
    #include "AnimNode_EvaluatePose.generated.h"  
      
    USTRUCT()  
    struct FAnimNode_EvaluatePose :public FAnimNode_Base  
    {  
        GENERATED_USTRUCT_BODY()  
      
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (PinShownByDefault))  
        UAnimSequenceBase* Sequence;  
      
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (PinShownByDefault))  
            FName CurveName;  
      
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Settings, meta = (PinShownByDefault))  
            float CurveValue;  
      
        UAnimInstance* MyInstance;  
    public:  
        //  Constructor  
        FAnimNode_EvaluatePose();  
      
        // FAnimNode_Base interface  
        virtual void Initialize(const FAnimationInitializeContext& Context) override;  
        virtual void CacheBones(const FAnimationCacheBonesContext& Context) override;  
        virtual void Evaluate(FPoseContext& Output) override;  
        virtual void OverrideAsset(UAnimationAsset* NewAsset) override;  
        virtual void GatherDebugData(FNodeDebugData& DebugData) override;  
        // End of FAnimNode_Base interface//  
      
    };  
    //Iterate Animation's curve's keys to get current time  
    void FAnimNode_EvaluatePose::Evaluate(FPoseContext& Output)  
    {     
    //CurveValue is connected to AnimInstance’s variable in AnimBlueprint, but it is not updated when executing this node. So how to get variable of AnimInstance? 2 ways.  
    //1. EvaluateGraphExposedInputs.Execute(Output); Cause crash. Explore this method in the future.  
    //2. Get property from AnimInstance. But in this way, the variable’s name has to be specified. Temporarily use this method.  
        UFloatProperty* FloatProp = Cast<UFloatProperty>(PW_PropertyTools::FindProperty(MyInstance, TEXT("Horiz Movement Speed")));  
        if (!FloatProp)  
        {  
            UE_LOG(LogTemp, Warning, TEXT("Horiz Movement Speed Not found"));  
            return;  
        }  
        float HorzSpeed = FloatProp->GetPropertyValue_InContainer(MyInstance);  
        CurveValue = HorzSpeed;  
          
        USkeleton* Skeleton = Sequence->GetSkeleton();  
        if (!Skeleton)  
        {  
            UE_LOG(LogTemp, Warning, TEXT("FAnimNode_EvaluatePose::Evaluate fail to find skeleton"));  
            return;  
        }  
        FSmartNameMapping* NameMapping = Skeleton->SmartNames.GetContainer(USkeleton::AnimCurveMappingName);  
        // retrieve curve  
        USkeleton::AnimCurveUID Uid;  
        if (!NameMapping->Exists(CurveName))  
        {  
            UE_LOG(LogTemp, Warning, TEXT("FAnimNode_EvaluatePose::Evaluate fail to find curve %s"), *CurveName.ToString());  
            return;  
        }  
      
        Uid = *NameMapping->FindUID(CurveName);  
        FFloatCurve * CurveToCompute = static_cast<FFloatCurve*>(Sequence->RawCurveData.GetCurveData(Uid));  
        if (!CurveToCompute)  
        {  
            UE_LOG(LogTemp, Warning, TEXT("FAnimNode_EvaluatePose::Evaluate fail to find curve %s"), *CurveName.ToString());  
            return;  
        }  
      
        auto FloatCurve = CurveToCompute->FloatCurve;  
        float OutTime = 0.0f;  
        BinarySeach(FloatCurve, CurveValue, OutTime);  
        if ((Sequence != NULL) && (Output.AnimInstance->CurrentSkeleton->IsCompatible(Sequence->GetSkeleton())))  
        {  
            Sequence->GetAnimationPose(Output.Pose, Output.Curve, FAnimExtractContext(OutTime, Output.AnimInstance->ShouldExtractRootMotion()));  
        }  
        else  
        {  
            Output.ResetToRefPose();  
        }  
    }  
  • 相关阅读:
    平衡二叉树之RB树
    平衡二叉树之AVL树
    实现哈希表
    LeetCode Median of Two Sorted Arrays
    LeetCode Minimum Window Substring
    LeetCode Interleaving String
    LeetCode Regular Expression Matching
    PAT 1087 All Roads Lead to Rome
    PAT 1086 Tree Traversals Again
    LeetCode Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/8444100.html
Copyright © 2011-2022 走看看