172 lines
4.5 KiB
C++
172 lines
4.5 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __NCURVE__
|
|
#define __NCURVE__
|
|
|
|
|
|
#include "math/nmath.h"
|
|
#include "metafile/nml.h"
|
|
#include "reflection/nenum_string.h"
|
|
#include "container/narray_list.h"
|
|
#include "time/ntime_range.h"
|
|
#include "time/ntime.h"
|
|
|
|
|
|
namespace GS {
|
|
|
|
static const float DefaultCurveOptimizationThreshold = 0.05f;
|
|
|
|
/*
|
|
@short Curve control point.
|
|
@author Emmanuel Julien (ejulien@nworks.fr)
|
|
*/
|
|
struct CurvePoint
|
|
{
|
|
NPLACEMENT_NEW(Curve)
|
|
|
|
/// Curve control point shape.
|
|
enum Shape
|
|
{
|
|
Shape_None = 0,
|
|
Shape_Linear,
|
|
Shape_TCB,
|
|
Shape_Hermite,
|
|
Shape_Bezier,
|
|
Shape_Bezier2,
|
|
Shape_Step
|
|
};
|
|
|
|
Shape shape;
|
|
|
|
Time t;
|
|
float v,
|
|
tension, continuity, bias,
|
|
param[4]; //< TCB parameters.
|
|
|
|
CurvePoint(const Time &time, float value, Shape shp = Shape_Linear) : t(time), v(value), shape(shp)
|
|
{
|
|
tension = 0;
|
|
continuity = 0;
|
|
bias = 0;
|
|
|
|
param[0] = param[1] = param[2] = param[3] = 0;
|
|
}
|
|
CurvePoint() : t(0), v(0), shape(Shape_Linear)
|
|
{
|
|
tension = 0;
|
|
continuity = 0;
|
|
bias = 0;
|
|
|
|
param[0] = param[1] = param[2] = param[3] = 0;
|
|
}
|
|
};
|
|
|
|
/*!
|
|
@short Curve object.
|
|
@author Emmanuel Julien (ejulien@nworks.fr)
|
|
*/
|
|
class Curve
|
|
{
|
|
public:
|
|
|
|
NPLACEMENT_NEW(Curve)
|
|
|
|
enum LoopMode
|
|
{
|
|
Reset = 0, ///< Returns 0.
|
|
Constant, ///< Returns first/last knot value.
|
|
Repeat, ///< Warp evaluation time to a value inside curve range and evaluate.
|
|
Oscillate, ///< Ping-pong style evaluation.
|
|
OffsetAndRepeat ///< Same as repeat but the whole curve is offset with the last knot value.
|
|
};
|
|
|
|
static Reflection::Enum::Dict loop_mode_dict[];
|
|
|
|
protected:
|
|
|
|
ArrayList <CurvePoint *> points; ///< Curve knots.
|
|
|
|
uint Optimize(uint point_count, const CurvePoint *src, CurvePoint *dst, float threshold);
|
|
|
|
public:
|
|
|
|
/// Evaluate curve at a given time.
|
|
void Evaluate(Time t, float *value, LoopMode loop_mode = Constant, Time loop_start = Time::Inf, Time loop_end = Time::Inf) const;
|
|
|
|
/// Evaluate incoming tangent to the curve.
|
|
float Incoming(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kf2) const;
|
|
/// Evaluate outgoing tangent to the curve.
|
|
float Outgoing(const CurvePoint *kf0, const CurvePoint *kf1, const CurvePoint *kfp) const;
|
|
|
|
/*!
|
|
@short Update a control point.
|
|
@note The time epsilon is considered on both side of the control
|
|
points time. If no point to update is found a new point is
|
|
inserted.
|
|
*/
|
|
void Update(const CurvePoint &, const Time &t_epsilon);
|
|
/// Insert a control point.
|
|
void Insert(const CurvePoint &);
|
|
/// Append a control point to the control point list.
|
|
void Append(const CurvePoint &);
|
|
|
|
/// Delete a curve control point from the channel.
|
|
void Delete(CurvePoint *);
|
|
|
|
/// Get curve time range, very fast.
|
|
TimeRange GetTimeRange() const;
|
|
/// Get curve value range, requires a full parsing of the knot list.
|
|
Range <float> GetValueRange() const;
|
|
|
|
/// Get curve range length in time.
|
|
Time GetDuration() const { return GetTimeRange().valueRange(); }
|
|
|
|
/// Optimize curve removing the less influential knots.
|
|
uint Optimize(float threshold = DefaultCurveOptimizationThreshold);
|
|
|
|
/// Return the curve control points as an array.
|
|
ArrayList <CurvePoint *> &GetPoints() { return points; }
|
|
/// Return the number of control point in curve.
|
|
uint GetPointCount() const { return points.GetCount(); }
|
|
|
|
/// Sort curve point array by time.
|
|
void Sort();
|
|
/*!
|
|
@short Set a control point content.
|
|
|
|
@Note This function does modify the internal ordering of the curve
|
|
keys in order to keep them time ordered.
|
|
Please use the Sort() function to make sure the curve can
|
|
still be correctly evaluated after a key time modification.
|
|
*/
|
|
void SetPoint(uint index, const CurvePoint &content) const;
|
|
|
|
/// Allocate a set of control points.
|
|
bool AllocatePoint(uint n);
|
|
|
|
/*!
|
|
@short Return the closest point on curve to a given time position.
|
|
The default behavior is to return the first point whose time is
|
|
greater than the query time.
|
|
*/
|
|
int GetPointIndex(const Time &time, bool t_greater_than = true) const;
|
|
|
|
void Clear();
|
|
|
|
virtual size_t MemoryFootPrint() const { return size_t(points.GetCount()) * sizeof(CurvePoint) + sizeof(Curve); }
|
|
|
|
bool FromMetaTag(NML::Tag &);
|
|
NML::Tag *AsMetaTag() const;
|
|
|
|
virtual ~Curve();
|
|
};
|
|
|
|
} // GS
|
|
|
|
|
|
#endif // __NCURVE__
|