Added support for bezier interpolation.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3684 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -57,22 +57,22 @@ Ipo::Ipo(const XMLNode &curve, float fps)
|
||||
for(unsigned int i=0; i<curve.getNumNodes(); i++)
|
||||
{
|
||||
const XMLNode *node = curve.getNode(i);
|
||||
Vec3 xy;
|
||||
node->get2("c", &xy);
|
||||
core::vector2df xy;
|
||||
node->get("c", &xy);
|
||||
// Convert blender's frame number (1 ...) into time (0 ...)
|
||||
float t = (xy.getX()-1)/fps;
|
||||
float t = (xy.X-1)/fps;
|
||||
if(t<m_min_time) m_min_time = t;
|
||||
if(t>m_max_time) m_max_time = t;
|
||||
xy.setX(t);
|
||||
xy.X = t;
|
||||
m_points.push_back(xy);
|
||||
if(m_interpolation==IP_BEZIER)
|
||||
{
|
||||
Vec3 handle;
|
||||
node->get2("h1", &handle);
|
||||
handle.setX((xy.getX()-1)/fps);
|
||||
core::vector2df handle;
|
||||
node->get("h1", &handle);
|
||||
handle.X = (xy.X-1)/fps;
|
||||
m_handle1.push_back(handle);
|
||||
node->get2("h2", &handle);
|
||||
handle.setX((xy.getX()-1)/fps);
|
||||
node->get("h2", &handle);
|
||||
handle.X = (xy.X-1)/fps;
|
||||
m_handle2.push_back(handle);
|
||||
}
|
||||
} // for i<getNumNodes()
|
||||
@@ -139,19 +139,29 @@ float Ipo::get() const
|
||||
// Search for the first point in the (sorted) array which is greater or equal
|
||||
// to the current time.
|
||||
// FIXME: we should store the last point to speed this up!
|
||||
while(n<m_points.size()-1 && m_time >=m_points[n].getX())
|
||||
while(n<m_points.size()-1 && m_time >=m_points[n].X)
|
||||
n++;
|
||||
n--;
|
||||
switch(m_interpolation)
|
||||
{
|
||||
case IP_CONST : return m_points[n].getY();
|
||||
case IP_CONST : return m_points[n].Y;
|
||||
case IP_LINEAR : {
|
||||
float t = m_time-m_points[n].getX();
|
||||
return m_points[n].getY() + t*(m_points[n+1].getY()-m_points[n].getY()) /
|
||||
(m_points[n+1].getX()-m_points[n].getX());
|
||||
float t = m_time-m_points[n].X;
|
||||
return m_points[n].Y + t*(m_points[n+1].Y-m_points[n].Y) /
|
||||
(m_points[n+1].X-m_points[n].X);
|
||||
}
|
||||
case IP_BEZIER: { // FIXME: for now only:
|
||||
return m_points[n].getY();
|
||||
case IP_BEZIER: {
|
||||
if(n==m_points.size()-1)
|
||||
{
|
||||
// FIXME: only const implemented atm.
|
||||
return m_points[n].Y;
|
||||
}
|
||||
core::vector2df c = 3*(m_handle2[n]-m_points[n]);
|
||||
core::vector2df b = 3*(m_handle1[n+1]-m_handle2[n])-c;
|
||||
core::vector2df a = m_points[n+1] - m_points[n] - c - b;
|
||||
float t = (m_time-m_points[n].X)/(m_points[n+1].X-m_points[n].X);
|
||||
core::vector2df r = ((a*t+b)*t+c)*t+m_points[n];
|
||||
return r.Y;
|
||||
}
|
||||
} // switch
|
||||
// Keep the compiler happy:
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "irrlicht.h"
|
||||
using namespace irr;
|
||||
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
class XMLNode;
|
||||
@@ -45,11 +48,10 @@ private:
|
||||
/** The four extend types. */
|
||||
enum {ET_CONST, ET_EXTRAP, ET_CYCLIC_EXTRAP, ET_CYCLIC} m_extend;
|
||||
|
||||
/** The actual control points. Using Vec3 is a bit of an overkill since
|
||||
* the IPs are only 2d, but the amount of memory is small anyway. */
|
||||
std::vector<Vec3> m_points;
|
||||
/** The actual control points. */
|
||||
std::vector<core::vector2df> m_points;
|
||||
/** Only used for bezier curves: the two handles. */
|
||||
std::vector<Vec3> m_handle1, m_handle2;
|
||||
std::vector<core::vector2df> m_handle1, m_handle2;
|
||||
|
||||
/** Current time in cycle. */
|
||||
float m_time;
|
||||
|
||||
@@ -161,6 +161,19 @@ int XMLNode::get(const std::string &attribute, std::string *value) const
|
||||
return 1;
|
||||
} // get
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int XMLNode::get(const std::string &attribute, core::vector2df *value) const
|
||||
{
|
||||
std::string s = "";
|
||||
if(!get(attribute, &s)) return 0;
|
||||
|
||||
std::vector<std::string> v = StringUtils::split(s,' ');
|
||||
if(v.size()!=2) return 0;
|
||||
value->X = (float)atof(v[0].c_str());
|
||||
value->Y = (float)atof(v[1].c_str());
|
||||
return 1;
|
||||
} // get(vector2df)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int XMLNode::get(const std::string &attribute, core::vector3df *value) const
|
||||
{
|
||||
@@ -189,21 +202,6 @@ int XMLNode::get(const std::string &attribute, Vec3 *value) const
|
||||
return 1;
|
||||
} // get(Vec3)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Only reads in a tuple and sets only x and y coordinates. Z is unchanges.
|
||||
* This is used in reading blender's IPO data. */
|
||||
int XMLNode::get2(const std::string &attribute, Vec3 *value) const
|
||||
{
|
||||
std::string s = "";
|
||||
if(!get(attribute, &s)) return 0;
|
||||
|
||||
std::vector<std::string> v = StringUtils::split(s,' ');
|
||||
if(v.size()!=2) return 0;
|
||||
value->setX((float)atof(v[0].c_str()));
|
||||
value->setY((float)atof(v[1].c_str()));
|
||||
return 1;
|
||||
} // get2(Vec3)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
int XMLNode::get(const std::string &attribute, video::SColorf *color) const
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
int get(const std::string &attribute, float *value) const;
|
||||
int get(const std::string &attribute, bool *value) const;
|
||||
int get(const std::string &attribute, Vec3 *value) const;
|
||||
int get2(const std::string &attribute,Vec3 *value) const;
|
||||
int get(const std::string &attribute, core::vector2df *value) const;
|
||||
int get(const std::string &attribute, core::vector3df *value) const;
|
||||
int get(const std::string &attribute, video::SColorf *value) const;
|
||||
int get(const std::string &attribute, std::vector<std::string> *value) const;
|
||||
|
||||
Reference in New Issue
Block a user