Hi guys! I planned to share my solution, but I have no time to complete it, so I’m here to share a part of my solution. Many people ask me how I get time by distance from curve. Code below is not perfect, but I’m not a C++ programmer This code works only if you compress curve with “Uniform Indexable” compression type!
#include "Animation/AnimInstanceBase.h"
#include "Animation/AnimCurveCompressionCodec_UniformIndexable.h"
DEFINE_LOG_CATEGORY(LogAnimInstanceBase)
float UAnimInstanceBase::GetCurveTime(const UAnimSequence* *AnimationSequence*, const FName *CurveName*, const float *CurveValue*)
{
if (AnimationSequence == nullptr)
{
UE_LOG(LogAnimInstanceBase, Error, TEXT("Invalid Animation Sequence ptr"));
return 0.0f;
}
* // Get curve SmartName*
FSmartName CurveSmartName;
AnimationSequence->GetSkeleton()->GetSmartNameByName(USkeleton::AnimCurveMappingName, CurveName, CurveSmartName);
* // Create a buffered access to times and values in curve*
const FAnimCurveBufferAccess CurveBuffer = FAnimCurveBufferAccess(AnimationSequence, CurveSmartName.UID);
* // The number of elements in curve*
const int NumSamples = static_cast<int>(CurveBuffer.GetNumSamples());
const int LastIndex = NumSamples - 1;
if (NumSamples < 2)
{
return 0.0f;
}
* // Corner cases*
if (CurveValue <= CurveBuffer.GetValue(0))
{
return CurveBuffer.GetTime(0);
}
if (CurveValue >= CurveBuffer.GetValue(LastIndex))
{
return CurveBuffer.GetTime(LastIndex);
}
* // Binary search*
int32 NextIndex = 1;
int32 Count = LastIndex - NextIndex;
while (Count > 0)
{
const int32 Step = Count / 2;
const int32 Middle = NextIndex + Step;
if (CurveValue > CurveBuffer.GetValue(Middle))
{
NextIndex = Middle + 1;
Count -= Step + 1;
}
else
{
Count = Step;
}
}
const int32 PrevIndex = NextIndex - 1;
const float PrevCurveValue = CurveBuffer.GetValue(PrevIndex);
const float NextCurveValue = CurveBuffer.GetValue(NextIndex);
const float PrevCurveTime = CurveBuffer.GetTime(PrevIndex);
const float NextCurveTime = CurveBuffer.GetTime(NextIndex);
* // Find time by two nearest known points on the curve*
const float Diff = NextCurveValue - PrevCurveValue;
const float Alpha = !FMath::IsNearlyZero(Diff) ? (CurveValue - PrevCurveValue) / Diff : 0.0f;
return FMath::Lerp(PrevCurveTime, NextCurveTime, Alpha);
}
P.S.: If you know how to improve code or found a bug, please let me know.
P.P.S: same in gist Get time by value from curve compressed with Uniform Indexable · GitHub