/* 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);
}
}