perlin_noise 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.markdown +485 -0
- data/Rakefile +9 -0
- data/lib/perlin/curve.rb +21 -0
- data/lib/perlin/gradient_table.rb +41 -0
- data/lib/perlin/noise.rb +81 -0
- data/lib/perlin/version.rb +3 -0
- data/lib/perlin_noise.rb +7 -0
- data/perlin_noise.gemspec +24 -0
- data/test/test_perlin.rb +155 -0
- metadata +58 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
data/lib/perlin/curve.rb
ADDED
@@ -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
|
data/lib/perlin/noise.rb
ADDED
@@ -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
|
+
|
data/lib/perlin_noise.rb
ADDED
@@ -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
|
data/test/test_perlin.rb
ADDED
@@ -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:
|