mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-25 09:44:02 +00:00
bspline wip more
This commit is contained in:
parent
214590742d
commit
0afd09dc75
7 changed files with 210 additions and 33 deletions
|
@ -469,11 +469,11 @@ void AnimationEditor::applyState()
|
|||
addRenderObject(tr, LR_BLACKGROUND);
|
||||
|
||||
splinegrid = new SplineGrid;
|
||||
splinegrid->resize(5,5,30,30);
|
||||
splinegrid->setTexture("mithalas-house-bg-0001");
|
||||
splinegrid->setWidthHeight(200, 200);
|
||||
splinegrid->position = Vector(400, 300);
|
||||
splinegrid->resize(3,3,10,10);
|
||||
splinegrid->resetControlPoints();
|
||||
splinegrid->setTexture("mithalas-house-bg-0001");
|
||||
addRenderObject(splinegrid, LR_PARTICLES_TOP);
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ set(BBGE_SRCS
|
|||
CMakeLists.txt
|
||||
Core.cpp
|
||||
Core.h
|
||||
Interpolators.cpp
|
||||
Interpolators.h
|
||||
DarkLayer.cpp
|
||||
DarkLayer.h
|
||||
DataStructures.cpp
|
||||
|
|
68
BBGE/Interpolators.cpp
Normal file
68
BBGE/Interpolators.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "Interpolators.h"
|
||||
#include <math.h>
|
||||
|
||||
CosineInterpolator::CosineInterpolator()
|
||||
{
|
||||
}
|
||||
|
||||
void CosineInterpolator::clear()
|
||||
{
|
||||
pxy.clear();
|
||||
}
|
||||
|
||||
void CosineInterpolator::setPoints(const Vector* p, size_t n)
|
||||
{
|
||||
pxy.resize(n);
|
||||
for(size_t i = 0; i < n; ++i)
|
||||
{
|
||||
pxy[i].first = p[i].x;
|
||||
pxy[i].second = p[i].y;
|
||||
}
|
||||
|
||||
|
||||
std::sort(pxy.begin(), pxy.end());
|
||||
}
|
||||
|
||||
float CosineInterpolator::operator()(float x) const
|
||||
{
|
||||
if (x < pxy[0].first)
|
||||
return pxy[0].second;
|
||||
|
||||
size_t N = pxy.size() - 1;
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
{
|
||||
// TODO: binary search
|
||||
if (pxy[i + 1].first > x)
|
||||
{
|
||||
float xfactor = (x - pxy[i].first) / (pxy[i + 1].first - pxy[i].first);
|
||||
float yfactor = (1.0f - cos(xfactor * 3.141596f)) * 0.5f;
|
||||
return yfactor * pxy[i + 1].second + (1 - yfactor) * pxy[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
return pxy[N].second;
|
||||
}
|
||||
|
||||
void CosineInterpolator::interpolateRange(float *ys, const float* xs, size_t n)
|
||||
{
|
||||
size_t i = 0, k = 0;
|
||||
for( ; k < n; ++k)
|
||||
{
|
||||
const float x = xs[k];
|
||||
|
||||
while(x < pxy[i].first)
|
||||
{
|
||||
++i;
|
||||
if(i >= pxy.size())
|
||||
goto tail;
|
||||
}
|
||||
|
||||
ys[k] = pxy[i].second;
|
||||
}
|
||||
return;
|
||||
|
||||
tail:
|
||||
const float v = pxy.back().second;
|
||||
for( ; k < n; ++k)
|
||||
ys[k] = v;
|
||||
}
|
23
BBGE/Interpolators.h
Normal file
23
BBGE/Interpolators.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef BBGE_INTERPOLATORS_H
|
||||
#define BBGE_INTERPOLATORS_H
|
||||
|
||||
#include <algorithm> // std::pair
|
||||
#include <vector>
|
||||
#include "Vector.h"
|
||||
|
||||
class CosineInterpolator
|
||||
{
|
||||
public:
|
||||
CosineInterpolator();
|
||||
void clear();
|
||||
void setPoints(const Vector *p, size_t n);
|
||||
float operator()(float x) const;
|
||||
void interpolateRange(float *ys, const float *xs, size_t n);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::pair<float, float> > pxy;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1543,6 +1543,13 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
{
|
||||
newb->selectable = bone->BoolAttribute("sel");
|
||||
}
|
||||
if (bone->Attribute("grid"))
|
||||
{
|
||||
SimpleIStringStream is(bone->Attribute("grid"));
|
||||
int x, y;
|
||||
is >> x >> y;
|
||||
newb->createGrid(x, y);
|
||||
}
|
||||
bone = bone->NextSiblingElement("Bone");
|
||||
}
|
||||
// attach bones
|
||||
|
@ -1735,6 +1742,15 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
|||
newAnimation.keyframes.push_back(newSkeletalKeyframe);
|
||||
key = key->NextSiblingElement("Key");
|
||||
}
|
||||
|
||||
XMLElement *interp = animation->FirstChildElement("Interpolator");
|
||||
while(interp)
|
||||
{
|
||||
|
||||
|
||||
interp = interp->NextSiblingElement("Interpolator");
|
||||
}
|
||||
|
||||
animation = animation->NextSiblingElement("Animation");
|
||||
this->animations.push_back(newAnimation);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "tbsp.hh"
|
||||
#include "RenderBase.h"
|
||||
#include "Core.h"
|
||||
#include "Interpolators.h"
|
||||
|
||||
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
|
||||
|
||||
|
@ -14,8 +15,7 @@ SplineGridCtrlPoint::SplineGridCtrlPoint()
|
|||
Vector SplineGridCtrlPoint::getSplinePosition() const
|
||||
{
|
||||
SplineGridCtrlPoint *p = (SplineGridCtrlPoint*)getParent();
|
||||
Vector pos = position;
|
||||
return Vector(pos.x / p->width, pos.y / p->height);
|
||||
return Vector(2 * position.x / p->width, 2 * position.y / p->height);
|
||||
}
|
||||
|
||||
void SplineGridCtrlPoint::onUpdate(float dt)
|
||||
|
@ -32,17 +32,19 @@ void SplineGridCtrlPoint::onUpdate(float dt)
|
|||
|
||||
if(movingPoint == this)
|
||||
{
|
||||
SplineGridCtrlPoint *p = (SplineGridCtrlPoint*)getParent();
|
||||
SplineGrid *p = (SplineGrid*)getParent();
|
||||
const Vector parentPos = p->getWorldPosition();
|
||||
position = core->mouse.position - parentPos;
|
||||
p->recalc();
|
||||
}
|
||||
}
|
||||
|
||||
SplineGrid::SplineGrid()
|
||||
: degreeX(3), degreeY(3), _cpx(0), _cpy(0), _xres(0), _yres(0)
|
||||
: degreeX(3), degreeY(3), _cpx(0), _cpy(0), _xres(0), _yres(0), splinetype(SPLINE_BSPLINE)
|
||||
{
|
||||
setWidthHeight(128, 128);
|
||||
//renderQuad = false;
|
||||
renderQuad = true;
|
||||
renderBorder = true;
|
||||
}
|
||||
|
||||
SplineGrid::~SplineGrid()
|
||||
|
@ -55,8 +57,8 @@ 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);
|
||||
tbsp::fillKnotVector<float>(&knotsX[0], w, degreeX, 0.0f, 1.0f);
|
||||
tbsp::fillKnotVector<float>(&knotsY[0], h, degreeY, 0.0f, 1.0f);
|
||||
tbsp::fillKnotVector<float>(&knotsX[0], w, degreeX, -1.0f, 1.0f);
|
||||
tbsp::fillKnotVector<float>(&knotsY[0], h, degreeY, -1.0f, 1.0f);
|
||||
|
||||
this->createGrid(xres, yres);
|
||||
|
||||
|
@ -77,6 +79,11 @@ void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres)
|
|||
}
|
||||
}
|
||||
|
||||
_cpx = w;
|
||||
_cpy = h;
|
||||
_xres = xres;
|
||||
_yres = yres;
|
||||
|
||||
// kill any excess points
|
||||
for(size_t i = 0; i < oldp.size(); ++i)
|
||||
if(oldp[i])
|
||||
|
@ -90,31 +97,87 @@ void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres)
|
|||
if(!ref)
|
||||
ref = createControlPoint(x, y);
|
||||
}
|
||||
|
||||
_cpx = w;
|
||||
_cpy = h;
|
||||
_xres = xres;
|
||||
_yres = yres;
|
||||
}
|
||||
|
||||
void SplineGrid::recalc()
|
||||
{
|
||||
std::vector<Vector> px(_cpx);
|
||||
switch(splinetype)
|
||||
{
|
||||
case SPLINE_BSPLINE:
|
||||
recalcBSpline();
|
||||
break;
|
||||
|
||||
case SPLINE_COSINE:
|
||||
recalcCosine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SplineGrid::recalcBSpline()
|
||||
{
|
||||
std::vector<Vector> px(std::max(_cpx, _xres));
|
||||
std::vector<Vector> work(std::max(degreeX, degreeY));
|
||||
|
||||
// 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();
|
||||
|
||||
Vector *dst = &tmp[y * _xres];
|
||||
tbsp::evalRange<float, Vector>(dst, _xres, &work[0], &knotsX[0], &px[0], px.size(), degreeX, 0.0f, 1.0f);
|
||||
tbsp::evalRange(dst, _xres, &work[0], &knotsX[0], &px[0], _cpx, degreeX, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
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,
|
||||
*/
|
||||
}
|
||||
|
||||
void SplineGrid::resetControlPoints()
|
||||
{
|
||||
const float dx = width / float(_cpx + 1);
|
||||
const float dy = height / float(_cpy + 1);
|
||||
const float dx = width / float(_cpx - 1);
|
||||
const float dy = height / float(_cpy - 1);
|
||||
float yy = height * -0.5f;
|
||||
for(size_t y = 0; y < _cpy; ++y, yy += dy)
|
||||
{
|
||||
|
@ -128,11 +191,10 @@ void SplineGrid::resetControlPoints()
|
|||
SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
||||
{
|
||||
assert(x < _cpx && y < _cpy);
|
||||
const float w2 = width * -0.5f;
|
||||
const float h2 = height * -0.5f;
|
||||
const Vector wh(width, height);
|
||||
const Vector pos01(float(x) / float(_cpx-1), float(y) / float(_cpy-1));
|
||||
SplineGridCtrlPoint *cp = new SplineGridCtrlPoint();
|
||||
cp->position.x = w2 + float(x) / float(_cpx + 1);
|
||||
cp->position.y = h2 + float(y) / float(_cpy + 1);
|
||||
cp->position = (pos01 - Vector(0.5f, 0.5f)) * wh;
|
||||
this->addChild(cp, PM_POINTER);
|
||||
return cp;
|
||||
}
|
||||
|
@ -140,8 +202,6 @@ SplineGridCtrlPoint* SplineGrid::createControlPoint(size_t x, size_t y)
|
|||
void SplineGrid::onUpdate(float dt)
|
||||
{
|
||||
Quad::onUpdate(dt);
|
||||
|
||||
recalc(); // HACK
|
||||
}
|
||||
|
||||
void SplineGrid::onRender(const RenderState& rs) const
|
||||
|
@ -150,7 +210,7 @@ void SplineGrid::onRender(const RenderState& rs) const
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
const Vector wh(width, height);
|
||||
const Vector wh2(width * 0.5f, height * 0.5f);
|
||||
|
||||
glLineWidth(2);
|
||||
glColor4f(0.0f, 1.0f, 0.3f, 0.3f);
|
||||
|
@ -180,23 +240,20 @@ void SplineGrid::onRender(const RenderState& rs) const
|
|||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
glColor4f(0.0f, 0.2f, 1.0f, 1.0f);
|
||||
glPointSize(3);
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
for(size_t y = 0; y < _cpy; ++y)
|
||||
{
|
||||
glBegin(GL_LINE_STRIP);
|
||||
const value_type *line = &tmp[y * _xres];
|
||||
for(size_t x = 0; x < _xres; ++x)
|
||||
{
|
||||
Vector pos = line[x] * wh;
|
||||
Vector pos = line[x] * wh2;
|
||||
glVertex2f(pos.x, pos.y);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glEnd();
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
#include "glm/glm.hpp"
|
||||
#include "Quad.h"
|
||||
|
||||
enum SplineType
|
||||
{
|
||||
SPLINE_BSPLINE,
|
||||
SPLINE_COSINE,
|
||||
};
|
||||
|
||||
class SplineGridCtrlPoint : public Quad
|
||||
{
|
||||
public:
|
||||
|
@ -27,6 +33,7 @@ public:
|
|||
// # of control points on each axis
|
||||
void resize(size_t w, size_t h, size_t xres, size_t yres);
|
||||
void recalc();
|
||||
|
||||
void resetControlPoints();
|
||||
|
||||
virtual void onRender(const RenderState& rs) const OVERRIDE;
|
||||
|
@ -34,6 +41,9 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void recalcBSpline();
|
||||
void recalcCosine();
|
||||
|
||||
SplineGridCtrlPoint *createControlPoint(size_t x, size_t y);
|
||||
|
||||
unsigned degreeX, degreeY;
|
||||
|
@ -46,6 +56,7 @@ private:
|
|||
size_t _yres;
|
||||
|
||||
std::vector<SplineGridCtrlPoint*> ctrlp;
|
||||
SplineType splinetype;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue