1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-01-24 17:26:41 +00:00

split grid rendering off from Quad, to a new RenderGrid class

This commit is contained in:
fgenesis 2023-07-10 17:23:19 +02:00
parent 0f0f3e9023
commit 976ce8ff3e
12 changed files with 594 additions and 496 deletions

View file

@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "RenderBase.h"
#include "Game.h"
#include "SplineGrid.h"
#include "RenderGrid.h"
int TIMELINE_GRIDSIZE = 10;
@ -958,8 +959,9 @@ void AnimationEditor::editStripKey()
}
else
{
if(editingBone && !editingBone->getDrawGrid().empty())
if(editingBone && editingBone->getGrid())
{
RenderGrid *grid = editingBone->getGrid();
Animation *a = editSprite->getCurrentAnimation();
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
@ -973,12 +975,12 @@ void AnimationEditor::editStripKey()
assert(bk->controlpoints.size() == interp->bsp.ctrlX() * interp->bsp.ctrlY());
splinegrid = new SplineGrid;
splinegrid->drawOrder = editingBone->drawOrder;
RenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY());
rgrid->drawOrder = grid->drawOrder;
splinegrid->setTexture(editingBone->texture->name);
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
splinegrid->position = Vector(400, 300);
//splinegrid->followCamera = 1;
splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), editingBone->getDrawGrid().width(), editingBone->getDrawGrid().height(), interp->bsp.degX(), interp->bsp.degY());
splinegrid->importControlPoints(&bk->controlpoints[0]);
//editSprite->addChild(splinegrid, PM_STATIC, RBP_OFF, CHILD_FRONT);
//editSprite->alphaMod = 0.5f;

View file

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Element.h"
#include "Game.h"
#include "RenderGrid.h"
ElementEffectData::ElementEffectData()
: elementEffectType(EFX_NONE)
@ -182,8 +183,8 @@ void Element::update(float dt)
updateLife(dt);
if (eff)
updateEffects(dt);
if (!drawGrid.empty())
updateGrid(dt);
if(grid)
grid->update(dt);
}
}
@ -204,26 +205,8 @@ int Element::getElementEffectIndex()
void Element::setGridFromWavy()
{
if (!drawGrid.empty())
{
const size_t NX = drawGrid.width() - 1;
const size_t H = drawGrid.height();
const float iw = 1.0f / float(getWidth());
for (size_t x = 0; x < NX; x++)
{
for (size_t y = 0; y < H; y++)
{
const size_t wavy_y = (H - y)-1;
if (wavy_y < 0 || wavy_y < eff->wavy.size())
{
const float tmp = eff->wavy[wavy_y].x * iw;
drawGrid(x,y).x = tmp - 0.5f;
drawGrid(x+1,y).x = tmp + 0.5f;
}
}
}
}
if(grid && eff->wavy.size())
grid->setFromWavy(&eff->wavy[0], eff->wavy.size(), width);
}
void Element::setElementEffectByIndex(int eidx)

View file

@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Gradient.h"
#include "TTFFont.h"
#include "RoundedRect.h"
#include "RenderGrid.h"
#define GEM_GRAB 10
@ -561,8 +562,12 @@ void WorldMapRender::setVis(WorldMapTile *tile)
if (visMethod == VIS_VERTEX)
{
tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
tileDataToVis(tile, tile->q->getDrawGrid());
RenderGrid *g = tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
if(g)
{
g->drawOrder = GRID_DRAW_WORLDMAP;
tileDataToVis(tile, g->array2d());
}
}
else if (visMethod == VIS_WRITE)
{
@ -662,7 +667,6 @@ WorldMapRender::WorldMapRender() : RenderObject(), ActionMapper()
q->setTexturePointer(texs[i]);
q->position = pos;
q->alphaMod = 0;
q->drawOrder = Quad::GRID_DRAW_WORLDMAP;
tile->q = q;

View file

@ -112,7 +112,7 @@ public:
int screenWidth, screenHeight;
int textureWidth, textureHeight;
Vector ** drawGrid;
Vector ** drawGrid; // TODO: make this + related code use RenderGrid
// returns handle > 0 on success
int loadShaderFile(const char *vert, const char *frag);

View file

@ -72,6 +72,8 @@ set(BBGE_SRCS
Refcounted.h
RenderBase.cpp
RenderBase.h
RenderGrid.cpp
RenderGrid.h
RenderObject.cpp
RenderObject.h
RenderObject_inline.h

View file

@ -21,148 +21,92 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Quad.h"
#include "Core.h"
#include "RenderBase.h"
#include "RenderGrid.h"
#include <assert.h>
Quad::Quad(const std::string &tex, const Vector &pos)
: RenderObject()
{
renderBorderColor = Vector(1,1,1);
initQuad();
renderBorderColor = Vector(1,1,1);
position = pos;
setTexture(tex);
}
Quad::Quad() : RenderObject()
{
initQuad();
}
void Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
Quad::~Quad()
{
deleteGrid();
if (x == 0 || y == 0)
{
doUpdateGrid = false;
}
else
{
doUpdateGrid = true;
this->drawGridOffsetX = dgox;
this->drawGridOffsetY = dgoy;
this->drawGridModX = dgmx;
this->drawGridModY = dgmy;
this->drawGridTimeMultiplier = dgtm;
drawGridOut = dgo;
createGrid(x, y);
}
gridTimer = 0;
}
void Quad::createGrid(int xd, int yd)
void Quad::initQuad()
{
drawGrid.init(xd, yd);
resetGrid();
Vector *dg = drawGrid.data();
for(size_t i = 0; i < drawGrid.linearsize(); ++i)
dg[i].z = 1.0f;
addType(SCO_QUAD);
borderAlpha = 0.5;
repeatToFillScale = Vector(1,1);
autoWidth = autoHeight = 0;
renderBorder = false;
renderCenter = true;
width = 2; height = 2;
upperLeftTextureCoordinates = Vector(0,0);
lowerRightTextureCoordinates = Vector(1,1);
renderQuad = true;
grid = NULL;
}
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
void Quad::deleteGrid()
{
if (x < drawGrid.width() && y < drawGrid.height())
{
drawGrid(x, y).z = alpha;
}
delete grid;
grid = NULL;
}
void Quad::setStripPoints(bool vert, const Vector *points, size_t n)
void Quad::destroy()
{
if (drawGrid.empty()) return;
resetGrid();
deleteGrid();
RenderObject::destroy();
}
const float mul = float(n);
if (!vert) // horz
{
const size_t xmax = std::min(drawGrid.width(), n);
for (size_t y = 0; y < drawGrid.height(); y++)
{
Vector *row = drawGrid.row(y);
for (size_t x = 0; x < xmax; x++)
row[x] += points[x] * mul;
}
}
else
{
const size_t ymax = std::min(drawGrid.height(), n);
for (size_t x = 0; x < drawGrid.width(); x++)
for (size_t y = 0; y < ymax; y++)
drawGrid(x, y) += points[y] * mul;
}
}
void Quad::ResetGrid(Vector* dst, size_t w, size_t h)
RenderGrid *Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
{
assert(w > 1 && h > 1);
const float xMulF = 1.0f / (float)(w-1);
const float yMulF = 1.0f / (float)(h-1);
for (size_t y = 0; y < h; y++)
{
const float yval = float(y)*yMulF-0.5f;
for (size_t x = 0; x < w; x++)
{
dst->x = float(x)*xMulF-0.5f;
dst->y = yval;
++dst;
}
}
RenderGrid *g = createGrid(x, y);
if(g)
g->setSegs(dgox, dgoy, dgmx, dgmy, dgtm, dgo);
return g;
}
void Quad::ResetGridAndAlpha(Vector* dst, size_t w, size_t h, float alpha)
RenderGrid *Quad::createGrid(int xd, int yd)
{
assert(w > 1 && h > 1);
const float xMulF = 1.0f / (float)(w-1);
const float yMulF = 1.0f / (float)(h-1);
for (size_t y = 0; y < h; y++)
{
const float yval = float(y)*yMulF-0.5f;
for (size_t x = 0; x < w; x++)
{
dst->x = float(x)*xMulF-0.5f;
dst->y = yval;
dst->z = alpha;
++dst;
}
}
delete grid;
return (grid = xd && yd
? new RenderGrid(xd, yd)
: NULL);
}
void Quad::resetGrid()
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
{
if (drawGrid.empty()) return;
ResetGrid(drawGrid.data(), drawGrid.width(), drawGrid.height());
if(grid)
grid->setAlpha(x, y, alpha);
}
void Quad::initQuad()
void Quad::setStripPoints(bool vert, const Vector *points, size_t n)
{
repeatToFillScale = Vector(1,1);
gridType = GRID_WAVY;
gridTimer = 0;
doUpdateGrid = false;
autoWidth = autoHeight = 0;
renderBorder = false;
renderCenter = true;
width = 2; height = 2;
upperLeftTextureCoordinates = Vector(0,0);
lowerRightTextureCoordinates = Vector(1,1);
renderQuad = true;
if(grid)
grid->setStripPoints(vert, points, n);
}
void Quad::resetGrid()
{
if(grid)
grid->reset();
}
void Quad::_renderBorder(const RenderState& rs, Vector color, float borderalpha) const
@ -195,27 +139,7 @@ void Quad::_renderBorder(const RenderState& rs, Vector color, float borderalpha)
RenderObject::lastTextureApplied = 0;
}
Quad::Quad() : RenderObject()
{
addType(SCO_QUAD);
borderAlpha = 0.5;
drawOrder = GRID_DRAW_DEFAULT;
initQuad();
}
void Quad::deleteGrid()
{
drawGrid.clear();
}
void Quad::destroy()
{
deleteGrid();
RenderObject::destroy();
}
bool Quad::isCoordinateInside(Vector coord, int minSize) const
{
@ -275,272 +199,28 @@ bool Quad::isCoordinateInsideWorldRect(const Vector &coord, int w, int h) const
return false;
}
void Quad::updateGrid(float dt)
{
if (!doUpdateGrid) return;
if (gridType == GRID_WAVY)
{
gridTimer += dt * drawGridTimeMultiplier;
resetGrid();
size_t hx = drawGrid.width()/2;
for (size_t x = 0; x < drawGrid.width(); x++)
{
float yoffset = x * drawGridOffsetY;
float addY = 0;
if (drawGridModY != 0)
addY = cosf(gridTimer+yoffset)*drawGridModY;
for (size_t y = 0; y < drawGrid.height(); y++)
{
float xoffset = y * drawGridOffsetX;
if (drawGridModX != 0)
{
float addX = (sinf(gridTimer+xoffset)*drawGridModX);
if (drawGridOut && x < hx)
drawGrid(x,y).x += addX;
else
drawGrid(x,y).x -= addX;
}
drawGrid(x,y).y += addY;
}
}
}
}
void Quad::renderGrid(const RenderState& rs) const
{
if (drawGrid.width() < 2 || drawGrid.height() < 2)
return;
switch(drawOrder)
{
case GRID_DRAW_LRTB:
renderGrid_LRTB(rs);
break;
RenderState rx(rs);
rx.color = rs.color * this->color;
rx.alpha = rs.alpha * this->alpha.x * this->alphaMod;
case GRID_DRAW_LRBT:
renderGrid_LRBT(rs);
break;
glPushMatrix();
glScalef(width, height, 1);
case GRID_DRAW_WORLDMAP:
renderGridWithAlpha(rs);
break;
}
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
// debug points
if (RenderObject::renderCollisionShape)
{
const size_t NX = drawGrid.width()-1;
const size_t NY = drawGrid.height()-1;
const float w = this->getWidth();
const float h = this->getHeight();
glBindTexture(GL_TEXTURE_2D, 0);
glPointSize(2);
glColor3f(1,0,0);
glBegin(GL_POINTS);
for (size_t y = 0; y < NY; y++)
{
for (size_t x = 0; x < NX; x++)
{
glVertex2f(w*drawGrid(x,y).x, h*drawGrid(x,y).y);
glVertex2f(w*drawGrid(x,y+1).x, h*drawGrid(x,y+1).y);
glVertex2f(w*drawGrid(x+1,y+1).x, h*drawGrid(x+1,y+1).y);
glVertex2f(w*drawGrid(x+1,y).x, h*drawGrid(x+1,y).y);
}
}
glEnd();
grid->renderDebugPoints(rx);
RenderObject::lastTextureApplied = 0;
}
}
void Quad::renderGrid_LRTB(const RenderState& rs) const
{
const float percentX = lowerRightTextureCoordinates.x - upperLeftTextureCoordinates.x;
const float percentY = lowerRightTextureCoordinates.y - upperLeftTextureCoordinates.y;
const float baseX = upperLeftTextureCoordinates.x;
const float baseY = upperLeftTextureCoordinates.y;
const size_t NX = drawGrid.width()-1;
const size_t NY = drawGrid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
const float w = this->getWidth();
const float h = this->getHeight();
const float red = rs.color.x * this->color.x;
const float green = rs.color.y * this->color.y;
const float blue = rs.color.z * this->color.z;
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
glColor4f(red, green, blue, alpha);
glBegin(GL_QUADS);
float v0 = baseY;
float v1 = v0 + incY;
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = drawGrid.row(y);
const Vector *row1 = drawGrid.row(y+1);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
glTexCoord2f(u0, v0);
glVertex2f(w*dg00.x, h*dg00.y);
glTexCoord2f(u0, v1);
glVertex2f(w*dg01.x, h*dg01.y);
glTexCoord2f(u1, v1);
glVertex2f(w*dg11.x, h*dg11.y);
glTexCoord2f(u1, v0);
glVertex2f(w*dg10.x, h*dg10.y);
}
}
glEnd();
}
void Quad::renderGrid_LRBT(const RenderState& rs) const
{
const float percentX = lowerRightTextureCoordinates.x - upperLeftTextureCoordinates.x;
const float percentY = upperLeftTextureCoordinates.y - lowerRightTextureCoordinates.y;
const float baseX = upperLeftTextureCoordinates.x;
const float baseY = lowerRightTextureCoordinates.y;
const size_t NX = drawGrid.width()-1;
const size_t NY = drawGrid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
const float w = this->getWidth();
const float h = this->getHeight();
const float red = rs.color.x * this->color.x;
const float green = rs.color.y * this->color.y;
const float blue = rs.color.z * this->color.z;
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
glColor4f(red, green, blue, alpha);
glBegin(GL_QUADS);
float v0 = baseY;
float v1 = v0 + incY;
for (size_t y = NY; y --> 0; v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = drawGrid.row(y+1);
const Vector *row1 = drawGrid.row(y);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
glTexCoord2f(u0, v0);
glVertex2f(w*dg00.x, h*dg00.y);
glTexCoord2f(u0, v1);
glVertex2f(w*dg01.x, h*dg01.y);
glTexCoord2f(u1, v1);
glVertex2f(w*dg11.x, h*dg11.y);
glTexCoord2f(u1, v0);
glVertex2f(w*dg10.x, h*dg10.y);
}
}
glEnd();
glPopMatrix();
}
void Quad::renderGridWithAlpha(const RenderState& rs) const
{
const float percentX = fabsf(this->lowerRightTextureCoordinates.x - this->upperLeftTextureCoordinates.x);
const float percentY = fabsf(this->upperLeftTextureCoordinates.y - this->lowerRightTextureCoordinates.y);
const float baseX =
(lowerRightTextureCoordinates.x < upperLeftTextureCoordinates.x)
? lowerRightTextureCoordinates.x : upperLeftTextureCoordinates.x;
const float baseY =
(lowerRightTextureCoordinates.y < upperLeftTextureCoordinates.y)
? lowerRightTextureCoordinates.y : upperLeftTextureCoordinates.y;
const size_t NX = drawGrid.width()-1;
const size_t NY = drawGrid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
const float w = this->getWidth();
const float h = this->getHeight();
const float red = rs.color.x * this->color.x;
const float green = rs.color.y * this->color.y;
const float blue = rs.color.z * this->color.z;
const float alpha = rs.alpha * this->alpha.x * this->alphaMod;
glBegin(GL_QUADS);
float v0 = 1 - percentY + baseY;
float v1 = v0 + incY;
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = drawGrid.row(y);
const Vector *row1 = drawGrid.row(y+1);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
if (dg00.z != 0 || dg01.z != 0 || dg10.z != 0 || dg11.z != 0)
{
glColor4f(red, green, blue, alpha*dg00.z);
glTexCoord2f(u0, v0);
glVertex2f(w*dg00.x, h*dg00.y);
glColor4f(red, green, blue, alpha*dg01.z);
glTexCoord2f(u0, v1);
glVertex2f(w*dg01.x, h*dg01.y);
glColor4f(red, green, blue, alpha*dg11.z);
glTexCoord2f(u1, v1);
glVertex2f(w*dg11.x, h*dg11.y);
glColor4f(red, green, blue, alpha*dg10.z);
glTexCoord2f(u1, v0);
glVertex2f(w*dg10.x, h*dg10.y);
}
}
}
glEnd();
}
void Quad::repeatTextureToFill(bool on)
{
@ -556,7 +236,7 @@ void Quad::onRender(const RenderState& rs) const
const float _w2 = width*0.5f;
const float _h2 = height*0.5f;
if (drawGrid.empty())
if (!grid)
{
glBegin(GL_QUADS);
{
@ -643,9 +323,9 @@ void Quad::onUpdate(float dt)
else if (autoHeight == AUTO_VIRTUALHEIGHT)
height = core->getVirtualHeight();
if (!drawGrid.empty() && alpha.x > 0 && alphaMod > 0)
if (grid && alpha.x > 0 && alphaMod > 0)
{
updateGrid(dt);
grid->update(dt);
}
}

View file

@ -39,12 +39,15 @@ protected:
void onRender(const RenderState& rs) const OVERRIDE;
};
class RenderGrid;
class Quad : public RenderObject
{
public:
Quad(const std::string &tex, const Vector &pos);
Quad();
void createGrid(int x, int y);
virtual ~Quad();
RenderGrid *createGrid(int x, int y);
void destroy() OVERRIDE;
bool isCoordinateInside(Vector coord, int minSize=0) const;
bool isCoordinateInsideWorld(const Vector &coord, int minSize=0) const;
@ -58,78 +61,44 @@ public:
float getWidth() const {return width;}
float getHeight() const {return height;}
void setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
RenderGrid *setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
void setDrawGridAlpha(size_t x, size_t y, float alpha);
void repeatTextureToFill(bool on);
void refreshRepeatTextureToFill();
bool isRepeatingTextureToFill() const { return repeatTexture; }
void setStripPoints(bool vert, const Vector *points, size_t n);
Array2d<Vector>& getDrawGrid() { return drawGrid; }
const Array2d<Vector>& getDrawGrid() const { return drawGrid; }
RenderGrid *getGrid() { return grid; }
const RenderGrid *getGrid() const { return grid; }
void reloadDevice() OVERRIDE;
void deleteGrid();
Vector upperLeftTextureCoordinates, lowerRightTextureCoordinates;
enum GridDrawOrder
{
GRID_DRAW_WORLDMAP = -1, // LRTB order, uses grid.z as alpha
GRID_DRAW_LRTB = 0, // the default. ignores grid.z
GRID_DRAW_LRBT = 1, // Y axis inverted
GRID_DRAW_DEFAULT = GRID_DRAW_LRTB
};
enum GridType
{
GRID_WAVY = 0,
GRID_STRIP = 1, // quad is in strip mode
GRID_INTERP = 2, // quad is in grid mode
};
unsigned char gridType; // unsigned char to save space
char autoWidth, autoHeight; // char to save space
// TODO: this should be a bitmask
char autoWidth, autoHeight;
bool renderQuad, renderCenter, renderBorder;
Vector texOff;
float borderAlpha;
Vector renderBorderColor;
Vector repeatToFillScale;
static void ResetGrid(Vector *dst, size_t w, size_t h);
static void ResetGridAndAlpha(Vector *dst, size_t w, size_t h, float alpha = 1.0f);
protected:
RenderGrid *grid;
protected:
float gridTimer;
Array2d<Vector> drawGrid;
void resetGrid();
void updateGrid(float dt);
void renderGrid(const RenderState& rs) const;
void renderGrid_LRTB(const RenderState& rs) const;
void renderGrid_LRBT(const RenderState& rs) const;
void renderGridWithAlpha(const RenderState& rs) const;
float drawGridOffsetX;
float drawGridOffsetY;
float drawGridModX;
float drawGridModY;
float drawGridTimeMultiplier;
bool drawGridOut;
void onSetTexture() OVERRIDE;
void onRender(const RenderState& rs) const OVERRIDE;
void onUpdate(float dt) OVERRIDE;
public:
GridDrawOrder drawOrder;
private:
bool doUpdateGrid;
void initQuad();
void _renderBorder(const RenderState& rs, Vector color, float borderalpha) const;
};

381
BBGE/RenderGrid.cpp Normal file
View file

@ -0,0 +1,381 @@
#include "RenderGrid.h"
#include "RenderBase.h"
#include "RenderState.h"
static void ResetGrid(Vector* dst, size_t w, size_t h)
{
assert(w > 1 && h > 1);
const float xMulF = 1.0f / (float)(w-1);
const float yMulF = 1.0f / (float)(h-1);
for (size_t y = 0; y < h; y++)
{
const float yval = float(y)*yMulF-0.5f;
for (size_t x = 0; x < w; x++)
{
dst->x = float(x)*xMulF-0.5f;
dst->y = yval;
++dst;
}
}
}
void RenderGrid::ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha)
{
assert(w > 1 && h > 1);
const float xMulF = 1.0f / (float)(w-1);
const float yMulF = 1.0f / (float)(h-1);
for (size_t y = 0; y < h; y++)
{
const float yval = float(y)*yMulF-0.5f;
for (size_t x = 0; x < w; x++)
{
dst->x = float(x)*xMulF-0.5f;
dst->y = yval;
dst->z = alpha;
++dst;
}
}
}
RenderGrid::RenderGrid(size_t w, size_t h)
: gridTimer(0)
, drawGridOffsetX(0), drawGridOffsetY(0), drawGridModX(0), drawGridModY(0), drawGridTimeMultiplier(0)
, drawGridOut(false), gridType(GRID_WAVY), drawOrder(GRID_DRAW_DEFAULT)
{
init(w, h);
}
RenderGrid::~RenderGrid()
{
}
void RenderGrid::init(size_t w, size_t h)
{
assert(w > 1 && h > 1);
grid.init(w, h);
reset();
Vector *dg = grid.data();
for(size_t i = 0; i < grid.linearsize(); ++i)
dg[i].z = 1.0f;
}
void RenderGrid::reset()
{
ResetGrid(grid.data(), grid.width(), grid.height());
}
void RenderGrid::resetWithAlpha(float a)
{
ResetWithAlpha(grid.data(), grid.width(), grid.height(), a);
}
void RenderGrid::update(float dt)
{
if (gridType == GRID_WAVY)
{
gridTimer += dt * drawGridTimeMultiplier;
reset();
size_t hx = grid.width()/2;
for (size_t x = 0; x < grid.width(); x++)
{
float yoffset = x * drawGridOffsetY;
float addY = 0;
if (drawGridModY != 0)
addY = cosf(gridTimer+yoffset)*drawGridModY;
for (size_t y = 0; y < grid.height(); y++)
{
float xoffset = y * drawGridOffsetX;
if (drawGridModX != 0)
{
float addX = (sinf(gridTimer+xoffset)*drawGridModX);
if (drawGridOut && x < hx)
grid(x,y).x += addX;
else
grid(x,y).x -= addX;
}
grid(x,y).y += addY;
}
}
}
}
void RenderGrid::setAlpha(size_t x, size_t y, float a)
{
if (x < grid.width() && y < grid.height())
grid(x, y).z = a;
}
void RenderGrid::setSegs(float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
{
drawGridOffsetX = dgox;
drawGridOffsetY = dgoy;
drawGridModX = dgmx;
drawGridModY = dgmy;
drawGridTimeMultiplier = dgtm;
drawGridOut = dgo;
gridTimer = 0;
gridType = GRID_WAVY;
}
void RenderGrid::setStripPoints(bool vert, const Vector* points, size_t n)
{
reset();
const float mul = float(n);
if (!vert) // horz
{
const size_t xmax = std::min(grid.width(), n);
for (size_t y = 0; y < grid.height(); y++)
{
Vector *row = grid.row(y);
for (size_t x = 0; x < xmax; x++)
row[x] += points[x] * mul;
}
}
else
{
const size_t ymax = std::min(grid.height(), n);
for (size_t x = 0; x < grid.width(); x++)
for (size_t y = 0; y < ymax; y++)
grid(x, y) += points[y] * mul;
}
}
void RenderGrid::setFromWavy(const Vector* wavy, size_t len, float width)
{
const size_t NX = grid.width() - 1;
const size_t H = grid.height();
const float iw = 1.0f / width;
for (size_t x = 0; x < NX; x++) // TODO invert loop
{
for (size_t y = 0; y < H; y++)
{
const size_t wavy_y = (H - y)-1;
if (wavy_y < len)
{
const float tmp = wavy[wavy_y].x * iw;
grid(x,y).x = tmp - 0.5f;
grid(x+1,y).x = tmp + 0.5f;
}
}
}
}
void RenderGrid::render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
{
switch(drawOrder)
{
case GRID_DRAW_LRTB:
render_LRTB(rs, upperLeftTexCoords, lowerRightTexCoords);
break;
case GRID_DRAW_LRBT:
render_LRBT(rs, upperLeftTexCoords, lowerRightTexCoords);
break;
case GRID_DRAW_WORLDMAP:
render_WithAlpha(rs, upperLeftTexCoords, lowerRightTexCoords);
break;
}
}
void RenderGrid::renderDebugPoints(const RenderState& rs) const
{
(void)rs; // unused
glPointSize(2);
glColor3f(1,0,0);
glBegin(GL_POINTS);
const size_t NX = grid.width()-1;
const size_t NY = grid.height()-1;
for (size_t y = 0; y < NY; y++)
{
for (size_t x = 0; x < NX; x++)
{
glVertex2f(grid(x,y).x, grid(x,y).y);
glVertex2f(grid(x,y+1).x, grid(x,y+1).y);
glVertex2f(grid(x+1,y+1).x, grid(x+1,y+1).y);
glVertex2f(grid(x+1,y).x, grid(x+1,y).y);
}
}
glEnd();
}
void RenderGrid::render_LRTB(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
{
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
const float percentY = lowerRightTexCoords.y - upperLeftTexCoords.y;
const float baseX = upperLeftTexCoords.x;
const float baseY = upperLeftTexCoords.y;
const size_t NX = grid.width()-1;
const size_t NY = grid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
glColor4f(rs.color.x, rs.color.y, rs.color.z, rs.alpha);
glBegin(GL_QUADS);
float v0 = baseY;
float v1 = v0 + incY;
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = grid.row(y);
const Vector *row1 = grid.row(y+1);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
glTexCoord2f(u0, v0);
glVertex2f(dg00.x, dg00.y);
glTexCoord2f(u0, v1);
glVertex2f(dg01.x, dg01.y);
glTexCoord2f(u1, v1);
glVertex2f(dg11.x, dg11.y);
glTexCoord2f(u1, v0);
glVertex2f(dg10.x, dg10.y);
}
}
glEnd();
}
void RenderGrid::render_LRBT(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
{
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
const float percentY = upperLeftTexCoords.y - lowerRightTexCoords.y;
const float baseX = upperLeftTexCoords.x;
const float baseY = lowerRightTexCoords.y;
const size_t NX = grid.width()-1;
const size_t NY = grid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
glColor4f(rs.color.x, rs.color.y, rs.color.z, rs.alpha);
glBegin(GL_QUADS);
float v0 = baseY;
float v1 = v0 + incY;
for (size_t y = NY; y --> 0; v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = grid.row(y+1);
const Vector *row1 = grid.row(y);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
glTexCoord2f(u0, v0);
glVertex2f(dg00.x, dg00.y);
glTexCoord2f(u0, v1);
glVertex2f(dg01.x, dg01.y);
glTexCoord2f(u1, v1);
glVertex2f(dg11.x, dg11.y);
glTexCoord2f(u1, v0);
glVertex2f(dg10.x, dg10.y);
}
}
glEnd();
}
void RenderGrid::render_WithAlpha(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
{
const float percentX = fabsf(lowerRightTexCoords.x - upperLeftTexCoords.x);
const float percentY = fabsf(upperLeftTexCoords.y - lowerRightTexCoords.y);
const float baseX =
(lowerRightTexCoords.x < upperLeftTexCoords.x)
? lowerRightTexCoords.x : upperLeftTexCoords.x;
const float baseY =
(lowerRightTexCoords.y < upperLeftTexCoords.y)
? lowerRightTexCoords.y : upperLeftTexCoords.y;
const size_t NX = grid.width()-1;
const size_t NY = grid.height()-1;
// NOTE: These are used to avoid repeated expensive divide operations,
// but they may cause rounding error of around 1 part per million,
// which could in theory cause minor graphical glitches with broken
// OpenGL implementations. --achurch
const float incX = percentX / float(NX);
const float incY = percentY / float(NY);
const Vector c = rs.color;
const float alpha = rs.alpha;
glBegin(GL_QUADS);
float v0 = 1 - percentY + baseY;
float v1 = v0 + incY;
for (size_t y = 0; y < NY; y++, v0 = v1, v1 += incY)
{
float u0 = baseX;
float u1 = u0 + incX;
const Vector *row0 = grid.row(y);
const Vector *row1 = grid.row(y+1);
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
{
const Vector dg00 = row0[x];
const Vector dg01 = row1[x];
const Vector dg10 = row0[x+1];
const Vector dg11 = row1[x+1];
if (dg00.z != 0 || dg01.z != 0 || dg10.z != 0 || dg11.z != 0)
{
glColor4f(c.x, c.y, c.z, alpha*dg00.z);
glTexCoord2f(u0, v0);
glVertex2f(dg00.x, dg00.y);
glColor4f(c.x, c.y, c.z, alpha*dg01.z);
glTexCoord2f(u0, v1);
glVertex2f(dg01.x, dg01.y);
glColor4f(c.x, c.y, c.z, alpha*dg11.z);
glTexCoord2f(u1, v1);
glVertex2f(dg11.x, dg11.y);
glColor4f(c.x, c.y, c.z, alpha*dg10.z);
glTexCoord2f(u1, v0);
glVertex2f(dg10.x, dg10.y);
}
}
}
glEnd();
}

73
BBGE/RenderGrid.h Normal file
View file

@ -0,0 +1,73 @@
#ifndef BBGE_RENDERGRID_H
#define BBGE_RENDERGRID_H
#include "Vector.h"
#include "DataStructures.h"
struct RenderState;
enum GridDrawOrder
{
GRID_DRAW_WORLDMAP = -1, // LRTB order, uses grid.z as alpha
GRID_DRAW_LRTB = 0, // the default. ignores grid.z
GRID_DRAW_LRBT = 1, // Y axis inverted
GRID_DRAW_DEFAULT = GRID_DRAW_LRTB
};
enum GridType
{
GRID_UNDEFINED = -1,
GRID_WAVY = 0,
GRID_STRIP = 1, // quad is in strip mode
GRID_INTERP = 2, // quad is in grid mode
};
class RenderGrid
{
public:
RenderGrid(size_t w, size_t h);
~RenderGrid();
void init(size_t w, size_t h);
void reset();
void resetWithAlpha(float a);
void update(float dt);
void render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
void renderDebugPoints(const RenderState& rs) const;
void setAlpha(size_t x, size_t y, float a);
void setSegs(float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
void setStripPoints(bool vert, const Vector *points, size_t n);
void setFromWavy(const Vector *wavy, size_t len, float width);
size_t width() const { return grid.width(); }
size_t height() const { return grid.height(); }
size_t linearsize() const { return grid.linearsize(); }
const Vector *data() const { return grid.data(); }
Vector *data() { return grid.data(); }
Array2d<Vector>& array2d() { return grid; }
const Array2d<Vector>& array2d() const { return grid; }
static void ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha);
protected:
Array2d<Vector> grid;
float gridTimer;
float drawGridOffsetX;
float drawGridOffsetY;
float drawGridModX;
float drawGridModY;
float drawGridTimeMultiplier;
bool drawGridOut;
public:
unsigned char gridType; // unsigned char to save space
unsigned char drawOrder;
void render_LRTB(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
void render_LRBT(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
void render_WithAlpha(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
};
#endif

View file

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "ReadXML.h"
#include "RenderBase.h"
#include "SplineGrid.h"
#include "RenderGrid.h"
#include <tinyxml2.h>
using namespace tinyxml2;
@ -129,16 +130,9 @@ void Bone::addSegment(Bone *b)
void Bone::createStrip(bool vert, int num)
{
if (!vert)
{
createGrid(num, 2);
}
else
{
createGrid(2, num);
}
RenderGrid *grid = vert ? createGrid(2, num) : createGrid(num, 2);
stripVert = vert;
gridType = GRID_STRIP;
grid->gridType = GRID_STRIP;
changeStrip.resize(num);
}
@ -980,6 +974,7 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
XMLElement *bones = xml->NewElement("Bones");
for (i = 0; i < this->bones.size(); i++)
{
const RenderGrid * const grid = this->bones[i]->getGrid();
XMLElement *bone = xml->NewElement("Bone");
bone->SetAttribute("idx", (unsigned int) this->bones[i]->boneIdx);
bone->SetAttribute("gfx", this->bones[i]->gfx.c_str());
@ -1009,10 +1004,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
bone->SetAttribute("offy", this->bones[i]->offset.y);
if (!this->bones[i]->prt.empty())
bone->SetAttribute("prt", this->bones[i]->prt.c_str());
if(!this->bones[i]->getDrawGrid().empty() && this->bones[i]->gridType != Quad::GRID_STRIP)
if(grid && grid->gridType != GRID_STRIP)
{
std::ostringstream os;
os << this->bones[i]->getDrawGrid().width() << " " << this->bones[i]->getDrawGrid().height();
os << grid->width() << " " << grid->height();
bone->SetAttribute("grid", os.str().c_str());
}
else if (!this->bones[i]->changeStrip.empty())
@ -1037,9 +1032,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
os << this->bones[i]->originalScale.x << " " << this->bones[i]->originalScale.y;
bone->SetAttribute("sz", os.str().c_str());
}
if(this->bones[i]->drawOrder != Quad::GRID_DRAW_DEFAULT)
if(grid && grid->drawOrder != GRID_DRAW_DEFAULT)
{
bone->SetAttribute("gridDrawOrder", (int)this->bones[i]->drawOrder);
bone->SetAttribute("gridDrawOrder", (int)grid->drawOrder);
}
@ -1132,9 +1128,10 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
Bone *bone = this->getBoneByIdx(b->idx);
if(bone)
{
const RenderGrid * const bgrid = bone->getGrid();
os << b->idx << " " << b->x << " " << b->y << " " << b->rot << " ";
// don't want to store grid points if they can be regenerated automatically
size_t usedGridSize = bone->gridType == Quad::GRID_INTERP ? 0 : b->grid.size();
size_t usedGridSize = (!bgrid || bgrid->gridType == GRID_INTERP) ? 0 : b->grid.size();
os << usedGridSize << " ";
if(usedGridSize)
for (size_t i = 0; i < usedGridSize; i++)
@ -1604,12 +1601,13 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
}
if (bone->Attribute("grid"))
{
if(newb->getDrawGrid().empty())
RenderGrid *grid = newb->getGrid();
if(!grid)
{
SimpleIStringStream is(bone->Attribute("grid"), SimpleIStringStream::REUSE);
int x, y;
is >> x >> y;
newb->createGrid(x, y);
grid = newb->createGrid(x, y);
}
else
{
@ -1617,11 +1615,11 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
os << "Bone idx " << newb->idx << " already has a DrawGrid, ignoring \"grid\" attribute";
errorLog(os.str());
}
}
if(const char *gdo = bone->Attribute("gridDrawOrder"))
{
int ord = atoi(gdo);
newb->drawOrder = (Quad::GridDrawOrder)ord;
if(const char *gdo = bone->Attribute("gridDrawOrder"))
{
int ord = atoi(gdo);
grid->drawOrder = (GridDrawOrder)ord;
}
}
bone = bone->NextSiblingElement("Bone");
}
@ -1809,7 +1807,6 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
for (size_t i = 0; i < this->bones.size(); i++)
{
Bone *bone = this->bones[i];
const Array2d<Vector>& dg = bone->getDrawGrid();
BoneKeyframe *bk = newSkeletalKeyframe.getBoneKeyframe(bone->boneIdx);
if(!bk)
{
@ -1845,7 +1842,8 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
debugLog(os.str());
continue;
}
if(bi->getDrawGrid().empty())
RenderGrid *grid = bi->getGrid();
if(!grid)
{
std::ostringstream os;
os << "Interpolator specifies bone [" << bi->boneIdx << "] that has no grid";
@ -1854,7 +1852,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
}
SplineType spline = SPLINE_BSPLINE;
int cx = 3, cy = 3, degx = 3, degy = 3;
unsigned cx = 3, cy = 3, degx = 3, degy = 3;
if(const char *stype = interp->Attribute("type"))
{
SimpleIStringStream is(stype, SimpleIStringStream::REUSE);
@ -1883,7 +1881,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
}
}
bi->gridType = Quad::GRID_INTERP;
grid->gridType = GRID_INTERP;
// bone grid should have been created via <Bone grid=... /> earlier
const char *idata = interp->Attribute("data");
@ -1898,7 +1896,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
bgip.bsp.resize(cx, cy, degx, degy);
const size_t numcp = size_t(cx) * size_t(cy);
const size_t numgridp = bi->getDrawGrid().linearsize();
const size_t numgridp = grid->linearsize();
// data format: "W H [x y x y ... (W*H times)] W H x y x y ..."
// ^- start of 1st keyframe ^- 2nd keyframe
@ -2062,7 +2060,8 @@ void AnimationLayer::updateBones()
b->scale.x = lerp(bkey1->sx, bkey2->sx, dt, lerpType);
b->scale.y = lerp(bkey1->sy, bkey2->sy, dt, lerpType);
}
if (b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && b->gridType == Quad::GRID_STRIP)
RenderGrid *grid = b->getGrid();
if (grid && b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && grid->gridType == GRID_STRIP)
{
if (bkey2->grid.size() < b->changeStrip.size())
bkey2->grid.resize(b->changeStrip.size());
@ -2074,22 +2073,21 @@ void AnimationLayer::updateBones()
}
b->setStripPoints(b->stripVert, &b->changeStrip[0], b->changeStrip.size());
}
if (b->animated==Bone::ANIM_ALL && b->gridType == Quad::GRID_INTERP)
if (grid && b->animated==Bone::ANIM_ALL && grid->gridType == GRID_INTERP)
{
Array2d<Vector>& dg = b->getDrawGrid();
const size_t N = dg.linearsize();
const size_t N = grid->linearsize();
if(bkey1->grid.size() < N)
{
bkey1->grid.resize(N);
Quad::ResetGridAndAlpha(&bkey1->grid[0], dg.width(), dg.height(), 1.0f);
RenderGrid::ResetWithAlpha(&bkey1->grid[0], grid->width(), grid->height(), 1.0f);
}
if(bkey2->grid.size() < N)
{
bkey2->grid.resize(N);
Quad::ResetGridAndAlpha(&bkey2->grid[0], dg.width(), dg.height(), 1.0f);
RenderGrid::ResetWithAlpha(&bkey2->grid[0], grid->width(), grid->height(), 1.0f);
}
Vector *dst = dg.data();
Vector *dst = grid->data();
for(size_t i = 0; i < N; ++i)
{
dst[i].x = lerp(bkey1->grid[i].x, bkey2->grid[i].x, dt, lerpType);
@ -2219,16 +2217,16 @@ void SkeletalSprite::selectNextBone()
void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
{
const Array2d<Vector>& dg = bone->getDrawGrid();
const RenderGrid *grid = bone->getGrid();
assert(bone->boneIdx == bk.idx);
assert(bk.grid.size() == dg.linearsize());
bsp.recalc(&bk.grid[0], dg.width(), dg.height(), &bk.controlpoints[0]);
assert(bk.grid.size() == grid->linearsize());
bsp.recalc(&bk.grid[0], grid->width(), grid->height(), &bk.controlpoints[0]);
}
void BoneGridInterpolator::updateGridAndBone(BoneKeyframe& bk, Bone *bone)
{
updateGridOnly(bk, bone);
Vector *dst = bone->getDrawGrid().data();
Vector *dst = bone->getGrid()->data();
std::copy(bk.grid.begin(), bk.grid.end(), dst);
}

View file

@ -1,6 +1,7 @@
#include "SplineGrid.h"
#include "RenderBase.h"
#include "Core.h"
#include "RenderGrid.h"
SplineGridCtrlPoint *SplineGridCtrlPoint::movingPoint;
@ -69,7 +70,7 @@ void SplineGridCtrlPoint::onUpdate(float dt)
}
SplineGrid::SplineGrid()
: deg(0)
: wasModified(false), deg(0)
{
setWidthHeight(128, 128);
renderQuad = true;
@ -80,12 +81,12 @@ SplineGrid::~SplineGrid()
{
}
void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
RenderGrid *SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy)
{
size_t oldcpx = bsp.ctrlX();
size_t oldcpy = bsp.ctrlY();
this->createGrid(xres, yres);
RenderGrid *ret = this->createGrid(xres, yres);
std::vector<SplineGridCtrlPoint*> oldp;
ctrlp.swap(oldp);
@ -121,13 +122,18 @@ void SplineGrid::resize(size_t w, size_t h, size_t xres, size_t yres, unsigned d
}
recalc();
return ret;
}
void SplineGrid::recalc()
{
exportControlPoints(&bsp.controlpoints[0]);
bsp.recalc(drawGrid.data(), drawGrid.width(), drawGrid.height());
wasModified = true;
if(grid)
{
bsp.recalc(grid->data(), grid->width(), grid->height());
wasModified = true;
}
}
void SplineGrid::exportControlPoints(Vector* controlpoints)

View file

@ -33,7 +33,7 @@ public:
~SplineGrid();
// # of control points on each axis
void resize(size_t w, size_t h, size_t xres, size_t yres, unsigned degx, unsigned degy);
RenderGrid *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);