From 1442259c0bb3c7e3ad8284377ab01c89ad83b8e9 Mon Sep 17 00:00:00 2001 From: Allanis Date: Thu, 11 Jul 2013 17:43:33 +0100 Subject: [PATCH] [Add] Nebulae generation code. (Not using it at the minute). --- src/opengl.h | 2 +- src/perlin.c | 187 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 114 insertions(+), 75 deletions(-) diff --git a/src/opengl.h b/src/opengl.h index 0b35ff7..ac11926 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -105,7 +105,7 @@ void gl_exit(void); int gl_isTrans(const glTexture* t, const int x, const int y); void gl_getSpriteFromDir(int* x, int* y, const glTexture* t, const double dir); void gl_screenshot(const char* filename); -int SDL_SavePNG(SDL_Surface* surface, const char* file); +int SDL_savePNG(SDL_Surface* surface, const char* file); /*#if DEBUG == 1 */ void gl_checkErr(void); /*#else */ diff --git a/src/perlin.c b/src/perlin.c index 8c2c5c8..2ca7aeb 100644 --- a/src/perlin.c +++ b/src/perlin.c @@ -2,18 +2,21 @@ #include #include +#include "lephisto.h" #include "log.h" #include "rng.h" +#include "lfile.h" #include "perlin.h" +#define NEBULAE_Z 32 + #define NOISE_MAX_OCTAVES 128 #define NOISE_MAX_DIMENSIONS 4 #define NOISE_DEFAULT_HURST 0.5 #define NOISE_DEFAULT_LACUNARITY 2. #define LERP(a, b, x) (a + x * (b - a)) -#define ABS(a) ((a)<0?-(a):(a)) #define CLAMP(a, b, x) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) typedef void* noise_t; @@ -27,9 +30,10 @@ typedef struct { float H; float lacunarity; float exponent[NOISE_MAX_OCTAVES]; -} perlin_data_t; +} perling_data_t; -static float* noise_genNebulae(const int w, const int h, const int n, float rug); +static float* genNebulaeMap(const int w, const int h, const int n, float rug); +SDL_Surface* surfaceFromNebulaeMap(float* map, const int w, const int h); static noise_t noise_new(int dimensions, float hurst, float lacunarity); /* Basic perlin noise. */ static float noise_get(noise_t noise, float* f); @@ -39,7 +43,7 @@ static float noise_get(noise_t noise, float* f); static float noise_turbulence(noise_t noise, float* f, float octaves); static void noise_delete(noise_t noise); -static float lattice(perlin_data_t* data, int ix, float fx, int iy, +static float lattice(perling_data_t* pdata, int ix, float fx, int iy, float fy, int iz, float fz, int iw, float fw) { int n[4] = { ix, iy, iz, iw }; @@ -48,10 +52,10 @@ static float lattice(perlin_data_t* data, int ix, float fx, int iy, int i; float value = 0; - for(i = 0; i < data->ndim; i++) - nindex = data->map[(nindex + n[i]) & 0xFF]; - for(i = 0; i < data->ndim; i++) - value += data->buffer[nindex][i] * f[i]; + for(i = 0; i < pdata->ndim; i++) + nindex = pdata->map[(nindex + n[i]) & 0xFF]; + for(i = 0; i < pdata->ndim; i++) + value += pdata->buffer[nindex][i] * f[i]; return value; } @@ -63,120 +67,120 @@ static float lattice(perlin_data_t* data, int ix, float fx, int iy, #define FLOOR(a) ((int) a - (a < 0 && a != (int)a)) #define CUBIC(a) (a * a * (3 - 2 * a)) -static void normalize(perlin_data_t* data, float* f) { +static void normalize(perling_data_t* pdata, float* f) { float magnitude = 0; int i; - for(i = 0; i < data->ndim; i++) + for(i = 0; i < pdata->ndim; i++) magnitude += f[i] * f[i]; magnitude = 1 / sqrtf(magnitude); - for(i = 0; i < data->ndim; i++) + for(i = 0; i < pdata->ndim; i++) f[i] *= magnitude; } static noise_t noise_new(int ndim, float hurst, float lacunarity) { - perlin_data_t* data=(perlin_data_t*)calloc(sizeof(perlin_data_t), 1); + perling_data_t* pdata=(perling_data_t*)calloc(sizeof(perling_data_t), 1); int i, j; unsigned char tmp; float f = 1; - data->ndim = ndim; + pdata->ndim = ndim; for(i = 0; i < 256; i++) { - data->map[i] = (unsigned char) i; - for(j = 0; j < data->ndim; j++) - data->buffer[i][j] = RNGF()-0.5; - normalize(data, data->buffer[i]); + pdata->map[i] = (unsigned char) i; + for(j = 0; j < pdata->ndim; j++) + pdata->buffer[i][j] = RNGF()-0.5; + normalize(pdata, pdata->buffer[i]); } while(--i) { j = RNG(0, 255); - SWAP(data->map[i], data->map[j], tmp); + SWAP(pdata->map[i], pdata->map[j], tmp); } - data->H = hurst; - data->lacunarity = lacunarity; + pdata->H = hurst; + pdata->lacunarity = lacunarity; for(i = 0; i < NOISE_MAX_OCTAVES; i++) { /*exponent[i] = powf(f, -H); */ - data->exponent[i] = 1.0f / f; + pdata->exponent[i] = 1.0f / f; f *= lacunarity; } - return (noise_t)data; + return (noise_t)pdata; } static float noise_get(noise_t noise, float *f ) { - perlin_data_t* data = (perlin_data_t*) noise; + perling_data_t* pdata = (perling_data_t*) noise; int n[NOISE_MAX_DIMENSIONS]; /* Indexes to pass to lattice function */ int i; float r[NOISE_MAX_DIMENSIONS]; /* Remainders to pass to lattice function */ float w[NOISE_MAX_DIMENSIONS]; /* Cubic values to pass to interpolation function */ float value; - for(i=0; indim; i++) { + for(i=0; indim; i++) { n[i] = FLOOR(f[i]); r[i] = f[i] - n[i]; w[i] = CUBIC(r[i]); } - switch(data->ndim) { + switch(pdata->ndim) { case 1: - value = LERP(lattice(data,n[0], r[0],0,0,0,0,0,0), - lattice(data,n[0]+1, r[0]-1,0,0,0,0,0,0), + value = LERP(lattice(pdata,n[0], r[0],0,0,0,0,0,0), + lattice(pdata,n[0]+1, r[0]-1,0,0,0,0,0,0), w[0]); break; case 2: - value = LERP(LERP(lattice(data,n[0], r[0], n[1], r[1],0,0,0,0), - lattice(data,n[0]+1, r[0]-1, n[1], r[1],0,0,0,0), + value = LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1],0,0,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1],0,0,0,0), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1,0,0,0,0), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1,0,0,0,0), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1,0,0,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1,0,0,0,0), w[0]), w[1]); break; case 3: - value = LERP(LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2], r[2],0,0), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2],0,0), + value = LERP(LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2], r[2],0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2],0,0), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2],0,0), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2],0,0), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2],0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2],0,0), w[0]), w[1]), - LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1,0,0), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1,0,0), + LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1,0,0), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), w[0]), w[1]), w[2]); break; case 4: default: - value = LERP(LERP(LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2], r[2], n[3], r[3]), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2], n[3], r[3]), + value = LERP(LERP(LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2], r[2], n[3], r[3]), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2], n[3], r[3]), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2], n[3], r[3]), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2], n[3], r[3]), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2], n[3], r[3]), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2], n[3], r[3]), w[0]), w[1]), - LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1, n[3], r[3]), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1, n[3], r[3]), + LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1, n[3], r[3]), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1, n[3], r[3]), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1, n[3], r[3]), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1, n[3], r[3]), w[0]), w[1]), w[2]), - LERP(LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2], r[2], n[3]+1, r[3]-1), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2], n[3]+1, r[3]-1), + LERP(LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2], r[2], n[3]+1, r[3]-1), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2], r[2], n[3]+1, r[3]-1), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2], n[3]+1, r[3]-1), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2], n[3]+1, r[3]-1), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2], r[2], n[3]+1, r[3]-1), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2], r[2], n[3]+1, r[3]-1), w[0]), w[1]), - LERP(LERP(lattice(data,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1, n[3]+1, r[3]-1), - lattice(data,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1, n[3]+1, r[3]-1), + LERP(LERP(lattice(pdata,n[0], r[0], n[1], r[1], n[2]+1, r[2]-1, n[3]+1, r[3]-1), + lattice(pdata,n[0]+1, r[0]-1, n[1], r[1], n[2]+1, r[2]-1, n[3]+1, r[3]-1), w[0]), - LERP(lattice(data,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), - lattice(data,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1, n[3]+1, r[3]-1), + LERP(lattice(pdata,n[0], r[0], n[1]+1, r[1]-1, n[2]+1, r[2]-1,0,0), + lattice(pdata,n[0]+1, r[0]-1, n[1]+1, r[1]-1, n[2]+1, r[2]-1, n[3]+1, r[3]-1), w[0]), w[1]), w[2]), @@ -189,52 +193,53 @@ static float noise_get(noise_t noise, float *f ) #if 0 float noise_fbm(noise_t noise, float* f, float octaves) { float tf[NOISE_MAX_DIMENSIONS]; - perlin_data_t* data = (perlin_data_t*) noise; + perling_data_t* pdata = (perling_data_t*) noise; /* Init locals. */ float value = 0; int i, j; - memcpy(tf, f, sizeof(float) * data->ndim); + memcpy(tf, f, sizeof(float) * pdata->ndim); /* Inner loop for spectral construction, where the fractal is build. */ for(i = 0; i < (int)octaves; i++) { - value += noise_get(noise, tf) * data->exponent[i]; - for(j = 0; j < data->ndim; j++) tf[j] *= data->lacunarity; + value += noise_get(noise, tf) * pdata->exponent[i]; + for(j = 0; j < pdata->ndim; j++) tf[j] *= pdata->lacunarity; } /* Take care of remainder in octaves. */ octaves -= (int)octaves; if(octaves > DELTA) - value += octaves * noise_get(noise, tf) * data->exponent[i]; + value += octaves * noise_get(noise, tf) * pdata->exponent[i]; return CLAMP(-0.99999f, 0.99999f, value); } #endif static float noise_turbulence(noise_t noise, float* f, float octaves) { float tf[NOISE_MAX_DIMENSIONS]; - perlin_data_t* data = (perlin_data_t*) noise; + perling_data_t* pdata = (perling_data_t*) noise; /* Init locals. */ float value = 0; int i, j; - memcpy(tf, f, sizeof(float) * data->ndim); + memcpy(tf, f, sizeof(float) * pdata->ndim); /* Inner loop of spectral construction, where the fractal is built. */ for(i = 0; i < (int)octaves; i++) { - value += ABS(noise_get(noise, tf)) * data->exponent[i]; - for(j = 0; j < data->ndim; j++) tf[j] *= data->lacunarity; + value += ABS(noise_get(noise, tf)) * pdata->exponent[i]; + for(j = 0; j < pdata->ndim; j++) tf[j] *= pdata->lacunarity; } /* Take care of remainders in octaves. */ octaves -= (int)octaves; if(octaves > DELTA) - value += octaves * ABS(noise_get(noise, tf)) * data->exponent[i]; + value += octaves * ABS(noise_get(noise, tf)) * pdata->exponent[i]; return CLAMP(-0.99999f, 0.99999f, value); } void noise_delete(noise_t noise) { - free((perlin_data_t*)noise); + free((perling_data_t*)noise); } -static float* noise_genNebulae(const int w, const int h, const int n, float rug) { +/* Generate a 3d nebulae map of dimensions w,h,n with ruggedness rig. */ +static float* genNebulaeMap(const int w, const int h, const int n, float rug) { int x, y, z; float f[3]; float octaves; @@ -256,13 +261,15 @@ static float* noise_genNebulae(const int w, const int h, const int n, float rug) return NULL; } + f[2] = 0.; for(z = 0; z < n; z++) { for(y = 0; y < h; y++) { + + f[1] = rug * (float)y / (float)h; + for(x = 0; x < w; x++) { f[0] = rug * (float)x / (float)w; - f[1] = rug * (float)y / (float)h; - f[2] = rug * (float)z / (float)n; value = noise_turbulence(noise, f, octaves); @@ -270,6 +277,7 @@ static float* noise_genNebulae(const int w, const int h, const int n, float rug) nebulae[z*w*h + y*w+x] = (value < 1.) ? value : 1.; } } + f[2] += 0.01; } noise_delete(noise); @@ -277,16 +285,13 @@ static float* noise_genNebulae(const int w, const int h, const int n, float rug) return nebulae; } -glTexture* noise_genCloud(const int w, const int h, double rug) { +/* Generate an SDL_Surface from a 2d nebulae map. */ +SDL_Surface* surfaceFromNebulaeMap(float* map, const int w, const int h) { int i; - float* map; SDL_Surface* sur; uint32_t* pix; - glTexture* tex; double c; - map = noise_genNebulae(w, h, 1, rug); - sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBAMASK); pix = sur->pixels; @@ -298,6 +303,40 @@ glTexture* noise_genCloud(const int w, const int h, double rug) { } SDL_UnlockSurface(sur); + return sur; +} + +/* Generate nebulae and save them for late use. */ +void noise_generateNebulae(const int w, const int h) { + int i; + float* nebu; + SDL_Surface* sur; + char nebu_file[PATH_MAX]; + + /* Generate all the nebulae. */ + nebu = genNebulaeMap(w, h, NEBULAE_Z, 15.); + + /* Save each nebulae as an image. */ + for(i = 0; i < NEBULAE_Z; i++) { + sur = surfaceFromNebulaeMap(&nebu[i*w*h], w, h); + snprintf(nebu_file, PATH_MAX, "%s/nebu_%02d.png", lfile_basePath(), i); + SDL_savePNG(sur, nebu_file); + SDL_FreeSurface(sur); + } + + /* Cleanup. */ + free(nebu); +} + +glTexture* noise_genCloud(const int w, const int h, double rug) { + float* map; + SDL_Surface* sur; + glTexture* tex; + + /*noise_generateNebulae(w, h);*/ + + map = genNebulaeMap(w, h, 1, rug); + sur = surfaceFromNebulaeMap(map, w, h); free(map); tex = gl_loadImage(sur);