Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / gst / goom / flying_stars_fx.c
1 /* Goom Project
2  * Copyright (C) <2003> iOS-Software
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "goom_fx.h"
20 #include "goom_plugin_info.h"
21 #include "goom_tools.h"
22
23 #include "mathtools.h"
24
25 /* TODO:-- FAIRE PROPREMENT... BOAH... */
26 #define NCOL 15
27
28 /*static const int colval[] = {
29 0xfdf6f5,
30 0xfae4e4,
31 0xf7d1d1,
32 0xf3b6b5,
33 0xefa2a2,
34 0xec9190,
35 0xea8282,
36 0xe87575,
37 0xe46060,
38 0xe14b4c,
39 0xde3b3b,
40 0xdc2d2f,
41 0xd92726,
42 0xd81619,
43 0xd50c09,
44 0
45 };
46 */
47 static const int colval[] = {
48   0x1416181a,
49   0x1419181a,
50   0x141f181a,
51   0x1426181a,
52   0x142a181a,
53   0x142f181a,
54   0x1436181a,
55   0x142f1819,
56   0x14261615,
57   0x13201411,
58   0x111a100a,
59   0x0c180508,
60   0x08100304,
61   0x00050101,
62   0x0
63 };
64
65
66 /* The different modes of the visual FX.
67  * Put this values on fx_mode */
68 #define FIREWORKS_FX 0
69 #define RAIN_FX 1
70 #define FOUNTAIN_FX 2
71 #define LAST_FX 3
72
73 typedef struct _FS_STAR
74 {
75   float x, y;
76   float vx, vy;
77   float ax, ay;
78   float age, vage;
79 } Star;
80
81 typedef struct _FS_DATA
82 {
83
84   int fx_mode;
85   int nbStars;
86
87   int maxStars;
88   Star *stars;
89
90   float min_age;
91   float max_age;
92
93   PluginParam min_age_p;
94   PluginParam max_age_p;
95   PluginParam nbStars_p;
96   PluginParam nbStars_limit_p;
97   PluginParam fx_mode_p;
98
99   PluginParameters params;
100 } FSData;
101
102 static void
103 fs_init (VisualFX * _this, PluginInfo * info)
104 {
105
106   FSData *data;
107
108   data = (FSData *) malloc (sizeof (FSData));
109
110   data->fx_mode = FIREWORKS_FX;
111   data->maxStars = 4096;
112   data->stars = (Star *) malloc (data->maxStars * sizeof (Star));
113   data->nbStars = 0;
114
115   secure_i_param (&data->max_age_p, "Fireworks Smallest Bombs");
116   IVAL (data->max_age_p) = 80;
117   IMIN (data->max_age_p) = 0;
118   IMAX (data->max_age_p) = 100;
119   ISTEP (data->max_age_p) = 1;
120
121   secure_i_param (&data->min_age_p, "Fireworks Largest Bombs");
122   IVAL (data->min_age_p) = 99;
123   IMIN (data->min_age_p) = 0;
124   IMAX (data->min_age_p) = 100;
125   ISTEP (data->min_age_p) = 1;
126
127   secure_i_param (&data->nbStars_limit_p, "Max Number of Particules");
128   IVAL (data->nbStars_limit_p) = 512;
129   IMIN (data->nbStars_limit_p) = 0;
130   IMAX (data->nbStars_limit_p) = data->maxStars;
131   ISTEP (data->nbStars_limit_p) = 64;
132
133   secure_i_param (&data->fx_mode_p, "FX Mode");
134   IVAL (data->fx_mode_p) = data->fx_mode;
135   IMIN (data->fx_mode_p) = 1;
136   IMAX (data->fx_mode_p) = 3;
137   ISTEP (data->fx_mode_p) = 1;
138
139   secure_f_feedback (&data->nbStars_p, "Number of Particules (% of Max)");
140
141   plugin_parameters (&data->params, "Particule System", 7);
142   data->params.params[0] = &data->fx_mode_p;
143   data->params.params[1] = &data->nbStars_limit_p;
144   data->params.params[2] = 0;
145   data->params.params[3] = &data->min_age_p;
146   data->params.params[4] = &data->max_age_p;
147   data->params.params[5] = 0;
148   data->params.params[6] = &data->nbStars_p;
149
150   _this->params = &data->params;
151   _this->fx_data = (void *) data;
152 }
153
154 static void
155 fs_free (VisualFX * _this)
156 {
157   FSData *data = (FSData *) _this->fx_data;
158
159   goom_plugin_parameters_free (&data->params);
160
161   free (data->stars);
162   free (_this->fx_data);
163 }
164
165
166 /**
167  * Cree une nouvelle 'bombe', c'est a dire une particule appartenant a une fusee d'artifice.
168  */
169 static void
170 addABomb (FSData * fs, int mx, int my, float radius, float vage, float gravity,
171     PluginInfo * info)
172 {
173
174   int i = fs->nbStars;
175   float ro;
176   int theta;
177
178   if (fs->nbStars >= fs->maxStars)
179     return;
180   fs->nbStars++;
181
182   fs->stars[i].x = mx;
183   fs->stars[i].y = my;
184
185   ro = radius * (float) goom_irand (info->gRandom, 100) / 100.0f;
186   ro *= (float) goom_irand (info->gRandom, 100) / 100.0f + 1.0f;
187   theta = goom_irand (info->gRandom, 256);
188
189   fs->stars[i].vx = ro * cos256[theta];
190   fs->stars[i].vy = -0.2f + ro * sin256[theta];
191
192   fs->stars[i].ax = 0;
193   fs->stars[i].ay = gravity;
194
195   fs->stars[i].age = 0;
196   if (vage < fs->min_age)
197     vage = fs->min_age;
198   fs->stars[i].vage = vage;
199 }
200
201
202 /**
203  * Met a jour la position et vitesse d'une particule.
204  */
205 static void
206 updateStar (Star * s)
207 {
208   s->x += s->vx;
209   s->y += s->vy;
210   s->vx += s->ax;
211   s->vy += s->ay;
212   s->age += s->vage;
213 }
214
215
216 /**
217  * Ajoute de nouvelles particules au moment d'un evenement sonore.
218  */
219 static void
220 fs_sound_event_occured (VisualFX * _this, PluginInfo * info)
221 {
222
223   FSData *data = (FSData *) _this->fx_data;
224   int i;
225
226   int max = (int) ((1.0f + info->sound.goomPower) * goom_irand (info->gRandom,
227           150)) + 100;
228   float radius =
229       (1.0f + info->sound.goomPower) * (float) (goom_irand (info->gRandom,
230           150) + 50) / 300;
231   int mx;
232   int my;
233   float vage, gravity = 0.02f;
234
235   switch (data->fx_mode) {
236     case FIREWORKS_FX:
237     {
238       double dx, dy;
239
240       do {
241         mx = goom_irand (info->gRandom, info->screen.width);
242         my = goom_irand (info->gRandom, info->screen.height);
243         dx = (mx - info->screen.width / 2);
244         dy = (my - info->screen.height / 2);
245       } while (dx * dx + dy * dy <
246           (info->screen.height / 2) * (info->screen.height / 2));
247       vage = data->max_age * (1.0f - info->sound.goomPower);
248     }
249       break;
250     case RAIN_FX:
251       mx = goom_irand (info->gRandom, info->screen.width);
252       if (mx > info->screen.width / 2)
253         mx = info->screen.width;
254       else
255         mx = 0;
256       my = -(info->screen.height / 3) - goom_irand (info->gRandom,
257           info->screen.width / 3);
258       radius *= 1.5;
259       vage = 0.002f;
260       break;
261     case FOUNTAIN_FX:
262       my = info->screen.height + 2;
263       vage = 0.001f;
264       radius += 1.0f;
265       mx = info->screen.width / 2;
266       gravity = 0.04f;
267       break;
268     default:
269       return;
270       /* my = i R A N D (info->screen.height); vage = 0.01f; */
271   }
272
273   radius *= info->screen.height / 200.0f;       /* why 200 ? because the FX was developped on 320x200 */
274   max *= info->screen.height / 200.0f;
275
276   if (info->sound.timeSinceLastBigGoom < 1) {
277     radius *= 1.5;
278     max *= 2;
279   }
280   for (i = 0; i < max; ++i)
281     addABomb (data, mx, my, radius, vage, gravity, info);
282 }
283
284
285 /**
286  * Main methode of the FX.
287  */
288 static void
289 fs_apply (VisualFX * _this, Pixel * src, Pixel * dest, PluginInfo * info)
290 {
291
292   int i;
293   int col;
294   FSData *data = (FSData *) _this->fx_data;
295
296   /* Get the new parameters values */
297   data->min_age = 1.0f - (float) IVAL (data->min_age_p) / 100.0f;
298   data->max_age = 1.0f - (float) IVAL (data->max_age_p) / 100.0f;
299   FVAL (data->nbStars_p) = (float) data->nbStars / (float) data->maxStars;
300   data->nbStars_p.change_listener (&data->nbStars_p);
301   data->maxStars = IVAL (data->nbStars_limit_p);
302   data->fx_mode = IVAL (data->fx_mode_p);
303
304   /* look for events */
305   if (info->sound.timeSinceLastGoom < 1) {
306     fs_sound_event_occured (_this, info);
307     if (goom_irand (info->gRandom, 20) == 1) {
308       IVAL (data->fx_mode_p) = goom_irand (info->gRandom, (LAST_FX * 3));
309       data->fx_mode_p.change_listener (&data->fx_mode_p);
310     }
311   }
312
313   /* update particules */
314   for (i = 0; i < data->nbStars; ++i) {
315     updateStar (&data->stars[i]);
316
317     /* dead particule */
318     if (data->stars[i].age >= NCOL)
319       continue;
320
321     /* choose the color of the particule */
322     col = colval[(int) data->stars[i].age];
323
324     /* draws the particule */
325     info->methods.draw_line (dest, (int) data->stars[i].x,
326         (int) data->stars[i].y,
327         (int) (data->stars[i].x - data->stars[i].vx * 6),
328         (int) (data->stars[i].y - data->stars[i].vy * 6), col,
329         (int) info->screen.width, (int) info->screen.height);
330     info->methods.draw_line (dest, (int) data->stars[i].x,
331         (int) data->stars[i].y,
332         (int) (data->stars[i].x - data->stars[i].vx * 2),
333         (int) (data->stars[i].y - data->stars[i].vy * 2), col,
334         (int) info->screen.width, (int) info->screen.height);
335   }
336
337   /* look for dead particules */
338   for (i = 0; i < data->nbStars;) {
339
340     if ((data->stars[i].x > info->screen.width + 64)
341         || ((data->stars[i].vy >= 0)
342             && (data->stars[i].y - 16 * data->stars[i].vy >
343                 info->screen.height))
344         || (data->stars[i].x < -64)
345         || (data->stars[i].age >= NCOL)) {
346       data->stars[i] = data->stars[data->nbStars - 1];
347       data->nbStars--;
348     } else
349       ++i;
350   }
351 }
352
353 void
354 flying_star_create (VisualFX * vfx)
355 {
356   vfx->init = fs_init;
357   vfx->free = fs_free;
358   vfx->apply = fs_apply;
359   vfx->fx_data = NULL;
360   vfx->params = NULL;
361 }