From 5f006f139b5a7f4199b60ebfc6bf108bf57224ab Mon Sep 17 00:00:00 2001 From: Lingis Date: Wed, 12 Feb 2020 10:12:47 -0500 Subject: [PATCH] Not correct, wrong shape of curve created in Bezier::valueAt --- modules/autonavigation/helperfunctions.cpp | 30 ++++++----- modules/autonavigation/helperfunctions.h | 4 +- modules/autonavigation/pathcurves.cpp | 63 +++++++++++++++++++++- modules/autonavigation/pathcurves.h | 6 +++ 4 files changed, 88 insertions(+), 15 deletions(-) diff --git a/modules/autonavigation/helperfunctions.cpp b/modules/autonavigation/helperfunctions.cpp index 453ce20018..59144cfdef 100644 --- a/modules/autonavigation/helperfunctions.cpp +++ b/modules/autonavigation/helperfunctions.cpp @@ -53,29 +53,35 @@ namespace openspace::autonavigation::interpolation { glm::dvec3 linear(double t, const glm::dvec3 &cp1, const glm::dvec3 &cp2) { return cp1 * (1.0 - t) + cp2 * t; } - - glm::dvec3 piecewiseCubicBezier(double t, const std::vector &points) { + /* + // Interpolate a list of control points and knot times + glm::dvec3 piecewiseCubicBezier(double t, std::vector ×, const std::vector &points) { size_t n = points.size(); ghoul_assert(n > 4, "Minimum of four control points needed for interpolation!"); - ghoul_assert((n - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!"); size_t nrSegments = (size_t)std::floor((n - 1) / 3.0); - - // for points equally spaced in time - double tSegment = std::fmod(t*nrSegments, 1.0); - tSegment = std::max(0.0, std::min(tSegment, 1.0)); - - size_t idx = std::floor(t*nrSegments) * 3; - - // prevent stepping past the last segment if t = 1.0 - if (idx > n - 4) { + int nrTimes = times.size(); + ghoul_assert(nrSegments == nrTimes - 1, "Number of interval times must match number of intervals"); + + if (abs(1.0-t) < 0.00001) return points.back(); + if (nrTimes < 1) { + return points[0]; } + + // find current segmant and scale time + std::vector::iterator low = std::lower_bound(times.begin(), times.end(), t); + int segmentIdx = low - times.begin(); + + double tSegment = (t - times[segmentIdx]) / (times[segmentIdx + 1] - times[segmentIdx]); + + int idx = segmentIdx * 3; return cubicBezier(tSegment, points[idx], points[idx + 1], points[idx + 2], points[idx + 3]); } + */ glm::dvec3 piecewiseLinear(double t, const std::vector &points) { size_t n = points.size(); diff --git a/modules/autonavigation/helperfunctions.h b/modules/autonavigation/helperfunctions.h index 25fdd69e74..d6be2342c5 100644 --- a/modules/autonavigation/helperfunctions.h +++ b/modules/autonavigation/helperfunctions.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace openspace::autonavigation::helpers { @@ -50,7 +51,8 @@ namespace openspace::autonavigation::interpolation { glm::dvec3 linear(double t, const glm::dvec3 &cp1, const glm::dvec3 &cp2); - glm::dvec3 piecewiseCubicBezier(double t, const std::vector &controlPoints); + // Inside bezier3 + // glm::dvec3 piecewiseCubicBezier(double t, std::vector ×, const std::vector &points); glm::dvec3 piecewiseLinear(double t, const std::vector &controlPoints); diff --git a/modules/autonavigation/pathcurves.cpp b/modules/autonavigation/pathcurves.cpp index ec038b4825..a13776ceee 100644 --- a/modules/autonavigation/pathcurves.cpp +++ b/modules/autonavigation/pathcurves.cpp @@ -129,10 +129,69 @@ Bezier3Curve::Bezier3Curve(CameraState& start, CameraState& end) { _points.push_back(end.position + endTangentLength * endTangentDirection); _points.push_back(end.position); + + + // initial interval times + int nrIntervals = (int)std::floor((_points.size() - 1) / 3.0); //TODO valivate! + + for (double time = 0.0; time <= 1.0; time += 1.0 / nrIntervals) { + _intervalTimes.push_back(time); + } + // TODO: test that time == 1 is included + + reparameterizeByArcLength(); +} +/* +glm::dvec3 Bezier3Curve::valueAt(double t) { + return interpolation::piecewiseCubicBezier(t, _intervalTimes, _points); +} +*/ + +// Interpolate a list of control points and knot times +glm::dvec3 Bezier3Curve::valueAt(double t) { + size_t n = _points.size(); + ghoul_assert(n > 4, "Minimum of four control points needed for interpolation!"); + ghoul_assert((n - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!"); + + size_t nrSegments = (size_t)std::floor((n - 1) / 3.0); + int nrTimes = _intervalTimes.size(); + ghoul_assert(nrSegments == nrTimes - 1, "Number of interval times must match number of intervals"); + + if (abs(1.0 - t) < 0.00001) + return _points.back(); + if (nrTimes < 1) { + return _points[0]; + } + + // find current segmant and scale time + std::vector::iterator low = std::lower_bound(_intervalTimes.begin(), _intervalTimes.end(), t); + int segmentIdx = low - _intervalTimes.begin(); + + double tSegment = (t - _intervalTimes[segmentIdx]) / (_intervalTimes[segmentIdx + 1] - _intervalTimes[segmentIdx]); + + int idx = segmentIdx * 3; + + return interpolation::cubicBezier(tSegment, _points[idx], _points[idx + 1], + _points[idx + 2], _points[idx + 3]); } -glm::dvec3 Bezier3Curve::valueAt(double t) { - return interpolation::piecewiseCubicBezier(t, _points); +void Bezier3Curve::reparameterizeByArcLength() { + // For bezier every third is a knot shaed beetween segments + int nrIntervals = (int)std::floor((float)(_points.size() - 1) / 3.0); //TODO valivate! + + if (nrIntervals == 1) { + return; + } + + double totalLength = arcLength(1.0); //THIS IS WHERE IT GOES INTO INTERPOLATOR WITHOUT ANY VALUES IN TIMES VECTOR IF >! SEGMENTS OTHERWISE IN PATHSEGMENT::INITCURVE + std::vector newTimes; + + // Save time as relative curve length from start to each knot + for ( double time : _intervalTimes) { + newTimes.push_back(arcLength(time) / totalLength); + } + + _intervalTimes.swap(newTimes); } LinearCurve::LinearCurve(CameraState& start, CameraState& end) { diff --git a/modules/autonavigation/pathcurves.h b/modules/autonavigation/pathcurves.h index 56d9353811..051eb39ac6 100644 --- a/modules/autonavigation/pathcurves.h +++ b/modules/autonavigation/pathcurves.h @@ -39,6 +39,7 @@ public: std::vector getPoints(); // for debugging double arcLength(double tLimit = 1.0); + protected: // the points used for creating the curve (e.g. control points of a Bezier curve) std::vector _points; @@ -48,6 +49,11 @@ class Bezier3Curve : public PathCurve { public: Bezier3Curve(CameraState& start, CameraState& end); glm::dvec3 valueAt(double t); + +private: + void reparameterizeByArcLength(); + + std::vector _intervalTimes; }; class LinearCurve : public PathCurve {