Core/Movement: Allow overwriting number of steps for spline length calculations

* Also minor cleanup of non-virtual functions in spline derived classes
This commit is contained in:
Shauren
2022-06-07 15:13:54 +02:00
parent 45f056d574
commit b9353041a6
3 changed files with 26 additions and 35 deletions

View File

@@ -165,9 +165,9 @@ float SplineBase::SegLengthCatmullRom(index_type index) const
index_type i = 1;
float length = 0;
while (i <= STEPS_PER_SEGMENT)
while (i <= stepsPerSegment)
{
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos);
C_Evaluate(p, float(i) / float(stepsPerSegment), s_catmullRomCoeffs, nextPos);
length += (nextPos - curPos).length();
curPos = nextPos;
++i;
@@ -188,9 +188,9 @@ float SplineBase::SegLengthBezier3(index_type index) const
index_type i = 1;
float length = 0;
while (i <= STEPS_PER_SEGMENT)
while (i <= stepsPerSegment)
{
C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos);
C_Evaluate(p, float(i) / float(stepsPerSegment), s_Bezier3Coeffs, nextPos);
length += (nextPos - curPos).length();
curPos = nextPos;
++i;

View File

@@ -51,14 +51,11 @@ protected:
bool cyclic;
float initialOrientation;
enum{
// could be modified, affects segment length evaluation precision
// lesser value saves more performance in cost of lover precision
// minimal value is 1
// client's value is 20, blizzs use 2-3 steps to compute length
STEPS_PER_SEGMENT = 3
};
static_assert(STEPS_PER_SEGMENT > 0, "STEPS_PER_SEGMENT shouldn't be lesser than 1");
// could be modified, affects segment length evaluation precision
// lesser value saves more performance in cost of lover precision
// minimal value is 1
// client's value is 20, blizzs use 2-3 steps to compute length
index_type stepsPerSegment = 3;
protected:
void EvaluateLinear(index_type, float, Vector3&) const;
@@ -122,21 +119,24 @@ public:
Vector3 const& getPoint(index_type i) const { return points[i]; }
/** Initializes spline. Don't call other methods while spline not initialized. */
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m, float orientation);
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation);
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m, float orientation = 0.0f);
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation = 0.0f);
/** As i can see there are a lot of ways how spline can be initialized
would be no harm to have some custom initializers. */
template<class Init> inline void init_spline_custom(Init& initializer)
template<class Init>
void init_spline_custom(Init& initializer)
{
initializer(m_mode, cyclic, points, index_lo, index_hi);
}
void clear();
virtual void clear();
/** Calculates distance between [i; i+1] points, assumes that index i is in bounds. */
float SegLength(index_type i) const { return (this->*seglengths[m_mode])(i);}
void set_steps_per_segment(index_type newStepsPerSegment) { stepsPerSegment = newStepsPerSegment; }
std::string ToString() const;
};
@@ -159,34 +159,25 @@ public:
@param t - percent of spline's length, assumes that t in range [0, 1]. */
void evaluate_percent(float t, Vector3 & c) const;
using SplineBase::evaluate_percent;
/** Calculates derivation for given t
@param t - percent of spline's length, assumes that t in range [0, 1]. */
void evaluate_derivative(float t, Vector3& hermite) const;
/** Calculates the position for given segment Idx, and percent of segment length t
@param t = partial_segment_length / whole_segment_length
@param Idx - spline segment index, should be in range [first, last). */
void evaluate_percent(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_percent(Idx, u, c);}
/** Caclulates derivation for index Idx, and percent of segment length t
@param Idx - spline segment index, should be in range [first, last)
@param t - percent of spline segment length, assumes that t in range [0, 1]. */
void evaluate_derivative(index_type Idx, float u, Vector3& c) const { SplineBase::evaluate_derivative(Idx, u, c);}
using SplineBase::evaluate_derivative;
// Assumes that t in range [0, 1]
index_type computeIndexInBounds(float t) const;
void computeIndex(float t, index_type& out_idx, float& out_u) const;
/** Initializes spline. Don't call other methods while spline not initialized. */
void init_spline(const Vector3 * controls, index_type count, EvaluationMode m, float orientation = 0) { SplineBase::init_spline(controls, count, m, orientation);}
void init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation = 0) { SplineBase::init_cyclic_spline(controls, count, m, cyclic_point, orientation);}
/** Initializes lengths with SplineBase::SegLength method. */
void initLengths();
/** Initializes lengths in some custom way
Note that value returned by cacher must be greater or equal to previous value. */
template<class T> inline void initLengths(T& cacher)
template<class T>
void initLengths(T& cacher)
{
index_type i = index_lo;
lengths.resize(index_hi+1);
@@ -216,7 +207,7 @@ public:
length_type length(index_type Idx) const { return lengths[Idx];}
void set_length(index_type i, length_type length) { lengths[i] = length;}
void clear();
void clear() override;
};
}

View File

@@ -60,13 +60,13 @@ template<typename length_type> SplineBase::index_type Spline<length_type>::compu
return i;
}
template<typename length_type> void Spline<length_type>::computeIndex(float t, index_type& index, float& u) const
template<typename length_type> void Spline<length_type>::computeIndex(float t, index_type& out_idx, float& out_u) const
{
ASSERT(t >= 0.f && t <= 1.f);
length_type length_ = t * length();
index = computeIndexInBounds(length_);
ASSERT(index < index_hi);
u = (length_ - length(index)) / (float)length(index, index+1);
out_idx = computeIndexInBounds(length_);
ASSERT(out_idx < index_hi);
out_u = (length_ - length(out_idx)) / (float)length(out_idx, out_idx+1);
}
template<typename length_type> SplineBase::index_type Spline<length_type>::computeIndexInBounds( float t ) const