labyrinth

view 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 source
1 #include <stdlib.h>
2 #include <math.h>
3 #include "noise.h"
5 typedef struct vec2 {
6 float x, y;
7 } vec2_t;
9 typedef struct vec3 {
10 float x, y, z;
11 } vec3_t;
13 /* ---- Ken Perlin's implementation of noise ---- */
15 #define B 0x100
16 #define BM 0xff
17 #define N 0x1000
18 #define NP 12 /* 2^N */
19 #define NM 0xfff
21 #define lerp(a, b, t) ((a) + ((b) - (a)) * t)
22 #define s_curve(t) (t * t * (3.0f - 2.0f * t))
24 #define setup(elem, b0, b1, r0, r1) \
25 do { \
26 float t = elem + N; \
27 b0 = ((int)t) & BM; \
28 b1 = (b0 + 1) & BM; \
29 r0 = t - (int)t; \
30 r1 = r0 - 1.0f; \
31 } while(0)
34 static int perm[B + B + 2]; /* permuted index from g_n onto themselves */
35 static vec3_t grad3[B + B + 2]; /* 3D random gradients */
36 static vec2_t grad2[B + B + 2]; /* 2D random gradients */
37 static float grad1[B + B + 2]; /* 1D random ... slopes */
38 static int tables_valid;
40 static vec2_t v2_normalize(vec2_t v)
41 {
42 vec2_t res;
43 float len = sqrt(v.x * v.x + v.y * v.y);
44 if(len != 0.0f) {
45 res.x = v.x / len;
46 res.y = v.y / len;
47 } else {
48 res = v;
49 }
50 return res;
51 }
53 static vec3_t v3_normalize(vec3_t v)
54 {
55 vec3_t res;
56 float len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
57 if(len != 0.0f) {
58 res.x = v.x / len;
59 res.y = v.y / len;
60 res.z = v.z / len;
61 } else {
62 res = v;
63 }
64 return res;
65 }
67 static void init_noise()
68 {
69 int i;
71 /* calculate random gradients */
72 for(i=0; i<B; i++) {
73 perm[i] = i; /* .. and initialize permutation mapping to identity */
75 grad1[i] = (float)((rand() % (B + B)) - B) / B;
77 grad2[i].x = (float)((rand() % (B + B)) - B) / B;
78 grad2[i].y = (float)((rand() % (B + B)) - B) / B;
79 grad2[i] = v2_normalize(grad2[i]);
81 grad3[i].x = (float)((rand() % (B + B)) - B) / B;
82 grad3[i].y = (float)((rand() % (B + B)) - B) / B;
83 grad3[i].z = (float)((rand() % (B + B)) - B) / B;
84 grad3[i] = v3_normalize(grad3[i]);
85 }
87 /* permute indices by swapping them randomly */
88 for(i=0; i<B; i++) {
89 int rand_idx = rand() % B;
91 int tmp = perm[i];
92 perm[i] = perm[rand_idx];
93 perm[rand_idx] = tmp;
94 }
96 /* fill up the rest of the arrays by duplicating the existing gradients */
97 /* and permutations */
98 for(i=0; i<B+2; i++) {
99 perm[B + i] = perm[i];
100 grad1[B + i] = grad1[i];
101 grad2[B + i] = grad2[i];
102 grad3[B + i] = grad3[i];
103 }
104 }
107 float noise1(float x)
108 {
109 int bx0, bx1;
110 float rx0, rx1, sx, u, v;
112 if(!tables_valid) {
113 init_noise();
114 tables_valid = 1;
115 }
117 setup(x, bx0, bx1, rx0, rx1);
118 sx = s_curve(rx0);
119 u = rx0 * grad1[perm[bx0]];
120 v = rx1 * grad1[perm[bx1]];
122 return lerp(u, v, sx);
123 }
125 float fbm1(float x, int octaves)
126 {
127 int i;
128 float res = 0.0f, freq = 1.0f;
129 for(i=0; i<octaves; i++) {
130 res += noise1(x * freq) / freq;
131 freq *= 2.0f;
132 }
133 return res;
134 }
136 float turbulence1(float x, int octaves)
137 {
138 int i;
139 float res = 0.0f, freq = 1.0f;
140 for(i=0; i<octaves; i++) {
141 res += fabs(noise1(x * freq) / freq);
142 freq *= 2.0f;
143 }
144 return res;
145 }