| /* |
| * Copyright 2024 Rive |
| */ |
| |
| #pragma once |
| |
| #include "rive/math/simd.hpp" |
| #include "rive/math/vec2d.hpp" |
| |
| namespace rive::pls |
| { |
| // Optimized SIMD helper for evaluating a single cubic at many points. |
| class EvalCubic |
| { |
| public: |
| inline EvalCubic(const Vec2D pts[]) |
| { |
| // Cubic power-basis form: |
| // |
| // | 1 0 0 0| |P0| |
| // Cubic(T) = x,y = |1 t t^2 t^3| * |-3 3 0 0| * |P1| |
| // | 3 -6 3 0| |P2| |
| // |-1 3 -3 1| |P3| |
| // |
| // Find the cubic's power basis coefficients. These define the bezier curve as: |
| // |
| // |t^3| |
| // Cubic(T) = x,y = |A B C| * |t^2| + P0 |
| // |. . .| |t | |
| // |
| // (Duplicate coefficients across a float4 so we can evaluate two at once.) |
| m_P0 = simd::load2f(pts + 0).xyxy; |
| float4 P1 = simd::load2f(pts + 1).xyxy; |
| float4 P2 = simd::load2f(pts + 2).xyxy; |
| float4 P3 = simd::load2f(pts + 3).xyxy; |
| m_C = 3.f * (P1 - m_P0); |
| float4 D = 3.f * (P2 - P1); |
| float4 E = P3 - m_P0; |
| m_B = D - m_C; |
| m_A = E - D; |
| } |
| |
| // Evaluates [Xa, Ya, Xb, Yb] at locations [Ta, Ta, Tb, Tb]. |
| inline float4 at(float4 t) const |
| { |
| return t * (t * (t * m_A + m_B) + m_C) + m_P0; // At^3 + Bt^2 + Ct + P0 |
| } |
| |
| private: |
| float4 m_A; |
| float4 m_B; |
| float4 m_C; |
| float4 m_P0; |
| }; |
| } // namespace rive::pls |