• [UE4][Custom Animation Graph Node]Evaluate Pose by Curve


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

    方法:继承FAnimNode_Base创建自定义动画节点。重写Evaluate部分。创建相应的AnimGraphNode。可参考前一篇http://blog.csdn.net/u010831746/article/details/50733287

    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。

    主要代码:

    AnimNode_EvaluatePose.h

    /*!
     * 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//
    
    };
    

    AnimNode_EvaluatePose.cpp

    //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();
    	}
    }
    



  • 相关阅读:
    SICP 习题1.16-1.19体会
    设计模式C++实现——组合模式
    QT官方下载地址
    浅析三角形測试程序
    操作系统开发之——进入保护模式
    PowerDesigner 打印错误
    @RequestParam注解一般用法
    Eclipse配置Maven的一些问题
    在windows上部署使用redis出现的问题及解决方法
    Eclipse导入模板格式Xml配置文件
  • 原文地址:https://www.cnblogs.com/corgi/p/5405447.html
Copyright © 2020-2023  润新知