2022-09-04 15:16:35 +00:00
|
|
|
#include "SplineGrid.h"
|
|
|
|
#include "tbsp.hh"
|
|
|
|
#include "RenderBase.h"
|
|
|
|
#include "Core.h"
|
2022-09-05 15:19:34 +00:00
|
|
|
#include "Interpolators.h"
|
2022-09-04 15:16:35 +00:00
|
|
|
|
|
|
|
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
|
|
|
|
|
|
|
SplineGridCtrlPoint::SplineGridCtrlPoint()
|
|
|
|
{
|
|
|
|
setTexture("gui/open-menu");
|
|
|
|
setWidthHeight(16, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector SplineGridCtrlPoint::getSplinePosition() const
|
|
|
|
{
|
|
|
|
SplineGridCtrlPoint *p = (SplineGridCtrlPoint*)getParent();
|
2022-09-05 15:19:34 +00:00
|
|
|
return Vector(2 * position.x / p->width, 2 * position.y / p->height);
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGridCtrlPoint::onUpdate(float dt)
|
|
|
|
{
|
|
|
|
const bool lmb = core->mouse.buttons.left;
|
|
|
|
|
|
|
|
if(lmb)
|
|
|
|
{
|
|
|
|
if(!movingPoint && isCoordinateInside(core->mouse.position))
|
|
|
|
movingPoint = this;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
movingPoint = NULL;
|
|
|
|
|
|
|
|
if(movingPoint == this)
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
SplineGrid *p = (SplineGrid*)getParent();
|
2022-09-04 15:16:35 +00:00
|
|
|
const Vector parentPos = p->getWorldPosition();
|
|
|
|
position = core->mouse.position - parentPos;
|
2022-09-05 15:19:34 +00:00
|
|
|
p->recalc();
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SplineGrid::SplineGrid()
|
2022-09-05 15:19:34 +00:00
|
|
|
: degreeX(3), degreeY(3), _cpx(0), _cpy(0), _xres(0), _yres(0), splinetype(SPLINE_BSPLINE)
|
2022-09-04 15:16:35 +00:00
|
|
|
{
|
|
|
|
setWidthHeight(128, 128);
|
2022-09-05 15:19:34 +00:00
|
|
|
renderQuad = true;
|
|
|
|
renderBorder = true;
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SplineGrid::~SplineGrid()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres)
|
|
|
|
{
|
|
|
|
|
|
|
|
knotsX.resize(tbsp__getNumKnots(w, degreeX));
|
|
|
|
knotsY.resize(tbsp__getNumKnots(h, degreeY));
|
|
|
|
tmp.resize(xres * h);
|
2022-09-05 15:19:34 +00:00
|
|
|
tbsp::fillKnotVector<float>(&knotsX[0], w, degreeX, -1.0f, 1.0f);
|
|
|
|
tbsp::fillKnotVector<float>(&knotsY[0], h, degreeY, -1.0f, 1.0f);
|
2022-09-04 15:16:35 +00:00
|
|
|
|
|
|
|
this->createGrid(xres, yres);
|
|
|
|
|
|
|
|
std::vector<SplineGridCtrlPoint*> oldp;
|
|
|
|
ctrlp.swap(oldp);
|
|
|
|
ctrlp.resize(w * h);
|
|
|
|
|
|
|
|
// move any old points over that fit within the new size
|
|
|
|
{
|
|
|
|
const size_t cw = std::min(_cpx, w);
|
|
|
|
const size_t ch = std::min(_cpy, h);
|
|
|
|
for(size_t y = 0; y < ch; ++y)
|
|
|
|
for(size_t x = 0; x < cw; ++x)
|
|
|
|
{
|
|
|
|
SplineGridCtrlPoint *& ref = oldp[y * _cpx + x];
|
|
|
|
ctrlp[y * w + x] = ref;
|
|
|
|
ref = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-05 15:19:34 +00:00
|
|
|
_cpx = w;
|
|
|
|
_cpy = h;
|
|
|
|
_xres = xres;
|
|
|
|
_yres = yres;
|
|
|
|
|
2022-09-04 15:16:35 +00:00
|
|
|
// kill any excess points
|
|
|
|
for(size_t i = 0; i < oldp.size(); ++i)
|
|
|
|
if(oldp[i])
|
|
|
|
oldp[i]->safeKill();
|
|
|
|
|
|
|
|
// extend until all points are there
|
|
|
|
for(size_t y = 0; y < h; ++y)
|
|
|
|
for(size_t x = 0; x < w; ++x)
|
|
|
|
{
|
|
|
|
SplineGridCtrlPoint *& ref = ctrlp[y * w + x];
|
|
|
|
if(!ref)
|
|
|
|
ref = createControlPoint(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::recalc()
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
switch(splinetype)
|
|
|
|
{
|
|
|
|
case SPLINE_BSPLINE:
|
|
|
|
recalcBSpline();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SPLINE_COSINE:
|
|
|
|
recalcCosine();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::recalcBSpline()
|
|
|
|
{
|
|
|
|
std::vector<Vector> px(std::max(_cpx, _xres));
|
2022-09-04 15:16:35 +00:00
|
|
|
std::vector<Vector> work(std::max(degreeX, degreeY));
|
2022-09-05 15:19:34 +00:00
|
|
|
|
|
|
|
// Each row -> X-axis interpolation
|
2022-09-04 15:16:35 +00:00
|
|
|
for(size_t y = 0; y < _cpy; ++y)
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
|
2022-09-04 15:16:35 +00:00
|
|
|
for(size_t x = 0; x < _cpx; ++x)
|
|
|
|
px[x] = ctrlp[y * _cpx + x]->getSplinePosition();
|
|
|
|
|
|
|
|
Vector *dst = &tmp[y * _xres];
|
2022-09-05 15:19:34 +00:00
|
|
|
tbsp::evalRange(dst, _xres, &work[0], &knotsX[0], &px[0], _cpx, degreeX, -1.0f, 1.0f);
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
2022-09-05 15:19:34 +00:00
|
|
|
|
|
|
|
this->resetGrid();
|
|
|
|
Vector **dg = this->getDrawGrid();
|
|
|
|
|
|
|
|
// Each column -> Y-axis interpolation
|
|
|
|
std::vector<Vector> out(_yres);
|
|
|
|
for(size_t x = 0; x < _xres; ++x)
|
|
|
|
{
|
|
|
|
for(size_t y = 0; y < _cpy; ++y)
|
|
|
|
px[y] = tmp[y * _xres + x];
|
|
|
|
|
|
|
|
tbsp::evalRange(&out[0], _yres, &work[0], &knotsY[0], &px[0], _cpy, degreeY, -1.0f, 1.0f);
|
|
|
|
|
|
|
|
for(size_t y = 0; y < _yres; ++y)
|
|
|
|
{
|
|
|
|
// output values are in [-1,+1] while drawgrid normally goes from [-0.5,+0.5]
|
|
|
|
Vector gp = out[y] * 0.5f;
|
|
|
|
gp.z = 1; // used as alpha
|
|
|
|
dg[x][y] = gp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::recalcCosine()
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
/*std::vector<Vector> px(std::max(_cpx, _xres));
|
|
|
|
std::vector<float> out(std::max(_xres, _yres));
|
|
|
|
|
|
|
|
CosineInterpolator top;
|
|
|
|
// Each row -> X-axis interpolation
|
|
|
|
for(size_t y = 0; y < _cpy; ++y)
|
|
|
|
{
|
|
|
|
|
|
|
|
for(size_t x = 0; x < _cpx; ++x)
|
|
|
|
px[x] = ctrlp[y * _cpx + x]->getSplinePosition();
|
|
|
|
std::sort(px.begin(), px.end());
|
|
|
|
|
|
|
|
top.setPoints(&px[0], _cpx);
|
|
|
|
|
|
|
|
Vector *dst = &tmp[y * _xres];
|
|
|
|
top.interpolateRange(&out[0,
|
|
|
|
*/
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::resetControlPoints()
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
const float dx = width / float(_cpx - 1);
|
|
|
|
const float dy = height / float(_cpy - 1);
|
2022-09-04 15:16:35 +00:00
|
|
|
float yy = height * -0.5f;
|
|
|
|
for(size_t y = 0; y < _cpy; ++y, yy += dy)
|
|
|
|
{
|
|
|
|
float xx = width * -0.5f;
|
|
|
|
SplineGridCtrlPoint **row = &ctrlp[y * _cpx];
|
|
|
|
for(size_t x = 0; x < _cpx; ++x, xx += dx)
|
|
|
|
row[x]->position = Vector(xx, yy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
|
|
|
{
|
|
|
|
assert(x < _cpx && y < _cpy);
|
2022-09-05 15:19:34 +00:00
|
|
|
const Vector wh(width, height);
|
|
|
|
const Vector pos01(float(x) / float(_cpx-1), float(y) / float(_cpy-1));
|
2022-09-04 15:16:35 +00:00
|
|
|
SplineGridCtrlPoint *cp = new SplineGridCtrlPoint();
|
2022-09-05 15:19:34 +00:00
|
|
|
cp->position = (pos01 - Vector(0.5f, 0.5f)) * wh;
|
2022-09-04 15:16:35 +00:00
|
|
|
this->addChild(cp, PM_POINTER);
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::onUpdate(float dt)
|
|
|
|
{
|
|
|
|
Quad::onUpdate(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplineGrid::onRender(const RenderState& rs) const
|
|
|
|
{
|
|
|
|
Quad::onRender(rs);
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
2022-09-05 15:19:34 +00:00
|
|
|
const Vector wh2(width * 0.5f, height * 0.5f);
|
2022-09-04 15:16:35 +00:00
|
|
|
|
|
|
|
glLineWidth(2);
|
|
|
|
glColor4f(0.0f, 1.0f, 0.3f, 0.3f);
|
|
|
|
|
|
|
|
// X axis
|
|
|
|
for(size_t y = 0; y < _cpy; ++y)
|
|
|
|
{
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
const SplineGridCtrlPoint * const *row = &ctrlp[y * _cpx];
|
|
|
|
for(size_t x = 0; x < _cpx; ++x)
|
|
|
|
{
|
|
|
|
const Vector p = row[x]->position;
|
|
|
|
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 = ctrlp[y * _cpx + x]->position;
|
|
|
|
glVertex2f(p.x, p.y);
|
|
|
|
}
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
|
2022-09-05 15:19:34 +00:00
|
|
|
/*
|
2022-09-04 15:16:35 +00:00
|
|
|
glColor4f(0.0f, 0.2f, 1.0f, 1.0f);
|
|
|
|
for(size_t y = 0; y < _cpy; ++y)
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
glBegin(GL_LINE_STRIP);
|
2022-09-04 15:16:35 +00:00
|
|
|
const value_type *line = &tmp[y * _xres];
|
|
|
|
for(size_t x = 0; x < _xres; ++x)
|
|
|
|
{
|
2022-09-05 15:19:34 +00:00
|
|
|
Vector pos = line[x] * wh2;
|
2022-09-04 15:16:35 +00:00
|
|
|
glVertex2f(pos.x, pos.y);
|
|
|
|
}
|
2022-09-05 15:19:34 +00:00
|
|
|
glEnd();
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
2022-09-05 15:19:34 +00:00
|
|
|
*/
|
2022-09-04 15:16:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|