UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
InterpCurve.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "Algo/MinElement.h"
8#include "Containers/Array.h"
11#include "Math/Color.h"
12#include "Math/Vector2D.h"
13#include "Math/Vector.h"
14#include "Math/Quat.h"
15#include "Math/TwoVectors.h"
17
24template<class T>
26{
27public:
28
31
34
37
38public:
39 using ElementType = T;
40
44 , LoopKeyOffset(0.f)
45 {
46 }
47
48public:
49
57 int32 AddPoint( const float InVal, const T &OutVal );
58
69
71 void Reset();
72
74 void SetLoopKey( float InLoopKey );
75
77 void ClearLoopKey();
78
83 [[nodiscard]] T Eval( const float InVal, const T& Default = T(ForceInit) ) const;
84
88 [[nodiscard]] T EvalDerivative( const float InVal, const T& Default = T(ForceInit) ) const;
89
93 [[nodiscard]] T EvalSecondDerivative( const float InVal, const T& Default = T(ForceInit) ) const;
94
102 float FindNearest( const T &PointInSpace, float& OutDistanceSq ) const;
103
107 float InaccurateFindNearest(const T& PointInSpace, float& OutDistanceSq) const;
108
117 float FindNearest( const T &PointInSpace, float& OutDistanceSq, float& OutSegment ) const;
118
122 float InaccurateFindNearest(const T& PointInSpace, float& OutDistanceSq, float& OutSegment) const;
123
130 float FindNearestOnSegment( const T &PointInSpace, int32 PtIdx, float& OutSquaredDistance ) const;
131
136
138 void AutoSetTangents(float Tension = 0.0f, bool bStationaryEndpoints = true);
139
141 void CalcBounds(T& OutMin, T& OutMax, const T& Default = T(ForceInit)) const;
142
145
146public:
147
157 {
158 // NOTE: This is not used often for FInterpCurves. Most of the time these are serialized
159 // as inline struct properties in UnClass.cpp!
160
161 Ar << Curve.Points;
163 {
164 Ar << Curve.bIsLooped;
165 Ar << Curve.LoopKeyOffset;
166 }
167
168 return Ar;
169 }
170
175 {
176 return (Curve1.Points == Curve2.Points &&
177 Curve1.bIsLooped == Curve2.bIsLooped &&
178 (!Curve1.bIsLooped || Curve1.LoopKeyOffset == Curve2.LoopKeyOffset));
179 }
180
185 {
186 return !(Curve1 == Curve2);
187 }
188
192 [[nodiscard]] int32 GetPointIndexForInputValue(const float InValue) const;
193};
194
195
196/* FInterpCurve inline functions
197 *****************************************************************************/
198
199template< class T >
200int32 FInterpCurve<T>::AddPoint( const float InVal, const T &OutVal )
201{
202 int32 i=0; for( i=0; i<Points.Num() && Points[i].InVal < InVal; i++);
203 Points.InsertUninitialized(i);
204 Points[i] = FInterpCurvePoint< T >(InVal, OutVal);
205 return i;
206}
207
208
209template< class T >
211{
212 if( PointIndex < 0 || PointIndex >= Points.Num() )
213 return PointIndex;
214
215 const T OutVal = Points[PointIndex].OutVal;
216 const EInterpCurveMode Mode = Points[PointIndex].InterpMode;
217 const T ArriveTan = Points[PointIndex].ArriveTangent;
218 const T LeaveTan = Points[PointIndex].LeaveTangent;
219
220 Points.RemoveAt(PointIndex);
221
222 const int32 NewPointIndex = AddPoint( NewInVal, OutVal );
223 Points[NewPointIndex].InterpMode = Mode;
224 Points[NewPointIndex].ArriveTangent = ArriveTan;
225 Points[NewPointIndex].LeaveTangent = LeaveTan;
226
227 return NewPointIndex;
228}
229
230
231template< class T >
233{
234 Points.Empty();
235}
236
237
238template <class T>
240{
241 // Can't set a loop key if there are no points
242 if (Points.Num() == 0)
243 {
244 bIsLooped = false;
245 return;
246 }
247
248 const float LastInKey = Points.Last().InVal;
249 if (InLoopKey > LastInKey)
250 {
251 // Calculate loop key offset from the input key of the final point
252 bIsLooped = true;
253 LoopKeyOffset = InLoopKey - LastInKey;
254 }
255 else
256 {
257 // Specified a loop key lower than the final point; turn off looping.
258 bIsLooped = false;
259 }
260}
261
262
263template <class T>
265{
266 bIsLooped = false;
267}
268
269
270template< class T >
272{
273 const int32 NumPoints = Points.Num();
274 const int32 LastPoint = NumPoints - 1;
275
276 check(NumPoints > 0);
277
278 if (InValue < Points[0].InVal)
279 {
280 return -1;
281 }
282
283 if (InValue >= Points[LastPoint].InVal)
284 {
285 return LastPoint;
286 }
287
288 int32 MinIndex = 0;
289 int32 MaxIndex = NumPoints;
290
291 while (MaxIndex - MinIndex > 1)
292 {
293 int32 MidIndex = (MinIndex + MaxIndex) / 2;
294
295 if (Points[MidIndex].InVal <= InValue)
296 {
297 MinIndex = MidIndex;
298 }
299 else
300 {
301 MaxIndex = MidIndex;
302 }
303 }
304
305 return MinIndex;
306}
307
308
309template< class T >
310T FInterpCurve<T>::Eval(const float InVal, const T& Default) const
311{
312 const int32 NumPoints = Points.Num();
313 const int32 LastPoint = NumPoints - 1;
314
315 // If no point in curve, return the Default value we passed in.
316 if (NumPoints == 0)
317 {
318 return Default;
319 }
320
321 // If we let NaNs in through here, they fail the check() on the Alpha between the two points.
322 if (FPlatformMath::IsNaN(InVal))
323 {
324#if ENABLE_NAN_DIAGNOSTIC
325 logOrEnsureNanError(TEXT("FInterpCurve<T>::Eval has InVal == NaN"));
326#endif
327 return Default;
328 }
329
330 // Binary search to find index of lower bound of input value
331 const int32 Index = GetPointIndexForInputValue(InVal);
332
333 // If before the first point, return its value
334 if (Index == -1)
335 {
336 return Points[0].OutVal;
337 }
338
339 // If on or beyond the last point, return its value.
340 if (Index == LastPoint)
341 {
342 if (!bIsLooped)
343 {
344 return Points[LastPoint].OutVal;
345 }
346 else if (InVal >= Points[LastPoint].InVal + LoopKeyOffset)
347 {
348 // Looped spline: last point is the same as the first point
349 return Points[0].OutVal;
350 }
351 }
352
353 // Somewhere within curve range - interpolate.
354 check(Index >= 0 && ((bIsLooped && Index < NumPoints) || (!bIsLooped && Index < LastPoint)));
355 const bool bLoopSegment = (bIsLooped && Index == LastPoint);
356 const int32 NextIndex = bLoopSegment ? 0 : (Index + 1);
357
358 const auto& PrevPoint = Points[Index];
359 const auto& NextPoint = Points[NextIndex];
360
361 const float Diff = bLoopSegment ? LoopKeyOffset : (NextPoint.InVal - PrevPoint.InVal);
362
363 if (Diff > 0.0f && PrevPoint.InterpMode != CIM_Constant)
364 {
365 const float Alpha = (InVal - PrevPoint.InVal) / Diff;
366 checkf(Alpha >= 0.0f && Alpha <= 1.0f, TEXT("Bad value in Eval(): in %f prev %f diff %f alpha %f"), InVal, PrevPoint.InVal, Diff, Alpha);
367
368 if (PrevPoint.InterpMode == CIM_Linear)
369 {
370 return FMath::Lerp(PrevPoint.OutVal, NextPoint.OutVal, Alpha);
371 }
372 else
373 {
374 return FMath::CubicInterp(PrevPoint.OutVal, PrevPoint.LeaveTangent * Diff, NextPoint.OutVal, NextPoint.ArriveTangent * Diff, Alpha);
375 }
376 }
377 else
378 {
379 return Points[Index].OutVal;
380 }
381}
382
383
384template< class T >
385T FInterpCurve<T>::EvalDerivative(const float InVal, const T& Default) const
386{
387 const int32 NumPoints = Points.Num();
388 const int32 LastPoint = NumPoints - 1;
389
390 // If no point in curve, return the Default value we passed in.
391 if (NumPoints == 0)
392 {
393 return Default;
394 }
395
396 // If we let NaNs in through here, they fail the check() on the Alpha between the two points.
397 if (FPlatformMath::IsNaN(InVal))
398 {
399#if ENABLE_NAN_DIAGNOSTIC
400 logOrEnsureNanError(TEXT("FInterpCurve<T>::EvalDerivative has InVal == NaN"));
401#endif
402 return Default;
403 }
404
405 // Binary search to find index of lower bound of input value
406 const int32 Index = GetPointIndexForInputValue(InVal);
407
408 // If before the first point, return its tangent value
409 if (Index == -1)
410 {
411 return Points[0].LeaveTangent;
412 }
413
414 // If on or beyond the last point, return its tangent value.
415 if (Index == LastPoint)
416 {
417 if (!bIsLooped)
418 {
419 return Points[LastPoint].ArriveTangent;
420 }
421 else if (InVal >= Points[LastPoint].InVal + LoopKeyOffset)
422 {
423 // Looped spline: last point is the same as the first point
424 return Points[0].ArriveTangent;
425 }
426 }
427
428 // Somewhere within curve range - interpolate.
429 check(Index >= 0 && ((bIsLooped && Index < NumPoints) || (!bIsLooped && Index < LastPoint)));
430 const bool bLoopSegment = (bIsLooped && Index == LastPoint);
431 const int32 NextIndex = bLoopSegment ? 0 : (Index + 1);
432
433 const auto& PrevPoint = Points[Index];
434 const auto& NextPoint = Points[NextIndex];
435
436 const float Diff = bLoopSegment ? LoopKeyOffset : (NextPoint.InVal - PrevPoint.InVal);
437
438 if (Diff > 0.0f && PrevPoint.InterpMode != CIM_Constant)
439 {
440 if (PrevPoint.InterpMode == CIM_Linear)
441 {
442 return (NextPoint.OutVal - PrevPoint.OutVal) / Diff;
443 }
444 else
445 {
446 const float Alpha = (InVal - PrevPoint.InVal) / Diff;
447 checkf(Alpha >= 0.0f && Alpha <= 1.0f, TEXT("Bad value in EvalDerivative(): in %f prev %f diff %f alpha %f"), InVal, PrevPoint.InVal, Diff, Alpha);
448
449 return FMath::CubicInterpDerivative(PrevPoint.OutVal, PrevPoint.LeaveTangent * Diff, NextPoint.OutVal, NextPoint.ArriveTangent * Diff, Alpha) / Diff;
450 }
451 }
452 else
453 {
454 // Derivative of a constant is zero
455 return T(ForceInit);
456 }
457}
458
459template< class T >
460T FInterpCurve<T>::EvalSecondDerivative(const float InVal, const T& Default) const
461{
462 const int32 NumPoints = Points.Num();
463 const int32 LastPoint = NumPoints - 1;
464
465 // If no point in curve, return the Default value we passed in.
466 if (NumPoints == 0)
467 {
468 return Default;
469 }
470
471 // If we let NaNs in through here, they fail the check() on the Alpha between the two points.
472 if (FPlatformMath::IsNaN(InVal))
473 {
474#if ENABLE_NAN_DIAGNOSTIC
475 logOrEnsureNanError(TEXT("FInterpCurve<T>::EvalSecondDerivative has InVal == NaN"));
476#endif
477 return Default;
478 }
479
480 // Binary search to find index of lower bound of input value
481 const int32 Index = GetPointIndexForInputValue(InVal);
482
483 // If before the first point, return 0
484 if (Index == -1)
485 {
486 return T(ForceInit);
487 }
488
489 // If on or beyond the last point, return 0
490 if (Index == LastPoint)
491 {
492 if (!bIsLooped || (InVal >= Points[LastPoint].InVal + LoopKeyOffset))
493 {
494 return T(ForceInit);
495 }
496 }
497
498 // Somewhere within curve range - interpolate.
499 check(Index >= 0 && ((bIsLooped && Index < NumPoints) || (!bIsLooped && Index < LastPoint)));
500 const bool bLoopSegment = (bIsLooped && Index == LastPoint);
501 const int32 NextIndex = bLoopSegment ? 0 : (Index + 1);
502
503 const auto& PrevPoint = Points[Index];
504 const auto& NextPoint = Points[NextIndex];
505
506 const float Diff = bLoopSegment ? LoopKeyOffset : (NextPoint.InVal - PrevPoint.InVal);
507
508 if (Diff > 0.0f && PrevPoint.InterpMode != CIM_Constant)
509 {
510 if (PrevPoint.InterpMode == CIM_Linear)
511 {
512 // No change in tangent, return 0.
513 return T(ForceInit);
514 }
515 else
516 {
517 const float Alpha = (InVal - PrevPoint.InVal) / Diff;
518 checkf(Alpha >= 0.0f && Alpha <= 1.0f, TEXT("Bad value in EvalSecondDerivative(): in %f prev %f diff %f alpha %f"), InVal, PrevPoint.InVal, Diff, Alpha);
519
520 return FMath::CubicInterpSecondDerivative(PrevPoint.OutVal, PrevPoint.LeaveTangent * Diff, NextPoint.OutVal, NextPoint.ArriveTangent * Diff, Alpha) / (Diff * Diff);
521 }
522 }
523 else
524 {
525 // Second derivative of a constant is zero
526 return T(ForceInit);
527 }
528}
529
530template< class T >
532{
533 float OutSegment;
534 return FindNearest(PointInSpace, OutDistanceSq, OutSegment);
535}
536
537template< class T >
539{
540 float OutSegment;
541 return FindNearest(PointInSpace, OutDistanceSq, OutSegment);
542}
543
544template< class T >
545float FInterpCurve<T>::FindNearest(const T &PointInSpace, float& OutDistanceSq, float& OutSegment) const // LWC_TODO: Precision loss
546{
547 const int32 NumPoints = Points.Num();
548 const int32 NumSegments = bIsLooped ? NumPoints : NumPoints - 1;
549
550 if (NumPoints > 1)
551 {
552 float BestDistanceSq;
553 float BestResult = FindNearestOnSegment(PointInSpace, 0, BestDistanceSq);
554 float BestSegment = 0;
555 for (int32 Segment = 1; Segment < NumSegments; ++Segment)
556 {
557 float LocalDistanceSq;
558 float LocalResult = FindNearestOnSegment(PointInSpace, Segment, LocalDistanceSq);
560 {
564 }
565 }
568 return BestResult;
569 }
570
571 if (NumPoints == 1)
572 {
573 OutDistanceSq = static_cast<float>((PointInSpace - Points[0].OutVal).SizeSquared());
574 OutSegment = 0;
575 return Points[0].InVal;
576 }
577
578 return 0.0f;
579}
580
581template< class T >
583{
584 return FindNearest(PointInSpace, OutDistanceSq, OutSegment);
585}
586
587template< class T >
589{
590 const int32 NumPoints = Points.Num();
591 const int32 LastPoint = NumPoints - 1;
592 const int32 NextPtIdx = (bIsLooped && PtIdx == LastPoint) ? 0 : (PtIdx + 1);
593 check(PtIdx >= 0 && ((bIsLooped && PtIdx < NumPoints) || (!bIsLooped && PtIdx < LastPoint)));
594
595 const float NextInVal = (bIsLooped && PtIdx == LastPoint) ? (Points[LastPoint].InVal + LoopKeyOffset) : Points[NextPtIdx].InVal;
596
597 if (CIM_Constant == Points[PtIdx].InterpMode)
598 {
599 const float Distance1 = static_cast<float>((Points[PtIdx].OutVal - PointInSpace).SizeSquared());
600 const float Distance2 = static_cast<float>((Points[NextPtIdx].OutVal - PointInSpace).SizeSquared());
601 if (Distance1 < Distance2)
602 {
604 return Points[PtIdx].InVal;
605 }
607 return NextInVal;
608 }
609
610 const float Diff = NextInVal - Points[PtIdx].InVal;
611 if (CIM_Linear == Points[PtIdx].InterpMode)
612 {
613 // like in function: FMath::ClosestPointOnLine
614 const float A = static_cast<float>((Points[PtIdx].OutVal - PointInSpace) | (Points[NextPtIdx].OutVal - Points[PtIdx].OutVal));
615 const float B = static_cast<float>((Points[NextPtIdx].OutVal - Points[PtIdx].OutVal).SizeSquared());
616 const float V = FMath::Clamp(-A / B, 0.f, 1.f);
617 OutSquaredDistance = static_cast<float>((FMath::Lerp(Points[PtIdx].OutVal, Points[NextPtIdx].OutVal, V) - PointInSpace).SizeSquared());
618 return V * Diff + Points[PtIdx].InVal;
619 }
620
621 {
622 const TArray<FInterpCurvePoint<T>>& PointsT = Points;
623
624 // Get the cubic's control points, shifted so PointInSpace is at the origin
625 const T P0 = PointsT[PtIdx].OutVal - PointInSpace;
626 const T P1 = PointsT[NextPtIdx].OutVal - PointInSpace;
627 const T T0 = PointsT[PtIdx].LeaveTangent * Diff;
628 const T T1 = PointsT[NextPtIdx].ArriveTangent * Diff;
629 const T CubicCoeffs[4] = { P0, T0, -3 * P0 - 2 * T0 - T1 + 3 * P1, 2 * P0 + T0 + T1 - 2 * P1 };
630
631 // Curve is closest to PointInSpace when (Curve - PointInSpace).Dot(CurveDerivative) == 0
632 // Since we pre-subtracted PointInSpace, this becomes Curve.Dot(CurveDerivative) == 0,
633 // which expands out to the degree-5 polynomial w/ the below coefficients
635 Coeffs[5] = 3 * CubicCoeffs[3].Dot(CubicCoeffs[3]);
636 Coeffs[4] = 5 * CubicCoeffs[3].Dot(CubicCoeffs[2]);
637 Coeffs[3] = 4 * CubicCoeffs[3].Dot(CubicCoeffs[1]) + 2 * CubicCoeffs[2].Dot(CubicCoeffs[2]);
638 Coeffs[2] = 3 * CubicCoeffs[2].Dot(CubicCoeffs[1]) + 3 * CubicCoeffs[3].Dot(CubicCoeffs[0]);
639 Coeffs[1] = CubicCoeffs[1].Dot(CubicCoeffs[1]) + 2 * CubicCoeffs[0].Dot(CubicCoeffs[2]);
640 Coeffs[0] = CubicCoeffs[0].Dot(CubicCoeffs[1]);
641
642 // Test the endpoints first -- recall P0 and P1 already have PointInSpace subtracted out
643 float BestDistSq = static_cast<float>(P0.SizeSquared());
644 float BestParam = 0;
645 float EndDistSq = static_cast<float>(P1.SizeSquared());
646 if (EndDistSq < BestDistSq)
647 {
648 BestParam = 1;
650 }
651 // Check the roots
653 for (int32 RootIdx = 0; RootIdx < RootSolver.Roots.Num(); ++RootIdx)
654 {
655 T FoundPoint = FMath::CubicInterp(P0, T0, P1, T1, RootSolver.Roots[RootIdx]);
656 float RootDistSq = static_cast<float>(FoundPoint.SizeSquared());
658 {
659 BestParam = static_cast<float>(RootSolver.Roots[RootIdx]);
661 }
662 }
663 // Return the best parameter value for the segment, shifted back to overall curve parameter space
665 return BestParam * Diff + Points[PtIdx].InVal;
666
667 }
668}
669
670template< class T >
672{
673 return FindNearestOnSegment(PointInSpace, PtIdx, OutSquaredDistance);
674}
675
676template< class T >
677void FInterpCurve<T>::AutoSetTangents(float Tension, bool bStationaryEndpoints)
678{
679 const int32 NumPoints = Points.Num();
680 const int32 LastPoint = NumPoints - 1;
681
682 // Iterate over all points in this InterpCurve
683 for (int32 PointIndex = 0; PointIndex < NumPoints; PointIndex++)
684 {
685 const int32 PrevIndex = (PointIndex == 0) ? (bIsLooped ? LastPoint : 0) : (PointIndex - 1);
686 const int32 NextIndex = (PointIndex == LastPoint) ? (bIsLooped ? 0 : LastPoint) : (PointIndex + 1);
687
688 auto& ThisPoint = Points[PointIndex];
689 const auto& PrevPoint = Points[PrevIndex];
690 const auto& NextPoint = Points[NextIndex];
691
692 if (ThisPoint.InterpMode == CIM_CurveAuto || ThisPoint.InterpMode == CIM_CurveAutoClamped)
693 {
694 if (bStationaryEndpoints && (PointIndex == 0 || (PointIndex == LastPoint && !bIsLooped)))
695 {
696 // Start and end points get zero tangents if bStationaryEndpoints is true
697 ThisPoint.ArriveTangent = T(ForceInit);
698 ThisPoint.LeaveTangent = T(ForceInit);
699 }
700 else if (PrevPoint.IsCurveKey())
701 {
702 const bool bWantClamping = (ThisPoint.InterpMode == CIM_CurveAutoClamped);
703 T Tangent;
704
705 const float PrevTime = (bIsLooped && PointIndex == 0) ? (ThisPoint.InVal - LoopKeyOffset) : PrevPoint.InVal;
706 const float NextTime = (bIsLooped && PointIndex == LastPoint) ? (ThisPoint.InVal + LoopKeyOffset) : NextPoint.InVal;
707
709 PrevTime, // Previous time
710 PrevPoint.OutVal, // Previous point
711 ThisPoint.InVal, // Current time
712 ThisPoint.OutVal, // Current point
713 NextTime, // Next time
714 NextPoint.OutVal, // Next point
715 Tension, // Tension
716 bWantClamping, // Want clamping?
717 Tangent); // Out
718
719 ThisPoint.ArriveTangent = Tangent;
720 ThisPoint.LeaveTangent = Tangent;
721 }
722 else
723 {
724 // Following on from a line or constant; set curve tangent equal to that so there are no discontinuities
725 ThisPoint.ArriveTangent = PrevPoint.ArriveTangent;
726 ThisPoint.LeaveTangent = PrevPoint.LeaveTangent;
727 }
728 }
729 else if (ThisPoint.InterpMode == CIM_Linear)
730 {
731 ThisPoint.LeaveTangent = NextPoint.OutVal - ThisPoint.OutVal;
732
733 // Following from a curve, we should set the tangents equal so that there are no discontinuities
734 ThisPoint.ArriveTangent = PrevPoint.IsCurveKey() ? ThisPoint.LeaveTangent : ThisPoint.OutVal - PrevPoint.OutVal;
735 }
736 else if (ThisPoint.InterpMode == CIM_Constant)
737 {
738 ThisPoint.ArriveTangent = T(ForceInit);
739 ThisPoint.LeaveTangent = T(ForceInit);
740 }
741 }
742}
743
744
745template< class T >
747{
748 const int32 NumPoints = Points.Num();
749
750 if (NumPoints == 0)
751 {
752 OutMin = Default;
753 OutMax = Default;
754 }
755 else if (NumPoints == 1)
756 {
757 OutMin = Points[0].OutVal;
758 OutMax = Points[0].OutVal;
759 }
760 else
761 {
762 OutMin = Points[0].OutVal;
763 OutMax = Points[0].OutVal;
764
765 const int32 NumSegments = bIsLooped ? NumPoints : (NumPoints - 1);
766
767 for (int32 Index = 0; Index < NumSegments; Index++)
768 {
769 const int32 NextIndex = (Index == NumPoints - 1) ? 0 : (Index + 1);
770 CurveFindIntervalBounds(Points[Index], Points[NextIndex], OutMin, OutMax, 0.0f);
771 }
772 }
773}
774
775template <class T>
777{
778 if (Points.IsEmpty())
779 {
780 return {};
781 }
782
783 return FFloatInterval(Points[0].InVal, Points.Last().InVal);
784}
785
786/* Common type definitions
787 *****************************************************************************/
788
789#define DEFINE_INTERPCURVE_WRAPPER_STRUCT(Name, ElementType) \
790 struct Name : FInterpCurve<ElementType> \
791 { \
792 private: \
793 typedef FInterpCurve<ElementType> Super; \
794 \
795 public: \
796 Name() \
797 : Super() \
798 { \
799 } \
800 \
801 Name(const Super& Other) \
802 : Super( Other ) \
803 { \
804 } \
805 }; \
806 \
807 template <> \
808 struct TIsBitwiseConstructible<Name, FInterpCurve<ElementType>> \
809 { \
810 enum { Value = true }; \
811 }; \
812 \
813 template <> \
814 struct TIsBitwiseConstructible<FInterpCurve<ElementType>, Name> \
815 { \
816 enum { Value = true }; \
817 };
818
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
@ ForceInit
Definition CoreMiscDefines.h:155
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
void ComputeCurveTangent(float PrevTime, const T &PrevPoint, float CurTime, const T &CurPoint, float NextTime, const T &NextPoint, float Tension, bool bWantClamping, T &OutTangent)
Definition InterpCurvePoint.h:214
EInterpCurveMode
Definition InterpCurvePoint.h:16
@ CIM_CurveAutoClamped
Definition InterpCurvePoint.h:35
@ CIM_Linear
Definition InterpCurvePoint.h:18
@ CIM_Constant
Definition InterpCurvePoint.h:25
@ CIM_CurveAuto
Definition InterpCurvePoint.h:22
void CurveFindIntervalBounds(const FInterpCurvePoint< T > &Start, const FInterpCurvePoint< T > &End, T &CurrentMin, T &CurrentMax, const U &Dummy)
Definition InterpCurvePoint.h:402
#define DEFINE_INTERPCURVE_WRAPPER_STRUCT(Name, ElementType)
Definition InterpCurve.h:789
#define logOrEnsureNanError(_FormatString_,...)
Definition LogMacros.h:436
@ VER_UE4_INTERPCURVE_SUPPORTS_LOOPING
Definition ObjectVersion.h:599
USkinnedMeshComponent float
Definition SkinnedMeshComponent.h:60
Definition Archive.h:1208
UE_FORCEINLINE_HINT FPackageFileVersion UEVer() const
Definition Archive.h:204
Definition InterpCurve.h:26
void SetLoopKey(float InLoopKey)
Definition InterpCurve.h:239
T ElementType
Definition InterpCurve.h:39
void ClearLoopKey()
Definition InterpCurve.h:264
int32 GetPointIndexForInputValue(const float InValue) const
Definition InterpCurve.h:271
void CalcBounds(T &OutMin, T &OutMax, const T &Default=T(ForceInit)) const
Definition InterpCurve.h:746
float InaccurateFindNearest(const T &PointInSpace, float &OutDistanceSq) const
Definition InterpCurve.h:538
T Eval(const float InVal, const T &Default=T(ForceInit)) const
Definition InterpCurve.h:310
float LoopKeyOffset
Definition InterpCurve.h:36
friend bool operator==(const FInterpCurve &Curve1, const FInterpCurve &Curve2)
Definition InterpCurve.h:174
friend FArchive & operator<<(FArchive &Ar, FInterpCurve &Curve)
Definition InterpCurve.h:156
friend bool operator!=(const FInterpCurve &Curve1, const FInterpCurve &Curve2)
Definition InterpCurve.h:184
TArray< FInterpCurvePoint< T > > Points
Definition InterpCurve.h:30
T EvalDerivative(const float InVal, const T &Default=T(ForceInit)) const
Definition InterpCurve.h:385
T EvalSecondDerivative(const float InVal, const T &Default=T(ForceInit)) const
Definition InterpCurve.h:460
float InaccurateFindNearestOnSegment(const T &PointInSpace, int32 PtIdx, float &OutSquaredDistance) const
Definition InterpCurve.h:671
FInterpCurve()
Definition InterpCurve.h:42
bool bIsLooped
Definition InterpCurve.h:33
void Reset()
Definition InterpCurve.h:232
FFloatInterval GetKeyInterval() const
Definition InterpCurve.h:776
float FindNearestOnSegment(const T &PointInSpace, int32 PtIdx, float &OutSquaredDistance) const
Definition InterpCurve.h:588
int32 MovePoint(int32 PointIndex, float NewInVal)
Definition InterpCurve.h:210
int32 AddPoint(const float InVal, const T &OutVal)
Definition InterpCurve.h:200
void AutoSetTangents(float Tension=0.0f, bool bStationaryEndpoints=true)
Definition InterpCurve.h:677
float FindNearest(const T &PointInSpace, float &OutDistanceSq) const
Definition InterpCurve.h:531
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT ElementType & Last(SizeType IndexFromTheEnd=0) UE_LIFETIMEBOUND
Definition Array.h:1263
UE_NODEBUG UE_FORCEINLINE_HINT void InsertUninitialized(SizeType Index)
Definition Array.h:1782
void RemoveAt(SizeType Index, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2083
UE_REWRITE bool IsEmpty() const
Definition Array.h:1133
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition StaticArray.h:26
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
Definition Color.h:48
static constexpr T CubicInterpDerivative(const T &P0, const T &T0, const T &P1, const T &T1, const U &A)
Definition UnrealMathUtility.h:1241
static constexpr UE_FORCEINLINE_HINT T Lerp(const T &A, const T &B, const U &Alpha)
Definition UnrealMathUtility.h:1116
static constexpr T CubicInterp(const T &P0, const T &T0, const T &P1, const T &T1, const U &A)
Definition UnrealMathUtility.h:1212
static constexpr T CubicInterpSecondDerivative(const T &P0, const T &T0, const T &P1, const T &T1, const U &A)
Definition UnrealMathUtility.h:1262
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
Definition TwoVectors.h:15
Definition PolynomialRootSolver.h:18