 TrinityCore
G3D::SplineBase Class Reference

`#include <Spline.h>`

## Public Member Functions

SplineBase ()

virtual ~SplineBase ()

float getFinalInterval () const

float duration () const

void computeIndex (float s, int &i, float &u) const

## Static Public Member Functions

static Matrix4 computeBasis ()

## Public Attributes

Array< float > time

SplineExtrapolationMode extrapolationMode

float finalInterval

SplineInterpolationMode interpolationMode

## Protected Member Functions

void computeIndexInBounds (float s, int &i, float &u) const

## Detailed Description

Common implementation code for all G3D::Spline template parameters

## Constructor & Destructor Documentation

 G3D::SplineBase::SplineBase ( )
inline
46  :
48  finalInterval(-1),
SplineExtrapolationMode extrapolationMode
Definition: Spline.h:33
Definition: SplineExtrapolationMode.h:67
float finalInterval
Definition: Spline.h:42
Definition: SplineExtrapolationMode.h:34
SplineInterpolationMode interpolationMode
Definition: Spline.h:44
 virtual G3D::SplineBase::~SplineBase ( )
inlinevirtual
51 {}

## Member Function Documentation

 Matrix4 G3D::SplineBase::computeBasis ( )
static

Computes the derivative spline basis from the control point version.

22  {
23  // The standard Catmull-Rom spline basis (e.g., Watt & Watt p108)
24  // is for [u^3 u^2 u^1 u^0] * B * [p p p p]^T.
25  // We need a basis formed for:
26  //
27  // U * C * [2*p' p p 2*p']^T
28  //
29  // U * C * [p2-p0 p1 p2 p3-p1]^T
30  //
31  // To make this transformation, compute the differences of columns in C:
32  // For [p0 p1 p2 p3]
33  Matrix4 basis =
34  Matrix4( -1, 3, -3, 1,
35  2, -5, 4, -1,
36  -1, 0, 1, 0,
37  0, 2, 0, 0) * 0.5f;
38
39  // For [-p0 p1 p2 p3]^T
40  basis.setColumn(0, -basis.column(0));
41
42  // For [-p0 p1 p2 p3-p1]^T
43  basis.setColumn(1, basis.column(1) + basis.column(3));
44
45  // For [p2-p0 p1 p2 p3-p1]^T
46  basis.setColumn(2, basis.column(2) - basis.column(0));
47
48  return basis;
49 } Here is the call graph for this function: Here is the caller graph for this function:

 void G3D::SplineBase::computeIndex ( float s, int & i, float & u ) const

Given a time s, finds i and 0 <= u < 1 such that s = time[i] * u + time[i + 1] * (1 - u). Note that i may be outside the bounds of the time and control arrays; use getControl to handle wraparound and extrapolation issues.

This function takes expected O(1) time for control points with uniform time sampled control points or for uniformly distributed random time samples, but may take O( log time.size() ) time in the worst case.

Called from evaluate().

90  {
91  int N = time.size();
92  debugAssertM(N > 0, "No control points");
93  float t0 = time;
94  float tn = time[N - 1];
95
96  if (N < 2) {
97  // No control points to work with
98  i = 0;
99  u = 0.0;
101  float fi = getFinalInterval();
102
103  // Cyclic spline
104  if ((s < t0) || (s >= tn + fi)) {
105  // Cyclic, off the bottom or top
106
107  // Compute offset and reduce to the in-bounds case
108
109  float d = duration();
110  // Number of times we wrapped around the cyclic array
111  int wraps = iFloor((s - t0) / d);
112
113  debugAssert(s - d * wraps >= t0);
114  debugAssert(s - d * wraps < tn + getFinalInterval());
115
116  computeIndex(s - d * wraps, i, u);
117  i += wraps * N;
118
119  } else if (s >= tn) {
120  debugAssert(s < tn + fi);
121  // Cyclic, off the top but before the end of the last interval
122  i = N - 1;
123  u = (s - tn) / fi;
124
125  } else {
126  // Cyclic, in bounds
127  computeIndexInBounds(s, i, u);
128  }
129
130  } else {
131  // Non-cyclic
132
133  if (s < t0) {
134  // Non-cyclic, off the bottom. Assume points are spaced
135  // following the first time interval.
136
137  float dt = time - t0;
138  float x = (s - t0) / dt;
139  i = iFloor(x);
140  u = x - i;
141
142  } else if (s >= tn) {
143  // Non-cyclic, off the top. Assume points are spaced following
144  // the last time interval.
145
146  float dt = tn - time[N - 2];
147  float x = N - 1 + (s - tn) / dt;
148  i = iFloor(x);
149  u = x - i;
150
151  } else {
152  // In bounds, non-cyclic. Assume a regular
153  // distribution (which gives O(1) for uniform spacing)
154  // and then binary search to handle the general case
155  // efficiently.
156  computeIndexInBounds(s, i, u);
157
158  } // if in bounds
159  } // extrapolation Mode
160 }
void computeIndex(float s, int &i, float &u) const
Definition: SplineBase.cpp:90
void computeIndexInBounds(float s, int &i, float &u) const
Definition: SplineBase.cpp:61
SplineExtrapolationMode extrapolationMode
Definition: Spline.h:33
Definition: SplineExtrapolationMode.h:34
int iFloor(double fValue)
Definition: g3dmath.h:603
Array< float > time
Definition: Spline.h:26
#define debugAssertM(exp, message)
Definition: debugAssert.h:161
float getFinalInterval() const
Definition: SplineBase.cpp:6
#define debugAssert(exp)
Definition: debugAssert.h:160
int size() const
Definition: Array.h:430
float duration() const
Definition: SplineBase.cpp:52
G3D::int16 x
Definition: Vector2int16.h:37 Here is the call graph for this function: Here is the caller graph for this function:

 void G3D::SplineBase::computeIndexInBounds ( float s, int & i, float & u ) const
protected

Assumes that t0 <= s < tn. called by computeIndex.

61  {
62  int N = time.size();
63  float t0 = time;
64  float tn = time[N - 1];
65
66  i = iFloor((N - 1) * (s - t0) / (tn - t0));
67
68  // Inclusive bounds for binary search
69  int hi = N - 1;
70  int lo = 0;
71
72  while ((time[i] > s) || (time[i + 1] <= s)) {
73
74  if (time[i] > s) {
75  // too big
76  hi = i - 1;
77  } else if (time[i + 1] <= s) {
78  // too small
79  lo = i + 1;
80  }
81
82  i = (hi + lo) / 2;
83  }
84
85  // Having exited the above loop, i must be correct, so compute u.
86  u = (s - time[i]) / (time[i + 1] - time[i]);
87 }
int iFloor(double fValue)
Definition: g3dmath.h:603
Array< float > time
Definition: Spline.h:26
int size() const
Definition: Array.h:430 Here is the call graph for this function: Here is the caller graph for this function:

 float G3D::SplineBase::duration ( ) const

Returns the amount of time covered by this spline in one period. For a cyclic spline, this contains the final interval.

52  {
53  if (time.size() == 0) {
54  return 0;
55  } else {
56  return time.last() - time + getFinalInterval();
57  }
58 }
const T & last() const
Definition: Array.h:923
Array< float > time
Definition: Spline.h:26
float getFinalInterval() const
Definition: SplineBase.cpp:6
int size() const
Definition: Array.h:430 Here is the call graph for this function: Here is the caller graph for this function:

 float G3D::SplineBase::getFinalInterval ( ) const

See specification for Spline::finalInterval; this handles the non-positive case. Returns 0 if not cyclic.

6  {
8  return 0;
9  } else if (finalInterval <= 0) {
10  int N = time.size();
11  if (N >= 2) {
12  return (time - time + time[N - 1] - time[N - 2]) * 0.5f;
13  } else {
14  return 1.0f;
15  }
16  } else {
17  return finalInterval;
18  }
19 }
SplineExtrapolationMode extrapolationMode
Definition: Spline.h:33
float finalInterval
Definition: Spline.h:42
Definition: SplineExtrapolationMode.h:34
Array< float > time
Definition: Spline.h:26
int size() const
Definition: Array.h:430 Here is the call graph for this function: Here is the caller graph for this function:

## Member Data Documentation

 SplineExtrapolationMode G3D::SplineBase::extrapolationMode

If CYCLIC, then the control points will be assumed to wrap around. If LINEAR, then the tangents at the ends of the spline point to the final control points. If CONSTANT, the end control points will be treated as multiple contol points (so the value remains constant at the ends)

 float G3D::SplineBase::finalInterval

For a cyclic spline, this is the time elapsed between the last control point and the first. If less than or equal to zero this is assumed to be:

(time - time + . time[time.size() - 1] - time[time.size() - 2]) / 2.

 SplineInterpolationMode G3D::SplineBase::interpolationMode
 Array G3D::SplineBase::time

Times at which control points occur. Must have the same number of elements as Spline::control.

The documentation for this class was generated from the following files: