[Add] Nebulae generation code. (Not using it at the minute).

This commit is contained in:
Allanis 2013-07-11 17:43:33 +01:00
parent e4e7bf4b17
commit 1442259c0b
2 changed files with 114 additions and 75 deletions

View File

@ -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 */

View File

@ -2,18 +2,21 @@
#include <stdlib.h>
#include <string.h>
#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; i<data->ndim; i++) {
for(i=0; i<pdata->ndim; 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);