00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if !defined(INCLUDED_MATH_CURVE_H)
00028 #define INCLUDED_MATH_CURVE_H
00029
00030 #include "debugging/debugging.h"
00031 #include "container/array.h"
00032 #include <math/matrix.h>
00033
00034 template<typename I, typename Degree>
00035 struct BernsteinPolynomial
00036 {
00037 static double apply (double t)
00038 {
00039 return 1;
00040 }
00041 };
00042
00043 typedef IntegralConstant<0> Zero;
00044 typedef IntegralConstant<1> One;
00045 typedef IntegralConstant<2> Two;
00046 typedef IntegralConstant<3> Three;
00047 typedef IntegralConstant<4> Four;
00048
00049 template<>
00050 struct BernsteinPolynomial<Zero, Zero>
00051 {
00052 static double apply (double t)
00053 {
00054 return 1;
00055 }
00056 };
00057
00058 template<>
00059 struct BernsteinPolynomial<Zero, One>
00060 {
00061 static double apply (double t)
00062 {
00063 return 1 - t;
00064 }
00065 };
00066
00067 template<>
00068 struct BernsteinPolynomial<One, One>
00069 {
00070 static double apply (double t)
00071 {
00072 return t;
00073 }
00074 };
00075
00076 template<>
00077 struct BernsteinPolynomial<Zero, Two>
00078 {
00079 static double apply (double t)
00080 {
00081 return (1 - t) * (1 - t);
00082 }
00083 };
00084
00085 template<>
00086 struct BernsteinPolynomial<One, Two>
00087 {
00088 static double apply (double t)
00089 {
00090 return 2 * (1 - t) * t;
00091 }
00092 };
00093
00094 template<>
00095 struct BernsteinPolynomial<Two, Two>
00096 {
00097 static double apply (double t)
00098 {
00099 return t * t;
00100 }
00101 };
00102
00103 template<>
00104 struct BernsteinPolynomial<Zero, Three>
00105 {
00106 static double apply (double t)
00107 {
00108 return (1 - t) * (1 - t) * (1 - t);
00109 }
00110 };
00111
00112 template<>
00113 struct BernsteinPolynomial<One, Three>
00114 {
00115 static double apply (double t)
00116 {
00117 return 3 * (1 - t) * (1 - t) * t;
00118 }
00119 };
00120
00121 template<>
00122 struct BernsteinPolynomial<Two, Three>
00123 {
00124 static double apply (double t)
00125 {
00126 return 3 * (1 - t) * t * t;
00127 }
00128 };
00129
00130 template<>
00131 struct BernsteinPolynomial<Three, Three>
00132 {
00133 static double apply (double t)
00134 {
00135 return t * t * t;
00136 }
00137 };
00138
00139 typedef Array<Vector3> ControlPoints;
00140
00141 inline Vector3 CubicBezier_evaluate (const Vector3* firstPoint, double t)
00142 {
00143 Vector3 result(0, 0, 0);
00144 double denominator = 0;
00145
00146 {
00147 double weight = BernsteinPolynomial<Zero, Three>::apply(t);
00148 result += (*firstPoint++) * weight;
00149 denominator += weight;
00150 }
00151 {
00152 double weight = BernsteinPolynomial<One, Three>::apply(t);
00153 result += (*firstPoint++) * weight;
00154 denominator += weight;
00155 }
00156 {
00157 double weight = BernsteinPolynomial<Two, Three>::apply(t);
00158 result += (*firstPoint++) * weight;
00159 denominator += weight;
00160 }
00161 {
00162 double weight = BernsteinPolynomial<Three, Three>::apply(t);
00163 result += (*firstPoint++) * weight;
00164 denominator += weight;
00165 }
00166
00167 return result / denominator;
00168 }
00169
00170 inline Vector3 CubicBezier_evaluateMid (const Vector3* firstPoint)
00171 {
00172 return firstPoint[0] * 0.125 + firstPoint[1] * 0.375 + firstPoint[2] * 0.375 + firstPoint[3] * 0.125;
00173 }
00174
00175 inline Vector3 CatmullRom_evaluate (const ControlPoints& controlPoints, double t)
00176 {
00177
00178 t *= double(controlPoints.size() - 1);
00179
00180
00181 std::size_t segment = 0;
00182 for (std::size_t i = 0; i < controlPoints.size() - 1; ++i) {
00183 if (t <= double(i + 1)) {
00184 segment = i;
00185 break;
00186 }
00187 }
00188 t -= segment;
00189
00190 const double reciprocal_alpha = 1.0 / 3.0;
00191
00192 Vector3 bezierPoints[4];
00193 bezierPoints[0] = controlPoints[segment];
00194 bezierPoints[1] = (segment > 0) ? controlPoints[segment]
00195 + (controlPoints[segment + 1] - controlPoints[segment - 1]) * (reciprocal_alpha * 0.5)
00196 : controlPoints[segment] + (controlPoints[segment + 1] - controlPoints[segment]) * reciprocal_alpha;
00197 bezierPoints[2] = (segment < controlPoints.size() - 2) ? controlPoints[segment + 1] + (controlPoints[segment]
00198 - controlPoints[segment + 2]) * (reciprocal_alpha * 0.5) : controlPoints[segment + 1]
00199 + (controlPoints[segment] - controlPoints[segment + 1]) * reciprocal_alpha;
00200 bezierPoints[3] = controlPoints[segment + 1];
00201 return CubicBezier_evaluate(bezierPoints, t);
00202 }
00203
00204 typedef Array<float> Knots;
00205
00206 inline double BSpline_basis (const Knots& knots, std::size_t i, std::size_t degree, double t)
00207 {
00208 if (degree == 0) {
00209 if (knots[i] <= t && t < knots[i + 1] && knots[i] < knots[i + 1]) {
00210 return 1;
00211 }
00212 return 0;
00213 }
00214 double leftDenom = knots[i + degree] - knots[i];
00215 double left = (leftDenom == 0) ? 0 : ((t - knots[i]) / leftDenom) * BSpline_basis(knots, i, degree - 1, t);
00216 double rightDenom = knots[i + degree + 1] - knots[i + 1];
00217 double right = (rightDenom == 0) ? 0 : ((knots[i + degree + 1] - t) / rightDenom) * BSpline_basis(knots, i + 1,
00218 degree - 1, t);
00219 return left + right;
00220 }
00221
00222 inline Vector3 BSpline_evaluate (const ControlPoints& controlPoints, const Knots& knots, std::size_t degree, double t)
00223 {
00224 Vector3 result(0, 0, 0);
00225 for (std::size_t i = 0; i < controlPoints.size(); ++i) {
00226 result += controlPoints[i] * BSpline_basis(knots, i, degree, t);
00227 }
00228 return result;
00229 }
00230
00231 typedef Array<float> NURBSWeights;
00232
00233 inline Vector3 NURBS_evaluate (const ControlPoints& controlPoints, const NURBSWeights& weights, const Knots& knots,
00234 std::size_t degree, double t)
00235 {
00236 Vector3 result(0, 0, 0);
00237 double denominator = 0;
00238 for (std::size_t i = 0; i < controlPoints.size(); ++i) {
00239 double weight = weights[i] * BSpline_basis(knots, i, degree, t);
00240 result += controlPoints[i] * weight;
00241 denominator += weight;
00242 }
00243 return result / denominator;
00244 }
00245
00246 inline void KnotVector_openUniform (Knots& knots, std::size_t count, std::size_t degree)
00247 {
00248 knots.resize(count + degree + 1);
00249
00250 std::size_t equalKnots = 1;
00251
00252 for (std::size_t i = 0; i < equalKnots; ++i) {
00253 knots[i] = 0;
00254 knots[knots.size() - (i + 1)] = 1;
00255 }
00256
00257 std::size_t difference = knots.size() - 2 * (equalKnots);
00258 for (std::size_t i = 0; i < difference; ++i) {
00259 knots[i + equalKnots] = Knots::value_type(double(i + 1) * 1.0 / double(difference + 1));
00260 }
00261 }
00262
00263 #endif