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 StatsAndAchievements.h
SteamRender.cpp SteamRender.cpp
Strand.cpp Strand.cpp
Strand.h
StringBank_gen.h StringBank_gen.h
SubtitlePlayer.cpp SubtitlePlayer.cpp
SubtitlePlayer.h SubtitlePlayer.h

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "CollideEntity.h" #include "CollideEntity.h"
#include "Segmented.h" #include "Segmented.h"
#include "Strand.h"
#include "Particles.h" #include "Particles.h"
#include "Scriptable.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 #define SEGMENTED_H
#include "../BBGE/Quad.h" #include "../BBGE/Quad.h"
#include "VertexBuffer.h"
class Segmented class Segmented
{ {
@ -44,16 +43,5 @@ protected:
std::vector<RenderObject *> segments; 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 #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 along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "Segmented.h" #include "Strand.h"
#include "RenderBase.h" #include "RenderBase.h"
Strand::Strand(const Vector &position, size_t segs, size_t dist) Strand::Strand(const Vector &position, size_t segs, float dist)
: RenderObject(), Segmented(dist, dist) : RenderObject()
, points(segs)
, gpubuf(GPUBUF_DYNAMIC | GPUBUF_VERTEXBUF) , gpubuf(GPUBUF_DYNAMIC | GPUBUF_VERTEXBUF)
, dist(dist)
{ {
assert(segs); assert(segs);
cull = false; cull = false;
segments.resize(segs); for (size_t i = 0; i < segs; i++)
for (size_t i = 0; i < segments.size(); i++) points[i] = position;
{
// FIXME: This is super costly to waste an entire RenderObject just to store a position.
segments[i] = new RenderObject;
}
initSegments(position);
} }
void Strand::destroy() void Strand::updatePoints()
{ {
RenderObject::destroy(); Vector last = position;
for (size_t i = 0; i < segments.size(); i++) const float distsq = sqr(dist);
const size_t N = points.size();
for(size_t i = 0; i < N; ++i)
{ {
segments[i]->destroy(); Vector pt = points[i];
delete segments[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) void Strand::onUpdate(float dt)
{ {
RenderObject::onUpdate(dt); RenderObject::onUpdate(dt);
updateSegments(position); updatePoints();
const size_t numSegments = segments.size(); const size_t N = points.size();
do 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); float *p = (float*)gpubuf.beginWrite(GPUBUFTYPE_VEC2_RGBA, bytes, GPUACCESS_DEFAULT);
// Note: We're rewriting all of the vertex data here. // 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. // but currently this is to keep buffer layouts simple.
const float factor = 1.0f / 50.0f; 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 Vector falloff = color * factor;
const float falloffAlpha = 1.0f / float(numSegments); const float falloffAlpha = 1.0f / float(N);
float a = 1.0f; float a = 1.0f;
Vector c = color; Vector c = color;
@ -82,8 +90,8 @@ void Strand::onUpdate(float dt)
size_t i; size_t i;
for(i = 0; i < colorLimit; ++i) for(i = 0; i < colorLimit; ++i)
{ {
*p++ = segments[i]->position.x; *p++ = points[i].x;
*p++ = segments[i]->position.y; *p++ = points[i].y;
*p++ = c.x; *p++ = c.x;
*p++ = c.y; *p++ = c.y;
@ -93,10 +101,10 @@ void Strand::onUpdate(float dt)
c -= falloff; c -= falloff;
a -= falloffAlpha; a -= falloffAlpha;
} }
for( ; i < numSegments; ++i) for( ; i < N; ++i)
{ {
*p++ = segments[i]->position.x; *p++ = points[i].x;
*p++ = segments[i]->position.y; *p++ = points[i].y;
*p++ = 0.0f; *p++ = 0.0f;
*p++ = 0.0f; *p++ = 0.0f;
@ -115,5 +123,5 @@ void Strand::onRender(const RenderState& rs) const
glLineWidth(1); glLineWidth(1);
gpubuf.apply(); 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