tavli
view src/pnoise.cc @ 11:a8e26f163f99
poulia
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 27 Jun 2015 08:01:51 +0300 |
parents | |
children |
line source
1 #include <stdlib.h>
2 #include "pnoise.h"
3 #include "vmath/vmath.h"
5 #define B 0x100
6 #define BM 0xff
7 #define N 0x1000
8 #define NP 12
9 #define NM 0xfff
11 #define s_curve(t) ((t) * (t) * (3.0f - 2.0f * (t)))
12 #define setup(elem, b0, b1, r0, r1) \
13 do { \
14 float t = elem + N; \
15 b0 = ((int)t) & BM; \
16 b1 = (b0 + 1) & BM; \
17 r0 = t - (int)t; \
18 r1 = r0 - 1.0f; \
19 } while(0)
21 #define setup_p(elem, b0, b1, r0, r1, p) \
22 do { \
23 float t = elem + N; \
24 b0 = (((int)t) & BM) % p; \
25 b1 = ((b0 + 1) & BM) % p; \
26 r0 = t - (int)t; \
27 r1 = r0 - 1.0f; \
28 } while(0)
30 static int perm[B + B + 2];
31 static vec2_t grad2[B + B + 2];
32 static bool tables_valid;
34 static void init_noise()
35 {
36 for(int i=0; i<B; i++) {
37 perm[i] = i;
39 grad2[i].x = (float)((rand() % (B + B)) - B) / B;
40 grad2[i].y = (float)((rand() % (B + B)) - B) / B;
41 grad2[i] = v2_normalize(grad2[i]);
42 }
44 for(int i=0; i<B; i++) {
45 int rand_idx = rand() % B;
47 int tmp = perm[i];
48 perm[i] = perm[rand_idx];
49 perm[rand_idx] = tmp;
50 }
52 for(int i=0; i<B+2; i++) {
53 perm[B + i] = perm[i];
54 grad2[B + i] = grad2[i];
55 }
56 }
58 #define lerp(a, b, t) ((a) + ((b) - (a)) * t)
60 float dbg_noise2(float x, float y)
61 {
62 if(!tables_valid) {
63 init_noise();
64 tables_valid = true;
65 }
67 int bx0, bx1, by0, by1;
68 float rx0, rx1, ry0, ry1;
69 setup(x, bx0, bx1, rx0, rx1);
70 setup(y, by0, by1, ry0, ry1);
72 int i = perm[bx0];
73 int j = perm[bx1];
75 int b00 = perm[i + by0];
76 int b10 = perm[j + by0];
77 int b01 = perm[i + by1];
78 int b11 = perm[j + by1];
80 float sx = s_curve(rx0);
81 float sy = s_curve(ry0);
83 vec2_t g00 = grad2[b00];
84 vec2_t g10 = grad2[b10];
85 vec2_t g01 = grad2[b01];
86 vec2_t g11 = grad2[b11];
88 float u = g00.x * rx0 + g00.y * ry0;
89 float v = g10.x * rx1 + g10.y * ry0;
90 float a = lerp(u, v, sx);
92 u = g01.x * rx0 + g01.y * ry1;
93 v = g11.x * rx1 + g11.y * ry1;
94 float b = lerp(u, v, sx);
96 return lerp(a, b, sy);
97 }
99 float pnoise2(float x, float y, int periodx, int periody)
100 {
101 if(!tables_valid) {
102 init_noise();
103 tables_valid = true;
104 }
106 int bx0, bx1, by0, by1;
107 float rx0, rx1, ry0, ry1;
108 setup_p(x, bx0, bx1, rx0, rx1, periodx);
109 setup_p(y, by0, by1, ry0, ry1, periody);
111 int i = perm[bx0];
112 int j = perm[bx1];
114 int b00 = perm[i + by0];
115 int b10 = perm[j + by0];
116 int b01 = perm[i + by1];
117 int b11 = perm[j + by1];
119 float sx = s_curve(rx0);
120 float sy = s_curve(ry0);
122 vec2_t g00 = grad2[b00];
123 vec2_t g10 = grad2[b10];
124 vec2_t g01 = grad2[b01];
125 vec2_t g11 = grad2[b11];
127 float u = g00.x * rx0 + g00.y * ry0;
128 float v = g10.x * rx1 + g10.y * ry0;
129 float a = lerp(u, v, sx);
131 u = g01.x * rx0 + g01.y * ry1;
132 v = g11.x * rx1 + g11.y * ry1;
133 float b = lerp(u, v, sx);
135 return lerp(a, b, sy);
136 }
138 float pturbulence2(float x, float y, int periodx, int periody, int octaves)
139 {
140 int i;
141 float res = 0.0f, freq = 1.0f;
142 for(i=0; i<octaves; i++) {
143 res += fabs(pnoise2(x * freq, y * freq, periodx, periody) / freq);
144 freq *= 2.0f;
145 periodx *= 2;
146 periody *= 2;
147 }
148 return res;
149 }