mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-03 16:09:39 +00:00
361 lines
8.7 KiB
C
361 lines
8.7 KiB
C
/* Goom Project
|
|
* Copyright (C) <2003> iOS-Software
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
#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;
|
|
|
|
secure_i_param (&data->max_age_p, "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;
|
|
|
|
secure_i_param (&data->min_age_p, "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;
|
|
|
|
secure_i_param (&data->nbStars_limit_p, "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;
|
|
|
|
secure_i_param (&data->fx_mode_p, "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;
|
|
|
|
secure_f_feedback (&data->nbStars_p, "Number of Particules (% of Max)");
|
|
|
|
plugin_parameters (&data->params, "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)
|
|
{
|
|
FSData *data = (FSData *) _this->fx_data;
|
|
|
|
goom_plugin_parameters_free (&data->params);
|
|
|
|
free (data->stars);
|
|
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;
|
|
}
|
|
}
|
|
|
|
void
|
|
flying_star_create (VisualFX * vfx)
|
|
{
|
|
vfx->init = fs_init;
|
|
vfx->free = fs_free;
|
|
vfx->apply = fs_apply;
|
|
vfx->fx_data = NULL;
|
|
vfx->params = NULL;
|
|
}
|