Fix spline length calculations bug

#2385
This commit is contained in:
Wojtek Figat
2024-09-09 20:47:49 +02:00
parent bbb0d36494
commit abb684aed2

View File

@@ -150,35 +150,30 @@ float Spline::GetSplineLength() const
{ {
float sum = 0.0f; float sum = 0.0f;
constexpr int32 slices = 20; constexpr int32 slices = 20;
constexpr float step = 1.0f / (float)slices; constexpr float step = 1.0f / (float)(slices - 1);
Vector3 prevPoint = Vector3::Zero; const Vector3 scale = _transform.Scale;
if (Curve.GetKeyframes().Count() != 0)
{
const auto& a = Curve[0];
prevPoint = a.Value.Translation * _transform.Scale;
}
for (int32 i = 1; i < Curve.GetKeyframes().Count(); i++) for (int32 i = 1; i < Curve.GetKeyframes().Count(); i++)
{ {
const auto& a = Curve[i - 1]; const auto& a = Curve[i - 1];
const auto& b = Curve[i]; const auto& b = Curve[i];
Vector3 prevPoint = a.Value.Translation * scale;
const float length = Math::Abs(b.Time - a.Time); const float length = Math::Abs(b.Time - a.Time);
Vector3 leftTangent, rightTangent; Vector3 leftTangent, rightTangent;
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent); AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent);
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent); AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent);
// TODO: implement sth more analytical than brute-force solution for (int32 slice = 1; slice < slices; slice++)
for (int32 slice = 0; slice < slices; slice++)
{ {
const float t = (float)slice * step; const float t = (float)slice * step;
Vector3 pos; Vector3 pos;
AnimationUtils::Bezier(a.Value.Translation, leftTangent, rightTangent, b.Value.Translation, t, pos); AnimationUtils::Bezier(a.Value.Translation, leftTangent, rightTangent, b.Value.Translation, t, pos);
pos *= _transform.Scale; pos *= scale;
sum += (float)Vector3::DistanceSquared(pos, prevPoint); sum += (float)Vector3::Distance(pos, prevPoint);
prevPoint = pos; prevPoint = pos;
} }
} }
return Math::Sqrt(sum); return sum;
} }
float Spline::GetSplineSegmentLength(int32 index) const float Spline::GetSplineSegmentLength(int32 index) const
@@ -188,28 +183,28 @@ float Spline::GetSplineSegmentLength(int32 index) const
CHECK_RETURN(index > 0 && index < GetSplinePointsCount(), 0.0f); CHECK_RETURN(index > 0 && index < GetSplinePointsCount(), 0.0f);
float sum = 0.0f; float sum = 0.0f;
constexpr int32 slices = 20; constexpr int32 slices = 20;
constexpr float step = 1.0f / (float)slices; constexpr float step = 1.0f / (float)(slices - 1);
const auto& a = Curve[index - 1]; const auto& a = Curve[index - 1];
const auto& b = Curve[index]; const auto& b = Curve[index];
Vector3 startPoint = a.Value.Translation * _transform.Scale; const Vector3 scale = _transform.Scale;
Vector3 prevPoint = a.Value.Translation * scale;
{ {
const float length = Math::Abs(b.Time - a.Time); const float length = Math::Abs(b.Time - a.Time);
Vector3 leftTangent, rightTangent; Vector3 leftTangent, rightTangent;
AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent); AnimationUtils::GetTangent(a.Value.Translation, a.TangentOut.Translation, length, leftTangent);
AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent); AnimationUtils::GetTangent(b.Value.Translation, b.TangentIn.Translation, length, rightTangent);
// TODO: implement sth more analytical than brute-force solution for (int32 slice = 1; slice < slices; slice++)
for (int32 slice = 0; slice < slices; slice++)
{ {
const float t = (float)slice * step; const float t = (float)slice * step;
Vector3 pos; Vector3 pos;
AnimationUtils::Bezier(a.Value.Translation, leftTangent, rightTangent, b.Value.Translation, t, pos); AnimationUtils::Bezier(a.Value.Translation, leftTangent, rightTangent, b.Value.Translation, t, pos);
pos *= _transform.Scale; pos *= scale;
sum += (float)Vector3::DistanceSquared(pos, startPoint); sum += (float)Vector3::Distance(pos, prevPoint);
startPoint = pos; prevPoint = pos;
} }
} }
return Math::Sqrt(sum); return sum;
} }
float Spline::GetSplineTime(int32 index) const float Spline::GetSplineTime(int32 index) const