Change particle system to accept an arbitrary number of colors and sizes to inerpolate.

API changes:
- ParticleSystem:setSize(min, max, var) -> ParticleSystem:setSizes(s0, ..., sN)
  !! ParticleSystem:setSize() drops variation parameter !!
- ParticleSystem:setColor([color1], [color2]) -> ParticleSystem:setColor([color1], ..., [colorN])

--HG--
branch : minor
This commit is contained in:
vrld
2011-04-06 21:24:09 +02:00
parent aa5eb4380d
commit 2425ea9979
4 changed files with 93 additions and 92 deletions
+50 -44
View File
@@ -25,7 +25,6 @@
#include <SDL_opengl.h>
#include <cmath>
#include <cstdlib>
#include <cstring>
namespace love
{
@@ -34,6 +33,13 @@ namespace graphics
namespace opengl
{
namespace
{
Colorf colorToFloat(const Color& c) {
return Colorf( (GLfloat)c.r/255.0f, (GLfloat)c.g/255.0f, (GLfloat)c.b/255.0f, (GLfloat)c.a/255.0f );
}
}
float calculate_variation(float inner, float outer, float var)
{
float low = inner - (outer/2.0f)*var;
@@ -48,14 +54,14 @@ namespace opengl
direction(0), spread(0), relative(false), speedMin(0), speedMax(0), gravityMin(0),
gravityMax(0), radialAccelerationMin(0), radialAccelerationMax(0),
tangentialAccelerationMin(0), tangentialAccelerationMax(0),
sizeStart(1), sizeEnd(1), sizeVariation(0), rotationMin(0), rotationMax(0),
sizeVariation(0), rotationMin(0), rotationMax(0),
spinStart(0), spinEnd(0), spinVariation(0), offsetX(sprite->getWidth()*0.5f),
offsetY(sprite->getHeight()*0.5f)
{
this->sprite = sprite;
sprite->retain();
memset(colorStart, 255, 4);
memset(colorEnd, 255, 4);
sizes.push_back(1.0f);
colors.push_back( Colorf(1.0f, 1.0f, 1.0f, 1.0f) );
setBufferSize(buffer);
}
@@ -107,9 +113,9 @@ namespace opengl
max = tangentialAccelerationMax;
pLast->tangentialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
pLast->sizeStart = calculate_variation(sizeStart, sizeEnd, sizeVariation);
pLast->sizeEnd = calculate_variation(sizeEnd, sizeStart, sizeVariation);
pLast->size = pLast->sizeStart;
pLast->sizeOffset = (rand() / (float(RAND_MAX)+1)) * sizeVariation; // time offset for size change
pLast->sizeIntervalSize = (1.0 - (rand() / (float(RAND_MAX)+1)) * sizeVariation) - pLast->sizeOffset;
pLast->size = sizes[(size_t)(pLast->sizeOffset - .5f) * (sizes.size() - 1)];
min = rotationMin;
max = rotationMax;
@@ -117,10 +123,7 @@ namespace opengl
pLast->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
pLast->rotation = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;;
pLast->color[0] = (float)colorStart[0] / 255;
pLast->color[1] = (float)colorStart[1] / 255;
pLast->color[2] = (float)colorStart[2] / 255;
pLast->color[3] = (float)colorStart[3] / 255;
pLast->color = colors[0];
pLast++;
}
@@ -237,20 +240,13 @@ namespace opengl
void ParticleSystem::setSize(float size)
{
sizeStart = size;
sizeEnd = size;
sizes.resize(1);
sizes[0] = size;
}
void ParticleSystem::setSize(float start, float end)
void ParticleSystem::setSize(const std::vector<float>& newSizes, float variation)
{
sizeStart = start;
sizeEnd = end;
}
void ParticleSystem::setSize(float start, float end, float variation)
{
sizeStart = start;
sizeEnd = end;
sizes = newSizes;
sizeVariation = variation;
}
@@ -294,16 +290,17 @@ namespace opengl
spinVariation = variation;
}
void ParticleSystem::setColor(unsigned char * color)
void ParticleSystem::setColor(const Color& color)
{
memcpy(colorStart, color, 4);
memcpy(colorEnd, color, 4);
colors.resize(1);
colors[0] = colorToFloat(color);
}
void ParticleSystem::setColor(unsigned char * start, unsigned char * end)
void ParticleSystem::setColor(const std::vector<Color>& newColors)
{
memcpy(colorStart, start, 4);
memcpy(colorEnd, end, 4);
colors.resize( newColors.size() );
for (size_t i = 0; i < newColors.size(); ++i)
colors[i] = colorToFloat( newColors[i] );
}
void ParticleSystem::setOffset(float x, float y)
@@ -403,12 +400,8 @@ namespace opengl
{
glPushMatrix();
glColor4f(p->color[0],p->color[1],p->color[2],p->color[3]);
glTranslatef(p->position[0],p->position[1],0.0f);
glRotatef(LOVE_TODEG(p->rotation), 0.0f, 0.0f, 1.0f); // rad * (180 / pi)
glScalef(p->size,p->size,1.0f);
glTranslatef(-offsetX,-offsetY,0.0f);
sprite->draw(0,0, 0, 1, 1, 0, 0);
glColor4f(p->color.r, p->color.g, p->color.b, p->color.a);
sprite->draw(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY);
glPopMatrix();
p++;
@@ -481,19 +474,32 @@ namespace opengl
p->position[0] = ppos.getX();
p->position[1] = ppos.getY();
const float t = p->life / p->lifetime;
// Change size.
p->size = p->sizeEnd - ((p->sizeEnd - p->sizeStart) * t);
const float t = 1.0f - p->life / p->lifetime;
// Rotate.
p->rotation += (p->spinStart*(1-t) + p->spinEnd*t)*dt;
p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t)*dt;
// Update color.
p->color[0] = (float)(colorEnd[0]*(1.0f-t) + colorStart[0] * t)/255.0f;
p->color[1] = (float)(colorEnd[1]*(1.0f-t) + colorStart[1] * t)/255.0f;
p->color[2] = (float)(colorEnd[2]*(1.0f-t) + colorStart[2] * t)/255.0f;
p->color[3] = (float)(colorEnd[3]*(1.0f-t) + colorStart[3] * t)/255.0f;
// Change size according to given intervals:
// i = 0 1 2 3 n-1
// |-------|-------|------|--- ... ---|
// t = 0 1/(n-1) 3/(n-1) 1
//
// `s' is the interpolation variable scaled to the current
// interval width, e.g. if n = 5 and t = 0.3, then the current
// indices are 1,2 and s = 0.3 - 0.25 = 0.05
float s = p->sizeOffset + t * p->sizeIntervalSize; // size variation
s *= (float)(sizes.size() - 1); // 0 <= s < sizes.size()
size_t i = (size_t)s;
size_t k = (i == sizes.size() - 1) ? i : i + 1; // boundary check (prevents failing on t = 1.0f)
s -= (float)i; // transpose s to be in interval [0:1]: i <= s < i + 1 ~> 0 <= s < 1
p->size = sizes[i] * (1.0f - t) + sizes[k] * t;
// Update color according to given intervals (as above)
s = t * (float)(colors.size() - 1);
i = (size_t)s;
k = (i == colors.size() - 1) ? i : i + 1;
s -= (float)i; // 0 <= s <= 1
p->color = colors[i] * (1.0f - s) + colors[k] * s;
// Next particle.
p++;
+12 -21
View File
@@ -26,7 +26,9 @@
#include <common/math.h>
#include <common/Vector.h>
#include <graphics/Drawable.h>
#include <graphics/Color.h>
#include "Image.h"
#include <vector>
namespace love
{
@@ -50,14 +52,14 @@ namespace opengl
float tangentialAcceleration;
float size;
float sizeStart;
float sizeEnd;
float sizeOffset;
float sizeIntervalSize;
float rotation;
float spinStart;
float spinEnd;
float color[4];
Colorf color;
};
/**
@@ -127,8 +129,7 @@ namespace opengl
float tangentialAccelerationMax;
// Size.
float sizeStart;
float sizeEnd;
std::vector<float> sizes;
float sizeVariation;
// Rotation
@@ -145,8 +146,7 @@ namespace opengl
float offsetY;
// Color.
unsigned char colorStart[4];
unsigned char colorEnd[4];
std::vector<Colorf> colors;
void add();
void remove(particle * p);
@@ -278,20 +278,12 @@ namespace opengl
**/
void setSize(float size);
/**
* Sets the size of the sprite upon creation and upon death (1.0 being the default size).
* @param start The size of the sprite upon creation
* @param end The size of the sprite upon death.
**/
void setSize(float start, float end);
/**
* Sets the size of the sprite upon creation and upon death (1.0 being the default size) and any variation.
* @param start The size of the sprite upon creation
* @param end The size of the sprite upon death.
* @param newSizes Array of sizes
* @param variation The amount of variation on the starting size (0 being no variation and 1.0 a random size between start and end).
**/
void setSize(float start, float end, float variation);
void setSize(const std::vector<float>& newSizes, float variation = 0.0f);
/**
* Sets the amount of variation to the sprite's beginning size (0 being no variation and 1.0 a random size between start and end).
@@ -343,7 +335,7 @@ namespace opengl
* Sets the color of the particles.
* @param color The color.
**/
void setColor(unsigned char * color);
void setColor(const Color& color);
/**
* Sets the particles' offsets for rotation.
@@ -354,10 +346,9 @@ namespace opengl
/**
* Sets the color of the particles.
* @param start The color of the particle when created.
* @param end The color of the particle upon death.
* @param newColors Array of colors
**/
void setColor(unsigned char * start, unsigned char * end);
void setColor(const std::vector<Color>& newColors);
/**
* Returns the x-coordinate of the emitter's position.
@@ -143,13 +143,19 @@ namespace opengl
return 0;
}
int w_ParticleSystem_setSize(lua_State * L)
int w_ParticleSystem_setSizes(lua_State * L)
{
ParticleSystem * t = luax_checkparticlesystem(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
float arg2 = (float)luaL_optnumber(L, 3, arg1);
float arg3 = (float)luaL_optnumber(L, 4, 0);
t->setSize(arg1, arg2, arg3);
size_t nSizes = lua_gettop(L) - 1;
if (nSizes == 1) {
t->setSize(luaL_checknumber(L, 2));
} else {
std::vector<float> sizes(nSizes);
for (size_t i = 0; i < nSizes; ++i)
sizes[i] = luaL_checknumber(L, 1 + i + 1);
t->setSize(sizes);
}
return 0;
}
@@ -188,28 +194,26 @@ namespace opengl
return 0;
}
int w_ParticleSystem_setColor(lua_State * L)
int w_ParticleSystem_setColors(lua_State * L)
{
ParticleSystem * t = luax_checkparticlesystem(L, 1);
unsigned char start[4];
size_t nColors = (lua_gettop(L) - 1) / 4;
start[0] = (unsigned char)luaL_checkint(L, 2);
start[1] = (unsigned char)luaL_checkint(L, 3);
start[2] = (unsigned char)luaL_checkint(L, 4);
start[3] = (unsigned char)luaL_checkint(L, 5);
if(lua_gettop(L) > 5)
{
unsigned char end[4];
end[0] = (unsigned char)luaL_checkint(L, 6);
end[1] = (unsigned char)luaL_checkint(L, 7);
end[2] = (unsigned char)luaL_checkint(L, 8);
end[3] = (unsigned char)luaL_checkint(L, 9);
t->setColor(start, end);
if (nColors == 1) {
t->setColor(Color(luaL_checkint(L,2),
luaL_checkint(L,3),
luaL_checkint(L,4),
luaL_checkint(L,5)));
} else {
std::vector<Color> colors(nColors);
for (size_t i = 0; i < nColors; ++i) {
colors[i] = Color(luaL_checkint(L, 1 + i*4 + 1),
luaL_checkint(L, 1 + i*4 + 2),
luaL_checkint(L, 1 + i*4 + 3),
luaL_checkint(L, 1 + i*4 + 4));
}
t->setColor(colors);
}
else
t->setColor(start);
return 0;
}
@@ -343,12 +347,12 @@ namespace opengl
{ "setGravity", w_ParticleSystem_setGravity },
{ "setRadialAcceleration", w_ParticleSystem_setRadialAcceleration },
{ "setTangentialAcceleration", w_ParticleSystem_setTangentialAcceleration },
{ "setSize", w_ParticleSystem_setSize },
{ "setSizes", w_ParticleSystem_setSizes },
{ "setSizeVariation", w_ParticleSystem_setSizeVariation },
{ "setRotation", w_ParticleSystem_setRotation },
{ "setSpin", w_ParticleSystem_setSpin },
{ "setSpinVariation", w_ParticleSystem_setSpinVariation },
{ "setColor", w_ParticleSystem_setColor },
{ "setColors", w_ParticleSystem_setColors },
{ "setOffset", w_ParticleSystem_setOffset },
{ "getX", w_ParticleSystem_getX },
{ "getY", w_ParticleSystem_getY },
@@ -46,12 +46,12 @@ namespace opengl
int w_ParticleSystem_setGravity(lua_State * L);
int w_ParticleSystem_setRadialAcceleration(lua_State * L);
int w_ParticleSystem_setTangentialAcceleration(lua_State * L);
int w_ParticleSystem_setSize(lua_State * L);
int w_ParticleSystem_setSizes(lua_State * L);
int w_ParticleSystem_setSizeVariation(lua_State * L);
int w_ParticleSystem_setRotation(lua_State * L);
int w_ParticleSystem_setSpin(lua_State * L);
int w_ParticleSystem_setSpinVariation(lua_State * L);
int w_ParticleSystem_setColor(lua_State * L);
int w_ParticleSystem_setColors(lua_State * L);
int w_ParticleSystem_setOffset(lua_State * L);
int w_ParticleSystem_getX(lua_State * L);
int w_ParticleSystem_getY(lua_State * L);