mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-02-27 08:34:02 +00:00
Merge branch 'more-bspline' into tile-optimization
This commit is contained in:
commit
d4b80525a9
8 changed files with 1187 additions and 128 deletions
|
@ -240,6 +240,7 @@ void AnimationEditor::applyState()
|
|||
editingBone = 0;
|
||||
currentKey = 0;
|
||||
splinegrid = 0;
|
||||
assistedSplineEdit = true;
|
||||
|
||||
editSprite = new SkeletalSprite();
|
||||
editSprite->cull = false;
|
||||
|
@ -302,6 +303,8 @@ void AnimationEditor::applyState()
|
|||
addAction(MakeFunctionEvent(AnimationEditor, decrTimelineGrid), KEY_O, 0);
|
||||
addAction(MakeFunctionEvent(AnimationEditor, incrTimelineGrid), KEY_P, 0);
|
||||
|
||||
addAction(MakeFunctionEvent(AnimationEditor, toggleSplineMode), KEY_W, 0);
|
||||
|
||||
|
||||
|
||||
addAction(ACTION_SWIMLEFT, KEY_J, -1);
|
||||
|
@ -462,6 +465,12 @@ void AnimationEditor::applyState()
|
|||
reverseAnim->event.set(MakeFunctionEvent(AnimationEditor, reverseAnim));
|
||||
addRenderObject(reverseAnim, LR_MENU);
|
||||
|
||||
DebugButton *bAssist = new DebugButton(0, 0, 150);
|
||||
bAssist->position = Vector(10, 510);
|
||||
bAssist->event.set(MakeFunctionEvent(AnimationEditor, toggleSplineMode));
|
||||
addRenderObject(bAssist, LR_MENU);
|
||||
bSplineAssist = bAssist;
|
||||
|
||||
|
||||
OutlineRect *rect = new OutlineRect;
|
||||
rect->setWidthHeight(400,400);
|
||||
|
@ -494,6 +503,7 @@ void AnimationEditor::applyState()
|
|||
|
||||
updateTimelineGrid();
|
||||
updateTimelineUnit();
|
||||
updateButtonLabels();
|
||||
}
|
||||
|
||||
void AnimationEditor::clearUndoHistory()
|
||||
|
@ -1005,18 +1015,24 @@ void AnimationEditor::editStripKey()
|
|||
bgGrad->makeVertical(Vector(0.4f, 0.6f, 0.4f), Vector(0.8f, 1, 0.8f));
|
||||
|
||||
BoneKeyframe *bk = a->getKeyframe(currentKey)->getBoneKeyframe(editingBone->boneIdx);
|
||||
assert(bk->controlpoints.size() == interp->bsp.ctrlX() * interp->bsp.ctrlY());
|
||||
const size_t totalcp = interp->bsp.ctrlX() * interp->bsp.ctrlY();
|
||||
const bool reset = bk->controlpoints.empty();
|
||||
bk->controlpoints.resize(totalcp);
|
||||
assert(!splinegrid);
|
||||
|
||||
splinegrid = new SplineGrid;
|
||||
splinegrid = new SplineGrid();
|
||||
DynamicRenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY());
|
||||
rgrid->setDrawOrder(grid->getDrawOrder());
|
||||
splinegrid->setTexture(editingBone->texture->name);
|
||||
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
||||
splinegrid->position = Vector(400, 300);
|
||||
//splinegrid->followCamera = 1;
|
||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
||||
//editSprite->addChild(splinegrid, PM_STATIC, RBP_OFF, CHILD_FRONT);
|
||||
//editSprite->alphaMod = 0.5f;
|
||||
splinegrid->setAssist(assistedSplineEdit);
|
||||
|
||||
if(reset)
|
||||
splinegrid->resetControlPoints();
|
||||
else
|
||||
splinegrid->importKeyframe(bk);
|
||||
|
||||
addRenderObject(splinegrid, LR_PARTICLES_TOP);
|
||||
}
|
||||
else
|
||||
|
@ -1616,6 +1632,23 @@ void AnimationEditor::decrTimelineGrid()
|
|||
updateTimelineGrid();
|
||||
}
|
||||
|
||||
void AnimationEditor::toggleSplineMode()
|
||||
{
|
||||
assistedSplineEdit = !assistedSplineEdit;
|
||||
updateButtonLabels();
|
||||
if(splinegrid)
|
||||
splinegrid->setAssist(assistedSplineEdit);
|
||||
}
|
||||
|
||||
void AnimationEditor::updateButtonLabels()
|
||||
{
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "S.Assist (W)(" << (assistedSplineEdit ? "on" : "off") << ")";
|
||||
bSplineAssist->label->setText(os.str());
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationEditor::updateTimelineGrid()
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
@ -1636,9 +1669,9 @@ void AnimationEditor::applyBoneToSplineGrid()
|
|||
{
|
||||
Animation *a = editSprite->getCurrentAnimation();
|
||||
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());
|
||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
||||
splinegrid->importKeyframe(bk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1648,10 +1681,10 @@ void AnimationEditor::applySplineGridToBone()
|
|||
{
|
||||
Animation *a = editSprite->getCurrentAnimation();
|
||||
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());
|
||||
splinegrid->exportControlPoints(&bk->controlpoints[0]);
|
||||
splinegrid->exportKeyframe(bk);
|
||||
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
||||
interp->updateGridAndBone(*bk, editingBone);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
class DebugFont;
|
||||
class BitmapText;
|
||||
class SplineGrid;
|
||||
class DebugButton;
|
||||
|
||||
class KeyframeWidget : public Quad
|
||||
{
|
||||
|
@ -133,6 +134,7 @@ public:
|
|||
SkeletalKeyframe buffer;
|
||||
|
||||
bool editingStrip;
|
||||
bool assistedSplineEdit;
|
||||
size_t selectedStripPoint;
|
||||
|
||||
void reverseAnim();
|
||||
|
@ -162,6 +164,10 @@ public:
|
|||
SplineGrid *splinegrid;
|
||||
void applySplineGridToBone();
|
||||
void applyBoneToSplineGrid();
|
||||
|
||||
void toggleSplineMode();
|
||||
DebugButton *bSplineAssist;
|
||||
void updateButtonLabels();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -101,9 +100,10 @@ void BSpline2D::resize(size_t cx, size_t cy, unsigned degx, unsigned degy)
|
|||
|
||||
void BSpline2D::recalc(Vector* dst, size_t xres, size_t yres, const Vector *controlpoints)
|
||||
{
|
||||
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 +113,9 @@ 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);
|
||||
// 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);
|
||||
|
||||
// Each column -> Y-axis interpolation
|
||||
for(size_t x = 0; x < _cpx; ++x)
|
||||
|
@ -162,3 +164,80 @@ void BSpline2DWithPoints::reset()
|
|||
{
|
||||
BSpline2D::reset(&controlpoints[0]);
|
||||
}
|
||||
|
||||
bool BSpline2DControlPointGenerator::resize(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);
|
||||
|
||||
cp2d.init(cx, cy);
|
||||
|
||||
const size_t maxcp = std::max(cx, cy);
|
||||
vectmp.resize(maxcp);
|
||||
|
||||
return interp.x.init(&floats[0], cx, cx)
|
||||
&& interp.y.init(&floats[interpStorageSizeX], cy, cy);
|
||||
}
|
||||
|
||||
bool 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];
|
||||
}
|
||||
|
||||
return 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.y.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();
|
||||
}
|
||||
|
||||
|
||||
bool BSpline2DControlPointGeneratorWithPoints::resize(size_t cx, size_t cy)
|
||||
{
|
||||
designpoints.resize(cx * cy);
|
||||
return BSpline2DControlPointGenerator::resize(cx, cy);
|
||||
}
|
||||
|
||||
Vector* BSpline2DControlPointGeneratorWithPoints::generateControlPoints()
|
||||
{
|
||||
return BSpline2DControlPointGenerator::generateControlPoints(&designpoints[0]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -36,18 +45,20 @@ public:
|
|||
inline unsigned degX() const { return _degx; }
|
||||
inline unsigned degY() const { return _degy; }
|
||||
|
||||
inline const float *getKnotsX() const { return &knotsX[0]; }
|
||||
inline const float *getKnotsY() const { return &knotsY[0]; }
|
||||
|
||||
private:
|
||||
|
||||
size_t _cpx, _cpy; // # of control points
|
||||
unsigned _degx, _degy;
|
||||
float _tmin, _tmax;
|
||||
std::vector<float> knotsX, knotsY;
|
||||
};
|
||||
|
||||
|
||||
class BSpline2DWithPoints : public BSpline2D
|
||||
{
|
||||
public:
|
||||
|
||||
void resize(size_t cx, size_t cy, unsigned degx, unsigned degy);
|
||||
void recalc(Vector *dst, size_t xres, size_t yres);
|
||||
|
||||
|
@ -61,4 +72,31 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class BSpline2DControlPointGenerator
|
||||
{
|
||||
public:
|
||||
bool resize(size_t cx, size_t cy);
|
||||
|
||||
bool 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:
|
||||
bool resize(size_t cx, size_t cy);
|
||||
Vector *generateControlPoints();
|
||||
std::vector<Vector> designpoints;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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)
|
||||
|
@ -1850,10 +1858,8 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
grid->gridType = GRID_INTERP;
|
||||
// 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;
|
||||
|
||||
|
@ -1864,9 +1870,11 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
const size_t numcp = size_t(cx) * size_t(cy);
|
||||
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 ..."
|
||||
// ^- start of 1st keyframe ^- 2nd keyframe
|
||||
SimpleIStringStream is(idata ? idata : "", SimpleIStringStream::REUSE);
|
||||
SimpleIStringStream is(idata, SimpleIStringStream::REUSE);
|
||||
|
||||
// fixup keyframes and recalc spline points
|
||||
for(size_t k = 0; k < newAnimation.keyframes.size(); ++k)
|
||||
|
@ -1891,11 +1899,11 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
bk->grid.resize(numgridp);
|
||||
bgip.updateGridOnly(*bk, bi);
|
||||
}
|
||||
}
|
||||
// ---- end bspline -----
|
||||
}
|
||||
|
||||
animation = animation->NextSiblingElement("Animation");
|
||||
this->animations.push_back(newAnimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
#include "SplineGrid.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "RenderBase.h"
|
||||
#include "Core.h"
|
||||
#include "RenderGrid.h"
|
||||
#include "SkeletalSprite.h"
|
||||
|
||||
|
||||
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
||||
|
||||
|
@ -74,11 +79,12 @@ void SplineGridCtrlPoint::onUpdate(float dt)
|
|||
}
|
||||
|
||||
SplineGrid::SplineGrid()
|
||||
: wasModified(false), deg(0), pointscale(1)
|
||||
: wasModified(false), deg(0), pointscale(1), _assistMode(true)
|
||||
{
|
||||
setWidthHeight(128, 128);
|
||||
renderQuad = true;
|
||||
renderBorder = true;
|
||||
renderBorderColor = Vector(0.5f, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
SplineGrid::~SplineGrid()
|
||||
|
@ -87,6 +93,9 @@ SplineGrid::~SplineGrid()
|
|||
|
||||
DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
|
||||
{
|
||||
if(!cpgen.resize(w, h))
|
||||
return NULL;
|
||||
|
||||
size_t oldcpx = bsp.ctrlX();
|
||||
size_t oldcpy = bsp.ctrlY();
|
||||
|
||||
|
@ -126,6 +135,9 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr
|
|||
ref = createControlPoint(x, y);
|
||||
}
|
||||
|
||||
if(!cpgen.refresh(bsp.getKnotsX(), bsp.getKnotsY(), bsp.degX(), bsp.degY()))
|
||||
return NULL;
|
||||
|
||||
recalc();
|
||||
|
||||
return ret;
|
||||
|
@ -133,7 +145,17 @@ DynamicRenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yr
|
|||
|
||||
void SplineGrid::recalc()
|
||||
{
|
||||
exportControlPoints(&bsp.controlpoints[0]);
|
||||
if(_assistMode)
|
||||
{
|
||||
exportGridPoints(&cpgen.designpoints[0]);
|
||||
_generateControlPointsFromDesignPoints();
|
||||
}
|
||||
else
|
||||
{
|
||||
exportGridPoints(&bsp.controlpoints[0]);
|
||||
bsp.recalc(&cpgen.designpoints[0], bsp.ctrlX(), bsp.ctrlY());
|
||||
}
|
||||
|
||||
if(grid)
|
||||
{
|
||||
bsp.recalc(grid->dataRW(), grid->width(), grid->height());
|
||||
|
@ -141,24 +163,67 @@ void SplineGrid::recalc()
|
|||
}
|
||||
}
|
||||
|
||||
void SplineGrid::exportControlPoints(Vector* controlpoints)
|
||||
void SplineGrid::exportGridPoints(Vector* pdst) const
|
||||
{
|
||||
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)
|
||||
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(_assistMode)
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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(_assistMode) // ALWAYS DO THIS!!
|
||||
{
|
||||
cpgen.designpoints = bsp.controlpoints;
|
||||
_generateControlPointsFromDesignPoints();
|
||||
}
|
||||
|
||||
recalc();
|
||||
}
|
||||
|
||||
void SplineGrid::_generateControlPointsFromDesignPoints()
|
||||
{
|
||||
const Vector *cp = cpgen.generateControlPoints();
|
||||
memcpy(&bsp.controlpoints[0], cp, bsp.controlpoints.size() * sizeof(*cp));
|
||||
}
|
||||
|
||||
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
||||
|
@ -190,7 +255,10 @@ void SplineGrid::onRender(const RenderState& rs) const
|
|||
const Vector wh2(width * 0.5f, height * 0.5f);
|
||||
|
||||
glLineWidth(2);
|
||||
glColor4f(0.0f, 0.3f, 1.0f, 0.3f);
|
||||
if(_assistMode)
|
||||
glColor4f(0.0f, 0.3f, 1.0f, 0.4f);
|
||||
else
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
|
||||
|
||||
const size_t cpx = bsp.ctrlX();
|
||||
const size_t cpy = bsp.ctrlY();
|
||||
|
@ -219,6 +287,45 @@ void SplineGrid::onRender(const RenderState& rs) const
|
|||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
const Vector *psrc = _assistMode
|
||||
? &bsp.controlpoints[0]
|
||||
: &cpgen.designpoints[0];
|
||||
|
||||
if(RenderObject::renderCollisionShape)
|
||||
{
|
||||
glLineWidth(1);
|
||||
glColor4f(1.0f, 0.3f, 0.3f, 0.7f);
|
||||
glPushMatrix();
|
||||
glScalef(width, height, 1);
|
||||
|
||||
// X axis
|
||||
for(size_t y = 0; y < cpy; ++y)
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
const Vector *row = &psrc[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 = psrc[y * cpx + x];
|
||||
glVertex2f(p.x, p.y);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void SplineGrid::setPointScale(const float scale)
|
||||
|
@ -230,3 +337,17 @@ void SplineGrid::setPointScale(const float scale)
|
|||
ctrlp[i]->scale.y = scale;
|
||||
}
|
||||
}
|
||||
|
||||
void SplineGrid::setAssist(bool on)
|
||||
{
|
||||
if(on == _assistMode)
|
||||
return;
|
||||
|
||||
if(on)
|
||||
importGridPoints(&cpgen.designpoints[0]);
|
||||
else
|
||||
importGridPoints(&bsp.controlpoints[0]);
|
||||
|
||||
_assistMode = on;
|
||||
recalc();
|
||||
}
|
||||
|
|
|
@ -7,11 +7,8 @@
|
|||
#include "Quad.h"
|
||||
#include "Interpolators.h"
|
||||
|
||||
enum SplineType
|
||||
{
|
||||
SPLINE_BSPLINE,
|
||||
SPLINE_COSINE,
|
||||
};
|
||||
|
||||
class BoneKeyframe;
|
||||
|
||||
class SplineGridCtrlPoint : public Quad
|
||||
{
|
||||
|
@ -36,13 +33,22 @@ public:
|
|||
// # of control points on each axis
|
||||
DynamicRenderGrid *resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
|
||||
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 setPointScale(const float scale);
|
||||
float getPointScale() const { return pointscale; }
|
||||
|
||||
void setAssist(bool on);
|
||||
|
||||
|
||||
virtual void onRender(const RenderState& rs) const OVERRIDE;
|
||||
virtual void onUpdate(float dt) OVERRIDE;
|
||||
|
@ -53,6 +59,7 @@ public:
|
|||
bool wasModified; // to be checked/reset by external code
|
||||
|
||||
private:
|
||||
void _generateControlPointsFromDesignPoints();
|
||||
|
||||
SplineGridCtrlPoint *createControlPoint(size_t x, size_t y);
|
||||
|
||||
|
@ -60,6 +67,9 @@ private:
|
|||
unsigned deg;
|
||||
BSpline2DWithPoints bsp;
|
||||
float pointscale;
|
||||
|
||||
BSpline2DControlPointGeneratorWithPoints cpgen;
|
||||
bool _assistMode;
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue