1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-10-20 13:29:30 +00:00

new tbsp version; working spline control point generation prototype

This commit is contained in:
fgenesis 2024-07-04 21:40:31 +02:00
commit fc3580ca64
5 changed files with 876 additions and 87 deletions

View file

@ -1,6 +1,5 @@
#include "Interpolators.h"
#include <math.h>
#include "tbsp.hh"
// usually one would expect that a bspline goes from t=0 to t=1.
// here, splines eval between these -0.5 .. +0.5.
@ -79,7 +78,24 @@ tail:
}
BSpline2D::BSpline2D()
: _cpx(0), _cpy(0), _degx(0), _degy(0), _tmin(0), _tmax(0)
: _cpx(0), _cpy(0), _degx(0), _degy(0), _tmin(0), _tmax(0), _ext(NULL)
{
}
BSpline2D::~BSpline2D()
{
if(_ext)
{
_ext->~Extended();
free(_ext);
}
}
BSpline2D::BSpline2D(const BSpline2D& o)
: _cpx(o._cpx), _cpy(o._cpy), _degx(o._degx), _degy(o._degy)
, _tmin(o._tmin), _tmax(o._tmax)
, knotsX(o.knotsX), knotsY(o.knotsY)
, _ext(NULL) // VERY important
{
}
@ -97,13 +113,83 @@ void BSpline2D::resize(size_t cx, size_t cy, unsigned degx, unsigned degy)
_degy = degy;
_tmin = tmin;
_tmax = tmax;
const size_t maxCp = std::max(cx, cy);
const size_t interpStorageSizeX = tbsp__getInterpolatorStorageSize(cx, cx);
const size_t interpStorageSizeY = tbsp__getInterpolatorStorageSize(cy, cy);
const size_t interpInitTempSize = tbsp__getInterpolatorInitTempSize(maxCp, maxCp);
const size_t interpStorageNeeded = interpStorageSizeX + interpStorageSizeY;
if(_ext && _ext->capacity < interpStorageNeeded)
{
free(_ext);
_ext = NULL;
}
if(!_ext)
{
void *extmem = malloc(sizeof(Extended) + sizeof(float) * interpStorageNeeded);
Extended *ext = new (extmem) Extended;
ext->capacity = interpStorageNeeded;
_ext = ext;
}
if(_ext)
{
// Some extra temp memory is required during init, but can be discarded right afterward
std::vector<float> interptmp(interpInitTempSize);
float *mx = _ext->floats();
float *my = mx + interpStorageSizeX;
_ext->interp.x = tbsp::initInterpolator(mx, &interptmp[0], degx, cx, cx, &knotsX[0]);
_ext->interp.y = tbsp::initInterpolator(my, &interptmp[0], degy, cy, cy, &knotsY[0]);
_ext->tmp2d.init(cx, cy);
}
}
void BSpline2D::recalc(Vector* dst, size_t xres, size_t yres, const Vector *controlpoints)
{
if(_ext)
{
const size_t maxCp = std::max(_cpx, _cpy);
Array2d<Vector>& tmp2d = _ext->tmp2d;
std::vector<Vector> tmpcp(maxCp), tmpin(maxCp);
// FIXME: should have in/out stride in the generator function
// y direction first
for(size_t x = 0; x < _cpx; ++x)
{
const Vector *src = &controlpoints[x];
for(size_t i = 0; i < _cpy; ++i, src += _cpx)
tmpin[i] = *src;
tbsp::generateControlPoints<Vector>(&tmpcp[0], NULL, _ext->interp.y, &tmpin[0]);
for(size_t y = 0; y < _cpy; ++y)
tmp2d(x, y) = tmpcp[y];
}
// x direction
for(size_t y = 0; y < _cpy; ++y)
{
Vector *row = tmp2d.row(y);
memcpy(&tmpin[0], row, sizeof(Vector) * _cpx);
tbsp::generateControlPoints<Vector>(row, NULL, _ext->interp.x, &tmpin[0]);
}
controlpoints = tmp2d.data();
}
const unsigned maxDeg = std::max(_degx, _degy);
std::vector<Vector> tmpv;
size_t degn = std::max(_degx, _degy);
size_t tmpn = (yres * _cpx) + degn;
size_t tmpn = (yres * _cpx) + maxDeg;
size_t tmpsz = tmpn * sizeof(Vector);
Vector *tmp;
if(tmpsz < 17*1024)
@ -113,7 +199,7 @@ void BSpline2D::recalc(Vector* dst, size_t xres, size_t yres, const Vector *cont
tmpv.resize(tmpn);
tmp = &tmpv[0];
}
Vector *work = tmp + (tmpn - degn);
Vector *work = tmp + (tmpn - maxDeg);
// Each column -> Y-axis interpolation
for(size_t x = 0; x < _cpx; ++x)

View file

@ -4,6 +4,15 @@
#include <algorithm> // std::pair
#include <vector>
#include "Vector.h"
#include "tbsp.hh"
#include "DataStructures.h"
enum SplineType
{
INTERPOLATOR_BSPLINE,
INTERPOLATOR_COSINE,
INTERPOLATOR_BSPLINE_EXT
};
class CosineInterpolator
{
@ -23,6 +32,9 @@ class BSpline2D
{
public:
BSpline2D();
BSpline2D(const BSpline2D&);
~BSpline2D();
// # of control points on each axis
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
@ -37,10 +49,26 @@ public:
inline unsigned degY() const { return _degy; }
private:
size_t _cpx, _cpy; // # of control points
unsigned _degx, _degy;
float _tmin, _tmax;
std::vector<float> knotsX, knotsY;
// always allocated on heap, with extra space at the end
struct Extended
{
Array2d<Vector> tmp2d;
struct
{
tbsp::Interpolator<float> x, y;
} interp;
size_t capacity;
float *floats() { return reinterpret_cast<float*>(this + 1); }
// space for n floats follows
};
Extended *_ext;
};

View file

@ -1660,7 +1660,9 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
XMLElement *animation = animations->FirstChildElement("Animation");
while(animation)
{
Animation newAnimation;
this->animations.push_back(Animation());
Animation& newAnimation = this->animations.back();
newAnimation.name = animation->Attribute("name");
if(animation->Attribute("resetOnEnd"))
newAnimation.resetOnEnd = animation->BoolAttribute("resetOnEnd");
@ -1786,8 +1788,15 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
}
// <Interpolator bone="name or idx" type="TYPE config and params" data="controlpoints; aded by editor" />
size_t numInterp = 0;
XMLElement *interp = animation->FirstChildElement("Interpolator");
for( ; interp; interp = interp->NextSiblingElement("Interpolator"))
++numInterp;
newAnimation.interpolators.resize(numInterp);
interp = animation->FirstChildElement("Interpolator");
for(numInterp = 0 ; interp; interp = interp->NextSiblingElement("Interpolator"), ++numInterp)
{
Bone *bi = NULL;
const char *sbone = interp->Attribute("bone");
@ -1817,17 +1826,16 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
continue;
}
SplineType spline = SPLINE_BSPLINE;
SplineType spline = INTERPOLATOR_BSPLINE;
unsigned cx = 3, cy = 3, degx = 3, degy = 3;
if(const char *stype = interp->Attribute("type"))
{
SimpleIStringStream is(stype, SimpleIStringStream::REUSE);
std::string ty;
is >> ty;
BoneGridInterpolator bgip;
if(ty == "bspline")
{
spline = SPLINE_BSPLINE;
spline = INTERPOLATOR_BSPLINE;
if(!(is >> cx >> cy >> degx >> degy))
{
if(!degx)
@ -1851,9 +1859,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
// bone grid should have been created via <Bone grid=... /> earlier
const char *idata = interp->Attribute("data");
newAnimation.interpolators.push_back(BoneGridInterpolator());
BoneGridInterpolator& bgip = newAnimation.interpolators.back();
//bgip.type = spline;
BoneGridInterpolator& bgip = newAnimation.interpolators[numInterp];
bgip.idx = bi->boneIdx;
bgip.storeBoneByIdx = boneByIdx;
@ -1895,7 +1901,6 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
}
animation = animation->NextSiblingElement("Animation");
this->animations.push_back(newAnimation);
}
}
}

View file

@ -7,11 +7,6 @@
#include "Quad.h"
#include "Interpolators.h"
enum SplineType
{
SPLINE_BSPLINE,
SPLINE_COSINE,
};
class SplineGridCtrlPoint : public Quad
{