1 // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY ---
2
3 /* filter.c version 0.7
4 * contient les filtres applicable a un buffer
5 * creation : 01/10/2000
6 * -ajout de sinFilter()
7 * -ajout de zoomFilter()
8 * -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs
9 * -optimisation de sinFilter (utilisant une table de sin)
10 * -asm
11 * -optimisation de la procedure de generation du buffer de transformation
12 * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100]
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 /* #define _DEBUG_PIXEL */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <inttypes.h>
26
27 #include "goom_filters.h"
28 #include "goom_graphic.h"
29 #include "goom_tools.h"
30 #include "goom_plugin_info.h"
31 #include "goom_fx.h"
32 #include "v3d.h"
33
34 /* TODO : MOVE THIS AWAY !!! */
35 /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */
setPixelRGB(PluginInfo * goomInfo,Pixel * buffer,Uint x,Uint y,Color c)36 static inline void setPixelRGB (PluginInfo *goomInfo, Pixel *buffer, Uint x, Uint y, Color c)
37 {
38 Pixel i;
39
40 i.channels.b = c.b;
41 i.channels.g = c.v;
42 i.channels.r = c.r;
43 *(buffer + (x + y * goomInfo->screen.width)) = i;
44 }
45
setPixelRGB_(Pixel * buffer,Uint x,Color c)46 static inline void setPixelRGB_ (Pixel *buffer, Uint x, Color c)
47 {
48 buffer[x].channels.r = c.r;
49 buffer[x].channels.g = c.v;
50 buffer[x].channels.b = c.b;
51 }
52
getPixelRGB(PluginInfo * goomInfo,Pixel * buffer,Uint x,Uint y,Color * c)53 static inline void getPixelRGB (PluginInfo *goomInfo, Pixel *buffer, Uint x, Uint y, Color * c)
54 {
55 Pixel i = *(buffer + (x + y * goomInfo->screen.width));
56 c->b = i.channels.b;
57 c->v = i.channels.g;
58 c->r = i.channels.r;
59 }
60
getPixelRGB_(Pixel * buffer,Uint x,Color * c)61 static inline void getPixelRGB_ (Pixel *buffer, Uint x, Color * c)
62 {
63 Pixel i = *(buffer + x);
64 c->b = i.channels.b;
65 c->v = i.channels.g;
66 c->r = i.channels.r;
67 }
68 /* END TODO */
69
70
71 /* DEPRECATED */
72 // retourne x>>s , en testant le signe de x
73 //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s)))
74 //#define EFFECT_DISTORS 4
75 //#define EFFECT_DISTORS_SL 2
76 //#define INTERLACE_ADD 9
77 //#define INTERLACE_AND 0xf
78 /* END DEPRECATED */
79
80 #define BUFFPOINTNB 16
81 #define BUFFPOINTNBF 16.0f
82 #define BUFFPOINTMASK 0xffff
83
84 #define sqrtperte 16
85 /* faire : a % sqrtperte <=> a & pertemask */
86 #define PERTEMASK 0xf
87 /* faire : a / sqrtperte <=> a >> PERTEDEC */
88 #define PERTEDEC 4
89
90 /* pure c version of the zoom filter */
91 static void c_zoom (Pixel *expix1, Pixel *expix2, unsigned int prevX, unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio, int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
92
93 /* simple wrapper to give it the same proto than the others */
zoom_filter_c(int sizeX,int sizeY,Pixel * src,Pixel * dest,int * brutS,int * brutD,int buffratio,int precalCoef[16][16])94 void zoom_filter_c (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]) {
95 c_zoom(src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef);
96 }
97
98 static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]);
99
100
101 typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA {
102
103 PluginParam enabled_bp;
104 PluginParameters params;
105
106 unsigned int *coeffs, *freecoeffs;
107
108 signed int *brutS, *freebrutS; /* source */
109 signed int *brutD, *freebrutD; /* dest */
110 signed int *brutT, *freebrutT; /* temp (en cours de generation) */
111
112 guint32 zoom_width;
113
114 unsigned int prevX, prevY;
115
116 float general_speed;
117 int reverse; /* reverse the speed */
118 char theMode;
119 int waveEffect;
120 int hypercosEffect;
121 int vPlaneEffect;
122 int hPlaneEffect;
123 char noisify;
124 int middleX, middleY;
125
126 int mustInitBuffers;
127 int interlace_start;
128
129 /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
130 int buffratio;
131 int *firedec;
132
133 /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
134 int precalCoef[BUFFPOINTNB][BUFFPOINTNB];
135
136 /** calculatePXandPY statics */
137 int wave;
138 int wavesp;
139
140 } ZoomFilterFXWrapperData;
141
142
143
144
zoomVector(ZoomFilterFXWrapperData * data,float X,float Y)145 static inline v2g zoomVector(ZoomFilterFXWrapperData *data, float X, float Y)
146 {
147 v2g vecteur;
148 float vx, vy;
149 float sq_dist = X*X + Y*Y;
150
151 /* sx = (X < 0.0f) ? -1.0f : 1.0f;
152 sy = (Y < 0.0f) ? -1.0f : 1.0f;
153 */
154 float coefVitesse = (1.0f+ data->general_speed) / 50.0f;
155
156 // Effects
157
158 /* Centralized FX */
159
160 switch (data->theMode) {
161 case CRYSTAL_BALL_MODE:
162 coefVitesse -= (sq_dist-0.3f)/15.0f;
163 break;
164 case AMULETTE_MODE:
165 coefVitesse += sq_dist * 3.5f;
166 break;
167 case WAVE_MODE:
168 coefVitesse += sin(sq_dist*20.0f) / 100.0f;
169 break;
170 case SCRUNCH_MODE:
171 coefVitesse += sq_dist / 10.0f;
172 break;
173 //case HYPERCOS1_MODE:
174 break;
175 //case HYPERCOS2_MODE:
176 break;
177 //case YONLY_MODE:
178 break;
179 case SPEEDWAY_MODE:
180 coefVitesse *= 4.0f * Y;
181 break;
182 default:
183 break;
184 }
185
186 if (coefVitesse < -2.01f)
187 coefVitesse = -2.01f;
188 if (coefVitesse > 2.01f)
189 coefVitesse = 2.01f;
190
191 vx = coefVitesse * X;
192 vy = coefVitesse * Y;
193
194 /* Amulette 2 */
195 // vx = X * tan(dist);
196 // vy = Y * tan(dist);
197
198 /* Rotate */
199 //vx = (X+Y)*0.1;
200 //vy = (Y-X)*0.1;
201
202
203 // Effects adds-on
204
205 /* Noise */
206 if (data->noisify)
207 {
208 vx += (((float)rand()) / ((float)RAND_MAX) - 0.5f) / 50.0f;
209 vy += (((float)rand()) / ((float)RAND_MAX) - 0.5f) / 50.0f;
210 }
211
212 /* Hypercos */
213 if (data->hypercosEffect)
214 {
215 vx += sin(Y*10.0f)/120.0f;
216 vy += sin(X*10.0f)/120.0f;
217 }
218
219 /* H Plane */
220 if (data->hPlaneEffect) vx += Y * 0.0025f * data->hPlaneEffect;
221
222 /* V Plane */
223 if (data->vPlaneEffect) vy += X * 0.0025f * data->vPlaneEffect;
224
225 /* TODO : Water Mode */
226 // if (data->waveEffect)
227
228 vecteur.x = vx;
229 vecteur.y = vy;
230
231 return vecteur;
232 }
233
234
235 /*
236 * Makes a stripe of a transform buffer (brutT)
237 *
238 * The transform is (in order) :
239 * Translation (-data->middleX, -data->middleY)
240 * Homothetie (Center : 0,0 Coeff : 2/data->prevX)
241 */
makeZoomBufferStripe(ZoomFilterFXWrapperData * data,int INTERLACE_INCR)242 static void makeZoomBufferStripe(ZoomFilterFXWrapperData * data, int INTERLACE_INCR)
243 {
244 // Position of the pixel to compute in pixmap coordinates
245 Uint x, y;
246 // Where (verticaly) to stop generating the buffer stripe
247 int maxEnd = (data->interlace_start + INTERLACE_INCR);
248 // Ratio from pixmap to normalized coordinates
249 float ratio = 2.0f/((float)data->prevX);
250 // Ratio from normalized to virtual pixmap coordinates
251 float inv_ratio = BUFFPOINTNBF/ratio;
252 float min = ratio/BUFFPOINTNBF;
253 // Y position of the pixel to compute in normalized coordinates
254 float Y = ((float)(data->interlace_start - data->middleY)) * ratio;
255
256 maxEnd = data->prevY;
257 if (maxEnd > (data->interlace_start + INTERLACE_INCR))
258 maxEnd = (data->interlace_start + INTERLACE_INCR);
259
260 for (y = data->interlace_start; (y < data->prevY) && ((signed int)y<maxEnd); y++) {
261 Uint premul_y_prevX = y * data->prevX * 2;
262 float X = - ((float)data->middleX) * ratio;
263 for (x = 0; x < data->prevX; x++)
264 {
265 v2g vector = zoomVector (data, X, Y);
266
267 /* Finish and avoid null displacement */
268 if (fabs(vector.x) < min) vector.x = (vector.x < 0.0f) ? -min : min;
269 if (fabs(vector.y) < min) vector.y = (vector.y < 0.0f) ? -min : min;
270
271 data->brutT[premul_y_prevX] = ((int)((X-vector.x)*inv_ratio)+((int)(data->middleX*BUFFPOINTNB)));
272 data->brutT[premul_y_prevX+1] = ((int)((Y-vector.y)*inv_ratio)+((int)(data->middleY*BUFFPOINTNB)));
273 premul_y_prevX += 2;
274 X += ratio;
275 }
276 Y += ratio;
277 }
278 data->interlace_start += INTERLACE_INCR;
279 if (y >= data->prevY-1) data->interlace_start = -1;
280 }
281
282
283 /*
284 * calculer px et py en fonction de x,y,middleX,middleY et theMode
285 * px et py indique la nouvelle position (en sqrtperte ieme de pixel)
286 * (valeur * 16)
287
288 inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py)
289 {
290 if (data->theMode == WATER_MODE) {
291 int yy;
292
293 yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10;
294 if (yy < 0)
295 yy = 0;
296 if (yy >= (signed int)goomInfo->screen.height)
297 yy = goomInfo->screen.height - 1;
298
299 *px = (x << 4) + data->firedec[yy] + (data->wave / 10);
300 *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130);
301
302 data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
303 if (data->wave < -10)
304 data->wavesp += 2;
305 if (data->wave > 10)
306 data->wavesp -= 2;
307 data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
308 if (data->wavesp > 100)
309 data->wavesp = (data->wavesp * 9) / 10;
310 }
311 else {
312 int dist = 0, vx9, vy9;
313 int vx, vy;
314 int ppx, ppy;
315 int fvitesse = data->vitesse << 4;
316
317 if (data->noisify) {
318 x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
319 y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify);
320 }
321 vx = (x - data->middleX) << 9;
322 vy = (y - data->middleY) << 9;
323
324 if (data->hPlaneEffect)
325 vx += data->hPlaneEffect * (y - data->middleY);
326
327 if (data->vPlaneEffect)
328 vy += data->vPlaneEffect * (x - data->middleX);
329
330 if (data->waveEffect) {
331 fvitesse *=
332 1024 +
333 ShiftRight (goomInfo->sintable
334 [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6);
335 fvitesse /= 1024;
336 }
337
338 if (data->hypercosEffect) {
339 vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
340 vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
341 }
342
343 vx9 = ShiftRight (vx, 9);
344 vy9 = ShiftRight (vy, 9);
345 dist = vx9 * vx9 + vy9 * vy9;
346
347 switch (data->theMode) {
348 case WAVE_MODE:
349 fvitesse *=
350 1024 +
351 ShiftRight (goomInfo->sintable
352 [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6);
353 fvitesse>>=10;
354 break;
355 case CRYSTAL_BALL_MODE:
356 fvitesse += (dist >> (10-EFFECT_DISTORS_SL));
357 break;
358 case AMULETTE_MODE:
359 fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL));
360 break;
361 case SCRUNCH_MODE:
362 fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL));
363 break;
364 case HYPERCOS1_MODE:
365 vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1);
366 vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1);
367 break;
368 case HYPERCOS2_MODE:
369 vx =
370 vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0);
371 vy =
372 vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0);
373 fvitesse = 128 << 4;
374 break;
375 case YONLY_MODE:
376 fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6);
377 fvitesse >>= 10;
378 break;
379 case SPEEDWAY_MODE:
380 fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL));
381 break;
382 }
383
384 if (fvitesse < -3024)
385 fvitesse = -3024;
386
387 if (vx < 0) // pb avec decalage sur nb negatif
388 ppx = -(-(vx * fvitesse) >> 16);
389 // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile)
390 // * * * * * 9 = nb chiffre virgule de vx)
391 else
392 ppx = ((vx * fvitesse) >> 16);
393
394 if (vy < 0)
395 ppy = -(-(vy * fvitesse) >> 16);
396 else
397 ppy = ((vy * fvitesse) >> 16);
398
399 *px = (data->middleX << 4) + ppx;
400 *py = (data->middleY << 4) + ppy;
401 }
402 }
403 */
404
405
406
c_zoom(Pixel * expix1,Pixel * expix2,unsigned int prevX,unsigned int prevY,signed int * brutS,signed int * brutD,int buffratio,int precalCoef[16][16])407 static void c_zoom (Pixel *expix1, Pixel *expix2, unsigned int prevX, unsigned int prevY, signed int *brutS, signed int *brutD,
408 int buffratio, int precalCoef[16][16])
409 {
410 int myPos, myPos2;
411 Color couleur;
412
413 unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC;
414
415 int bufsize = prevX * prevY * 2;
416 int bufwidth = prevX;
417
418 expix1[0].val=expix1[prevX-1].val=expix1[prevX*prevY-1].val=expix1[prevX*prevY-prevX].val=0;
419
420 for (myPos = 0; myPos < bufsize; myPos += 2) {
421 Color col1, col2, col3, col4;
422 int c1, c2, c3, c4, px, py;
423 int pos;
424 int coeffs;
425
426 int brutSmypos = brutS[myPos];
427
428 myPos2 = myPos + 1;
429
430 px = brutSmypos + (((brutD[myPos] - brutSmypos) * buffratio) >> BUFFPOINTNB);
431 brutSmypos = brutS[myPos2];
432 py = brutSmypos + (((brutD[myPos2] - brutSmypos) * buffratio) >> BUFFPOINTNB);
433
434 if ((py >= (int)ay) || (px >= (int)ax)) {
435 pos = coeffs = 0;
436 } else {
437 pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC));
438 /* coef en modulo 15 */
439 coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK];
440 }
441 getPixelRGB_ (expix1, pos, &col1);
442 getPixelRGB_ (expix1, pos + 1, &col2);
443 getPixelRGB_ (expix1, pos + bufwidth, &col3);
444 getPixelRGB_ (expix1, pos + bufwidth + 1, &col4);
445
446 c1 = coeffs;
447 c2 = (c1 >> 8) & 0xFF;
448 c3 = (c1 >> 16) & 0xFF;
449 c4 = (c1 >> 24) & 0xFF;
450 c1 = c1 & 0xff;
451
452 couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4;
453 if (couleur.r > 5)
454 couleur.r -= 5;
455 couleur.r >>= 8;
456
457 couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4;
458 if (couleur.v > 5)
459 couleur.v -= 5;
460 couleur.v >>= 8;
461
462 couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4;
463 if (couleur.b > 5)
464 couleur.b -= 5;
465 couleur.b >>= 8;
466
467 setPixelRGB_ (expix2, myPos >> 1, couleur);
468 }
469 }
470
471 /** generate the water fx horizontal direction buffer */
generateTheWaterFXHorizontalDirectionBuffer(PluginInfo * goomInfo,ZoomFilterFXWrapperData * data)472 static void generateTheWaterFXHorizontalDirectionBuffer(PluginInfo *goomInfo, ZoomFilterFXWrapperData *data) {
473
474 int loopv;
475 int decc = goom_irand(goomInfo->gRandom, 8) - 4;
476 int spdc = goom_irand(goomInfo->gRandom, 8) - 4;
477 int accel = goom_irand(goomInfo->gRandom, 8) - 4;
478
479 for (loopv = data->prevY; loopv != 0;) {
480
481 loopv--;
482 data->firedec[loopv] = decc;
483 decc += spdc / 10;
484 spdc += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3);
485
486 if (decc > 4)
487 spdc -= 1;
488 if (decc < -4)
489 spdc += 1;
490
491 if (spdc > 30)
492 spdc = spdc - goom_irand(goomInfo->gRandom, 3) + accel / 10;
493 if (spdc < -30)
494 spdc = spdc + goom_irand(goomInfo->gRandom, 3) + accel / 10;
495
496 if (decc > 8 && spdc > 1)
497 spdc -= goom_irand(goomInfo->gRandom, 3) - 2;
498
499 if (decc < -8 && spdc < -1)
500 spdc += goom_irand(goomInfo->gRandom, 3) + 2;
501
502 if (decc > 8 || decc < -8)
503 decc = decc * 8 / 9;
504
505 accel += goom_irand(goomInfo->gRandom, 2) - goom_irand(goomInfo->gRandom, 2);
506 if (accel > 20)
507 accel -= 2;
508 if (accel < -20)
509 accel += 2;
510 }
511 }
512
513
514
515 /**
516 * Main work for the dynamic displacement map.
517 *
518 * Reads data from pix1, write to pix2.
519 *
520 * Useful datas for this FX are stored in ZoomFilterData.
521 *
522 * If you think that this is a strange function name, let me say that a long time ago,
523 * there has been a slow version and a gray-level only one. Then came these function,
524 * fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image.
525 * So that is why you have this name, for the nostalgy of the first days of goom
526 * when it was just a tiny program writen in Turbo Pascal on my i486...
527 */
zoomFilterFastRGB(PluginInfo * goomInfo,Pixel * pix1,Pixel * pix2,ZoomFilterData * zf,Uint resx,Uint resy,int switchIncr,float switchMult)528 void zoomFilterFastRGB (PluginInfo *goomInfo, Pixel * pix1, Pixel * pix2, ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult)
529 {
530 Uint x, y;
531
532 ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData*)goomInfo->zoomFilter_fx.fx_data;
533
534 if (!BVAL(data->enabled_bp)) return;
535
536 /** changement de taille **/
537 if ((data->prevX != resx) || (data->prevY != resy)) {
538 data->prevX = resx;
539 data->prevY = resy;
540
541 if (data->brutS) free (data->freebrutS);
542 data->brutS = 0;
543 if (data->brutD) free (data->freebrutD);
544 data->brutD = 0;
545 if (data->brutT) free (data->freebrutT);
546 data->brutT = 0;
547
548 data->middleX = resx / 2;
549 data->middleY = resy / 2;
550 data->mustInitBuffers = 1;
551 if (data->firedec) free (data->firedec);
552 data->firedec = 0;
553 }
554
555 if (data->interlace_start != -2)
556 zf = NULL;
557
558 /** changement de config **/
559 if (zf) {
560 data->reverse = zf->reverse;
561 data->general_speed = (float)(zf->vitesse-128)/128.0f;
562 if (data->reverse) data->general_speed = -data->general_speed;
563 data->middleX = zf->middleX;
564 data->middleY = zf->middleY;
565 data->theMode = zf->mode;
566 data->hPlaneEffect = zf->hPlaneEffect;
567 data->vPlaneEffect = zf->vPlaneEffect;
568 data->waveEffect = zf->waveEffect;
569 data->hypercosEffect = zf->hypercosEffect;
570 data->noisify = zf->noisify;
571 data->interlace_start = 0;
572 }
573
574
575 if (data->mustInitBuffers) {
576
577 data->mustInitBuffers = 0;
578 data->freebrutS = (signed int *) calloc (resx * resy * 2 + 128, sizeof(unsigned int));
579 data->brutS = (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128);
580
581 data->freebrutD = (signed int *) calloc (resx * resy * 2 + 128, sizeof(unsigned int));
582 data->brutD = (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128);
583
584 data->freebrutT = (signed int *) calloc (resx * resy * 2 + 128, sizeof(unsigned int));
585 data->brutT = (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128);
586
587 data->buffratio = 0;
588
589 data->firedec = (int *) malloc (data->prevY * sizeof (int));
590 generateTheWaterFXHorizontalDirectionBuffer(goomInfo, data);
591
592 data->interlace_start = 0;
593 makeZoomBufferStripe(data,resy);
594
595 /* Copy the data from temp to dest and source */
596 memcpy(data->brutS,data->brutT,resx * resy * 2 * sizeof(int));
597 memcpy(data->brutD,data->brutT,resx * resy * 2 * sizeof(int));
598 }
599
600 /* generation du buffer de trans */
601 if (data->interlace_start == -1) {
602
603 /* sauvegarde de l'etat actuel dans la nouvelle source
604 * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */
605 y = data->prevX * data->prevY * 2;
606 for (x = 0; x < y; x += 2) {
607 int brutSmypos = data->brutS[x];
608 int x2 = x + 1;
609
610 data->brutS[x] = brutSmypos + (((data->brutD[x] - brutSmypos) * data->buffratio) >> BUFFPOINTNB);
611 brutSmypos = data->brutS[x2];
612 data->brutS[x2] = brutSmypos + (((data->brutD[x2] - brutSmypos) * data->buffratio) >> BUFFPOINTNB);
613 }
614 data->buffratio = 0;
615 }
616
617 if (data->interlace_start == -1) {
618 signed int * tmp;
619 tmp = data->brutD;
620 data->brutD=data->brutT;
621 data->brutT=tmp;
622 tmp = data->freebrutD;
623 data->freebrutD=data->freebrutT;
624 data->freebrutT=tmp;
625 data->interlace_start = -2;
626 }
627
628 if (data->interlace_start>=0)
629 {
630 /* creation de la nouvelle destination */
631 makeZoomBufferStripe(data,resy/16);
632 }
633
634 if (switchIncr != 0) {
635 data->buffratio += switchIncr;
636 if (data->buffratio > BUFFPOINTMASK)
637 data->buffratio = BUFFPOINTMASK;
638 }
639
640 if (switchMult != 1.0f) {
641 data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) +
642 (float) data->buffratio * switchMult);
643 }
644
645 data->zoom_width = data->prevX;
646
647 goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2,
648 data->brutS, data->brutD, data->buffratio, data->precalCoef);
649 }
650
generatePrecalCoef(int precalCoef[16][16])651 static void generatePrecalCoef (int precalCoef[16][16])
652 {
653 int coefh, coefv;
654
655 for (coefh = 0; coefh < 16; coefh++) {
656 for (coefv = 0; coefv < 16; coefv++) {
657
658 int i;
659 int diffcoeffh;
660 int diffcoeffv;
661
662 diffcoeffh = sqrtperte - coefh;
663 diffcoeffv = sqrtperte - coefv;
664
665 if (!(coefh || coefv)) {
666 i = 255;
667 }
668 else {
669 int i1, i2, i3, i4;
670
671 i1 = diffcoeffh * diffcoeffv;
672 i2 = coefh * diffcoeffv;
673 i3 = diffcoeffh * coefv;
674 i4 = coefh * coefv;
675
676 // TODO: faire mieux...
677 if (i1) i1--;
678 if (i2) i2--;
679 if (i3) i3--;
680 if (i4) i4--;
681
682 i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24);
683 }
684 precalCoef[coefh][coefv] = i;
685 }
686 }
687 }
688
689 /* VisualFX Wrapper */
690
zoomFilterVisualFXWrapper_init(struct _VISUAL_FX * _this,PluginInfo * info)691 static void zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo *info)
692 {
693 ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData*)malloc(sizeof(ZoomFilterFXWrapperData));
694
695 (void)info;
696 data->coeffs = 0;
697 data->freecoeffs = 0;
698 data->brutS = 0;
699 data->freebrutS = 0;
700 data->brutD = 0;
701 data->freebrutD = 0;
702 data->brutT = 0;
703 data->freebrutT = 0;
704 data->prevX = 0;
705 data->prevY = 0;
706
707 data->mustInitBuffers = 1;
708 data->interlace_start = -2;
709
710 data->general_speed = 0.0f;
711 data->reverse = 0;
712 data->theMode = rand() % 10;
713 data->waveEffect = 0;
714 data->hypercosEffect = 0;
715 data->vPlaneEffect = 0;
716 data->hPlaneEffect = 0;
717 data->noisify = 2;
718
719 /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */
720 data->buffratio = 0;
721 data->firedec = 0;
722
723 data->wave = data->wavesp = 0;
724
725 data->enabled_bp = secure_b_param("Enabled", 1);
726
727 data->params = plugin_parameters ("Zoom Filter", 1);
728 data->params.params[0] = &data->enabled_bp;
729
730 _this->params = &data->params;
731 _this->fx_data = (void*)data;
732
733 /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */
734 generatePrecalCoef(data->precalCoef);
735 }
736
zoomFilterVisualFXWrapper_free(struct _VISUAL_FX * _this)737 static void zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this)
738 {
739 ZoomFilterFXWrapperData *data = _this->fx_data;
740 if (data) {
741 free (data->params.params);
742 free(data->freebrutS);
743 free(data->freebrutD);
744 free(data->freebrutT);
745 free(data->firedec);
746 free (data);
747 }
748 }
749
zoomFilterVisualFXWrapper_apply(struct _VISUAL_FX * _this,Pixel * src,Pixel * dest,PluginInfo * info)750 static void zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel *src, Pixel *dest, PluginInfo *info)
751 {
752 (void)_this;
753 (void)src;
754 (void)dest;
755 (void)info;
756 }
757
zoomFilterVisualFXWrapper_create(void)758 VisualFX zoomFilterVisualFXWrapper_create(void)
759 {
760 VisualFX fx = {
761 .init = zoomFilterVisualFXWrapper_init,
762 .free = zoomFilterVisualFXWrapper_free,
763 .apply = zoomFilterVisualFXWrapper_apply
764 };
765 return fx;
766 }
767
768
769 /* TODO : MOVE THIS AWAY */
770
pointFilter(PluginInfo * goomInfo,Pixel * pix1,Color c,float t1,float t2,float t3,float t4,Uint cycle)771 void pointFilter (PluginInfo *goomInfo, Pixel * pix1, Color c, float t1, float t2, float t3, float t4, Uint cycle)
772 {
773 Uint x = (Uint) ((int) (goomInfo->screen.width / 2)
774 + (int) (t1 * cos ((float) cycle / t3)));
775 Uint y = (Uint) ((int) (goomInfo->screen.height/2)
776 + (int) (t2 * sin ((float) cycle / t4)));
777
778 if ((x > 1) && (y > 1) && ((int)x < goomInfo->screen.width - 2) && ((int)y < goomInfo->screen.height - 2)) {
779 setPixelRGB (goomInfo, pix1, x + 1, y, c);
780 setPixelRGB (goomInfo, pix1, x, y + 1, c);
781 setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE);
782 setPixelRGB (goomInfo, pix1, x + 2, y + 1, c);
783 setPixelRGB (goomInfo, pix1, x + 1, y + 2, c);
784 }
785 }
786