diff --git a/src/modules/graphics/opengl/ParticleSystem.cpp b/src/modules/graphics/opengl/ParticleSystem.cpp index 49f4cf087..8c1dd3484 100644 --- a/src/modules/graphics/opengl/ParticleSystem.cpp +++ b/src/modules/graphics/opengl/ParticleSystem.cpp @@ -146,12 +146,16 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p) , offsetX(p.offsetX) , offsetY(p.offsetY) , colors(p.colors) + , quads(p.quads) , relativeRotation(p.relativeRotation) { setBufferSize(maxParticles); if (texture != nullptr) texture->retain(); + + for (Quad *quad : quads) + quad->retain(); } ParticleSystem::~ParticleSystem() @@ -159,6 +163,9 @@ ParticleSystem::~ParticleSystem() if (texture != nullptr) texture->release(); + for (Quad *quad : quads) + quad->release(); + deleteBuffers(); } @@ -305,6 +312,8 @@ void ParticleSystem::initParticle(Particle *p, float t) p->angle += atan2f(p->velocity.y, p->velocity.x); p->color = colors[0]; + + p->quadIndex = 0; } void ParticleSystem::insertTop(Particle *p) @@ -721,6 +730,30 @@ std::vector ParticleSystem::getColor() const return ncolors; } +void ParticleSystem::setQuads(const std::vector &newQuads) +{ + for (Quad *quad : newQuads) + quad->retain(); + + for (Quad *quad : quads) + quad->release(); + + quads = newQuads; +} + +void ParticleSystem::setQuads() +{ + for (Quad *quad : quads) + quad->release(); + + quads.clear(); +} + +const std::vector &ParticleSystem::getQuads() const +{ + return quads; +} + void ParticleSystem::setRelativeRotation(bool enable) { relativeRotation = enable; @@ -820,9 +853,14 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo Vertex *pVerts = particleVerts; Particle *p = pHead; + bool useQuads = !quads.empty(); + // set the vertex data for each particle (transformation, texcoords, color) while (p) { + if (useQuads) + textureVerts = quads[p->quadIndex]->getVertices(); + // particle vertices are image vertices transformed by particle information t.setTransformation(p->position[0], p->position[1], p->angle, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f); t.transform(pVerts, textureVerts, 4); @@ -948,6 +986,15 @@ void ParticleSystem::update(float dt) s -= (float)i; // 0 <= s <= 1 p->color = colors[i] * (1.0f - s) + colors[k] * s; + // Update the quad index. + k = quads.size(); + if (k > 0) + { + s = t * (float) k; // [0:numquads-1] (clamped below) + i = (s > 0.0f) ? (size_t) s : 0; + p->quadIndex = (i < k) ? i : k - 1; + } + // Next particle. p = p->next; } diff --git a/src/modules/graphics/opengl/ParticleSystem.h b/src/modules/graphics/opengl/ParticleSystem.h index 96e6f8d5a..6f9e8750f 100644 --- a/src/modules/graphics/opengl/ParticleSystem.h +++ b/src/modules/graphics/opengl/ParticleSystem.h @@ -27,6 +27,7 @@ #include "common/Vector.h" #include "graphics/Drawable.h" #include "graphics/Color.h" +#include "graphics/Quad.h" #include "Texture.h" // STL @@ -421,6 +422,17 @@ public: **/ std::vector getColor() const; + /** + * Sets a list of Quads to use for particles over their lifetime. + **/ + void setQuads(const std::vector &newQuads); + void setQuads(); + + /** + * Gets the Quads used when drawing the particles. + **/ + const std::vector &getQuads() const; + /** * sets whether particle angles & rotations are relative to their velocities. **/ @@ -531,6 +543,8 @@ protected: float spinEnd; Colorf color; + + int quadIndex; }; // Pointer to the beginning of the allocated memory. @@ -625,6 +639,9 @@ protected: // Color. std::vector colors; + // Quads. + std::vector quads; + bool relativeRotation; void createBuffers(size_t size); diff --git a/src/modules/graphics/opengl/wrap_ParticleSystem.cpp b/src/modules/graphics/opengl/wrap_ParticleSystem.cpp index f813774ae..72bd113f7 100644 --- a/src/modules/graphics/opengl/wrap_ParticleSystem.cpp +++ b/src/modules/graphics/opengl/wrap_ParticleSystem.cpp @@ -569,6 +569,53 @@ int w_ParticleSystem_getColors(lua_State *L) return colors.size(); } +int w_ParticleSystem_setQuads(lua_State *L) +{ + ParticleSystem *t = luax_checkparticlesystem(L, 1); + std::vector quads; + + if (lua_istable(L, 2)) + { + for (size_t i = 1; i <= lua_objlen(L, 2); i++) + { + lua_rawgeti(L, 2, i); + + Quad *q = luax_checktype(L, -1, "Quad", GRAPHICS_QUAD_T); + quads.push_back(q); + + lua_pop(L, 1); + } + } + else + { + for (int i = 2; i <= lua_gettop(L); i++) + { + Quad *q = luax_checktype(L, i, "Quad", GRAPHICS_QUAD_T); + quads.push_back(q); + } + } + + t->setQuads(quads); + return 0; +} + +int w_ParticleSystem_getQuads(lua_State *L) +{ + ParticleSystem *t = luax_checkparticlesystem(L, 1); + const std::vector quads = t->getQuads(); + + lua_createtable(L, (int) quads.size(), 0); + + for (size_t i = 0; i < quads.size(); i++) + { + quads[i]->retain(); + luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quads[i]); + lua_rawseti(L, -2, i + 1); + } + + return 1; +} + int w_ParticleSystem_setRelativeRotation(lua_State *L) { ParticleSystem *t = luax_checkparticlesystem(L, 1); @@ -699,6 +746,8 @@ static const luaL_Reg functions[] = { "getSpinVariation", w_ParticleSystem_getSpinVariation }, { "setColors", w_ParticleSystem_setColors }, { "getColors", w_ParticleSystem_getColors }, + { "setQuads", w_ParticleSystem_setQuads }, + { "getQuads", w_ParticleSystem_getQuads }, { "setOffset", w_ParticleSystem_setOffset }, { "getOffset", w_ParticleSystem_getOffset }, { "setRelativeRotation", w_ParticleSystem_setRelativeRotation }, diff --git a/src/modules/graphics/opengl/wrap_ParticleSystem.h b/src/modules/graphics/opengl/wrap_ParticleSystem.h index b3c96a54f..f1f788388 100644 --- a/src/modules/graphics/opengl/wrap_ParticleSystem.h +++ b/src/modules/graphics/opengl/wrap_ParticleSystem.h @@ -75,6 +75,8 @@ int w_ParticleSystem_setSpinVariation(lua_State *L); int w_ParticleSystem_getSpinVariation(lua_State *L); int w_ParticleSystem_setColors(lua_State *L); int w_ParticleSystem_getColors(lua_State *L); +int w_ParticleSystem_setQuads(lua_State *L); +int w_ParticleSystem_getQuads(lua_State *L); int w_ParticleSystem_setOffset(lua_State *L); int w_ParticleSystem_getOffset(lua_State *L); int w_ParticleSystem_setRelativeRotation(lua_State *L);