aboutsummaryrefslogtreecommitdiff
path: root/externals/g3dlite/G3D/Spline.h
diff options
context:
space:
mode:
Diffstat (limited to 'externals/g3dlite/G3D/Spline.h')
-rw-r--r--externals/g3dlite/G3D/Spline.h367
1 files changed, 0 insertions, 367 deletions
diff --git a/externals/g3dlite/G3D/Spline.h b/externals/g3dlite/G3D/Spline.h
deleted file mode 100644
index fdd29e69ce9..00000000000
--- a/externals/g3dlite/G3D/Spline.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/**
- @file Spline.h
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- */
-
-#ifndef G3D_SPLINE_H
-#define G3D_SPLINE_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Vector4.h"
-
-namespace G3D {
-
-/** Common implementation code for all G3D::Spline template parameters */
-class SplineBase {
-public:
-
- /** Times at which control points occur. Must have the same
- number of elements as Spline::control. */
- Array<float> time;
-
- /** If cyclic, then the control points will be assumed to wrap around.
- If not cyclic, then the tangents at the ends of the spline
- point to the final control points.*/
- bool cyclic;
-
- /** 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[0] - time[1] + .
- time[time.size() - 1] - time[time.size() - 2]) / 2.
- */
- float finalInterval;
-
- SplineBase() : cyclic(true), finalInterval(-1) {}
-
- virtual ~SplineBase() {}
-
- /** See specification for Spline::finalInterval; this handles the
- non-positive case. Returns 0 if not cyclic. */
- float getFinalInterval() const;
-
- /** Returns the amount of time covered by this spline in one
- period. For a cyclic spline, this contains the final
- interval.*/
- float duration() const;
-
- /** Computes the derivative spline basis from the control point version. */
- static Matrix4 computeBasis();
-
-protected:
-
- /** Assumes that t0 <= s < tn. called by computeIndex. */
- void computeIndexInBounds(float s, int& i, float& u) const;
-
-public:
-
- /**
- Given a time @a s, finds @a i and 0 <= @a u < 1 such that
- @a s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that
- @a 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().
- */
- void computeIndex(float s, int& i, float& u) const;
-};
-
-
-/**
- Smooth parameteric curve implemented using a piecewise 3rd-order
- Catmull-Rom spline curve. The spline is considered infinite and may
- either continue linearly from the specified control points or cycle
- through them. Control points are spaced uniformly in time at unit
- intervals by default, but irregular spacing may be explicitly
- specified.
-
- The dimension of the spline can be set by varying the Control
- template parameter. For a 1D function, use Spline<float>. For a
- curve in the plane, Spline<Vector2>. Note that <i>any</i> template
- parameter that supports operator+(Control) and operator*(float) can
- be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or
- your own classes.
-
- To provide shortest-path interpolation, subclass G3D::Spline and
- override ensureShortestPath(). To provide normalization of
- interpolated points (e.g., projecting Quats onto the unit
- hypersphere) override correct().
-
- See Real Time Rendering, 2nd edition, ch 12 for a general discussion
- of splines and their properties.
-
- @sa G3D::UprightSpline, G3D::QuatSpline
- */
-template<typename Control>
-class Spline : public SplineBase {
-protected:
- /** The additive identity control point. */
- Control zero;
-
-public:
-
- /** Control points. Must have the same number of elements as
- Spline::time.*/
- Array<Control> control;
-
- Spline() {
- static Control x;
- // Hide the fact from C++ that we are using an
- // uninitialized variable here by pointer arithmetic.
- // This is ok because any type that is a legal control
- // point also supports multiplication by float.
- zero = *(&x) * 0.0f;
- }
-
- /** Appends a control point at a specific time that must be
- greater than that of the previous point. */
- void append(float t, const Control& c) {
- debugAssertM((time.size() == 0) || (t > time.last()),
- "Control points must have monotonically increasing times.");
- time.append(t);
- control.append(c);
- debugAssert(control.size() == time.size());
- }
-
-
- /** Appends control point spaced in time based on the previous
- control point, or spaced at unit intervals if this is the
- first control point. */
- void append(const Control& c) {
- switch (time.size()) {
- case 0:
- append(0, c);
- break;
-
- case 1:
- if (time[0] == 0) {
- append(1, c);
- } else {
- append(time[0], c);
- }
- break;
-
- default:
- append(2 * time[time.size() - 1] - time[time.size() - 2], c);
- }
- debugAssert(control.size() == time.size());
- }
-
- /** Erases all control points and times, but retains the state of
- cyclic and finalInterval.
- */
- void clear() {
- control.clear();
- time.clear();
- }
-
-
- /** Number of control points */
- int size() const {
- debugAssert(time.size() == control.size());
- return control.size();
- }
-
-
- /** Returns the requested control point and time sample based on
- array index. If the array index is out of bounds, wraps (for
- a cyclic spline) or linearly extrapolates (for a non-cyclic
- spline), assuming time intervals follow the first or last
- sample recorded.
-
- Calls correct() on the control point if it was extrapolated.
-
- Returns 0 if there are no control points.
-
- @sa Spline::control and Spline::time for the underlying
- control point array; Spline::computeIndex to find the index
- given a time.
- */
- void getControl(int i, float& t, Control& c) const {
- int N = control.size();
- if (N == 0) {
- c = zero;
- t = 0;
- } else if (cyclic) {
- c = control[iWrap(i, N)];
-
- if (i < 0) {
- // Wrapped around bottom
-
- // Number of times we wrapped around the cyclic array
- int wraps = (N + 1 - i) / N;
- int j = (i + wraps * N) % N;
- t = time[j] - wraps * duration();
-
- } else if (i < N) {
-
- t = time[i];
-
- } else {
- // Wrapped around top
-
- // Number of times we wrapped around the cyclic array
- int wraps = i / N;
- int j = i % N;
- t = time[j] + wraps * duration();
- }
-
- } else if (i < 0) {
- // Are there enough points to extrapolate?
- if (N >= 2) {
- // Step away from control point 0
- float dt = time[1] - time[0];
-
- // Extrapolate (note; i is negative)
- c = control[1] * float(i) + control[0] * float(1 - i);
- correct(c);
- t = dt * i + time[0];
-
- } else {
- // Just clamp
- c = control[0];
-
- // Only 1 time; assume 1s intervals
- t = time[0] + i;
- }
-
- } else if (i >= N) {
- if (N >= 2) {
- float dt = time[N - 1] - time[N - 2];
-
- // Extrapolate
- c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1);
- correct(c);
- t = time[N - 1] + dt * (i - N + 1);
-
- } else {
- // Return the last, clamping
- c = control.last();
- // Only 1 time; assume 1s intervals
- t = time[0] + i;
- }
- } else {
- // In bounds
- c = control[i];
- t = time[i];
- }
- }
-
-protected:
-
- /** Returns a series of N control points and times, fixing
- boundary issues. The indices may be assumed to be treated
- cyclically. */
- void getControls(int i, float* T, Control* A, int N) const {
- for (int j = 0; j < N; ++j) {
- getControl(i + j, T[j], A[j]);
- }
- ensureShortestPath(A, N);
- }
-
- /**
- Mutates the array of N control points. It is useful to override this
- method by one that wraps the values if they are angles or quaternions
- for which "shortest path" interpolation is significant.
- */
- virtual void ensureShortestPath(Control* A, int N) const { (void)A; (void) N;}
-
- /** Normalize or otherwise adjust this interpolated Control. */
- virtual void correct(Control& A) const { (void)A; }
-
-public:
-
-
- /**
- Return the position at time s. The spline is defined outside
- of the time samples by extrapolation or cycling.
- */
- Control evaluate(float s) const {
- debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points.");
-
- /*
- @cite http://www.gamedev.net/reference/articles/article1497.asp
- Derivation of basis matrix follows.
-
- Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position
- at time t[1] <= s <= t[2].
-
- Let u = s - t[0]
- Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3]
- Let dt0 = t[0] - t[-1]
- Let dt1 = t[1] - t[0]
- Let dt2 = t[2] - t[1]
- */
-
- // Index of the first control point (i.e., the u = 0 point)
- int i = 0;
- // Fractional part of the time
- float u = 0;
-
- computeIndex(s, i, u);
-
- Control p[4];
- float t[4];
- getControls(i - 1, t, p, 4);
- float dt0 = t[1] - t[0];
- float dt1 = t[2] - t[1];
- float dt2 = t[3] - t[2];
-
- static const Matrix4 basis = computeBasis();
-
- // Powers of u
- Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f);
-
- // Compute the weights on each of the control points.
- const Vector4& weights = uvec * basis;
-
- // Compute the weighted sum of the neighboring control points.
- Control sum;
-
- const Control& p0 = p[0];
- const Control& p1 = p[1];
- const Control& p2 = p[2];
- const Control& p3 = p[3];
-
- const Control& dp0 = p1 + (p0*-1.0f);
- const Control& dp1 = p2 + (p1*-1.0f);
- const Control& dp2 = p3 + (p2*-1.0f);
-
- // The factor of 1/2 from averaging two time intervals is
- // already factored into the basis
-
- // tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5);
- // The last term normalizes for unequal time intervals
- float x = (dt0 + dt1) * 0.5f;
- float n0 = x / dt0;
- float n1 = x / dt1;
- float n2 = x / dt2;
- const Control& dp1n1 = dp1 * n1;
- const Control& tan1 = dp0 * n0 + dp1n1;
- const Control& tan2 = dp1n1 + dp2 * n2;
-
- sum =
- tan1 * weights[0]+
- p1 * weights[1] +
- p2 * weights[2] +
- tan2 * weights[3];
-
-
- correct(sum);
- return sum;
- }
-};
-
-}
-
-#endif