perlin_noise 0.1.0

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/.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: