mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-05-11 03:23:50 +00:00
More work on tile rendering:
- Use indexed triangle rendering, no more GL_QUADS for tiles - Fix aquarian text on maps - Tile tex repeat mode works again Known broken: - Editor - Tile repeat with grid effects
This commit is contained in:
parent
395ff079e9
commit
368271c40e
25 changed files with 749 additions and 429 deletions
|
@ -961,7 +961,7 @@ void AnimationEditor::editStripKey()
|
||||||
{
|
{
|
||||||
if(editingBone && editingBone->getGrid())
|
if(editingBone && editingBone->getGrid())
|
||||||
{
|
{
|
||||||
RenderGrid *grid = editingBone->getGrid();
|
DynamicRenderGrid *grid = editingBone->getGrid();
|
||||||
Animation *a = editSprite->getCurrentAnimation();
|
Animation *a = editSprite->getCurrentAnimation();
|
||||||
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
||||||
|
|
||||||
|
@ -975,8 +975,8 @@ void AnimationEditor::editStripKey()
|
||||||
assert(bk->controlpoints.size() == interp->bsp.ctrlX() * interp->bsp.ctrlY());
|
assert(bk->controlpoints.size() == interp->bsp.ctrlX() * interp->bsp.ctrlY());
|
||||||
|
|
||||||
splinegrid = new SplineGrid;
|
splinegrid = new SplineGrid;
|
||||||
RenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY());
|
DynamicRenderGrid *rgrid = splinegrid->resize(interp->bsp.ctrlX(), interp->bsp.ctrlY(), grid->width(), grid->height(), interp->bsp.degX(), interp->bsp.degY());
|
||||||
rgrid->drawOrder = grid->drawOrder;
|
rgrid->setDrawOrder(grid->getDrawOrder());
|
||||||
splinegrid->setTexture(editingBone->texture->name);
|
splinegrid->setTexture(editingBone->texture->name);
|
||||||
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
splinegrid->setWidthHeight(editingBone->width, editingBone->height);
|
||||||
splinegrid->position = Vector(400, 300);
|
splinegrid->position = Vector(400, 300);
|
||||||
|
@ -1604,7 +1604,7 @@ 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->controlpoints.size() == splinegrid->getSpline().ctrlX() * splinegrid->getSpline().ctrlY());
|
||||||
assert(bk->grid.size() == editingBone->getDrawGrid().linearsize());
|
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
||||||
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
splinegrid->importControlPoints(&bk->controlpoints[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1616,7 +1616,7 @@ 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->controlpoints.size() == splinegrid->getSpline().ctrlX() * splinegrid->getSpline().ctrlY());
|
||||||
assert(bk->grid.size() == editingBone->getDrawGrid().linearsize());
|
assert(bk->grid.size() == editingBone->getGrid()->linearsize());
|
||||||
splinegrid->exportControlPoints(&bk->controlpoints[0]);
|
splinegrid->exportControlPoints(&bk->controlpoints[0]);
|
||||||
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
BoneGridInterpolator *interp = a->getBoneGridInterpolator(editingBone->boneIdx);
|
||||||
interp->updateGridAndBone(*bk, editingBone);
|
interp->updateGridAndBone(*bk, editingBone);
|
||||||
|
|
|
@ -3522,14 +3522,14 @@ bool DSQ::loadTileset(std::string pack, const unsigned char *usedIdx, size_t use
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
et->tu1 = x*cell;
|
et->tc.u1 = x*cell;
|
||||||
et->tv1 = y*cell;
|
et->tc.v1 = y*cell;
|
||||||
et->tu2 = et->tu1 + cell;
|
et->tc.u2 = et->tc.u1 + cell;
|
||||||
et->tv2 = et->tv1 + cell;
|
et->tc.v2 = et->tc.v1 + cell;
|
||||||
|
|
||||||
et->tv2 = 1 - et->tv2;
|
/*et->tc.v2 = 1 - et->tc.v2;
|
||||||
et->tv1 = 1 - et->tv1;
|
et->tc.v1 = 1 - et->tc.v1;
|
||||||
std::swap(et->tv1,et->tv2);
|
std::swap(et->tc.v1,et->tc.v2);*/
|
||||||
|
|
||||||
et->w = 512*cell;
|
et->w = 512*cell;
|
||||||
et->h = 512*cell;
|
et->h = 512*cell;
|
||||||
|
|
|
@ -243,7 +243,7 @@ void Element::setElementEffectByIndex(int eidx)
|
||||||
eff->wavyMin = bity;
|
eff->wavyMin = bity;
|
||||||
eff->wavyMax = bity*1.2f;
|
eff->wavyMax = bity*1.2f;
|
||||||
|
|
||||||
if(RenderGrid *g = createGrid(2, e.segsy))
|
if(DynamicRenderGrid *g = createGrid(2, e.segsy))
|
||||||
{
|
{
|
||||||
g->gridType = GRID_UNDEFINED; // by default it's GRID_WAVY, but that would reset during update
|
g->gridType = GRID_UNDEFINED; // by default it's GRID_WAVY, but that would reset during update
|
||||||
setGridFromWavy();
|
setGridFromWavy();
|
||||||
|
|
|
@ -124,13 +124,15 @@ void TileMgr::createTiles(const TileDef* defs, size_t n)
|
||||||
t->flags |= TILEFLAG_FH;
|
t->flags |= TILEFLAG_FH;
|
||||||
if(d.fv)
|
if(d.fv)
|
||||||
t->flags |= TILEFLAG_FV;
|
t->flags |= TILEFLAG_FV;
|
||||||
if(d.repeat)
|
|
||||||
t->setRepeatOn(d.rsx, d.rsy);
|
|
||||||
|
|
||||||
t->rotation = d.rot;
|
t->rotation = d.rot;
|
||||||
t->tag = d.tag;
|
t->tag = d.tag;
|
||||||
t->scalex = d.sx;
|
t->scalex = d.sx;
|
||||||
t->scaley = d.sy;
|
t->scaley = d.sy;
|
||||||
|
|
||||||
|
// must be done last
|
||||||
|
if(d.repeat)
|
||||||
|
t->setRepeatOn(d.rsx, d.rsy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +190,7 @@ TileData* TileMgr::_createTile(unsigned tilesetID, unsigned layer, float x, flo
|
||||||
//t.beforeScaleOffsetY = 0;
|
//t.beforeScaleOffsetY = 0;
|
||||||
t.flags = GetTileFlags(ef);
|
t.flags = GetTileFlags(ef);
|
||||||
t.tag = 0;
|
t.tag = 0;
|
||||||
|
t.rep = NULL;
|
||||||
t.et = tileset.getByIdx(tilesetID);
|
t.et = tileset.getByIdx(tilesetID);
|
||||||
assert(t.et);
|
assert(t.et);
|
||||||
/* t.eff = */ tileEffects.assignEffect(t, effidx);
|
/* t.eff = */ tileEffects.assignEffect(t, effidx);
|
||||||
|
|
|
@ -563,11 +563,11 @@ void WorldMapRender::setVis(WorldMapTile *tile)
|
||||||
|
|
||||||
if (visMethod == VIS_VERTEX)
|
if (visMethod == VIS_VERTEX)
|
||||||
{
|
{
|
||||||
RenderGrid *g = tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
|
DynamicRenderGrid *g = tile->q->setSegs(MAPVIS_SUBDIV, MAPVIS_SUBDIV, 0, 0, 0, 0, 2.0, 1);
|
||||||
if(g)
|
if(g)
|
||||||
{
|
{
|
||||||
g->gridType = GRID_UNDEFINED;
|
g->gridType = GRID_UNDEFINED;
|
||||||
g->drawOrder = GRID_DRAW_WORLDMAP;
|
g->setDrawOrder(GRID_DRAW_WORLDMAP);
|
||||||
tileDataToVis(tile, g->array2d());
|
tileDataToVis(tile, g->array2d());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ public:
|
||||||
int screenWidth, screenHeight;
|
int screenWidth, screenHeight;
|
||||||
int textureWidth, textureHeight;
|
int textureWidth, textureHeight;
|
||||||
|
|
||||||
Vector ** drawGrid; // TODO: make this + related code use RenderGrid
|
Vector ** drawGrid; // TODO: make this + related code use DynamicRenderGrid
|
||||||
|
|
||||||
// returns handle > 0 on success
|
// returns handle > 0 on success
|
||||||
int loadShaderFile(const char *vert, const char *frag);
|
int loadShaderFile(const char *vert, const char *frag);
|
||||||
|
|
|
@ -155,7 +155,9 @@ void Core::setup_opengl()
|
||||||
if(afterEffectManager)
|
if(afterEffectManager)
|
||||||
afterEffectManager->updateDevice();
|
afterEffectManager->updateDevice();
|
||||||
|
|
||||||
defaultQuadVertexBuf.initQuadVertices(0, 0, 1, 1);
|
TexCoordBox defaultTC;
|
||||||
|
defaultTC.setStandard();
|
||||||
|
defaultQuadGrid.init(2, 2, defaultTC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
|
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
|
||||||
|
@ -279,7 +281,7 @@ static bool checkWritable(const std::string& path, bool warn, bool critical)
|
||||||
|
|
||||||
|
|
||||||
Core::Core(const std::string &filesystem, const std::string& extraDataDir, int numRenderLayers, const std::string &appName, int particleSize, std::string userDataSubFolder)
|
Core::Core(const std::string &filesystem, const std::string& extraDataDir, int numRenderLayers, const std::string &appName, int particleSize, std::string userDataSubFolder)
|
||||||
: ActionMapper(), StateManager(), appName(appName), defaultQuadVertexBuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
|
: ActionMapper(), StateManager(), appName(appName)
|
||||||
{
|
{
|
||||||
window = NULL;
|
window = NULL;
|
||||||
sound = NULL;
|
sound = NULL;
|
||||||
|
@ -731,6 +733,8 @@ void Core::initGraphicsLibrary(int width, int height, bool fullscreen, bool vsyn
|
||||||
debugLog((const char*)glGetString(GL_RENDERER));
|
debugLog((const char*)glGetString(GL_RENDERER));
|
||||||
debugLog((const char*)glGetString(GL_VERSION));
|
debugLog((const char*)glGetString(GL_VERSION));
|
||||||
|
|
||||||
|
DynamicGPUBuffer::StaticInit();
|
||||||
|
|
||||||
enumerateScreenModes(window->getDisplayIndex());
|
enumerateScreenModes(window->getDisplayIndex());
|
||||||
|
|
||||||
window->updateSize();
|
window->updateSize();
|
||||||
|
@ -1920,7 +1924,7 @@ void Core::shutdown()
|
||||||
frameBuffer.unloadDevice();
|
frameBuffer.unloadDevice();
|
||||||
debugLog("OK");
|
debugLog("OK");
|
||||||
|
|
||||||
defaultQuadVertexBuf.dropBuffer();
|
defaultQuadGrid.dropBuffers();
|
||||||
|
|
||||||
debugLog("Shutdown Graphics Library...");
|
debugLog("Shutdown Graphics Library...");
|
||||||
shutdownGraphicsLibrary();
|
shutdownGraphicsLibrary();
|
||||||
|
|
|
@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "TextureMgr.h"
|
#include "TextureMgr.h"
|
||||||
#include "VertexBuffer.h"
|
#include "VertexBuffer.h"
|
||||||
#include "DarkLayer.h"
|
#include "DarkLayer.h"
|
||||||
|
#include "RenderGrid.h"
|
||||||
#include "GameKeys.h"
|
#include "GameKeys.h"
|
||||||
|
|
||||||
class ParticleEffect;
|
class ParticleEffect;
|
||||||
|
@ -413,7 +413,7 @@ public:
|
||||||
|
|
||||||
TextureMgr texmgr;
|
TextureMgr texmgr;
|
||||||
|
|
||||||
inline const DynamicGPUBuffer *getDefaultQuadVertexBuffer() const { return &defaultQuadVertexBuf; }
|
inline const RenderGrid *getDefaultQuadGrid() const { return &defaultQuadGrid; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ protected:
|
||||||
virtual void updateActionButtons();
|
virtual void updateActionButtons();
|
||||||
void clearActionButtons();
|
void clearActionButtons();
|
||||||
|
|
||||||
DynamicGPUBuffer defaultQuadVertexBuf;
|
RenderGrid defaultQuadGrid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// inclusive!
|
// inclusive!
|
||||||
|
|
|
@ -84,4 +84,35 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Accessor2d
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Accessor2d(T *p, size_t w, size_t h) : _p(p), _w(w), _h(h) {}
|
||||||
|
|
||||||
|
size_t width() const {return _w;}
|
||||||
|
size_t height() const {return _h;}
|
||||||
|
size_t linearsize() const {return _w * _h;}
|
||||||
|
|
||||||
|
inline T& operator()(size_t x, size_t y)
|
||||||
|
{
|
||||||
|
return _p[y * _w + x];
|
||||||
|
}
|
||||||
|
inline const T& operator()(size_t x, size_t y) const
|
||||||
|
{
|
||||||
|
return _p[y * _w + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T *data() const { return _p; }
|
||||||
|
T *data() { return _p; }
|
||||||
|
|
||||||
|
const T *row(size_t y) const { return &_p[y * _w]; }
|
||||||
|
T *row(size_t y) { return &_p[y * _w]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const T *_p;
|
||||||
|
const size_t _w, _h;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -75,20 +75,29 @@ void Quad::destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RenderGrid *Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
DynamicRenderGrid *Quad::setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
||||||
{
|
{
|
||||||
RenderGrid *g = createGrid(x, y);
|
DynamicRenderGrid *g = createGrid(x, y);
|
||||||
if(g)
|
if(g)
|
||||||
g->setSegs(dgox, dgoy, dgmx, dgmy, dgtm, dgo);
|
g->setSegs(dgox, dgoy, dgmx, dgmy, dgtm, dgo);
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderGrid *Quad::createGrid(int xd, int yd)
|
DynamicRenderGrid *Quad::createGrid(int xd, int yd)
|
||||||
{
|
{
|
||||||
delete grid;
|
delete grid;
|
||||||
return (grid = xd && yd
|
grid = NULL;
|
||||||
? new RenderGrid(xd, yd)
|
if(xd && yd)
|
||||||
: NULL);
|
{
|
||||||
|
TexCoordBox tc;
|
||||||
|
tc.u1 = upperLeftTextureCoordinates.x;
|
||||||
|
tc.v1 = upperLeftTextureCoordinates.y;
|
||||||
|
tc.u2 = lowerRightTextureCoordinates.x;
|
||||||
|
tc.v2 = lowerRightTextureCoordinates.y;
|
||||||
|
grid = new DynamicRenderGrid();
|
||||||
|
grid->init(xd, yd, tc);
|
||||||
|
}
|
||||||
|
return grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
|
void Quad::setDrawGridAlpha(size_t x, size_t y, float alpha)
|
||||||
|
@ -208,7 +217,7 @@ void Quad::renderGrid(const RenderState& rs) const
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glScalef(width, height, 1);
|
glScalef(width, height, 1);
|
||||||
|
|
||||||
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
|
grid->render(rx);
|
||||||
|
|
||||||
// debug points
|
// debug points
|
||||||
if (RenderObject::renderCollisionShape)
|
if (RenderObject::renderCollisionShape)
|
||||||
|
|
12
BBGE/Quad.h
12
BBGE/Quad.h
|
@ -39,7 +39,7 @@ protected:
|
||||||
void onRender(const RenderState& rs) const OVERRIDE;
|
void onRender(const RenderState& rs) const OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderGrid;
|
class DynamicRenderGrid;
|
||||||
|
|
||||||
class Quad : public RenderObject
|
class Quad : public RenderObject
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ public:
|
||||||
Quad(const std::string &tex, const Vector &pos);
|
Quad(const std::string &tex, const Vector &pos);
|
||||||
Quad();
|
Quad();
|
||||||
virtual ~Quad();
|
virtual ~Quad();
|
||||||
RenderGrid *createGrid(int x, int y);
|
DynamicRenderGrid *createGrid(int x, int y);
|
||||||
void destroy() OVERRIDE;
|
void destroy() OVERRIDE;
|
||||||
bool isCoordinateInside(Vector coord, int minSize=0) const;
|
bool isCoordinateInside(Vector coord, int minSize=0) const;
|
||||||
bool isCoordinateInsideWorld(const Vector &coord, int minSize=0) const;
|
bool isCoordinateInsideWorld(const Vector &coord, int minSize=0) const;
|
||||||
|
@ -61,14 +61,14 @@ public:
|
||||||
float getWidth() const {return width;}
|
float getWidth() const {return width;}
|
||||||
float getHeight() const {return height;}
|
float getHeight() const {return height;}
|
||||||
|
|
||||||
RenderGrid *setSegs(int x, int y, float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo);
|
DynamicRenderGrid *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 setDrawGridAlpha(size_t x, size_t y, float alpha);
|
||||||
void repeatTextureToFill(bool on);
|
void repeatTextureToFill(bool on);
|
||||||
void refreshRepeatTextureToFill();
|
void refreshRepeatTextureToFill();
|
||||||
bool isRepeatingTextureToFill() const { return repeatTexture; }
|
bool isRepeatingTextureToFill() const { return repeatTexture; }
|
||||||
void setStripPoints(bool vert, const Vector *points, size_t n);
|
void setStripPoints(bool vert, const Vector *points, size_t n);
|
||||||
RenderGrid *getGrid() { return grid; }
|
DynamicRenderGrid *getGrid() { return grid; }
|
||||||
const RenderGrid *getGrid() const { return grid; }
|
const DynamicRenderGrid *getGrid() const { return grid; }
|
||||||
|
|
||||||
void reloadDevice() OVERRIDE;
|
void reloadDevice() OVERRIDE;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
RenderGrid *grid;
|
DynamicRenderGrid *grid;
|
||||||
|
|
||||||
|
|
||||||
void resetGrid();
|
void resetGrid();
|
||||||
|
|
|
@ -41,157 +41,87 @@ void RenderGrid::ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RenderGrid::RenderGrid()
|
||||||
RenderGrid::RenderGrid(size_t w, size_t h)
|
: indexbuf(GPUBUF_STATIC | GPUBUF_INDEXBUF), vbo(GPUBUF_DYNAMIC | GPUBUF_VERTEXBUF), trisToDraw(0)
|
||||||
: gridTimer(0)
|
, needVBOUpdate(false), drawOrder(GRID_DRAW_DEFAULT)
|
||||||
, drawGridOffsetX(0), drawGridOffsetY(0), drawGridModX(0), drawGridModY(0), drawGridTimeMultiplier(0)
|
|
||||||
, drawGridOut(false), gridType(GRID_WAVY), drawOrder(GRID_DRAW_DEFAULT)
|
|
||||||
{
|
{
|
||||||
init(w, h);
|
tc.setStandard();
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderGrid::~RenderGrid()
|
RenderGrid::~RenderGrid()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::init(size_t w, size_t h)
|
void RenderGrid::dropBuffers()
|
||||||
|
{
|
||||||
|
vbo.dropBuffer();
|
||||||
|
indexbuf.dropBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderGrid::init(size_t w, size_t h, const TexCoordBox& tc)
|
||||||
{
|
{
|
||||||
assert(w > 1 && h > 1);
|
assert(w > 1 && h > 1);
|
||||||
grid.init(w, h);
|
grid.init(w, h);
|
||||||
|
setDrawOrder((GridDrawOrder)drawOrder, true);
|
||||||
|
this->tc = tc;
|
||||||
reset();
|
reset();
|
||||||
Vector *dg = grid.data();
|
Vector *dg = grid.data();
|
||||||
for(size_t i = 0; i < grid.linearsize(); ++i)
|
for(size_t i = 0; i < grid.linearsize(); ++i)
|
||||||
dg[i].z = 1.0f;
|
dg[i].z = 1.0f;
|
||||||
|
|
||||||
|
updateVBO();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderGrid::reset()
|
void RenderGrid::reset()
|
||||||
{
|
{
|
||||||
ResetGrid(grid.data(), grid.width(), grid.height());
|
ResetGrid(grid.data(), grid.width(), grid.height());
|
||||||
|
needVBOUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::resetWithAlpha(float a)
|
void RenderGrid::resetWithAlpha(float a)
|
||||||
{
|
{
|
||||||
ResetWithAlpha(grid.data(), grid.width(), grid.height(), a);
|
ResetWithAlpha(grid.data(), grid.width(), grid.height(), a);
|
||||||
}
|
needVBOUpdate = true;
|
||||||
|
|
||||||
void RenderGrid::update(float dt)
|
|
||||||
{
|
|
||||||
if (gridType == GRID_WAVY)
|
|
||||||
{
|
|
||||||
gridTimer += dt * drawGridTimeMultiplier;
|
|
||||||
reset();
|
|
||||||
const size_t w = grid.width();
|
|
||||||
const size_t h = grid.height();
|
|
||||||
|
|
||||||
size_t nx = w;
|
|
||||||
if(drawGridOut)
|
|
||||||
nx /= 2;
|
|
||||||
|
|
||||||
for (size_t y = 0; y < h; y++)
|
|
||||||
{
|
|
||||||
Vector * const row = grid.row(y);
|
|
||||||
const float xoffset = y * drawGridOffsetX;
|
|
||||||
const float addx = sinf(gridTimer+xoffset)*drawGridModX;
|
|
||||||
|
|
||||||
size_t x;
|
|
||||||
for (x = 0; x < nx; x++)
|
|
||||||
row[x].x -= addx;
|
|
||||||
for (; x < w; x++)
|
|
||||||
row[x].x += addx;
|
|
||||||
|
|
||||||
if(const float dgmy = drawGridModY)
|
|
||||||
for (x = 0; x < w; x++)
|
|
||||||
{
|
|
||||||
float yoffset = x * drawGridOffsetY;
|
|
||||||
row[x].y += cosf(gridTimer+yoffset)*dgmy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::setAlpha(size_t x, size_t y, float a)
|
void RenderGrid::setAlpha(size_t x, size_t y, float a)
|
||||||
{
|
{
|
||||||
if (x < grid.width() && y < grid.height())
|
if (x < grid.width() && y < grid.height())
|
||||||
grid(x, y).z = a;
|
grid(x, y).z = a;
|
||||||
|
needVBOUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::setSegs(float dgox, float dgoy, float dgmx, float dgmy, float dgtm, bool dgo)
|
void RenderGrid::setDrawOrder(GridDrawOrder ord, bool force)
|
||||||
{
|
{
|
||||||
drawGridOffsetX = dgox;
|
if(!force && drawOrder == ord)
|
||||||
drawGridOffsetY = dgoy;
|
return;
|
||||||
drawGridModX = dgmx;
|
drawOrder = ord;
|
||||||
drawGridModY = dgmy;
|
trisToDraw = indexbuf.initGridIndices_Triangles(grid.width(), grid.height(), ord == GRID_DRAW_LRBT, GPUACCESS_HOSTCOPY);
|
||||||
drawGridTimeMultiplier = dgtm;
|
|
||||||
drawGridOut = dgo;
|
|
||||||
gridTimer = 0;
|
|
||||||
gridType = GRID_WAVY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::setStripPoints(bool vert, const Vector* points, size_t n)
|
void RenderGrid::setTexCoords(const TexCoordBox& tc)
|
||||||
{
|
{
|
||||||
reset();
|
this->tc = tc;
|
||||||
|
needVBOUpdate = true;
|
||||||
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 float* 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 y = 0; y < H; y++)
|
|
||||||
{
|
|
||||||
const size_t wavy_y = (H - y)-1;
|
|
||||||
if (wavy_y < len)
|
|
||||||
{
|
|
||||||
const float tmp = wavy[wavy_y] * iw;
|
|
||||||
Vector * const row = grid.row(y);
|
|
||||||
for (size_t x = 0; x < NX; x++)
|
|
||||||
{
|
|
||||||
row[x].x = tmp - 0.5f;
|
|
||||||
row[x+1].x = tmp + 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RenderGrid::render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
void RenderGrid::render(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
switch(drawOrder)
|
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:
|
case GRID_DRAW_WORLDMAP:
|
||||||
render_WithAlpha(rs, upperLeftTexCoords, lowerRightTexCoords);
|
if(rs.alpha != 1 || rs.color != Vector(1,1,1))
|
||||||
break;
|
{
|
||||||
|
render_WithAlpha(rs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else fall through
|
||||||
|
|
||||||
|
default:
|
||||||
|
render_Indexed(rs);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,133 +131,74 @@ void RenderGrid::renderDebugPoints(const RenderState& rs) const
|
||||||
|
|
||||||
glPointSize(2);
|
glPointSize(2);
|
||||||
glColor3f(1,0,0);
|
glColor3f(1,0,0);
|
||||||
glBegin(GL_POINTS);
|
vbo.apply();
|
||||||
const size_t W = grid.width();
|
glDrawArrays(GL_POINTS, 0, grid.linearsize());
|
||||||
const size_t H = grid.height();
|
|
||||||
for (size_t y = 0; y < H; y++)
|
|
||||||
{
|
|
||||||
const Vector * const row = grid.row(y);
|
|
||||||
for (size_t x = 0; x < W; x++)
|
|
||||||
glVertex2f(row[x].x, row[x].y);
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::render_LRTB(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
void RenderGrid::updateVBO()
|
||||||
{
|
{
|
||||||
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
|
const float percentX = tc.u2 - tc.u1;
|
||||||
const float percentY = lowerRightTexCoords.y - upperLeftTexCoords.y;
|
const float percentY = tc.v2 - tc.v1;
|
||||||
|
|
||||||
const float baseX = upperLeftTexCoords.x;
|
const float baseX = tc.u1;
|
||||||
const float baseY = upperLeftTexCoords.y;
|
const float baseY = tc.v1;
|
||||||
|
|
||||||
const size_t NX = grid.width()-1;
|
const size_t W = grid.width();
|
||||||
const size_t NY = grid.height()-1;
|
const size_t H = grid.height();
|
||||||
|
|
||||||
// NOTE: These are used to avoid repeated expensive divide operations,
|
// NOTE: These are used to avoid repeated expensive divide operations,
|
||||||
// but they may cause rounding error of around 1 part per million,
|
// but they may cause rounding error of around 1 part per million,
|
||||||
// which could in theory cause minor graphical glitches with broken
|
// which could in theory cause minor graphical glitches with broken
|
||||||
// OpenGL implementations. --achurch
|
// OpenGL implementations. --achurch
|
||||||
const float incX = percentX / float(NX);
|
const float incX = percentX / float(W-1);
|
||||||
const float incY = percentY / float(NY);
|
const float incY = percentY / float(H-1);
|
||||||
|
|
||||||
glColor4f(rs.color.x, rs.color.y, rs.color.z, rs.alpha);
|
do
|
||||||
|
|
||||||
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 *p = (float*)vbo.beginWrite(GPUBUFTYPE_VEC2_TC, W*H * (2*2) * sizeof(float), GPUACCESS_DEFAULT);
|
||||||
float u1 = u0 + incX;
|
|
||||||
const Vector *row0 = grid.row(y);
|
float v = baseY;
|
||||||
const Vector *row1 = grid.row(y+1);
|
for (size_t y = 0; y < H; y++, v += incY)
|
||||||
for (size_t x = 0; x < NX; x++, u0 = u1, u1 += incX)
|
//for (size_t y = H; y --> 0; v += incY)
|
||||||
{
|
{
|
||||||
const Vector dg00 = row0[x];
|
float u = baseX;
|
||||||
const Vector dg01 = row1[x];
|
const Vector *row = grid.row(y);
|
||||||
const Vector dg10 = row0[x+1];
|
for (size_t x = 0; x < W; x++, u += incX)
|
||||||
const Vector dg11 = row1[x+1];
|
{
|
||||||
|
*p++ = row->x;
|
||||||
glTexCoord2f(u0, v0);
|
*p++ = row->y;
|
||||||
glVertex2f(dg00.x, dg00.y);
|
++row;
|
||||||
|
*p++ = u;
|
||||||
glTexCoord2f(u0, v1);
|
*p++ = v;
|
||||||
glVertex2f(dg01.x, dg01.y);
|
}
|
||||||
|
|
||||||
glTexCoord2f(u1, v1);
|
|
||||||
glVertex2f(dg11.x, dg11.y);
|
|
||||||
|
|
||||||
glTexCoord2f(u1, v0);
|
|
||||||
glVertex2f(dg10.x, dg10.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glEnd();
|
while(!vbo.commitWrite());
|
||||||
|
|
||||||
|
needVBOUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderGrid::render_LRBT(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const
|
void RenderGrid::render_Indexed(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
const float percentX = lowerRightTexCoords.x - upperLeftTexCoords.x;
|
(void)rs;
|
||||||
const float percentY = upperLeftTexCoords.y - lowerRightTexCoords.y;
|
// can't render this here when color/alpha is modulated AND we have colors as part of the vertex data;
|
||||||
|
// old opengl simply doesn't support this
|
||||||
const float baseX = upperLeftTexCoords.x;
|
assert(drawOrder != GRID_DRAW_WORLDMAP || (rs.color == Vector(1,1,1) && rs.alpha == 1));
|
||||||
const float baseY = lowerRightTexCoords.y;
|
vbo.apply();
|
||||||
|
indexbuf.drawElements(GL_TRIANGLES, trisToDraw);
|
||||||
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
|
void RenderGrid::render_WithAlpha(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
const float percentX = fabsf(lowerRightTexCoords.x - upperLeftTexCoords.x);
|
const float percentX = fabsf(tc.u2 - tc.u1);
|
||||||
const float percentY = fabsf(upperLeftTexCoords.y - lowerRightTexCoords.y);
|
const float percentY = fabsf(tc.v1 - tc.v2);
|
||||||
|
|
||||||
const float baseX =
|
const float baseX =
|
||||||
(lowerRightTexCoords.x < upperLeftTexCoords.x)
|
(tc.u2 < tc.u1)
|
||||||
? lowerRightTexCoords.x : upperLeftTexCoords.x;
|
? tc.u2 : tc.u1;
|
||||||
const float baseY =
|
const float baseY =
|
||||||
(lowerRightTexCoords.y < upperLeftTexCoords.y)
|
(tc.v2 < tc.v1)
|
||||||
? lowerRightTexCoords.y : upperLeftTexCoords.y;
|
? tc.v2 : tc.v1;
|
||||||
|
|
||||||
const size_t NX = grid.width()-1;
|
const size_t NX = grid.width()-1;
|
||||||
const size_t NY = grid.height()-1;
|
const size_t NY = grid.height()-1;
|
||||||
|
@ -381,3 +252,120 @@ void RenderGrid::render_WithAlpha(const RenderState& rs, const Vector& upperLeft
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
DynamicRenderGrid::DynamicRenderGrid()
|
||||||
|
: RenderGrid()
|
||||||
|
, gridTimer(0)
|
||||||
|
, drawGridOffsetX(0), drawGridOffsetY(0), drawGridModX(0), drawGridModY(0), drawGridTimeMultiplier(0)
|
||||||
|
, drawGridOut(false), gridType(GRID_WAVY)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicRenderGrid::~DynamicRenderGrid()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicRenderGrid::update(float dt)
|
||||||
|
{
|
||||||
|
if (gridType == GRID_WAVY)
|
||||||
|
{
|
||||||
|
gridTimer += dt * drawGridTimeMultiplier;
|
||||||
|
reset();
|
||||||
|
const size_t w = grid.width();
|
||||||
|
const size_t h = grid.height();
|
||||||
|
|
||||||
|
size_t nx = w;
|
||||||
|
if(drawGridOut)
|
||||||
|
nx /= 2;
|
||||||
|
|
||||||
|
for (size_t y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
Vector * const row = grid.row(y);
|
||||||
|
const float xoffset = y * drawGridOffsetX;
|
||||||
|
const float addx = sinf(gridTimer+xoffset)*drawGridModX;
|
||||||
|
|
||||||
|
size_t x;
|
||||||
|
for (x = 0; x < nx; x++)
|
||||||
|
row[x].x -= addx;
|
||||||
|
for (; x < w; x++)
|
||||||
|
row[x].x += addx;
|
||||||
|
|
||||||
|
if(const float dgmy = drawGridModY)
|
||||||
|
for (x = 0; x < w; x++)
|
||||||
|
{
|
||||||
|
float yoffset = x * drawGridOffsetY;
|
||||||
|
row[x].y += cosf(gridTimer+yoffset)*dgmy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// always update vbo now
|
||||||
|
}
|
||||||
|
else if(!needVBOUpdate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateVBO();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicRenderGrid::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 DynamicRenderGrid::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
needVBOUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicRenderGrid::setFromWavy(const float* 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 y = 0; y < H; y++)
|
||||||
|
{
|
||||||
|
const size_t wavy_y = (H - y)-1;
|
||||||
|
if (wavy_y < len)
|
||||||
|
{
|
||||||
|
const float tmp = wavy[wavy_y] * iw;
|
||||||
|
Vector * const row = grid.row(y);
|
||||||
|
for (size_t x = 0; x < NX; x++)
|
||||||
|
{
|
||||||
|
row[x].x = tmp - 0.5f;
|
||||||
|
row[x+1].x = tmp + 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needVBOUpdate = true;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "DataStructures.h"
|
#include "DataStructures.h"
|
||||||
|
#include "VertexBuffer.h"
|
||||||
|
#include "Texture.h" // TexCoordBox
|
||||||
|
|
||||||
struct RenderState;
|
struct RenderState;
|
||||||
|
|
||||||
|
@ -23,23 +25,26 @@ enum GridType
|
||||||
GRID_INTERP = 3, // quad is in grid mode
|
GRID_INTERP = 3, // quad is in grid mode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// simple render grid, must be manually uploaded to GPU if changed
|
||||||
class RenderGrid
|
class RenderGrid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderGrid(size_t w, size_t h);
|
RenderGrid();
|
||||||
~RenderGrid();
|
~RenderGrid();
|
||||||
|
void dropBuffers();
|
||||||
|
|
||||||
void init(size_t w, size_t h);
|
void init(size_t w, size_t h, const TexCoordBox& tc);
|
||||||
void reset();
|
void reset();
|
||||||
void resetWithAlpha(float a);
|
void resetWithAlpha(float a);
|
||||||
void update(float dt);
|
void render(const RenderState& rs) const;
|
||||||
void render(const RenderState& rs, const Vector& upperLeftTexCoords, const Vector& lowerRightTexCoords) const;
|
|
||||||
void renderDebugPoints(const RenderState& rs) const;
|
void renderDebugPoints(const RenderState& rs) const;
|
||||||
void setAlpha(size_t x, size_t y, float a);
|
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 setDrawOrder(GridDrawOrder ord, bool force = false);
|
||||||
void setStripPoints(bool vert, const Vector *points, size_t n);
|
inline GridDrawOrder getDrawOrder() const { return GridDrawOrder(drawOrder); }
|
||||||
void setFromWavy(const float *wavy, size_t len, float width);
|
void setTexCoords(const TexCoordBox& tc);
|
||||||
|
const TexCoordBox& getTexCoords() const { return tc; }
|
||||||
|
|
||||||
|
bool empty() const { return !(width() | height()); }
|
||||||
size_t width() const { return grid.width(); }
|
size_t width() const { return grid.width(); }
|
||||||
size_t height() const { return grid.height(); }
|
size_t height() const { return grid.height(); }
|
||||||
size_t linearsize() const { return grid.linearsize(); }
|
size_t linearsize() const { return grid.linearsize(); }
|
||||||
|
@ -47,11 +52,39 @@ public:
|
||||||
Vector *data() { return grid.data(); }
|
Vector *data() { return grid.data(); }
|
||||||
Array2d<Vector>& array2d() { return grid; }
|
Array2d<Vector>& array2d() { return grid; }
|
||||||
const Array2d<Vector>& array2d() const { return grid; }
|
const Array2d<Vector>& array2d() const { return grid; }
|
||||||
|
const DynamicGPUBuffer& getVBO() const { return vbo; }
|
||||||
|
void updateVBO();
|
||||||
|
|
||||||
static void ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha);
|
static void ResetWithAlpha(Vector* dst, size_t w, size_t h, float alpha);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
DynamicGPUBuffer indexbuf, vbo;
|
||||||
|
size_t trisToDraw;
|
||||||
Array2d<Vector> grid;
|
Array2d<Vector> grid;
|
||||||
|
TexCoordBox tc;
|
||||||
|
bool needVBOUpdate;
|
||||||
|
|
||||||
|
void render_Indexed(const RenderState& rs) const;
|
||||||
|
void render_WithAlpha(const RenderState& rs) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GridDrawOrder drawOrder;
|
||||||
|
};
|
||||||
|
|
||||||
|
// supports animation and automatic upload
|
||||||
|
class DynamicRenderGrid : public RenderGrid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DynamicRenderGrid();
|
||||||
|
~DynamicRenderGrid();
|
||||||
|
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
|
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 float *wavy, size_t len, float width);
|
||||||
|
|
||||||
|
protected:
|
||||||
float gridTimer;
|
float gridTimer;
|
||||||
float drawGridOffsetX;
|
float drawGridOffsetX;
|
||||||
float drawGridOffsetY;
|
float drawGridOffsetY;
|
||||||
|
@ -61,11 +94,6 @@ protected:
|
||||||
bool drawGridOut;
|
bool drawGridOut;
|
||||||
public:
|
public:
|
||||||
unsigned char gridType; // unsigned char to save space
|
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
|
#endif
|
||||||
|
|
|
@ -130,7 +130,7 @@ void Bone::addSegment(Bone *b)
|
||||||
|
|
||||||
void Bone::createStrip(bool vert, int num)
|
void Bone::createStrip(bool vert, int num)
|
||||||
{
|
{
|
||||||
RenderGrid *grid = vert ? createGrid(2, num) : createGrid(num, 2);
|
DynamicRenderGrid *grid = vert ? createGrid(2, num) : createGrid(num, 2);
|
||||||
stripVert = vert;
|
stripVert = vert;
|
||||||
grid->gridType = GRID_STRIP;
|
grid->gridType = GRID_STRIP;
|
||||||
changeStrip.resize(num);
|
changeStrip.resize(num);
|
||||||
|
@ -974,7 +974,7 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
||||||
XMLElement *bones = xml->NewElement("Bones");
|
XMLElement *bones = xml->NewElement("Bones");
|
||||||
for (i = 0; i < this->bones.size(); i++)
|
for (i = 0; i < this->bones.size(); i++)
|
||||||
{
|
{
|
||||||
const RenderGrid * const grid = this->bones[i]->getGrid();
|
const DynamicRenderGrid * const grid = this->bones[i]->getGrid();
|
||||||
XMLElement *bone = xml->NewElement("Bone");
|
XMLElement *bone = xml->NewElement("Bone");
|
||||||
bone->SetAttribute("idx", (unsigned int) this->bones[i]->boneIdx);
|
bone->SetAttribute("idx", (unsigned int) this->bones[i]->boneIdx);
|
||||||
bone->SetAttribute("gfx", this->bones[i]->gfx.c_str());
|
bone->SetAttribute("gfx", this->bones[i]->gfx.c_str());
|
||||||
|
@ -1033,9 +1033,9 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
||||||
bone->SetAttribute("sz", os.str().c_str());
|
bone->SetAttribute("sz", os.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(grid && grid->drawOrder != GRID_DRAW_DEFAULT)
|
if(grid && grid->getDrawOrder() != GRID_DRAW_DEFAULT)
|
||||||
{
|
{
|
||||||
bone->SetAttribute("gridDrawOrder", (int)grid->drawOrder);
|
bone->SetAttribute("gridDrawOrder", (int)grid->getDrawOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1073,7 +1073,8 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
||||||
const BoneGridInterpolator& bgip = a->interpolators[j];
|
const BoneGridInterpolator& bgip = a->interpolators[j];
|
||||||
XMLElement *interp = xml->NewElement("Interpolator");
|
XMLElement *interp = xml->NewElement("Interpolator");
|
||||||
Bone *bone = this->getBoneByIdx(bgip.idx);
|
Bone *bone = this->getBoneByIdx(bgip.idx);
|
||||||
assert(bone->gridType == Quad::GRID_INTERP);
|
DynamicRenderGrid *grid = bone->getGrid();
|
||||||
|
assert(grid && grid->gridType == GRID_INTERP);
|
||||||
if(bgip.storeBoneByIdx)
|
if(bgip.storeBoneByIdx)
|
||||||
interp->SetAttribute("bone", (int)bone->boneIdx);
|
interp->SetAttribute("bone", (int)bone->boneIdx);
|
||||||
else
|
else
|
||||||
|
@ -1128,7 +1129,7 @@ bool SkeletalSprite::saveSkeletal(const std::string &fn)
|
||||||
Bone *bone = this->getBoneByIdx(b->idx);
|
Bone *bone = this->getBoneByIdx(b->idx);
|
||||||
if(bone)
|
if(bone)
|
||||||
{
|
{
|
||||||
const RenderGrid * const bgrid = bone->getGrid();
|
const DynamicRenderGrid * const bgrid = bone->getGrid();
|
||||||
os << b->idx << " " << b->x << " " << b->y << " " << b->rot << " ";
|
os << b->idx << " " << b->x << " " << b->y << " " << b->rot << " ";
|
||||||
// don't want to store grid points if they can be regenerated automatically
|
// don't want to store grid points if they can be regenerated automatically
|
||||||
size_t usedGridSize = (!bgrid || bgrid->gridType == GRID_INTERP) ? 0 : b->grid.size();
|
size_t usedGridSize = (!bgrid || bgrid->gridType == GRID_INTERP) ? 0 : b->grid.size();
|
||||||
|
@ -1601,7 +1602,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
}
|
}
|
||||||
if (bone->Attribute("grid"))
|
if (bone->Attribute("grid"))
|
||||||
{
|
{
|
||||||
RenderGrid *grid = newb->getGrid();
|
DynamicRenderGrid *grid = newb->getGrid();
|
||||||
if(!grid)
|
if(!grid)
|
||||||
{
|
{
|
||||||
SimpleIStringStream is(bone->Attribute("grid"), SimpleIStringStream::REUSE);
|
SimpleIStringStream is(bone->Attribute("grid"), SimpleIStringStream::REUSE);
|
||||||
|
@ -1618,7 +1619,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
if(const char *gdo = bone->Attribute("gridDrawOrder"))
|
if(const char *gdo = bone->Attribute("gridDrawOrder"))
|
||||||
{
|
{
|
||||||
int ord = atoi(gdo);
|
int ord = atoi(gdo);
|
||||||
grid->drawOrder = (GridDrawOrder)ord;
|
grid->setDrawOrder((GridDrawOrder)ord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bone = bone->NextSiblingElement("Bone");
|
bone = bone->NextSiblingElement("Bone");
|
||||||
|
@ -1842,7 +1843,7 @@ void SkeletalSprite::loadSkeletal(const std::string &fn)
|
||||||
debugLog(os.str());
|
debugLog(os.str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RenderGrid *grid = bi->getGrid();
|
DynamicRenderGrid *grid = bi->getGrid();
|
||||||
if(!grid)
|
if(!grid)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
@ -2060,7 +2061,7 @@ void AnimationLayer::updateBones()
|
||||||
b->scale.x = lerp(bkey1->sx, bkey2->sx, dt, lerpType);
|
b->scale.x = lerp(bkey1->sx, bkey2->sx, dt, lerpType);
|
||||||
b->scale.y = lerp(bkey1->sy, bkey2->sy, dt, lerpType);
|
b->scale.y = lerp(bkey1->sy, bkey2->sy, dt, lerpType);
|
||||||
}
|
}
|
||||||
RenderGrid *grid = b->getGrid();
|
DynamicRenderGrid *grid = b->getGrid();
|
||||||
if (grid && b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && grid->gridType == GRID_STRIP)
|
if (grid && b->animated==Bone::ANIM_ALL && !b->changeStrip.empty() && grid->gridType == GRID_STRIP)
|
||||||
{
|
{
|
||||||
if (bkey2->grid.size() < b->changeStrip.size())
|
if (bkey2->grid.size() < b->changeStrip.size())
|
||||||
|
@ -2079,12 +2080,12 @@ void AnimationLayer::updateBones()
|
||||||
if(bkey1->grid.size() < N)
|
if(bkey1->grid.size() < N)
|
||||||
{
|
{
|
||||||
bkey1->grid.resize(N);
|
bkey1->grid.resize(N);
|
||||||
RenderGrid::ResetWithAlpha(&bkey1->grid[0], grid->width(), grid->height(), 1.0f);
|
DynamicRenderGrid::ResetWithAlpha(&bkey1->grid[0], grid->width(), grid->height(), 1.0f);
|
||||||
}
|
}
|
||||||
if(bkey2->grid.size() < N)
|
if(bkey2->grid.size() < N)
|
||||||
{
|
{
|
||||||
bkey2->grid.resize(N);
|
bkey2->grid.resize(N);
|
||||||
RenderGrid::ResetWithAlpha(&bkey2->grid[0], grid->width(), grid->height(), 1.0f);
|
DynamicRenderGrid::ResetWithAlpha(&bkey2->grid[0], grid->width(), grid->height(), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector *dst = grid->data();
|
Vector *dst = grid->data();
|
||||||
|
@ -2217,7 +2218,7 @@ void SkeletalSprite::selectNextBone()
|
||||||
|
|
||||||
void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
|
void BoneGridInterpolator::updateGridOnly(BoneKeyframe& bk, const Bone *bone)
|
||||||
{
|
{
|
||||||
const RenderGrid *grid = bone->getGrid();
|
const DynamicRenderGrid *grid = bone->getGrid();
|
||||||
assert(bone->boneIdx == bk.idx);
|
assert(bone->boneIdx == bk.idx);
|
||||||
assert(bk.grid.size() == grid->linearsize());
|
assert(bk.grid.size() == grid->linearsize());
|
||||||
bsp.recalc(&bk.grid[0], grid->width(), grid->height(), &bk.controlpoints[0]);
|
bsp.recalc(&bk.grid[0], grid->width(), grid->height(), &bk.controlpoints[0]);
|
||||||
|
|
|
@ -81,12 +81,12 @@ SplineGrid::~SplineGrid()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderGrid *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)
|
||||||
{
|
{
|
||||||
size_t oldcpx = bsp.ctrlX();
|
size_t oldcpx = bsp.ctrlX();
|
||||||
size_t oldcpy = bsp.ctrlY();
|
size_t oldcpy = bsp.ctrlY();
|
||||||
|
|
||||||
RenderGrid *ret = this->createGrid(xres, yres);
|
DynamicRenderGrid *ret = this->createGrid(xres, yres);
|
||||||
|
|
||||||
std::vector<SplineGridCtrlPoint*> oldp;
|
std::vector<SplineGridCtrlPoint*> oldp;
|
||||||
ctrlp.swap(oldp);
|
ctrlp.swap(oldp);
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
~SplineGrid();
|
~SplineGrid();
|
||||||
|
|
||||||
// # of control points on each axis
|
// # of control points on each axis
|
||||||
RenderGrid *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 exportControlPoints(Vector *controlpoints);
|
||||||
void importControlPoints(const Vector *controlpoints);
|
void importControlPoints(const Vector *controlpoints);
|
||||||
|
|
|
@ -30,6 +30,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "GLLoad.h"
|
#include "GLLoad.h"
|
||||||
#include "stb_image_resize.h"
|
#include "stb_image_resize.h"
|
||||||
|
|
||||||
|
bool TexCoordBox::isStandard() const
|
||||||
|
{
|
||||||
|
return u1 == 0 && v1 == 0 && u2 == 1 && v2 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TexCoordBox::setStandard()
|
||||||
|
{
|
||||||
|
u1 = 0;
|
||||||
|
v1 = 0;
|
||||||
|
u2 = 1;
|
||||||
|
v2 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Texture::Texture()
|
Texture::Texture()
|
||||||
{
|
{
|
||||||
|
@ -88,13 +101,13 @@ static const GLenum repeatLUT[] = { GL_CLAMP_TO_EDGE, GL_REPEAT };
|
||||||
void Texture::apply(bool repeat) const
|
void Texture::apply(bool repeat) const
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, gltexid);
|
glBindTexture(GL_TEXTURE_2D, gltexid);
|
||||||
if(repeat != _repeating)
|
/*if(repeat != _repeating)
|
||||||
{
|
{
|
||||||
_repeating = repeat;
|
_repeating = repeat;
|
||||||
GLenum rep = repeatLUT[repeat];
|
GLenum rep = repeatLUT[repeat];
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, rep);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, rep);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, rep);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, rep);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GlTexFormat
|
struct GlTexFormat
|
||||||
|
@ -127,8 +140,8 @@ bool Texture::upload(const ImageData& img, bool mipmap)
|
||||||
if(!gltexid)
|
if(!gltexid)
|
||||||
glGenTextures(1, &gltexid);
|
glGenTextures(1, &gltexid);
|
||||||
glBindTexture(GL_TEXTURE_2D, gltexid);
|
glBindTexture(GL_TEXTURE_2D, gltexid);
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
_repeating = false;
|
_repeating = false;
|
||||||
|
|
||||||
const GlTexFormat& f = formatLUT[img.channels - 1];
|
const GlTexFormat& f = formatLUT[img.channels - 1];
|
||||||
|
|
|
@ -24,6 +24,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "Refcounted.h"
|
#include "Refcounted.h"
|
||||||
|
|
||||||
|
struct TexCoordBox
|
||||||
|
{
|
||||||
|
float u1, v1; // upper left (x,y)
|
||||||
|
float u2, v2; // lower right (x,y)
|
||||||
|
|
||||||
|
bool isStandard() const;
|
||||||
|
void setStandard();
|
||||||
|
};
|
||||||
|
|
||||||
enum TextureLoadResult
|
enum TextureLoadResult
|
||||||
{
|
{
|
||||||
|
|
204
BBGE/Tile.cpp
204
BBGE/Tile.cpp
|
@ -146,12 +146,11 @@ static void dropEffect(TileData& t)
|
||||||
|
|
||||||
static void dropRepeat(TileData& t)
|
static void dropRepeat(TileData& t)
|
||||||
{
|
{
|
||||||
if(t.flags & TILEFLAG_OWN_REPEAT)
|
if(t.rep)
|
||||||
{
|
{
|
||||||
delete t.rep;
|
delete t.rep;
|
||||||
t.flags &= ~TILEFLAG_OWN_REPEAT;
|
t.rep = NULL;
|
||||||
}
|
}
|
||||||
t.rep = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dropAll(TileData& t)
|
static void dropAll(TileData& t)
|
||||||
|
@ -232,6 +231,10 @@ size_t TileStorage::cloneSome(const TileEffectStorage& effstore, const size_t* i
|
||||||
for(size_t i = ret; i < N; ++i) // loop only over newly added tiles
|
for(size_t i = ret; i < N; ++i) // loop only over newly added tiles
|
||||||
{
|
{
|
||||||
TileData& t = tiles[i];
|
TileData& t = tiles[i];
|
||||||
|
if(t.rep)
|
||||||
|
{
|
||||||
|
t.rep = new TileRepeatData(*t.rep); // must be done BEFORE assigning eff
|
||||||
|
}
|
||||||
if((t.flags & TILEFLAG_OWN_EFFDATA) && t.eff)
|
if((t.flags & TILEFLAG_OWN_EFFDATA) && t.eff)
|
||||||
{
|
{
|
||||||
int efx = t.eff->efxidx;
|
int efx = t.eff->efxidx;
|
||||||
|
@ -239,10 +242,6 @@ size_t TileStorage::cloneSome(const TileEffectStorage& effstore, const size_t* i
|
||||||
t.flags &= TILEFLAG_OWN_EFFDATA;
|
t.flags &= TILEFLAG_OWN_EFFDATA;
|
||||||
effstore.assignEffect(t, efx); // recreate effect properly
|
effstore.assignEffect(t, efx); // recreate effect properly
|
||||||
}
|
}
|
||||||
if((t.flags & TILEFLAG_OWN_REPEAT) && t.rep)
|
|
||||||
{
|
|
||||||
t.rep = new TileRepeatData(*t.rep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshAll();
|
refreshAll();
|
||||||
|
@ -282,9 +281,11 @@ void TileStorage::clearSelection()
|
||||||
tiles[i].flags &= ~TILEFLAG_SELECTED;
|
tiles[i].flags &= ~TILEFLAG_SELECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
TileEffectData::TileEffectData(const TileEffectConfig& cfg)
|
TileEffectData::TileEffectData(const TileEffectConfig& cfg, const TileData *t)
|
||||||
: efxtype(cfg.type), efxidx(cfg.index)
|
: efxtype(cfg.type), efxidx(cfg.index)
|
||||||
, grid(NULL), alpha(1), blend(BLEND_DEFAULT)
|
, grid(NULL), alpha(1), blend(BLEND_DEFAULT)
|
||||||
|
, ownGrid(false), shared(false)
|
||||||
|
|
||||||
{
|
{
|
||||||
switch(cfg.type)
|
switch(cfg.type)
|
||||||
{
|
{
|
||||||
|
@ -294,14 +295,14 @@ TileEffectData::TileEffectData(const TileEffectConfig& cfg)
|
||||||
|
|
||||||
case EFX_WAVY:
|
case EFX_WAVY:
|
||||||
{
|
{
|
||||||
float bity = 20; // FIXME
|
assert(t);
|
||||||
|
float bity = t->et->h/float(cfg.u.wavy.segsy);
|
||||||
wavy.wavy.resize(cfg.u.wavy.segsy, 0.0f);
|
wavy.wavy.resize(cfg.u.wavy.segsy, 0.0f);
|
||||||
wavy.flip = cfg.u.wavy.flip;
|
wavy.flip = cfg.u.wavy.flip;
|
||||||
wavy.min = bity;
|
wavy.min = bity;
|
||||||
wavy.max = bity*1.2f;
|
wavy.max = bity*1.2f;
|
||||||
|
|
||||||
RenderGrid *g = new RenderGrid(2, cfg.u.wavy.segsy);
|
DynamicRenderGrid *g = _ensureGrid(2, cfg.u.wavy.segsy, t);
|
||||||
grid = g;
|
|
||||||
g->gridType = GRID_UNDEFINED; // we do the grid update manually
|
g->gridType = GRID_UNDEFINED; // we do the grid update manually
|
||||||
|
|
||||||
wavy.angleOffset = 0;
|
wavy.angleOffset = 0;
|
||||||
|
@ -317,8 +318,7 @@ TileEffectData::TileEffectData(const TileEffectConfig& cfg)
|
||||||
|
|
||||||
case EFX_SEGS:
|
case EFX_SEGS:
|
||||||
{
|
{
|
||||||
RenderGrid *g = new RenderGrid(cfg.u.segs.x, cfg.u.segs.y);
|
DynamicRenderGrid *g = _ensureGrid(cfg.u.segs.x, cfg.u.segs.y, t);
|
||||||
grid = g;
|
|
||||||
g->setSegs(cfg.u.segs.dgox, cfg.u.segs.dgoy, cfg.u.segs.dgmx, cfg.u.segs.dgmy, cfg.u.segs.dgtm, cfg.u.segs.dgo);
|
g->setSegs(cfg.u.segs.dgox, cfg.u.segs.dgoy, cfg.u.segs.dgmx, cfg.u.segs.dgmy, cfg.u.segs.dgtm, cfg.u.segs.dgo);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -335,7 +335,43 @@ TileEffectData::TileEffectData(const TileEffectConfig& cfg)
|
||||||
|
|
||||||
TileEffectData::~TileEffectData()
|
TileEffectData::~TileEffectData()
|
||||||
{
|
{
|
||||||
delete grid;
|
if(ownGrid)
|
||||||
|
delete grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicRenderGrid *TileEffectData::_ensureGrid(size_t w, size_t h, const TileData *t)
|
||||||
|
{
|
||||||
|
DynamicRenderGrid *g = grid;
|
||||||
|
if(ownGrid)
|
||||||
|
{
|
||||||
|
assert(g);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(t && t->rep)
|
||||||
|
{
|
||||||
|
assert(!shared); // a shared instance MUST have its own grid and MUST NOT refer to the grid of any tile
|
||||||
|
if(ownGrid)
|
||||||
|
delete g;
|
||||||
|
g = &t->rep->grid;
|
||||||
|
ownGrid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!g)
|
||||||
|
{
|
||||||
|
g = new DynamicRenderGrid;
|
||||||
|
ownGrid = true;
|
||||||
|
}
|
||||||
|
grid = g;
|
||||||
|
TexCoordBox tc;
|
||||||
|
if(t)
|
||||||
|
tc = t->getTexcoords();
|
||||||
|
else
|
||||||
|
tc.setStandard();
|
||||||
|
g->init(w, h, tc);
|
||||||
|
if(t && t->rep)
|
||||||
|
t->rep->refresh(*t);
|
||||||
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileEffectData::Wavy::update(float dt)
|
void TileEffectData::Wavy::update(float dt)
|
||||||
|
@ -463,19 +499,28 @@ void TileEffectStorage::assignEffect(TileData& t, int index) const
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t idx = size_t(index);
|
size_t idx = size_t(index);
|
||||||
|
if(idx >= configs.size())
|
||||||
|
return;
|
||||||
|
|
||||||
if(idx < prepared.size() && prepared[idx])
|
|
||||||
|
bool needinstance = false;
|
||||||
|
if(idx < configs.size())
|
||||||
{
|
{
|
||||||
t.eff = prepared[idx];
|
needinstance = configs[idx].needsOwnInstanceForTile(t);
|
||||||
}
|
}
|
||||||
else if(idx < configs.size())
|
|
||||||
|
if(needinstance)
|
||||||
{
|
{
|
||||||
if(configs[idx].type == EFX_NONE)
|
if(configs[idx].type == EFX_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
t.eff = new TileEffectData(configs[idx]);
|
t.eff = new TileEffectData(configs[idx], &t);
|
||||||
t.flags |= TILEFLAG_OWN_EFFDATA;
|
t.flags |= TILEFLAG_OWN_EFFDATA;
|
||||||
}
|
}
|
||||||
|
else if(idx < prepared.size() && prepared[idx])
|
||||||
|
{
|
||||||
|
t.eff = prepared[idx];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileEffectStorage::update(float dt)
|
void TileEffectStorage::update(float dt)
|
||||||
|
@ -513,7 +558,10 @@ void TileEffectStorage::finalize()
|
||||||
// segs and alpha are independent of the tile they are applied to,
|
// segs and alpha are independent of the tile they are applied to,
|
||||||
// so we can create shared instances of the effect.
|
// so we can create shared instances of the effect.
|
||||||
if(c.type == EFX_SEGS || c.type == EFX_ALPHA)
|
if(c.type == EFX_SEGS || c.type == EFX_ALPHA)
|
||||||
prepared[i] = new TileEffectData(c);
|
{
|
||||||
|
prepared[i] = new TileEffectData(c, NULL);
|
||||||
|
prepared[i]->shared = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,12 +580,21 @@ bool TileData::isCoordinateInside(float cx, float cy, float minsize) const
|
||||||
}
|
}
|
||||||
|
|
||||||
TileRepeatData::TileRepeatData()
|
TileRepeatData::TileRepeatData()
|
||||||
: vertexbuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
|
: texscaleX(1), texscaleY(1)
|
||||||
|
, texOffX(0), texOffY(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scaley)
|
TileRepeatData::TileRepeatData(const TileRepeatData& o)
|
||||||
|
: texscaleX(o.texscaleX), texscaleY(o.texscaleY)
|
||||||
|
, texOffX(o.texOffX), texOffY(o.texOffY)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TexCoordBox TileRepeatData::calcTexCoords(const TileData& t) const
|
||||||
|
{
|
||||||
|
const ElementTemplate& et = *t.et;
|
||||||
|
|
||||||
float tw, th;
|
float tw, th;
|
||||||
if(et.tex)
|
if(et.tex)
|
||||||
{
|
{
|
||||||
|
@ -550,43 +607,118 @@ void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scal
|
||||||
th = et.h;
|
th = et.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float tu1 = texOffX;
|
TexCoordBox tc;
|
||||||
const float tv1 = texOffY;
|
tc.u1 = texOffX;
|
||||||
const float tu2 = (et.w*scalex*texscaleX)/tw + texOffX;
|
tc.v1 = texOffY;
|
||||||
const float tv2 = (et.h*scaley*texscaleY)/th + texOffY;
|
tc.u2 = (et.w*t.scalex*texscaleX)/tw + texOffX;
|
||||||
|
tc.v2 = (et.h*t.scaley*texscaleY)/th + texOffY;
|
||||||
|
|
||||||
this->tu1 = tu1;
|
// HACK: partially repeated textures have a weird Y axis. assuming a repeat factor of 0.5,
|
||||||
this->tv1 = tv1;
|
// instead of texcoords from 0 -> 0.4 everything is biased towards the opposite end, ie. 0.6 -> 1.
|
||||||
this->tu2 = tu2;
|
// This is especially true for partial repeats, we always need to bias towards the other end.
|
||||||
this->tv2 = tv2;
|
// I have no idea why this has to be like this for tiles, but this is NOT the case for fonts.
|
||||||
|
// And NOTE: without this, maps may look deceivingly correct, but they really are not.
|
||||||
|
const float percentY = tc.v2 - tc.v1;
|
||||||
|
const float remainder = 1.0f - fmodf(percentY, 1.0f);
|
||||||
|
tc.v1 += remainder; // bias towards next int
|
||||||
|
tc.v2 += remainder;
|
||||||
|
|
||||||
vertexbuf.initQuadVertices(tu1, tv1, tu2, tv2);
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileRepeatData::refresh(const TileData& t)
|
||||||
|
{
|
||||||
|
TexCoordBox tc = calcTexCoords(t);
|
||||||
|
|
||||||
|
/*if(t.eff)
|
||||||
|
if(const DynamicRenderGrid *g = t.eff->grid)
|
||||||
|
{
|
||||||
|
grid.init(g->width(), g->height(), grid.getTexCoords());
|
||||||
|
grid.gridType = g->gridType;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if(grid.empty())
|
||||||
|
grid.init(2, 2, tc);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grid.setTexCoords(tc);
|
||||||
|
grid.reset();
|
||||||
|
grid.updateVBO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TileRepeatData* TileData::setRepeatOn(float texscalex, float texscaley, float offx, float offy)
|
TileRepeatData* TileData::setRepeatOn(float texscalex, float texscaley, float offx, float offy)
|
||||||
{
|
{
|
||||||
if(rep && !(flags & TILEFLAG_OWN_REPEAT))
|
flags |= TILEFLAG_REPEAT;
|
||||||
rep = NULL;
|
|
||||||
flags |= (TILEFLAG_OWN_REPEAT | TILEFLAG_REPEAT);
|
|
||||||
if(!rep)
|
if(!rep)
|
||||||
rep = new TileRepeatData;
|
rep = new TileRepeatData;
|
||||||
rep->texscaleX = texscalex;
|
rep->texscaleX = texscalex;
|
||||||
rep->texscaleY = texscaley;
|
rep->texscaleY = texscaley;
|
||||||
rep->texOffX = offx;
|
rep->texOffX = offx;
|
||||||
rep->texOffY = offy;
|
rep->texOffY = offy;
|
||||||
rep->refresh(*et, scalex, scaley);
|
rep->refresh(*this);
|
||||||
|
|
||||||
|
// FIXME: if eff, link eff->grid to rep->grid
|
||||||
|
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileData::setRepeatOff()
|
void TileData::setRepeatOff()
|
||||||
{
|
{
|
||||||
flags &= ~TILEFLAG_REPEAT;
|
flags &= ~TILEFLAG_REPEAT;
|
||||||
|
// don't delete this->rep; if we're in editor mode we don't want to lose the repeat data just yet
|
||||||
|
// also, a TileEffectData may point to rep->grid
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileData::refreshRepeat()
|
void TileData::refreshRepeat()
|
||||||
{
|
{
|
||||||
if((flags & TILEFLAG_OWN_REPEAT) && rep)
|
if(rep)
|
||||||
{
|
{
|
||||||
rep->refresh(*et, scalex, scaley);
|
rep->refresh(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TileData::hasStandardTexcoords() const
|
||||||
|
{
|
||||||
|
// repeat applies per-tile texcoords, so if that's set it's non-standard
|
||||||
|
return !rep && et->tc.isStandard();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TexCoordBox& TileData::getTexcoords() const
|
||||||
|
{
|
||||||
|
return !(flags & TILEFLAG_REPEAT)
|
||||||
|
? et->tc
|
||||||
|
: rep->grid.getTexCoords();
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderGrid *TileData::getGrid() const
|
||||||
|
{
|
||||||
|
if(flags & TILEFLAG_REPEAT)
|
||||||
|
return &rep->getGrid();
|
||||||
|
|
||||||
|
if(eff && eff->grid)
|
||||||
|
return eff->grid;
|
||||||
|
|
||||||
|
return et->grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TileEffectConfig::needsOwnInstanceForTile(const TileData& t) const
|
||||||
|
{
|
||||||
|
const bool rep = !!(t.flags & TILEFLAG_REPEAT);
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case EFX_NONE:
|
||||||
|
case EFX_ALPHA:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case EFX_WAVY:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case EFX_SEGS:
|
||||||
|
return rep || !t.hasStandardTexcoords();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
return true; // uhhhh
|
||||||
|
}
|
||||||
|
|
51
BBGE/Tile.h
51
BBGE/Tile.h
|
@ -5,6 +5,9 @@
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "EngineEnums.h"
|
#include "EngineEnums.h"
|
||||||
#include "VertexBuffer.h"
|
#include "VertexBuffer.h"
|
||||||
|
#include "RenderGrid.h"
|
||||||
|
#include "Texture.h" // TexCoordBox
|
||||||
|
|
||||||
|
|
||||||
// A Tile is a very stripped down RenderObject that bypasses the default
|
// A Tile is a very stripped down RenderObject that bypasses the default
|
||||||
// rendering pipeline for efficiency reasons.
|
// rendering pipeline for efficiency reasons.
|
||||||
|
@ -33,14 +36,17 @@ Assumptions:
|
||||||
- Most tiles that exist are going to be rendered
|
- Most tiles that exist are going to be rendered
|
||||||
- Only few tiles have an effect attached
|
- Only few tiles have an effect attached
|
||||||
|
|
||||||
Gotaches:
|
Gotchas:
|
||||||
- Keeping a pointer to a TileData is not safe.
|
- Keeping a pointer to a TileData is not safe.
|
||||||
- Tile indexes are not stable. Moving a tile changes the index it can be addressed with
|
- Tile indexes are not stable. Moving a tile changes the index it can be addressed with
|
||||||
|
- Tile repeat causes a tile to have non-standard texcoords.
|
||||||
|
Grid effect texcoords need to be synced with repeat tc, if repeat is toggled.
|
||||||
|
Also mind non-standard texcoords in ElementTemplate (eg. aquarian glyphs)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ElementTemplate;
|
class ElementTemplate;
|
||||||
class Texture;
|
class Texture;
|
||||||
class RenderGrid;
|
class DynamicRenderGrid;
|
||||||
class TileRender;
|
class TileRender;
|
||||||
|
|
||||||
enum EFXType
|
enum EFXType
|
||||||
|
@ -51,6 +57,8 @@ enum EFXType
|
||||||
EFX_WAVY
|
EFX_WAVY
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TileData;
|
||||||
|
|
||||||
// static configuration for one effect type. POD.
|
// static configuration for one effect type. POD.
|
||||||
struct TileEffectConfig
|
struct TileEffectConfig
|
||||||
{
|
{
|
||||||
|
@ -81,6 +89,9 @@ public:
|
||||||
BlendType blend;
|
BlendType blend;
|
||||||
} alpha;
|
} alpha;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
|
||||||
|
bool needsOwnInstanceForTile(const TileData& t) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TileFlags
|
enum TileFlags
|
||||||
|
@ -96,24 +107,23 @@ enum TileFlags
|
||||||
TILEFLAG_HIDDEN = 0x80, // don't render tile
|
TILEFLAG_HIDDEN = 0x80, // don't render tile
|
||||||
TILEFLAG_SELECTED = 0x100, // ephemeral: selected in editor
|
TILEFLAG_SELECTED = 0x100, // ephemeral: selected in editor
|
||||||
TILEFLAG_EDITOR_HIDDEN = 0x200, // tile is hidden for editor reasons. temporarily set when multi-selecting and moving. doesn't count as hidden externally and is only for rendering.
|
TILEFLAG_EDITOR_HIDDEN = 0x200, // tile is hidden for editor reasons. temporarily set when multi-selecting and moving. doesn't count as hidden externally and is only for rendering.
|
||||||
TILEFLAG_OWN_REPEAT = 0x400, // owns TileRepeatData, may update, must delete
|
TILEFLAG_FV = 0x400, // flipped vertically
|
||||||
TILEFLAG_FV = 0x800, // flipped vertically
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TileData;
|
|
||||||
|
|
||||||
struct TileEffectData
|
struct TileEffectData
|
||||||
{
|
{
|
||||||
TileEffectData(const TileEffectConfig& cfg);
|
TileEffectData(const TileEffectConfig& cfg, const TileData *t); // NULL is passed in during global prepare, when we don't have a tile
|
||||||
~TileEffectData();
|
~TileEffectData();
|
||||||
void update(float dt, const TileData *t); // optional t needed for EFX_WAVY
|
void update(float dt, const TileData *t); // optional t needed for EFX_WAVY
|
||||||
void doInteraction(const TileData& t, const Vector& pos, const Vector& vel, float mult, float touchWidth);
|
void doInteraction(const TileData& t, const Vector& pos, const Vector& vel, float mult, float touchWidth);
|
||||||
|
|
||||||
const EFXType efxtype;
|
const EFXType efxtype;
|
||||||
const unsigned efxidx; // index of TileEffect
|
const unsigned efxidx; // index of TileEffect
|
||||||
RenderGrid *grid;
|
DynamicRenderGrid *grid; // may or may not own this. This possibly points to a tile's TileRepeatData::grid
|
||||||
InterpolatedVector alpha;
|
InterpolatedVector alpha;
|
||||||
BlendType blend;
|
BlendType blend;
|
||||||
|
bool ownGrid; // true if we own grid
|
||||||
|
bool shared; // only used for assertions. set if this tile effect instance is pre-made and shared across many tiles
|
||||||
|
|
||||||
struct Wavy
|
struct Wavy
|
||||||
{
|
{
|
||||||
|
@ -128,23 +138,29 @@ struct TileEffectData
|
||||||
Wavy wavy;
|
Wavy wavy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DynamicRenderGrid *_ensureGrid(size_t w, size_t h, const TileData *t);
|
||||||
TileEffectData(const TileEffectData&); // no-copy
|
TileEffectData(const TileEffectData&); // no-copy
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TileRepeatData
|
struct TileRepeatData
|
||||||
{
|
{
|
||||||
TileRepeatData();
|
TileRepeatData();
|
||||||
|
TileRepeatData(const TileRepeatData& o);
|
||||||
|
const TexCoordBox& getTexCoords() const { return grid.getTexCoords(); }
|
||||||
|
const DynamicRenderGrid& getGrid() const { return grid; }
|
||||||
|
|
||||||
// written via refresh()
|
// written via refresh()
|
||||||
DynamicGPUBuffer vertexbuf;
|
DynamicRenderGrid grid; // need this here because a repeating tile WITH a grid-based tile effect is a special and annoying case to handle
|
||||||
float tu1, tv1, tu2, tv2;
|
|
||||||
|
|
||||||
// set by user
|
// set by user
|
||||||
float texscaleX, texscaleY;
|
float texscaleX, texscaleY;
|
||||||
float texOffX, texOffY;
|
float texOffX, texOffY;
|
||||||
|
|
||||||
// pass ET & scale of owning tile
|
// pass owning tile
|
||||||
void refresh(const ElementTemplate& et, float scalex, float scaley);
|
void refresh(const TileData& t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TexCoordBox calcTexCoords(const TileData& t) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// POD and as compact as possible. Intended for rendering as quickly as possible.
|
// POD and as compact as possible. Intended for rendering as quickly as possible.
|
||||||
|
@ -157,9 +173,9 @@ struct TileData
|
||||||
float rotation;
|
float rotation;
|
||||||
unsigned flags; // TileFlags
|
unsigned flags; // TileFlags
|
||||||
unsigned tag; // FIXME: make this int
|
unsigned tag; // FIXME: make this int
|
||||||
const ElementTemplate *et; // never NULL. texture, texcoords, etc is here. // TODO: maybe replace with unsigned tilesetID? but that's an extra indirection or two during rendering...
|
const ElementTemplate *et; // never NULL. texture, texcoords, etc is here.
|
||||||
TileEffectData *eff; // mostly NULL
|
TileEffectData *eff; // mostly NULL. owned if flags & TILEFLAG_OWN_EFFDATA, otherwise shared
|
||||||
TileRepeatData *rep;
|
TileRepeatData *rep; // NULL in most cases, set if repeating. Always owned.
|
||||||
|
|
||||||
// helpers for external access
|
// helpers for external access
|
||||||
inline void setVisible(bool on) { if(on) flags &= ~TILEFLAG_HIDDEN; else flags |= TILEFLAG_HIDDEN; }
|
inline void setVisible(bool on) { if(on) flags &= ~TILEFLAG_HIDDEN; else flags |= TILEFLAG_HIDDEN; }
|
||||||
|
@ -168,6 +184,11 @@ struct TileData
|
||||||
TileRepeatData *setRepeatOn(float texscalex = 1, float texscaley = 1, float offx = 0, float offy = 0);
|
TileRepeatData *setRepeatOn(float texscalex = 1, float texscaley = 1, float offx = 0, float offy = 0);
|
||||||
void setRepeatOff();
|
void setRepeatOff();
|
||||||
void refreshRepeat();
|
void refreshRepeat();
|
||||||
|
|
||||||
|
bool hasStandardTexcoords() const;
|
||||||
|
|
||||||
|
const TexCoordBox& getTexcoords() const;
|
||||||
|
const RenderGrid *getGrid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TileEffectStorage
|
class TileEffectStorage
|
||||||
|
|
|
@ -64,8 +64,6 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
|
|
||||||
const bool renderExtras = renderBorders || RenderObject::renderCollisionShape;
|
const bool renderExtras = renderBorders || RenderObject::renderCollisionShape;
|
||||||
const TileEffectData *prevEff = ((TileEffectData*)NULL)+1; // initial value is different from anything else
|
const TileEffectData *prevEff = ((TileEffectData*)NULL)+1; // initial value is different from anything else
|
||||||
const RenderGrid *grid = NULL;
|
|
||||||
const DynamicGPUBuffer *lastVertexBuf = NULL;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -114,12 +112,9 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
{
|
{
|
||||||
prevEff = eff;
|
prevEff = eff;
|
||||||
BlendType blend = BLEND_DEFAULT;
|
BlendType blend = BLEND_DEFAULT;
|
||||||
alpha = rs.alpha;
|
|
||||||
grid = NULL;
|
|
||||||
|
|
||||||
if(eff)
|
if(eff)
|
||||||
{
|
{
|
||||||
grid = eff->grid;
|
|
||||||
alpha *= eff->alpha.x;
|
alpha *= eff->alpha.x;
|
||||||
blend = eff->blend;
|
blend = eff->blend;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +131,7 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
// Maps were designed with the bug present so we need to replicate it,
|
// Maps were designed with the bug present so we need to replicate it,
|
||||||
// otherwise things won't look correct.
|
// otherwise things won't look correct.
|
||||||
unsigned effflag = tile.flags;
|
unsigned effflag = tile.flags;
|
||||||
if(grid)
|
if(eff && eff->grid)
|
||||||
effflag &= ~TILEFLAG_FV;
|
effflag &= ~TILEFLAG_FV;
|
||||||
|
|
||||||
float effrot = tile.rotation;
|
float effrot = tile.rotation;
|
||||||
|
@ -166,37 +161,12 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
glScalef(sw, sh, 1);
|
glScalef(sw, sh, 1);
|
||||||
|
|
||||||
|
|
||||||
|
const RenderGrid *grid = tile.getGrid();
|
||||||
if(!grid)
|
if(!grid)
|
||||||
{
|
grid = core->getDefaultQuadGrid();
|
||||||
const DynamicGPUBuffer *vb = !(tile.flags & TILEFLAG_REPEAT)
|
rx.alpha = alpha;
|
||||||
? tile.et->vertexbuf
|
grid->render(rx);
|
||||||
: &tile.rep->vertexbuf;
|
|
||||||
assert(vb);
|
|
||||||
if(vb != lastVertexBuf)
|
|
||||||
{
|
|
||||||
lastVertexBuf = vb;
|
|
||||||
vb->apply();
|
|
||||||
}
|
|
||||||
vb->DrawArrays(GL_TRIANGLE_FAN, 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rx.alpha = alpha;
|
|
||||||
|
|
||||||
Vector upperLeftTextureCoordinates, lowerRightTextureCoordinates;
|
|
||||||
if(tile.flags & TILEFLAG_REPEAT)
|
|
||||||
{
|
|
||||||
upperLeftTextureCoordinates = Vector(tile.rep->tu1, tile.rep->tv1);
|
|
||||||
lowerRightTextureCoordinates = Vector(tile.rep->tu2, tile.rep->tv2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
upperLeftTextureCoordinates = Vector(et->tu1, et->tv1);
|
|
||||||
lowerRightTextureCoordinates = Vector(et->tu2, et->tv2);
|
|
||||||
}
|
|
||||||
|
|
||||||
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(renderExtras)
|
if(renderExtras)
|
||||||
{
|
{
|
||||||
|
@ -221,6 +191,7 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
glVertex2f(0,0);
|
glVertex2f(0,0);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
|
// TODO: move this to the IBO
|
||||||
glLineWidth(2);
|
glLineWidth(2);
|
||||||
glBegin(GL_LINE_STRIP);
|
glBegin(GL_LINE_STRIP);
|
||||||
glVertex2f(0.5f, 0.5f);
|
glVertex2f(0.5f, 0.5f);
|
||||||
|
@ -235,7 +206,8 @@ void TileRender::onRender(const RenderState& rs) const
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER, 0);
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||||
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
|
||||||
|
|
||||||
RenderObject::lastTextureApplied = lastTexId;
|
RenderObject::lastTextureApplied = lastTexId;
|
||||||
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
||||||
|
|
|
@ -172,8 +172,7 @@ const ElementTemplate* Tileset::getAdjacent(size_t idx, int direction, bool wrap
|
||||||
|
|
||||||
ElementTemplate::~ElementTemplate()
|
ElementTemplate::~ElementTemplate()
|
||||||
{
|
{
|
||||||
if(ownsVertexbuf)
|
delete grid;
|
||||||
delete const_cast<DynamicGPUBuffer*>(vertexbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElementTemplate::finalize()
|
void ElementTemplate::finalize()
|
||||||
|
@ -195,20 +194,16 @@ void ElementTemplate::finalize()
|
||||||
h = 64;
|
h = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tu1 == 0 && tv1 == 0 && tu2 == 1 && tv2 == 1)
|
if(tc.isStandard())
|
||||||
{
|
{
|
||||||
// this avoids buffer switches later on
|
delete grid;
|
||||||
vertexbuf = core->getDefaultQuadVertexBuffer();
|
grid = NULL;
|
||||||
ownsVertexbuf = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DynamicGPUBuffer *vb = ownsVertexbuf
|
if(!grid)
|
||||||
? const_cast<DynamicGPUBuffer*>(vertexbuf)
|
grid = new RenderGrid;
|
||||||
: new DynamicGPUBuffer(GPUBUF_STATIC | GPUBUF_VERTEXBUF);
|
grid->init(2, 2, tc);
|
||||||
vb->initQuadVertices(tu1, tv1, tu2, tv2);
|
|
||||||
vertexbuf = vb;
|
|
||||||
ownsVertexbuf = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "VertexBuffer.h"
|
#include "RenderGrid.h"
|
||||||
|
|
||||||
|
class DynamicRenderGrid;
|
||||||
|
|
||||||
class ElementTemplate
|
class ElementTemplate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; vertexbuf = NULL; ownsVertexbuf = false; }
|
ElementTemplate() { w=0; h=0; idx=-1; tc.setStandard(); grid = NULL; }
|
||||||
~ElementTemplate();
|
~ElementTemplate();
|
||||||
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
||||||
|
|
||||||
|
@ -18,11 +20,10 @@ public:
|
||||||
// lazily assigned when tex is loaded
|
// lazily assigned when tex is loaded
|
||||||
CountedPtr<Texture> tex; // NULL if failed to load or not yet loaded
|
CountedPtr<Texture> tex; // NULL if failed to load or not yet loaded
|
||||||
float w,h; // custom size if used, otherwise texture size
|
float w,h; // custom size if used, otherwise texture size
|
||||||
const DynamicGPUBuffer * vertexbuf; // never NULL
|
RenderGrid *grid; // NULL if default, otherwise we own this
|
||||||
bool ownsVertexbuf;
|
|
||||||
|
|
||||||
// fixed
|
// fixed
|
||||||
float tu1, tu2, tv1, tv2; // texcoords
|
TexCoordBox tc;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
std::string gfx;
|
std::string gfx;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "RenderBase.h"
|
#include "RenderBase.h"
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "Texture.h" // TexCoordBox
|
||||||
|
|
||||||
bool DynamicGPUBuffer::_HasARB = false;
|
bool DynamicGPUBuffer::_HasARB = false;
|
||||||
|
|
||||||
|
@ -34,8 +35,9 @@ DynamicGPUBuffer::DynamicGPUBuffer(unsigned usage)
|
||||||
: _bufid(0)
|
: _bufid(0)
|
||||||
, _binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB)
|
, _binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB)
|
||||||
, _size(0)
|
, _size(0)
|
||||||
, _cap(0)
|
, _h_cap(0)
|
||||||
, _h_data(NULL)
|
, _h_data(NULL)
|
||||||
|
, _d_cap(0)
|
||||||
, _d_map(NULL)
|
, _d_map(NULL)
|
||||||
, _usage(toGlUsage(usage))
|
, _usage(toGlUsage(usage))
|
||||||
, _datatype(BufDataType(-1))
|
, _datatype(BufDataType(-1))
|
||||||
|
@ -55,7 +57,7 @@ void* DynamicGPUBuffer::_allocBytes(size_t bytes)
|
||||||
void *p = realloc(_h_data, bytes);
|
void *p = realloc(_h_data, bytes);
|
||||||
if(p)
|
if(p)
|
||||||
{
|
{
|
||||||
_cap = bytes;
|
_h_cap = bytes;
|
||||||
_h_data = p;
|
_h_data = p;
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
@ -63,10 +65,10 @@ void* DynamicGPUBuffer::_allocBytes(size_t bytes)
|
||||||
|
|
||||||
void* DynamicGPUBuffer::_ensureBytes(size_t bytes)
|
void* DynamicGPUBuffer::_ensureBytes(size_t bytes)
|
||||||
{
|
{
|
||||||
if(bytes < _cap)
|
if(bytes < _h_cap)
|
||||||
return _h_data;
|
return _h_data;
|
||||||
|
|
||||||
size_t newsize = 2 * _size;
|
size_t newsize = 2 * _h_cap;
|
||||||
if(newsize < bytes)
|
if(newsize < bytes)
|
||||||
newsize += bytes;
|
newsize += bytes;
|
||||||
|
|
||||||
|
@ -81,9 +83,10 @@ void* DynamicGPUBuffer::beginWrite(BufDataType type, size_t newsize, unsigned ac
|
||||||
if(_HasARB)
|
if(_HasARB)
|
||||||
{
|
{
|
||||||
glBindBufferARB(_binding, _ensureDBuf());
|
glBindBufferARB(_binding, _ensureDBuf());
|
||||||
glBufferDataARB(_binding, newsize, NULL, _usage); // orphan buffer
|
|
||||||
if(!(access & GPUACCESS_HOSTCOPY))
|
if(!(access & GPUACCESS_HOSTCOPY))
|
||||||
{
|
{
|
||||||
|
_d_cap = newsize;
|
||||||
|
glBufferDataARB(_binding, newsize, NULL, _usage); // orphan buffer
|
||||||
void *p = glMapBufferARB(_binding, GL_WRITE_ONLY_ARB);
|
void *p = glMapBufferARB(_binding, GL_WRITE_ONLY_ARB);
|
||||||
_d_map = p;
|
_d_map = p;
|
||||||
if(p)
|
if(p)
|
||||||
|
@ -95,21 +98,41 @@ void* DynamicGPUBuffer::beginWrite(BufDataType type, size_t newsize, unsigned ac
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicGPUBuffer::commitWrite()
|
bool DynamicGPUBuffer::commitWrite()
|
||||||
|
{
|
||||||
|
return _commitWrite(_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicGPUBuffer::commitWrite(size_t used)
|
||||||
|
{
|
||||||
|
_size = used;
|
||||||
|
return _commitWrite(used);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicGPUBuffer::_commitWrite(size_t used)
|
||||||
{
|
{
|
||||||
if(_HasARB)
|
if(_HasARB)
|
||||||
{
|
{
|
||||||
if(_d_map)
|
if(_d_map)
|
||||||
{
|
{
|
||||||
|
assert(used <= _d_cap);
|
||||||
_d_map = NULL;
|
_d_map = NULL;
|
||||||
return glUnmapBufferARB(_binding); // can fail
|
return glUnmapBufferARB(_binding); // can fail
|
||||||
}
|
}
|
||||||
// otherwise, the prev. call to glMapBufferARB failed (or GPUACCESS_NOMAP was set).
|
// otherwise, the prev. call to glMapBufferARB failed (or GPUACCESS_HOSTCOPY was set).
|
||||||
// -> didn't map, but wrote to host memory. upload it.
|
// -> didn't map, but wrote to host memory. upload it.
|
||||||
assert(_h_data);
|
assert(_h_data);
|
||||||
glBufferSubDataARB(_binding, 0, _size, _h_data);
|
assert(used <= _h_cap);
|
||||||
|
if(used <= _d_cap)
|
||||||
|
glBufferSubDataARB(_binding, 0, used, _h_data); // update existing buffer
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_d_cap = used;
|
||||||
|
glBufferDataARB(_binding, used, _h_data, _usage); // alloc new buffer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// else nothing to do
|
// else nothing to do
|
||||||
|
|
||||||
|
assert(used <= _h_cap);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,33 +167,40 @@ void DynamicGPUBuffer::apply(BufDataType usetype) const
|
||||||
if(!usetype)
|
if(!usetype)
|
||||||
usetype = _datatype;
|
usetype = _datatype;
|
||||||
|
|
||||||
|
const unsigned bufid = this->_bufid;
|
||||||
|
|
||||||
void *p;
|
void *p;
|
||||||
if(_HasARB)
|
if(bufid)
|
||||||
{
|
{
|
||||||
unsigned bufid = this->_bufid;
|
|
||||||
assert(bufid != s_lastVertexBuffer); // check that it's no redundant state change
|
|
||||||
if(bufid == s_lastVertexBuffer && usetype == s_lastDataType)
|
|
||||||
return;
|
|
||||||
p = NULL;
|
p = NULL;
|
||||||
s_lastVertexBuffer = bufid;
|
//if(bufid != s_lastVertexBuffer)
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
|
// glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p = (void*)this->_h_data;
|
p = (void*)this->_h_data;
|
||||||
assert(p != s_lastHostPtr); // check that it's no redundant state change
|
//assert(p != s_lastHostPtr); // check that it's no redundant state change
|
||||||
if(p == s_lastHostPtr && usetype == s_lastDataType) // don't need to check for datatype since that's const for the buffer with that ptr
|
//if(p == s_lastHostPtr && usetype == s_lastDataType) // don't need to check for datatype since that's const for the buffer with that ptr
|
||||||
return;
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_lastDataType = usetype;
|
assert(bufid || p);
|
||||||
|
|
||||||
assert((ty & 0xf) < Countof(s_gltype));
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
|
||||||
const unsigned gltype = s_gltype[usetype & 0xf];
|
|
||||||
const unsigned scalars = (usetype >> 4) & 0xf;
|
//if(bufid == s_lastVertexBuffer && usetype == s_lastDataType && p == s_lastHostPtr)
|
||||||
const unsigned stride = (usetype >> 8) & 0xff;
|
// return;
|
||||||
const unsigned tcoffset = (usetype >> 16) & 0xff;
|
|
||||||
const unsigned coloroffset = usetype >> 24;
|
s_lastDataType = usetype;
|
||||||
|
s_lastVertexBuffer = bufid;
|
||||||
|
|
||||||
|
unsigned u = usetype; // always want unsigned shifts
|
||||||
|
assert((u & 0xf) < Countof(s_gltype));
|
||||||
|
const unsigned gltype = s_gltype[u & 0xf];
|
||||||
|
const unsigned scalars = (u >> 4u) & 0xf;
|
||||||
|
const unsigned stride = (u >> 8u) & 0xff;
|
||||||
|
const unsigned tcoffset = (u >> 16u) & 0xff;
|
||||||
|
const unsigned coloroffset = u >> 24u;
|
||||||
|
|
||||||
// vertex and texcoords are always enabled
|
// vertex and texcoords are always enabled
|
||||||
glVertexPointer(scalars, gltype, stride, p);
|
glVertexPointer(scalars, gltype, stride, p);
|
||||||
|
@ -225,38 +255,107 @@ void DynamicGPUBuffer::dropBuffer()
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicGPUBuffer::DrawArrays(unsigned glmode, size_t n, size_t first)
|
static unsigned getBoundBuffer(unsigned target)
|
||||||
{
|
{
|
||||||
glDrawArrays(glmode, first, n);
|
int id = 0;
|
||||||
|
glGetIntegerv(target, &id);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first)
|
void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first) const
|
||||||
{
|
{
|
||||||
assert(_binding == GL_ELEMENT_ARRAY_BUFFER_ARB);
|
assert(_binding == GL_ELEMENT_ARRAY_BUFFER_ARB);
|
||||||
assert(s_gltype[_datatype & 0xf] == GL_SHORT);
|
assert(s_gltype[_datatype & 0xf] == GL_SHORT);
|
||||||
|
assert(getBoundBuffer(GL_ARRAY_BUFFER_BINDING)); // FIXME: this assert is wrong if indices are on the host
|
||||||
|
|
||||||
if(s_lastIndexBuffer != _bufid)
|
unsigned id = _bufid;
|
||||||
{
|
|
||||||
s_lastIndexBuffer = _bufid;
|
|
||||||
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _bufid);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDrawElements(glmode, n, GL_SHORT, NULL);
|
//if(s_lastIndexBuffer != id)
|
||||||
|
//{
|
||||||
|
// s_lastIndexBuffer = id;
|
||||||
|
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, id);
|
||||||
|
//}
|
||||||
|
|
||||||
|
void *p = id ? NULL : _h_data;
|
||||||
|
assert(p || id);
|
||||||
|
|
||||||
|
glDrawElements(glmode, n, GL_UNSIGNED_SHORT, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicGPUBuffer::initQuadVertices(float tu1, float tv1, float tu2, float tv2)
|
void DynamicGPUBuffer::initQuadVertices(const TexCoordBox& tc, unsigned access)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
float *p = (float*)beginWrite(GPUBUFTYPE_VEC2_TC, (4*4) * sizeof(float), GPUACCESS_DEFAULT);
|
float *p = (float*)beginWrite(GPUBUFTYPE_VEC2_TC, (4*4) * sizeof(float), access);
|
||||||
*p++ = -0.5f; *p++ = +0.5f; // xy
|
*p++ = -0.5f; *p++ = +0.5f; // xy
|
||||||
*p++ = tu1; *p++ = 1.0f-tv1; // uv
|
*p++ = tc.u1; *p++ = tc.v1; // uv
|
||||||
*p++ = +0.5f; *p++ = +0.5f; // xy
|
*p++ = +0.5f; *p++ = +0.5f; // xy
|
||||||
*p++ = tu2; *p++ = 1.0f-tv1; // uv
|
*p++ = tc.u2; *p++ = tc.v1; // uv
|
||||||
*p++ = +0.5f; *p++ = -0.5f; // xy
|
*p++ = +0.5f; *p++ = -0.5f; // xy
|
||||||
*p++ = tu2; *p++ = 1.0f-tv2; // uv
|
*p++ = tc.u2; *p++ = tc.v2; // uv
|
||||||
*p++ = -0.5f; *p++ = -0.5f; // xy
|
*p++ = -0.5f; *p++ = -0.5f; // xy
|
||||||
*p++ = tu1; *p++ = 1.0f-tv2; // uv
|
*p++ = tc.u1; *p++ = tc.v2; // uv
|
||||||
}
|
}
|
||||||
while(!commitWrite());
|
while(!commitWrite());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0---1---2---3
|
||||||
|
// | | | |
|
||||||
|
// 4---5---6---7
|
||||||
|
// | | | |
|
||||||
|
// 8---9---10--11
|
||||||
|
// This is a 4x3 grid
|
||||||
|
// Which is 3*2 = 6 quads
|
||||||
|
// That's 12 triangles
|
||||||
|
// Each triangle is 3 indices, so we get 36 indices in total
|
||||||
|
size_t DynamicGPUBuffer::initGridIndices_Triangles(size_t w, size_t h, bool invert, unsigned access)
|
||||||
|
{
|
||||||
|
assert(w * h < 0xffff);
|
||||||
|
|
||||||
|
const size_t quadsx = w - 1;
|
||||||
|
const size_t quadsy = h - 1;
|
||||||
|
const size_t quads = quadsx * quadsy;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
unsigned short *p = (unsigned short*)beginWrite(GPUBUFTYPE_U16, 6*quads * sizeof(short), access);
|
||||||
|
|
||||||
|
if(!invert)
|
||||||
|
{
|
||||||
|
// top to bottom
|
||||||
|
for(size_t y = 0; y < quadsy; ++y)
|
||||||
|
{
|
||||||
|
size_t i = y * w;
|
||||||
|
for(size_t x = 0; x < quadsx; ++x)
|
||||||
|
{
|
||||||
|
*p++ = (unsigned short)(i); // 0
|
||||||
|
*p++ = (unsigned short)(i + 1); // 1
|
||||||
|
*p++ = (unsigned short)(i + w); // 4
|
||||||
|
|
||||||
|
*p++ = (unsigned short)(i + 1); // 1
|
||||||
|
*p++ = (unsigned short)(i + w + 1); // 5
|
||||||
|
*p++ = (unsigned short)(i + w); // 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// bottom to top
|
||||||
|
for(size_t y = quadsy; y --> 0; )
|
||||||
|
{
|
||||||
|
size_t i = y * w;
|
||||||
|
for(size_t x = 0; x < quadsx; ++x)
|
||||||
|
{
|
||||||
|
*p++ = (unsigned short)(i); // 0
|
||||||
|
*p++ = (unsigned short)(i + 1); // 1
|
||||||
|
*p++ = (unsigned short)(i + w); // 4
|
||||||
|
|
||||||
|
*p++ = (unsigned short)(i + 1); // 1
|
||||||
|
*p++ = (unsigned short)(i + w + 1); // 5
|
||||||
|
*p++ = (unsigned short)(i + w); // 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(!commitWrite());
|
||||||
|
return quads * 6; // each quad is 2 triangles x 3 verts
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdlib.h> // size_t
|
#include <stdlib.h> // size_t
|
||||||
|
|
||||||
|
struct TexCoordBox;
|
||||||
|
|
||||||
enum BufUsage
|
enum BufUsage
|
||||||
{
|
{
|
||||||
// usage
|
// usage
|
||||||
|
@ -43,9 +45,8 @@ enum AccessFlags
|
||||||
|
|
||||||
class DynamicGPUBuffer
|
class DynamicGPUBuffer
|
||||||
{
|
{
|
||||||
friend class BufMapW;
|
|
||||||
public:
|
public:
|
||||||
void StaticInit();
|
static void StaticInit();
|
||||||
DynamicGPUBuffer(unsigned usage);
|
DynamicGPUBuffer(unsigned usage);
|
||||||
~DynamicGPUBuffer();
|
~DynamicGPUBuffer();
|
||||||
void dropBuffer();
|
void dropBuffer();
|
||||||
|
@ -54,37 +55,51 @@ public:
|
||||||
|
|
||||||
// beginWrite(), then write exactly newsize bytes, then commit
|
// beginWrite(), then write exactly newsize bytes, then commit
|
||||||
void *beginWrite(BufDataType type, size_t newsize, unsigned access); // AccessFlags
|
void *beginWrite(BufDataType type, size_t newsize, unsigned access); // AccessFlags
|
||||||
bool commitWrite();
|
bool commitWrite(); // used same size as passed to beginWrite()
|
||||||
|
bool commitWrite(size_t used); // explicitly specify used size (may be less than initially requested)
|
||||||
|
|
||||||
void upload(BufDataType type, const void *data, size_t size);
|
void upload(BufDataType type, const void *data, size_t size);
|
||||||
|
|
||||||
static void DrawArrays(unsigned glmode, size_t n, size_t first = 0); // uses last applied buffer for drawing
|
|
||||||
|
|
||||||
// uses own data for indexing and prev. applied buffer for the data to draw
|
// uses own data for indexing and prev. applied buffer for the data to draw
|
||||||
void drawElements(unsigned glmode, size_t n, size_t first = 0);
|
void drawElements(unsigned glmode, size_t n, size_t first = 0) const;
|
||||||
|
|
||||||
|
|
||||||
void apply(BufDataType usetype = GPUBUFTYPE_NONE) const;
|
void apply(BufDataType usetype = GPUBUFTYPE_NONE) const;
|
||||||
|
|
||||||
// Inteded for use with DrawArrays(4) and GL_TRIANGLE_FAN or GL_QUADS (both work)
|
// Inteded for use with DrawArrays(4) and GL_TRIANGLE_FAN or GL_QUADS (both work)
|
||||||
void initQuadVertices(float tu1, float tu2, float tv1, float tv2);
|
void initQuadVertices(const TexCoordBox& tc, unsigned access);
|
||||||
|
|
||||||
|
// Init indices for drawing a grid, like this 4x3 grid:
|
||||||
|
// 0---1---2---3
|
||||||
|
// | | | |
|
||||||
|
// 4---5---6---7
|
||||||
|
// | | | |
|
||||||
|
// 8---9---10--11
|
||||||
|
// Returns the number of triangles to use with GL_TRIANGLES.
|
||||||
|
// Pass invert==true to draw from bottom to top.
|
||||||
|
size_t initGridIndices_Triangles(size_t w, size_t h, bool invert, unsigned access);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void* _allocBytes(size_t bytes);
|
void* _allocBytes(size_t bytes);
|
||||||
void* _ensureBytes(size_t bytes);
|
void* _ensureBytes(size_t bytes);
|
||||||
unsigned _ensureDBuf();
|
unsigned _ensureDBuf();
|
||||||
|
bool _commitWrite(size_t used);
|
||||||
|
|
||||||
unsigned _bufid;
|
unsigned _bufid;
|
||||||
unsigned _binding;
|
unsigned _binding;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
size_t _cap;
|
size_t _h_cap;
|
||||||
void *_h_data;
|
void *_h_data;
|
||||||
|
size_t _d_cap;
|
||||||
void *_d_map;
|
void *_d_map;
|
||||||
const unsigned _usage;
|
const unsigned _usage;
|
||||||
BufDataType _datatype;
|
BufDataType _datatype;
|
||||||
|
|
||||||
static bool _HasARB;
|
static bool _HasARB;
|
||||||
|
|
||||||
|
DynamicGPUBuffer(const DynamicGPUBuffer&); // no copy
|
||||||
|
DynamicGPUBuffer& operator=(const DynamicGPUBuffer&); // no assign
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue