119 lines
3.5 KiB
C
119 lines
3.5 KiB
C
|
/**
|
||
|
@file spline.h
|
||
|
|
||
|
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||
|
|
||
|
@created 2004-07-25
|
||
|
@edited 2007-05-05
|
||
|
*/
|
||
|
|
||
|
#ifndef G3D_SPLINEFUNC_H
|
||
|
#define G3D_SPLINEFUNC_H
|
||
|
|
||
|
#include "G3D/platform.h"
|
||
|
#include "G3D/debug.h"
|
||
|
#include "G3D/Array.h"
|
||
|
#include "G3D/g3dmath.h"
|
||
|
|
||
|
namespace G3D {
|
||
|
|
||
|
/**
|
||
|
Interpolates a property according to a piecewise linear spline. This provides
|
||
|
C0 continuity but the derivatives are not smooth.
|
||
|
<P>
|
||
|
Example:
|
||
|
<CODE>
|
||
|
const double times[] = {MIDNIGHT, SUNRISE - HOUR, SUNRISE, SUNRISE + sunRiseAndSetTime / 4, SUNRISE + sunRiseAndSetTime, SUNSET - sunRiseAndSetTime, SUNSET - sunRiseAndSetTime / 2, SUNSET, SUNSET + HOUR/2, DAY};
|
||
|
const Color3 color[] = {Color3(0, .0, .1), Color3(0, .0, .1), Color3::black(), Color3::black(), Color3::white() * .25, Color3::white() * .25, Color3(.5, .2, .2), Color3(.05, .05, .1), Color3(0, .0, .1), Color3(0, .0, .1)};
|
||
|
ambient = linearSpline(time, times, color, 10);
|
||
|
</CODE>
|
||
|
|
||
|
See also G3D::Spline
|
||
|
|
||
|
@param x The spline is a function of x; this is the sample to choose.
|
||
|
@param controlX controlX[i], controlY[i] is a control points. It is assumed
|
||
|
that controlX are strictly increasing. XType must support
|
||
|
the "<" operator and a subtraction operator that returns
|
||
|
a number.
|
||
|
@param controlY YType must support multiplication and addition.
|
||
|
@param numControl The number of control points.
|
||
|
*/
|
||
|
template<class XType, class YType>
|
||
|
YType linearSpline(double x, const XType* controlX, const YType* controlY, int numControl) {
|
||
|
debugAssert(numControl >= 1);
|
||
|
|
||
|
// Off the beginning
|
||
|
if ((numControl == 1) || (x < controlX[0])) {
|
||
|
return controlY[0];
|
||
|
}
|
||
|
|
||
|
for (int i = 1; i < numControl; ++i) {
|
||
|
if (x < controlX[i]) {
|
||
|
const double alpha = (double)(controlX[i] - x) / (controlX[i] - controlX[i - 1]);
|
||
|
return controlY[i] * (1 - alpha) + controlY[i - 1] * alpha;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Off the end
|
||
|
return controlY[numControl - 1];
|
||
|
}
|
||
|
|
||
|
|
||
|
/** See also G3D::Spline*/
|
||
|
template<class YType> YType cyclicCatmullRomSpline(
|
||
|
double t,
|
||
|
const YType* controlY,
|
||
|
int numPoints) {
|
||
|
|
||
|
debugAssert(numPoints >= 3);
|
||
|
|
||
|
t = wrap(t, numPoints);
|
||
|
|
||
|
// Find the indices of adjacent control points
|
||
|
int i = iFloor(t);
|
||
|
|
||
|
// Compute the distance from the control point
|
||
|
t = t - i;
|
||
|
|
||
|
// Shift back one point for correct indexing
|
||
|
i += numPoints - 1;
|
||
|
|
||
|
// Pick up four control points
|
||
|
const YType& P0 = controlY[(i + 0) % numPoints];
|
||
|
const YType& P1 = controlY[(i + 1) % numPoints];
|
||
|
const YType& P2 = controlY[(i + 2) % numPoints];
|
||
|
const YType& P3 = controlY[(i + 3) % numPoints];
|
||
|
|
||
|
return 0.5 * ((2 * P1) +
|
||
|
(-P0 + P2) * t +
|
||
|
(2*P0 - 5*P1 + 4*P2 - P3) * t*t +
|
||
|
(-P0 + 3*P1- 3*P2 + P3) * t*t*t);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
A cubic spline with regularly spaced
|
||
|
control points. The spline interpolates
|
||
|
the control points. The spline
|
||
|
will wrap from the last point back to the first.
|
||
|
|
||
|
The t parameter is on the range [0, controlY.size()],
|
||
|
where integers correspond to control points exactly.
|
||
|
|
||
|
See also G3D::Spline
|
||
|
|
||
|
@cite http://www.mvps.org/directx/articles/catmull/
|
||
|
*/
|
||
|
template<class YType> YType cyclicCatmullRomSpline(
|
||
|
double t,
|
||
|
const Array<YType>& controlY) {
|
||
|
|
||
|
int numPoints = controlY.size();
|
||
|
return cyclicCatmullRomSpline(t, controlY.getCArray(), numPoints);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|