15 #ifndef MOTIVE_MATH_COMPACT_SPLINE_H_
16 #define MOTIVE_MATH_COMPACT_SPLINE_H_
18 #include "motive/common.h"
19 #include "motive/math/compact_spline_node.h"
20 #include "motive/math/curve.h"
24 class BulkSplineEvaluator;
28 typedef uint16_t CompactSplineIndex;
29 static const CompactSplineIndex kInvalidSplineIndex =
30 static_cast<CompactSplineIndex
>(-1);
31 static const CompactSplineIndex kBeforeSplineIndex =
32 static_cast<CompactSplineIndex
>(-2);
33 static const CompactSplineIndex kAfterSplineIndex =
34 static_cast<CompactSplineIndex
>(-3);
35 static const CompactSplineIndex kMaxSplineIndex =
36 static_cast<CompactSplineIndex
>(-4);
39 inline bool OutsideSpline(CompactSplineIndex index) {
40 return index >= kAfterSplineIndex;
43 enum CompactSplineAddMethod {
44 kAddWithoutModification,
45 kEnsureCubicWellBehaved,
85 Init(y_range, x_granularity);
90 CompactSpline& operator=(
const CompactSpline& rhs) {
91 assert(rhs.num_nodes_ <= max_nodes_);
92 y_range_ = rhs.y_range_;
93 x_granularity_ = rhs.x_granularity_;
94 num_nodes_ = rhs.num_nodes_;
95 memcpy(nodes_, rhs.nodes_, rhs.num_nodes_ *
sizeof(nodes_[0]));
117 void Init(
const Range& y_range,
const float x_granularity) {
120 x_granularity_ = x_granularity;
150 void AddNode(
const float x,
const float y,
const float derivative,
151 const CompactSplineAddMethod method = kEnsureCubicWellBehaved);
156 const CompactSplineAngle angle) {
200 max_nodes_ = num_nodes_;
223 p.ptr += idx *
Size();
239 CompactSplineIndex
IndexForX(
const float x,
240 const CompactSplineIndex guess_index)
const;
245 const float x,
const CompactSplineIndex guess_index,
246 const bool repeat,
float* final_x)
const;
252 CompactSplineIndex
ClampIndex(
const CompactSplineIndex index,
float* x)
const;
255 float StartX()
const {
return Front().X(x_granularity_); }
256 float StartY()
const {
return Front().Y(y_range_); }
257 float StartDerivative()
const {
return nodes_[0].Derivative(); }
259 float EndX()
const {
return Back().X(x_granularity_); }
260 float EndY()
const {
return Back().Y(y_range_); }
261 float EndDerivative()
const {
return Back().Derivative(); }
262 float NodeX(
const CompactSplineIndex index)
const;
263 float NodeY(
const CompactSplineIndex index)
const;
264 float NodeDerivative(
const CompactSplineIndex index)
const {
265 assert(index < num_nodes_);
266 return nodes_[index].Derivative();
268 float LengthX()
const {
return EndX() - StartX(); }
269 Range RangeX()
const {
return Range(StartX(), EndX()); }
270 const Range& RangeY()
const {
return y_range_; }
282 float CalculatedSlowly(
const float x,
const CurveValueType value_type)
const;
287 void Ys(
const float start_x,
const float delta_x,
const size_t num_points,
288 float* ys,
float* derivatives =
nullptr)
const;
291 Range RangeX(
const CompactSplineIndex index)
const;
300 assert(num_nodes_ >= 1);
301 return num_nodes_ - 1;
306 assert(num_nodes_ >= 2);
307 return num_nodes_ - 2;
311 CompactSplineIndex
num_nodes()
const {
return num_nodes_; }
312 CompactSplineIndex max_nodes()
const {
return max_nodes_; }
316 const Range& y_range()
const {
return y_range_; }
317 float x_granularity()
const {
return x_granularity_; }
325 uint8_t* buffer =
new uint8_t[
Size(max_nodes)];
336 spline->max_nodes_ = max_nodes;
346 assert(num_nodes <= kMaxSplineIndex);
362 assert(num_nodes <= kMaxSplineIndex);
364 CreateInPlace(static_cast<CompactSplineIndex>(num_nodes), buffer);
378 assert(num_nodes <= kMaxSplineIndex);
394 assert(num_nodes <= kMaxSplineIndex);
396 CreateInPlace(static_cast<CompactSplineIndex>(num_nodes), buffer);
405 if (spline ==
nullptr)
return;
407 delete[]
reinterpret_cast<uint8_t*
>(spline);
419 uint8_t* buffer =
new uint8_t[
Size(max_nodes) * num_splines];
433 int num_splines,
void* buffer) {
434 const size_t size =
Size(max_nodes);
435 uint8_t* b =
reinterpret_cast<uint8_t*
>(buffer);
436 for (
int i = 0; i < num_splines; ++i) {
445 if (splines ==
nullptr)
return;
447 delete[]
reinterpret_cast<uint8_t*
>(splines);
456 static size_t Size(CompactSplineIndex max_nodes) {
460 const size_t kAlignMask =
sizeof(float) - 1;
463 const size_t aligned = (size + kAlignMask) & ~kAlignMask;
473 return num_splines * kBaseSize +
487 virtual void AddPoint(
int point_index,
495 const size_t num_splines,
const float start_x,
496 const float delta_x,
const size_t num_points,
513 const size_t num_splines,
const float start_x,
514 const float delta_x,
const size_t num_points,
float* ys,
515 float* derivatives =
nullptr);
520 template <
int kDimensions>
522 const float delta_x,
const size_t num_ys,
523 mathfu::VectorPacked<float, kDimensions>* ys) {
524 BulkYs(splines, kDimensions, start_x, delta_x, num_ys,
525 reinterpret_cast<float*>(ys));
529 static const size_t kBaseSize;
533 assert(num_nodes_ < max_nodes_);
534 nodes_[num_nodes_++] = node;
538 bool IndexContainsX(
const CompactSplineXGrain compact_x,
539 const CompactSplineIndex index)
const;
542 CompactSplineIndex BinarySearchIndexForX(
543 const CompactSplineXGrain compact_x)
const;
546 float WidthX(
const detail::CompactSplineNode& s,
547 const detail::CompactSplineNode& e)
const {
548 return (e.x() - s.x()) * x_granularity_;
553 const detail::CompactSplineNode& e)
const;
555 const detail::CompactSplineNode& Front()
const {
556 assert(num_nodes_ > 0);
560 const detail::CompactSplineNode& Back()
const {
561 assert(num_nodes_ > 0);
562 return nodes_[num_nodes_ - 1];
569 float x_granularity_;
572 CompactSplineIndex num_nodes_;
576 CompactSplineIndex max_nodes_;
635 SplineState(
float y,
float derivative) : y(y), derivative(derivative) {}
644 : current(current), spline(&spline) {}
649 #endif // MOTIVE_MATH_COMPACT_SPLINE_H_
float y_scale
Definition: compact_spline.h:624
CompactSplineIndex IndexForX(const float x, const CompactSplineIndex guess_index) const
CompactSplineIndex IndexForXAllowingRepeat(const float x, const CompactSplineIndex guess_index, const bool repeat, float *final_x) const
void Finalize()
Definition: compact_spline.h:199
void AddUncompressedNodes(const UncompressedNode *nodes, size_t num_nodes)
static size_t ArraySize(size_t num_splines, size_t num_nodes)
Definition: compact_spline.h:472
Float representation of a point on the spline.
Definition: compact_spline.h:55
Initialization parameters to create a cubic curve with start and end y-values and derivatives...
Definition: curve.h:335
bool repeat
If true, start back at the beginning after we reach the end.
Definition: compact_spline.h:627
Traverse through a set of splines in a performant way.
Definition: bulk_spline_evaluator.h:37
void Init(const Range &y_range, const float x_granularity)
Definition: compact_spline.h:117
void InitFromNodes(const UncompressedNode *nodes, size_t num_nodes)
Definition: compact_spline_node.h:55
Definition: compact_spline.h:638
SplinePlayback(float start_x=0.0f, bool repeat=false, float playback_rate=1.0f, float blend_x=0.0f, float y_offset=0.0f, float y_scale=1.0f)
Definition: compact_spline.h:593
float CalculatedSlowly(const float x, const CurveValueType value_type) const
static void BulkEvaluate(const CompactSpline *const splines, const size_t num_splines, const float start_x, const float delta_x, const size_t num_points, BulkOutput *out)
Definition: compact_spline.h:484
CompactSpline * Next()
Definition: compact_spline.h:211
static CompactSpline * CreateArrayInPlace(CompactSplineIndex max_nodes, int num_splines, void *buffer)
Definition: compact_spline.h:432
void AddNodeVerbatim(const CompactSplineXGrain x, const CompactSplineYRung y, const CompactSplineAngle angle)
Definition: compact_spline.h:155
static void BulkYs(const CompactSpline *const splines, const float start_x, const float delta_x, const size_t num_ys, mathfu::VectorPacked< float, kDimensions > *ys)
Definition: compact_spline.h:521
CompactSplineIndex LastNodeIndex() const
Returns the index of the last node in the spline.
Definition: compact_spline.h:299
float blend_x
Definition: compact_spline.h:608
static CompactSpline * CreateInPlace(CompactSplineIndex max_nodes, void *buffer)
Definition: compact_spline.h:333
void Ys(const float start_x, const float delta_x, const size_t num_points, float *ys, float *derivatives=nullptr) const
CompactSpline * NextAtIdx(int idx)
Definition: compact_spline.h:216
CompactSplineIndex num_nodes() const
Returns the number of nodes in this spline.
Definition: compact_spline.h:311
float start_x
The starting point from which to play.
Definition: compact_spline.h:604
static float RecommendXGranularity(const float max_x)
static CompactSpline * CreateFromNodes(const UncompressedNode *nodes, size_t num_nodes)
Definition: compact_spline.h:344
static void Destroy(CompactSpline *spline)
Definition: compact_spline.h:404
static CompactSpline * CreateArray(CompactSplineIndex max_nodes, int num_splines)
Definition: compact_spline.h:417
CompactSplineIndex LastSegmentIndex() const
Returns the start index of the last segment in the spline.
Definition: compact_spline.h:305
Parameters to specify how a spline should be traversed.
Definition: compact_spline.h:590
static size_t Size(CompactSplineIndex max_nodes)
Definition: compact_spline.h:456
size_t Size() const
Returns the memory occupied by this spline.
Definition: compact_spline.h:207
static CompactSpline * CreateFromSpline(const CompactSpline &source_spline, size_t num_nodes)
Definition: compact_spline.h:376
static CompactSpline * CreateFromNodesInPlace(const UncompressedNode *nodes, size_t num_nodes, void *buffer)
Definition: compact_spline.h:360
Definition: compact_spline.h:630
float YCalculatedSlowly(const float x) const
Definition: compact_spline.h:275
void Clear()
Remove all nodes from the spline.
Definition: compact_spline.h:204
static CompactSpline * Create(CompactSplineIndex max_nodes)
Definition: compact_spline.h:324
static void DestroyArray(CompactSpline *splines, int)
Frees the memory allocated with CreateArray() using global delete.
Definition: compact_spline.h:444
static void BulkYs(const CompactSpline *const splines, const size_t num_splines, const float start_x, const float delta_x, const size_t num_points, float *ys, float *derivatives=nullptr)
static const CompactSplineIndex kDefaultMaxNodes
Definition: compact_spline.h:79
Represent a smooth curve in a small amount of memory.
Definition: compact_spline.h:73
float playback_rate
Definition: compact_spline.h:616
void InitFromSpline(const CompactSpline &spline)
void AddNode(const float x, const float y, const float derivative, const CompactSplineAddMethod method=kEnsureCubicWellBehaved)
CubicInit CreateCubicInit(const CompactSplineIndex index) const
const detail::CompactSplineNode * nodes() const
Return const versions of internal values. For serialization.
Definition: compact_spline.h:315
static CompactSpline * CreateFromSplineInPlace(const CompactSpline &source_spline, size_t num_nodes, void *buffer)
Definition: compact_spline.h:392
CompactSplineIndex ClampIndex(const CompactSplineIndex index, float *x) const
Represent an interval on a number line.
Definition: range.h:37
float y_offset
Definition: compact_spline.h:620