/* 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. */ // --- CHUI EN TRAIN DE SUPPRIMER LES EXTERN RESOLX ET C_RESOLY --- /* filter.c version 0.7 * contient les filtres applicable a un buffer * creation : 01/10/2000 * -ajout de sinFilter() * -ajout de zoomFilter() * -copie de zoomFilter() en zoomFilterRGB(), gerant les 3 couleurs * -optimisation de sinFilter (utilisant une table de sin) * -asm * -optimisation de la procedure de generation du buffer de transformation * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100] */ /* #define _DEBUG_PIXEL */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #ifdef HAVE_INTTYPES_H #include #endif #include "goom_filters.h" #include "goom_graphic.h" #include "goom_tools.h" #include "goom_plugin_info.h" #include "goom_fx.h" #include "v3d.h" /* TODO : MOVE THIS AWAY !!! */ /* jeko: j'ai essayer de le virer, mais si on veut les laisser inline c'est un peu lourdo... */ static inline void setPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color c) { Pixel i; i.channels.b = c.b; i.channels.g = c.v; i.channels.r = c.r; *(buffer + (x + y * goomInfo->screen.width)) = i; } static inline void setPixelRGB_ (Pixel * buffer, Uint x, Color c) { buffer[x].channels.r = c.r; buffer[x].channels.g = c.v; buffer[x].channels.b = c.b; } static inline void getPixelRGB (PluginInfo * goomInfo, Pixel * buffer, Uint x, Uint y, Color * c) { Pixel i = *(buffer + (x + y * goomInfo->screen.width)); c->b = i.channels.b; c->v = i.channels.g; c->r = i.channels.r; } static inline void getPixelRGB_ (Pixel * buffer, Uint x, Color * c) { Pixel i = *(buffer + x); c->b = i.channels.b; c->v = i.channels.g; c->r = i.channels.r; } /* END TODO */ /* DEPRECATED */ // retourne x>>s , en testant le signe de x //#define ShiftRight(_x,_s) (((_x)<0) ? -(-(_x)>>(_s)) : ((_x)>>(_s))) //#define EFFECT_DISTORS 4 //#define EFFECT_DISTORS_SL 2 //#define INTERLACE_ADD 9 //#define INTERLACE_AND 0xf /* END DEPRECATED */ #define BUFFPOINTNB 16 #define BUFFPOINTNBF 16.0f #define BUFFPOINTMASK 0xffff #define sqrtperte 16 /* faire : a % sqrtperte <=> a & pertemask */ #define PERTEMASK 0xf /* faire : a / sqrtperte <=> a >> PERTEDEC */ #define PERTEDEC 4 /* pure c version of the zoom filter */ 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]); /* simple wrapper to give it the same proto than the others */ void zoom_filter_c (int sizeX, int sizeY, Pixel * src, Pixel * dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]) { c_zoom (src, dest, sizeX, sizeY, brutS, brutD, buffratio, precalCoef); } static void generatePrecalCoef (int precalCoef[BUFFPOINTNB][BUFFPOINTNB]); typedef struct _ZOOM_FILTER_FX_WRAPPER_DATA { PluginParam enabled_bp; PluginParameters params; unsigned int *coeffs, *freecoeffs; signed int *brutS, *freebrutS; /* source */ signed int *brutD, *freebrutD; /* dest */ signed int *brutT, *freebrutT; /* temp (en cours de generation) */ guint32 zoom_width; unsigned int prevX, prevY; float general_speed; int reverse; /* reverse the speed */ char theMode; int waveEffect; int hypercosEffect; int vPlaneEffect; int hPlaneEffect; char noisify; int middleX, middleY; int mustInitBuffers; int interlace_start; /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */ int buffratio; int *firedec; /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */ int precalCoef[BUFFPOINTNB][BUFFPOINTNB]; /** calculatePXandPY statics */ int wave; int wavesp; } ZoomFilterFXWrapperData; static inline v2g zoomVector (ZoomFilterFXWrapperData * data, float X, float Y) { v2g vecteur; float vx, vy; float sq_dist = X * X + Y * Y; /* sx = (X < 0.0f) ? -1.0f : 1.0f; sy = (Y < 0.0f) ? -1.0f : 1.0f; */ float coefVitesse = (1.0f + data->general_speed) / 50.0f; // Effects /* Centralized FX */ switch (data->theMode) { case CRYSTAL_BALL_MODE: coefVitesse -= (sq_dist - 0.3f) / 15.0f; break; case AMULETTE_MODE: coefVitesse += sq_dist * 3.5f; break; case WAVE_MODE: coefVitesse += sin (sq_dist * 20.0f) / 100.0f; break; case SCRUNCH_MODE: coefVitesse += sq_dist / 10.0f; break; //case HYPERCOS1_MODE: break; //case HYPERCOS2_MODE: break; //case YONLY_MODE: break; case SPEEDWAY_MODE: coefVitesse *= 4.0f * Y; break; default: break; } if (coefVitesse < -2.01f) coefVitesse = -2.01f; if (coefVitesse > 2.01f) coefVitesse = 2.01f; vx = coefVitesse * X; vy = coefVitesse * Y; /* Amulette 2 */ // vx = X * tan(dist); // vy = Y * tan(dist); /* Rotate */ //vx = (X+Y)*0.1; //vy = (Y-X)*0.1; // Effects adds-on /* Noise */ if (data->noisify) { vx += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f; vy += (((float) rand ()) / ((float) RAND_MAX) - 0.5f) / 50.0f; } /* Hypercos */ if (data->hypercosEffect) { vx += sin (Y * 10.0f) / 120.0f; vy += sin (X * 10.0f) / 120.0f; } /* H Plane */ if (data->hPlaneEffect) vx += Y * 0.0025f * data->hPlaneEffect; /* V Plane */ if (data->vPlaneEffect) vy += X * 0.0025f * data->vPlaneEffect; /* TODO : Water Mode */ // if (data->waveEffect) vecteur.x = vx; vecteur.y = vy; return vecteur; } /* * Makes a stripe of a transform buffer (brutT) * * The transform is (in order) : * Translation (-data->middleX, -data->middleY) * Homothetie (Center : 0,0 Coeff : 2/data->prevX) */ static void makeZoomBufferStripe (ZoomFilterFXWrapperData * data, int INTERLACE_INCR) { // Position of the pixel to compute in pixmap coordinates Uint x, y; // Where (verticaly) to stop generating the buffer stripe int maxEnd; // Ratio from pixmap to normalized coordinates float ratio = 2.0f / ((float) data->prevX); // Ratio from normalized to virtual pixmap coordinates float inv_ratio = BUFFPOINTNBF / ratio; float min = ratio / BUFFPOINTNBF; // Y position of the pixel to compute in normalized coordinates float Y = ((float) (data->interlace_start - data->middleY)) * ratio; maxEnd = data->prevY; if (maxEnd > (data->interlace_start + INTERLACE_INCR)) maxEnd = (data->interlace_start + INTERLACE_INCR); for (y = data->interlace_start; (y < data->prevY) && ((signed int) y < maxEnd); y++) { Uint premul_y_prevX = y * data->prevX * 2; float X = -((float) data->middleX) * ratio; for (x = 0; x < data->prevX; x++) { v2g vector = zoomVector (data, X, Y); /* Finish and avoid null displacement */ if (fabs (vector.x) < min) vector.x = (vector.x < 0.0f) ? -min : min; if (fabs (vector.y) < min) vector.y = (vector.y < 0.0f) ? -min : min; data->brutT[premul_y_prevX] = ((int) ((X - vector.x) * inv_ratio) + ((int) (data->middleX * BUFFPOINTNB))); data->brutT[premul_y_prevX + 1] = ((int) ((Y - vector.y) * inv_ratio) + ((int) (data->middleY * BUFFPOINTNB))); premul_y_prevX += 2; X += ratio; } Y += ratio; } data->interlace_start += INTERLACE_INCR; if (y >= data->prevY - 1) data->interlace_start = -1; } /* * calculer px et py en fonction de x,y,middleX,middleY et theMode * px et py indique la nouvelle position (en sqrtperte ieme de pixel) * (valeur * 16) inline void calculatePXandPY (PluginInfo *goomInfo, ZoomFilterFXWrapperData *data, int x, int y, int *px, int *py) { if (data->theMode == WATER_MODE) { int yy; yy = y + goom_irand(goomInfo->gRandom, 4) - goom_irand(goomInfo->gRandom, 4) + data->wave / 10; if (yy < 0) yy = 0; if (yy >= (signed int)goomInfo->screen.height) yy = goomInfo->screen.height - 1; *px = (x << 4) + data->firedec[yy] + (data->wave / 10); *py = (y << 4) + 132 - ((data->vitesse < 131) ? data->vitesse : 130); data->wavesp += goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3); if (data->wave < -10) data->wavesp += 2; if (data->wave > 10) data->wavesp -= 2; data->wave += (data->wavesp / 10) + goom_irand(goomInfo->gRandom, 3) - goom_irand(goomInfo->gRandom, 3); if (data->wavesp > 100) data->wavesp = (data->wavesp * 9) / 10; } else { int dist = 0, vx9, vy9; int vx, vy; int ppx, ppy; int fvitesse = data->vitesse << 4; if (data->noisify) { x += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify); y += goom_irand(goomInfo->gRandom, data->noisify) - goom_irand(goomInfo->gRandom, data->noisify); } vx = (x - data->middleX) << 9; vy = (y - data->middleY) << 9; if (data->hPlaneEffect) vx += data->hPlaneEffect * (y - data->middleY); if (data->vPlaneEffect) vy += data->vPlaneEffect * (x - data->middleX); if (data->waveEffect) { fvitesse *= 1024 + ShiftRight (goomInfo->sintable [(unsigned short) (dist * 0xffff + EFFECT_DISTORS)], 6); fvitesse /= 1024; } if (data->hypercosEffect) { vx += ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1); vy += ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1); } vx9 = ShiftRight (vx, 9); vy9 = ShiftRight (vy, 9); dist = vx9 * vx9 + vy9 * vy9; switch (data->theMode) { case WAVE_MODE: fvitesse *= 1024 + ShiftRight (goomInfo->sintable [(unsigned short) (dist * 0xffff * EFFECT_DISTORS)], 6); fvitesse>>=10; break; case CRYSTAL_BALL_MODE: fvitesse += (dist >> (10-EFFECT_DISTORS_SL)); break; case AMULETTE_MODE: fvitesse -= (dist >> (4 - EFFECT_DISTORS_SL)); break; case SCRUNCH_MODE: fvitesse -= (dist >> (10 - EFFECT_DISTORS_SL)); break; case HYPERCOS1_MODE: vx = vx + ShiftRight (goomInfo->sintable[(-vy + dist) & 0xffff], 1); vy = vy + ShiftRight (goomInfo->sintable[(vx + dist) & 0xffff], 1); break; case HYPERCOS2_MODE: vx = vx + ShiftRight (goomInfo->sintable[(-ShiftRight (vy, 1) + dist) & 0xffff], 0); vy = vy + ShiftRight (goomInfo->sintable[(ShiftRight (vx, 1) + dist) & 0xffff], 0); fvitesse = 128 << 4; break; case YONLY_MODE: fvitesse *= 1024 + ShiftRight (goomInfo->sintable[vy & 0xffff], 6); fvitesse >>= 10; break; case SPEEDWAY_MODE: fvitesse -= (ShiftRight(vy,10-EFFECT_DISTORS_SL)); break; } if (fvitesse < -3024) fvitesse = -3024; if (vx < 0) // pb avec decalage sur nb negatif ppx = -(-(vx * fvitesse) >> 16); // 16 = 9 + 7 (7 = nb chiffre virgule de vitesse * (v = 128 => immobile) // * * * * * 9 = nb chiffre virgule de vx) else ppx = ((vx * fvitesse) >> 16); if (vy < 0) ppy = -(-(vy * fvitesse) >> 16); else ppy = ((vy * fvitesse) >> 16); *px = (data->middleX << 4) + ppx; *py = (data->middleY << 4) + ppy; } } */ static void c_zoom (Pixel * expix1, Pixel * expix2, unsigned int prevX, unsigned int prevY, signed int *brutS, signed int *brutD, int buffratio, int precalCoef[16][16]) { int myPos, myPos2; Color couleur; unsigned int ax = (prevX - 1) << PERTEDEC, ay = (prevY - 1) << PERTEDEC; int bufsize = prevX * prevY * 2; int bufwidth = prevX; expix1[0].val = expix1[prevX - 1].val = expix1[prevX * prevY - 1].val = expix1[prevX * prevY - prevX].val = 0; for (myPos = 0; myPos < bufsize; myPos += 2) { Color col1, col2, col3, col4; int c1, c2, c3, c4, px, py; int pos; int coeffs; int brutSmypos = brutS[myPos]; myPos2 = myPos + 1; px = brutSmypos + (((brutD[myPos] - brutSmypos) * buffratio) >> BUFFPOINTNB); brutSmypos = brutS[myPos2]; py = brutSmypos + (((brutD[myPos2] - brutSmypos) * buffratio) >> BUFFPOINTNB); if ((py >= ay) || (px >= ax)) { pos = coeffs = 0; } else { pos = ((px >> PERTEDEC) + prevX * (py >> PERTEDEC)); /* coef en modulo 15 */ coeffs = precalCoef[px & PERTEMASK][py & PERTEMASK]; } getPixelRGB_ (expix1, pos, &col1); getPixelRGB_ (expix1, pos + 1, &col2); getPixelRGB_ (expix1, pos + bufwidth, &col3); getPixelRGB_ (expix1, pos + bufwidth + 1, &col4); c1 = coeffs; c2 = (c1 >> 8) & 0xFF; c3 = (c1 >> 16) & 0xFF; c4 = (c1 >> 24) & 0xFF; c1 = c1 & 0xff; couleur.r = col1.r * c1 + col2.r * c2 + col3.r * c3 + col4.r * c4; if (couleur.r > 5) couleur.r -= 5; couleur.r >>= 8; couleur.v = col1.v * c1 + col2.v * c2 + col3.v * c3 + col4.v * c4; if (couleur.v > 5) couleur.v -= 5; couleur.v >>= 8; couleur.b = col1.b * c1 + col2.b * c2 + col3.b * c3 + col4.b * c4; if (couleur.b > 5) couleur.b -= 5; couleur.b >>= 8; setPixelRGB_ (expix2, myPos >> 1, couleur); } } /** generate the water fx horizontal direction buffer */ static void generateTheWaterFXHorizontalDirectionBuffer (PluginInfo * goomInfo, ZoomFilterFXWrapperData * data) { int loopv; int decc = goom_irand (goomInfo->gRandom, 8) - 4; int spdc = goom_irand (goomInfo->gRandom, 8) - 4; int accel = goom_irand (goomInfo->gRandom, 8) - 4; for (loopv = data->prevY; loopv != 0;) { loopv--; data->firedec[loopv] = decc; decc += spdc / 10; spdc += goom_irand (goomInfo->gRandom, 3) - goom_irand (goomInfo->gRandom, 3); if (decc > 4) spdc -= 1; if (decc < -4) spdc += 1; if (spdc > 30) spdc = spdc - goom_irand (goomInfo->gRandom, 3) + accel / 10; if (spdc < -30) spdc = spdc + goom_irand (goomInfo->gRandom, 3) + accel / 10; if (decc > 8 && spdc > 1) spdc -= goom_irand (goomInfo->gRandom, 3) - 2; if (decc < -8 && spdc < -1) spdc += goom_irand (goomInfo->gRandom, 3) + 2; if (decc > 8 || decc < -8) decc = decc * 8 / 9; accel += goom_irand (goomInfo->gRandom, 2) - goom_irand (goomInfo->gRandom, 2); if (accel > 20) accel -= 2; if (accel < -20) accel += 2; } } /** * Main work for the dynamic displacement map. * * Reads data from pix1, write to pix2. * * Useful datas for this FX are stored in ZoomFilterData. * * If you think that this is a strange function name, let me say that a long time ago, * there has been a slow version and a gray-level only one. Then came these function, * fast and workin in RGB colorspace ! nice but it only was applying a zoom to the image. * So that is why you have this name, for the nostalgy of the first days of goom * when it was just a tiny program writen in Turbo Pascal on my i486... */ void zoomFilterFastRGB (PluginInfo * goomInfo, Pixel * pix1, Pixel * pix2, ZoomFilterData * zf, Uint resx, Uint resy, int switchIncr, float switchMult) { Uint x, y; ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) goomInfo->zoomFilter_fx.fx_data; if (!BVAL (data->enabled_bp)) return; /** changement de taille **/ if ((data->prevX != resx) || (data->prevY != resy)) { data->prevX = resx; data->prevY = resy; if (data->brutS) free (data->freebrutS); data->brutS = 0; if (data->brutD) free (data->freebrutD); data->brutD = 0; if (data->brutT) free (data->freebrutT); data->brutT = 0; data->middleX = resx / 2; data->middleY = resy / 2; data->mustInitBuffers = 1; if (data->firedec) free (data->firedec); data->firedec = 0; } if (data->interlace_start != -2) zf = NULL; /** changement de config **/ if (zf) { data->reverse = zf->reverse; data->general_speed = (float) (zf->vitesse - 128) / 128.0f; if (data->reverse) data->general_speed = -data->general_speed; data->middleX = zf->middleX; data->middleY = zf->middleY; data->theMode = zf->mode; data->hPlaneEffect = zf->hPlaneEffect; data->vPlaneEffect = zf->vPlaneEffect; data->waveEffect = zf->waveEffect; data->hypercosEffect = zf->hypercosEffect; data->noisify = zf->noisify; data->interlace_start = 0; } if (data->mustInitBuffers) { data->mustInitBuffers = 0; data->freebrutS = (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); data->brutS = (gint32 *) ((1 + ((uintptr_t) (data->freebrutS)) / 128) * 128); data->freebrutD = (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); data->brutD = (gint32 *) ((1 + ((uintptr_t) (data->freebrutD)) / 128) * 128); data->freebrutT = (signed int *) calloc (resx * resy * 2 + 128, sizeof (unsigned int)); data->brutT = (gint32 *) ((1 + ((uintptr_t) (data->freebrutT)) / 128) * 128); data->buffratio = 0; data->firedec = (int *) malloc (data->prevY * sizeof (int)); generateTheWaterFXHorizontalDirectionBuffer (goomInfo, data); data->interlace_start = 0; makeZoomBufferStripe (data, resy); /* Copy the data from temp to dest and source */ memcpy (data->brutS, data->brutT, resx * resy * 2 * sizeof (int)); memcpy (data->brutD, data->brutT, resx * resy * 2 * sizeof (int)); } /* generation du buffer de trans */ if (data->interlace_start == -1) { /* sauvegarde de l'etat actuel dans la nouvelle source * TODO: write that in MMX (has been done in previous version, but did not follow some new fonctionnalities) */ y = data->prevX * data->prevY * 2; for (x = 0; x < y; x += 2) { int brutSmypos = data->brutS[x]; int x2 = x + 1; data->brutS[x] = brutSmypos + (((data->brutD[x] - brutSmypos) * data->buffratio) >> BUFFPOINTNB); brutSmypos = data->brutS[x2]; data->brutS[x2] = brutSmypos + (((data->brutD[x2] - brutSmypos) * data->buffratio) >> BUFFPOINTNB); } data->buffratio = 0; } if (data->interlace_start == -1) { signed int *tmp; tmp = data->brutD; data->brutD = data->brutT; data->brutT = tmp; tmp = data->freebrutD; data->freebrutD = data->freebrutT; data->freebrutT = tmp; data->interlace_start = -2; } if (data->interlace_start >= 0) { /* creation de la nouvelle destination */ makeZoomBufferStripe (data, resy / 16); } if (switchIncr != 0) { data->buffratio += switchIncr; if (data->buffratio > BUFFPOINTMASK) data->buffratio = BUFFPOINTMASK; } if (switchMult != 1.0f) { data->buffratio = (int) ((float) BUFFPOINTMASK * (1.0f - switchMult) + (float) data->buffratio * switchMult); } data->zoom_width = data->prevX; goomInfo->methods.zoom_filter (data->prevX, data->prevY, pix1, pix2, data->brutS, data->brutD, data->buffratio, data->precalCoef); } static void generatePrecalCoef (int precalCoef[16][16]) { int coefh, coefv; for (coefh = 0; coefh < 16; coefh++) { for (coefv = 0; coefv < 16; coefv++) { int i; int diffcoeffh; int diffcoeffv; diffcoeffh = sqrtperte - coefh; diffcoeffv = sqrtperte - coefv; if (!(coefh || coefv)) { i = 255; } else { int i1, i2, i3, i4; i1 = diffcoeffh * diffcoeffv; i2 = coefh * diffcoeffv; i3 = diffcoeffh * coefv; i4 = coefh * coefv; // TODO: faire mieux... if (i1) i1--; if (i2) i2--; if (i3) i3--; if (i4) i4--; i = (i1) | (i2 << 8) | (i3 << 16) | (i4 << 24); } precalCoef[coefh][coefv] = i; } } } /* VisualFX Wrapper */ static void zoomFilterVisualFXWrapper_init (struct _VISUAL_FX *_this, PluginInfo * info) { ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) malloc (sizeof (ZoomFilterFXWrapperData)); data->coeffs = 0; data->freecoeffs = 0; data->brutS = 0; data->freebrutS = 0; data->brutD = 0; data->freebrutD = 0; data->brutT = 0; data->freebrutT = 0; data->prevX = 0; data->prevY = 0; data->mustInitBuffers = 1; data->interlace_start = -2; data->general_speed = 0.0f; data->reverse = 0; data->theMode = AMULETTE_MODE; data->waveEffect = 0; data->hypercosEffect = 0; data->vPlaneEffect = 0; data->hPlaneEffect = 0; data->noisify = 2; /** modif by jeko : fixedpoint : buffration = (16:16) (donc 0<=buffration<=2^16) */ data->buffratio = 0; data->firedec = 0; data->wave = data->wavesp = 0; data->enabled_bp = secure_b_param ("Enabled", 1); data->params = plugin_parameters ("Zoom Filter", 1); data->params.params[0] = &data->enabled_bp; _this->params = &data->params; _this->fx_data = (void *) data; /** modif d'optim by Jeko : precalcul des 4 coefs resultant des 2 pos */ generatePrecalCoef (data->precalCoef); } static void zoomFilterVisualFXWrapper_free (struct _VISUAL_FX *_this) { ZoomFilterFXWrapperData *data = (ZoomFilterFXWrapperData *) _this->fx_data; if (data->freebrutT) free (data->freebrutT); if (data->freebrutS) free (data->freebrutS); if (data->freebrutD) free (data->freebrutD); if (data->firedec) free (data->firedec); goom_plugin_parameters_free (_this->params); free (_this->fx_data); } static void zoomFilterVisualFXWrapper_apply (struct _VISUAL_FX *_this, Pixel * src, Pixel * dest, PluginInfo * info) { } VisualFX zoomFilterVisualFXWrapper_create (void) { VisualFX fx; fx.init = zoomFilterVisualFXWrapper_init; fx.free = zoomFilterVisualFXWrapper_free; fx.apply = zoomFilterVisualFXWrapper_apply; fx.params = NULL; fx.fx_data = NULL; return fx; } /* TODO : MOVE THIS AWAY */ void pointFilter (PluginInfo * goomInfo, Pixel * pix1, Color c, float t1, float t2, float t3, float t4, Uint cycle) { Uint x = (Uint) ((int) (goomInfo->screen.width / 2) + (int) (t1 * cos ((float) cycle / t3))); Uint y = (Uint) ((int) (goomInfo->screen.height / 2) + (int) (t2 * sin ((float) cycle / t4))); if ((x > 1) && (y > 1) && (x < goomInfo->screen.width - 2) && (y < goomInfo->screen.height - 2)) { setPixelRGB (goomInfo, pix1, x + 1, y, c); setPixelRGB (goomInfo, pix1, x, y + 1, c); setPixelRGB (goomInfo, pix1, x + 1, y + 1, WHITE); setPixelRGB (goomInfo, pix1, x + 2, y + 1, c); setPixelRGB (goomInfo, pix1, x + 1, y + 2, c); } }