1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-05-11 19:43:50 +00:00

rework QuadGrid and some anim editor internal things to use VBOs

This commit is contained in:
fgenesis 2025-03-15 04:15:19 +01:00
parent 7b7681ffb6
commit db5fcfa632
5 changed files with 186 additions and 73 deletions

View file

@ -77,34 +77,73 @@ class TimelineTickRender : public RenderObject
public:
TimelineTickRender()
: bg("black", Vector(400, 0))
, vbo(GPUBUF_VERTEXBUF | GPUBUF_DYNAMIC)
{
addChild(&bg, PM_STATIC, RBP_ON);
bg.setWidthHeight(800, TIMELINE_HEIGHT);
bg.alphaMod = 0.2f;
updateVBO();
}
virtual ~TimelineTickRender()
{
}
virtual void onUpdate(float dt) OVERRIDE
{
const float h2 = TIMELINE_HEIGHT * 0.5f;
const float tx = ae->getAnimTime() * (TIMELINE_GRIDSIZE / TIMELINE_UNIT);
// Update data for last 2 vertices (last line)
const float linedata[] =
{
tx + TIMELINE_X_OFFS, -h2,
tx + TIMELINE_X_OFFS, h2
};
vbo.updatePartial((verts * 2 * sizeof(float)) - sizeof(linedata), &linedata[0], sizeof(linedata));
RenderObject::onUpdate(dt);
}
void updateVBO()
{
const size_t lines = (size_t(800) / TIMELINE_GRIDSIZE) + 1;
verts = lines * 2;
const size_t bytes = verts * 2 * sizeof(float);
const float h2 = TIMELINE_HEIGHT * 0.5f;
float *p;
do
{
p = (float*)vbo.beginWrite(GPUBUFTYPE_VEC2, bytes, GPUACCESS_DEFAULT);
for (int x = 0; x < 800; x += TIMELINE_GRIDSIZE)
{
*p++ = x + TIMELINE_X_OFFS; *p++ = -h2;
*p++ = x + TIMELINE_X_OFFS; *p++ = h2;
}
// Last 2 vertices -- colored differently
const float tx = ae->getAnimTime() * (TIMELINE_GRIDSIZE / TIMELINE_UNIT);
*p++ = tx + TIMELINE_X_OFFS; *p++ = -h2;
*p++ = tx + TIMELINE_X_OFFS; *p++ = h2;
}
while(!vbo.commitWriteExact(p));
}
private:
Quad bg;
DynamicGPUBuffer vbo;
size_t verts;
void onRender(const RenderState& rs) const OVERRIDE
{
glLineWidth(1);
glBegin(GL_LINES);
vbo.apply();
glColor4f(1, 1, 1, 1);
const float h2 = TIMELINE_HEIGHT * 0.5f;
for (int x = 0; x < 800; x += TIMELINE_GRIDSIZE)
{
glVertex3f(x + TIMELINE_X_OFFS, -h2, 0);
glVertex3f(x + TIMELINE_X_OFFS, h2, 0);
}
glDrawArrays(GL_LINES, 0, verts-2);
glColor4f(0, 1, 0, 1);
float tx = ae->getAnimTime() * (TIMELINE_GRIDSIZE / TIMELINE_UNIT);
glVertex3f(tx + TIMELINE_X_OFFS, -h2, 0);
glVertex3f(tx + TIMELINE_X_OFFS, h2, 0);
glEnd();
glDrawArrays(GL_LINES, verts-2, 2);
}
};
@ -115,7 +154,7 @@ public:
DebugFont label;
TimelineRender(int page)
: page(page), label(6)
: page(page), label(6), vbo(GPUBUF_VERTEXBUF | GPUBUF_DYNAMIC)
{
setWidthHeight(800, 10);
addChild(&label, PM_STATIC);
@ -159,6 +198,30 @@ public:
private:
DynamicGPUBuffer vbo;
void updateVBO()
{
SkeletalSprite *spr = ae->getPageSprite(page);
if(!spr->isLoaded())
return;
const float h2 = height * 0.5f;
const float tx = spr->getAnimationLayer(0)->timer * (TIMELINE_GRIDSIZE / TIMELINE_UNIT);
const float linedata[] =
{
tx + TIMELINE_X_OFFS, h2 - 5,
tx + TIMELINE_X_OFFS, h2 + 5
};
vbo.upload(GPUBUFTYPE_VEC2, &linedata[0], sizeof(linedata));
}
virtual void onUpdate(float dt) OVERRIDE
{
updateVBO();
Quad::onUpdate(dt);
}
void onRender(const RenderState& rs) const OVERRIDE
{
SkeletalSprite *spr = ae->getPageSprite(page);
@ -176,13 +239,13 @@ private:
Quad::onRender(rs);
glPopMatrix();
glColor4f(0, 1, 0, 1);
glLineWidth(3);
glBegin(GL_LINES);
float tx = spr->getAnimationLayer(0)->timer * (TIMELINE_GRIDSIZE / TIMELINE_UNIT);
glVertex3f(tx + TIMELINE_X_OFFS, h2 - 5, 0);
glVertex3f(tx + TIMELINE_X_OFFS, h2 + 5, 0);
glEnd();
if(vbo.size())
{
glColor4f(0, 1, 0, 1);
glLineWidth(3);
vbo.apply();
glDrawArrays(GL_LINES, 0, 2);
}
}
std::vector<KeyframeWidget*> keyframes;
@ -2167,6 +2230,7 @@ void AnimationEditor::selectPage(unsigned page)
void AnimationEditor::updateTimelineGrid()
{
timelineTicks->updateVBO();
std::ostringstream os;
os << "Grid: " << TIMELINE_GRIDSIZE;
gridsize->setText(os.str());

View file

@ -5,15 +5,19 @@
QuadGrid::QuadGrid(size_t w, size_t h)
: pauseLevel(0), _w(w+1), _h(h+1)
, dirty(true)
, vbo(GPUBUF_DYNAMIC | GPUBUF_VERTEXBUF)
, ibo(GPUBUF_STATIC | GPUBUF_INDEXBUF)
, _points((w+1) * (h+1))
{
addType(SCO_QUAD_GRID);
_points.resize((w+1) * (h+1));
resetUV();
resetPos(1, 1);
this->width = 2;
this->height = 2;
this->cull = false;
this->repeatTexture = true;
_numtris = ibo.initGridIndices_Triangles(w+1, h+1, false, GPUACCESS_DEFAULT);
}
QuadGrid* QuadGrid::New(size_t w, size_t h)
@ -46,6 +50,8 @@ void QuadGrid::resetUV(float xmul, float ymul)
}
v += incY;
}
dirty = true;
}
void QuadGrid::resetPos(float w, float h, float xoffs, float yoffs)
@ -66,50 +72,29 @@ void QuadGrid::resetPos(float w, float h, float xoffs, float yoffs)
row[x].y = yy;
}
}
}
static inline void drawOnePoint(const QuadGrid::Point& p, float ox, float oy)
{
glTexCoord2f(p.u + ox, p.v + oy);
glVertex2f(p.x, p.y);
dirty = true;
}
void QuadGrid::onRender(const RenderState& rs) const
{
glColor4f(color.x, color.y, color.z, alpha.x * alphaMod);
const float ox = texOffset.x;
const float oy = texOffset.y;
const size_t NX = pointsX();
// go over grids
const size_t W = quadsX();
const size_t H = quadsY();
for(size_t y = 0; y < H; ++y)
{
const Point * const row0 = &_points[y * NX];
const Point * const row1 = row0 + NX;
for(size_t x = 0; x < W; ++x)
{
glBegin(GL_QUADS);
drawOnePoint(row0[x], ox, oy);
drawOnePoint(row0[x+1], ox, oy);
drawOnePoint(row1[x+1], ox, oy);
drawOnePoint(row1[x], ox, oy);
glEnd();
}
}
vbo.apply();
ibo.drawElements(GL_TRIANGLES, _numtris);
}
void QuadGrid::onUpdate(float dt)
{
if(pauseLevel < core->particlesPaused)
return;
const bool interp = texOffset.isInterpolating();
if(!(pauseLevel < core->particlesPaused))
{
texOffset.update(dt);
RenderObject::onUpdate(dt);
}
texOffset.update(dt);
RenderObject::onUpdate(dt);
if(dirty || interp)
updateVBO();
}
void QuadGrid::onSetTexture() // same as Quad::setTexture()
@ -125,3 +110,24 @@ void QuadGrid::onSetTexture() // same as Quad::setTexture()
height = 64;
}
}
void QuadGrid::updateVBO()
{
const size_t bytes = _points.size() * sizeof(Point);
do
{
const Point *s = &_points[0];
Point *p = (Point*)vbo.beginWrite(GPUBUFTYPE_VEC2_TC, bytes, GPUACCESS_DEFAULT);
for(size_t i = 0; i < _points.size(); ++i, ++p, ++s)
{
p->x = s->x;
p->y = s->y;
p->u = s->u + texOffset.x;
p->v = s->v + texOffset.y;
}
}
while(!vbo.commitWrite());
dirty = false;
}

View file

@ -3,6 +3,7 @@
#include <vector>
#include "RenderObject.h"
#include "VertexBuffer.h"
/*
This class is an extension for Quad, where coordinates and UV coords can be set freely.
@ -34,6 +35,7 @@ public:
inline Point& operator()(size_t x, size_t y)
{
dirty = true;
return _points[y * _w + x];
}
@ -59,12 +61,17 @@ public:
public:
InterpolatedVector texOffset;
int pauseLevel;
bool dirty;
private:
QuadGrid(size_t w, size_t h);
const size_t _w, _h; // number of points in each direction (2x3 quads => 3x4 grid points)
void updateVBO();
DynamicGPUBuffer vbo, ibo;
std::vector<Point> _points;
size_t _numtris;
};

View file

@ -141,16 +141,7 @@ bool DynamicGPUBuffer::_commitWrite(size_t used)
// -> didn't map, but wrote to host memory. upload it.
assert(_h_data);
assert(used <= _h_cap);
if(used)
{
if(used <= _d_cap)
glBufferSubDataARB(_gl_binding, 0, used, _h_data); // update existing buffer
else
{
_d_cap = used;
glBufferDataARB(_gl_binding, used, _h_data, _gl_usage); // alloc new buffer
}
}
_uploadFromHost(_h_data, used);
}
// else nothing to do
@ -161,21 +152,63 @@ bool DynamicGPUBuffer::_commitWrite(size_t used)
void DynamicGPUBuffer::upload(BufDataType type, const void* data, size_t size)
{
_datatype = type;
_size = size;
if(_HasARB)
{
const unsigned id = _ensureDBuf();
unsigned& last = s_lastBuffer[_usage & GPUBUF_BINDING_MASK];
if(id != last)
{
last = id;
glBindBufferARB(_gl_binding, id);
}
_d_cap = size;
glBufferDataARB(_gl_binding, size, data, _gl_usage);
const unsigned id = _Bind(_ensureDBuf(), _gl_binding, _usage);
_uploadFromHost(data, size);
}
else
memcpy(_ensureBytes(size), data, size);
{
void *dst = _ensureBytes(size);
if(data)
memcpy(dst, data, size);
}
}
unsigned DynamicGPUBuffer::_Bind(unsigned id, unsigned binding, unsigned usage)
{
unsigned& last = s_lastBuffer[usage & GPUBUF_BINDING_MASK];
if(id != last)
{
last = id;
glBindBufferARB(binding, id);
}
return id;
}
// Assumes buffer is already bound
void DynamicGPUBuffer::_uploadFromHost(const void * data, size_t size)
{
assert(_HasARB);
if(size)
{
if(size <= _d_cap)
glBufferSubDataARB(_gl_binding, 0, size, data); // update existing buffer
else
{
_d_cap = size;
glBufferDataARB(_gl_binding, size, data, _gl_usage); // alloc new buffer
}
}
}
void DynamicGPUBuffer::updatePartial(size_t offset, const void * data, size_t size)
{
if(_HasARB)
{
assert(_bufid); // Must have been previously allocated
assert(offset + size <= _d_cap);
_Bind(_bufid, _gl_binding, _usage);
glBufferSubDataARB(_gl_binding, offset, size, data);
}
if(_h_data)
{
assert(offset + size <= _h_cap);
memcpy((char*)_h_data + offset, data, size);
}
}
static const unsigned s_gltype[] =

View file

@ -63,6 +63,7 @@ public:
bool commitWriteExact(const void *p); // asserts that as many bytes as allocated were written
void upload(BufDataType type, const void *data, size_t size);
void updatePartial(size_t offset, const void *data, size_t size);
// 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) const;
@ -93,6 +94,8 @@ private:
void* _ensureBytes(size_t bytes);
unsigned _ensureDBuf();
bool _commitWrite(size_t used);
void _uploadFromHost(const void *data, size_t size);
static unsigned _Bind(unsigned id, unsigned binding, unsigned usage);
unsigned _bufid;
unsigned _gl_binding;