103 lines
2.9 KiB
C
103 lines
2.9 KiB
C
#include "SDL.h"
|
|
|
|
#include "log.h"
|
|
#include "rng.h"
|
|
#include "opengl.h"
|
|
#include "plasmaf.h"
|
|
|
|
static double* pf_genFractalMap(const int w, const int h, double rug);
|
|
static void pf_divFractal(double* map, const double x, const double y,
|
|
const double w, const double h, const
|
|
double rw, const double rh, double c1,
|
|
double c2, double c3, double c4, double rug);
|
|
|
|
/* Acutally generate the fractal and loads it up in an opengl texture. */
|
|
glTexture* pf_genFractal(const int w, const int h, double rug) {
|
|
int i;
|
|
double* map;
|
|
SDL_Surface* sur;
|
|
uint32_t* pix;
|
|
glTexture* tex;
|
|
double c;
|
|
|
|
map = pf_genFractalMap(w, h, rug);
|
|
|
|
sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBAMASK);
|
|
pix = sur->pixels;
|
|
|
|
/* Convert from mapping to actual colours. */
|
|
SDL_LockSurface(sur);
|
|
for(i = 0; i < h*w; i++) {
|
|
c = map[i];
|
|
pix[i] = RMASK + BMASK + GMASK + (AMASK & (uint32_t)(AMASK*c));
|
|
}
|
|
SDL_UnlockSurface(sur);
|
|
|
|
free(map);
|
|
|
|
tex = gl_loadImage(sur);
|
|
|
|
return tex;
|
|
}
|
|
|
|
static double* pf_genFractalMap(const int w, const int h, double rug) {
|
|
double* map; /* We'll use it to map out the fractal before saving. */
|
|
double cx, cy;
|
|
|
|
map = malloc(w*h * sizeof(double));
|
|
if(map == NULL) {
|
|
WARN("Out of memory");
|
|
return NULL;
|
|
}
|
|
|
|
/* Set up initial values. */
|
|
cx = (double)w/2;
|
|
cy = (double)h/2;
|
|
|
|
/* Start by doing the four squares. */
|
|
pf_divFractal(map, 0, 0, cx, cy, w, h, 0., 0., 1., 0., rug);
|
|
pf_divFractal(map, cx, 0, cx, cy, w, h, 0., 0., 0., 1., rug);
|
|
pf_divFractal(map, cx, cy, cx, cy, w, h, 1., 0., 0., 0., rug);
|
|
pf_divFractal(map, 0, cy, cx, cy, w, h, 0., 1., 0., 0., rug);
|
|
|
|
return map;
|
|
}
|
|
|
|
static void pf_divFractal(double* map, const double x, const double y,
|
|
const double w, const double h, const double rw,
|
|
const double rh, double c1, double c2, double c3,
|
|
double c4, double rug) {
|
|
|
|
double nw, nh; /* New dimensions. */
|
|
double m, e1, e2, e3, e4; /* Middle and edges. */
|
|
|
|
/* Still need to subdivide. */
|
|
if((w>1.) || (h>1.)) {
|
|
/* Calculate new dimensions. */
|
|
nw = w/2.;
|
|
nh = h/2.;
|
|
|
|
/* Edges. */
|
|
m = (c1 + c2 + c3 + c4)/4.;
|
|
e1 = (c1 + c2)/2.;
|
|
e2 = (c2 + c3)/2.;
|
|
e3 = (c3 + c4)/2.;
|
|
e4 = (c4 + c1)/2.;
|
|
|
|
/* Now change the middle colour. */
|
|
/*DEBUG("%f + %f", m, rug*(RNGF()-0.5) * ((nw+nh)/(rw+rh)*1000)); */
|
|
m += rug*(RNGF()-0.5)*((nw+nh)/(rw+rh)*3.);
|
|
if(m < 0.) m = 0.;
|
|
else if(m>1.) m = 1.;
|
|
|
|
/* Recursivation. */
|
|
pf_divFractal(map, x, y, nw, nh, rw, rh, c1, e1, m, e4, rug);
|
|
pf_divFractal(map, x+nw, y, nw, nh, rw, rh, e1, c2, e2, m, rug);
|
|
pf_divFractal(map, x+nw, y+nh, nw, nh, rw, rh, m, e2, c3, e3, rug);
|
|
pf_divFractal(map, x, y+nh, nw, nh, rw, rh, e4, m, e3, c4, rug);
|
|
} else
|
|
/* Actually write the pixel. */
|
|
map[(int)y*(int)rw + (int)x] = (c1 + c2 + c3 + c4)/4.;
|
|
}
|
|
|