/* Libvisual-plugins - Standard plugins for libvisual * * Copyright (C) 2000, 2001 Pascal Brochart * * Authors: Pascal Brochart * Dennis Smit * * $Id: * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "actor_plazma.h" #include "plazma.h" #ifndef PI #define PI 3.14159265358979323846 #endif #define RESFACTXF(par1) ( (float) priv->width*(par1)/priv->video->width ) #define RESFACTYF(par1) ( (float) priv->height*(par1)/priv->video->height ) /* New prototypes */ static void do_plasma(PlazmaPrivate *priv, double x1, double y1, double x2, double y2, unsigned char *t); static void what_display(PlazmaPrivate *priv); static void plazma_create(PlazmaPrivate *priv); static void aff_pixel(PlazmaPrivate *priv, int x, int y, int colpix); static void cercle (PlazmaPrivate *priv, int h, int k, int y, uint8_t colcer); static void droite (PlazmaPrivate *priv, int x1, int y1, int x2, int y2, uint8_t color); static void grille_3d (PlazmaPrivate *priv, float alpha, float beta, float gamma, int persp, int dist_cam, int col_grille_3d, int cx, int cy); static void cercle_3d (PlazmaPrivate *priv, float alpha, float beta, float gamma, int persp, int dist_cam, int col_grille_3d, int cx, int cy); static void do_radial_wave(PlazmaPrivate *priv); static void do_tourni_spec(PlazmaPrivate *priv); static void do_lines(PlazmaPrivate *priv); static void do_grille_3d(PlazmaPrivate *priv); static void do_spectrum(PlazmaPrivate *priv); static void do_cercle_3d(PlazmaPrivate *priv); void _plazma_run (PlazmaPrivate *priv) { if (priv->state == priv->old_state) priv->state++; priv->old_state = priv->state; switch (priv->effect) { case 0: do_plasma(priv, (sin(((double)priv->state)*priv->R[0])+1)/2, (sin(((double)priv->state)*priv->R[1])+1)/2, (cos(((double)priv->state)*priv->R[2])+1)/2, (cos(((double)priv->state)*priv->R[3])+1)/2, priv->tmem); break; case 1: do_plasma(priv, (sin(((double)priv->state)*priv->R[0])+1)/2, (sin(((double)priv->state)*priv->R[1])+1)/2, (cos(((double)priv->state)*priv->R[2])+1)/2, (cos(((double)priv->state)*priv->R[3])+1)/2, priv->tmem1); break; } what_display(priv); } void _plazma_init(PlazmaPrivate *priv) { int c, i; float halfPI = (float)PI/2; for (c=0; c<4; c++) priv->R[c]=((double)(cos(c)*120))/5000; priv->tmem = visual_mem_malloc0 (priv->tabley*priv->tablex); priv->tmem1 = visual_mem_malloc0 (priv->tabley*priv->tablex); priv->cosw.i = priv->width; priv->cosw.f = visual_mem_malloc0(sizeof(float)*priv->width); for (i=0; iwidth;i++) priv->cosw.f[i] = cos((float)i/priv->width*PI+halfPI); priv->sinw.i = priv->width; priv->sinw.f = visual_mem_malloc0(sizeof(float)*priv->width); for (i=0; iwidth;i++) priv->sinw.f[i] = sin((float)i/priv->width*PI+halfPI); plazma_create(priv); _plazma_change_effect(priv); } void _plazma_cleanup(PlazmaPrivate *priv) { if (priv->tmem != NULL) visual_mem_free (priv->tmem); if (priv->tmem1 != NULL) visual_mem_free (priv->tmem1); if (priv->cosw.f != NULL) visual_mem_free (priv->cosw.f); if (priv->sinw.f != NULL) visual_mem_free (priv->sinw.f); } void _plazma_change_effect(PlazmaPrivate *priv) { int c; switch (priv->effect) { case 0: for (c=0 ; c<256; c++) { priv->colors.colors[c].r = (sin(((double)c)/256*6*PI+(sin(445)))+1)*127; priv->colors.colors[c].g = (sin(((double)c)/256*6*PI+(sin(561)))+1)*127; priv->colors.colors[c].b = (cos(((double)c)/256*6*PI+(sin(278)))+1)*127; } break; case 1: for (c=0 ; c<256; c++) { priv->colors.colors[c].r = (sin(((double)c)/256*6*PI+(sin(c/4)))+1)*127; priv->colors.colors[c].g = (sin(((double)c)/256*6*PI+(sin(561)))+1)*127; priv->colors.colors[c].b = (cos(((double)c)/256*6*PI+(sin(278)))+1)*127; } break; } } static void do_plasma(PlazmaPrivate *priv, double x1, double y1, double x2, double y2, unsigned char *t) { unsigned int X1=x1*(priv->tablex/2), Y1=y1*(priv->tabley/2), X2=x2*(priv->tablex/2), Y2=y2*(priv->tabley/2), y; unsigned char *t1=t+X1+Y1*priv->tablex, *t2=t+X2+Y2*priv->tablex; for (y=0; yheight; y++) { unsigned char*tmp = priv->pixel + y * priv->video->pitch; unsigned int t = y*priv->tablex, tmax=t+priv->width; for (t=t; ttabley ; y++) { int x; for (x=0 ; xtablex ; x++) { double tmp = (((double)((x-(priv->tablex/2))*(x-(priv->tablex/2))+(y-(priv->tablex/2))*(y-(priv->tablex/2))))*(PI/(priv->tablex*priv->tablex+priv->tabley*priv->tabley))); priv->tmem[y*priv->tablex+x] = tan(tan(tmp*1500))+(tan(tmp)*40)+sqrt(exp(tmp)*10)+sin(tmp*10); priv->tmem1[y*priv->tablex+x] = sin(exp(tmp*35)*120)+sqrt(tmp*14)+log(exp(tmp*8)+cos(tmp*tmp))+tan(exp(tmp*40)*150)/6; } } } static void aff_pixel(PlazmaPrivate *priv, int x, int y, int colpix) { unsigned char*point, *old_point; if (x<0 || x>(priv->width-1) || y<0 || y>(priv->height-1)) return; point = priv->pixel+y*priv->video->pitch; old_point = point; point[x] = old_point[x] | colpix; if (!priv->use_3d) point[x] = colpix; } static void cercle (PlazmaPrivate *priv, int h, int k, int y, uint8_t colcer) { int x = -1, d = 3 - 2 * y; while (x <= y) { if (d < 0) { d += 4 * x + 6; x++; } else { d += 4 * (x - y) + 10; x++; y--; } aff_pixel (priv, h + x, y + k, colcer); aff_pixel (priv, h + y, x + k, colcer); aff_pixel (priv, h - y, x + k, colcer); aff_pixel (priv, h - x, y + k, colcer); aff_pixel (priv, h - x, -y + k, colcer); aff_pixel (priv, h - y, -x + k, colcer); aff_pixel (priv, h + y, -x + k, colcer); aff_pixel (priv, h + x, -y + k, colcer); } } static void droite (PlazmaPrivate *priv, int x1, int y1, int x2, int y2, uint8_t color) { int lx, ly, dx, dy; int i, j, k; lx = abs(x1-x2); ly = abs(y1-y2); dx = (x1>x2) ? -1 : 1; dy = (y1>y2) ? -1 : 1; if (lx>ly) { for (i=x1,j=y1,k=0;i!=x2;i+=dx,k+=ly) { if (k>=lx) { k -= lx; j += dy; } aff_pixel (priv, i, j, color); } } else { for (i=y1,j=x1,k=0;i!=y2;i+=dy,k+=lx) { if (k>=ly) { k -= ly; j += dx; } aff_pixel (priv, j, i, color); } } } static void rotation_3d (float *x, float *y, float *z, float alpha, float beta, float gamma) { float nx, ny; float cosga = cos (gamma), singa=sin (gamma), cosal=cos (alpha), sinal=sin (alpha); nx = cosga * *x - singa * *y; ny = cosal * (singa * *x + cosga * *y) - sinal * *z; *z = sinal * (singa * *x + cosga * *y) + cosal * *z; *x = nx; *y = ny; } static void perspective (float *x, float *y, float *z, int persp, int dist_cam) { float foc_cam = 100; *x = *x * (foc_cam + persp) / (dist_cam + persp - *z); *y = *y * (foc_cam + persp) / (dist_cam + persp - *z); } static void grille_3d (PlazmaPrivate *priv, float alpha, float beta, float gamma, int persp, int dist_cam, int col_grille_3d, int cx, int cy) { float x, y, z; int16_t ax = 0, ay = 0, ampli_grille = 0, ix, iy, i, j, nb_x, nb_y; nb_x = 32; nb_y = 32; if (priv->spectrum == 0 && priv->lines == 1) ampli_grille = 128; for (i = 0; i < nb_x; i++) { for (j = 0; j < nb_y; j++) { x = RESFACTXF ((i - ((float) nb_x) / 2) * 10); y = RESFACTYF ((j - ((float) nb_y) / 2) * 10); z = RESFACTXF ((float) (priv->pcm_buffer[i + (nb_x/3)*j])/(1024-ampli_grille)); rotation_3d (&x, &y, &z, alpha, beta, gamma); perspective (&x, &y, &z, persp, dist_cam); ix = (int) x; iy = (int) y; if (j != 0) { droite (priv, ix+cx, iy+cy, ax+cx, ay+cy, col_grille_3d); } ax = ix; ay = iy; } } } static void cercle_3d (PlazmaPrivate *priv, float alpha, float beta, float gamma, int persp, int dist_cam, int col_grille_3d, int cx, int cy) { float x, y, z; int16_t ax = 0, ay = 0, ix, iy, i, j, nb_x, nb_y; nb_x = 16; nb_y = 16; for (i = 0; i < nb_x; i++) { for (j = 0; j < nb_y; j++) { x = RESFACTXF ((i - ((float) nb_x) / 2) * 30); y = RESFACTYF ((j - ((float) nb_y) / 2) * 30); z = RESFACTXF ((float) (priv->render_buffer[i + (nb_x/32)*j])/64); rotation_3d (&x, &y, &z, alpha, beta, gamma); perspective (&x, &y, &z, persp, dist_cam); ix = (int) x; iy = (int) y; if (j != 0) { cercle (priv, ix+cx, iy+cy, 3, col_grille_3d); cercle (priv, ax+cx, ay+cy, 3, col_grille_3d); } ax = ix; ay = iy; } } } static void do_radial_wave(PlazmaPrivate *priv) { int i, halfheight, halfwidth, shift, col_fleur; float y1, old_y1, k, opt, opt_old; y1 = priv->pcm_buffer[0]/450; col_fleur = 74; shift = priv->height/3.1; if (priv->effect) col_fleur = 72; halfheight = priv->height >> 1; halfwidth = priv->width >> 1; for (i=1 ; iwidth ; i++) { old_y1 = y1; y1 = priv->pcm_buffer[i]/450; if (y1<-50) y1 = y1/2; for (k=1 ; k<2.6 ; k+=0.4) { opt = shift+(y1/k); opt_old = shift+(old_y1/k); droite (priv, halfwidth + priv->cosw.f[i-1] * opt_old, halfheight + priv->sinw.f[i-1] * opt_old, halfwidth + priv->cosw.f[i] * opt, halfheight + priv->sinw.f[i] * opt, col_fleur); droite (priv, halfwidth - priv->cosw.f[i-1] * opt_old, halfheight + priv->sinw.f[i-1] * opt_old, halfwidth - priv->cosw.f[i] * opt, halfheight + priv->sinw.f[i] * opt, col_fleur); } } for (k=1 ; k<2.6 ; k+=0.4) { opt = shift+(y1/k); droite (priv, halfwidth + priv->cosw.f[1] * opt, halfheight - priv->sinw.f[1] * opt, halfwidth - priv->cosw.f[1] * opt, halfheight - priv->sinw.f[1] * opt, col_fleur); droite (priv, halfwidth - priv->cosw.f[1] * opt, halfheight - priv->sinw.f[1] * opt, halfwidth + priv->cosw.f[1] * opt, halfheight - priv->sinw.f[1] * opt, col_fleur); } } static void do_tourni_spec(PlazmaPrivate *priv) { int i, j, k, l, halfheight, halfwidth, col_tourni, amplitude; float v, vr, x, y; v = 0.1; vr = 0.00001; col_tourni = 52; amplitude = 44; j = 20; k = priv->k_put; l = 1000; halfheight = priv->height >> 1; halfwidth = priv->width >> 1; if (priv->effect) col_tourni = 99; if (priv->lines == 0 && priv->spectrum == 1) { j = 4; l = 2500; amplitude = 88; } for (i=0 ; irot_tourni))*amplitude+(priv->render_buffer[i>>2]/j); y = sin(k/(v*0.6))*amplitude+(priv->render_buffer[i>>2]/20); aff_pixel (priv, x*cos(k*vr)+y*sin(k*vr)+halfwidth, x*sin(k*vr)-y*cos(k*vr)+halfheight, col_tourni); } priv->k_put = k; } static void do_lines(PlazmaPrivate *priv) { int lc, lc2lc, reg_lines,larg_lines; float pluseffect, coul_lines; if (priv->lines == 1 && priv->spectrum == 0) { reg_lines = (priv->height/2)-3; larg_lines = 240; } else { reg_lines = 77; larg_lines = 420; } for (lc=0 ; lcwidth ; lc++) { for (lc2lc=0 ; lc2lc<7 ; lc2lc++) { coul_lines = 55; pluseffect = 0; if (priv->effect) { coul_lines = 227.4; pluseffect = 0.5; } if (lc2lc==0 || lc2lc==1 || lc2lc==4 || lc2lc==5 || lc2lc==6) coul_lines = 400/(3.4+pluseffect); aff_pixel(priv, lc, reg_lines+(priv->pcm_buffer[lc % 1024]/larg_lines)+lc2lc, coul_lines); } } } static void do_spectrum(PlazmaPrivate *priv) { int lc, lc2lc, lc2lc2lc, l_spect, toujours=0, coul_lines; int i=0, too_hard=64, first_decr=FALSE; float precision = 71; if (priv->lines == 0 && priv->spectrum == 1) { priv->val_maxi = priv->height - 150; l_spect = 14; } else { priv->val_maxi = priv->height - 280; l_spect = 32; } for (lc=1 ; lcwidth ; lc+=10 , toujours++, too_hard-=i) { for (lc2lc=0; lc2lc<7 ; lc2lc++, precision+=0.08) { for (lc2lc2lc=0 ; lc2lc2lc<7 ; lc2lc2lc++) { coul_lines=7.4+priv->chcol0+precision+(lc2lc*2); if (lc2lc2lc==0 || lc2lc2lc==1 || lc2lc2lc==5 || lc2lc2lc==6) coul_lines = priv->chcol0+(lc2lc*2); aff_pixel(priv, lc+lc2lc, (priv->height - 10) -((priv->render_buffer[toujours]/(l_spect+too_hard))&priv->val_maxi)+lc2lc2lc, coul_lines); } } if (!too_hard) too_hard = 2; if (lc<33) { i = 6; first_decr = TRUE; } else { if (first_decr) { first_decr = FALSE; too_hard -= 10; } i = 2; } } } static void do_grille_3d(PlazmaPrivate *priv) { int dis_col = 322; if (priv->effect) dis_col = 72; if (priv->spectrum) grille_3d (priv, 1.45, 0, priv->compt_grille_3d/30, 200, 110, dis_col, priv->width / 2, priv->height / 10); else grille_3d (priv, 1.1, 0, priv->compt_grille_3d/30, 200, 20, dis_col, priv->width / 2, priv->height / 5); priv->compt_grille_3d += 0.1; } static void do_cercle_3d(PlazmaPrivate *priv) { int dis_col = 382; if (priv->effect) dis_col = 99; if (priv->lines) cercle_3d (priv, 3.6, 0, priv->compt_cercle_3d/30, 200, 80, dis_col, priv->width / 2, priv->height); else cercle_3d (priv, 3.2, 0, priv->compt_cercle_3d/30, 200, 80, dis_col, priv->width / 2, priv->height / 2); priv->compt_cercle_3d -= 0.1; } static void what_display(PlazmaPrivate *priv) { if (priv->use_3d) { if (priv->options) { if (priv->lines) do_radial_wave(priv); if (priv->spectrum) do_tourni_spec(priv); } else { if (priv->lines) do_grille_3d(priv); if (priv->spectrum) do_cercle_3d(priv); } } else { if (priv->lines) do_lines(priv); if (priv->spectrum) do_spectrum(priv); } }