10 #ifndef hifi_CubicHermiteSpline_h
11 #define hifi_CubicHermiteSpline_h
13 #include "GLMHelpers.h"
17 class CubicHermiteSplineFunctor {
19 CubicHermiteSplineFunctor() : _p0(), _m0(), _p1(), _m1() {}
20 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) {}
22 CubicHermiteSplineFunctor(
const CubicHermiteSplineFunctor& orig) : _p0(orig._p0), _m0(orig._m0), _p1(orig._p1), _m1(orig._m1) {}
24 CubicHermiteSplineFunctor& operator=(
const CubicHermiteSplineFunctor&) =
default;
26 virtual ~CubicHermiteSplineFunctor() {}
29 glm::vec3 operator()(
float t)
const {
32 float w0 = 2.0f * t3 - 3.0f * t2 + 1.0f;
33 float w1 = t3 - 2.0f * t2 + t;
34 float w2 = -2.0f * t3 + 3.0f * t2;
36 return w0 * _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
40 glm::vec3 d(
float t)
const {
42 float w0 = -6.0f * t + 6.0f * t2;
43 float w1 = 1.0f - 4.0f * t + 3.0f * t2;
44 float w2 = 6.0f * t - 6.0f * t2;
45 float w3 = -2.0f * t + 3.0f * t2;
46 return w0 * _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
50 glm::vec3 d2(
float t)
const {
51 float w0 = -6.0f + 12.0f * t;
52 float w1 = -4.0f + 6.0f * t;
53 float w2 = 6.0f - 12.0f * t;
54 float w3 = -2.0f + 6.0f * t;
55 return w0 + _p0 + w1 * _m0 + w2 * _p1 + w3 * _m1;
65 class CubicHermiteSplineFunctorWithArcLength :
public CubicHermiteSplineFunctor {
67 static const int NUM_SUBDIVISIONS = 15;
69 CubicHermiteSplineFunctorWithArcLength() : CubicHermiteSplineFunctor() {
70 memset(_values, 0,
sizeof(
float) * (NUM_SUBDIVISIONS + 1));
72 CubicHermiteSplineFunctorWithArcLength(
const glm::vec3& p0,
const glm::vec3& m0,
const glm::vec3& p1,
const glm::vec3& m1) : CubicHermiteSplineFunctor(p0, m0, p1, m1) {
77 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() {
79 float linearDistance = glm::length(baseTrans - tipTrans);
81 _m0 = baseGain * linearDistance * (baseRot * Vectors::UNIT_Y);
83 _m1 = tipGain * linearDistance * (tipRot * Vectors::UNIT_Y);
88 CubicHermiteSplineFunctorWithArcLength(
const CubicHermiteSplineFunctorWithArcLength& orig) : CubicHermiteSplineFunctor(orig) {
89 memcpy(_values, orig._values,
sizeof(
float) * (NUM_SUBDIVISIONS + 1));
92 CubicHermiteSplineFunctorWithArcLength& operator=(
const CubicHermiteSplineFunctorWithArcLength&) =
default;
95 float arcLength(
float t)
const {
96 float index = t * NUM_SUBDIVISIONS;
97 int prevIndex = std::min(std::max(0, (
int)glm::floor(index)), (
int)NUM_SUBDIVISIONS);
98 int nextIndex = std::min(std::max(0, (
int)glm::ceil(index)), (
int)NUM_SUBDIVISIONS);
99 float alpha = glm::fract(index);
100 return std::lerp(_values[prevIndex], _values[nextIndex], alpha);
104 float arcLengthInverse(
float s)
const {
107 for (nextIndex = 0; nextIndex < NUM_SUBDIVISIONS; nextIndex++) {
108 if (_values[nextIndex] > s) {
112 int prevIndex = std::min(std::max(0, nextIndex - 1), (
int)NUM_SUBDIVISIONS);
113 float alpha = glm::clamp((s - _values[prevIndex]) / (_values[nextIndex] - _values[prevIndex]), 0.0f, 1.0f);
114 const float DELTA = 1.0f / NUM_SUBDIVISIONS;
115 return std::lerp(prevIndex * DELTA, nextIndex * DELTA, alpha);
118 float _values[NUM_SUBDIVISIONS + 1];
122 const float DELTA = 1.0f / NUM_SUBDIVISIONS;
126 for (
int i = 1; i < NUM_SUBDIVISIONS + 1; i++) {
127 accum += glm::distance(this->
operator()(alpha),
128 this->
operator()(alpha + DELTA));