GH-854 Add Monotonic Cubic Interpolation#1224
GH-854 Add Monotonic Cubic Interpolation#1224JoltedJon wants to merge 3 commits intoRedot-Engine:masterfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds monotonic cubic interpolation support across core math, vector/quaternion types, variant bindings, animation runtime, and editor menus, introducing INTERPOLATION_CUBIC_MONOTONIC and INTERPOLATION_CUBIC_MONOTONIC_ANGLE and corresponding time/angle-aware APIs and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant Editor as Editor (Track UI)
participant Animation as Animation Runtime
participant Math as Math::monotonic_cubic*
participant Type as Vector/Quaternion Implementation
participant Variant as Variant Bindings / Scripts
Editor->>Animation: User selects/interpolates key (MONOTONIC)
Animation->>Type: _interpolate dispatch (INTERPOLATION_CUBIC_MONOTONIC)
Type->>Math: call monotonic_cubic_interpolate(_in_time / _angle variants)
Math-->>Type: interpolated numeric components
Type-->>Animation: composed Vector/Quaternion result
Animation-->>Variant: expose result to scripting / export
Variant-->>Editor: script-accessible interpolation methods
Estimated code review effort🎯 4 (Complex) | ⏱️ ~70 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip You can enable review details to help with troubleshooting, context usage and more.Enable the |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
editor/animation/animation_track_editor.cpp (1)
3092-3117:⚠️ Potential issue | 🔴 CriticalAdd icon handling for the new interpolation enums.
These modes are now selectable, but the draw path at Lines 2315-2321 and Line 2395 still uses a 5-entry
interp_iconlookup. That no longer matches the interpolation enum, so monotonic tracks will show the wrong icon or read past the array during redraw.Suggested fix
- Ref<Texture2D> interp_icon[5] = { - get_editor_theme_icon(SNAME("InterpRaw")), - get_editor_theme_icon(SNAME("InterpLinear")), - get_editor_theme_icon(SNAME("InterpCubic")), - get_editor_theme_icon(SNAME("InterpLinearAngle")), - get_editor_theme_icon(SNAME("InterpCubicAngle")), - }; @@ - Ref<Texture2D> icon = interp_icon[interp_mode]; + Ref<Texture2D> icon; + switch (interp_mode) { + case Animation::INTERPOLATION_NEAREST: + icon = get_editor_theme_icon(SNAME("InterpRaw")); + break; + case Animation::INTERPOLATION_LINEAR: + icon = get_editor_theme_icon(SNAME("InterpLinear")); + break; + case Animation::INTERPOLATION_CUBIC: + case Animation::INTERPOLATION_CUBIC_MONOTONIC: + icon = get_editor_theme_icon(SNAME("InterpCubic")); + break; + case Animation::INTERPOLATION_LINEAR_ANGLE: + icon = get_editor_theme_icon(SNAME("InterpLinearAngle")); + break; + case Animation::INTERPOLATION_CUBIC_ANGLE: + case Animation::INTERPOLATION_CUBIC_MONOTONIC_ANGLE: + icon = get_editor_theme_icon(SNAME("InterpCubicAngle")); + break; + default: + icon = get_editor_theme_icon(SNAME("InterpRaw")); + break; + }Also applies to: 3568-3571
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@editor/animation/animation_track_editor.cpp` around lines 3092 - 3117, The draw code still uses a 5-entry interp_icon lookup which no longer matches the expanded interpolation enum (new monotonic entries), causing wrong icons/UB; update the interp_icon array and any switch/lookup in the drawing code to include icons for MENU_INTERPOLATION_CUBIC_MONOTONIC and MENU_INTERPOLATION_CUBIC_MONOTONIC_ANGLE (and their angle/non-angle counterparts), and adjust any index mapping logic so each interpolation enum value maps to the correct icon (update references to interp_icon and the drawing functions that read interpolation enum values). Ensure you add the corresponding get_editor_theme_icon calls for the new monotonic variants and verify the lookup size matches the enum range so no out-of-bounds access occurs.scene/resources/animation.h (1)
62-70:⚠️ Potential issue | 🔴 CriticalDo not renumber existing
InterpolationTypeenum values.Adding
INTERPOLATION_CUBIC_MONOTONICbefore existing entries changes legacy numeric IDs (notablyINTERPOLATION_LINEAR_ANGLEandINTERPOLATION_CUBIC_ANGLE). That can break backward compatibility for serialized animation tracks and runtime interpolation selection.🔧 Proposed fix
enum InterpolationType : uint8_t { INTERPOLATION_NEAREST, INTERPOLATION_LINEAR, INTERPOLATION_CUBIC, - INTERPOLATION_CUBIC_MONOTONIC, INTERPOLATION_LINEAR_ANGLE, INTERPOLATION_CUBIC_ANGLE, + INTERPOLATION_CUBIC_MONOTONIC, INTERPOLATION_CUBIC_MONOTONIC_ANGLE, };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scene/resources/animation.h` around lines 62 - 70, The enum InterpolationType was modified in a way that shifts numeric IDs (specifically INTERPOLATION_LINEAR_ANGLE and INTERPOLATION_CUBIC_ANGLE); restore backward compatibility by ensuring existing values retain their original numeric IDs—either move INTERPOLATION_CUBIC_MONOTONIC to the end of the enum list or add explicit integer assignments for each enum entry so INTERPOLATION_NEAREST, INTERPOLATION_LINEAR, INTERPOLATION_CUBIC, INTERPOLATION_LINEAR_ANGLE, and INTERPOLATION_CUBIC_ANGLE keep their previous numeric values; update the InterpolationType definition accordingly to avoid changing legacy serialized IDs.
🧹 Nitpick comments (2)
core/math/quaternion.cpp (1)
269-368: Extract the shared spherical-cubic core.These two overloads duplicate the full phase-alignment and dual-expmap flow from
spherical_cubic_interpolate{_in_time}. A small helper that takes the scalar interpolation op would keep future fixes to the quaternion math in one place.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@core/math/quaternion.cpp` around lines 269 - 368, Both spherical_monotonic_cubic_interpolate and spherical_monotonic_cubic_interpolate_in_time duplicate the phase-alignment, flip handling, dual ExpMap and slerp blending logic; extract that shared flow into a single helper (e.g., spherical_monotonic_cubic_interpolate_core) that accepts a scalar interpolation callable (std::function or template parameter) and any optional time arguments, so the two public methods call the core with either Math::monotonic_cubic_interpolate or Math::monotonic_cubic_interpolate_in_time; update the core to perform Basis conversions, flip adjustments (from_q, pre_q, to_q, post_q), compute ln vectors in both from_q and to_q spaces, call the provided scalar interpolator for x/y/z, build q1/q2 and return q1.slerp(q2, p_weight), keeping the public function names spherical_monotonic_cubic_interpolate and spherical_monotonic_cubic_interpolate_in_time as thin wrappers.scene/resources/animation.cpp (1)
6566-6754: Extract the shared Variant cubic dispatcher before these two implementations drift.
Animation::monotonic_cubic_interpolate_in_time_variantis effectively a second copy ofAnimation::cubic_interpolate_in_time_variant. Any future type fix now has to be mirrored across another very large switch and array-walking block. I'd pull the shared traversal into a helper and inject the cubic vs monotonic primitives.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scene/resources/animation.cpp` around lines 6566 - 6754, The two large switch+array traversal blocks in Animation::monotonic_cubic_interpolate_in_time_variant and Animation::cubic_interpolate_in_time_variant should be refactored into a single helper (e.g., Animation::variant_cubic_dispatcher) that accepts a strategy flag or function pointers for the primitive scalar/vector interpolation routines (e.g., Math::cubic_interpolate_in_time vs Math::monotonic_cubic_interpolate_in_time and the instance methods like Vector2::monotonic_cubic_interpolate_in_time / cubic_interpolate_in_time, Quaternion::spherical_monotonic_cubic_interpolate_in_time / spherical_cubic_interpolate_in_time). Move the shared array handling and type-switch logic into that helper and have the two public methods call it with the appropriate primitive functions; ensure you preserve the special-casing (numeric cast_to_blendwise/cast_from_blendwise, string fallback, PACKED_BYTE_ARRAY skip, p_snap_array_element behavior) by passing any needed flags through the helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@core/math/math_funcs.h`:
- Around line 947-960: The function monotonic_cubic_interpolate_angle_in_time
has the timestamp parameters in the wrong order (p_pre_t, p_to_t, p_post_t)
which mismatches the established _in_time API; change the signature to accept (T
p_to_t, T p_pre_t, T p_post_t) and update the call to
monotonic_cubic_interpolate_in_time(...) to pass the timestamps in the same
order expected by that function (p_weight, p_to_t, p_pre_t, p_post_t) so pre/to
timestamps are not swapped; ensure the parameter names in the function
declaration/definition and any callers use the corrected order to preserve API
consistency with cubic_interpolate_angle_in_time and VariantUtilityFunctions.
In `@core/variant/variant_utility.cpp`:
- Around line 548-550: The wrapper
VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time forwards time
arguments to Math::monotonic_cubic_interpolate_angle_in_time in the wrong order,
swapping to_t and pre_t; fix it by calling
Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight,
pre_t, to_t, post_t) so that the forwarded times match Math's expected (p_pre_t,
p_to_t, p_post_t) parameter order.
In `@tests/core/math/test_math_funcs.h`:
- Around line 694-700: The test block is calling
Math::cubic_interpolate_angle_in_time instead of the intended
Math::monotonic_cubic_interpolate_angle_in_time; update all five CHECK lines to
call Math::monotonic_cubic_interpolate_angle_in_time (keeping the same argument
order) so the monotonic helper is exercised, then re-run tests and update the
expected doctest::Approx values to the correct baselines produced by the
monotonic implementation.
---
Outside diff comments:
In `@editor/animation/animation_track_editor.cpp`:
- Around line 3092-3117: The draw code still uses a 5-entry interp_icon lookup
which no longer matches the expanded interpolation enum (new monotonic entries),
causing wrong icons/UB; update the interp_icon array and any switch/lookup in
the drawing code to include icons for MENU_INTERPOLATION_CUBIC_MONOTONIC and
MENU_INTERPOLATION_CUBIC_MONOTONIC_ANGLE (and their angle/non-angle
counterparts), and adjust any index mapping logic so each interpolation enum
value maps to the correct icon (update references to interp_icon and the drawing
functions that read interpolation enum values). Ensure you add the corresponding
get_editor_theme_icon calls for the new monotonic variants and verify the lookup
size matches the enum range so no out-of-bounds access occurs.
In `@scene/resources/animation.h`:
- Around line 62-70: The enum InterpolationType was modified in a way that
shifts numeric IDs (specifically INTERPOLATION_LINEAR_ANGLE and
INTERPOLATION_CUBIC_ANGLE); restore backward compatibility by ensuring existing
values retain their original numeric IDs—either move
INTERPOLATION_CUBIC_MONOTONIC to the end of the enum list or add explicit
integer assignments for each enum entry so INTERPOLATION_NEAREST,
INTERPOLATION_LINEAR, INTERPOLATION_CUBIC, INTERPOLATION_LINEAR_ANGLE, and
INTERPOLATION_CUBIC_ANGLE keep their previous numeric values; update the
InterpolationType definition accordingly to avoid changing legacy serialized
IDs.
---
Nitpick comments:
In `@core/math/quaternion.cpp`:
- Around line 269-368: Both spherical_monotonic_cubic_interpolate and
spherical_monotonic_cubic_interpolate_in_time duplicate the phase-alignment,
flip handling, dual ExpMap and slerp blending logic; extract that shared flow
into a single helper (e.g., spherical_monotonic_cubic_interpolate_core) that
accepts a scalar interpolation callable (std::function or template parameter)
and any optional time arguments, so the two public methods call the core with
either Math::monotonic_cubic_interpolate or
Math::monotonic_cubic_interpolate_in_time; update the core to perform Basis
conversions, flip adjustments (from_q, pre_q, to_q, post_q), compute ln vectors
in both from_q and to_q spaces, call the provided scalar interpolator for x/y/z,
build q1/q2 and return q1.slerp(q2, p_weight), keeping the public function names
spherical_monotonic_cubic_interpolate and
spherical_monotonic_cubic_interpolate_in_time as thin wrappers.
In `@scene/resources/animation.cpp`:
- Around line 6566-6754: The two large switch+array traversal blocks in
Animation::monotonic_cubic_interpolate_in_time_variant and
Animation::cubic_interpolate_in_time_variant should be refactored into a single
helper (e.g., Animation::variant_cubic_dispatcher) that accepts a strategy flag
or function pointers for the primitive scalar/vector interpolation routines
(e.g., Math::cubic_interpolate_in_time vs
Math::monotonic_cubic_interpolate_in_time and the instance methods like
Vector2::monotonic_cubic_interpolate_in_time / cubic_interpolate_in_time,
Quaternion::spherical_monotonic_cubic_interpolate_in_time /
spherical_cubic_interpolate_in_time). Move the shared array handling and
type-switch logic into that helper and have the two public methods call it with
the appropriate primitive functions; ensure you preserve the special-casing
(numeric cast_to_blendwise/cast_from_blendwise, string fallback,
PACKED_BYTE_ARRAY skip, p_snap_array_element behavior) by passing any needed
flags through the helper.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a60ef8ef-5981-48e7-9a61-c26f77ab2797
📒 Files selected for processing (15)
core/math/math_funcs.hcore/math/quaternion.cppcore/math/quaternion.hcore/math/vector2.hcore/math/vector3.hcore/math/vector4.cppcore/math/vector4.hcore/variant/variant_call.cppcore/variant/variant_utility.cppcore/variant/variant_utility.heditor/animation/animation_track_editor.cppeditor/animation/animation_track_editor.hscene/resources/animation.cppscene/resources/animation.htests/core/math/test_math_funcs.h
| template <typename T> | ||
| constexpr T monotonic_cubic_interpolate_angle_in_time(T p_from, T p_to, T p_pre, T p_post, T p_weight, T p_pre_t, T p_to_t, T p_post_t) { | ||
| T from_rot = fmod(p_from, (T)TAU); | ||
|
|
||
| T pre_diff = fmod(p_pre - from_rot, (T)TAU); | ||
| T pre_rot = from_rot + fmod((T)2 * pre_diff, (T)TAU) - pre_diff; | ||
|
|
||
| T to_diff = fmod(p_to - from_rot, (T)TAU); | ||
| T to_rot = from_rot + fmod((T)2 * to_diff, (T)TAU) - to_diff; | ||
|
|
||
| T post_diff = fmod(p_post - to_rot, (T)TAU); | ||
| T post_rot = to_rot + fmod((T)2 * post_diff, (T)TAU) - post_diff; | ||
|
|
||
| return monotonic_cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Compare the positional argument order used by the existing and new angle-in-time helpers.
rg -n -C2 '\b(cubic_interpolate_angle_in_time|monotonic_cubic_interpolate_angle_in_time)\s*\(' --glob='*.{h,hpp,hh,c,cc,cpp,cxx}'Repository: Redot-Engine/redot-engine
Length of output: 7269
Fix parameter order for monotonic_cubic_interpolate_angle_in_time to match existing _in_time APIs.
The new function signature takes (p_pre_t, p_to_t, p_post_t) while the existing cubic_interpolate_angle_in_time() takes (p_to_t, p_pre_t, p_post_t). This breaks the API contract—any caller copied from the existing helper or using the pattern established by VariantUtilityFunctions will silently swap the pre and to timestamps, computing incorrect tangent magnitudes.
Suggested fix
template <typename T>
-constexpr T monotonic_cubic_interpolate_angle_in_time(T p_from, T p_to, T p_pre, T p_post, T p_weight, T p_pre_t, T p_to_t, T p_post_t) {
+constexpr T monotonic_cubic_interpolate_angle_in_time(T p_from, T p_to, T p_pre, T p_post, T p_weight, T p_to_t, T p_pre_t, T p_post_t) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| template <typename T> | |
| constexpr T monotonic_cubic_interpolate_angle_in_time(T p_from, T p_to, T p_pre, T p_post, T p_weight, T p_pre_t, T p_to_t, T p_post_t) { | |
| T from_rot = fmod(p_from, (T)TAU); | |
| T pre_diff = fmod(p_pre - from_rot, (T)TAU); | |
| T pre_rot = from_rot + fmod((T)2 * pre_diff, (T)TAU) - pre_diff; | |
| T to_diff = fmod(p_to - from_rot, (T)TAU); | |
| T to_rot = from_rot + fmod((T)2 * to_diff, (T)TAU) - to_diff; | |
| T post_diff = fmod(p_post - to_rot, (T)TAU); | |
| T post_rot = to_rot + fmod((T)2 * post_diff, (T)TAU) - post_diff; | |
| return monotonic_cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); | |
| template <typename T> | |
| constexpr T monotonic_cubic_interpolate_angle_in_time(T p_from, T p_to, T p_pre, T p_post, T p_weight, T p_to_t, T p_pre_t, T p_post_t) { | |
| T from_rot = fmod(p_from, (T)TAU); | |
| T pre_diff = fmod(p_pre - from_rot, (T)TAU); | |
| T pre_rot = from_rot + fmod((T)2 * pre_diff, (T)TAU) - pre_diff; | |
| T to_diff = fmod(p_to - from_rot, (T)TAU); | |
| T to_rot = from_rot + fmod((T)2 * to_diff, (T)TAU) - to_diff; | |
| T post_diff = fmod(p_post - to_rot, (T)TAU); | |
| T post_rot = to_rot + fmod((T)2 * post_diff, (T)TAU) - post_diff; | |
| return monotonic_cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/math/math_funcs.h` around lines 947 - 960, The function
monotonic_cubic_interpolate_angle_in_time has the timestamp parameters in the
wrong order (p_pre_t, p_to_t, p_post_t) which mismatches the established
_in_time API; change the signature to accept (T p_to_t, T p_pre_t, T p_post_t)
and update the call to monotonic_cubic_interpolate_in_time(...) to pass the
timestamps in the same order expected by that function (p_weight, p_to_t,
p_pre_t, p_post_t) so pre/to timestamps are not swapped; ensure the parameter
names in the function declaration/definition and any callers use the corrected
order to preserve API consistency with cubic_interpolate_angle_in_time and
VariantUtilityFunctions.
| double VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight, | ||
| double to_t, double pre_t, double post_t) { | ||
| return Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); |
There was a problem hiding this comment.
Fix swapped time arguments in angle monotonic wrapper (wrong interpolation behavior).
At Line 550, to_t and pre_t are forwarded in the wrong order for Math::monotonic_cubic_interpolate_angle_in_time.
core/math/math_funcs.h expects (..., p_pre_t, p_to_t, p_post_t). Current forwarding can distort angle interpolation timing.
🔧 Proposed fix
double VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight,
double to_t, double pre_t, double post_t) {
- return Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight, to_t, pre_t, post_t);
+ return Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight, pre_t, to_t, post_t);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| double VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight, | |
| double to_t, double pre_t, double post_t) { | |
| return Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); | |
| double VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight, | |
| double to_t, double pre_t, double post_t) { | |
| return Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight, pre_t, to_t, post_t); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@core/variant/variant_utility.cpp` around lines 548 - 550, The wrapper
VariantUtilityFunctions::monotonic_cubic_interpolate_angle_in_time forwards time
arguments to Math::monotonic_cubic_interpolate_angle_in_time in the wrong order,
swapping to_t and pre_t; fix it by calling
Math::monotonic_cubic_interpolate_angle_in_time(from, to, pre, post, weight,
pre_t, to_t, post_t) so that the forwarded times match Math's expected (p_pre_t,
p_to_t, p_post_t) parameter order.
| TEST_CASE_TEMPLATE("[Math] monotonic_cubic_interpolate_angle_in_time", T, float, double) { | ||
| CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0)); | ||
| CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964)); | ||
| CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627)); | ||
| CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394)); | ||
| CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0))); | ||
| } |
There was a problem hiding this comment.
This block never hits the monotonic angle-in-time helper.
All five assertions still call Math::cubic_interpolate_angle_in_time(), so this duplicates the cubic coverage and leaves Math::monotonic_cubic_interpolate_angle_in_time() untested. The copied expectations will also need re-baselining once the monotonic call is wired in.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@tests/core/math/test_math_funcs.h` around lines 694 - 700, The test block is
calling Math::cubic_interpolate_angle_in_time instead of the intended
Math::monotonic_cubic_interpolate_angle_in_time; update all five CHECK lines to
call Math::monotonic_cubic_interpolate_angle_in_time (keeping the same argument
order) so the monotonic helper is exercised, then re-run tests and update the
expected doctest::Approx values to the correct baselines produced by the
monotonic implementation.
Adds a Monotonic version of Cubic Interpolation. resolves #854
Cubic Interpolation is prone to overshooting during animations. This new feature allows for animations to be smooth but also doesn't overshoot the key frames.
The new function keeps the curve monotonic which means that the first derivative of the curve keeps the same sign, which cubic interpolation does not honor.
Here is the difference between Cubic and Monotonic Cubic for a curve going from 0 -> 90 -> 0 -> 0 -> 90.

screenrecording-2026-03-13_00-31-00.mp4
Summary by CodeRabbit