perlin 0.1.0pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +13 -0
- data/LICENSE +21 -0
- data/README.md +33 -0
- data/Rakefile +85 -0
- data/examples/chunk_in_2d.rb +22 -0
- data/examples/chunk_in_3d.rb +24 -0
- data/examples/index_in_2d.rb +23 -0
- data/examples/index_in_3d.rb +25 -0
- data/examples/ogl/README.md +3 -0
- data/examples/ogl/run.rb +200 -0
- data/ext/perlin/classic.c +160 -0
- data/ext/perlin/classic.h +24 -0
- data/ext/perlin/extconf.rb +15 -0
- data/ext/perlin/generator.c +292 -0
- data/ext/perlin/generator.h +35 -0
- data/ext/perlin/perlin.c +27 -0
- data/ext/perlin/perlin.h +20 -0
- data/ext/perlin/simplex.c +475 -0
- data/ext/perlin/simplex.h +196 -0
- data/lib/perlin.rb +13 -0
- data/lib/perlin/1.9/perlin.so +0 -0
- data/lib/perlin/generator.rb +161 -0
- data/lib/perlin/version.rb +5 -0
- metadata +128 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
#include "classic.h"
|
2
|
+
|
3
|
+
long seed = 0; // Speeds up lookup of this value when it is accessed a LOT. PROBABLY NOT THREAD SAFE!
|
4
|
+
|
5
|
+
static inline float perlin_interpolate(const float a, const float b, const float x)
|
6
|
+
{
|
7
|
+
const float ft = x * M_PI;
|
8
|
+
const float f = (1 - cos(ft)) * 0.5;
|
9
|
+
return a * (1 - f) + b * f;
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
// 2D ------------------------------------------------------------------
|
14
|
+
|
15
|
+
static inline float perlin_noise_2d(const int x, const int y)
|
16
|
+
{
|
17
|
+
long n = x + y * 57;
|
18
|
+
n = (n << 13) ^ n;
|
19
|
+
return (1.0 - ((n * (n * n * 15731*seed + 789221*seed) + 1376312589*seed) & 0x7fffffff) / 1073741824.0);
|
20
|
+
}
|
21
|
+
|
22
|
+
static float perlin_smooth_noise_2d(const int x, const int y)
|
23
|
+
{
|
24
|
+
const float corners = (
|
25
|
+
perlin_noise_2d(x - 1, y - 1) +
|
26
|
+
perlin_noise_2d(x + 1, y - 1) +
|
27
|
+
perlin_noise_2d(x - 1, y + 1) +
|
28
|
+
perlin_noise_2d(x + 1, y + 1)
|
29
|
+
) / 4;
|
30
|
+
const float sides = (
|
31
|
+
perlin_noise_2d(x - 1, y) +
|
32
|
+
perlin_noise_2d(x + 1, y) +
|
33
|
+
perlin_noise_2d(x, y - 1) +
|
34
|
+
perlin_noise_2d(x, y + 1)
|
35
|
+
) / 4;
|
36
|
+
const float center = perlin_noise_2d(x, y) / 4;
|
37
|
+
return corners + sides + center;
|
38
|
+
}
|
39
|
+
|
40
|
+
float perlin_interpolated_noise_2d(const float x, const float y)
|
41
|
+
{
|
42
|
+
const int integer_X = (int)x;
|
43
|
+
const float fractional_X = x - integer_X;
|
44
|
+
|
45
|
+
const int integer_Y = (int)y;
|
46
|
+
const float fractional_Y = y - integer_Y;
|
47
|
+
|
48
|
+
const float v1 = perlin_smooth_noise_2d(integer_X, integer_Y);
|
49
|
+
const float v2 = perlin_smooth_noise_2d(integer_X + 1, integer_Y);
|
50
|
+
const float v3 = perlin_smooth_noise_2d(integer_X, integer_Y + 1);
|
51
|
+
const float v4 = perlin_smooth_noise_2d(integer_X + 1, integer_Y + 1);
|
52
|
+
|
53
|
+
const float i1 = perlin_interpolate(v1, v2, fractional_X);
|
54
|
+
const float i2 = perlin_interpolate(v3, v4, fractional_X);
|
55
|
+
|
56
|
+
return perlin_interpolate(i1, i2, fractional_Y);
|
57
|
+
}
|
58
|
+
|
59
|
+
float perlin_octaves_2d(const float x, const float y, const float p, const float n)
|
60
|
+
{
|
61
|
+
float total = 0.;
|
62
|
+
float frequency = 1., amplitude = 1.;
|
63
|
+
int i;
|
64
|
+
|
65
|
+
for (i = 0; i < n; ++i)
|
66
|
+
{
|
67
|
+
total += perlin_interpolated_noise_2d(x * frequency, y * frequency) * amplitude;
|
68
|
+
frequency *= 2;
|
69
|
+
amplitude *= p;
|
70
|
+
}
|
71
|
+
|
72
|
+
return total;
|
73
|
+
}
|
74
|
+
|
75
|
+
// 3D ------------------------------------------------------------------
|
76
|
+
|
77
|
+
static inline float perlin_noise_3d(const int x, const int y, const int z)
|
78
|
+
{
|
79
|
+
long n = x + y + z * 57;
|
80
|
+
n = (n << 13) ^ n;
|
81
|
+
return (1.0 - ((n * (n * n * 15731*seed + 789221*seed) + 1376312589*seed) & 0x7fffffff) / 1073741824.0);
|
82
|
+
}
|
83
|
+
|
84
|
+
static float perlin_smooth_noise_3d(const int x, const int y, const int z)
|
85
|
+
{
|
86
|
+
const float corners = (
|
87
|
+
perlin_noise_3d(x - 1, y - 1, z + 1) +
|
88
|
+
perlin_noise_3d(x + 1, y - 1, z + 1) +
|
89
|
+
perlin_noise_3d(x - 1, y + 1, z + 1) +
|
90
|
+
perlin_noise_3d(x + 1, y + 1, z + 1) +
|
91
|
+
perlin_noise_3d(x - 1, y - 1, z - 1) +
|
92
|
+
perlin_noise_3d(x + 1, y - 1, z - 1) +
|
93
|
+
perlin_noise_3d(x - 1, y + 1, z - 1) +
|
94
|
+
perlin_noise_3d(x + 1, y + 1, z - 1)
|
95
|
+
) / 16;
|
96
|
+
const float sides = (
|
97
|
+
perlin_noise_3d(x - 1, y, z + 1) +
|
98
|
+
perlin_noise_3d(x + 1, y, z + 1) +
|
99
|
+
perlin_noise_3d(x, y - 1, z + 1) +
|
100
|
+
perlin_noise_3d(x, y + 1, z + 1) +
|
101
|
+
perlin_noise_3d(x - 1, y, z - 1) +
|
102
|
+
perlin_noise_3d(x + 1, y, z - 1) +
|
103
|
+
perlin_noise_3d(x, y - 1, z - 1) +
|
104
|
+
perlin_noise_3d(x, y + 1, z - 1) +
|
105
|
+
perlin_noise_3d(x - 1, y - 1, z) +
|
106
|
+
perlin_noise_3d(x + 1, y - 1, z) +
|
107
|
+
perlin_noise_3d(x + 1, y + 1, z) +
|
108
|
+
perlin_noise_3d(x - 1, y + 1, z)
|
109
|
+
) / 8;
|
110
|
+
const float center = perlin_noise_2d(x, y) / 12;
|
111
|
+
return corners + sides + center;
|
112
|
+
}
|
113
|
+
|
114
|
+
float perlin_interpolated_noise_3d(const float x, const float y, const float z)
|
115
|
+
{
|
116
|
+
const int integer_X = (int)x;
|
117
|
+
const float fractional_X = x - integer_X;
|
118
|
+
|
119
|
+
const int integer_Y = (int)y;
|
120
|
+
const float fractional_Y = y - integer_Y;
|
121
|
+
|
122
|
+
const int integer_Z = (int)z;
|
123
|
+
const float fractional_Z = z - integer_Z;
|
124
|
+
|
125
|
+
const float a = perlin_smooth_noise_3d(integer_X, integer_Y, integer_Z);
|
126
|
+
const float b = perlin_smooth_noise_3d(integer_X + 1, integer_Y, integer_Z);
|
127
|
+
const float c = perlin_smooth_noise_3d(integer_X, integer_Y + 1, integer_Z);
|
128
|
+
const float d = perlin_smooth_noise_3d(integer_X, integer_Y, integer_Z + 1);
|
129
|
+
const float e = perlin_smooth_noise_3d(integer_X + 1, integer_Y + 1, integer_Z);
|
130
|
+
const float f = perlin_smooth_noise_3d(integer_X, integer_Y + 1, integer_Z + 1);
|
131
|
+
const float g = perlin_smooth_noise_3d(integer_X + 1, integer_Y, integer_Z + 1);
|
132
|
+
const float h = perlin_smooth_noise_3d(integer_X + 1, integer_Y + 1, integer_Z + 1);
|
133
|
+
|
134
|
+
const float i1 = perlin_interpolate(a, b, fractional_X);
|
135
|
+
const float i2 = perlin_interpolate(c, d, fractional_X);
|
136
|
+
const float i3 = perlin_interpolate(e, f, fractional_X);
|
137
|
+
const float i4 = perlin_interpolate(g, h, fractional_X);
|
138
|
+
|
139
|
+
const float y1 = perlin_interpolate(i1, i2, fractional_Y);
|
140
|
+
const float y2 = perlin_interpolate(i3, i4, fractional_Y);
|
141
|
+
|
142
|
+
return perlin_interpolate(y1, y2, fractional_Z);
|
143
|
+
}
|
144
|
+
|
145
|
+
float perlin_octaves_3d(const float x, const float y, const float z, const float p, const float n)
|
146
|
+
{
|
147
|
+
float total = 0.;
|
148
|
+
float frequency = 1., amplitude = 1.;
|
149
|
+
int i;
|
150
|
+
|
151
|
+
for (i = 0; i < n; ++i)
|
152
|
+
{
|
153
|
+
total += perlin_interpolated_noise_3d(x * frequency, y * frequency, z * frequency) * amplitude;
|
154
|
+
frequency *= 2;
|
155
|
+
amplitude *= p;
|
156
|
+
}
|
157
|
+
|
158
|
+
return total;
|
159
|
+
}
|
160
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
/*
|
2
|
+
* "Classic" Perlin noise generation.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#ifndef CLASSIC_H
|
6
|
+
#define CLASSIC_H
|
7
|
+
|
8
|
+
#include <math.h>
|
9
|
+
|
10
|
+
extern long seed;
|
11
|
+
|
12
|
+
static inline float perlin_interpolate(const float a, const float b, const float x);
|
13
|
+
|
14
|
+
static inline float perlin_noise_2d(const int x, const int y);
|
15
|
+
static float perlin_smooth_noise_2d(const int x, const int y);
|
16
|
+
float perlin_interpolated_noise_2d(const float x, const float y);
|
17
|
+
float perlin_octaves_2d(const float x, const float y, const float p, const float n);
|
18
|
+
|
19
|
+
static inline float perlin_noise_3d(const int x, const int y, const int z);
|
20
|
+
static float perlin_smooth_noise_3d(const int x, const int y, const int z);
|
21
|
+
float perlin_interpolated_noise_3d(const float x, const float y, const float z);
|
22
|
+
float perlin_octaves_3d(const float x, const float y, const float z, const float p, const float n);
|
23
|
+
|
24
|
+
#endif // CLASSIC_H
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
RUBY_VERSION =~ /(\d+.\d+)/
|
4
|
+
extension_name = "perlin/#{$1}/perlin"
|
5
|
+
|
6
|
+
dir_config(extension_name)
|
7
|
+
|
8
|
+
# 1.9 compatibility
|
9
|
+
$CFLAGS += ' -DRUBY_19' if RUBY_VERSION =~ /^1.9/
|
10
|
+
|
11
|
+
# let's use c99
|
12
|
+
#$CFLAGS += " -std=c99"
|
13
|
+
$CFLAGS += " -std=gnu99"
|
14
|
+
|
15
|
+
create_makefile(extension_name)
|
@@ -0,0 +1,292 @@
|
|
1
|
+
#include "generator.h"
|
2
|
+
|
3
|
+
VALUE Perlin_Generator_set_seed(const VALUE self, const VALUE seed)
|
4
|
+
{
|
5
|
+
rb_iv_set(self, "@seed", rb_funcall(seed, rb_intern("to_i"), 0));
|
6
|
+
}
|
7
|
+
|
8
|
+
VALUE Perlin_Generator_set_persistence(const VALUE self, const VALUE persistence)
|
9
|
+
{
|
10
|
+
rb_iv_set(self, "@persistence", rb_funcall(persistence, rb_intern("to_f"), 0));
|
11
|
+
}
|
12
|
+
|
13
|
+
VALUE Perlin_Generator_set_octave(const VALUE self, const VALUE octave)
|
14
|
+
{
|
15
|
+
rb_iv_set(self, "@octave", rb_funcall(octave, rb_intern("to_i"), 0));
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE Perlin_Generator_set_classic(const VALUE self, const VALUE classic)
|
19
|
+
{
|
20
|
+
rb_iv_set(self, "@classic", classic);
|
21
|
+
}
|
22
|
+
|
23
|
+
// x, y
|
24
|
+
// x, y, z
|
25
|
+
VALUE Perlin_Generator_run(const int argc, const VALUE *argv, const VALUE self)
|
26
|
+
{
|
27
|
+
VALUE x, y, z;
|
28
|
+
|
29
|
+
rb_scan_args(argc, argv, "21", &x, &y, &z);
|
30
|
+
|
31
|
+
switch(argc)
|
32
|
+
{
|
33
|
+
case 2:
|
34
|
+
Perlin_Generator_run2d(self, x, y);
|
35
|
+
break;
|
36
|
+
|
37
|
+
case 3:
|
38
|
+
Perlin_Generator_run3d(self, x, y, z);
|
39
|
+
break;
|
40
|
+
|
41
|
+
default:
|
42
|
+
rb_raise(rb_eArgError, "%d parameters not supported (2D and 3D are)", argc);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
/*
|
47
|
+
Takes points (x, y) and returns a height (n)
|
48
|
+
*/
|
49
|
+
VALUE Perlin_Generator_run2d(const VALUE self, const VALUE x, const VALUE y)
|
50
|
+
{
|
51
|
+
const float p = RFLOAT_VALUE(rb_iv_get(self, "@persistence"));
|
52
|
+
const int n = NUM2INT(rb_iv_get(self, "@octave"));
|
53
|
+
const VALUE classic = rb_iv_get(self, "@classic");
|
54
|
+
|
55
|
+
seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
|
56
|
+
|
57
|
+
if(RTEST(classic))
|
58
|
+
{
|
59
|
+
return rb_float_new(perlin_octaves_2d(NUM2DBL(x), NUM2DBL(y), p, n));
|
60
|
+
}
|
61
|
+
else
|
62
|
+
{
|
63
|
+
return rb_float_new(octave_noise_3d(n, p, 1.0, NUM2DBL(x), NUM2DBL(y), seed * SEED_OFFSET));
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
/*
|
68
|
+
Takes points (x, y, z) and returns a height (n)
|
69
|
+
*/
|
70
|
+
VALUE Perlin_Generator_run3d(const VALUE self, const VALUE x, const VALUE y, const VALUE z)
|
71
|
+
{
|
72
|
+
const float p = RFLOAT_VALUE(rb_iv_get(self, "@persistence"));
|
73
|
+
const int n = NUM2INT(rb_iv_get(self, "@octave"));
|
74
|
+
const VALUE classic = rb_iv_get(self, "@classic");
|
75
|
+
|
76
|
+
seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
|
77
|
+
|
78
|
+
if(RTEST(classic))
|
79
|
+
{
|
80
|
+
return rb_float_new(perlin_octaves_3d(NUM2DBL(x), NUM2DBL(y), NUM2DBL(z), p, n));
|
81
|
+
}
|
82
|
+
else
|
83
|
+
{
|
84
|
+
return rb_float_new(octave_noise_4d(n, p, 1.0, NUM2DBL(x), NUM2DBL(y), NUM2DBL(z), seed * SEED_OFFSET));
|
85
|
+
}
|
86
|
+
|
87
|
+
}
|
88
|
+
|
89
|
+
// x, y steps_x, steps_y, interval
|
90
|
+
// x, y, z, steps_x, steps_y, steps_z, interval
|
91
|
+
VALUE Perlin_Generator_chunk(const int argc, const VALUE *argv, const VALUE self)
|
92
|
+
{
|
93
|
+
VALUE a, b, c, d, e, f, g;
|
94
|
+
|
95
|
+
rb_scan_args(argc, argv, "52", &a, &b, &c, &d, &e, &f, &g);
|
96
|
+
|
97
|
+
switch(argc)
|
98
|
+
{
|
99
|
+
case 5:
|
100
|
+
Perlin_Generator_chunk2d(self, a, b, c, d, e);
|
101
|
+
break;
|
102
|
+
|
103
|
+
case 7:
|
104
|
+
Perlin_Generator_chunk3d(self, a, b, c, d, e, f, g);
|
105
|
+
break;
|
106
|
+
|
107
|
+
default:
|
108
|
+
rb_raise(rb_eArgError, "%d parameters not supported (5 for 2D and 7 for 3D are)", argc);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
/*
|
113
|
+
Returns a chunk of coordinates starting from x, y and of size steps_x, steps_y with interval.
|
114
|
+
*/
|
115
|
+
VALUE Perlin_Generator_chunk2d(const VALUE self, const VALUE x, const VALUE y, const VALUE steps_x, const VALUE steps_y, const VALUE interval)
|
116
|
+
{
|
117
|
+
const float p = RFLOAT_VALUE(rb_iv_get(self, "@persistence"));
|
118
|
+
const int n = NUM2INT(rb_iv_get(self, "@octave"));
|
119
|
+
const int is_classic = RTEST(rb_iv_get(self, "@classic"));
|
120
|
+
|
121
|
+
VALUE arr, row;
|
122
|
+
int i, j;
|
123
|
+
|
124
|
+
const float x_min = NUM2DBL(x), y_min = NUM2DBL(y);
|
125
|
+
float _x, _y;
|
126
|
+
const int _steps_x = NUM2INT(steps_x), _steps_y = NUM2INT(steps_y);
|
127
|
+
const float _interval = NUM2DBL(interval);
|
128
|
+
|
129
|
+
if(_steps_x < 1 || _steps_y < 1)
|
130
|
+
{
|
131
|
+
rb_raise(rb_eArgError, "steps must be >= 1");
|
132
|
+
}
|
133
|
+
|
134
|
+
seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
|
135
|
+
|
136
|
+
if(rb_block_given_p())
|
137
|
+
{
|
138
|
+
// Iterate through x, then y [0, 0], [1, 0], [2, 0]...
|
139
|
+
_x = x_min;
|
140
|
+
for (i = 0; i < _steps_x; i++)
|
141
|
+
{
|
142
|
+
_y = y_min;
|
143
|
+
for (j = 0; j < _steps_y; j++)
|
144
|
+
{
|
145
|
+
if(is_classic)
|
146
|
+
{
|
147
|
+
rb_yield_values(3, rb_float_new(perlin_octaves_2d(_x, _y, p, n)),
|
148
|
+
rb_float_new(_x), rb_float_new(_y));
|
149
|
+
}
|
150
|
+
else
|
151
|
+
{
|
152
|
+
rb_yield_values(3, rb_float_new(octave_noise_3d(n, p, 1.0, _x, _y, seed * SEED_OFFSET)),
|
153
|
+
rb_float_new(_x), rb_float_new(_y));
|
154
|
+
}
|
155
|
+
|
156
|
+
_y += _interval;
|
157
|
+
}
|
158
|
+
_x += _interval;
|
159
|
+
}
|
160
|
+
|
161
|
+
return Qnil;
|
162
|
+
}
|
163
|
+
else
|
164
|
+
{
|
165
|
+
// 2D array can be indexed with arr[x][y]
|
166
|
+
arr = rb_ary_new();
|
167
|
+
_x = x_min;
|
168
|
+
for (i = 0; i < _steps_x; i++)
|
169
|
+
{
|
170
|
+
row = rb_ary_new();
|
171
|
+
_y = y_min;
|
172
|
+
for (j = 0; j < _steps_y; j++)
|
173
|
+
{
|
174
|
+
if(is_classic)
|
175
|
+
{
|
176
|
+
rb_ary_push(row, rb_float_new(perlin_octaves_2d(_x, _y, p, n)));
|
177
|
+
}
|
178
|
+
else
|
179
|
+
{
|
180
|
+
rb_ary_push(row, rb_float_new(octave_noise_3d(n, p, 1.0, _x, _y, seed * SEED_OFFSET)));
|
181
|
+
}
|
182
|
+
|
183
|
+
_y += _interval;
|
184
|
+
}
|
185
|
+
rb_ary_push(arr, row);
|
186
|
+
_x += _interval;
|
187
|
+
}
|
188
|
+
return arr;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
|
192
|
+
/*
|
193
|
+
Returns a chunk of coordinates starting from x, y, z and of size steps_x, steps_y, size_z with interval.
|
194
|
+
*/
|
195
|
+
VALUE Perlin_Generator_chunk3d(const VALUE self, const VALUE x, const VALUE y, const VALUE z, const VALUE steps_x, const VALUE steps_y, const VALUE steps_z, const VALUE interval)
|
196
|
+
{
|
197
|
+
const float p = RFLOAT_VALUE(rb_iv_get(self, "@persistence"));
|
198
|
+
const int n = NUM2INT(rb_iv_get(self, "@octave"));
|
199
|
+
const int is_classic = RTEST(rb_iv_get(self, "@classic"));
|
200
|
+
|
201
|
+
VALUE arr, row, column;
|
202
|
+
int i, j, k;
|
203
|
+
|
204
|
+
const float x_min = NUM2DBL(x), y_min = NUM2DBL(y), z_min = NUM2DBL(z);
|
205
|
+
float _x, _y, _z;
|
206
|
+
const int _steps_x = NUM2INT(steps_x), _steps_y = NUM2INT(steps_y), _steps_z = NUM2INT(steps_z);
|
207
|
+
const float _interval = NUM2DBL(interval);
|
208
|
+
|
209
|
+
if(_steps_x < 1 || _steps_y < 1 || _steps_z < 1)
|
210
|
+
{
|
211
|
+
rb_raise(rb_eArgError, "steps must be >= 1");
|
212
|
+
}
|
213
|
+
|
214
|
+
seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
|
215
|
+
|
216
|
+
if(rb_block_given_p())
|
217
|
+
{
|
218
|
+
_x = x_min;
|
219
|
+
for (i = 0; i < _steps_x; i++)
|
220
|
+
{
|
221
|
+
_y = y_min;
|
222
|
+
for (j = 0; j < _steps_y; j++)
|
223
|
+
{
|
224
|
+
_z = z_min;
|
225
|
+
for (k = 0; k < _steps_z; k++)
|
226
|
+
{
|
227
|
+
if(is_classic)
|
228
|
+
{
|
229
|
+
rb_yield_values(4, rb_float_new(perlin_octaves_3d(_x, _y, _z, p, n)),
|
230
|
+
rb_float_new(_x), rb_float_new(_y), rb_float_new(_z));
|
231
|
+
}
|
232
|
+
else
|
233
|
+
{
|
234
|
+
rb_yield_values(4, rb_float_new(octave_noise_4d(n, p, 1.0, _x, _y, _z, seed * SEED_OFFSET)),
|
235
|
+
rb_float_new(_x), rb_float_new(_y), rb_float_new(_z));
|
236
|
+
}
|
237
|
+
|
238
|
+
_z += _interval;
|
239
|
+
}
|
240
|
+
_y += _interval;
|
241
|
+
}
|
242
|
+
_x += _interval;
|
243
|
+
}
|
244
|
+
return Qnil;
|
245
|
+
}
|
246
|
+
else
|
247
|
+
{
|
248
|
+
arr = rb_ary_new();
|
249
|
+
_x = x_min;
|
250
|
+
for (i = 0; i < _steps_x; i++)
|
251
|
+
{
|
252
|
+
row = rb_ary_new();
|
253
|
+
_y = y_min;
|
254
|
+
for (j = 0; j < _steps_y; j++)
|
255
|
+
{
|
256
|
+
column = rb_ary_new();
|
257
|
+
_z = z_min;
|
258
|
+
for (k = 0; k < _steps_z; k++)
|
259
|
+
{
|
260
|
+
if(is_classic)
|
261
|
+
{
|
262
|
+
rb_ary_push(column, rb_float_new(perlin_octaves_3d(_x, _y, _z, p, n)));
|
263
|
+
}
|
264
|
+
else
|
265
|
+
{
|
266
|
+
rb_ary_push(column, rb_float_new(octave_noise_4d(n, p, 1.0, _x, _y, _z, seed * SEED_OFFSET)));
|
267
|
+
}
|
268
|
+
|
269
|
+
_z += _interval;
|
270
|
+
}
|
271
|
+
rb_ary_push(row, column);
|
272
|
+
_y += _interval;
|
273
|
+
}
|
274
|
+
rb_ary_push(arr, row);
|
275
|
+
_x += _interval;
|
276
|
+
}
|
277
|
+
return arr;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
/*
|
282
|
+
The main initialize function which receives the inputs persistence and octave.
|
283
|
+
*/
|
284
|
+
VALUE Perlin_Generator_init(VALUE self, VALUE seed, VALUE persistence, VALUE octave, VALUE classic)
|
285
|
+
{
|
286
|
+
Perlin_Generator_set_seed(self, seed);
|
287
|
+
Perlin_Generator_set_persistence(self, persistence);
|
288
|
+
Perlin_Generator_set_octave(self, octave);
|
289
|
+
Perlin_Generator_set_classic(self, classic);
|
290
|
+
|
291
|
+
return self;
|
292
|
+
}
|