From 418918920e3f804c5a7bb38e8d506bf7105a14b9 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 Nov 2023 11:38:37 +0100 Subject: [PATCH] Add `GetSplineSegmentLength` to get spline segment length #1879 --- Source/Engine/Level/Actors/Spline.cpp | 35 +++++++++++++++++++++++++-- Source/Engine/Level/Actors/Spline.h | 7 ++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Level/Actors/Spline.cpp b/Source/Engine/Level/Actors/Spline.cpp index df93ea840..dfe7c2be8 100644 --- a/Source/Engine/Level/Actors/Spline.cpp +++ b/Source/Engine/Level/Actors/Spline.cpp @@ -149,8 +149,8 @@ float Spline::GetSplineDuration() const float Spline::GetSplineLength() const { float sum = 0.0f; - const int32 slices = 20; - const float step = 1.0f / (float)slices; + constexpr int32 slices = 20; + constexpr float step = 1.0f / (float)slices; Vector3 prevPoint = Vector3::Zero; if (Curve.GetKeyframes().Count() != 0) { @@ -181,6 +181,37 @@ float Spline::GetSplineLength() const return Math::Sqrt(sum); } +float Spline::GetSplineSegmentLength(int32 index) const +{ + if (index == 0) + return 0.0f; + CHECK_RETURN(index > 0 && index < GetSplinePointsCount(), 0.0f); + float sum = 0.0f; + constexpr int32 slices = 20; + constexpr float step = 1.0f / (float)slices; + const auto& a = Curve[index - 1]; + const auto& b = Curve[index]; + Vector3 startPoint = a.Value.Translation * _transform.Scale; + { + const float length = Math::Abs(b.Time - a.Time); + Vector3 leftTangent, rightTangent; + AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent); + AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent); + + // TODO: implement sth more analytical than brute-force solution + for (int32 slice = 0; slice < slices; slice++) + { + const float t = (float)slice * step; + Vector3 pos; + AnimationUtils::Bezier(a.Value.Translation, leftTangent, rightTangent, b.Value.Translation, t, pos); + pos *= _transform.Scale; + sum += (float)Vector3::DistanceSquared(pos, startPoint); + startPoint = pos; + } + } + return Math::Sqrt(sum); +} + float Spline::GetSplineTime(int32 index) const { CHECK_RETURN(index >= 0 && index < GetSplinePointsCount(), 0.0f) diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index cd022890b..4a81ee186 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -167,6 +167,13 @@ public: /// API_PROPERTY() float GetSplineLength() const; + /// + /// Gets the length of the spline segment (distance between pair of two points). + /// + /// The index of the segment end index. Zero-based, smaller than GetSplinePointsCount(). + /// The spline segment length. + API_FUNCTION() float GetSplineSegmentLength(int32 index) const; + /// /// Gets the time of the spline keyframe. ///