UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SplineMath.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
6#include "SplineInterfaces.h"
8#include <cstdint>
9#include <limits>
10
11namespace UE
12{
13namespace Geometry
14{
15namespace Spline
16{
17struct FKnot;
18
19// -------- Internal: numeric primitives (not public API) -----------------
20namespace Internal
21{
22 inline uint32 FloatToBits(float f)
23 {
24 uint32 u;
25 FMemory::Memcpy(&u, &f, sizeof(float));
26 return u;
27 }
28
29 inline float BitsToFloat(uint32 u)
30 {
31 float f;
32 FMemory::Memcpy(&f, &u, sizeof(float));
33 return f;
34 }
35
36 // Map IEEE754 float to a monotonic integer ordering and back.
37 inline uint32 ToOrdered(float f)
38 {
39 const uint32 u = FloatToBits(f);
40 const bool neg = (u & 0x80000000u) != 0;
41 return neg
42 ? ~u
43 : (u ^ 0x80000000u);
44 }
45
47 {
48 const uint32 u = (ordered & 0x80000000u)
49 ? (ordered ^ 0x80000000u)
50 : ~ordered;
51 return BitsToFloat(u);
52 }
53
57 inline float NextafterNoSubnormal(float from, bool bStepRight)
58 {
59 if (FMath::IsNaN(from) || !FMath::IsFinite(from))
60 {
61 return from; // keep NaN/Inf unchanged
62 }
63 if (from == 0.0f)
64 {
65 const float minNorm = std::numeric_limits<float>::min();
66 return bStepRight
67 ? +minNorm
68 : -minNorm;
69 }
70
72 if (bStepRight)
73 {
74 ++ordered;
75 }
76 else
77 {
78 --ordered;
79 }
80 float y = FromOrdered(ordered);
81
82 const float minNorm = std::numeric_limits<float>::min();
83 const float ay = FMath::Abs(y);
84 if (ay > 0.0f && ay < minNorm)
85 {
86 // Preserve the computed result's sign to maintain monotonicity
87 const float snapped = std::copysign(minNorm, y);
88
89 if (snapped == from)
90 {
91 // We're at ±FLT_MIN stepping toward zero; make monotone progress to signed zero
92 y = std::copysign(0.0f, y);
93 }
94 else
95 {
96 y = snapped;
97 }
98 }
99 if (!FMath::IsFinite(y))
100 {
101 y = bStepRight
102 ? +std::numeric_limits<float>::max()
103 : -std::numeric_limits<float>::max();
104 }
105 return y;
106 }
107
109 inline float NormalizeZeroForKey(float v)
110 {
111 return (v == 0.0f)
112 ? 0.0f
113 : v;
114 }
115} // namespace Internal
116
117// -------- Public: parameter helpers (domain-centric names) ---------------
118namespace Param
119{
120 enum class EDir : uint8 { Left, Right };
121
123 inline float NextDistinct(float t)
124 {
125 return Internal::NextafterNoSubnormal(t, /*right=*/true);
126 }
127
128 inline float PrevDistinct(float t)
129 {
130 return Internal::NextafterNoSubnormal(t, /*right=*/false);
131 }
132
134 inline float Step(float t, EDir d)
135 {
137 }
138
140 inline float StepInside(float t, EDir d, const FInterval1f& bounds)
141 {
143 }
144
146 inline float NormalizeKey(float t)
147 {
149 }
150} // namespace Param
151
152namespace Math
153{
157 template <typename T>
158 double Size(const T& Value)
159 {
160 if constexpr (THasSizeMethod<T>::value)
161 return static_cast<double>(Value.Size());
162 else if constexpr (std::is_arithmetic_v<T>)
163 return FMath::Abs(static_cast<double>(Value));
164 else
165 return 1.0; // Default for other types
166 }
167
171 template <typename T>
172 double SizeSquared(const T& Value)
173 {
175 return static_cast<double>(Value.SizeSquared());
176 else if constexpr (std::is_arithmetic_v<T>)
177 return static_cast<double>(Value * Value);
178 else
179 return Size(Value) * Size(Value);
180 }
181
185 template <typename T>
186 double Distance(const T& A, const T& B)
187 {
189 return Size(B - A);
190 else
191 return 1.0; // Default fallback
192 }
193
197 template <typename T>
198 double CentripetalDistance(const T& A, const T& B)
199 {
200 return FMath::Sqrt(Distance(A, B));
201 }
202
206 template <typename T>
207 double Dot(const T& A, const T& B)
208 {
209 if constexpr (THasDotMethod<T>::value)
210 return static_cast<double>(A.Dot(B));
211 else if constexpr (std::is_arithmetic_v<T>)
212 return static_cast<double>(A * B);
213 else
214 return 0.0; // Fallback
215 }
216
220 template <typename T>
222 {
224 return Value.GetSafeNormal();
225 else if constexpr (std::is_arithmetic_v<T>)
226 {
227 const double AbsValue = FMath::Abs(static_cast<double>(Value));
229 ? T(0)
230 : (Value > 0
231 ? T(1)
232 : T(-1));
233 }
234 else
235 return Value; // Fallback
236 }
237
241 template <typename T>
242 bool Equals(const T& A, const T& B, float Tolerance = UE_KINDA_SMALL_NUMBER)
243 {
244 if constexpr (THasEqualsMethod<T>::value)
245 return A.Equals(B, Tolerance);
246 else if constexpr (std::is_arithmetic_v<T>)
247 return FMath::Abs(static_cast<float>(A - B)) <= Tolerance;
248 else if constexpr (THasSubtractionOperator<T>::value)
249 return Distance(A, B) <= Tolerance;
250 else
251 return false; // Fallback
252 }
253
254
257 {
259 template <typename T>
261 {
263 {
264 return T(ForceInit);
265 }
266 else
267 {
268 return T();
269 }
270 }
271
272 template <typename T>
274 {
275 if (Window.Num() < RequiredSize)
276 {
277 return false;
278 }
279
280 // Check for null pointers
281 for (const T* Ptr : Window)
282 {
283 if (!Ptr)
284 {
285 return false;
286 }
287 }
288
289 return true;
290 }
291
292 static bool IsValidParameter(float Parameter)
293 {
294 return !FPlatformMath::IsNaN(Parameter) &&
295 FPlatformMath::IsFinite(Parameter);
296 }
297
298 template <typename T>
300 {
301 if (Window.Num() < 2) return false;
302
303 // Check for degenerate/repeated points
304 for (int32 i = 1; i < Window.Num(); ++i)
305 {
306 if (DistanceSquared(*Window[i], *Window[i - 1]) < Tolerance)
307 {
308 return false;
309 }
310 }
311
312 return true;
313 }
314 };
315
316 // Cached factorial table access
317 template <int32 N>
319 {
320 static TArray<double> Table;
321 if (Table.Num() == 0)
322 {
323 Table.SetNum(N + 1);
324 Table[0] = 1.0;
325 for (int32 i = 1; i <= N; ++i)
326 {
327 Table[i] = Table[i - 1] * i;
328 }
329 }
330 return Table;
331 }
332
333 // Cached binomial coefficient table
334 template <int32 N>
336 {
338 if (Table.Num() == 0)
339 {
340 Table.SetNum(N + 1);
341 for (int32 i = 0; i <= N; ++i)
342 {
343 Table[i].SetNum(i + 1);
344 Table[i][0] = Table[i][i] = 1.0;
345 for (int32 j = 1; j < i; ++j)
346 {
347 Table[i][j] = Table[i - 1][j - 1] + Table[i - 1][j];
348 }
349 }
350 }
351 return Table;
352 }
353
354 // Bezier basis computation
355 template <int32 Order>
356 static void ComputeBezierBasis(float t, TArray<float>& OutBasis)
357 {
358 OutBasis.SetNumZeroed(4); // Cubic Bezier
359
360 const float mt = 1.0f - t;
361
362 if constexpr (Order == 0)
363 {
364 // Position basis
365 OutBasis[0] = mt * mt * mt;
366 OutBasis[1] = 3.0f * mt * mt * t;
367 OutBasis[2] = 3.0f * mt * t * t;
368 OutBasis[3] = t * t * t;
369 }
370 else if constexpr (Order == 1)
371 {
372 // First derivative basis
373 OutBasis[0] = -3.0f * mt * mt;
374 OutBasis[1] = 3.0f * mt * (1.0f - 3.0f * t);
375 OutBasis[2] = 3.0f * t * (2.0f - 3.0f * t);
376 OutBasis[3] = 3.0f * t * t;
377 }
378 else if constexpr (Order == 2)
379 {
380 // Second derivative basis
381 OutBasis[0] = 6.0f * mt;
382 OutBasis[1] = -12.0f + 18.0f * t;
383 OutBasis[2] = 6.0f - 18.0f * t;
384 OutBasis[3] = 6.0f * t;
385 }
386 else if constexpr (Order == 3)
387 {
388 // Third derivative basis (constant)
389 OutBasis[0] = -6.0f;
390 OutBasis[1] = 18.0f;
391 OutBasis[2] = -18.0f;
392 OutBasis[3] = 6.0f;
393 }
394 }
395
396 // compute basis functions for a given degree
397 static void ComputeBSplineBasisFunctions(
399 int32 Span,
400 float Parameter,
401 int32 Degree,
403 {
404 OutBasis.SetNum(Degree + 1);
407 Left.SetNum(Degree + 1);
408 Right.SetNum(Degree + 1);
409
410 OutBasis[0] = 1.0f;
411
412 for (int32 j = 1; j <= Degree; ++j)
413 {
414 const int32 LeftIndex = Span + 1 - j;
415 const int32 RightIndex = Span + j;
416
419 {
420 UE_LOG(LogTemp, Warning, TEXT("Invalid knot indices in ComputeBasisFunctions: LeftIndex=%d, RightIndex=%d"),
422 // Instead of continuing, we should zero out the basis and return.
423 OutBasis.SetNumZeroed(Degree + 1);
424 return;
425 }
426
429
430 float Saved = 0.0f;
431
432 for (int32 r = 0; r < j; ++r)
433 {
434 float Temp;
435 const float Denominator = Right[r + 1] + Left[j - r];
436 // Correctly handle zero denominator
437 if (FMath::IsNearlyZero(Denominator))
438 {
439 Temp = 0.0f;
440 }
441 else
442 {
443 Temp = OutBasis[r] / Denominator;
444 }
445
446 OutBasis[r] = Saved + Right[r + 1] * Temp;
447 Saved = Left[j - r] * Temp;
448 }
449
450 OutBasis[j] = Saved;
451 }
452 }
453
456 // Helper struct for shared derivative implementation
457 template <typename T, int32 Order>
459 {
460 static T Compute(TArrayView<const T* const> Window, float Parameter)
461 {
462 // Basic validation
464 {
465 return FSplineValidation::GetDefaultValue<T>();
466 }
467
469 {
470#if ENABLE_NAN_DIAGNOSTIC
471 logOrEnsureNanError(TEXT("Invalid parameter in derivative calculation"));
472#endif
473 return FSplineValidation::GetDefaultValue<T>();
474 }
475
476 // Get pre-computed binomial coefficients
479
480 const int32 WindowSize = Window.Num();
481 if (Order >= WindowSize || Order >= BinomialTable.Num())
482 {
483 return FSplineValidation::GetDefaultValue<T>();
484 }
485
486 // Optional geometry validation for higher derivatives
488 {
489 return FSplineValidation::GetDefaultValue<T>();
490 }
491
492 T Result = FSplineValidation::GetDefaultValue<T>();
493 const float t = Parameter;
494 const float mt = 1.0f - t;
495
496 // Compute derivative using binomial expansion
497 for (int32 i = 0; i <= WindowSize - Order - 1; ++i)
498 {
499 double Coeff = BinomialTable[WindowSize - 1][i];
500
501 // Protect against overflow
502 if (Coeff > DBL_MAX / (WindowSize - 1))
503 {
504 return FSplineValidation::GetDefaultValue<T>();
505 }
506
507 // Apply derivative scaling
508 Coeff *= FactorialTable[WindowSize - 1] / FactorialTable[WindowSize - Order - 1];
509
510 // Apply parameter terms with underflow protection
511 if (mt > 0.0f)
512 {
513 const float PowMT = FMath::Pow(mt, WindowSize - Order - 1 - i);
514 if (FPlatformMath::IsFinite(PowMT))
515 {
516 Coeff *= PowMT;
517 }
518 }
519 if (t > 0.0f)
520 {
521 const float PowT = FMath::Pow(t, i);
522 if (FPlatformMath::IsFinite(PowT))
523 {
524 Coeff *= PowT;
525 }
526 }
527
528 Result += *Window[i] * Coeff;
529 }
530 return Result;
531 }
532 };
533
534 // Computes the nth derivative (where n == DerivOrder) of a BSpline curve.
535 // Note: This implementation assumes that DerivOrder <= Degree.
536 template <typename T, int32 DerivOrder>
538 {
551 static T Compute(
553 const TArray<float>& Knots,
554 int32 Span,
555 float Parameter,
556 int32 Degree)
557 {
558 // Basic validation
559 if (Window.Num() < Degree + 1 || DerivOrder > Degree)
560 {
561 return T();
562 }
563
566 const int32 KnotStart = Span - Degree;
567
568 // Determine if knots are uniformly spaced
569 bool bIsUniform = true;
570 const float h = Knots[1] - Knots[0];
571 for (int32 i = 2; i < Knots.Num(); ++i)
572 {
574 {
575 bIsUniform = false;
576 break;
577 }
578 }
579
580 // Compute derivative control points
581 for (int32 i = 0; i < Degree; ++i)
582 {
583 const int32 KnotDenom = KnotStart + i + Degree - DerivOrder + 2; //Knot index for the denominator
584 const int32 KnotNum = KnotStart + i + 1; //Knot index in the numerator
585
586 if (KnotDenom >= Knots.Num() || KnotNum >= Knots.Num() ||
587 KnotDenom < 0 || KnotNum < 0)
588 {
589 return T();
590 }
591
592 const float Denom = Knots[KnotDenom] - Knots[KnotNum];
593
594 // Handle uniform knots differently
595 if (bIsUniform)
596 {
597 // For uniform knots, use the fixed interval h instead of Denom
598 DerivControlPoints[i] = ((*Window[i + 1] - *Window[i])) * (static_cast<float>(Degree) / h);
599 //Correct scaling for uniform knots
600 }
601 else
602 {
603 DerivControlPoints[i] = ((*Window[i + 1] - *Window[i])) * (static_cast<float>(Degree) / Denom);
604 //Correct scaling for non-uniform knots
605 }
606 }
607
608 // Adjust scale factor for uniform knots
609 //Removing the scale factor
610 float ScaleFactor = 1.0;
611
612 // Recurse for higher derivatives with adjusted knots and parameters
613 if constexpr (DerivOrder > 1)
614 {
615 //No change here
618 for (int32 i = 0; i < DerivControlPoints.Num(); ++i)
619 {
621 }
622
623 // Trim the knot vector for uniform case
625 if (bIsUniform)
626 {
627 TrimmedKnots.Reserve(Knots.Num() - 2);
628 for (int32 i = 1; i < Knots.Num() - 1; ++i)
629 {
630 TrimmedKnots.Add(Knots[i]);
631 }
632 }
633 else
634 {
636 }
637
639 DerivWindow, //Reduced degree control points
640 TrimmedKnots, //Remove the first and the last knot as the degree is now p-1
641 Span, // Keep Span the same for uniform knots
642 Parameter, //Same parameter
643 Degree - 1 //Reduce the degree
644 ) * ScaleFactor; //Multiply with scale factor
645 }
646 else
647 {
648 // Base case: First derivative
649 TArray<float> Basis;
650 Math::ComputeBSplineBasisFunctions(Knots, Span, Parameter, Degree - 1, Basis);
651
652 T Result = T();
653 for (int32 i = 0; i < Degree; ++i)
654 {
655 Result += DerivControlPoints[i] * Basis[i];
656 }
657 return Result * ScaleFactor;
658 }
659 }
660 };
661
662 // Base case: 0th derivative is just the original BSpline evaluation.
663 template <typename T>
665 {
677 static T Compute(
679 const TArray<float>& Knots,
680 int32 Span,
681 float Parameter,
682 int32 Degree)
683 {
684 // Regular evaluation using current basis functions
685 TArray<float> Basis;
686 ComputeBSplineBasisFunctions(Knots, Span, Parameter, Degree, Basis);
687
688 T Result = T();
689 for (int32 i = 0; i <= Degree; ++i)
690 {
691 Result += *Window[i] * Basis[i];
692 }
693 return Result;
694 }
695 };
696
697
698 // Bezier curve specific calculations
699 template <typename T, int32 Order>
701 {
702 static T Compute(TArrayView<const T* const> Window, float Parameter, float SegmentScale)
703 {
704 if constexpr (Order > 3)
705 {
706 return FSplineValidation::GetDefaultValue<T>();
707 }
708
709 if (!FSplineValidation::IsValidWindow(Window, 4) || // Cubic Bezier needs 4 points
711 {
712 return FSplineValidation::GetDefaultValue<T>();
713 }
714
715 // Use existing basis computation
716 TArray<float> Basis;
717 ComputeBezierBasis<Order>(Parameter, Basis);
718
719 // Apply basis to control points
720 T Result = FSplineValidation::GetDefaultValue<T>();
721 for (int32 i = 0; i < Window.Num(); ++i)
722 {
723 Result += *Window[i] * Basis[i];
724 }
725
726 // Apply segment scaling based on derivative order
727 // For derivatives, we need to divide by SegmentScale^Order because
728 // derivatives scale inversely with parameter range
729 if constexpr (Order > 0)
730 {
731 // Calculate scaling factor: 1 / SegmentScale^Order
732 float ScalingFactor = 1.0f;
733 for (int32 i = 0; i < Order; ++i)
734 {
735 ScalingFactor /= SegmentScale;
736 }
737 return Result * ScalingFactor;
738 }
739 else
740 {
741 return Result; // No scaling needed for position (Order = 0)
742 }
743 }
744 };
745
746
756 template <typename ValueType>
758 const TArrayView<ValueType> Coeffs,
759 float StartParam,
760 float EndParam,
761 float& OutSquaredDistance)
762 {
763 // Test endpoints first
764 const ValueType& P0 = Coeffs[0]; // Already relative to target
765 const ValueType At1 = P0 + Coeffs[1] + Coeffs[2] + Coeffs[3]; // Curve at t=1
766
767 float BestDistSq = static_cast<float>(Math::SizeSquared(P0));
768 float BestParam = StartParam;
769
770 const float EndDistSq = static_cast<float>(Math::SizeSquared(At1));
771 if (EndDistSq < BestDistSq)
772 {
775 }
776
777 // Find roots of (C(t) - P).Dot(C'(t))
778 const ValueType& P1 = Coeffs[1];
779 const ValueType& P2 = Coeffs[2];
780 const ValueType& P3 = Coeffs[3];
781
783 RootCoeffs[5] = 3.0 * Dot(P3, P3);
784 RootCoeffs[4] = 5.0 * Dot(P3, P2);
785 RootCoeffs[3] = 4.0 * Dot(P3, P1) + 2.0 * Dot(P2, P2);
786 RootCoeffs[2] = 3.0 * Dot(P2, P1) + 3.0 * Dot(P3, P0);
787 RootCoeffs[1] = Dot(P1, P1) + 2.0 * Dot(P2, P0);
788 RootCoeffs[0] = Dot(P1, P0);
789
790 // Find roots in [0,1]
792
793 // Check each root
794 for (int32 RootIdx = 0; RootIdx < RootSolver.Roots.Num(); ++RootIdx)
795 {
796 const float t = static_cast<float>(RootSolver.Roots[RootIdx]);
797 const float Param = FMath::Lerp(StartParam, EndParam, t);
798
799 const ValueType Point = P0 +
800 P1 * t +
801 P2 * (t * t) +
802 P3 * (t * t * t);
803
804 const float DistSq = static_cast<float>(Math::SizeSquared(Point));
805 if (DistSq < BestDistSq)
806 {
808 BestParam = Param;
809 }
810 }
811
813 return BestParam;
814 }
815
816 template <typename ValueType>
819 {
820 FInterval1f ParameterSpace = Spline.GetParameterSpace();
821 Step = FMath::Max(Step, UE_KINDA_SMALL_NUMBER);
822
823 const double ParamRight = FMath::Clamp(Param + Step, ParameterSpace.Min, ParameterSpace.Max);
824 const double ParamLeft = FMath::Clamp(Param - Step, ParameterSpace.Min, ParameterSpace.Max);
825
826 const ValueType ValueRight = Spline.Evaluate(ParamRight);
827 const ValueType ValueLeft = Spline.Evaluate(ParamLeft);
828
829 return (ValueRight - ValueLeft) / (2.0 * Step);
830 }
831
832 template <typename ValueType>
833 ValueType ComputeSecondDerivativeCentralDifference(const TSplineInterface<ValueType>& Spline, double Param, double Step = 0.1)
834 {
835 FInterval1f ParameterSpace = Spline.GetParameterSpace();
836 Step = FMath::Max(Step, UE_KINDA_SMALL_NUMBER);
837
838 const double ParamRight = FMath::Clamp(Param + Step, ParameterSpace.Min, ParameterSpace.Max);
839 Param = FMath::Clamp(Param, ParameterSpace.Min, ParameterSpace.Max);
840 const double ParamLeft = FMath::Clamp(Param - Step, ParameterSpace.Min, ParameterSpace.Max);
841
842 const ValueType ValueRight = Spline.Evaluate(ParamRight);
843 const ValueType Value = Spline.Evaluate(Param);
844 const ValueType ValueLeft = Spline.Evaluate(ParamLeft);
845
846 return (ValueRight - 2.0 * Value + ValueLeft) / (Step * Step);
847 }
848} // end namespace UE::Geometry::Spline::Math
849} // end namespace UE::Geometry::Spline
850} // end namespace UE::Geometry
851} // end namespace UE
@ 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
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
#define logOrEnsureNanError(_FormatString_,...)
Definition LogMacros.h:436
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
uint32 Size
Definition VulkanMemory.cpp:4034
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ArrayView.h:139
Definition Array.h:670
void SetNum(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2308
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition StaticArray.h:26
Definition SplineInterfaces.h:92
Definition ByteSwap.h:14
float NextafterNoSubnormal(float from, bool bStepRight)
Definition SplineMath.h:57
uint32 ToOrdered(float f)
Definition SplineMath.h:37
float BitsToFloat(uint32 u)
Definition SplineMath.h:29
uint32 FloatToBits(float f)
Definition SplineMath.h:22
float FromOrdered(uint32 ordered)
Definition SplineMath.h:46
float NormalizeZeroForKey(float v)
Definition SplineMath.h:109
float FindNearestPoint_Cubic(const TArrayView< ValueType > Coeffs, float StartParam, float EndParam, float &OutSquaredDistance)
Definition SplineMath.h:757
ValueType ComputeSecondDerivativeCentralDifference(const TSplineInterface< ValueType > &Spline, double Param, double Step=0.1)
Definition SplineMath.h:833
double CentripetalDistance(const T &A, const T &B)
Definition SplineMath.h:198
ValueType ComputeFirstDerivativeCentralDifference(const TSplineInterface< ValueType > &Spline, double Param, double Step=UE_KINDA_SMALL_NUMBER)
Definition SplineMath.h:817
const TArray< TArray< double > > & GetBinomialTable()
Definition SplineMath.h:335
T GetSafeNormal(const T &Value)
Definition SplineMath.h:221
const TArray< double > & GetFactorialTable()
Definition SplineMath.h:318
double SizeSquared(const T &Value)
Definition SplineMath.h:172
float NormalizeKey(float t)
Definition SplineMath.h:146
EDir
Definition SplineMath.h:120
float PrevDistinct(float t)
Definition SplineMath.h:128
float StepInside(float t, EDir d, const FInterval1f &bounds)
Definition SplineMath.h:140
float NextDistinct(float t)
Definition SplineMath.h:123
T DistanceSquared(const UE::Math::TVector2< T > &V1, const UE::Math::TVector2< T > &V2)
Definition VectorTypes.h:82
Definition AdvancedWidgetsModule.cpp:13
float v
Definition radaudio_mdct.cpp:62
static UE_FORCEINLINE_HINT bool IsNearlyEqual(float A, float B, float ErrorTolerance=UE_SMALL_NUMBER)
Definition UnrealMathUtility.h:388
static constexpr UE_FORCEINLINE_HINT T Lerp(const T &A, const T &B, const U &Alpha)
Definition UnrealMathUtility.h:1116
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
static UE_FORCEINLINE_HINT bool IsNearlyZero(float Value, float ErrorTolerance=UE_SMALL_NUMBER)
Definition UnrealMathUtility.h:407
static UE_FORCEINLINE_HINT void * Memcpy(void *Dest, const void *Src, SIZE_T Count)
Definition UnrealMemory.h:160
Definition IsConstructible.h:10
static T GetDefaultValue()
Definition SplineMath.h:260
static bool IsValidGeometry(TArrayView< const T *const > Window, float Tolerance=UE_KINDA_SMALL_NUMBER)
Definition SplineMath.h:299
static bool IsValidWindow(TArrayView< const T *const > Window, int32 RequiredSize)
Definition SplineMath.h:273
static bool IsValidParameter(float Parameter)
Definition SplineMath.h:292
static T Compute(TArrayView< const T *const > Window, const TArray< float > &Knots, int32 Span, float Parameter, int32 Degree)
Definition SplineMath.h:677
static T Compute(TArrayView< const T *const > Window, const TArray< float > &Knots, int32 Span, float Parameter, int32 Degree)
Definition SplineMath.h:551
static T Compute(TArrayView< const T *const > Window, float Parameter, float SegmentScale)
Definition SplineMath.h:702
static T Compute(TArrayView< const T *const > Window, float Parameter)
Definition SplineMath.h:460
Definition ParameterizedTypes.h:121
Definition ParameterizedTypes.h:66
Definition ParameterizedTypes.h:129
Definition ParameterizedTypes.h:105
Definition ParameterizedTypes.h:113
Definition ParameterizedTypes.h:137
Definition PolynomialRootSolver.h:18