[Add] Fancy new "cloud" generator. This needs some heavy tweaking/cleanup.
This commit is contained in:
parent
b8bafb4700
commit
4c1ee89ffb
11
src/ai.c
11
src/ai.c
@ -62,8 +62,9 @@
|
||||
#define AI_SECONDARY (1<<1) /* Firing secondary weapon. */
|
||||
|
||||
/* file info. */
|
||||
#define AI_PREFIX "../scripts/ai/"
|
||||
#define AI_PREFIX "../scripts/ai/"
|
||||
#define AI_SUFFIX ".lua"
|
||||
#define AI_INCLUDE "include/"
|
||||
|
||||
/* AI profiles. */
|
||||
static AI_Profile* profiles = NULL;
|
||||
@ -237,9 +238,11 @@ int ai_init(void) {
|
||||
|
||||
/* Load the profiles. */
|
||||
for(i = 0; i < nfiles; i++)
|
||||
if((strncmp(files[i], AI_PREFIX, strlen(AI_PREFIX))==0 &&
|
||||
strncmp(files[i] + strlen(files[i]) - strlen(AI_SUFFIX),
|
||||
AI_SUFFIX, strlen(AI_SUFFIX))==0))
|
||||
if((strncmp(files[i], AI_PREFIX, strlen(AI_PREFIX))==0) && /* prefixed. */
|
||||
(strncmp(files[i] + strlen(AI_PREFIX), AI_INCLUDE, /* Not an include. */
|
||||
strlen(AI_INCLUDE)) != 0) &&
|
||||
(strncmp(files[i] + strlen(files[i]) - strlen(AI_PREFIX), /* Suffixed. */
|
||||
AI_SUFFIX, strlen(AI_SUFFIX))==0))
|
||||
if(ai_loadProfile(files[i]))
|
||||
WARN("Error loading AI profile '%s'", files[i]);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "pilot.h"
|
||||
#include "space.h"
|
||||
#include "player.h"
|
||||
#include "plasmaf.h"
|
||||
#include "perlin.h"
|
||||
#include "mission.h"
|
||||
#include "ltime.h"
|
||||
#include "save.h"
|
||||
@ -68,7 +68,7 @@ void menu_main(void) {
|
||||
unsigned int bwid, wid;
|
||||
glTexture* tex;
|
||||
|
||||
tex = pf_genFractal(SCREEN_W, SCREEN_H, 5.);
|
||||
tex = noise_genCloud(SCREEN_W, SCREEN_H, 5.);
|
||||
|
||||
/* Create background image window. */
|
||||
bwid = window_create("BG", -1, -1, SCREEN_W, SCREEN_H);
|
||||
|
283
src/perlin.c
Normal file
283
src/perlin.c
Normal file
@ -0,0 +1,283 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "rng.h"
|
||||
|
||||
#include "perlin.h"
|
||||
|
||||
#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 struct {
|
||||
int ndim;
|
||||
unsigned char map[256]; /* Randomized map of indexes into buffer. */
|
||||
float buffer[256][NOISE_MAX_DIMENSIONS]; // Random 256 x ndim buffer. */
|
||||
/* Fractal stuff. */
|
||||
float H;
|
||||
float lacunarity;
|
||||
float exponent[NOISE_MAX_OCTAVES];
|
||||
} perlin_data_t;
|
||||
|
||||
static float* noise_genMap(const int w, const int h, float rug);
|
||||
|
||||
static float lattice(perlin_data_t* data, int ix, float fx, int iy,
|
||||
float fy, int iz, float fz, int iw, float fw) {
|
||||
|
||||
int n[4] = { ix, iy, iz, iw };
|
||||
float f[4] = { fx, fy, fz, fw };
|
||||
int nindex = 0;
|
||||
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];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#define DEFAULT_SEED 0x15687436
|
||||
#define DELTA 1e-6f
|
||||
#define SWAP(a, b, t) t = a; a = b; b = t
|
||||
|
||||
#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) {
|
||||
float magnitude = 0;
|
||||
int i;
|
||||
for(i = 0; i < data->ndim; i++)
|
||||
magnitude += f[i] * f[i];
|
||||
magnitude = 1 / sqrtf(magnitude);
|
||||
for(i = 0; i < data->ndim; i++)
|
||||
f[i] *= magnitude;
|
||||
}
|
||||
|
||||
noise_t noise_new(int ndim, float hurst, float lacunarity) {
|
||||
perlin_data_t* data=(perlin_data_t*)calloc(sizeof(perlin_data_t), 1);
|
||||
int i, j;
|
||||
unsigned char tmp;
|
||||
float f = 1;
|
||||
data->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]);
|
||||
}
|
||||
|
||||
while(--i) {
|
||||
j = RNG(0, 255);
|
||||
SWAP(data->map[i], data->map[j], tmp);
|
||||
}
|
||||
|
||||
data->H = hurst;
|
||||
data->lacunarity = lacunarity;
|
||||
for(i = 0; i < NOISE_MAX_OCTAVES; i++) {
|
||||
/*exponent[i] = powf(f, -H); */
|
||||
data->exponent[i] = 1.0f / f;
|
||||
f *= lacunarity;
|
||||
}
|
||||
return (noise_t)data;
|
||||
}
|
||||
|
||||
float noise_get(noise_t noise, float *f )
|
||||
{
|
||||
perlin_data_t* data = (perlin_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++) {
|
||||
n[i] = FLOOR(f[i]);
|
||||
r[i] = f[i] - n[i];
|
||||
w[i] = CUBIC(r[i]);
|
||||
}
|
||||
|
||||
switch(data->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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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]),
|
||||
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]),
|
||||
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]),
|
||||
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]),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
w[0]),
|
||||
w[1]),
|
||||
w[2]),
|
||||
w[3]);
|
||||
break;
|
||||
}
|
||||
return CLAMP(-0.99999f, 0.99999f, value);
|
||||
}
|
||||
|
||||
float noise_fbm(noise_t noise, float* f, float octaves) {
|
||||
float tf[NOISE_MAX_DIMENSIONS];
|
||||
perlin_data_t* data = (perlin_data_t*) noise;
|
||||
/* Init locals. */
|
||||
float value = 0;
|
||||
int i, j;
|
||||
memcpy(tf, f, sizeof(float) * data->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;
|
||||
}
|
||||
|
||||
/* Take care of remainder in octaves. */
|
||||
octaves -= (int)octaves;
|
||||
if(octaves > DELTA)
|
||||
value += octaves * noise_get(noise, tf) * data->exponent[i];
|
||||
return CLAMP(-0.99999f, 0.99999f, value);
|
||||
}
|
||||
|
||||
float noise_turbulence(noise_t noise, float* f, float octaves) {
|
||||
float tf[NOISE_MAX_DIMENSIONS];
|
||||
perlin_data_t* data = (perlin_data_t*) noise;
|
||||
/* Init locals. */
|
||||
float value = 0;
|
||||
int i, j;
|
||||
memcpy(tf, f, sizeof(float) * data->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;
|
||||
}
|
||||
|
||||
/* Take care of remainders in octaves. */
|
||||
octaves -= (int)octaves;
|
||||
if(octaves > DELTA)
|
||||
value += octaves * ABS(noise_get(noise, tf)) * data->exponent[i];
|
||||
return CLAMP(-0.99999f, 0.99999f, value);
|
||||
}
|
||||
|
||||
void noise_delete(noise_t noise) {
|
||||
free((perlin_data_t*)noise);
|
||||
}
|
||||
|
||||
static float* noise_genMap(const int w, const int h, float rug) {
|
||||
int x, y;
|
||||
float f[2];
|
||||
float octaves;
|
||||
float hurst;
|
||||
float lacunarity;
|
||||
noise_t noise;
|
||||
float* map;
|
||||
float value;
|
||||
|
||||
octaves = 3.;
|
||||
hurst = NOISE_DEFAULT_HURST;
|
||||
lacunarity = NOISE_DEFAULT_LACUNARITY;
|
||||
|
||||
noise = noise_new(2, hurst, lacunarity);
|
||||
|
||||
map = malloc(sizeof(float)*w*h);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
f[0] = rug * (float)x / (float)w;
|
||||
f[1] = rug * (float)y / (float)h;
|
||||
|
||||
/*value = noise_get(noise, f);*/
|
||||
/*value = noise_fbm(noise, f, octaves);*/
|
||||
value = noise_turbulence(noise, f, octaves);
|
||||
|
||||
value = value + 0.3;
|
||||
map[y*w+x] = (value < 1.) ? value : 1.;
|
||||
}
|
||||
}
|
||||
|
||||
noise_delete(noise);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
glTexture* noise_genCloud(const int w, const int h, double rug) {
|
||||
int i;
|
||||
float* map;
|
||||
SDL_Surface* sur;
|
||||
uint32_t* pix;
|
||||
glTexture* tex;
|
||||
double c;
|
||||
|
||||
map = noise_genMap(w, h, rug);
|
||||
|
||||
sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBMASK);
|
||||
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;
|
||||
}
|
||||
|
25
src/perlin.h
Normal file
25
src/perlin.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "opengl.h"
|
||||
|
||||
typedef void* noise_t;
|
||||
|
||||
#define NOISE_MAX_OCTAVES 128
|
||||
#define NOISE_MAX_DIMENSIONS 4
|
||||
#define NOISE_DEFAULT_HURST 0.5f
|
||||
#define NOISE_DEFAULT_LACUNARITY 2.0f
|
||||
|
||||
noise_t noise_new(int dimensions, float hurst, float lacunarity);
|
||||
|
||||
/* Basic perlin noise. */
|
||||
float noise_get(noise_t noise, float *f);
|
||||
|
||||
/* Fractional brownian motion. */
|
||||
float noise_fbm(noise_t noise, float* f, float octaves);
|
||||
|
||||
/* Turbulence. */
|
||||
float noise_turbulence(noise_t noise, float* f, float octaves);
|
||||
|
||||
void noise_delete(noise_t noise);
|
||||
|
||||
glTexture* noise_genCloud(const int w, const int h, double rug);
|
||||
|
@ -108,7 +108,7 @@ unsigned int randint(void) {
|
||||
}
|
||||
|
||||
/* Return a random double. */
|
||||
static double m_div = (double)(0xFFFFFFFF) + 1.;
|
||||
static double m_div = (double)(0xFFFFFFFF);
|
||||
double randfp(void) {
|
||||
double m = (double)mt_getInt();
|
||||
return m / m_div;
|
||||
|
Loading…
Reference in New Issue
Block a user