155 lines
4.7 KiB
C++
155 lines
4.7 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CryEngine Source code
|
|
//
|
|
// File:BSplineOpen
|
|
// Declaration of class BSplineVec3d (originally only open, but now
|
|
// capable of being a closed spline)
|
|
//
|
|
// History:
|
|
// 06/17/2002 :Created by Sergiy Migdalskiy <sergiy@crytek.de>
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
#pragma once
|
|
|
|
#include "BSplineKnots.h"
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
// This is a general B-Spline that can interpolate any values (like vectors or scalars)
|
|
// that support linear combination operations + and *
|
|
// Upon construction, you specify the number of unique knots (the extra knots are
|
|
// automatically added to maintain inclusive boundary condition) and the degree
|
|
// The number of control ponints you are to supply afterwards through the []
|
|
// operator is:
|
|
// numCPs() == nNumKnots + d - 1 // for open spline
|
|
// numCPs() == nNumKnots - 1 // for closed spline
|
|
// This is natural spline without derivative boundary conditions.
|
|
// The total number of extra knots added is 2*d, d for each boundary
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
// Value is the value that's interpolated by this BSpline
|
|
// Desc is the descriptor class with some static members describing
|
|
// how to treat the spline: as a closed or open one
|
|
class BSplineVec3d:
|
|
public _reference_target_t
|
|
{
|
|
public:
|
|
typedef Vec3 Value;
|
|
typedef BSplineKnots::Time Time;
|
|
typedef BSplineKnots::Value BlendValue;
|
|
|
|
// number of unique knots passed, and the degree
|
|
// the array of control points is NOT initialized
|
|
BSplineVec3d (int numKnots, int nDegree, bool isOpen);
|
|
~BSplineVec3d(void);
|
|
|
|
bool isOpen() {return m_isOpen;}
|
|
|
|
// retrieves the number of basis functions (and thus unique control points) involved
|
|
int numCPs()const
|
|
{
|
|
return m_isOpen ? numKnots() + m_nDegree - 1 : numKnots() - 1;
|
|
}
|
|
// number of unique knots maintained
|
|
int numKnots()const
|
|
{
|
|
return m_Knots.numKnots() - 2 * m_nDegree;
|
|
}
|
|
|
|
// retrieves a reference to the i-th control point
|
|
Value& operator [] (int i)
|
|
{
|
|
assert (i >= 0 && i < numCPs());
|
|
return m_arrCPs[i];
|
|
}
|
|
|
|
// retrieves a reference to the i-th control point
|
|
const Value& operator [] (int i)const
|
|
{
|
|
return getCP(i);
|
|
}
|
|
|
|
// retrieves a reference to the i-th control point
|
|
const Value& getCP (int i) const
|
|
{
|
|
assert (i >= 0 && i < numCPs());
|
|
return m_arrCPs[i];
|
|
}
|
|
|
|
// sets the given control point
|
|
void setCP (int i, const Value& pt)
|
|
{
|
|
assert (i >= 0 && i < numCPs());
|
|
m_arrCPs[i] = pt;
|
|
}
|
|
|
|
// computes the value of the spline at the given time
|
|
Value getValue (Time fTime)const;
|
|
|
|
// computes the value of the spline at the given time t
|
|
Value operator () (Time fTime) const
|
|
{
|
|
return getValue (fTime);
|
|
}
|
|
|
|
// sets the given unique knot time
|
|
void setKnotTime (int nKnot, Time fTime);
|
|
|
|
// call this after setting all knot times
|
|
void finalizeKnotTimes();
|
|
|
|
// retrieves the knot time, knot index is in the unique knot indexation (i.e. normally 0th != 1st)
|
|
Time getKnotTime (int nKnot)const;
|
|
|
|
// retrives the basis function value for the given control point at the given time
|
|
BlendValue getBasis (int nControlPoint, Time fTime) const;
|
|
|
|
// Returns the basis function starting at knot i (m_Knot internal numeration)
|
|
// The function is calculated at time t, on the interval nIntervalT (m_Knot numeration)
|
|
BlendValue getBasis (int i, Time t, int nIntervalT) const;
|
|
|
|
// get the d+1 derivative (delta) amplitude at knot k
|
|
Value getDelta (int k);
|
|
|
|
// return the spline degree
|
|
int getDegree()const
|
|
{
|
|
return m_nDegree;
|
|
}
|
|
|
|
// retrives the boundaries of the influence of the given control point, in time:
|
|
// pTime[0] is the starting knot, pTime[1] is the end knot
|
|
// NOTE: end knot may be < start knot; it means the support interval is cyclic
|
|
void getInfluenceInterval (int nControlPoint, int pTime[2]) const;
|
|
|
|
// Returns the P (product) penalty for knot closeness, as defined by Mary J. Lindstrom "Penalized Estimation of Free Knot Splines" 1999,
|
|
// logarithmic form
|
|
double getKnotProductPenalty()
|
|
{
|
|
return m_Knots.getKnotProductPenalty(m_nDegree, m_isOpen?numCPs() : m_nDegree+numKnots()-1);
|
|
}
|
|
|
|
// returns the time at which the given CP has the maximum influence at the curve
|
|
BSplineKnots::Time getCPPeak (int nControlPoint)
|
|
{
|
|
return m_Knots.getBasisPeak (nControlPoint + (m_isOpen?0:m_nDegree), m_nDegree);
|
|
}
|
|
protected:
|
|
// Modifies the given time so that it fits inside the spline boundaries.
|
|
void fixupTime(Time& fTime)const;
|
|
|
|
// degree of the spline
|
|
const int m_nDegree;
|
|
|
|
// array of control ponits
|
|
TElementaryArray<Value> m_arrCPs;
|
|
|
|
// knot array
|
|
BSplineKnots m_Knots;
|
|
|
|
// is the spline open?
|
|
bool m_isOpen;
|
|
};
|
|
|
|
TYPEDEF_AUTOPTR(BSplineVec3d);
|