|
|
|
/*
|
|
|
|
// Copyright (C) 2000 Julien Carme
|
|
|
|
// Copyright (C) 2001 Neil Stevens <neil@qualityassistant.com>
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2, as
|
|
|
|
// published by the Free Software Foundation.
|
|
|
|
//
|
|
|
|
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "renderer.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "display.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
|
|
|
|
|
|
|
SDL_Color color_table[NB_PALETTES][256];
|
|
|
|
short current_colors[256];
|
|
|
|
|
|
|
|
byte* surface1;
|
|
|
|
byte* surface2;
|
|
|
|
|
|
|
|
void generate_colors(void)
|
|
|
|
{
|
|
|
|
int i,k;
|
|
|
|
float colors[NB_PALETTES][2][3]={{{1,1,1},{1,1,1}},
|
|
|
|
{{2,1.5,0},{0,0.5,2}},
|
|
|
|
{{0,1,2},{0,1,0}},
|
|
|
|
{{0,2,1},{0,0,1}},
|
|
|
|
{{2,0,0},{0,1,1}}};
|
|
|
|
|
|
|
|
for (k=0;k<NB_PALETTES;k++)
|
|
|
|
{
|
|
|
|
for ( i=0; i<128; i++ )
|
|
|
|
{
|
|
|
|
color_table[k][i].r = colors[k][0][0]*i;
|
|
|
|
color_table[k][i].g = colors[k][0][1]*i;
|
|
|
|
color_table[k][i].b = colors[k][0][2]*i;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i=0; i<128; i++ )
|
|
|
|
{
|
|
|
|
color_table[k][i+128].r = colors[k][0][0]*127+colors[k][1][0]*i;
|
|
|
|
color_table[k][i+128].g = colors[k][0][1]*127+colors[k][1][1]*i;
|
|
|
|
color_table[k][i+128].b = colors[k][0][2]*127+colors[k][1][2]*i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void change_color(int t2,int t1,int w)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i=0;i<255;i++)
|
|
|
|
{
|
|
|
|
int r,g,b;
|
|
|
|
r = (color_table[t1][i].r*w+color_table[t2][i].r*(256-w) )>>11;
|
|
|
|
g = (color_table[t1][i].g*w+color_table[t2][i].g*(256-w) )>>10;
|
|
|
|
b = (color_table[t1][i].b*w+color_table[t2][i].b*(256-w) )>>11;
|
|
|
|
current_colors[i]=(r<<11)+(g<<5)+b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void compute_surface(t_interpol* vector_field)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
int add_dest=0;
|
|
|
|
int add_src;
|
|
|
|
t_interpol *interpol;
|
|
|
|
byte* ptr_pix;
|
|
|
|
int color;
|
|
|
|
byte* ptr_swap;
|
|
|
|
|
|
|
|
for (j=0;j<scr_par.height;j++)
|
|
|
|
{
|
|
|
|
for (i=0;i<scr_par.width;i++)
|
|
|
|
{
|
|
|
|
interpol=&vector_field[add_dest];
|
|
|
|
add_src=(interpol->coord & 0xFFFF)*scr_par.width+(interpol->coord>>16);
|
|
|
|
ptr_pix=&((byte*)surface1)[add_src];
|
|
|
|
color=(*(ptr_pix)*(interpol->weight>>24)
|
|
|
|
+*(ptr_pix+1)*((interpol->weight & 0xFFFFFF)>>16)
|
|
|
|
+*(ptr_pix+scr_par.width)*((interpol->weight & 0xFFFF)>>8)
|
|
|
|
+*(ptr_pix+scr_par.width+1)*(interpol->weight & 0xFF))>>8;
|
|
|
|
|
|
|
|
if (color>255)
|
|
|
|
surface2[add_dest]=255;
|
|
|
|
else
|
|
|
|
surface2[add_dest]=color;
|
|
|
|
add_dest++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr_swap=surface1;
|
|
|
|
surface1=surface2;
|
|
|
|
surface2=ptr_swap;
|
|
|
|
}
|
|
|
|
|
|
|
|
void display_surface(void)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
if (scr_par.scale>1)
|
|
|
|
{
|
|
|
|
for (i=0;i<scr_par.height;i++)
|
|
|
|
{
|
|
|
|
short* pdest=(short*)(screen->pixels+i*screen->pitch*scr_par.scale);
|
|
|
|
byte* psrc=surface1+i*scr_par.width;
|
|
|
|
|
|
|
|
if (scr_par.scale==2)
|
|
|
|
{
|
|
|
|
for (j=1; j<scr_par.width; j++)
|
|
|
|
{
|
|
|
|
*pdest = current_colors[*psrc++];
|
|
|
|
pdest++;
|
|
|
|
*pdest = *(pdest-1);
|
|
|
|
pdest++;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(screen->pixels+i*screen->pitch*2+screen->pitch,
|
|
|
|
screen->pixels+i*screen->pitch*2,screen->pitch);
|
|
|
|
}
|
|
|
|
/* else
|
|
|
|
{
|
|
|
|
for (j=1;j<scr_par.width;j++) {
|
|
|
|
*(pdest++)=current_colors[*psrc++];
|
|
|
|
*(pdest++)=*(pdest-1);
|
|
|
|
*(pdest++)=*(pdest-1);
|
|
|
|
}
|
|
|
|
memcpy(screen->pixels+i*screen->pitch*3+screen->pitch,
|
|
|
|
screen->pixels+i*screen->pitch*3,screen->pitch);
|
|
|
|
memcpy(screen->pixels+i*screen->pitch*3+screen->pitch*2,
|
|
|
|
screen->pixels+i*screen->pitch*3,screen->pitch);
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
byte* psrc=surface1;
|
|
|
|
for (i=0;i<scr_par.height;i++)
|
|
|
|
{
|
|
|
|
short* pdest=(short*)(screen->pixels+i*screen->pitch);
|
|
|
|
for (j=0;j<scr_par.width;j++)
|
|
|
|
*pdest++=current_colors[*psrc++];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SDL_UpdateRect(screen, 0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void blur(t_interpol* vector_field)
|
|
|
|
{
|
|
|
|
compute_surface(vector_field);
|
|
|
|
display_surface();
|
|
|
|
}
|
|
|
|
|
|
|
|
void plot1(int x,int y,int c);
|
|
|
|
void plot1(int x,int y,int c)
|
|
|
|
{
|
|
|
|
if (x>0 && x<scr_par.width-3 && y>0 && y<scr_par.height-3)
|
|
|
|
assign_max(&(surface1)[x+y*scr_par.width],c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plot2(int x,int y,int c);
|
|
|
|
void plot2(int x,int y,int c)
|
|
|
|
{
|
|
|
|
int ty;
|
|
|
|
|
|
|
|
if (x>0 && x<scr_par.width-3 && y>0 && y<scr_par.height-3) {
|
|
|
|
ty = y*scr_par.width;
|
|
|
|
assign_max(&(surface1)[x+ty],c);
|
|
|
|
assign_max(&(surface1)[x+1+ty],c);
|
|
|
|
assign_max(&(surface1)[x+ty+scr_par.width],c);
|
|
|
|
assign_max(&(surface1)[x+1+ty+scr_par.width],c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plot3(int x,int y,int c);
|
|
|
|
void plot3(int x,int y,int c)
|
|
|
|
{
|
|
|
|
int ty;
|
|
|
|
|
|
|
|
if (x>0 && x<scr_par.width-3 && y>0 && y<scr_par.height-3) {
|
|
|
|
ty = y*scr_par.width;
|
|
|
|
assign_max(&(surface1)[x+ty],c/3);
|
|
|
|
assign_max(&(surface1)[x+1+ty],c>>1);
|
|
|
|
assign_max(&(surface1)[x+ty+scr_par.width],c>>1);
|
|
|
|
assign_max(&(surface1)[x+1+ty+scr_par.width],c);
|
|
|
|
assign_max(&(surface1)[x+ty+(scr_par.width<<1)],c/3);
|
|
|
|
assign_max(&(surface1)[x+2+ty+(scr_par.width<<1)],c/3);
|
|
|
|
assign_max(&(surface1)[x+1+ty+(scr_par.width<<1)],c>>1);
|
|
|
|
assign_max(&(surface1)[x+2+ty+scr_par.width],c>>1);
|
|
|
|
assign_max(&(surface1)[x+2+ty+scr_par.width],c/3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
void line(int x1,int y1,int x2,int y2,int c)
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
float x,y,vx,vy,d;
|
|
|
|
const float step=1;
|
|
|
|
|
|
|
|
if (x1==x2 && y1==y2)
|
|
|
|
plot3(x1,y1,255);
|
|
|
|
else {
|
|
|
|
x=x1;
|
|
|
|
y=y1;
|
|
|
|
d=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
|
|
|
|
vx=step*(x2-x1)/d;
|
|
|
|
vy=step*(y2-y1)/d;
|
|
|
|
for (i=0;i<(int)(d/step)+1;i++) {
|
|
|
|
plot1(x,y,c);
|
|
|
|
x+=vx;
|
|
|
|
y+=vy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define SWAP(x,y) \
|
|
|
|
x = x + y; \
|
|
|
|
y = x - y; \
|
|
|
|
x = x - y;
|
|
|
|
|
|
|
|
void line(int _x1, int _y1, int _x2, int _y2, int _c)
|
|
|
|
{
|
|
|
|
int dx, dy, cxy, dxy;
|
|
|
|
/* calculate the distances */
|
|
|
|
dx = abs(_x1 - _x2);
|
|
|
|
dy = abs(_y1 - _y2);
|
|
|
|
|
|
|
|
cxy = 0;
|
|
|
|
if (dy > dx)
|
|
|
|
{
|
|
|
|
/* Follow Y axis */
|
|
|
|
if (_y1 > _y2)
|
|
|
|
{
|
|
|
|
SWAP(_y1, _y2);
|
|
|
|
SWAP(_x1, _x2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_x1 > _x2)
|
|
|
|
dxy = -1;
|
|
|
|
else
|
|
|
|
dxy = 1;
|
|
|
|
|
|
|
|
for (_y1=_y1; _y1<_y2; _y1++)
|
|
|
|
{
|
|
|
|
cxy += dx;
|
|
|
|
if (cxy >= dy)
|
|
|
|
{
|
|
|
|
_x1+= dxy;
|
|
|
|
cxy -= dy;
|
|
|
|
}
|
|
|
|
plot1(_x1, _y1, _c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Follow X axis */
|
|
|
|
if (_x1 > _x2)
|
|
|
|
{
|
|
|
|
SWAP(_x1, _x2);
|
|
|
|
SWAP(_y1, _y2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_y1 > _y2)
|
|
|
|
dxy = -1;
|
|
|
|
else
|
|
|
|
dxy = 1;
|
|
|
|
|
|
|
|
for (_x1=_x1; _x1<_x2; _x1++)
|
|
|
|
{
|
|
|
|
cxy += dy;
|
|
|
|
if (cxy >= dx)
|
|
|
|
{
|
|
|
|
_y1+=dxy;
|
|
|
|
cxy -= dx;
|
|
|
|
}
|
|
|
|
plot1(_x1, _y1, _c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sincos
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float *f;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Little optimization for cos/sin functions */
|
|
|
|
static struct sincos cosw = { 0, NULL };
|
|
|
|
static struct sincos sinw = { 0, NULL };
|
|
|
|
|
|
|
|
void spectral(t_effect* current_effect,short data[2][512])
|
|
|
|
{
|
|
|
|
int i, halfheight, halfwidth;
|
|
|
|
float old_y1,old_y2;
|
|
|
|
float _y1=(((data[0][0]+data[1][0])>>9)*current_effect->spectral_amplitude*scr_par.height)>>12;
|
|
|
|
float _y2=(((data[0][0]+data[1][0])>>9)*current_effect->spectral_amplitude*scr_par.height)>>12;
|
|
|
|
const int density_lines=5;
|
|
|
|
const int step=4;
|
|
|
|
const int shift=(current_effect->spectral_shift*scr_par.height)>>8;
|
|
|
|
|
|
|
|
if (cosw.i != scr_par.width || sinw.i != scr_par.width)
|
|
|
|
{
|
|
|
|
free(cosw.f);
|
|
|
|
free(sinw.f);
|
|
|
|
sinw.f = cosw.f = NULL;
|
|
|
|
sinw.i = cosw.i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cosw.i == 0 || cosw.f == NULL)
|
|
|
|
{
|
|
|
|
float halfPI = (float)PI/2;
|
|
|
|
cosw.i = scr_par.width;
|
|
|
|
cosw.f = malloc(sizeof(float)*scr_par.width);
|
|
|
|
for (i=0; i<scr_par.width;i+=step)
|
|
|
|
cosw.f[i] = cos((float)i/scr_par.width*PI+halfPI);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sinw.i == 0 || sinw.f == NULL)
|
|
|
|
{
|
|
|
|
float halfPI = (float)PI/2;
|
|
|
|
sinw.i = scr_par.width;
|
|
|
|
sinw.f = malloc(sizeof(float)*scr_par.width);
|
|
|
|
for (i=0; i<scr_par.width;i+=step)
|
|
|
|
sinw.f[i] = sin((float)i/scr_par.width*PI+halfPI);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_effect->mode_spectre==3)
|
|
|
|
{
|
|
|
|
if (_y1<0)
|
|
|
|
_y1=0;
|
|
|
|
|
|
|
|
if (_y2<0)
|
|
|
|
_y2=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
halfheight = scr_par.height >> 1;
|
|
|
|
halfwidth = scr_par.width >> 1;
|
|
|
|
for (i=step;i<scr_par.width;i+=step)
|
|
|
|
{
|
|
|
|
old_y1=_y1;
|
|
|
|
old_y2=_y2;
|
|
|
|
_y1=((data[1][(i<<9)/scr_par.width/density_lines]>>8)*
|
|
|
|
current_effect->spectral_amplitude*scr_par.height)>>12;
|
|
|
|
_y2=((data[0][(i<<9)/scr_par.width/density_lines]>>8)*
|
|
|
|
current_effect->spectral_amplitude*scr_par.height)>>12;
|
|
|
|
|
|
|
|
switch (current_effect->mode_spectre)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
line(i-step,halfheight+shift+old_y2,
|
|
|
|
i,halfheight+shift+_y2,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
line(i-step,halfheight+shift+old_y1,
|
|
|
|
i,halfheight+shift+_y1,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
line(i-step,halfheight-shift+old_y2,
|
|
|
|
i,halfheight-shift+_y2,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
line(i-step,halfheight+shift+old_y1,
|
|
|
|
i,halfheight+shift+_y1,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
line(i-step,halfheight-shift+old_y1,
|
|
|
|
i,halfheight-shift+_y1,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
line(halfwidth+shift+old_y2,i-step,
|
|
|
|
halfwidth+shift+_y2,i,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
line(halfwidth-shift+old_y2,i-step,
|
|
|
|
halfwidth-shift+_y2,i,
|
|
|
|
current_effect->spectral_color);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (_y1<0)
|
|
|
|
_y1=0;
|
|
|
|
if (_y2<0)
|
|
|
|
_y2=0;
|
|
|
|
case 4:
|
|
|
|
line(halfwidth + cosw.f[i-step] * (shift+old_y1),
|
|
|
|
halfheight + sinw.f[i-step] * (shift+old_y1),
|
|
|
|
halfwidth + cosw.f[i] * (shift+_y1),
|
|
|
|
halfheight + sinw.f[i] * (shift+_y1),
|
|
|
|
current_effect->spectral_color);
|
|
|
|
line(halfwidth - cosw.f[i-step] * (shift+old_y2),
|
|
|
|
halfheight + sinw.f[i-step] * (shift+old_y2),
|
|
|
|
halfwidth - cosw.f[i] * (shift+_y2),
|
|
|
|
halfheight + sinw.f[i] * (shift+_y2),
|
|
|
|
current_effect->spectral_color);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (current_effect->mode_spectre==3 || current_effect->mode_spectre==4)
|
|
|
|
line(halfwidth + cosw.f[scr_par.width - step] * (shift+_y1),
|
|
|
|
halfheight + sinw.f[scr_par.width - step] * (shift+_y1),
|
|
|
|
halfwidth - cosw.f[scr_par.width - step] * (shift+_y2),
|
|
|
|
halfheight + sinw.f[scr_par.width - step] * (shift+_y2),
|
|
|
|
current_effect->spectral_color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void curve(t_effect* current_effect)
|
|
|
|
{
|
|
|
|
int i,j,k;
|
|
|
|
float v,vr;
|
|
|
|
float x,y;
|
|
|
|
float amplitude=(float)current_effect->curve_amplitude/256;
|
|
|
|
|
|
|
|
for (j=0;j<2;j++)
|
|
|
|
{
|
|
|
|
v=80;
|
|
|
|
vr=0.001;
|
|
|
|
k=current_effect->x_curve;
|
|
|
|
for (i=0;i<64;i++)
|
|
|
|
{
|
|
|
|
x=cos((float)(k)/(v+v*j*1.34))*scr_par.height*amplitude;
|
|
|
|
y=sin((float)(k)/(1.756*(v+v*j*0.93)))*scr_par.height*amplitude;
|
|
|
|
plot2(x*cos((float)k*vr)+y*sin((float)k*vr)+scr_par.width/2,
|
|
|
|
x*sin((float)k*vr)-y*cos((float)k*vr)+scr_par.height/2,
|
|
|
|
current_effect->curve_color);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
current_effect->x_curve=k;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init_sdl(void)
|
|
|
|
{
|
|
|
|
surface1=(byte*)malloc(scr_par.width*scr_par.height);
|
|
|
|
surface2=(byte*)malloc(scr_par.width*scr_par.height);
|
|
|
|
|
|
|
|
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_WM_SetCaption("Tyler", 0L);
|
|
|
|
screen = SDL_SetVideoMode(scr_par.width * scr_par.scale,
|
|
|
|
scr_par.height * scr_par.scale, 16, VIDEO_FLAGS);
|
|
|
|
|
|
|
|
if ( screen == NULL )
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Couldn't init video mode: %s\n", SDL_GetError());
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
SDL_ShowCursor(0);
|
|
|
|
SDL_EnableKeyRepeat(0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void toggle_fullscreen(void)
|
|
|
|
{
|
|
|
|
SDL_WM_ToggleFullScreen(screen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void close_sdl(void)
|
|
|
|
{
|
|
|
|
SDL_Quit();
|
|
|
|
}
|