perlin 0.1.1-x86-mingw32 → 0.2.0-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,4 +1,13 @@
1
- 0.1.0
1
+ 0.2.0
2
+ -----
3
+
4
+ * Optimised C code to avoid use of slow Ruby ivars (up to 50% time reduction!).
5
+ * Added Perlin::Generator#simplex?
6
+ * Added checks for valid values given for Perlin::Generator#octave= and Perlin::Generator#seed= (both must >= 1).
7
+ * Added visualization example/tool using Gosu (which is usable in Ruby 1.8 and 1.9, unlike the old FXRuby/OpenGL example).
8
+ * FIXED: artifacts introduced into Simplex noise as seed value increases.
9
+
10
+ 0.1.1
2
11
  -----
3
12
 
4
13
  * Converted to gem (previously was just a .c file).
@@ -0,0 +1,101 @@
1
+ require 'rubygems'
2
+ require 'texplay'
3
+ require 'fidgit'
4
+ require 'perlin'
5
+
6
+ include Gosu
7
+
8
+ class Visualizer < Chingu::Window
9
+ def initialize
10
+ super 800, 600, false, 0.1
11
+ self.caption = "Perlin Visualizer"
12
+ enable_undocumented_retrofication
13
+ push_game_state Visualize
14
+ end
15
+ end
16
+
17
+ class Visualize < Fidgit::GuiState
18
+ SLIDER_WIDTH = 180
19
+ IMAGE_WIDTH = 74
20
+ IMAGE_SCALE = 8
21
+
22
+ def initialize
23
+ super
24
+
25
+ @image = TexPlay.create_image $window, IMAGE_WIDTH, IMAGE_WIDTH, :color => :red
26
+ @noise = Perlin::Generator.new 1, 0, 1
27
+
28
+ horizontal do
29
+ image_frame @image, :factor => IMAGE_SCALE
30
+
31
+ vertical do
32
+ vertical do
33
+ @seed_label = label ""
34
+ @seed_slider = slider :range => 1..10000, :width => SLIDER_WIDTH, :tip => "Perlin::Generator#seed" do |_, value|
35
+ @seed_label.text = "Seed = #{value}"
36
+ @noise.seed = value
37
+ update_image
38
+ end
39
+ end
40
+
41
+ vertical do
42
+ @persistence_label = label ""
43
+ @persistence_slider = slider :range => 0.0..1.0, :width => SLIDER_WIDTH, :tip => "Perlin::Generator#persistence" do |_, value|
44
+ @persistence_label.text = "Persist = #{"%.2f" % value}"
45
+ @noise.persistence = value
46
+ update_image
47
+ end
48
+ end
49
+
50
+ vertical do
51
+ @octave_label = label ""
52
+ @octave_slider = slider :range => 1..10, :width => SLIDER_WIDTH, :tip => "Perlin::Generator#octave" do |_, value|
53
+ @octave_label.text = "Octave = #{value}"
54
+ @noise.octave = value
55
+ update_image
56
+ end
57
+ end
58
+
59
+ vertical :padding_top => 32 do
60
+ @classic_button = toggle_button "Classic noise?" do |_, value|
61
+ @noise.classic = value
62
+ update_image
63
+ end
64
+ end
65
+
66
+ vertical :padding_top => 64 do
67
+ @step_label = label ""
68
+ @step_slider = slider :range => 0.01..1.0, :width => SLIDER_WIDTH, value: 0.1, :tip => "Step between points (pixels) in chunk" do |_, value|
69
+ @step_label.text = "Step = #{"%.2f" % value}"
70
+ @width_label.text = "Width = #{"%.2f" % (value * IMAGE_WIDTH)}"
71
+ update_image
72
+ end
73
+
74
+ @width_label = label "", :tip => "Width of visualized area in window"
75
+ end
76
+
77
+ # Initial values, so we get the correct details.
78
+ @seed_slider.value = 0
79
+ @persistence_slider.value = 0
80
+ @octave_slider.value = 0
81
+ @step_slider.value = 0.1
82
+ end
83
+ end
84
+
85
+ update_image
86
+ end
87
+
88
+ def update_image
89
+ step = @step_slider.value
90
+ width = @image.width
91
+
92
+ @noise.chunk 0, 0, width, width, step do |n, x, y|
93
+ intensity = (n + 1) * 0.5
94
+ @image.set_pixel x.fdiv(step).round, y.fdiv(step).round, :color => [intensity, intensity, intensity], :sync_mode => :no_sync
95
+ end
96
+
97
+ @image.force_sync [0, 0, width, width]
98
+ end
99
+ end
100
+
101
+ Visualizer.new.show
@@ -1,6 +1,17 @@
1
- require 'perlin'
1
+ # WARNING:
2
+ # This code WILL NOT work with Ruby 1.9, since FXRuby/OpenGL are not compatible with the newer Ruby version.
3
+ # Since gem/bundler can't be persuaded to only require gems based on Ruby version, you'll have to manage the gems
4
+ # yourself.
5
+ #
6
+ # Requiring 'fox16' actually uses the 'fxruby' gem, which is no longer supported.
7
+ #
8
+ # Requiring 'opengl' actually uses the 'ruby-opengl' gem, not the 'opengl' gem (they are only compatible with Ruby 1.8
9
+ # and Ruby 1.9, respectively).
10
+
2
11
  require 'rubygems'
12
+ require 'perlin'
3
13
  require 'fox16'
14
+ require 'opengl'
4
15
 
5
16
  # Base framework borrowed from: http://www.fxruby.org/examples/gltest.rb
6
17
 
@@ -2,24 +2,7 @@
2
2
 
3
3
  long seed = 0; // Speeds up lookup of this value when it is accessed a LOT. PROBABLY NOT THREAD SAFE!
4
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)
5
+ float perlin_smooth_noise_2d(const int x, const int y)
23
6
  {
24
7
  const float corners = (
25
8
  perlin_noise_2d(x - 1, y - 1) +
@@ -74,14 +57,7 @@ float perlin_octaves_2d(const float x, const float y, const float p, const float
74
57
 
75
58
  // 3D ------------------------------------------------------------------
76
59
 
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)
60
+ float perlin_smooth_noise_3d(const int x, const int y, const int z)
85
61
  {
86
62
  const float corners = (
87
63
  perlin_noise_3d(x - 1, y - 1, z + 1) +
@@ -9,15 +9,32 @@
9
9
 
10
10
  extern long seed;
11
11
 
12
- static inline float perlin_interpolate(const float a, const float b, const float x);
12
+ inline float perlin_interpolate(const float a, const float b, const float x)
13
+ {
14
+ const float ft = x * M_PI;
15
+ const float f = (1 - cos(ft)) * 0.5;
16
+ return a * (1 - f) + b * f;
17
+ }
13
18
 
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);
19
+ inline float perlin_noise_2d(const int x, const int y)
20
+ {
21
+ long n = x + y * 57;
22
+ n = (n << 13) ^ n;
23
+ return (1.0 - ((n * (n * n * 15731*seed + 789221*seed) + 1376312589*seed) & 0x7fffffff) / 1073741824.0);
24
+ }
25
+
26
+ inline float perlin_noise_3d(const int x, const int y, const int z)
27
+ {
28
+ long n = x + y + z * 57;
29
+ n = (n << 13) ^ n;
30
+ return (1.0 - ((n * (n * n * 15731*seed + 789221*seed) + 1376312589*seed) & 0x7fffffff) / 1073741824.0);
31
+ }
32
+
33
+ float perlin_smooth_noise_2d(const int x, const int y);
16
34
  float perlin_interpolated_noise_2d(const float x, const float y);
17
35
  float perlin_octaves_2d(const float x, const float y, const float p, const float n);
18
36
 
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);
37
+ float perlin_smooth_noise_3d(const int x, const int y, const int z);
21
38
  float perlin_interpolated_noise_3d(const float x, const float y, const float z);
22
39
  float perlin_octaves_3d(const float x, const float y, const float z, const float p, const float n);
23
40
 
@@ -1,23 +1,106 @@
1
1
  #include "generator.h"
2
2
 
3
+ void Init_Perlin_Generator(VALUE module)
4
+ {
5
+ VALUE rb_cPerlinGenerator = rb_define_class_under(module, "Generator", rb_cObject);
6
+ rb_define_alloc_func(rb_cPerlinGenerator, Perlin_Generator_allocate);
7
+
8
+ rb_define_method(rb_cPerlinGenerator, "initialize", Perlin_Generator_init, -1);
9
+
10
+ rb_define_method(rb_cPerlinGenerator, "seed", Perlin_Generator_get_seed, 0);
11
+ rb_define_method(rb_cPerlinGenerator, "persistence", Perlin_Generator_get_persistence, 0);
12
+ rb_define_method(rb_cPerlinGenerator, "octave", Perlin_Generator_get_octave, 0);
13
+ rb_define_method(rb_cPerlinGenerator, "classic?", Perlin_Generator_get_classic, 0);
14
+
15
+ rb_define_method(rb_cPerlinGenerator, "seed=", Perlin_Generator_set_seed, 1);
16
+ rb_define_method(rb_cPerlinGenerator, "persistence=", Perlin_Generator_set_persistence, 1);
17
+ rb_define_method(rb_cPerlinGenerator, "octave=", Perlin_Generator_set_octave, 1);
18
+ rb_define_method(rb_cPerlinGenerator, "classic=", Perlin_Generator_set_classic, 1);
19
+
20
+ rb_define_method(rb_cPerlinGenerator, "[]", Perlin_Generator_run, -1);
21
+ rb_define_method(rb_cPerlinGenerator, "run2d", Perlin_Generator_run2d, 2);
22
+ rb_define_method(rb_cPerlinGenerator, "run3d", Perlin_Generator_run3d, 3);
23
+
24
+ rb_define_method(rb_cPerlinGenerator, "chunk", Perlin_Generator_chunk, -1);
25
+ rb_define_method(rb_cPerlinGenerator, "chunk2d", Perlin_Generator_chunk2d, 5);
26
+ rb_define_method(rb_cPerlinGenerator, "chunk3d", Perlin_Generator_chunk3d, 7);
27
+ }
28
+
29
+ // Memory management.
30
+
31
+ VALUE Perlin_Generator_allocate(VALUE klass)
32
+ {
33
+ PerlinGenerator* generator = ALLOC(PerlinGenerator);
34
+ memset(generator, 0, sizeof(PerlinGenerator));
35
+
36
+ return Data_Wrap_Struct(klass, 0, Perlin_Generator_free, generator);
37
+ }
38
+
39
+ void Perlin_Generator_free(PerlinGenerator* generator)
40
+ {
41
+ xfree(generator);
42
+ }
43
+
44
+ // Getters and setters.
45
+
3
46
  VALUE Perlin_Generator_set_seed(const VALUE self, const VALUE seed)
4
47
  {
5
- rb_iv_set(self, "@seed", rb_funcall(seed, rb_intern("to_i"), 0));
48
+ GENERATOR();
49
+
50
+ long _seed = NUM2LONG(seed);
51
+ if(_seed < 1) rb_raise(rb_eArgError, "seed must be >= 1");
52
+ generator->seed = _seed;
53
+
54
+ return seed;
55
+ }
56
+
57
+ VALUE Perlin_Generator_get_seed(const VALUE self)
58
+ {
59
+ GENERATOR();
60
+ return LONG2NUM(generator->seed);
6
61
  }
7
62
 
8
63
  VALUE Perlin_Generator_set_persistence(const VALUE self, const VALUE persistence)
9
64
  {
10
- rb_iv_set(self, "@persistence", rb_funcall(persistence, rb_intern("to_f"), 0));
65
+ GENERATOR();
66
+ generator->persistence = NUM2DBL(persistence);
67
+ return persistence;
68
+ }
69
+
70
+ VALUE Perlin_Generator_get_persistence(const VALUE self)
71
+ {
72
+ GENERATOR();
73
+ return rb_float_new(generator->persistence);
11
74
  }
12
75
 
13
76
  VALUE Perlin_Generator_set_octave(const VALUE self, const VALUE octave)
14
77
  {
15
- rb_iv_set(self, "@octave", rb_funcall(octave, rb_intern("to_i"), 0));
78
+ GENERATOR();
79
+
80
+ long _octave = NUM2LONG(octave);
81
+ if(_octave < 1) rb_raise(rb_eArgError, "octave must be >= 1");
82
+ generator->octave = _octave;
83
+
84
+ return octave;
85
+ }
86
+
87
+ VALUE Perlin_Generator_get_octave(const VALUE self)
88
+ {
89
+ GENERATOR();
90
+ return LONG2NUM(generator->octave);
16
91
  }
17
92
 
18
93
  VALUE Perlin_Generator_set_classic(const VALUE self, const VALUE classic)
19
94
  {
20
- rb_iv_set(self, "@classic", classic);
95
+ GENERATOR();
96
+ generator->is_classic = RTEST(classic);
97
+ return classic;
98
+ }
99
+
100
+ VALUE Perlin_Generator_get_classic(const VALUE self)
101
+ {
102
+ GENERATOR();
103
+ return (generator->is_classic ? Qtrue : Qfalse);
21
104
  }
22
105
 
23
106
  // x, y
@@ -30,16 +113,9 @@ VALUE Perlin_Generator_run(const int argc, const VALUE *argv, const VALUE self)
30
113
 
31
114
  switch(argc)
32
115
  {
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);
116
+ case 2: return Perlin_Generator_run2d(self, x, y);
117
+ case 3: return Perlin_Generator_run3d(self, x, y, z);
118
+ default: rb_raise(rb_eArgError, "%d parameters not supported (2D and 3D are)", argc);
43
119
  }
44
120
  }
45
121
 
@@ -48,19 +124,17 @@ Takes points (x, y) and returns a height (n)
48
124
  */
49
125
  VALUE Perlin_Generator_run2d(const VALUE self, const VALUE x, const VALUE y)
50
126
  {
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");
127
+ GENERATOR();
54
128
 
55
- seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
56
-
57
- if(RTEST(classic))
129
+ if(generator->is_classic)
58
130
  {
59
- return rb_float_new(perlin_octaves_2d(NUM2DBL(x), NUM2DBL(y), p, n));
131
+ seed = generator->seed; // Store in global, for speed.
132
+ return rb_float_new(perlin_octaves_2d(NUM2DBL(x), NUM2DBL(y), generator->persistence, generator->octave));
60
133
  }
61
134
  else
62
135
  {
63
- return rb_float_new(octave_noise_3d(n, p, 1.0, NUM2DBL(x), NUM2DBL(y), seed * SEED_OFFSET));
136
+ return rb_float_new(octave_noise_3d(generator->octave, generator->persistence, 1.0, NUM2DBL(x), NUM2DBL(y),
137
+ generator->seed));
64
138
  }
65
139
  }
66
140
 
@@ -69,19 +143,17 @@ Takes points (x, y, z) and returns a height (n)
69
143
  */
70
144
  VALUE Perlin_Generator_run3d(const VALUE self, const VALUE x, const VALUE y, const VALUE z)
71
145
  {
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.
146
+ GENERATOR();
77
147
 
78
- if(RTEST(classic))
148
+ if(generator->is_classic)
79
149
  {
80
- return rb_float_new(perlin_octaves_3d(NUM2DBL(x), NUM2DBL(y), NUM2DBL(z), p, n));
150
+ seed = generator->seed; // Store in global, for speed.
151
+ return rb_float_new(perlin_octaves_3d(NUM2DBL(x), NUM2DBL(y), NUM2DBL(z), generator->persistence, generator->octave));
81
152
  }
82
153
  else
83
154
  {
84
- return rb_float_new(octave_noise_4d(n, p, 1.0, NUM2DBL(x), NUM2DBL(y), NUM2DBL(z), seed * SEED_OFFSET));
155
+ return rb_float_new(octave_noise_4d(generator->octave, generator->persistence, 1.0, NUM2DBL(x), NUM2DBL(y), NUM2DBL(z),
156
+ generator->seed));
85
157
  }
86
158
 
87
159
  }
@@ -96,16 +168,9 @@ VALUE Perlin_Generator_chunk(const int argc, const VALUE *argv, const VALUE self
96
168
 
97
169
  switch(argc)
98
170
  {
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);
171
+ case 5: return Perlin_Generator_chunk2d(self, a, b, c, d, e);
172
+ case 7: return Perlin_Generator_chunk3d(self, a, b, c, d, e, f, g);
173
+ default: rb_raise(rb_eArgError, "%d parameters not supported (5 for 2D and 7 for 3D are)", argc);
109
174
  }
110
175
  }
111
176
 
@@ -114,9 +179,7 @@ Returns a chunk of coordinates starting from x, y and of size steps_x, steps_y w
114
179
  */
115
180
  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
181
  {
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"));
182
+ GENERATOR();
120
183
 
121
184
  VALUE arr, row;
122
185
  int i, j;
@@ -131,7 +194,7 @@ VALUE Perlin_Generator_chunk2d(const VALUE self, const VALUE x, const VALUE y, c
131
194
  rb_raise(rb_eArgError, "steps must be >= 1");
132
195
  }
133
196
 
134
- seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
197
+ if(generator->is_classic) seed = generator->seed; // Store in global, for speed.
135
198
 
136
199
  if(rb_block_given_p())
137
200
  {
@@ -142,14 +205,14 @@ VALUE Perlin_Generator_chunk2d(const VALUE self, const VALUE x, const VALUE y, c
142
205
  _y = y_min;
143
206
  for (j = 0; j < _steps_y; j++)
144
207
  {
145
- if(is_classic)
208
+ if(generator->is_classic)
146
209
  {
147
- rb_yield_values(3, rb_float_new(perlin_octaves_2d(_x, _y, p, n)),
210
+ rb_yield_values(3, rb_float_new(perlin_octaves_2d(_x, _y, generator->persistence, generator->octave)),
148
211
  rb_float_new(_x), rb_float_new(_y));
149
212
  }
150
213
  else
151
214
  {
152
- rb_yield_values(3, rb_float_new(octave_noise_3d(n, p, 1.0, _x, _y, seed * SEED_OFFSET)),
215
+ rb_yield_values(3, rb_float_new(octave_noise_3d(generator->octave, generator->persistence, 1.0, _x, _y, generator->seed)),
153
216
  rb_float_new(_x), rb_float_new(_y));
154
217
  }
155
218
 
@@ -171,13 +234,13 @@ VALUE Perlin_Generator_chunk2d(const VALUE self, const VALUE x, const VALUE y, c
171
234
  _y = y_min;
172
235
  for (j = 0; j < _steps_y; j++)
173
236
  {
174
- if(is_classic)
237
+ if(generator->is_classic)
175
238
  {
176
- rb_ary_push(row, rb_float_new(perlin_octaves_2d(_x, _y, p, n)));
239
+ rb_ary_push(row, rb_float_new(perlin_octaves_2d(_x, _y, generator->persistence, generator->octave)));
177
240
  }
178
241
  else
179
242
  {
180
- rb_ary_push(row, rb_float_new(octave_noise_3d(n, p, 1.0, _x, _y, seed * SEED_OFFSET)));
243
+ rb_ary_push(row, rb_float_new(octave_noise_3d(generator->octave, generator->persistence, 1.0, _x, _y, generator->seed)));
181
244
  }
182
245
 
183
246
  _y += _interval;
@@ -194,9 +257,7 @@ Returns a chunk of coordinates starting from x, y, z and of size steps_x, steps_
194
257
  */
195
258
  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
259
  {
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"));
260
+ GENERATOR();
200
261
 
201
262
  VALUE arr, row, column;
202
263
  int i, j, k;
@@ -211,7 +272,7 @@ VALUE Perlin_Generator_chunk3d(const VALUE self, const VALUE x, const VALUE y, c
211
272
  rb_raise(rb_eArgError, "steps must be >= 1");
212
273
  }
213
274
 
214
- seed = NUM2LONG(rb_iv_get(self, "@seed")); // Store in global, for speed.
275
+ if(generator->is_classic) seed = generator->seed; // Store in global, for speed.
215
276
 
216
277
  if(rb_block_given_p())
217
278
  {
@@ -224,14 +285,15 @@ VALUE Perlin_Generator_chunk3d(const VALUE self, const VALUE x, const VALUE y, c
224
285
  _z = z_min;
225
286
  for (k = 0; k < _steps_z; k++)
226
287
  {
227
- if(is_classic)
288
+ if(generator->is_classic)
228
289
  {
229
- rb_yield_values(4, rb_float_new(perlin_octaves_3d(_x, _y, _z, p, n)),
290
+ rb_yield_values(4, rb_float_new(perlin_octaves_3d(_x, _y, _z, generator->persistence, generator->octave)),
230
291
  rb_float_new(_x), rb_float_new(_y), rb_float_new(_z));
231
292
  }
232
293
  else
233
294
  {
234
- rb_yield_values(4, rb_float_new(octave_noise_4d(n, p, 1.0, _x, _y, _z, seed * SEED_OFFSET)),
295
+ rb_yield_values(4,
296
+ rb_float_new(octave_noise_4d(generator->octave, generator->persistence, 1.0, _x, _y, _z, generator->seed)),
235
297
  rb_float_new(_x), rb_float_new(_y), rb_float_new(_z));
236
298
  }
237
299
 
@@ -257,13 +319,14 @@ VALUE Perlin_Generator_chunk3d(const VALUE self, const VALUE x, const VALUE y, c
257
319
  _z = z_min;
258
320
  for (k = 0; k < _steps_z; k++)
259
321
  {
260
- if(is_classic)
322
+ if(generator->is_classic)
261
323
  {
262
- rb_ary_push(column, rb_float_new(perlin_octaves_3d(_x, _y, _z, p, n)));
324
+ rb_ary_push(column, rb_float_new(perlin_octaves_3d(_x, _y, _z, generator->persistence, generator->octave)));
263
325
  }
264
326
  else
265
327
  {
266
- rb_ary_push(column, rb_float_new(octave_noise_4d(n, p, 1.0, _x, _y, _z, seed * SEED_OFFSET)));
328
+ rb_ary_push(column, rb_float_new(octave_noise_4d(generator->octave, generator->persistence, 1.0,
329
+ _x, _y, _z, generator->seed)));
267
330
  }
268
331
 
269
332
  _z += _interval;
@@ -281,12 +344,24 @@ VALUE Perlin_Generator_chunk3d(const VALUE self, const VALUE x, const VALUE y, c
281
344
  /*
282
345
  The main initialize function which receives the inputs persistence and octave.
283
346
  */
284
- VALUE Perlin_Generator_init(VALUE self, VALUE seed, VALUE persistence, VALUE octave, VALUE classic)
347
+ VALUE Perlin_Generator_init(const int argc, const VALUE *argv, const VALUE self)
285
348
  {
349
+ VALUE seed, persistence, octave, options;
350
+
351
+ rb_scan_args(argc, argv, "31", &seed, &persistence, &octave, &options);
352
+ if(NIL_P(options))
353
+ {
354
+ options = rb_hash_new();
355
+ }
356
+ else
357
+ {
358
+ Check_Type(options, T_HASH);
359
+ }
360
+
286
361
  Perlin_Generator_set_seed(self, seed);
287
362
  Perlin_Generator_set_persistence(self, persistence);
288
363
  Perlin_Generator_set_octave(self, octave);
289
- Perlin_Generator_set_classic(self, classic);
364
+ Perlin_Generator_set_classic(self, rb_hash_aref(options, ID2SYM(rb_intern("classic"))));
290
365
 
291
366
  return self;
292
367
  }
@@ -7,21 +7,28 @@
7
7
 
8
8
  #include <ruby.h>
9
9
 
10
+ #include <stdbool.h>
11
+
10
12
  #include "classic.h"
11
13
  #include "simplex.h"
12
14
 
13
15
  extern long seed;
14
16
 
15
- // Arbitrary number used to add an extra "seed" dimension for Simplex noise.
16
- // Seed 2D noise by offsetting the 3rd dimension.
17
- // Seed 3D noise by seeding with the 4th dimension.
18
- #define SEED_OFFSET -12354.1123f
17
+ void Init_Perlin_Generator();
18
+
19
+ // Getters.
20
+ VALUE Perlin_Generator_get_seed(const VALUE self);
21
+ VALUE Perlin_Generator_get_persistence(const VALUE self);
22
+ VALUE Perlin_Generator_get_octave(const VALUE self);
23
+ VALUE Perlin_Generator_get_classic(const VALUE self);
19
24
 
25
+ // Setters.
20
26
  VALUE Perlin_Generator_set_seed(const VALUE self, const VALUE seed);
21
27
  VALUE Perlin_Generator_set_persistence(const VALUE self, const VALUE persistence);
22
28
  VALUE Perlin_Generator_set_octave(const VALUE self, const VALUE octave);
23
29
  VALUE Perlin_Generator_set_classic(const VALUE self, const VALUE classic);
24
30
 
31
+ // Actually getting noise.
25
32
  VALUE Perlin_Generator_run(const int argc, const VALUE *argv, const VALUE self);
26
33
  VALUE Perlin_Generator_run2d(const VALUE self, const VALUE x, const VALUE y);
27
34
  VALUE Perlin_Generator_run3d(const VALUE self, const VALUE x, const VALUE y, const VALUE z);
@@ -30,6 +37,23 @@ VALUE Perlin_Generator_chunk(const int argc, const VALUE *argv, const VALUE self
30
37
  VALUE Perlin_Generator_chunk2d(const VALUE self, const VALUE x, const VALUE y, const VALUE steps_x, const VALUE steps_y, VALUE interval);
31
38
  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);
32
39
 
33
- VALUE Perlin_Generator_init(const VALUE self, const VALUE seed, const VALUE persistence, const VALUE octave, const VALUE classic);
40
+ VALUE Perlin_Generator_init(const int argc, const VALUE *argv, const VALUE self);
41
+
42
+ // Data management stuff.
43
+
44
+ typedef struct _PerlinGenerator
45
+ {
46
+ bool is_classic; // True if Classic, false if Simplex.
47
+ long seed; // >= 1
48
+ long octave; // >= 1
49
+ double persistence;
50
+ } PerlinGenerator;
51
+
52
+ #define GENERATOR() \
53
+ PerlinGenerator* generator; \
54
+ Data_Get_Struct(self, PerlinGenerator, generator);
55
+
56
+ VALUE Perlin_Generator_allocate(VALUE klass);
57
+ void Perlin_Generator_free(PerlinGenerator* generator);
34
58
 
35
59
  #endif // GENERATOR_H
@@ -7,21 +7,6 @@ located at http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
7
7
 
8
8
  void Init_perlin() {
9
9
  VALUE jm_Module = rb_define_module("Perlin");
10
- VALUE rb_cPerlin = rb_define_class_under(jm_Module, "Generator", rb_cObject);
11
-
12
- rb_define_method(rb_cPerlin, "initialize_", Perlin_Generator_init, 4);
13
-
14
- rb_define_method(rb_cPerlin, "seed=", Perlin_Generator_set_seed, 1);
15
- rb_define_method(rb_cPerlin, "persistence=", Perlin_Generator_set_persistence, 1);
16
- rb_define_method(rb_cPerlin, "octave=", Perlin_Generator_set_octave, 1);
17
- rb_define_method(rb_cPerlin, "classic=", Perlin_Generator_set_classic, 1);
18
-
19
- rb_define_method(rb_cPerlin, "[]", Perlin_Generator_run, -1);
20
- rb_define_method(rb_cPerlin, "run2d", Perlin_Generator_run2d, 2);
21
- rb_define_method(rb_cPerlin, "run3d", Perlin_Generator_run3d, 3);
22
-
23
- rb_define_method(rb_cPerlin, "chunk", Perlin_Generator_chunk, -1);
24
- rb_define_method(rb_cPerlin, "chunk2d", Perlin_Generator_chunk2d, 5);
25
- rb_define_method(rb_cPerlin, "chunk3d", Perlin_Generator_chunk3d, 7);
10
+ Init_Perlin_Generator(jm_Module);
26
11
  }
27
12
 
Binary file
Binary file
@@ -2,34 +2,37 @@ module Perlin
2
2
  # Perlin noise generator.
3
3
  #
4
4
  # @!attribute [rw] seed
5
+ # Seed value for the noise pattern (>= 0)
5
6
  # @return [Integer]
6
7
  #
7
- # @!attribute [r] persistence
8
+ # @!attribute [rw] persistence
9
+ # Amount of persistence of noise through each octave
8
10
  # @return [Float]
9
11
  #
10
- # @!attribute [r] octave
12
+ # @!attribute [rw] octave
13
+ # Number of octaves (or iterations) of noise to generate (>= 1)
11
14
  # @return [Integer]
12
15
  class Generator
13
- attr_reader :seed, :octave, :persistence
14
- def classic?; @classic; end
16
+ # @!method classic?
17
+ # @return [Boolean] True for Classic noise, false for Simplex noise.
15
18
 
16
- # @!method initialize(seed, persistence, octave)
19
+ # @!method classic=(value)
20
+ # @param value [Boolean] True for Classic noise, false for Simplex noise.
21
+ # @return [Boolean]
22
+
23
+ # @return [Boolean] True for Simplex noise, false for Classic noise.
24
+ def simplex?; !classic? end
25
+
26
+ # @!method initialize(seed, persistence, octave, options={})
17
27
  # Create a noise generator.
18
28
  #
19
29
  # Using the same seed will always produce the same pattern. Animate a perlin 'texture' by altering the seed based on time.
20
30
  #
21
- # @param seed [Integer] Seed value to create a different pattern.
22
- # @param persistence [Float] Used to generate different frequencies/amplitudes of output.
23
- # @param octave [Integer] Number of iterations to run (higher number of octaves takes more time)
31
+ # @param seed [Integer] Seed value to create a different pattern (must be >= 0).
32
+ # @param persistence [Float] Used to generate different frequencies/amplitudes of output .
33
+ # @param octave [Integer] Number of iterations to run (higher number of octaves takes more time) (must be >= 1)
24
34
  # @option options :classic [Boolean] (false) Whether to use the slower Classic algorithm, rather than default (and much faster) Simplex.
25
- def initialize(seed, persistence, octave, options = {})
26
- options = {
27
- :classic => false,
28
- }.merge! options
29
35
 
30
- initialize_(seed, persistence, octave, options[:classic])
31
- end
32
- protected :initialize_ # Underlying C implementation.
33
36
 
34
37
  # @overload chunk(x, y, steps_x, steps_y, interval)
35
38
  # Calculates a rectangular section of height (n) values and returns them as a 2D array.
@@ -1,5 +1,5 @@
1
1
  # Perlin noise generation.
2
2
  module Perlin
3
3
  # Current version of the gem.
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -4,7 +4,7 @@ require File.expand_path("../../helper.rb", __FILE__)
4
4
  describe Perlin::Generator do
5
5
  before :each do
6
6
  @classic = Perlin::Generator.new 123, 1.5, 2, :classic => true
7
- @simplex = Perlin::Generator.new 0, 1.5, 2
7
+ @simplex = Perlin::Generator.new 1, 1.5, 2
8
8
  @accuracy = 0.00001
9
9
  end
10
10
 
@@ -50,12 +50,16 @@ describe Perlin::Generator do
50
50
  @classic.seed.should eq 12
51
51
  @classic.seed.should be_kind_of Integer
52
52
  end
53
+
54
+ it "should fail unless >= 1" do
55
+ lambda { @classic.seed = 0 }.should raise_error ArgumentError, "seed must be >= 1"
56
+ end
53
57
  end
54
58
 
55
59
  describe "persistence=" do
56
60
  it "should set persistence correctly" do
57
- @classic.persistence = 12
58
- @classic.persistence.should eq 12
61
+ @classic.persistence = 12.1513
62
+ @classic.persistence.should eq 12.1513
59
63
  @classic.persistence.should be_kind_of Float
60
64
  end
61
65
  end
@@ -66,6 +70,10 @@ describe Perlin::Generator do
66
70
  @classic.octave.should eq 12
67
71
  @classic.octave.should be_kind_of Integer
68
72
  end
73
+
74
+ it "should fail unless >= 1" do
75
+ lambda { @classic.octave = 0 }.should raise_error ArgumentError, "octave must be >= 1"
76
+ end
69
77
  end
70
78
 
71
79
  describe "classic=" do
@@ -97,7 +105,7 @@ describe Perlin::Generator do
97
105
  describe "SIMPLEX" do
98
106
  describe "[](x, y)" do
99
107
  it "should return the appropriate value" do
100
- @simplex[0, 1].should be_within(@accuracy).of 0.7600996515471077
108
+ @simplex[0, 1].should be_within(@accuracy).of -0.7169484162988542
101
109
  end
102
110
 
103
111
  it "should return different values based on seed" do
@@ -109,7 +117,7 @@ describe Perlin::Generator do
109
117
 
110
118
  describe "[](x, y, z)" do
111
119
  it "should return the appropriate value" do
112
- @simplex[0, 1, 2].should be_within(@accuracy).of -0.4994023090387083
120
+ @simplex[0, 1, 2].should be_within(@accuracy).of 0.3528568374548613
113
121
  end
114
122
  end
115
123
  end
@@ -141,7 +149,7 @@ describe Perlin::Generator do
141
149
  describe "SIMPLEX" do
142
150
  it "should return the appropriate values" do
143
151
  chunk = @simplex.chunk 1, 2, 3, 4, 1
144
- chunk.should eq [[0.0, 0.19517135798668975, 0.19616149193873283, -5.932618130464163e-07], [0.10886869609093779, 0.10787834101090553, -5.932618130464163e-07, -0.19616171787047829], [-0.0431512326002121, 0.0, 0.260888409614563, 0.45605969740428703]]
152
+ chunk.should eq [[0.3256153247344187, -0.044141564834959, -1.9775393411691766e-07, -0.30403976440429686], [0.0, 1.9775393411691766e-07, 0.0, -0.21674697868461495], [1.9775393411691766e-07, -0.23931307266021215, -0.7600996287015893, -5.93261818394248e-07]]
145
153
  end
146
154
 
147
155
  it "should give the same results, regardless of x/y offset" do
@@ -159,7 +167,7 @@ describe Perlin::Generator do
159
167
  @simplex.chunk 1, 2, 3, 4, 1 do |h, x, y|
160
168
  arr << [h, x, y]
161
169
  end
162
- arr.should eq [[0.0, 1.0, 2.0], [0.19517135798668975, 1.0, 3.0], [0.19616149193873283, 1.0, 4.0], [-5.932618130464163e-07, 1.0, 5.0], [0.10886869609093779, 2.0, 2.0], [0.10787834101090553, 2.0, 3.0], [-5.932618130464163e-07, 2.0, 4.0], [-0.19616171787047829, 2.0, 5.0], [-0.0431512326002121, 3.0, 2.0], [0.0, 3.0, 3.0], [0.260888409614563, 3.0, 4.0], [0.45605969740428703, 3.0, 5.0]]
170
+ arr.should eq [[0.3256153247344187, 1.0, 2.0], [-0.044141564834959, 1.0, 3.0], [-1.9775393411691766e-07, 1.0, 4.0], [-0.30403976440429686, 1.0, 5.0], [0.0, 2.0, 2.0], [1.9775393411691766e-07, 2.0, 3.0], [0.0, 2.0, 4.0], [-0.21674697868461495, 2.0, 5.0], [1.9775393411691766e-07, 3.0, 2.0], [-0.23931307266021215, 3.0, 3.0], [-0.7600996287015893, 3.0, 4.0], [-5.93261818394248e-07, 3.0, 5.0]]
163
171
  end
164
172
  end
165
173
 
@@ -201,7 +209,7 @@ describe Perlin::Generator do
201
209
  describe "SIMPLEX" do
202
210
  it "should return the appropriate values" do
203
211
  chunk = @simplex.chunk 6, 5, 4, 3, 2, 1, 1
204
- chunk.should eq [[[-0.0506731136544405], [0.13219586780905937]], [[0.32796947870374366], [0.5241572306428496]], [[-0.10557871005195935], [-0.10961889028549195]]]
212
+ chunk.should eq [[[-0.13219586780905937], [-0.10557871005195935]], [[0.057937057229464836], [0.14160177316516637]], [[0.4784122159704566], [0.23034484239760417]]]
205
213
  end
206
214
 
207
215
  it "should work with a block" do
@@ -209,7 +217,7 @@ describe Perlin::Generator do
209
217
  @simplex.chunk 6, 5, 4, 3, 2, 1, 1 do |h, x, y, z|
210
218
  arr << [h, x, y, z]
211
219
  end
212
- arr.should eq [[-0.0506731136544405, 6.0, 5.0, 4.0], [0.13219586780905937, 6.0, 6.0, 4.0], [0.32796947870374366, 7.0, 5.0, 4.0], [0.5241572306428496, 7.0, 6.0, 4.0], [-0.10557871005195935, 8.0, 5.0, 4.0], [-0.10961889028549195, 8.0, 6.0, 4.0]]
220
+ arr.should eq [[-0.13219586780905937, 6.0, 5.0, 4.0], [-0.10557871005195935, 6.0, 6.0, 4.0], [0.057937057229464836, 7.0, 5.0, 4.0], [0.14160177316516637, 7.0, 6.0, 4.0], [0.4784122159704566, 8.0, 5.0, 4.0], [0.23034484239760417, 8.0, 6.0, 4.0]]
213
221
  end
214
222
  end
215
223
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perlin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: x86-mingw32
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-07-16 00:00:00.000000000 Z
14
+ date: 2012-12-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: RedCloth
@@ -109,6 +109,54 @@ dependencies:
109
109
  - - ~>
110
110
  - !ruby/object:Gem::Version
111
111
  version: 2.1.0
112
+ - !ruby/object:Gem::Dependency
113
+ name: texplay
114
+ requirement: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ~>
118
+ - !ruby/object:Gem::Version
119
+ version: 0.4.3
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ~>
126
+ - !ruby/object:Gem::Version
127
+ version: 0.4.3
128
+ - !ruby/object:Gem::Dependency
129
+ name: gosu
130
+ requirement: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ~>
134
+ - !ruby/object:Gem::Version
135
+ version: 0.7.45
136
+ type: :development
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ~>
142
+ - !ruby/object:Gem::Version
143
+ version: 0.7.45
144
+ - !ruby/object:Gem::Dependency
145
+ name: fidgit
146
+ requirement: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ~>
150
+ - !ruby/object:Gem::Version
151
+ version: 0.2.4
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ~>
158
+ - !ruby/object:Gem::Version
159
+ version: 0.2.4
112
160
  description: ! 'Perlin Noise C extension
113
161
 
114
162
 
@@ -119,6 +167,7 @@ description: ! 'Perlin Noise C extension
119
167
 
120
168
  '
121
169
  email:
170
+ - bil.bagpuss@gmail.com
122
171
  - mojobojo@gmail.com
123
172
  executables: []
124
173
  extensions: []
@@ -142,6 +191,7 @@ files:
142
191
  - ext/perlin/extconf.rb
143
192
  - examples/chunk_in_2d.rb
144
193
  - examples/chunk_in_3d.rb
194
+ - examples/gosu.rb
145
195
  - examples/index_in_2d.rb
146
196
  - examples/index_in_3d.rb
147
197
  - examples/ogl/README.md
@@ -150,7 +200,7 @@ files:
150
200
  - spec/perlin/generator_spec.rb
151
201
  - lib/perlin/1.8/perlin.so
152
202
  - lib/perlin/1.9/perlin.so
153
- homepage: https://github.com/boj/ruby-perlin
203
+ homepage: https://github.com/spooner/ruby-perlin
154
204
  licenses:
155
205
  - MIT
156
206
  post_install_message: