mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-01 15:35:47 +00:00
bspline point gen is now properly integrated and only called while in the editor.
the remaining code uses the same old basic control points as it previously did.
This commit is contained in:
parent
7d2f961573
commit
36aaa77436
6 changed files with 267 additions and 148 deletions
|
@ -1015,7 +1015,7 @@ void AnimationEditor::editStripKey()
|
||||||
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
||||||
splinegrid->position = Vector(400, 300);
|
splinegrid->position = Vector(400, 300);
|
||||||
//splinegrid->followCamera = 1;
|
//splinegrid->followCamera = 1;
|
||||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
splinegrid->importKeyframe(bk);
|
||||||
//editSprite->addChild(splinegrid, PM_STATIC, RBP_OFF, CHILD_FRONT);
|
//editSprite->addChild(splinegrid, PM_STATIC, RBP_OFF, CHILD_FRONT);
|
||||||
//editSprite->alphaMod = 0.5f;
|
//editSprite->alphaMod = 0.5f;
|
||||||
addRenderObject(splinegrid, LR_PARTICLES_TOP);
|
addRenderObject(splinegrid, LR_PARTICLES_TOP);
|
||||||
|
@ -1637,9 +1637,9 @@ void AnimationEditor::applyBoneToSplineGrid()
|
||||||
{
|
{
|
||||||
Animation *a = editSprite->getCurrentAnimation();
|
Animation *a = editSprite->getCurrentAnimation();
|
||||||
BoneKeyframe *bk = a->getKeyframe(currentKey)->getBoneKeyframe(editingBone->boneIdx);
|
BoneKeyframe *bk = a->getKeyframe(currentKey)->getBoneKeyframe(editingBone->boneIdx);
|
||||||
assert(bk->controlpoints.size() == splinegrid->getSpline().ctrlX() * splinegrid->getSpline().ctrlY());
|
|
||||||
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
||||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
splinegrid->importKeyframe(bk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1649,9 +1649,8 @@ void AnimationEditor::applySplineGridToBone()
|
||||||
{
|
{
|
||||||
Animation *a = editSprite->getCurrentAnimation();
|
Animation *a = editSprite->getCurrentAnimation();
|
||||||
BoneKeyframe *bk = a->getKeyframe(currentKey)->getBoneKeyframe(editingBone->boneIdx);
|
BoneKeyframe *bk = a->getKeyframe(currentKey)->getBoneKeyframe(editingBone->boneIdx);
|
||||||
assert(bk->controlpoints.size() == splinegrid->getSpline().ctrlX() * splinegrid->getSpline().ctrlY());
|
|
||||||
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
||||||
splinegrid->exportControlPoints(&bk->controlpoints[0]);
|
splinegrid->exportKeyframe(bk);
|
||||||
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
||||||
interp->updateGridAndBone(*bk, editingBone);
|
interp->updateGridAndBone(*bk, editingBone);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,24 +78,7 @@ tail:
|
||||||
}
|
}
|
||||||
|
|
||||||
BSpline2D::BSpline2D()
|
BSpline2D::BSpline2D()
|
||||||
: _cpx(0), _cpy(0), _degx(0), _degy(0), _tmin(0), _tmax(0), _ext(NULL)
|
: _cpx(0), _cpy(0), _degx(0), _degy(0), _tmin(0), _tmax(0)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,84 +96,10 @@ void BSpline2D::resize(size_t cx, size_t cy, unsigned degx, unsigned degy)
|
||||||
_degy = degy;
|
_degy = degy;
|
||||||
_tmin = tmin;
|
_tmin = tmin;
|
||||||
_tmax = tmax;
|
_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 interpRefreshTempSize = tbsp__getInterpolatorRefreshTempSize(maxCp, maxCp);
|
|
||||||
const size_t interpStorageNeeded = interpStorageSizeX + interpStorageSizeY;
|
|
||||||
|
|
||||||
if(_ext && _ext->capacity < interpStorageNeeded)
|
|
||||||
{
|
|
||||||
_ext->~Extended();
|
|
||||||
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(interpRefreshTempSize);
|
|
||||||
|
|
||||||
float *mx = _ext->floats();
|
|
||||||
float *my = mx + interpStorageSizeX;
|
|
||||||
|
|
||||||
_ext->interp.x.init(mx, cx, cx);
|
|
||||||
_ext->interp.x.refresh(&interptmp[0], &knotsX[0], degx);
|
|
||||||
|
|
||||||
_ext->interp.y.init(my, cy, cy);
|
|
||||||
_ext->interp.y.refresh(&interptmp[0], &knotsY[0], degy);
|
|
||||||
|
|
||||||
_ext->tmp2d.init(cx, cy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSpline2D::recalc(Vector* dst, size_t xres, size_t yres, const Vector *controlpoints)
|
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;
|
|
||||||
|
|
||||||
_ext->interp.y.generateControlPoints<Vector>(&tmpcp[0], NULL, &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);
|
|
||||||
_ext->interp.x.generateControlPoints<Vector>(row, NULL, &tmpin[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
controlpoints = tmp2d.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const unsigned maxDeg = std::max(_degx, _degy);
|
const unsigned maxDeg = std::max(_degx, _degy);
|
||||||
|
|
||||||
std::vector<Vector> tmpv;
|
std::vector<Vector> tmpv;
|
||||||
|
@ -204,6 +113,8 @@ void BSpline2D::recalc(Vector* dst, size_t xres, size_t yres, const Vector *cont
|
||||||
tmpv.resize(tmpn);
|
tmpv.resize(tmpn);
|
||||||
tmp = &tmpv[0];
|
tmp = &tmpv[0];
|
||||||
}
|
}
|
||||||
|
// tmp[] layout: leftmost part: entries to hold the matrix as it's being built;
|
||||||
|
// rightmost part: maxDeg entries as workmem for the deBoor eval
|
||||||
Vector *work = tmp + (tmpn - maxDeg);
|
Vector *work = tmp + (tmpn - maxDeg);
|
||||||
|
|
||||||
// Each column -> Y-axis interpolation
|
// Each column -> Y-axis interpolation
|
||||||
|
@ -253,3 +164,79 @@ void BSpline2DWithPoints::reset()
|
||||||
{
|
{
|
||||||
BSpline2D::reset(&controlpoints[0]);
|
BSpline2D::reset(&controlpoints[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BSpline2DControlPointGenerator::BSpline2DControlPointGenerator(size_t cx, size_t cy)
|
||||||
|
{
|
||||||
|
const size_t interpStorageSizeX = tbsp__getInterpolatorStorageSize(cx, cx);
|
||||||
|
const size_t interpStorageSizeY = tbsp__getInterpolatorStorageSize(cy, cy);
|
||||||
|
const size_t interpStorageNeeded = interpStorageSizeX + interpStorageSizeY;
|
||||||
|
floats.resize(interpStorageNeeded);
|
||||||
|
|
||||||
|
interp.x.init(&floats[0], cx, cx);
|
||||||
|
interp.y.init(&floats[interpStorageSizeX], cy, cy);
|
||||||
|
cp2d.init(cx, cy);
|
||||||
|
|
||||||
|
const size_t maxcp = std::max(cx, cy);
|
||||||
|
vectmp.resize(maxcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BSpline2DControlPointGenerator::refresh(const float* knotsx, const float* knotsy, unsigned degx, unsigned degy)
|
||||||
|
{
|
||||||
|
const size_t maxcp = vectmp.size();
|
||||||
|
const size_t tmpn = tbsp__getInterpolatorRefreshTempSize(maxcp, maxcp);
|
||||||
|
const size_t tmpsz = tmpn * sizeof(float);
|
||||||
|
float *tmp;
|
||||||
|
std::vector<float> tmpv;
|
||||||
|
if(tmpsz < 17*1024)
|
||||||
|
tmp = (float*)alloca(tmpsz);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpv.resize(tmpn);
|
||||||
|
tmp = &tmpv[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
interp.x.refresh(tmp, knotsx, degx);
|
||||||
|
interp.y.refresh(tmp, knotsy, degy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector* BSpline2DControlPointGenerator::generateControlPoints(const Vector *points2d)
|
||||||
|
{
|
||||||
|
const size_t cpx = interp.x.getNumInputPoints();
|
||||||
|
const size_t cpy = interp.x.getNumInputPoints();
|
||||||
|
|
||||||
|
// y direction first
|
||||||
|
for(size_t x = 0; x < cpx; ++x)
|
||||||
|
{
|
||||||
|
const Vector *src = &points2d[x];
|
||||||
|
for(size_t y = 0; y < cpy; ++y, src += cpx)
|
||||||
|
vectmp[y] = *src;
|
||||||
|
|
||||||
|
// solve in-place
|
||||||
|
interp.y.generateControlPoints<Vector>(&vectmp[0], NULL, &vectmp[0]);
|
||||||
|
|
||||||
|
for(size_t y = 0; y < cpy; ++y)
|
||||||
|
cp2d(x, y) = vectmp[y];
|
||||||
|
}
|
||||||
|
|
||||||
|
// x direction
|
||||||
|
for(size_t y = 0; y < cpy; ++y)
|
||||||
|
{
|
||||||
|
Vector *row = cp2d.row(y);
|
||||||
|
// solve in-place
|
||||||
|
interp.x.generateControlPoints<Vector>(row, NULL, row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cp2d.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSpline2DControlPointGeneratorWithPoints::BSpline2DControlPointGeneratorWithPoints(size_t cx, size_t cy)
|
||||||
|
: BSpline2DControlPointGenerator(cx, cy)
|
||||||
|
, designpoints(cx * cy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector* BSpline2DControlPointGeneratorWithPoints::generateControlPoints()
|
||||||
|
{
|
||||||
|
return BSpline2DControlPointGenerator::generateControlPoints(&designpoints[0]);
|
||||||
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ class BSpline2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BSpline2D();
|
BSpline2D();
|
||||||
BSpline2D(const BSpline2D&);
|
|
||||||
~BSpline2D();
|
|
||||||
|
|
||||||
|
|
||||||
// # of control points on each axis
|
// # of control points on each axis
|
||||||
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
|
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
|
||||||
|
@ -48,34 +45,20 @@ public:
|
||||||
inline unsigned degX() const { return _degx; }
|
inline unsigned degX() const { return _degx; }
|
||||||
inline unsigned degY() const { return _degy; }
|
inline unsigned degY() const { return _degy; }
|
||||||
|
|
||||||
|
inline const float *getKnotsX() const { return &knotsX[0]; }
|
||||||
|
inline const float *getKnotsY() const { return &knotsY[0]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
size_t _cpx, _cpy; // # of control points
|
size_t _cpx, _cpy; // # of control points
|
||||||
unsigned _degx, _degy;
|
unsigned _degx, _degy;
|
||||||
float _tmin, _tmax;
|
float _tmin, _tmax;
|
||||||
std::vector<float> knotsX, knotsY;
|
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BSpline2DWithPoints : public BSpline2D
|
class BSpline2DWithPoints : public BSpline2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
|
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
|
||||||
void recalc(Vector *dst, size_t xres, size_t yres);
|
void recalc(Vector *dst, size_t xres, size_t yres);
|
||||||
|
|
||||||
|
@ -89,4 +72,31 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BSpline2DControlPointGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BSpline2DControlPointGenerator(size_t cx, size_t cy);
|
||||||
|
|
||||||
|
void refresh(const float *knotsx, const float *knotsy, unsigned degx, unsigned degy);
|
||||||
|
|
||||||
|
Vector *generateControlPoints(const Vector *points2d);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array2d<Vector> cp2d;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
tbsp::Interpolator<float> x, y;
|
||||||
|
} interp;
|
||||||
|
std::vector<float> floats;
|
||||||
|
std::vector<Vector> vectmp;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BSpline2DControlPointGeneratorWithPoints : public BSpline2DControlPointGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BSpline2DControlPointGeneratorWithPoints(size_t cx, size_t cy);
|
||||||
|
Vector *generateControlPoints();
|
||||||
|
std::vector<Vector> designpoints;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1858,7 +1858,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
grid->gridType = GRID_INTERP;
|
grid->gridType = GRID_INTERP;
|
||||||
// bone grid should have been created via <Bone grid=... /> earlier
|
// bone grid should have been created via <Bone grid=... /> earlier
|
||||||
|
|
||||||
const char *idata = interp->Attribute("data");
|
|
||||||
BoneGridInterpolator& bgip = newAnimation.interpolators[numInterp];
|
BoneGridInterpolator& bgip = newAnimation.interpolators[numInterp];
|
||||||
bgip.idx = bi->boneIdx;
|
bgip.idx = bi->boneIdx;
|
||||||
bgip.storeBoneByIdx = boneByIdx;
|
bgip.storeBoneByIdx = boneByIdx;
|
||||||
|
@ -1870,9 +1870,11 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
const size_t numcp = size_t(cx) * size_t(cy);
|
const size_t numcp = size_t(cx) * size_t(cy);
|
||||||
const size_t numgridp = grid->linearsize();
|
const size_t numgridp = grid->linearsize();
|
||||||
|
|
||||||
|
if(const char *idata = interp->Attribute("data"))
|
||||||
|
{
|
||||||
// data format: "W H [x y x y ... (W*H times)] W H x y x y ..."
|
// data format: "W H [x y x y ... (W*H times)] W H x y x y ..."
|
||||||
// ^- start of 1st keyframe ^- 2nd keyframe
|
// ^- start of 1st keyframe ^- 2nd keyframe
|
||||||
SimpleIStringStream is(idata ? idata : "", SimpleIStringStream::REUSE);
|
SimpleIStringStream is(idata, SimpleIStringStream::REUSE);
|
||||||
|
|
||||||
// fixup keyframes and recalc spline points
|
// fixup keyframes and recalc spline points
|
||||||
for(size_t k = 0; k < newAnimation.keyframes.size(); ++k)
|
for(size_t k = 0; k < newAnimation.keyframes.size(); ++k)
|
||||||
|
@ -1897,6 +1899,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
bk->grid.resize(numgridp);
|
bk->grid.resize(numgridp);
|
||||||
bgip.updateGridOnly(*bk, bi);
|
bgip.updateGridOnly(*bk, bi);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ---- end bspline -----
|
// ---- end bspline -----
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#include "SplineGrid.h"
|
#include "SplineGrid.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "RenderGrid.h"
|
#include "RenderGrid.h"
|
||||||
|
#include "SkeletalSprite.h"
|
||||||
|
|
||||||
|
|
||||||
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
||||||
|
|
||||||
|
@ -74,7 +79,7 @@ void SplineGridCtrlPoint::onUpdate(float dt)
|
||||||
}
|
}
|
||||||
|
|
||||||
SplineGrid::SplineGrid()
|
SplineGrid::SplineGrid()
|
||||||
: wasModified(false), deg(0), pointscale(1)
|
: wasModified(false), deg(0), pointscale(1), cpgen(NULL)
|
||||||
{
|
{
|
||||||
setWidthHeight(128, 128);
|
setWidthHeight(128, 128);
|
||||||
renderQuad = true;
|
renderQuad = true;
|
||||||
|
@ -83,6 +88,7 @@ SplineGrid::SplineGrid()
|
||||||
|
|
||||||
SplineGrid::~SplineGrid()
|
SplineGrid::~SplineGrid()
|
||||||
{
|
{
|
||||||
|
delete cpgen;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
|
DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
|
||||||
|
@ -90,6 +96,12 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr
|
||||||
size_t oldcpx = bsp.ctrlX();
|
size_t oldcpx = bsp.ctrlX();
|
||||||
size_t oldcpy = bsp.ctrlY();
|
size_t oldcpy = bsp.ctrlY();
|
||||||
|
|
||||||
|
if(cpgen && (oldcpx != w || oldcpy != h))
|
||||||
|
{
|
||||||
|
delete cpgen;
|
||||||
|
cpgen = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DynamicRenderGrid *ret = this->createGrid(xres, yres);
|
DynamicRenderGrid *ret = this->createGrid(xres, yres);
|
||||||
ret->gridType = GRID_INTERP;
|
ret->gridType = GRID_INTERP;
|
||||||
|
|
||||||
|
@ -126,6 +138,8 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr
|
||||||
ref = createControlPoint(x, y);
|
ref = createControlPoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_initCpgen();
|
||||||
|
|
||||||
recalc();
|
recalc();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -133,7 +147,16 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr
|
||||||
|
|
||||||
void SplineGrid::recalc()
|
void SplineGrid::recalc()
|
||||||
{
|
{
|
||||||
exportControlPoints(&bsp.controlpoints[0]);
|
if(cpgen)
|
||||||
|
{
|
||||||
|
exportGridPoints(&cpgen->designpoints[0]);
|
||||||
|
_generateControlPointsFromDesignPoints();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exportGridPoints(&bsp.controlpoints[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if(grid)
|
if(grid)
|
||||||
{
|
{
|
||||||
bsp.recalc(grid->dataRW(), grid->width(), grid->height());
|
bsp.recalc(grid->dataRW(), grid->width(), grid->height());
|
||||||
|
@ -141,24 +164,74 @@ void SplineGrid::recalc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplineGrid::exportControlPoints(Vector* controlpoints)
|
void SplineGrid::exportGridPoints(Vector* pdst) const
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < ctrlp.size(); ++i)
|
for(size_t i = 0; i < ctrlp.size(); ++i)
|
||||||
controlpoints[i] = ctrlp[i]->getSplinePosition();
|
pdst[i] = ctrlp[i]->getSplinePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplineGrid::importControlPoints(const Vector* controlpoints)
|
void SplineGrid::importGridPoints(const Vector* psrc)
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < ctrlp.size(); ++i)
|
for(size_t i = 0; i < ctrlp.size(); ++i)
|
||||||
ctrlp[i]->setSplinePosition(controlpoints[i]);
|
ctrlp[i]->setSplinePosition(psrc[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineGrid::importKeyframe(const BoneKeyframe* bk)
|
||||||
|
{
|
||||||
|
const size_t numcp = bsp.ctrlX() * bsp.ctrlY();
|
||||||
|
assert(bk->controlpoints.size() == numcp);
|
||||||
|
|
||||||
|
bsp.controlpoints = bk->controlpoints;
|
||||||
|
|
||||||
|
if(cpgen)
|
||||||
|
{
|
||||||
|
// given control points, generate spline points (which are later caculated back into control points)
|
||||||
|
bsp.recalc(&cpgen->designpoints[0], bsp.ctrlX(), bsp.ctrlY());
|
||||||
|
importGridPoints(&cpgen->designpoints[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
importGridPoints(&bk->controlpoints[0]);
|
||||||
|
|
||||||
recalc();
|
recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SplineGrid::exportKeyframe(BoneKeyframe* bk) const
|
||||||
|
{
|
||||||
|
const size_t numcp = bsp.ctrlX() * bsp.ctrlY();
|
||||||
|
assert(bk->controlpoints.size() == numcp);
|
||||||
|
|
||||||
|
bk->controlpoints = bsp.controlpoints;
|
||||||
|
}
|
||||||
|
|
||||||
void SplineGrid::resetControlPoints()
|
void SplineGrid::resetControlPoints()
|
||||||
{
|
{
|
||||||
bsp.reset();
|
bsp.reset();
|
||||||
importControlPoints(&bsp.controlpoints[0]);
|
|
||||||
|
importGridPoints(&bsp.controlpoints[0]);
|
||||||
|
|
||||||
|
// This pushes the bspline controlpoints outwards so that all spline points line up as one would expect.
|
||||||
|
// If this weren't done, the tile's texture would be pulled inwards (more with increasing dimension);
|
||||||
|
// as if the tile was a piece of plastic foil that's seen too much heat.
|
||||||
|
if(cpgen)
|
||||||
|
{
|
||||||
|
cpgen->designpoints = bsp.controlpoints;
|
||||||
|
_generateControlPointsFromDesignPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
recalc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineGrid::_generateControlPointsFromDesignPoints()
|
||||||
|
{
|
||||||
|
const Vector *cp = cpgen->generateControlPoints();
|
||||||
|
memcpy(&bsp.controlpoints[0], cp, bsp.controlpoints.size() * sizeof(*cp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplineGrid::_initCpgen()
|
||||||
|
{
|
||||||
|
assert(!cpgen);
|
||||||
|
cpgen = new BSpline2DControlPointGeneratorWithPoints(bsp.ctrlX(), bsp.ctrlY());
|
||||||
|
cpgen->refresh(bsp.getKnotsX(), bsp.getKnotsY(), bsp.degX(), bsp.degY());
|
||||||
}
|
}
|
||||||
|
|
||||||
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
||||||
|
@ -219,6 +292,40 @@ void SplineGrid::onRender(const RenderState& rs) const
|
||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(RenderObject::renderCollisionShape && cpgen)
|
||||||
|
{
|
||||||
|
glColor4f(1.0f, 0.4f, 0.4f, 0.7f);
|
||||||
|
glPushMatrix();
|
||||||
|
glScalef(width, height, 1);
|
||||||
|
|
||||||
|
// X axis
|
||||||
|
for(size_t y = 0; y < cpy; ++y)
|
||||||
|
{
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
const Vector *row = &bsp.controlpoints[y * cpx];
|
||||||
|
for(size_t x = 0; x < cpx; ++x)
|
||||||
|
{
|
||||||
|
const Vector p = row[x];
|
||||||
|
glVertex2f(p.x, p.y);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Y axis
|
||||||
|
for(size_t x = 0; x < cpx; ++x)
|
||||||
|
{
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
for(size_t y = 0; y < cpy; ++y)
|
||||||
|
{
|
||||||
|
const Vector p = bsp.controlpoints[y * cpx + x];
|
||||||
|
glVertex2f(p.x, p.y);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplineGrid::setPointScale(const float scale)
|
void SplineGrid::setPointScale(const float scale)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "Interpolators.h"
|
#include "Interpolators.h"
|
||||||
|
|
||||||
|
|
||||||
|
class BoneKeyframe;
|
||||||
|
|
||||||
class SplineGridCtrlPoint : public Quad
|
class SplineGridCtrlPoint : public Quad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -31,8 +33,15 @@ public:
|
||||||
// # of control points on each axis
|
// # of control points on each axis
|
||||||
DynamicRenderGrid *resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
|
DynamicRenderGrid *resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
|
||||||
void recalc();
|
void recalc();
|
||||||
void exportControlPoints(Vector *controlpoints);
|
|
||||||
void importControlPoints(const Vector *controlpoints);
|
// Export/import grid points; depending on the mode these either correspond directly to control points
|
||||||
|
// or to spline points from which the control points need to be calculated first (using cpgen)
|
||||||
|
void exportGridPoints(Vector *pdst) const;
|
||||||
|
void importGridPoints(const Vector *psrc);
|
||||||
|
|
||||||
|
void importKeyframe(const BoneKeyframe *bk);
|
||||||
|
void exportKeyframe(BoneKeyframe *bk) const;
|
||||||
|
|
||||||
void resetControlPoints();
|
void resetControlPoints();
|
||||||
|
|
||||||
void setPointScale(const float scale);
|
void setPointScale(const float scale);
|
||||||
|
@ -48,6 +57,8 @@ public:
|
||||||
bool wasModified; // to be checked/reset by external code
|
bool wasModified; // to be checked/reset by external code
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _generateControlPointsFromDesignPoints();
|
||||||
|
void _initCpgen();
|
||||||
|
|
||||||
SplineGridCtrlPoint *createControlPoint(size_t x, size_t y);
|
SplineGridCtrlPoint *createControlPoint(size_t x, size_t y);
|
||||||
|
|
||||||
|
@ -55,6 +66,8 @@ private:
|
||||||
unsigned deg;
|
unsigned deg;
|
||||||
BSpline2DWithPoints bsp;
|
BSpline2DWithPoints bsp;
|
||||||
float pointscale;
|
float pointscale;
|
||||||
|
|
||||||
|
BSpline2DControlPointGeneratorWithPoints *cpgen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue