labyrinth
diff src/noise.c @ 0:8ba79034e8a6
labyrinth example initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 15 Jan 2015 14:59:38 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/noise.c Thu Jan 15 14:59:38 2015 +0200 1.3 @@ -0,0 +1,146 @@ 1.4 +#include <stdlib.h> 1.5 +#include <math.h> 1.6 +#include "noise.h" 1.7 + 1.8 +typedef struct vec2 { 1.9 + float x, y; 1.10 +} vec2_t; 1.11 + 1.12 +typedef struct vec3 { 1.13 + float x, y, z; 1.14 +} vec3_t; 1.15 + 1.16 +/* ---- Ken Perlin's implementation of noise ---- */ 1.17 + 1.18 +#define B 0x100 1.19 +#define BM 0xff 1.20 +#define N 0x1000 1.21 +#define NP 12 /* 2^N */ 1.22 +#define NM 0xfff 1.23 + 1.24 +#define lerp(a, b, t) ((a) + ((b) - (a)) * t) 1.25 +#define s_curve(t) (t * t * (3.0f - 2.0f * t)) 1.26 + 1.27 +#define setup(elem, b0, b1, r0, r1) \ 1.28 + do { \ 1.29 + float t = elem + N; \ 1.30 + b0 = ((int)t) & BM; \ 1.31 + b1 = (b0 + 1) & BM; \ 1.32 + r0 = t - (int)t; \ 1.33 + r1 = r0 - 1.0f; \ 1.34 + } while(0) 1.35 + 1.36 + 1.37 +static int perm[B + B + 2]; /* permuted index from g_n onto themselves */ 1.38 +static vec3_t grad3[B + B + 2]; /* 3D random gradients */ 1.39 +static vec2_t grad2[B + B + 2]; /* 2D random gradients */ 1.40 +static float grad1[B + B + 2]; /* 1D random ... slopes */ 1.41 +static int tables_valid; 1.42 + 1.43 +static vec2_t v2_normalize(vec2_t v) 1.44 +{ 1.45 + vec2_t res; 1.46 + float len = sqrt(v.x * v.x + v.y * v.y); 1.47 + if(len != 0.0f) { 1.48 + res.x = v.x / len; 1.49 + res.y = v.y / len; 1.50 + } else { 1.51 + res = v; 1.52 + } 1.53 + return res; 1.54 +} 1.55 + 1.56 +static vec3_t v3_normalize(vec3_t v) 1.57 +{ 1.58 + vec3_t res; 1.59 + float len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 1.60 + if(len != 0.0f) { 1.61 + res.x = v.x / len; 1.62 + res.y = v.y / len; 1.63 + res.z = v.z / len; 1.64 + } else { 1.65 + res = v; 1.66 + } 1.67 + return res; 1.68 +} 1.69 + 1.70 +static void init_noise() 1.71 +{ 1.72 + int i; 1.73 + 1.74 + /* calculate random gradients */ 1.75 + for(i=0; i<B; i++) { 1.76 + perm[i] = i; /* .. and initialize permutation mapping to identity */ 1.77 + 1.78 + grad1[i] = (float)((rand() % (B + B)) - B) / B; 1.79 + 1.80 + grad2[i].x = (float)((rand() % (B + B)) - B) / B; 1.81 + grad2[i].y = (float)((rand() % (B + B)) - B) / B; 1.82 + grad2[i] = v2_normalize(grad2[i]); 1.83 + 1.84 + grad3[i].x = (float)((rand() % (B + B)) - B) / B; 1.85 + grad3[i].y = (float)((rand() % (B + B)) - B) / B; 1.86 + grad3[i].z = (float)((rand() % (B + B)) - B) / B; 1.87 + grad3[i] = v3_normalize(grad3[i]); 1.88 + } 1.89 + 1.90 + /* permute indices by swapping them randomly */ 1.91 + for(i=0; i<B; i++) { 1.92 + int rand_idx = rand() % B; 1.93 + 1.94 + int tmp = perm[i]; 1.95 + perm[i] = perm[rand_idx]; 1.96 + perm[rand_idx] = tmp; 1.97 + } 1.98 + 1.99 + /* fill up the rest of the arrays by duplicating the existing gradients */ 1.100 + /* and permutations */ 1.101 + for(i=0; i<B+2; i++) { 1.102 + perm[B + i] = perm[i]; 1.103 + grad1[B + i] = grad1[i]; 1.104 + grad2[B + i] = grad2[i]; 1.105 + grad3[B + i] = grad3[i]; 1.106 + } 1.107 +} 1.108 + 1.109 + 1.110 +float noise1(float x) 1.111 +{ 1.112 + int bx0, bx1; 1.113 + float rx0, rx1, sx, u, v; 1.114 + 1.115 + if(!tables_valid) { 1.116 + init_noise(); 1.117 + tables_valid = 1; 1.118 + } 1.119 + 1.120 + setup(x, bx0, bx1, rx0, rx1); 1.121 + sx = s_curve(rx0); 1.122 + u = rx0 * grad1[perm[bx0]]; 1.123 + v = rx1 * grad1[perm[bx1]]; 1.124 + 1.125 + return lerp(u, v, sx); 1.126 +} 1.127 + 1.128 +float fbm1(float x, int octaves) 1.129 +{ 1.130 + int i; 1.131 + float res = 0.0f, freq = 1.0f; 1.132 + for(i=0; i<octaves; i++) { 1.133 + res += noise1(x * freq) / freq; 1.134 + freq *= 2.0f; 1.135 + } 1.136 + return res; 1.137 +} 1.138 + 1.139 +float turbulence1(float x, int octaves) 1.140 +{ 1.141 + int i; 1.142 + float res = 0.0f, freq = 1.0f; 1.143 + for(i=0; i<octaves; i++) { 1.144 + res += fabs(noise1(x * freq) / freq); 1.145 + freq *= 2.0f; 1.146 + } 1.147 + return res; 1.148 +} 1.149 +