10 #ifndef hifi_CubicHermiteSpline_h
11 #define hifi_CubicHermiteSpline_h
13 #include "GLMHelpers.h"
15 class CubicHermiteSplineFunctor {
17 CubicHermiteSplineFunctor() : _p0(), _m0(), _p1(), _m1() {}
18 CubicHermiteSplineFunctor(
const glm::vec3& p0,
const glm::vec3& m0,
const glm::vec3& p1,
const glm::vec3& m1) : _p0(p0), _m0(m0), _p1(p1), _m1(m1) {}
20 CubicHermiteSplineFunctor(
const CubicHermiteSplineFunctor& orig) : _p0(orig._p0), _m0(orig._m0), _p1(orig._p1), _m1(orig._m1) {}
22 CubicHermiteSplineFunctor& operator=(
const CubicHermiteSplineFunctor&) =
default;
24 virtual ~CubicHermiteSplineFunctor() {}
27 glm::vec3 operator()(
float t)
const {
30 float w0 = 2.0f * t3 - 3.0f * t2 + 1.0f;
31 float w1 = t3 - 2.0f * t2 + t;
32 float w2 = -2.0f * t3 + 3.0f * t2;
34 return w0 * _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
38 glm::vec3 d(
float t)
const {
40 float w0 = -6.0f * t + 6.0f * t2;
41 float w1 = 1.0f - 4.0f * t + 3.0f * t2;
42 float w2 = 6.0f * t - 6.0f * t2;
43 float w3 = -2.0f * t + 3.0f * t2;
44 return w0 * _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
48 glm::vec3 d2(
float t)
const {
49 float w0 = -6.0f + 12.0f * t;
50 float w1 = -4.0f + 6.0f * t;
51 float w2 = 6.0f - 12.0f * t;
52 float w3 = -2.0f + 6.0f * t;
53 return w0 + _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
63 class CubicHermiteSplineFunctorWithArcLength :
public CubicHermiteSplineFunctor {
65 enum Constants { NUM_SUBDIVISIONS = 15 };
67 CubicHermiteSplineFunctorWithArcLength() : CubicHermiteSplineFunctor() {
68 memset(_values, 0,
sizeof(
float) * (NUM_SUBDIVISIONS + 1));
70 CubicHermiteSplineFunctorWithArcLength(
const glm::vec3& p0,
const glm::vec3& m0,
const glm::vec3& p1,
const glm::vec3& m1) : CubicHermiteSplineFunctor(p0, m0, p1, m1) {
75 CubicHermiteSplineFunctorWithArcLength(
const glm::quat& tipRot,
const glm::vec3& tipTrans,
const glm::quat& baseRot,
const glm::vec3& baseTrans,
float baseGain = 1.0f,
float tipGain = 1.0f) : CubicHermiteSplineFunctor() {
77 float linearDistance = glm::length(baseTrans - tipTrans);
79 _m0 = baseGain * linearDistance * (baseRot * Vectors::UNIT_Y);
81 _m1 = tipGain * linearDistance * (tipRot * Vectors::UNIT_Y);
86 CubicHermiteSplineFunctorWithArcLength(
const CubicHermiteSplineFunctorWithArcLength& orig) : CubicHermiteSplineFunctor(orig) {
87 memcpy(_values, orig._values,
sizeof(
float) * (NUM_SUBDIVISIONS + 1));
90 CubicHermiteSplineFunctorWithArcLength& operator=(
const CubicHermiteSplineFunctorWithArcLength&) =
default;
93 float arcLength(
float t)
const {
94 float index = t * NUM_SUBDIVISIONS;
95 int prevIndex = std::min(std::max(0, (
int)glm::floor(index)), (
int)NUM_SUBDIVISIONS);
96 int nextIndex = std::min(std::max(0, (
int)glm::ceil(index)), (
int)NUM_SUBDIVISIONS);
97 float alpha = glm::fract(index);
98 return lerp(_values[prevIndex], _values[nextIndex], alpha);
102 float arcLengthInverse(
float s)
const {
105 for (nextIndex = 0; nextIndex < NUM_SUBDIVISIONS; nextIndex++) {
106 if (_values[nextIndex] > s) {
110 int prevIndex = std::min(std::max(0, nextIndex - 1), (
int)NUM_SUBDIVISIONS);
111 float alpha = glm::clamp((s - _values[prevIndex]) / (_values[nextIndex] - _values[prevIndex]), 0.0f, 1.0f);
112 const float DELTA = 1.0f / NUM_SUBDIVISIONS;
113 return lerp(prevIndex * DELTA, nextIndex * DELTA, alpha);
116 float _values[NUM_SUBDIVISIONS + 1];
120 const float DELTA = 1.0f / NUM_SUBDIVISIONS;
124 for (
int i = 1; i < NUM_SUBDIVISIONS + 1; i++) {
125 accum += glm::distance(this->
operator()(alpha),
126 this->
operator()(alpha + DELTA));