1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-07-03 22:44:32 +00:00

split Strand from Segmented; don't waste an entire RenderObject to store a single position

This commit is contained in:
fgenesis 2025-03-03 01:36:04 +01:00
parent 33567d323e
commit 6f8bc8647a
5 changed files with 61 additions and 39 deletions

View file

@ -89,6 +89,7 @@ SET(AQUARIA_SRCS
StatsAndAchievements.h
SteamRender.cpp
Strand.cpp
Strand.h
StringBank_gen.h
SubtitlePlayer.cpp
SubtitlePlayer.h

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "CollideEntity.h"
#include "Segmented.h"
#include "Strand.h"
#include "Particles.h"
#include "Scriptable.h"

View file

@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define SEGMENTED_H
#include "../BBGE/Quad.h"
#include "VertexBuffer.h"
class Segmented
{
@ -44,16 +43,5 @@ protected:
std::vector<RenderObject *> segments;
};
class Strand : public RenderObject, public Segmented
{
public:
Strand(const Vector &position, size_t segs, size_t dist=32);
void destroy() OVERRIDE;
protected:
void onUpdate(float dt) OVERRIDE;
void onRender(const RenderState& rs) const OVERRIDE;
DynamicGPUBuffer gpubuf;
};
#endif

View file

@ -18,45 +18,53 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Segmented.h"
#include "Strand.h"
#include "RenderBase.h"
Strand::Strand(const Vector &position, size_t segs, size_t dist)
: RenderObject(), Segmented(dist, dist)
Strand::Strand(const Vector &position, size_t segs, float dist)
: RenderObject()
, points(segs)
, gpubuf(GPUBUF_DYNAMIC | GPUBUF_VERTEXBUF)
, dist(dist)
{
assert(segs);
cull = false;
segments.resize(segs);
for (size_t i = 0; i < segments.size(); i++)
{
// FIXME: This is super costly to waste an entire RenderObject just to store a position.
segments[i] = new RenderObject;
}
initSegments(position);
for (size_t i = 0; i < segs; i++)
points[i] = position;
}
void Strand::destroy()
void Strand::updatePoints()
{
RenderObject::destroy();
for (size_t i = 0; i < segments.size(); i++)
Vector last = position;
const float distsq = sqr(dist);
const size_t N = points.size();
for(size_t i = 0; i < N; ++i)
{
segments[i]->destroy();
delete segments[i];
Vector pt = points[i];
const Vector diff = last - pt;
last = pt;
const float sqrLength = diff.getSquaredLength2D();
if (sqrLength < distsq)
continue;
Vector useDiff = diff;
useDiff.setLength2D(dist);
Vector reallyUseDiff = diff - useDiff;
points[i] = pt + reallyUseDiff;
}
segments.clear();
}
void Strand::onUpdate(float dt)
{
RenderObject::onUpdate(dt);
updateSegments(position);
updatePoints();
const size_t numSegments = segments.size();
const size_t N = points.size();
do
{
const size_t bytes = (numSegments+1) * 6 * sizeof(float);
const size_t bytes = (N+1) * 6 * sizeof(float); // +1 for the initial origin vertex
float *p = (float*)gpubuf.beginWrite(GPUBUFTYPE_VEC2_RGBA, bytes, GPUACCESS_DEFAULT);
// Note: We're rewriting all of the vertex data here.
@ -64,9 +72,9 @@ void Strand::onUpdate(float dt)
// but currently this is to keep buffer layouts simple.
const float factor = 1.0f / 50.0f;
const size_t colorLimit = numSegments<50 ? numSegments : 50;
const size_t colorLimit = N<50 ? N : 50;
const Vector falloff = color * factor;
const float falloffAlpha = 1.0f / float(numSegments);
const float falloffAlpha = 1.0f / float(N);
float a = 1.0f;
Vector c = color;
@ -82,8 +90,8 @@ void Strand::onUpdate(float dt)
size_t i;
for(i = 0; i < colorLimit; ++i)
{
*p++ = segments[i]->position.x;
*p++ = segments[i]->position.y;
*p++ = points[i].x;
*p++ = points[i].y;
*p++ = c.x;
*p++ = c.y;
@ -93,10 +101,10 @@ void Strand::onUpdate(float dt)
c -= falloff;
a -= falloffAlpha;
}
for( ; i < numSegments; ++i)
for( ; i < N; ++i)
{
*p++ = segments[i]->position.x;
*p++ = segments[i]->position.y;
*p++ = points[i].x;
*p++ = points[i].y;
*p++ = 0.0f;
*p++ = 0.0f;
@ -115,5 +123,5 @@ void Strand::onRender(const RenderState& rs) const
glLineWidth(1);
gpubuf.apply();
glDrawArrays(GL_LINE_STRIP, 0, GLsizei(segments.size() + 1));
glDrawArrays(GL_LINE_STRIP, 0, GLsizei(points.size() + 1));
}

24
Aquaria/Strand.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef SEGMENTED_STRAND_H
#define SEGMENTED_STRAND_H
#include "RenderObject.h"
#include "VertexBuffer.h"
class Strand : public RenderObject
{
public:
Strand(const Vector &position, size_t segs, float dist=32);
protected:
void onUpdate(float dt) OVERRIDE;
void onRender(const RenderState& rs) const OVERRIDE;
private:
void updatePoints();
DynamicGPUBuffer gpubuf;
std::vector<Vector> points;
float dist;
};
#endif