perlin_noise 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,4 +1,4 @@
1
- # perlin
1
+ # perlin_noise
2
2
  Ruby-implementation of N-dimension Perlin noise.
3
3
 
4
4
  ## Installation
@@ -37,7 +37,7 @@ n5d[rand, rand, rand, rand, rand]
37
37
  ```
38
38
 
39
39
  ## Options
40
- ### :interval
40
+ ### `:interval`
41
41
  A gradient noise repeats itself at certain interval. (Default interval is 256)
42
42
  You can change the interval of the noise generator but keep in mind that
43
43
  longer interval requires more pseudo-random gradient vectors to be maintained in memory.
@@ -48,6 +48,15 @@ n3d[0.1, 0.2, 0.3]
48
48
  n3d[0.1, 0.2, 100.3]
49
49
  ```
50
50
 
51
+ ### `:seed`
52
+
53
+ You can optionally specify a seed value for the random number generator.
54
+ (Caveat: seed value is set globally in Ruby 1.8)
55
+
56
+ ```ruby
57
+ noises = Perlin::Noise.new 1, :seed => 12345
58
+ ```
59
+
51
60
  ## Range of noise function
52
61
  While the original algorithm outputs a number between -1.0 and 1.0,
53
62
  Perlin::Noise#[] manipulates this output and returns a number between 0.0 and 1.0 for ease of use.
@@ -58,7 +67,8 @@ Even though the range of the noise function is from 0 to 1,
58
67
  you'll rarely see a noise value close to either end,
59
68
  as most of the values are distributed around the center.
60
69
  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.
70
+ one or more times to push away those "grey" values to either end,
71
+ achiving more contrasted output.
62
72
 
63
73
  ```ruby
64
74
  noise = Perlin::Noise.new 1
@@ -70,7 +80,8 @@ n = noise[0.1]
70
80
  end
71
81
  ```
72
82
 
73
- There's a shortcut for this process.
83
+ There's a shortcut for this specific process.
84
+
74
85
  ```ruby
75
86
  contrast = Perlin::Curve.contrast(Perlin::Curve::CUBIC, 3)
76
87
  n = contrast.call n
@@ -83,9 +94,7 @@ n = contrast.call n
83
94
  ```ruby
84
95
  noise = Perlin::Noise.new 1, :interval => 200
85
96
  0.step(300, 0.1).each do |x|
86
- n = noise[x]
87
- len = (n * 60).to_i
88
- puts '#' * len
97
+ puts '#' * (noise[x] * 60).floor
89
98
  end
90
99
  ```
91
100
 
@@ -237,7 +246,7 @@ bar = lambda { |n|
237
246
  bars[ (bars.length * n).floor ]
238
247
  }
239
248
 
240
- 0.upto(100) do |i|
249
+ 100.times do |i|
241
250
  70.times do |y|
242
251
  n = noises[i * 0.1, y * 0.1]
243
252
  n = contrast.call n
@@ -359,7 +368,7 @@ Noise looks much more interesting when combined.
359
368
  noises = Perlin::Noise.new(2)
360
369
  contrast = Perlin::Curve.contrast(Perlin::Curve::QUINTIC, 3)
361
370
 
362
- (0..100).each do |x|
371
+ 100.times do |x|
363
372
  n = 0
364
373
  [[0.02, 10], [0.04, 10], [0.1, 20], [0.2, 15]].each_with_index do |step_scale, idx|
365
374
  step, scale = step_scale
@@ -474,6 +483,10 @@ end
474
483
  ```
475
484
 
476
485
 
486
+ ## Contributors
487
+
488
+ - [Matthew Johnston](https://github.com/warmwaffles)
489
+
477
490
  ## References
478
491
  - Texturing & modeling: a procedural approach by David S. Ebert et al.
479
492
  - Improving Noise by Ken Perlin (http://mrl.nyu.edu/~perlin/paper445.pdf)
@@ -1,12 +1,28 @@
1
1
  module Perlin
2
+ if RUBY_VERSION =~ /^1\.8\./
3
+ class Random
4
+ def initialize *seed
5
+ # FIXME: Sets the global seed value; this is misleading
6
+ srand *seed
7
+ end
8
+
9
+ def rand *interval
10
+ Kernel.rand *interval
11
+ end
12
+ end
13
+ else
14
+ Random = ::Random
15
+ end
16
+
2
17
  class GradientTable
3
18
  # Bit-wise AND operation is not any faster than MOD in Ruby
4
19
  # MOD operation returns positive number for negative input
5
- def initialize dim, interval = 256
20
+ def initialize dim, interval = 256, seed = nil
6
21
  @dim = dim
7
22
  @interval = interval
23
+ @random = Random.new(*[seed].compact)
8
24
 
9
- @table = Array.new(interval) { rand @interval }
25
+ @table = Array.new(interval) { @random.rand @interval }
10
26
  @vectors = Array.new(interval) { random_unit_vector }
11
27
  end
12
28
 
@@ -30,7 +46,7 @@ module Perlin
30
46
 
31
47
  def random_unit_vector
32
48
  while true
33
- v = Vector[*Array.new(@dim) { rand * 2 - 1 }]
49
+ v = Vector[*Array.new(@dim) { @random.rand * 2 - 1 }]
34
50
  # Discards vectors whose length greater than 1 to avoid bias in distribution
35
51
  break if v.r > 0 && v.r <= 1
36
52
  end
data/lib/perlin/noise.rb CHANGED
@@ -3,7 +3,7 @@ module Perlin
3
3
  DEFAULT_OPTIONS = {
4
4
  :interval => 256,
5
5
  :curve => Perlin::Curve::QUINTIC,
6
- :contrast => proc { }
6
+ :seed => nil
7
7
  }
8
8
 
9
9
  def initialize dim, options = {}
@@ -12,13 +12,15 @@ module Perlin
12
12
  @dim = dim
13
13
  @interval = options.fetch(:interval)
14
14
  @curve = options.fetch(:curve)
15
+ @seed = options.fetch(:seed)
15
16
 
16
17
  raise ArgumentError.new("Invalid dimension: must be a positive integer") unless @dim.is_a?(Fixnum) && @dim > 0
17
18
  raise ArgumentError.new("Invalid interval: must be a positive integer") unless @interval.is_a?(Fixnum) && @interval > 0
18
19
  raise ArgumentError.new("Invalid curve specified: must be a Proc object") unless @curve.is_a?(Proc)
20
+ raise ArgumentError.new("Invalid seed: must be a number") unless @seed.nil? || @seed.is_a?(Numeric)
19
21
 
20
22
  # Generate pseudo-random gradient vector for each grid point
21
- @gradient_table = Perlin::GradientTable.new @dim, @interval
23
+ @gradient_table = Perlin::GradientTable.new @dim, @interval, @seed
22
24
  end
23
25
 
24
26
  # @param [*coords] Coordinates
@@ -30,7 +32,7 @@ module Perlin
30
32
  cell = Vector[*coords.map(&:to_i)]
31
33
  diff = coords - cell
32
34
 
33
- # Calculate noise factor at each surrouning vertex
35
+ # Calculate noise factor at each surrouning vertex
34
36
  nf = {}
35
37
  iterate @dim, 2 do |idx|
36
38
  idx = Vector[*idx]
@@ -39,7 +41,7 @@ module Perlin
39
41
  # product (dot product) between the gradient vectors of each grid point
40
42
  # and the vectors from the grid points."
41
43
  gv = @gradient_table[ * (cell + idx).to_a ]
42
- nf[idx.to_a] = gv.inner_product(diff - idx)
44
+ nf[idx.to_a] = gv.inner_product(diff - idx)
43
45
  end
44
46
 
45
47
  dim = @dim
@@ -1,3 +1,3 @@
1
1
  module Perlin
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
data/test/test_perlin.rb CHANGED
@@ -79,6 +79,12 @@ class PerlinTest < Test::Unit::TestCase
79
79
  assert_raise(ArgumentError) { Perlin::Noise.new 1, :interval => 0.5 }
80
80
  assert_raise(ArgumentError) { Perlin::Noise.new 1, :interval => -1 }
81
81
 
82
+ # Seed
83
+ Perlin::Noise.new 1, :seed => 1
84
+ Perlin::Noise.new 1, :seed => 0.1
85
+ Perlin::Noise.new 1, :seed => -0.1
86
+ assert_raise(ArgumentError) { Perlin::Noise.new 1, :seed => "seed" }
87
+
82
88
  # Curve
83
89
  Perlin::Noise.new 2, :curve => Perlin::Curve::CUBIC
84
90
  assert_raise(ArgumentError) { Perlin::Noise.new 2, :curve => nil }
@@ -128,7 +134,7 @@ class PerlinTest < Test::Unit::TestCase
128
134
  bars[ (bars.length * n).floor ]
129
135
  }
130
136
 
131
- 0.upto(100) do |i|
137
+ 100.times do |i|
132
138
  70.times do |y|
133
139
  n = noises[i * 0.1, y * 0.1]
134
140
  n = contrast.call n
@@ -139,11 +145,22 @@ class PerlinTest < Test::Unit::TestCase
139
145
  end
140
146
  end
141
147
 
148
+ def test_seed
149
+ noise1 = Perlin::Noise.new(1, :seed => 12345)
150
+ noise2 = Perlin::Noise.new(1, :seed => 12345)
151
+ assert_equal 0.step(1, 0.01).map { |v| noise1[v] },
152
+ 0.step(1, 0.01).map { |v| noise2[v] }
153
+
154
+ noise3 = Perlin::Noise.new(1, :seed => 54321)
155
+ assert_not_equal 0.step(1, 0.01).map { |v| noise1[v] },
156
+ 0.step(1, 0.01).map { |v| noise3[v] }
157
+ end
158
+
142
159
  def test_synthesis
143
- noises = Perlin::Noise.new(2)
160
+ noises = Perlin::Noise.new(2, :seed => 0.12345)
144
161
  contrast = Perlin::Curve.contrast(Perlin::Curve::QUINTIC, 3)
145
162
 
146
- (0..100).each do |x|
163
+ 100.times do |x|
147
164
  n = 0
148
165
  [[0.02, 10], [0.04, 10], [0.1, 30], [0.2, 15]].each_with_index do |step_scale, idx|
149
166
  step, scale = step_scale
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perlin_noise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-16 00:00:00.000000000 Z
12
+ date: 2012-07-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Perlin noise implemented in Ruby
15
15
  email:
@@ -49,10 +49,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
49
  version: '0'
50
50
  requirements: []
51
51
  rubyforge_project: perlin
52
- rubygems_version: 1.8.10
52
+ rubygems_version: 1.8.24
53
53
  signing_key:
54
54
  specification_version: 3
55
55
  summary: Perlin noise generator
56
56
  test_files:
57
57
  - test/test_perlin.rb
58
- has_rdoc: