PageRenderTime 48ms CodeModel.GetById 2ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 1ms

/xbmc/visualizations/Goom/goom2k4-0/src/ifs.c

http://github.com/xbmc/xbmc
C | 763 lines | 582 code | 128 blank | 53 comment | 105 complexity | b556e953f921192dff125eb2780725d5 MD5 | raw file
  1/*
  2 * ifs.c --- modified iterated functions system for goom.
  3 */
  4
  5/*-
  6 * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
  7 *
  8 * Permission to use, copy, modify, and distribute this software and its
  9 * documentation for any purpose and without fee is hereby granted,
 10 * provided that the above copyright notice appear in all copies and that
 11 * both that copyright notice and this permission notice appear in
 12 * supporting documentation.
 13 *
 14 * This file is provided AS IS with no warranties of any kind.  The author
 15 * shall have no liability with respect to the infringement of copyrights,
 16 * trade secrets or any patents by this file or any part thereof.  In no
 17 * event will the author be liable for any lost revenue or profits or
 18 * other special, indirect and consequential damages.
 19 *
 20 * If this mode is weird and you have an old MetroX server, it is buggy.
 21 * There is a free SuSE-enhanced MetroX X server that is fine.
 22 *
 23 * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
 24 *
 25 * Revision History:
 26 * 13-Dec-2003: Added some goom specific stuffs (to make ifs a VisualFX).
 27 * 11-Apr-2002: jeko@ios-software.com: Make ifs.c system-indendant. (ifs.h added)
 28 * 01-Nov-2000: Allocation checks
 29 * 10-May-1997: jwz@jwz.org: turned into a standalone program.
 30 *              Made it render into an offscreen bitmap and then copy
 31 *              that onto the screen, to reduce flicker.
 32 */
 33
 34/* #ifdef STANDALONE */
 35
 36#include <math.h>
 37#include <stdlib.h>
 38#include <stdio.h>
 39
 40#include "goom_config.h"
 41
 42#ifdef HAVE_MMX
 43#include "mmx.h"
 44#endif
 45
 46#include "goom_graphic.h"
 47#include "ifs.h"
 48#include "goom_tools.h"
 49
 50typedef struct _ifsPoint
 51{
 52	gint32  x, y;
 53}
 54IFSPoint;
 55
 56
 57#define MODE_ifs
 58
 59#define PROGCLASS "IFS"
 60
 61#define HACK_INIT init_ifs
 62#define HACK_DRAW draw_ifs
 63
 64#define ifs_opts xlockmore_opts
 65
 66#define DEFAULTS "*delay: 20000 \n" \
 67"*ncolors: 100 \n"
 68
 69#define SMOOTH_COLORS
 70
 71#define LRAND()            ((long) (goom_random(goomInfo->gRandom) & 0x7fffffff))
 72#define NRAND(n)           ((int) (LRAND() % (n)))
 73
 74#if RAND_MAX < 0x10000
 75#define MAXRAND (((float)(RAND_MAX<16)+((float)RAND_MAX)+1.0f)/127.0f)
 76#else
 77#define MAXRAND            (2147483648.0/127.0)           /* unsigned 1<<31 / 127.0 (cf goom_tools) as a float */
 78#endif
 79
 80/*****************************************************/
 81
 82typedef float DBL;
 83typedef int F_PT;
 84
 85/* typedef float               F_PT; */
 86
 87/*****************************************************/
 88
 89#define FIX 12
 90#define UNIT   ( 1<<FIX )
 91#define MAX_SIMI  6
 92
 93#define MAX_DEPTH_2  10
 94#define MAX_DEPTH_3  6
 95#define MAX_DEPTH_4  4
 96#define MAX_DEPTH_5  2
 97
 98/* PREVIOUS VALUE 
 99#define MAX_SIMI  6
100
101 * settings for a PC 120Mhz... *
102#define MAX_DEPTH_2  10
103#define MAX_DEPTH_3  6
104#define MAX_DEPTH_4  4
105#define MAX_DEPTH_5  3
106*/
107
108#define DBL_To_F_PT(x)  (F_PT)( (DBL)(UNIT)*(x) )
109
110typedef struct Similitude_Struct SIMI;
111typedef struct Fractal_Struct FRACTAL;
112
113struct Similitude_Struct
114{
115
116	DBL     c_x, c_y;
117	DBL     r, r2, A, A2;
118	F_PT    Ct, St, Ct2, St2;
119	F_PT    Cx, Cy;
120	F_PT    R, R2;
121};
122
123
124struct Fractal_Struct
125{
126
127	int     Nb_Simi;
128	SIMI    Components[5 * MAX_SIMI];
129	int     Depth, Col;
130	int     Count, Speed;
131	int     Width, Height, Lx, Ly;
132	DBL     r_mean, dr_mean, dr2_mean;
133	int     Cur_Pt, Max_Pt;
134
135	IFSPoint *Buffer1, *Buffer2;
136};
137
138typedef struct _IFS_DATA {
139	FRACTAL *Root;
140	FRACTAL *Cur_F;
141
142	/* Used by the Trace recursive method */
143	IFSPoint *Buf;
144	int Cur_Pt;
145	int initalized;
146} IfsData;
147
148
149/*****************************************************/
150
151static  DBL
152Gauss_Rand (PluginInfo *goomInfo, DBL c, DBL A, DBL S)
153{
154	DBL     y;
155
156	y = (DBL) LRAND () / MAXRAND;
157	y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
158	if (NRAND (2))
159		return (c + y);
160	return (c - y);
161}
162
163static  DBL
164Half_Gauss_Rand (PluginInfo *goomInfo, DBL c, DBL A, DBL S)
165{
166	DBL     y;
167
168	y = (DBL) LRAND () / MAXRAND;
169	y = A * (1.0 - exp (-y * y * S)) / (1.0 - exp (-S));
170	return (c + y);
171}
172
173static void
174Random_Simis (PluginInfo *goomInfo, FRACTAL * F, SIMI * Cur, int i)
175{
176	while (i--) {
177		Cur->c_x = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
178		Cur->c_y = Gauss_Rand (goomInfo, 0.0, .8, 4.0);
179		Cur->r = Gauss_Rand (goomInfo, F->r_mean, F->dr_mean, 3.0);
180		Cur->r2 = Half_Gauss_Rand (goomInfo, 0.0, F->dr2_mean, 2.0);
181		Cur->A = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
182		Cur->A2 = Gauss_Rand (goomInfo, 0.0, 360.0, 4.0) * (M_PI / 180.0);
183		Cur++;
184	}
185}
186
187static void
188free_ifs_buffers (FRACTAL * Fractal)
189{
190	if (Fractal->Buffer1 != NULL) {
191		(void) free ((void *) Fractal->Buffer1);
192		Fractal->Buffer1 = (IFSPoint *) NULL;
193	}
194	if (Fractal->Buffer2 != NULL) {
195		(void) free ((void *) Fractal->Buffer2);
196		Fractal->Buffer2 = (IFSPoint *) NULL;
197	}
198}
199
200
201static void
202free_ifs (FRACTAL * Fractal)
203{
204	free_ifs_buffers (Fractal);
205}
206
207/***************************************************************/
208
209static void
210init_ifs (PluginInfo *goomInfo, IfsData *data)
211{
212	int     i;
213	FRACTAL *Fractal;
214	int width = goomInfo->screen.width;
215	int height = goomInfo->screen.height;
216
217	if (data->Root == NULL) {
218		data->Root = (FRACTAL *) malloc (sizeof (FRACTAL));
219		if (data->Root == NULL)
220			return;
221		data->Root->Buffer1 = (IFSPoint *) NULL;
222		data->Root->Buffer2 = (IFSPoint *) NULL;
223	}
224	Fractal = data->Root;
225
226	free_ifs_buffers (Fractal);
227
228	i = (NRAND (4)) + 2;					/* Number of centers */
229	switch (i) {
230		case 3:
231			Fractal->Depth = MAX_DEPTH_3;
232			Fractal->r_mean = .6;
233			Fractal->dr_mean = .4;
234			Fractal->dr2_mean = .3;
235			break;
236
237		case 4:
238			Fractal->Depth = MAX_DEPTH_4;
239			Fractal->r_mean = .5;
240			Fractal->dr_mean = .4;
241			Fractal->dr2_mean = .3;
242			break;
243
244		case 5:
245			Fractal->Depth = MAX_DEPTH_5;
246			Fractal->r_mean = .5;
247			Fractal->dr_mean = .4;
248			Fractal->dr2_mean = .3;
249			break;
250
251		default:
252		case 2:
253			Fractal->Depth = MAX_DEPTH_2;
254			Fractal->r_mean = .7;
255			Fractal->dr_mean = .3;
256			Fractal->dr2_mean = .4;
257			break;
258	}
259	Fractal->Nb_Simi = i;
260	Fractal->Max_Pt = Fractal->Nb_Simi - 1;
261	for (i = 0; i <= Fractal->Depth + 2; ++i)
262		Fractal->Max_Pt *= Fractal->Nb_Simi;
263
264	if ((Fractal->Buffer1 = (IFSPoint *) calloc (Fractal->Max_Pt,
265						     sizeof (IFSPoint))) == NULL) {
266		free_ifs (Fractal);
267		return;
268	}
269	if ((Fractal->Buffer2 = (IFSPoint *) calloc (Fractal->Max_Pt,
270						     sizeof (IFSPoint))) == NULL) {
271		free_ifs (Fractal);
272		return;
273	}
274
275	Fractal->Speed = 6;
276	Fractal->Width = width;				/* modif by JeKo */
277	Fractal->Height = height;			/* modif by JeKo */
278	Fractal->Cur_Pt = 0;
279	Fractal->Count = 0;
280	Fractal->Lx = (Fractal->Width - 1) / 2;
281	Fractal->Ly = (Fractal->Height - 1) / 2;
282	Fractal->Col = rand () % (width * height);	/* modif by JeKo */
283
284	Random_Simis (goomInfo, Fractal, Fractal->Components, 5 * MAX_SIMI);
285}
286
287
288/***************************************************************/
289
290static inline void
291Transform (SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
292{
293	F_PT    xx, yy;
294
295	xo = xo - Simi->Cx;
296	xo = (xo * Simi->R) >> FIX; /* / UNIT; */
297	yo = yo - Simi->Cy;
298	yo = (yo * Simi->R) >> FIX; /* / UNIT; */
299
300	xx = xo - Simi->Cx;
301	xx = (xx * Simi->R2) >> FIX; /* / UNIT; */
302	yy = -yo - Simi->Cy;
303	yy = (yy * Simi->R2) >> FIX; /* / UNIT; */
304
305	*x =
306	  ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2)
307	   >> FIX /* / UNIT */ ) + Simi->Cx;
308	*y =
309	  ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2)
310	   >> FIX /* / UNIT */ ) + Simi->Cy;
311}
312
313/***************************************************************/
314
315static void
316Trace (FRACTAL * F, F_PT xo, F_PT yo, IfsData *data)
317{
318	F_PT    x, y, i;
319	SIMI   *Cur;
320
321	Cur = data->Cur_F->Components;
322	for (i = data->Cur_F->Nb_Simi; i; --i, Cur++) {
323		Transform (Cur, xo, yo, &x, &y);
324
325		data->Buf->x = F->Lx + ((x * F->Lx) >> (FIX+1) /* /(UNIT*2) */ );
326		data->Buf->y = F->Ly - ((y * F->Ly) >> (FIX+1) /* /(UNIT*2) */ );
327		data->Buf++;
328
329		data->Cur_Pt++;
330
331		if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
332			F->Depth--;
333			Trace (F, x, y, data);
334			F->Depth++;
335		}
336	}
337}
338
339static void
340Draw_Fractal (IfsData *data)
341{
342	FRACTAL *F = data->Root;
343	int     i, j;
344	F_PT    x, y, xo, yo;
345	SIMI   *Cur, *Simi;
346
347	for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
348		Cur->Cx = DBL_To_F_PT (Cur->c_x);
349		Cur->Cy = DBL_To_F_PT (Cur->c_y);
350
351		Cur->Ct = DBL_To_F_PT (cos (Cur->A));
352		Cur->St = DBL_To_F_PT (sin (Cur->A));
353		Cur->Ct2 = DBL_To_F_PT (cos (Cur->A2));
354		Cur->St2 = DBL_To_F_PT (sin (Cur->A2));
355
356		Cur->R = DBL_To_F_PT (Cur->r);
357		Cur->R2 = DBL_To_F_PT (Cur->r2);
358	}
359
360
361	data->Cur_Pt = 0;
362	data->Cur_F = F;
363	data->Buf = F->Buffer2;
364	for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
365		xo = Cur->Cx;
366		yo = Cur->Cy;
367		for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
368			if (Simi == Cur)
369				continue;
370			Transform (Simi, xo, yo, &x, &y);
371			Trace (F, x, y, data);
372		}
373	}
374
375	/* Erase previous */
376
377	F->Cur_Pt = data->Cur_Pt;
378	data->Buf = F->Buffer1;
379	F->Buffer1 = F->Buffer2;
380	F->Buffer2 = data->Buf;
381}
382
383
384static IFSPoint *
385draw_ifs (PluginInfo *goomInfo, int *nbpt, IfsData *data)
386{
387	int     i;
388	DBL     u, uu, v, vv, u0, u1, u2, u3;
389	SIMI   *S, *S1, *S2, *S3, *S4;
390	FRACTAL *F;
391
392	if (data->Root == NULL)
393		return NULL;
394	F = data->Root;
395	if (F->Buffer1 == NULL)
396		return NULL;
397
398	u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
399	uu = u * u;
400	v = 1.0 - u;
401	vv = v * v;
402	u0 = vv * v;
403	u1 = 3.0 * vv * u;
404	u2 = 3.0 * v * uu;
405	u3 = u * uu;
406
407	S = F->Components;
408	S1 = S + F->Nb_Simi;
409	S2 = S1 + F->Nb_Simi;
410	S3 = S2 + F->Nb_Simi;
411	S4 = S3 + F->Nb_Simi;
412
413	for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
414		S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
415		S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
416		S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
417		S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
418		S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
419		S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
420	}
421
422	Draw_Fractal (data);
423
424	if (F->Count >= 1000 / F->Speed) {
425		S = F->Components;
426		S1 = S + F->Nb_Simi;
427		S2 = S1 + F->Nb_Simi;
428		S3 = S2 + F->Nb_Simi;
429		S4 = S3 + F->Nb_Simi;
430
431		for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
432			S2->c_x = 2.0 * S4->c_x - S3->c_x;
433			S2->c_y = 2.0 * S4->c_y - S3->c_y;
434			S2->r = 2.0 * S4->r - S3->r;
435			S2->r2 = 2.0 * S4->r2 - S3->r2;
436			S2->A = 2.0 * S4->A - S3->A;
437			S2->A2 = 2.0 * S4->A2 - S3->A2;
438
439			*S1 = *S4;
440		}
441		Random_Simis (goomInfo, F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
442
443		Random_Simis (goomInfo, F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
444
445		F->Count = 0;
446	}
447	else
448		F->Count++;
449
450	F->Col++;
451
452	(*nbpt) = data->Cur_Pt;
453	return F->Buffer2;
454}
455
456
457/***************************************************************/
458
459static void release_ifs (IfsData *data)
460{
461	if (data->Root != NULL) {
462		free_ifs (data->Root);
463		(void) free ((void *) data->Root);
464		data->Root = (FRACTAL *) NULL;
465	}
466}
467
468#define RAND() goom_random(goomInfo->gRandom)
469
470static void ifs_update (PluginInfo *goomInfo, Pixel * data, Pixel * back, int increment, IfsData *fx_data)
471{
472	static int couleur = 0xc0c0c0c0;
473	static int v[4] = { 2, 4, 3, 2 };
474	static int col[4] = { 2, 4, 3, 2 };
475
476#define MOD_MER 0
477#define MOD_FEU 1
478#define MOD_MERVER 2
479	static int mode = MOD_MERVER;
480	static int justChanged = 0;
481	static int cycle = 0;
482	int     cycle10;
483
484	int     nbpt;
485	IFSPoint *points;
486	int     i;
487
488	int     couleursl = couleur;
489	int width = goomInfo->screen.width;
490	int height = goomInfo->screen.height;
491
492	cycle++;
493	if (cycle >= 80)
494		cycle = 0;
495
496	if (cycle < 40)
497		cycle10 = cycle / 10;
498	else
499		cycle10 = 7 - cycle / 10;
500
501	{
502		unsigned char *tmp = (unsigned char *) &couleursl;
503
504		for (i = 0; i < 4; i++) {
505			*tmp = (*tmp) >> cycle10;
506			tmp++;
507		}
508	}
509
510	points = draw_ifs (goomInfo, &nbpt, fx_data);
511	nbpt--;
512
513#ifdef HAVE_MMX
514	movd_m2r (couleursl, mm1);
515	punpckldq_r2r (mm1, mm1);
516	for (i = 0; i < nbpt; i += increment) {
517		int     x = points[i].x;
518		int     y = points[i].y;
519
520		if ((x < width) && (y < height) && (x > 0) && (y > 0)) {
521			int     pos = x + (y * width);
522			movd_m2r (back[pos], mm0);
523			paddusb_r2r (mm1, mm0);
524			movd_r2m (mm0, data[pos]);
525		}
526	}
527	emms();/*__asm__ __volatile__ ("emms");*/
528#else
529	for (i = 0; i < nbpt; i += increment) {
530		int     x = (int) points[i].x & 0x7fffffff;
531		int     y = (int) points[i].y & 0x7fffffff;
532
533		if ((x < width) && (y < height)) {
534			int     pos = x + (int) (y * width);
535			int     tra = 0, i = 0;
536			unsigned char *bra = (unsigned char *) &back[pos];
537			unsigned char *dra = (unsigned char *) &data[pos];
538			unsigned char *cra = (unsigned char *) &couleursl;
539
540			for (; i < 4; i++) {
541				tra = *cra;
542				tra += *bra;
543				if (tra > 255)
544					tra = 255;
545				*dra = tra;
546				++dra;
547				++cra;
548				++bra;
549			}
550		}
551	}
552#endif /*MMX*/
553		justChanged--;
554
555	col[ALPHA] = couleur >> (ALPHA * 8) & 0xff;
556	col[BLEU] = couleur >> (BLEU * 8) & 0xff;
557	col[VERT] = couleur >> (VERT * 8) & 0xff;
558	col[ROUGE] = couleur >> (ROUGE * 8) & 0xff;
559
560	if (mode == MOD_MER) {
561		col[BLEU] += v[BLEU];
562		if (col[BLEU] > 255) {
563			col[BLEU] = 255;
564			v[BLEU] = -(RAND() % 4) - 1;
565		}
566		if (col[BLEU] < 32) {
567			col[BLEU] = 32;
568			v[BLEU] = (RAND() % 4) + 1;
569		}
570
571		col[VERT] += v[VERT];
572		if (col[VERT] > 200) {
573			col[VERT] = 200;
574			v[VERT] = -(RAND() % 3) - 2;
575		}
576		if (col[VERT] > col[BLEU]) {
577			col[VERT] = col[BLEU];
578			v[VERT] = v[BLEU];
579		}
580		if (col[VERT] < 32) {
581			col[VERT] = 32;
582			v[VERT] = (RAND() % 3) + 2;
583		}
584
585		col[ROUGE] += v[ROUGE];
586		if (col[ROUGE] > 64) {
587			col[ROUGE] = 64;
588			v[ROUGE] = -(RAND () % 4) - 1;
589		}
590		if (col[ROUGE] < 0) {
591			col[ROUGE] = 0;
592			v[ROUGE] = (RAND () % 4) + 1;
593		}
594
595		col[ALPHA] += v[ALPHA];
596		if (col[ALPHA] > 0) {
597			col[ALPHA] = 0;
598			v[ALPHA] = -(RAND () % 4) - 1;
599		}
600		if (col[ALPHA] < 0) {
601			col[ALPHA] = 0;
602			v[ALPHA] = (RAND () % 4) + 1;
603		}
604
605		if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
606				 && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
607				 && (RAND () % 20 == 0)) && (justChanged < 0)) {
608			mode = RAND () % 3 ? MOD_FEU : MOD_MERVER;
609			justChanged = 250;
610		}
611	}
612	else if (mode == MOD_MERVER) {
613		col[BLEU] += v[BLEU];
614		if (col[BLEU] > 128) {
615			col[BLEU] = 128;
616			v[BLEU] = -(RAND () % 4) - 1;
617		}
618		if (col[BLEU] < 16) {
619			col[BLEU] = 16;
620			v[BLEU] = (RAND () % 4) + 1;
621		}
622
623		col[VERT] += v[VERT];
624		if (col[VERT] > 200) {
625			col[VERT] = 200;
626			v[VERT] = -(RAND () % 3) - 2;
627		}
628		if (col[VERT] > col[ALPHA]) {
629			col[VERT] = col[ALPHA];
630			v[VERT] = v[ALPHA];
631		}
632		if (col[VERT] < 32) {
633			col[VERT] = 32;
634			v[VERT] = (RAND () % 3) + 2;
635		}
636
637		col[ROUGE] += v[ROUGE];
638		if (col[ROUGE] > 128) {
639			col[ROUGE] = 128;
640			v[ROUGE] = -(RAND () % 4) - 1;
641		}
642		if (col[ROUGE] < 0) {
643			col[ROUGE] = 0;
644			v[ROUGE] = (RAND () % 4) + 1;
645		}
646
647		col[ALPHA] += v[ALPHA];
648		if (col[ALPHA] > 255) {
649			col[ALPHA] = 255;
650			v[ALPHA] = -(RAND () % 4) - 1;
651		}
652		if (col[ALPHA] < 0) {
653			col[ALPHA] = 0;
654			v[ALPHA] = (RAND () % 4) + 1;
655		}
656
657		if (((col[VERT] > 32) && (col[ROUGE] < col[VERT] + 40)
658				 && (col[VERT] < col[ROUGE] + 20) && (col[BLEU] < 64)
659				 && (RAND () % 20 == 0)) && (justChanged < 0)) {
660			mode = RAND () % 3 ? MOD_FEU : MOD_MER;
661			justChanged = 250;
662		}
663	}
664	else if (mode == MOD_FEU) {
665
666		col[BLEU] += v[BLEU];
667		if (col[BLEU] > 64) {
668			col[BLEU] = 64;
669			v[BLEU] = -(RAND () % 4) - 1;
670		}
671		if (col[BLEU] < 0) {
672			col[BLEU] = 0;
673			v[BLEU] = (RAND () % 4) + 1;
674		}
675
676		col[VERT] += v[VERT];
677		if (col[VERT] > 200) {
678			col[VERT] = 200;
679			v[VERT] = -(RAND () % 3) - 2;
680		}
681		if (col[VERT] > col[ROUGE] + 20) {
682			col[VERT] = col[ROUGE] + 20;
683			v[VERT] = -(RAND () % 3) - 2;
684			v[ROUGE] = (RAND () % 4) + 1;
685			v[BLEU] = (RAND () % 4) + 1;
686		}
687		if (col[VERT] < 0) {
688			col[VERT] = 0;
689			v[VERT] = (RAND () % 3) + 2;
690		}
691
692		col[ROUGE] += v[ROUGE];
693		if (col[ROUGE] > 255) {
694			col[ROUGE] = 255;
695			v[ROUGE] = -(RAND () % 4) - 1;
696		}
697		if (col[ROUGE] > col[VERT] + 40) {
698			col[ROUGE] = col[VERT] + 40;
699			v[ROUGE] = -(RAND () % 4) - 1;
700		}
701		if (col[ROUGE] < 0) {
702			col[ROUGE] = 0;
703			v[ROUGE] = (RAND () % 4) + 1;
704		}
705
706		col[ALPHA] += v[ALPHA];
707		if (col[ALPHA] > 0) {
708			col[ALPHA] = 0;
709			v[ALPHA] = -(RAND () % 4) - 1;
710		}
711		if (col[ALPHA] < 0) {
712			col[ALPHA] = 0;
713			v[ALPHA] = (RAND () % 4) + 1;
714		}
715
716		if (((col[ROUGE] < 64) && (col[VERT] > 32) && (col[VERT] < col[BLEU])
717				 && (col[BLEU] > 32)
718				 && (RAND () % 20 == 0)) && (justChanged < 0)) {
719			mode = RAND () % 2 ? MOD_MER : MOD_MERVER;
720			justChanged = 250;
721		}
722	}
723
724	couleur = (col[ALPHA] << (ALPHA * 8))
725		| (col[BLEU] << (BLEU * 8))
726		| (col[VERT] << (VERT * 8))
727		| (col[ROUGE] << (ROUGE * 8));
728}
729
730/** VISUAL_FX WRAPPER FOR IFS */
731
732static void ifs_vfx_apply(VisualFX *_this, Pixel *src, Pixel *dest, PluginInfo *goomInfo) {
733
734	IfsData *data = (IfsData*)_this->fx_data;
735	if (!data->initalized) {
736		data->initalized = 1;
737		init_ifs(goomInfo, data);
738	}
739	ifs_update (goomInfo, dest, src, goomInfo->update.ifs_incr, data);
740	/*TODO: trouver meilleur soluce pour increment (mettre le code de gestion de l'ifs dans ce fichier: ifs_vfx_apply) */
741}
742
743static void ifs_vfx_init(VisualFX *_this, PluginInfo *info) {
744
745	IfsData *data = (IfsData*)malloc(sizeof(IfsData));
746	data->Root = (FRACTAL*)NULL;
747	data->initalized = 0;
748	_this->fx_data = data;
749}
750
751static void ifs_vfx_free(VisualFX *_this) {
752	IfsData *data = (IfsData*)_this->fx_data;
753	release_ifs(data);
754	free(data);
755}
756
757VisualFX ifs_visualfx_create(void) {
758	VisualFX vfx;
759	vfx.init = ifs_vfx_init;
760	vfx.free = ifs_vfx_free;
761	vfx.apply = ifs_vfx_apply;
762	return vfx;
763}