perlin_noise 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.swp
2
+ *.swo
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in perlin.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,485 @@
1
+ # perlin
2
+ Ruby-implementation of N-dimension Perlin noise.
3
+
4
+ ## Installation
5
+
6
+ ```
7
+ gem install perlin_noise
8
+ ```
9
+
10
+ ```ruby
11
+ require 'perlin_noise'
12
+ ```
13
+
14
+ ## Basic
15
+ ### One-dimension
16
+ ```ruby
17
+ n1d = Perlin::Noise.new 1
18
+ 0.step(100, 0.01) do |x|
19
+ puts n1d[x]
20
+ end
21
+ ```
22
+
23
+ ### Two-dimension, three-dimension, or even more dimensions
24
+ ```ruby
25
+ n2d = Perlin::Noise.new 2
26
+ 0.step(100, 0.01) do |x|
27
+ 0.step(100, 0.01) do |y|
28
+ puts n2d[x, y]
29
+ end
30
+ end
31
+
32
+ n3d = Perlin::Noise.new 3
33
+ n3d[rand, rand, rand]
34
+
35
+ n5d = Perlin::Noise.new 5
36
+ n5d[rand, rand, rand, rand, rand]
37
+ ```
38
+
39
+ ## Options
40
+ ### :interval
41
+ A gradient noise repeats itself at certain interval. (Default interval is 256)
42
+ You can change the interval of the noise generator but keep in mind that
43
+ longer interval requires more pseudo-random gradient vectors to be maintained in memory.
44
+
45
+ ```ruby
46
+ n3d = Perlin::Noise.new 3, :interval => 100
47
+ n3d[0.1, 0.2, 0.3]
48
+ n3d[0.1, 0.2, 100.3]
49
+ ```
50
+
51
+ ## Range of noise function
52
+ While the original algorithm outputs a number between -1.0 and 1.0,
53
+ Perlin::Noise#[] manipulates this output and returns a number between 0.0 and 1.0 for ease of use.
54
+ Thus, noise values at all of the integer lattice points should be 0.5, not 0.
55
+
56
+ ## Increasing the contrast
57
+ Even though the range of the noise function is from 0 to 1,
58
+ you'll rarely see a noise value close to either end,
59
+ as most of the values are distributed around the center.
60
+ You might want to apply S-shaped curve functions defined in Perlin::Curve module
61
+ one or more times to push away those numbers to either end.
62
+
63
+ ```ruby
64
+ noise = Perlin::Noise.new 1
65
+
66
+ n = noise[0.1]
67
+
68
+ 3.times do
69
+ n = Perlin::Curve::CUBIC.call n
70
+ end
71
+ ```
72
+
73
+ There's a shortcut for this process.
74
+ ```ruby
75
+ contrast = Perlin::Curve.contrast(Perlin::Curve::CUBIC, 3)
76
+ n = contrast.call n
77
+ ```
78
+
79
+ ## Noise gallery
80
+
81
+ ### 1D noise
82
+
83
+ ```ruby
84
+ noise = Perlin::Noise.new 1, :interval => 200
85
+ 0.step(300, 0.1).each do |x|
86
+ n = noise[x]
87
+ len = (n * 60).to_i
88
+ puts '#' * len
89
+ end
90
+ ```
91
+
92
+ ```
93
+ ##############################
94
+ ################################
95
+ ##################################
96
+ ##################################
97
+ ################################
98
+ ##############################
99
+ ###########################
100
+ #########################
101
+ #########################
102
+ ###########################
103
+ ##############################
104
+ #################################
105
+ #####################################
106
+ ########################################
107
+ ###########################################
108
+ #############################################
109
+ ###########################################
110
+ ########################################
111
+ #####################################
112
+ #################################
113
+ ##############################
114
+ ###########################
115
+ #########################
116
+ #########################
117
+ ###########################
118
+ ##############################
119
+ ################################
120
+ ##################################
121
+ ##################################
122
+ ################################
123
+ ##############################
124
+ ##########################
125
+ ######################
126
+ ###################
127
+ ################
128
+ ###############
129
+ ################
130
+ ###################
131
+ ######################
132
+ ##########################
133
+ ##############################
134
+ #################################
135
+ #####################################
136
+ ########################################
137
+ ###########################################
138
+ #############################################
139
+ ###########################################
140
+ ########################################
141
+ #####################################
142
+ #################################
143
+ ##############################
144
+ ##########################
145
+ ######################
146
+ ###################
147
+ ################
148
+ ###############
149
+ ################
150
+ ###################
151
+ ######################
152
+ ##########################
153
+ ##############################
154
+ #################################
155
+ #####################################
156
+ ########################################
157
+ ###########################################
158
+ #############################################
159
+ ###########################################
160
+ ########################################
161
+ #####################################
162
+ #################################
163
+ ##############################
164
+ ##########################
165
+ ######################
166
+ ###################
167
+ ################
168
+ ###############
169
+ ################
170
+ ###################
171
+ ######################
172
+ ##########################
173
+ ##############################
174
+ ################################
175
+ ##################################
176
+ ##################################
177
+ ################################
178
+ ##############################
179
+ ###########################
180
+ #########################
181
+ #########################
182
+ ###########################
183
+ ##############################
184
+ #################################
185
+ #####################################
186
+ ########################################
187
+ ###########################################
188
+ #############################################
189
+ ###########################################
190
+ ########################################
191
+ #####################################
192
+ #################################
193
+ ##############################
194
+ ###########################
195
+ #########################
196
+ #########################
197
+ ###########################
198
+ ##############################
199
+ ################################
200
+ ##################################
201
+ ##################################
202
+ ################################
203
+ ##############################
204
+ ##########################
205
+ ######################
206
+ ###################
207
+ ################
208
+ ###############
209
+ ################
210
+ ###################
211
+ ######################
212
+ ##########################
213
+ ##############################
214
+ #################################
215
+ #####################################
216
+ ########################################
217
+ ###########################################
218
+ #############################################
219
+ ###########################################
220
+ ########################################
221
+ #####################################
222
+ #################################
223
+ ##############################
224
+ ##########################
225
+ ######################
226
+ ###################
227
+ ################
228
+ ```
229
+
230
+ ### 2D noise
231
+ ```ruby
232
+ noises = Perlin::Noise.new(2)
233
+ contrast = Perlin::Curve.contrast(Perlin::Curve::CUBIC, 2)
234
+
235
+ bars = " ▁▂▃▄▅▆▇█".each_char.to_a
236
+ bar = lambda { |n|
237
+ bars[ (bars.length * n).floor ]
238
+ }
239
+
240
+ 0.upto(100) do |i|
241
+ 70.times do |y|
242
+ n = noises[i * 0.1, y * 0.1]
243
+ n = contrast.call n
244
+
245
+ print bar.call(n)
246
+ end
247
+ puts
248
+ end
249
+ ```
250
+
251
+ ```
252
+ ▃▃▂▂▁▁▁▁▂▃▃▄▅▅▆▆▆▅▅▅▅▅▅▄▄▃▃▂▂▃▃▄▄▄▄▄▄▄▄▄▅▅▆▇▇▇▇▇▆▅▄▃▂▁ ▁▂▃▄▅▆▆▇▇▆▆▅▅
253
+ ▂▂▁▁▁▁▁▁▂▂▃▄▄▅▆▆▆▆▆▆▆▆▆▅▅▄▃▂▂▂▃▃▄▄▄▄▄▅▅▅▆▆▇▇██▇▇▆▅▄▃▂▁ ▁▂▃▄▅▆▆▇▇▇▇▆▆
254
+ ▁▁▁▁▁▁▁▁▂▃▃▄▄▅▅▆▆▆▇▇▇▇▇▆▆▅▄▃▃▃▃▃▄▄▄▅▅▆▆▆▇▇▇███▇▇▆▅▄▃▂▁ ▁▁▂▃▄▅▆▇▇▇▇▇▇
255
+ ▁ ▁▁▁▂▂▃▃▃▄▄▅▅▆▆▇▇▇▇▇▇▇▇▆▅▄▃▃▃▄▄▄▅▆▆▇▇▇▇▇████▇▇▆▆▅▄▃▂▁ ▁▁▂▂▃▄▅▆▇████
256
+ ▁▁▁▂▃▃▄▄▄▄▄▄▅▅▆▆▇▇▇███▇▇▆▅▄▄▄▄▄▅▅▆▇▇▇▇▇▇████▇▇▇▆▅▅▄▂▁▁▁▁▁▁▂▃▄▅▆▇████
257
+ ▁▁▁▂▃▄▄▅▅▅▅▄▄▄▄▄▅▅▆▇▇▇███▇▇▆▅▅▅▅▅▅▆▆▇▇▇▇▇▇▇▇▇▇▇▇▇▆▆▅▄▃▂▁▁▁▁▁▂▂▃▄▆▇▇███
258
+ ▁▁▂▃▄▅▆▆▆▅▅▅▄▃▃▃▃▄▅▆▇▇▇███▇▇▆▆▅▅▅▅▆▆▇▇▇▇▇▆▆▆▆▆▇▇▆▆▆▅▅▄▃▂▁▁▁▁▂▂▃▄▅▆▇▇▇▇
259
+ ▂▃▃▄▅▆▇▆▆▆▅▄▄▃▂▂▂▃▄▅▆▆▇▇██▇▇▆▆▅▅▅▅▅▆▆▆▇▆▆▅▅▅▅▅▆▆▆▆▆▅▄▄▃▂▂▂▂▂▂▃▃▄▅▆▆▇▇▆
260
+ ▃▄▅▅▆▇▇▇▆▅▅▄▃▂▁▁▁▂▃▄▅▅▆▇▇▇▇▇▆▅▅▄▄▄▅▅▆▆▆▅▅▄▄▄▄▄▅▅▅▅▅▄▄▃▃▂▂▂▂▃▃▃▄▅▅▆▆▆▆▅
261
+ ▄▅▅▆▇▇▇▆▆▅▄▃▂▂▁▁▁▁▂▃▄▅▆▆▇▇▇▆▅▅▄▄▃▄▄▄▅▅▅▅▄▃▃▃▃▃▄▄▄▄▄▄▃▃▂▂▂▃▃▄▄▄▅▅▅▆▅▅▅▄
262
+ ▅▅▆▇▇▇▆▆▅▄▃▃▂▁▁ ▁▁▂▃▃▄▅▆▆▆▆▅▄▄▃▃▂▃▃▃▄▄▄▄▃▃▂▂▂▃▃▃▃▃▃▃▂▂▂▂▃▃▄▅▅▅▆▆▆▆▅▅▄▃
263
+ ▅▆▆▇▇▇▆▅▄▃▂▂▁▁ ▁▂▂▃▄▅▅▆▆▅▄▃▂▂▂▂▂▂▃▃▄▄▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▃▄▅▅▆▆▆▆▆▆▅▄▄▃
264
+ ▅▆▆▆▆▆▅▄▃▂▁▁▁ ▁▂▃▃▄▅▅▅▅▄▃▂▁▁▁▁▁▂▂▃▄▄▃▃▂▂▂▁▁▁▁▁▁▁▁▁▁▂▃▄▅▆▆▆▆▆▆▆▅▅▄▄▃
265
+ ▅▅▆▆▆▅▄▃▂▁▁▁ ▁▁▂▃▄▄▅▅▅▄▃▂▁▁ ▁▁▂▃▄▄▄▃▃▂▂▁▁▁▁▁▁ ▁▁▂▃▄▅▆▆▆▆▆▆▆▅▅▄▄▄
266
+ ▄▅▅▅▅▄▃▂▁▁▁▁▁ ▁▁▁▂▃▄▄▅▅▅▅▄▃▁▁ ▁▂▃▄▅▅▅▄▄▃▂▁▁ ▁▁▂▄▅▆▆▆▆▆▅▅▅▅▅▅▅▄
267
+ ▄▄▄▄▄▃▂▁▁▁▁▁▁▁▁▁▂▃▃▄▅▆▆▆▅▄▃▁▁ ▁▁▂▄▅▅▅▅▅▄▃▂▂▁ ▁▁▂▃▅▆▆▆▆▅▅▄▄▄▄▅▅▅▅
268
+ ▃▄▄▄▃▃▂▁▁▁▁▂▂▂▂▂▃▃▄▅▅▆▆▆▅▄▃▂▁▁▁▁▁▂▃▅▅▆▆▆▅▅▄▃▂▁▁▁▁▁▁▁▂▃▄▅▆▆▆▆▅▄▃▃▃▄▄▅▅▆
269
+ ▃▄▄▄▄▃▂▂▂▂▂▃▃▃▃▃▃▄▄▅▅▆▆▆▅▅▄▃▂▂▂▂▃▃▄▅▆▆▆▆▅▅▄▃▂▁▁▁▁▂▂▂▃▄▅▆▇▆▆▅▄▃▃▂▃▃▄▅▅▆
270
+ ▃▄▄▄▄▃▃▃▂▃▃▄▄▄▄▄▃▃▄▄▅▅▆▆▅▅▄▃▃▃▃▃▄▄▅▆▆▆▆▅▅▄▃▃▂▂▂▂▂▃▃▄▄▅▆▇▇▇▆▅▄▃▂▂▂▃▄▄▅▅
271
+ ▄▅▅▅▅▄▄▃▃▃▄▅▅▅▄▄▃▃▃▃▄▅▅▅▅▅▅▄▄▄▄▄▅▅▆▆▆▆▅▅▄▃▃▂▂▂▂▂▃▄▄▅▅▆▇▇▇▇▆▅▄▃▂▂▂▂▃▄▄▄
272
+ ▅▅▆▆▅▅▅▄▄▄▅▅▅▅▅▄▃▂▂▃▃▄▄▅▅▅▅▅▅▅▅▅▆▆▆▆▆▅▄▄▃▃▂▂▂▂▂▃▄▄▅▅▆▇▇▇▇▇▆▅▄▃▂▂▂▂▂▃▃▃
273
+ ▆▆▆▆▆▆▅▅▅▅▆▆▆▆▅▄▃▂▂▂▂▃▃▄▅▅▆▆▆▆▆▆▆▇▆▆▅▄▃▃▂▂▁▁▁▂▂▃▄▅▅▆▆▇▇██▇▇▆▅▄▃▂▂▂▂▂▃▃
274
+ ▆▇▇▇▇▆▆▆▆▆▆▇▇▆▅▄▃▂▁▁▁▂▂▃▄▅▆▆▇▇▇▇▇▇▇▆▅▄▃▂▁▁▁▁▁▁▂▃▄▅▅▆▆▇▇██▇▇▆▅▄▄▃▂▂▂▂▂▂
275
+ ▆▇▇▇▇▇▆▆▆▆▇▇▇▇▆▄▃▁▁▁▁▁▁▂▄▅▆▇▇████▇▇▆▅▃▂▁▁▁ ▁▁▂▃▄▅▅▅▆▆▇▇▇▇▇▇▆▅▄▃▃▂▂▂▂▂
276
+ ▆▇▇▇▇▇▆▆▆▆▇▇▇▇▆▅▃▁▁ ▁▁▂▃▅▆▇█████▇▇▆▅▃▂▁▁ ▁▁▂▃▄▄▄▄▅▅▆▇▇▇▇▇▆▆▅▄▃▂▂▂▂▃
277
+ ▆▇▇▇▇▆▆▅▅▆▆▇▇▇▇▅▄▂▁▁▁▁▁▂▃▅▆▇███▇▇▇▆▆▅▄▃▂▁▁ ▁▁▂▃▄▄▄▃▄▄▅▆▇▇▇▇▇▆▅▄▃▃▂▂▃▃
278
+ ▅▆▇▇▆▆▅▅▅▅▆▇▇▇▇▆▄▃▂▁▁▁▁▂▃▅▆▇▇▇▇▇▇▆▆▆▅▄▃▂▂▁▁▁▁▂▃▃▄▄▃▃▃▃▄▅▆▆▇▇▆▆▅▄▃▂▂▂▃▃
279
+ ▅▆▆▆▆▅▄▄▄▄▅▆▇▇▇▆▅▄▃▂▂▂▂▂▃▄▅▆▆▆▆▆▅▅▅▅▅▅▄▃▃▂▁▁▂▂▃▄▄▄▃▂▂▂▃▄▅▆▆▆▆▅▅▄▃▂▂▂▃▄
280
+ ▄▅▆▆▅▄▄▃▃▄▄▅▆▇▇▇▆▅▄▃▃▃▃▃▄▄▅▅▆▅▅▅▄▅▅▅▅▅▅▄▃▃▂▂▂▃▄▄▄▄▃▃▂▂▃▃▄▅▅▅▅▄▄▃▂▂▂▂▃▄
281
+ ▄▅▅▅▅▄▃▃▃▃▄▅▆▇▇▇▆▆▅▄▄▄▄▄▄▄▅▅▅▄▄▄▄▄▄▅▅▆▅▅▄▃▃▃▃▄▄▅▅▅▄▃▃▃▃▃▄▄▄▄▄▄▃▂▁▁▁▂▂▃
282
+ ▄▅▅▅▅▄▃▃▂▃▄▅▆▆▇▇▇▆▆▅▅▅▄▄▄▄▄▄▄▄▃▃▃▃▄▅▆▆▆▅▅▄▃▃▄▄▅▅▆▅▅▄▄▃▃▃▃▃▄▃▃▃▂▁▁▁▁▁▂▃
283
+ ▃▄▅▅▄▄▃▃▃▃▄▅▆▆▇▇▇▇▆▆▅▅▅▅▅▄▄▄▄▃▃▂▂▃▄▅▆▆▆▆▅▄▄▄▄▅▆▆▆▆▆▅▅▄▃▃▃▃▂▂▂▂▁▁▁ ▁▁▂▃
284
+ ▃▃▄▄▄▄▃▃▃▄▄▅▆▇▇▇▇▇▆▆▆▅▅▅▅▄▄▄▄▃▃▃▃▃▄▅▆▇▇▆▆▅▅▄▅▅▆▇▇▇▆▆▆▅▄▃▂▂▁▁▁▁▁ ▁▁▂▃
285
+ ▂▃▃▄▄▄▄▄▄▄▅▆▆▇▇▇▇▇▆▆▅▅▅▄▄▄▄▄▄▄▃▃▃▄▅▆▇▇▇▇▆▅▅▅▅▅▆▇▇▇▇▇▆▆▄▃▂▁▁▁▁ ▁▁▂▃▃
286
+ ▁▂▃▃▄▄▄▄▅▅▆▆▇▇▇▇▇▇▆▅▅▄▄▄▄▄▄▅▅▅▄▄▄▅▆▇▇▇▇▇▆▆▅▄▄▅▅▆▇▇▇▇▇▆▅▃▂▁▁ ▁▁▁▂▂▃▄
287
+ ▁▂▃▃▄▄▅▅▅▆▆▆▇▇▇▇▇▆▅▅▄▃▃▃▃▄▄▅▅▅▅▅▅▅▆▇▇▇▇▇▆▅▄▄▄▄▄▅▆▇▇▇▇▆▅▄▂▁▁ ▁▁▁▁▁▂▂▃▄▅
288
+ ▂▂▃▃▄▅▅▅▆▆▆▆▆▇▇▇▆▆▅▄▃▃▂▂▃▃▄▅▅▆▅▅▅▆▆▇▇▇▇▆▆▅▄▃▃▃▃▄▅▆▆▇▇▆▅▄▃▂▁▁▁▁▂▂▂▃▃▄▄▅
289
+ ▂▃▃▄▅▅▅▅▆▆▆▆▆▆▆▆▆▅▅▄▃▃▂▂▂▃▄▅▅▆▅▅▅▆▆▇▇▇▆▆▅▄▃▂▂▂▂▃▄▅▆▆▆▆▅▄▃▂▂▂▂▃▃▃▃▄▄▄▄▅
290
+ ▃▄▄▅▅▅▅▅▅▅▅▅▅▆▆▆▆▆▅▄▃▃▂▂▂▃▄▄▅▅▅▅▅▅▆▆▇▆▆▅▄▃▂▂▁▁▁▂▃▄▅▅▆▆▅▄▃▃▃▃▃▄▄▄▄▄▄▄▄▄
291
+ ▄▄▅▅▅▅▅▄▄▄▄▄▄▅▅▆▆▆▅▅▄▃▃▂▂▃▃▄▄▄▄▄▄▅▅▆▆▆▆▅▄▃▂▁▁▁▁▁▂▃▄▅▅▅▅▄▄▃▃▃▄▅▅▅▅▄▄▃▃▄
292
+ ▅▅▆▆▅▅▄▄▃▃▃▃▄▄▅▆▆▆▆▅▅▄▃▃▃▃▃▃▃▃▃▃▃▄▄▅▆▆▅▅▄▃▂▁ ▁▂▂▃▄▄▅▅▄▄▄▄▄▅▅▅▅▅▄▃▃▃▃
293
+ ▆▆▆▆▆▅▄▃▃▂▂▃▃▄▅▆▆▆▆▆▅▅▄▃▃▂▂▂▂▂▂▂▂▂▃▄▅▅▅▄▃▃▂▁ ▁▁▂▂▃▃▄▄▄▄▄▄▅▅▆▆▆▅▄▃▃▂▂
294
+ ▆▇▇▇▆▅▄▃▂▂▂▂▃▄▅▅▆▆▆▆▆▅▅▄▃▃▂▂▁▁▁▁▁▁▂▃▄▄▄▄▃▃▂▁▁ ▁▁▁▂▂▃▃▃▃▄▄▅▅▆▆▆▅▅▄▃▃▃
295
+ ▇▇▇▇▆▅▄▃▂▂▂▃▃▄▅▅▆▆▆▆▆▆▅▅▄▃▂▁▁▁ ▁▁▂▃▄▄▄▄▃▃▂▁▁▁ ▁▁▁▁▂▂▂▂▃▄▄▅▅▆▆▆▅▄▄▃▃
296
+ ▇▇▇▇▇▆▄▃▃▂▃▃▄▄▅▅▅▅▆▆▆▆▆▅▅▄▃▂▁ ▁▁▂▃▄▄▄▄▄▃▃▂▁▁▁▁▁▁▁▁▁▁▂▂▃▄▄▅▅▆▆▆▅▅▄▄
297
+ ▇▇▇▇▇▆▄▃▃▃▄▄▅▅▅▅▅▅▅▅▅▆▆▆▆▅▃▂▁▁ ▁▁▂▃▄▄▅▅▅▄▃▃▂▁▁▁▁▁ ▁▁▁▂▃▄▄▅▅▆▆▆▆▅▅
298
+ ▆▇▇▇▆▅▄▄▃▄▄▅▅▅▅▅▄▄▄▄▅▆▆▆▆▆▅▃▂▁▁▁ ▁▁▂▃▄▄▅▆▆▆▅▄▃▂▂▁▁▁▁ ▁▁▂▂▃▄▅▅▆▆▆▆▆▆
299
+ ▅▆▆▆▆▅▄▄▃▄▅▅▆▅▅▄▄▃▃▄▄▅▆▇▇▆▆▄▃▂▂▂▁▁▁▁▁▂▃▄▄▅▆▆▇▆▆▄▃▃▂▂▁▁▁ ▁▁▂▂▃▄▄▅▆▇▇▆▆▆
300
+ ▄▅▆▆▅▅▄▃▃▄▄▅▆▅▅▄▃▃▃▃▄▅▆▇▇▇▆▅▄▄▃▃▂▁▁▁▁▁▂▃▄▅▆▇▇▇▆▆▅▄▃▃▂▁▁▁▁▁▂▃▃▄▅▆▆▇▇▆▆▅
301
+ ▄▅▅▅▅▄▃▃▃▃▄▅▅▅▄▄▃▂▃▃▄▅▆▇▇▇▇▆▅▅▄▃▃▂▁▁▁▁▂▃▄▅▆▇▇▇▇▆▅▅▄▃▃▂▂▁▁▂▃▃▄▅▅▆▆▇▆▆▅▅
302
+ ▄▄▅▅▅▄▃▃▂▃▄▄▅▅▄▃▃▂▃▃▄▅▆▇▇▇▇▇▆▅▅▄▄▃▂▁▁▁▂▃▄▅▆▇▇▇▇▇▆▅▅▄▄▃▂▂▂▃▃▄▅▅▆▆▇▆▆▅▄▄
303
+ ▃▄▄▅▄▄▃▂▂▃▃▄▄▄▄▃▃▂▃▃▄▅▆▇███▇▇▆▆▆▅▄▃▂▁▂▂▃▄▄▅▆▇▇▇▇▆▆▅▅▄▃▃▃▃▃▄▅▆▆▇▇▇▆▅▄▃▂
304
+ ▂▃▄▄▄▄▃▃▃▃▃▄▄▄▃▃▃▃▃▄▅▆▇▇█████▇▇▇▆▅▄▃▃▂▃▃▄▄▅▆▇▇▇▆▆▅▅▅▄▃▃▃▃▄▅▅▆▇▇▇▇▆▅▃▂▁
305
+ ▂▃▃▄▄▄▄▃▃▃▃▄▄▃▃▃▃▃▄▄▅▆▇████████▇▇▆▆▅▄▄▄▄▄▅▅▅▆▆▆▆▅▅▄▄▄▃▃▃▃▄▅▆▆▇▇▇▇▆▄▂▁▁
306
+ ▂▂▃▄▅▅▅▄▄▄▄▄▃▃▃▃▃▃▄▅▆▆▇██████████▇▇▆▆▅▅▅▅▅▅▅▅▅▅▄▄▄▄▃▃▃▃▃▃▄▅▆▆▇▇▇▆▅▃▂▁
307
+ ▂▂▃▅▅▆▆▆▅▅▄▄▃▃▂▂▃▃▄▅▆▇▇▇██████████▇▇▇▆▆▅▅▅▄▄▄▃▃▃▃▃▃▃▃▂▂▂▃▃▄▅▆▇▇▇▆▅▃▂▁
308
+ ▂▃▄▅▆▇▇▆▆▅▅▄▃▂▂▂▂▃▄▅▆▆▇▇▇▇▇▇▇▇▇▇▇██▇▇▇▆▆▅▅▄▃▃▂▂▂▂▂▃▃▂▂▂▂▂▃▃▄▅▆▇▇▆▅▃▂▁▁
309
+ ▃▄▅▆▇▇▇▇▆▅▅▄▃▂▁▁▂▃▄▅▅▆▆▇▇▇▆▆▆▆▆▆▇▇▇▇▇▇▆▆▅▄▃▃▂▂▂▂▂▂▃▃▂▂▂▂▂▂▃▄▅▆▆▆▆▅▄▃▂▂
310
+ ▃▄▅▆▇▇▇▇▆▅▄▃▂▂▁▁▁▂▃▄▅▅▆▆▆▆▅▅▅▅▅▅▆▇▇▇▇▇▆▅▅▄▃▂▂▂▂▂▃▃▃▃▃▃▂▂▂▂▂▃▄▅▆▆▆▅▅▄▃▃
311
+ ▄▅▆▇▇█▇▇▆▅▄▃▂▁▁▁▁▁▂▃▄▅▅▅▅▅▄▄▄▄▄▄▅▆▆▇▇▆▆▅▄▃▂▂▂▂▂▃▃▄▄▄▄▃▃▂▂▂▂▃▄▅▆▆▆▆▅▅▄▄
312
+ ▅▅▆▇██▇▇▆▅▄▃▂▁ ▁▂▃▃▄▄▅▅▄▄▃▃▃▃▄▄▅▆▆▆▆▅▄▃▃▂▂▁▂▂▃▄▅▅▅▅▄▃▂▂▂▂▃▄▅▆▆▆▆▆▅▅▅
313
+ ▅▆▇▇██▇▆▅▄▃▂▁▁ ▁▁▂▃▄▄▄▄▄▃▃▂▂▃▃▄▄▅▅▅▅▄▃▃▂▁▁▁▂▃▄▅▅▅▅▅▄▃▂▂▂▂▂▃▄▅▆▆▆▆▆▆▆
314
+ ▆▇▇███▇▆▅▃▂▂▁ ▁▁▂▃▄▄▄▄▄▃▃▃▂▃▃▃▄▄▄▄▄▃▂▂▁▁▁▁▁▂▃▅▅▅▅▅▄▃▂▁▁▁▂▃▃▄▅▆▇▇▇▇▇
315
+ ▇▇████▇▆▄▃▂▁▁ ▁▂▃▃▄▅▅▅▅▄▄▃▃▃▃▃▄▄▄▃▃▂▂▁▁ ▁▁▂▃▄▅▅▅▄▄▃▂▁▁▁▁▂▃▄▅▆▇▇███
316
+ ▇▇████▇▆▄▃▂▁▁ ▁▂▃▄▅▅▆▆▆▅▅▄▄▄▄▄▄▃▃▃▂▂▁▁ ▁▂▂▃▄▄▄▄▃▂▁▁▁▁▁▁▂▃▄▆▇▇███
317
+ ▇▇████▇▆▄▃▂▁▁ ▁▂▃▄▅▅▆▆▇▇▆▆▅▅▄▄▄▄▃▃▃▂▂▁▁▁ ▁▁▂▃▃▃▃▃▂▂▁▁▁▁▁▁▂▃▄▆▇▇███
318
+ ▆▇▇███▇▆▅▃▂▂▁ ▁▂▃▄▅▆▆▇▇▇▇▇▆▅▅▄▄▄▃▃▃▃▂▂▁▁▁▁▁▁▁▂▂▃▃▃▂▂▁▁▁▁▁▁▂▂▃▄▆▆▇▇▇▇
319
+ ▅▆▇▇██▇▆▅▄▃▂▁▁ ▁▁▂▃▄▅▆▆▇▇█▇▇▆▆▅▅▄▄▄▃▃▃▃▃▂▂▁▁▁▁▂▂▂▃▃▃▂▂▂▁▁▁▁▂▂▃▄▅▆▆▇▇▇▆
320
+ ▅▅▆▇██▇▇▆▅▄▃▂▁▁▁▁▂▃▄▅▅▆▇▇▇▇▇▆▅▅▄▄▃▃▄▄▄▄▄▃▃▂▂▂▂▂▃▃▃▃▃▃▃▂▂▂▂▂▃▃▄▄▅▆▆▆▆▆▅
321
+ ▄▅▆▇▇█▇▇▆▅▄▃▂▁▁▁▁▁▂▃▄▅▆▆▇▇▇▆▅▅▄▃▃▃▃▄▄▄▅▄▄▄▃▃▃▃▃▄▄▄▄▄▄▃▃▃▃▃▃▄▄▄▅▆▆▆▆▆▅▄
322
+ ▃▄▅▆▇▇▇▇▆▅▄▃▂▁▁▁▁▁▂▃▃▄▅▆▆▆▆▆▅▄▃▃▂▃▃▄▅▅▅▅▅▄▄▄▄▄▄▅▅▅▅▅▅▄▄▄▄▄▄▄▅▅▆▆▆▆▆▅▄▄
323
+ ▃▄▅▆▇▇▇▇▇▆▅▄▃▂▁▁▁▁▂▂▃▄▄▅▆▆▅▅▄▃▃▂▂▂▃▄▅▆▆▆▆▆▅▅▅▅▅▆▆▆▆▆▆▆▅▅▅▅▅▅▆▆▇▇▇▆▆▅▄▃
324
+ ▃▄▄▆▇▇▇▇▇▆▅▄▃▂▁▁▁▁▂▃▃▄▄▅▅▅▄▄▃▃▂▂▂▃▄▅▆▇▇▇▇▇▆▆▆▆▇▇▇▇▇▇▇▇▆▆▅▅▆▆▆▇▇▇▇▇▆▅▄▃
325
+ ▃▃▄▅▆▇▇▇▇▆▅▄▃▂▂▁▂▂▃▃▃▄▄▄▄▄▄▃▃▃▂▂▃▄▅▆▇████▇▇▇▇▇▇██████▇▇▆▆▆▆▆▇▇███▇▇▆▅▄
326
+ ▃▄▄▅▆▆▇▇▆▆▅▄▃▂▂▂▃▃▄▄▄▄▄▄▃▃▃▃▃▃▃▃▄▅▆▇▇█████▇▇▇▇███████▇▇▆▆▆▆▆▇▇████▇▆▅▅
327
+ ▄▄▄▄▅▆▆▆▆▆▅▄▃▂▂▃▃▄▅▅▅▄▄▃▃▂▂▂▂▃▃▄▅▆▇▇█████▇▇▇▇▇▇█████▇▇▆▆▅▅▅▆▇▇████▇▇▆▅
328
+ ▄▄▄▄▄▅▆▆▆▅▄▃▃▃▃▃▄▅▅▅▅▅▄▃▂▂▂▂▂▃▄▅▆▆▇███▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▆▅▄▄▄▄▅▆▇▇███▇▇▆▆
329
+ ▄▄▃▄▄▅▅▆▆▅▄▃▃▂▃▄▄▅▆▆▅▄▃▂▂▁▁▂▂▃▄▅▆▇▇▇▇▇▇▆▆▆▆▆▆▆▆▆▆▆▆▆▆▅▄▃▃▃▃▄▅▆▇▇▇▇▇▇▆▆
330
+ ▄▄▃▃▄▄▅▅▅▅▄▃▂▂▃▃▄▅▅▅▅▄▃▂▁▁▁▁▂▃▄▅▆▇▇▇▇▇▆▅▅▅▅▄▄▅▅▅▅▅▅▅▄▄▃▂▂▂▃▃▄▅▆▇▇▇▇▆▆▅
331
+ ▄▃▃▃▃▄▅▅▅▅▄▃▂▂▃▃▄▅▅▅▄▃▂▁▁▁▁▁▂▃▄▅▆▇▇▇▆▆▅▄▄▄▃▃▃▃▄▄▄▄▄▄▃▃▂▂▁▂▂▃▄▅▆▆▇▇▆▆▅▄
332
+ ▄▃▂▃▃▄▅▅▆▅▄▃▃▂▂▃▃▄▄▄▃▂▂▁ ▁▂▃▄▅▆▆▆▆▆▅▄▃▃▃▃▂▂▂▃▃▃▃▃▃▂▂▁▁▁▁▂▃▄▅▅▆▆▆▅▅▄▃
333
+ ▃▃▂▃▃▄▅▆▆▅▅▄▃▃▃▃▃▃▃▃▂▂▁ ▁▂▃▃▄▅▆▆▆▅▄▄▃▃▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▂▃▄▅▅▆▅▄▄▃▂
334
+ ▄▃▂▃▃▄▅▆▆▆▅▄▄▃▃▃▃▃▂▂▁▁ ▁▂▃▃▄▅▅▅▅▅▄▃▃▃▂▂▂▁▁▁▁▁▁▁▁▁▁ ▁▁▂▂▃▄▅▅▄▃▂▂▁
335
+ ▄▃▃▃▄▅▆▆▇▇▆▅▅▄▄▃▃▂▂▁▁▁ ▁▁▂▃▃▄▄▅▅▅▅▄▄▃▃▃▂▁▁▁ ▁▁▁▁▁ ▁▁▂▃▃▄▄▄▃▂▁▁
336
+ ▄▄▃▃▄▅▆▇▇▇▆▆▅▅▄▄▃▂▂▁▁ ▁▁▂▃▃▄▄▄▄▄▅▅▅▄▄▄▃▃▂▁▁ ▁▁▁▁▁ ▁▁▂▂▃▄▄▃▃▂▁
337
+ ▅▄▄▄▄▅▆▆▇▇▇▆▆▅▅▄▃▃▂▁▁▁ ▁▂▂▃▄▄▄▃▃▃▄▄▅▅▅▅▄▄▃▂▁▁ ▁▁▁▁▁▁▁▁▁▁▁▂▂▃▄▄▄▃▂▁▁
338
+ ▅▄▄▄▄▄▅▆▇▇▆▆▆▆▅▅▄▃▃▂▁▁▁▁▂▃▄▄▅▅▄▃▃▃▃▄▅▅▆▅▅▄▄▂▁▁ ▁▁▂▂▂▂▂▂▁▁▁▁▂▃▄▄▅▄▄▃▂▁
339
+ ▅▄▄▃▃▄▅▅▆▆▆▆▆▅▅▅▅▄▄▃▂▂▂▂▃▄▅▅▅▅▄▃▃▃▃▄▅▅▆▆▅▅▄▂▂▁▁▁▁▂▂▃▃▃▃▂▂▂▂▂▃▃▄▅▅▅▅▄▃▂
340
+ ▅▄▃▃▃▃▄▄▅▅▅▅▅▅▅▅▅▅▄▄▃▃▂▃▄▄▅▆▆▅▄▃▃▂▃▃▄▅▅▅▅▄▃▂▁▁▁▁▂▃▃▄▄▄▄▃▃▂▂▃▃▄▅▆▆▆▆▅▄▄
341
+ ▄▃▃▂▂▂▃▄▄▄▄▄▄▄▅▅▅▅▅▅▄▃▃▄▄▅▅▆▆▅▄▃▂▂▂▃▄▄▅▄▄▃▃▂▁▁▁▂▂▃▄▅▅▅▅▄▃▃▃▃▄▅▆▆▇▇▇▆▅▅
342
+ ▃▃▂▂▂▂▂▃▃▃▃▃▃▄▄▅▆▆▆▅▅▄▄▄▅▅▆▆▆▅▄▃▂▂▂▂▃▄▄▄▃▃▂▁▁▁▁▂▃▄▅▅▆▆▅▅▄▄▄▄▅▅▆▇▇▇▇▇▆▅
343
+ ▃▂▂▁▁▁▁▂▂▂▂▂▂▃▄▅▆▆▇▆▆▅▅▅▅▆▆▆▅▅▄▃▂▂▂▂▃▃▃▃▃▂▂▁▁▁▂▂▃▄▅▆▆▆▆▅▅▄▄▅▅▆▇▇███▇▇▆
344
+ ▃▂▂▁▁▁▁▁▁▁▁▁▁▂▃▅▆▇▇▇▇▆▆▆▆▆▆▆▅▅▄▃▂▂▂▂▃▃▃▃▃▂▂▁▁▂▂▃▄▅▆▆▆▆▆▅▅▅▅▆▆▇▇██████▇
345
+ ▃▂▂▁▁▁▁▁▁ ▁▂▄▆▇██▇▇▇▇▇▇▇▆▅▄▃▃▂▂▂▂▃▄▄▄▃▃▂▂▂▃▃▄▅▆▆▆▆▆▅▅▅▅▅▆▇▇████████
346
+ ▄▃▂▁▁▁▁ ▁▂▄▆▇████▇▇▇▇▇▆▅▄▃▂▂▂▂▃▃▄▅▄▄▃▃▃▃▄▄▅▆▆▆▆▅▅▅▄▄▅▅▆▇▇████████
347
+ ▄▃▂▂▁▁▁▁▁▁ ▁▂▃▅▇▇██▇▇██▇▇▆▆▄▃▃▂▂▂▃▄▅▅▅▅▄▄▄▄▅▅▆▆▆▆▅▅▄▃▃▄▄▅▆▇▇████████
348
+ ▄▄▃▂▂▁▁▁▁▁▁▁▁▁▂▃▅▆▇▇▇▇▇▇▇▇▇▆▆▅▄▃▂▂▂▃▄▅▆▆▅▅▄▄▅▅▆▆▆▆▅▄▄▃▂▂▂▃▄▅▆▇▇███▇▇▇▇
349
+ ▅▄▃▂▂▂▂▂▂▂▂▂▁▂▂▃▄▅▆▆▆▆▆▇▇▇▇▆▆▅▄▃▂▂▃▃▄▅▆▆▅▅▄▅▅▆▆▆▆▅▅▄▃▂▁▁▂▂▄▅▅▆▇▇▇▇▆▆▆▆
350
+ ▄▄▃▂▂▃▃▃▄▃▃▃▂▂▂▃▃▄▅▅▅▅▆▆▇▇▇▆▆▅▄▃▂▂▃▃▄▅▅▅▅▄▄▄▅▅▆▆▆▅▄▃▂▁▁▁▁▂▃▄▅▅▆▆▆▆▅▅▅▅
351
+ ▄▃▃▂▂▃▃▄▄▄▄▄▃▃▃▃▃▃▄▄▄▄▅▅▆▇▇▆▆▅▄▃▂▂▂▃▄▄▅▅▄▃▃▄▄▅▆▆▆▅▄▃▂▁ ▁▁▂▃▄▅▅▆▅▅▅▄▄▄
352
+ ```
353
+
354
+ ### Noise synthesis
355
+
356
+ Noise looks much more interesting when combined.
357
+
358
+ ```ruby
359
+ noises = Perlin::Noise.new(2)
360
+ contrast = Perlin::Curve.contrast(Perlin::Curve::QUINTIC, 3)
361
+
362
+ (0..100).each do |x|
363
+ n = 0
364
+ [[0.02, 10], [0.04, 10], [0.1, 20], [0.2, 15]].each_with_index do |step_scale, idx|
365
+ step, scale = step_scale
366
+ n += contrast.call( noises[idx, x * step] ) * scale
367
+ end
368
+ puts '=' * n.floor
369
+ end
370
+ ```
371
+
372
+ ```
373
+ ================================
374
+ =========================================
375
+ ===============================================
376
+ ===============================================
377
+ ========================================
378
+ ===========================
379
+ ===================
380
+ =====================
381
+ ========================
382
+ ===========================
383
+ ============================
384
+ =============================
385
+ ==============================
386
+ ==============================
387
+ ==============================
388
+ ===========================
389
+ =======================
390
+ ======================
391
+ ======================
392
+ ========================
393
+ ==========================
394
+ ============================
395
+ ===============================
396
+ =================================
397
+ ==================================
398
+ =================================
399
+ ================================
400
+ =================================
401
+ ==================================
402
+ =====================================
403
+ ======================================
404
+ =========================================
405
+ ================================================
406
+ =========================================================
407
+ ===========================================================
408
+ =====================================================
409
+ ==============================================
410
+ ===============================================
411
+ =====================================================
412
+ =================================================
413
+ =================================
414
+ ==================
415
+ =============
416
+ =============
417
+ ====================
418
+ ============================
419
+ =====================================
420
+ ==============================================
421
+ ================================================
422
+ =============================================
423
+ ================================
424
+ ==================
425
+ ============
426
+ ===========
427
+ ===========
428
+ ==================
429
+ =========================
430
+ ==========================
431
+ ===========================
432
+ ================================
433
+ ================================
434
+ ==================================
435
+ =========================================
436
+ ==================================================
437
+ ====================================================
438
+ ===============================================
439
+ =========================================
440
+ ==========================================
441
+ ==============================================
442
+ ============================================
443
+ ===============================
444
+ ================
445
+ ==========
446
+ ========
447
+ ==========
448
+ =============
449
+ ===================
450
+ ==========================
451
+ ===============================
452
+ ================================
453
+ =========================
454
+ ================
455
+ ===========
456
+ =======
457
+ ======
458
+ =============
459
+ ====================
460
+ ======================
461
+ ========================
462
+ =============================
463
+ ===============================
464
+ ==================================
465
+ =======================================
466
+ ========================================
467
+ =========================================
468
+ ================================================
469
+ ======================================================
470
+ ======================================================
471
+ ===============================================
472
+ ======================================
473
+ ================================
474
+ ```
475
+
476
+
477
+ ## References
478
+ - Texturing & modeling: a procedural approach by David S. Ebert et al.
479
+ - Improving Noise by Ken Perlin (http://mrl.nyu.edu/~perlin/paper445.pdf)
480
+ - http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html#algorithm
481
+ - http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
482
+ - http://burtleburtle.net/bob/rand/unitvec.html
483
+ - http://briansharpe.wordpress.com/2011/11/14/two-useful-interpolation-functions-for-noise-development/
484
+ - http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html
485
+ - http://www.java-gaming.org/index.php?topic=22796.0
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib'
6
+ t.pattern = 'test/**/test_*.rb'
7
+ t.verbose = true
8
+ end
9
+
@@ -0,0 +1,21 @@
1
+ module Perlin
2
+ module Curve
3
+ LINEAR = proc { |t| t }
4
+ CUBIC = proc { |t| 3 * (t ** 2) - 2 * (t ** 3) }
5
+ QUINTIC = proc { |t| 6 * (t ** 5) - 15 * (t ** 4) + 10 * (t ** 3) }
6
+
7
+ # Returns a Proc object which applies S-curve function to
8
+ # a given number between 0 and 1.
9
+ # @param[Proc] curve
10
+ # @param[Fixnum] times
11
+ # @return[Proc]
12
+ def self.contrast curve, times
13
+ lambda { |n|
14
+ times.times do
15
+ n = curve.call n
16
+ end
17
+ n
18
+ }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module Perlin
2
+ class GradientTable
3
+ # Bit-wise AND operation is not any faster than MOD in Ruby
4
+ # MOD operation returns positive number for negative input
5
+ def initialize dim, interval = 256
6
+ @dim = dim
7
+ @interval = interval
8
+
9
+ @table = Array.new(interval) { rand @interval }
10
+ @vectors = Array.new(interval) { random_unit_vector }
11
+ end
12
+
13
+ def [] *coords
14
+ @vectors[index *coords]
15
+ end
16
+
17
+ private
18
+ # A simple hashing
19
+ def index *coords
20
+ s = coords.last
21
+ coords.reverse[1..-1].each do |c|
22
+ s = perm(s) + c
23
+ end
24
+ perm(s)
25
+ end
26
+
27
+ def perm s
28
+ @table[s % @interval]
29
+ end
30
+
31
+ def random_unit_vector
32
+ while true
33
+ v = Vector[*Array.new(@dim) { rand * 2 - 1 }]
34
+ # Discards vectors whose length greater than 1 to avoid bias in distribution
35
+ break if v.r > 0 && v.r <= 1
36
+ end
37
+ r = v.r
38
+ v.map { |e| e / v.r }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,81 @@
1
+ module Perlin
2
+ class Noise
3
+ DEFAULT_OPTIONS = {
4
+ :interval => 256,
5
+ :curve => Perlin::Curve::QUINTIC,
6
+ :contrast => proc { }
7
+ }
8
+
9
+ def initialize dim, options = {}
10
+ options = DEFAULT_OPTIONS.merge options
11
+
12
+ @dim = dim
13
+ @interval = options.fetch(:interval)
14
+ @curve = options.fetch(:curve)
15
+
16
+ raise ArgumentError.new("Invalid dimension: must be a positive integer") unless @dim.is_a?(Fixnum) && @dim > 0
17
+ raise ArgumentError.new("Invalid interval: must be a positive integer") unless @interval.is_a?(Fixnum) && @interval > 0
18
+ raise ArgumentError.new("Invalid curve specified: must be a Proc object") unless @curve.is_a?(Proc)
19
+
20
+ # Generate pseudo-random gradient vector for each grid point
21
+ @gradient_table = Perlin::GradientTable.new @dim, @interval
22
+ end
23
+
24
+ # @param [*coords] Coordinates
25
+ # @return [Float] Noise value between (-1..1)
26
+ def [] *coords
27
+ raise ArgumentError.new("Invalid coordinates") unless coords.length == @dim
28
+
29
+ coords = Vector[*coords]
30
+ cell = Vector[*coords.map(&:to_i)]
31
+ diff = coords - cell
32
+
33
+ # Calculate noise factor at each surrouning vertex
34
+ nf = {}
35
+ iterate @dim, 2 do |idx|
36
+ idx = Vector[*idx]
37
+
38
+ # "The value of each gradient ramp is computed by means of a scalar
39
+ # product (dot product) between the gradient vectors of each grid point
40
+ # and the vectors from the grid points."
41
+ gv = @gradient_table[ * (cell + idx).to_a ]
42
+ nf[idx.to_a] = gv.inner_product(diff - idx)
43
+ end
44
+
45
+ dim = @dim
46
+ diff.to_a.each do |u|
47
+ bu = @curve.call u
48
+
49
+ # Pair-wise interpolation, trimming down dimensions
50
+ iterate dim, 2 do |idx1|
51
+ next if idx1.first == 1
52
+
53
+ idx2 = idx1.dup
54
+ idx2[0] = 1
55
+ idx3 = idx1[1..-1]
56
+
57
+ nf[idx3] = nf[idx1] + bu * (nf[idx2] - nf[idx1])
58
+ end
59
+ dim -= 1
60
+ end
61
+ (nf[[]] + 1) * 0.5
62
+ end
63
+
64
+ private
65
+ def iterate dim, length, &block
66
+ iterate_recursive dim, length, Array.new(dim, 0), &block
67
+ end
68
+
69
+ def iterate_recursive dim, length, idx, &block
70
+ length.times do |i|
71
+ idx[dim - 1] = i
72
+ if dim == 1
73
+ yield idx
74
+ else
75
+ iterate_recursive dim - 1, length, idx, &block
76
+ end
77
+ end
78
+ end
79
+ end#Noise
80
+ end#Perlin
81
+
@@ -0,0 +1,3 @@
1
+ module Perlin
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'matrix'
3
+ require 'perlin/version'
4
+ require 'perlin/curve'
5
+ require 'perlin/gradient_table'
6
+ require 'perlin/noise'
7
+
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "perlin/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "perlin_noise"
7
+ s.version = Perlin::VERSION
8
+ s.authors = ["Junegunn Choi"]
9
+ s.email = ["junegunn.c@gmail.com"]
10
+ s.homepage = "https://github.com/junegunn/perlin_noise"
11
+ s.summary = %q{Perlin noise generator}
12
+ s.description = %q{Perlin noise implemented in Ruby}
13
+
14
+ s.rubyforge_project = "perlin"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,155 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ require 'perlin_noise'
7
+ require 'benchmark'
8
+
9
+ # TODO
10
+ class PerlinTest < Test::Unit::TestCase
11
+ def test_gradient_table
12
+ [10, 100, 1000].each do |interval|
13
+
14
+ gt = Perlin::GradientTable.new 1, interval
15
+
16
+ interval.times do |i|
17
+ assert (0.99..1.01).include?(gt[interval + i].r)
18
+ end
19
+
20
+ assert_equal gt[1], gt[1 + interval]
21
+ assert_equal gt[1], gt[1 + interval * 2]
22
+
23
+ gt = Perlin::GradientTable.new 2, interval
24
+ assert_equal gt[1, 1], gt[1, 1 + interval]
25
+ assert_equal gt[1, 1], gt[1, 1 + interval * 2]
26
+
27
+ gt = Perlin::GradientTable.new 4, interval
28
+ assert_equal gt[1, 2, 3, 4], gt[1, 2, 3 + interval, 4]
29
+ assert_equal gt[1, 2, 3, 4], gt[1, 2, 3 + interval * 2, 4]
30
+
31
+ interval.times do |i|
32
+ # FIXME: rand
33
+ assert (0.99..1.01).include?(gt[rand(interval), rand(interval), rand(interval), interval + i].r)
34
+ end
35
+ end
36
+
37
+ # FIXME: Just checking. Two-fold slower than default Ruby hash
38
+ gt = Perlin::GradientTable.new 3
39
+ puts Benchmark.measure {
40
+ 300000.times do |i|
41
+ gt[i * 0.01, i * 0.02, i * 0.03]
42
+ end
43
+ }
44
+ end
45
+
46
+ def test_curve
47
+ curves = [ Perlin::Curve::LINEAR, Perlin::Curve::CUBIC, Perlin::Curve::QUINTIC ]
48
+
49
+ curves.each_with_index do |c, idx|
50
+ 0.step(1, 0.01).each do |x|
51
+ case idx
52
+ when 0
53
+ assert_equal x, c.call(x)
54
+ else
55
+ if x == 1 || x == 0
56
+ assert_equal x, c.call(x)
57
+ elsif x > 0.5
58
+ assert c.call(x) > x
59
+ elsif x == 0.5
60
+ assert_equal x, c.call(x)
61
+ else
62
+ assert c.call(x) < x
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def test_noise_invalid_params
70
+ # Dimension
71
+ assert_raise(ArgumentError) { Perlin::Noise.new 0 }
72
+ assert_raise(ArgumentError) { Perlin::Noise.new 0.1 }
73
+ assert_raise(ArgumentError) { Perlin::Noise.new -1 }
74
+ assert_raise(ArgumentError) { Perlin::Noise.new -0.1 }
75
+
76
+ # Interval
77
+ Perlin::Noise.new 1
78
+ Perlin::Noise.new 1, :inteval => 100
79
+ assert_raise(ArgumentError) { Perlin::Noise.new 1, :interval => 0.5 }
80
+ assert_raise(ArgumentError) { Perlin::Noise.new 1, :interval => -1 }
81
+
82
+ # Curve
83
+ Perlin::Noise.new 2, :curve => Perlin::Curve::CUBIC
84
+ assert_raise(ArgumentError) { Perlin::Noise.new 2, :curve => nil }
85
+ end
86
+
87
+ def test_noise_1d
88
+ width = 60
89
+
90
+ noise = Perlin::Noise.new 1, :interval => 200
91
+ 0.step(300, 0.1).each do |x|
92
+ n = noise[x]
93
+ len = (n * width).to_i
94
+ puts '#' * len
95
+ assert (0..width).include?(len)
96
+
97
+ if x.to_i == x
98
+ assert_equal 0.5, noise[x]
99
+ end
100
+ end
101
+ end
102
+
103
+ def test_noise_range
104
+ (1..7).each do |dim|
105
+ noise = Perlin::Noise.new dim
106
+ max = -999
107
+ min = 999
108
+
109
+ (0..100).each do |i|
110
+ coords = Array.new(dim) { |j| i * (j + 1) * 0.001 }
111
+ n = noise[*coords]
112
+
113
+ assert (0..1).include?(n)
114
+
115
+ max = n if n > max
116
+ min = n if n < min
117
+ end
118
+ end
119
+ end
120
+
121
+
122
+ def test_noise_2d
123
+ noises = Perlin::Noise.new(2)
124
+ contrast = Perlin::Curve.contrast(Perlin::Curve::CUBIC, 2)
125
+
126
+ bars = " ▁▂▃▄▅▆▇█".each_char.to_a
127
+ bar = lambda { |n|
128
+ bars[ (bars.length * n).floor ]
129
+ }
130
+
131
+ 0.upto(100) do |i|
132
+ 70.times do |y|
133
+ n = noises[i * 0.1, y * 0.1]
134
+ n = contrast.call n
135
+
136
+ print bar.call(n)
137
+ end
138
+ puts
139
+ end
140
+ end
141
+
142
+ def test_synthesis
143
+ noises = Perlin::Noise.new(2)
144
+ contrast = Perlin::Curve.contrast(Perlin::Curve::QUINTIC, 3)
145
+
146
+ (0..100).each do |x|
147
+ n = 0
148
+ [[0.02, 10], [0.04, 10], [0.1, 30], [0.2, 15]].each_with_index do |step_scale, idx|
149
+ step, scale = step_scale
150
+ n += contrast.call( noises[idx, x * step] ) * scale
151
+ end
152
+ puts '=' * n.floor
153
+ end
154
+ end
155
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perlin_noise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Junegunn Choi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-16 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Perlin noise implemented in Ruby
15
+ email:
16
+ - junegunn.c@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - README.markdown
24
+ - Rakefile
25
+ - lib/perlin/curve.rb
26
+ - lib/perlin/gradient_table.rb
27
+ - lib/perlin/noise.rb
28
+ - lib/perlin/version.rb
29
+ - lib/perlin_noise.rb
30
+ - perlin_noise.gemspec
31
+ - test/test_perlin.rb
32
+ homepage: https://github.com/junegunn/perlin_noise
33
+ licenses: []
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project: perlin
52
+ rubygems_version: 1.8.10
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Perlin noise generator
56
+ test_files:
57
+ - test/test_perlin.rb
58
+ has_rdoc: