Files
veejay/veejay-current/libgoom/flying_stars_fx.c
Niels Elburg 20ba7effd7 added xmms visualization plugin Goom, libgoom, added 2 new effects , color map and goom fx to veejay-current
git-svn-id: svn://code.dyne.org/veejay/trunk@686 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
2006-11-14 00:59:48 +00:00

315 lines
7.2 KiB
C

#include "goom_fx.h"
#include "goom_plugin_info.h"
#include "goom_tools.h"
#include "mathtools.h"
/* TODO:-- FAIRE PROPREMENT... BOAH... */
#define NCOL 15
/*static const int colval[] = {
0xfdf6f5,
0xfae4e4,
0xf7d1d1,
0xf3b6b5,
0xefa2a2,
0xec9190,
0xea8282,
0xe87575,
0xe46060,
0xe14b4c,
0xde3b3b,
0xdc2d2f,
0xd92726,
0xd81619,
0xd50c09,
0
};
*/
static const int colval[] = {
0x1416181a,
0x1419181a,
0x141f181a,
0x1426181a,
0x142a181a,
0x142f181a,
0x1436181a,
0x142f1819,
0x14261615,
0x13201411,
0x111a100a,
0x0c180508,
0x08100304,
0x00050101,
0x0
};
/* The different modes of the visual FX.
* Put this values on fx_mode */
#define FIREWORKS_FX 0
#define RAIN_FX 1
#define FOUNTAIN_FX 2
#define LAST_FX 3
typedef struct _FS_STAR {
float x,y;
float vx,vy;
float ax,ay;
float age,vage;
} Star;
typedef struct _FS_DATA{
int fx_mode;
int nbStars;
int maxStars;
Star *stars;
float min_age;
float max_age;
PluginParam min_age_p;
PluginParam max_age_p;
PluginParam nbStars_p;
PluginParam nbStars_limit_p;
PluginParam fx_mode_p;
PluginParameters params;
} FSData;
static void fs_init(VisualFX *_this, PluginInfo *info) {
FSData *data;
data = (FSData*)malloc(sizeof(FSData));
data->fx_mode = FIREWORKS_FX;
data->maxStars = 4096;
data->stars = (Star*)malloc(data->maxStars * sizeof(Star));
data->nbStars = 0;
data->max_age_p = secure_i_param ("Fireworks Smallest Bombs");
IVAL(data->max_age_p) = 80;
IMIN(data->max_age_p) = 0;
IMAX(data->max_age_p) = 100;
ISTEP(data->max_age_p) = 1;
data->min_age_p = secure_i_param ("Fireworks Largest Bombs");
IVAL(data->min_age_p) = 99;
IMIN(data->min_age_p) = 0;
IMAX(data->min_age_p) = 100;
ISTEP(data->min_age_p) = 1;
data->nbStars_limit_p = secure_i_param ("Max Number of Particules");
IVAL(data->nbStars_limit_p) = 512;
IMIN(data->nbStars_limit_p) = 0;
IMAX(data->nbStars_limit_p) = data->maxStars;
ISTEP(data->nbStars_limit_p) = 64;
data->fx_mode_p = secure_i_param ("FX Mode");
IVAL(data->fx_mode_p) = data->fx_mode;
IMIN(data->fx_mode_p) = 1;
IMAX(data->fx_mode_p) = 3;
ISTEP(data->fx_mode_p) = 1;
data->nbStars_p = secure_f_feedback ("Number of Particules (% of Max)");
data->params = plugin_parameters ("Particule System", 7);
data->params.params[0] = &data->fx_mode_p;
data->params.params[1] = &data->nbStars_limit_p;
data->params.params[2] = 0;
data->params.params[3] = &data->min_age_p;
data->params.params[4] = &data->max_age_p;
data->params.params[5] = 0;
data->params.params[6] = &data->nbStars_p;
_this->params = &data->params;
_this->fx_data = (void*)data;
}
static void fs_free(VisualFX *_this) {
free (_this->fx_data);
}
/**
* Cree une nouvelle 'bombe', c'est a dire une particule appartenant a une fusee d'artifice.
*/
static void addABomb (FSData *fs, int mx, int my, float radius, float vage, float gravity, PluginInfo *info) {
int i = fs->nbStars;
float ro;
int theta;
if (fs->nbStars >= fs->maxStars)
return;
fs->nbStars++;
fs->stars[i].x = mx;
fs->stars[i].y = my;
ro = radius * (float)goom_irand(info->gRandom,100) / 100.0f;
ro *= (float)goom_irand(info->gRandom,100)/100.0f + 1.0f;
theta = goom_irand(info->gRandom,256);
fs->stars[i].vx = ro * cos256[theta];
fs->stars[i].vy = -0.2f + ro * sin256[theta];
fs->stars[i].ax = 0;
fs->stars[i].ay = gravity;
fs->stars[i].age = 0;
if (vage < fs->min_age)
vage=fs->min_age;
fs->stars[i].vage = vage;
}
/**
* Met a jour la position et vitesse d'une particule.
*/
static void updateStar (Star *s) {
s->x+=s->vx;
s->y+=s->vy;
s->vx+=s->ax;
s->vy+=s->ay;
s->age+=s->vage;
}
/**
* Ajoute de nouvelles particules au moment d'un evenement sonore.
*/
static void fs_sound_event_occured(VisualFX *_this, PluginInfo *info) {
FSData *data = (FSData*)_this->fx_data;
int i;
int max = (int)((1.0f+info->sound.goomPower)*goom_irand(info->gRandom,150)) + 100;
float radius = (1.0f+info->sound.goomPower) * (float)(goom_irand(info->gRandom,150)+50)/300;
int mx;
int my;
float vage, gravity = 0.02f;
switch (data->fx_mode) {
case FIREWORKS_FX:
{
double dx,dy;
do {
mx = goom_irand(info->gRandom,info->screen.width);
my = goom_irand(info->gRandom,info->screen.height);
dx = (mx - info->screen.width/2);
dy = (my - info->screen.height/2);
} while (dx*dx + dy*dy < (info->screen.height/2)*(info->screen.height/2));
vage = data->max_age * (1.0f - info->sound.goomPower);
}
break;
case RAIN_FX:
mx = goom_irand(info->gRandom,info->screen.width);
if (mx > info->screen.width/2)
mx = info->screen.width;
else
mx = 0;
my = -(info->screen.height/3)-goom_irand(info->gRandom,info->screen.width/3);
radius *= 1.5;
vage = 0.002f;
break;
case FOUNTAIN_FX:
my = info->screen.height+2;
vage = 0.001f;
radius += 1.0f;
mx = info->screen.width / 2;
gravity = 0.04f;
break;
default:
return;
/* my = i R A N D (info->screen.height); vage = 0.01f; */
}
radius *= info->screen.height / 200.0f; /* why 200 ? because the FX was developped on 320x200 */
max *= info->screen.height / 200.0f;
if (info->sound.timeSinceLastBigGoom < 1) {
radius *= 1.5;
max *= 2;
}
for (i=0;i<max;++i)
addABomb (data,mx,my,radius,vage,gravity,info);
}
/**
* Main methode of the FX.
*/
static void fs_apply(VisualFX *_this, Pixel *src, Pixel *dest, PluginInfo *info) {
int i;
int col;
FSData *data = (FSData*)_this->fx_data;
/* Get the new parameters values */
data->min_age = 1.0f - (float)IVAL(data->min_age_p)/100.0f;
data->max_age = 1.0f - (float)IVAL(data->max_age_p)/100.0f;
FVAL(data->nbStars_p) = (float)data->nbStars / (float)data->maxStars;
data->nbStars_p.change_listener(&data->nbStars_p);
data->maxStars = IVAL(data->nbStars_limit_p);
data->fx_mode = IVAL(data->fx_mode_p);
/* look for events */
if (info->sound.timeSinceLastGoom < 1) {
fs_sound_event_occured(_this, info);
if (goom_irand(info->gRandom,20)==1) {
IVAL(data->fx_mode_p) = goom_irand(info->gRandom,(LAST_FX*3));
data->fx_mode_p.change_listener(&data->fx_mode_p);
}
}
/* update particules */
for (i=0;i<data->nbStars;++i) {
updateStar(&data->stars[i]);
/* dead particule */
if (data->stars[i].age>=NCOL)
continue;
/* choose the color of the particule */
col = colval[(int)data->stars[i].age];
/* draws the particule */
info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y,
(int)(data->stars[i].x-data->stars[i].vx*6),
(int)(data->stars[i].y-data->stars[i].vy*6),
col,
(int)info->screen.width, (int)info->screen.height);
info->methods.draw_line(dest,(int)data->stars[i].x,(int)data->stars[i].y,
(int)(data->stars[i].x-data->stars[i].vx*2),
(int)(data->stars[i].y-data->stars[i].vy*2),
col,
(int)info->screen.width, (int)info->screen.height);
}
/* look for dead particules */
for (i=0;i<data->nbStars;) {
if ((data->stars[i].x > info->screen.width + 64)
||((data->stars[i].vy>=0)&&(data->stars[i].y - 16*data->stars[i].vy > info->screen.height))
||(data->stars[i].x < -64)
||(data->stars[i].age>=NCOL)) {
data->stars[i] = data->stars[data->nbStars-1];
data->nbStars--;
}
else ++i;
}
}
VisualFX flying_star_create(void) {
VisualFX vfx = {
init: fs_init,
free: fs_free,
apply: fs_apply,
fx_data: 0
};
return vfx;
}