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