/* 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(), gérant les 3 couleurs * -optimisation de sinFilter (utilisant une table de sin) * -asm * -optimisation de la procedure de génération du buffer de transformation * la vitesse est maintenant comprise dans [0..128] au lieu de [0..100] */ /*#define _DEBUG_PIXEL; */ #include "filters.h" #include "graphic.h" #include "goom_tools.h" #include #include #include #ifdef MMX #define USE_ASM #endif #ifdef POWERPC #define USE_ASM #endif #ifdef USE_ASM #define EFFECT_DISTORS 4 #else #define EFFECT_DISTORS 10 #endif extern volatile guint32 resolx; extern volatile guint32 resoly; #ifdef USE_ASM #ifdef MMX int mmx_zoom () ; guint32 mmx_zoom_size; #endif /* MMX */ #ifdef POWERPC extern unsigned int useAltivec; extern void ppc_zoom(void); extern void ppc_zoom_altivec(void); unsigned int ppcsize4; #endif /* PowerPC */ unsigned int *coeffs = 0, *freecoeffs = 0; guint32 *expix1 = 0; /* pointeur exporte vers p1 */ guint32 *expix2 = 0; /* pointeur exporte vers p2 */ guint32 zoom_width; #endif /* ASM */ static int sintable [0xffff] ; static int vitesse = 127; static char theMode = AMULETTE_MODE ; static int vPlaneEffect = 0; static int hPlaneEffect = 0; static char noisify = 2; static int middleX , middleY ; static unsigned char sqrtperte = 16 ; static int * firedec = 0 ; /* retourne x>>s , en testant le signe de x */ inline int ShiftRight (int x, const unsigned char s) { if (x<0) return -(-x >> s) ; else return x >> s ; } /* 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) */ void calculatePXandPY (int x, int y, int *px, int *py) { if (theMode == WATER_MODE) { static int wave = 0 ; static int wavesp = 0 ; int yy ; yy = y + RAND () % 4 + wave / 10 ; yy -= RAND () % 4; if (yy < 0) yy = 0 ; if (yy >= resoly) yy = resoly - 1 ; *px = (x<<4) + firedec [yy] + (wave / 10) ; *py = (y<<4) + 132 - ((vitesse < 132) ? vitesse : 131) ; wavesp += RAND () % 3; wavesp -= RAND () % 3; if (wave < -10) wavesp += 2 ; if (wave > 10) wavesp -= 2 ; wave += (wavesp / 10) + RAND () % 3; wave -= RAND () % 3; if (wavesp > 100) wavesp = (wavesp * 9) / 10 ; } else { int dist ; register int vx,vy ; int fvitesse = vitesse << 4 ; if (noisify) { x += RAND() % noisify; x -= RAND() % noisify; y += RAND() % noisify; y -= RAND() % noisify; } if (hPlaneEffect) vx = ((x - middleX) << 9) + hPlaneEffect * (y - middleY); else vx = (x - middleX) << 9 ; if (vPlaneEffect) vy = ((y - middleY) << 9) + vPlaneEffect * (x - middleX); else vy = (y - middleY) << 9 ; switch (theMode) { case WAVE_MODE: dist = ShiftRight(vx,9) * ShiftRight(vx,9) + ShiftRight(vy,9) * ShiftRight(vy,9); fvitesse *= 1024 + ShiftRight ( sintable [(unsigned short)(0xffff*dist*EFFECT_DISTORS)],6); fvitesse /= 1024 ; break ; case CRYSTAL_BALL_MODE: dist = ShiftRight(vx,9) * ShiftRight(vx,9) + ShiftRight(vy,9) * ShiftRight(vy,9); fvitesse += (dist * EFFECT_DISTORS >> 10); break; case AMULETTE_MODE: dist = ShiftRight(vx,9) * ShiftRight(vx,9) + ShiftRight(vy,9) * ShiftRight(vy,9); fvitesse -= (dist * EFFECT_DISTORS >> 4); break; case SCRUNCH_MODE: dist = ShiftRight(vx,9) * ShiftRight(vx,9) + ShiftRight(vy,9) * ShiftRight(vy,9); fvitesse -= (dist * EFFECT_DISTORS >> 9); break; } if (vx<0) *px = (middleX << 4) - (-(vx * fvitesse) >> 16) ; else *px = (middleX << 4) + ((vx * fvitesse) >> 16) ; if (vy<0) *py = (middleY << 4) - (-(vy * fvitesse) >> 16) ; else *py = (middleY << 4) + ((vy * fvitesse) >> 16) ; } } /*#define _DEBUG */ inline void setPixelRGB(Uint *buffer, Uint x, Uint y, Color c) { /* buffer[ y*WIDTH + x ] = (c.r<<16)|(c.v<<8)|c.b */ #ifdef _DEBUG_PIXEL if ( x+y*resolx >= resolx * resoly) { fprintf (stderr,"setPixel ERROR : hors du tableau... %i, %i\n", x,y) ; /*exit (1) ; */ } #endif #ifdef USE_DGA buffer[ y*resolx + x ] = (c.b<<16)|(c.v<<8)|c.r ; #else buffer[ y*resolx + x ] = (c.r<<16)|(c.v<<8)|c.b ; #endif } inline void setPixelRGB_ (Uint *buffer, Uint x, Color c) { #ifdef _DEBUG if ( x >= resolx*resoly ) { printf ("setPixel ERROR : hors du tableau... %i, %i\n", x,y) ; exit (1) ; } #endif #ifdef USE_DGA buffer[ x ] = (c.b<<16)|(c.v<<8)|c.r ; #else buffer[ x ] = (c.r<<16)|(c.v<<8)|c.b ; #endif } inline void getPixelRGB (Uint *buffer, Uint x, Uint y, Color *c) { register unsigned char *tmp8; #ifdef _DEBUG if (x + y * resolx >= resolx*resoly) { printf ("getPixel ERROR : hors du tableau... %i, %i\n", x,y) ; exit (1) ; } #endif #ifdef __BIG_ENDIAN__ c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + (x + y*resolx))); c->r = *(unsigned char *)(++tmp8); c->v = *(unsigned char *)(++tmp8); c->b = *(unsigned char *)(++tmp8); #else /* ATTENTION AU PETIT INDIEN */ c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + (x + y*resolx))); c->v = *(unsigned char *)(++tmp8); c->r = *(unsigned char *)(++tmp8); /* *c = (Color) buffer[x+y*WIDTH] ; */ #endif } inline void getPixelRGB_ (Uint *buffer, Uint x, Color *c) { register unsigned char *tmp8; #ifdef _DEBUG if ( x >= resolx*resoly ) { printf ("getPixel ERROR : hors du tableau... %i\n", x) ; exit (1) ; } #endif #ifdef __BIG_ENDIAN__ c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + x)); c->r = *(unsigned char *)(++tmp8); c->v = *(unsigned char *)(++tmp8); c->b = *(unsigned char *)(++tmp8); #else /* ATTENTION AU PETIT INDIEN */ c->b = *(unsigned char *)(tmp8 = (unsigned char*)(buffer + x)); c->v = *(unsigned char *)(++tmp8); c->r = *(unsigned char *)(++tmp8); /* *c = (Color) buffer[x+y*WIDTH] ; */ #endif } /*===============================================================*/ void zoomFilterFastRGB (Uint *pix1, Uint *pix2, ZoomFilterData *zf, Uint resx, Uint resy) { static guint32 prevX = 0, prevY = 0; static char reverse = 0 ; /*vitesse inversé..(zoom out) */ /* static int perte = 100; // 100 = normal */ static unsigned char pertedec = 8 ; static char firstTime = 1; Uint x, y; /* static unsigned int prevX = 0, prevY = 0; */ #ifdef USE_ASM expix1 = pix1 ; expix2 = pix2 ; #else Color couleur; Color col1,col2,col3,col4; Uint position ; static unsigned int *pos10 = 0; static unsigned int *c1 = 0, *c2 = 0, *c3 = 0, *c4 = 0; #endif if ((prevX != resx) || (prevY != resy)) { prevX = resx; prevY = resy; #ifndef USE_ASM if (c1) free (c1) ; if (c2) free (c2) ; if (c3) free (c3) ; if (c4) free (c4) ; if (pos10) free (pos10) ; c1=c2=c3=c4=pos10=0; #else if (coeffs) free (freecoeffs) ; coeffs = 0; #endif middleX = resx / 2 ; middleY = resy - 1; firstTime = 1 ; if (firedec) free (firedec); firedec=0; } if (zf) { reverse = zf->reverse ; vitesse = zf->vitesse ; if (reverse) vitesse = 256 - vitesse ; #ifndef USE_ASM sqrtperte = zf->sqrtperte ; #endif pertedec = zf->pertedec ; middleX = zf->middleX ; middleY = zf->middleY ; theMode = zf->mode ; hPlaneEffect = zf->hPlaneEffect; vPlaneEffect = zf->vPlaneEffect; noisify = zf->noisify; } if (firstTime || zf) { /* generation d'une table de sinus */ if (firstTime) { unsigned short us ; firstTime = 0; #ifdef USE_ASM freecoeffs = (unsigned int *) malloc (resx*resy*2*sizeof(unsigned int)+128); coeffs = (guint32 *)((1+((unsigned int)(freecoeffs))/128)*128); #else pos10 = (unsigned int *) malloc (resx*resy*sizeof(unsigned int)) ; c1 = (unsigned int *) malloc (resx*resy*sizeof(unsigned int)) ; c2 = (unsigned int *) malloc (resx*resy*sizeof(unsigned int)) ; c3 = (unsigned int *) malloc (resx*resy*sizeof(unsigned int)) ; c4 = (unsigned int *) malloc (resx*resy*sizeof(unsigned int)) ; #endif for (us=0; us<0xffff; us++) { sintable [us] = (int)(1024.0f * sin (us*2*3.31415f/0xffff)) ; } { int loopv ; firedec = (int *) malloc (prevY * sizeof(int)) ; for (loopv = prevY ; loopv != 0 ;) { static int decc = 0 ; static int spdc = 0 ; static int accel = 0 ; loopv -- ; firedec [loopv] = decc ; decc += spdc / 10 ; spdc+= RAND () % 3; spdc-= RAND () % 3; if (decc > 4) spdc -= 1 ; if (decc < -4) spdc += 1 ; if (spdc > 30) spdc = spdc - RAND () % 3 + accel / 10 ; if (spdc < -30) spdc = spdc + RAND () % 3 + accel / 10 ; if (decc > 8 && spdc > 1 ) spdc -= RAND () % 3 - 2 ; if (decc < -8 && spdc < -1 ) spdc += RAND () % 3 + 2 ; if (decc > 8 || decc < -8) decc = decc * 8 / 9 ; accel += RAND () % 2; accel -= RAND () % 2; if (accel > 20) accel -= 2 ; if (accel < -20) accel += 2 ; } } } /* generation du buffer */ for (y = 0 ; y < prevY ; y++) for (x = 0; x < prevX ; x++) { int px,py; unsigned char coefv,coefh; /* calculer px et py en fonction de */ /* x,y,middleX,middleY et theMode */ calculatePXandPY (x,y,&px, &py) ; if ((px == x << 4) && (py == y << 4)) py += 8 ; if ( (py<0) || (px<0) || (py>=(prevY-1)*sqrtperte) || (px>=(prevX-1)*sqrtperte)) { #ifdef USE_ASM coeffs[(y*prevX+x)*2]=0 ; coeffs[(y*prevX+x)*2+1]=0; #else pos10[y*prevX+x]=0 ; c1[y*prevX+x] = 0 ; c2[y*prevX+x] = 0 ; c3[y*prevX+x] = 0 ; c4[y*prevX+x] = 0 ; #endif } else { int npx10 ; int npy10 ; int pos; npx10 = (px/sqrtperte) ; npy10 = (py/sqrtperte) ; /* if (npx10 >= prevX) fprintf(stderr,"error npx:%d",npx10); if (npy10 >= prevY) fprintf(stderr,"error npy:%d",npy10); */ coefh = px % sqrtperte ; coefv = py % sqrtperte ; #ifdef USE_ASM pos = (y*prevX+x)*2; coeffs[pos] = (npx10 + prevX * npy10) * 4; if (!(coefh || coefv)) coeffs[pos+1] = (sqrtperte*sqrtperte-1) ; else coeffs[pos+1] = ( (sqrtperte-coefh) * (sqrtperte-coefv) ); coeffs[pos+1] |= (coefh * (sqrtperte-coefv)) << 8 ; coeffs[pos+1] |= ((sqrtperte-coefh) * coefv) << 16 ; coeffs[pos+1] |= (coefh * coefv)<<24 ; #else pos = y*prevX+x; pos10[pos]= npx10 + prevX * npy10 ; if (!(coefh || coefv)) c1[pos] = sqrtperte*sqrtperte-1 ; else c1[pos] = (sqrtperte-coefh) * (sqrtperte-coefv); c2[pos] = coefh * (sqrtperte-coefv) ; c3[pos] = (sqrtperte-coefh) * coefv ; c4[pos] = coefh * coefv ; #endif } } } #ifdef USE_ASM #ifdef MMX zoom_width = prevX ; mmx_zoom_size = prevX * prevY ; mmx_zoom () ; #endif #ifdef POWERPC zoom_width = prevX; if (useAltivec) { ppcsize4 = ((unsigned int)(prevX*prevY))/4; ppc_zoom_altivec(); } else { ppcsize4 = ((unsigned int)(prevX*prevY)); ppc_zoom(); } #endif #else for (position=0; position>= pertedec ; couleur.v = col1.v * c1[position] + col2.v * c2[position] + col3.v * c3[position] + col4.v * c4[position]; couleur.v >>= pertedec ; couleur.b = col1.b * c1[position] + col2.b * c2[position] + col3.b * c3[position] + col4.b * c4[position]; couleur.b >>= pertedec ; setPixelRGB_(pix2,position,couleur); } #endif } void pointFilter(Uint *pix1, Color c, float t1, float t2, float t3, float t4, Uint cycle) { Uint x = (Uint)((int)middleX + (int)(t1*cos((float)cycle/t3))); Uint y = (Uint)((int)middleY + (int)(t2*sin((float)cycle/t4))); if ((x>1) && (y>1) && (x