perlin 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -45,11 +45,6 @@ task :browse_yard => :yard do
45
45
  Launchy.open "doc/index.html" rescue nil
46
46
  end
47
47
 
48
- desc "Create platform-specific compiled gem"
49
- task :native_gem do
50
- Rake::Task["native"].invoke "gem"
51
- end
52
-
53
48
  desc "Run benchmarks"
54
49
  task :bench => :compile do
55
50
  require File.expand_path("../bench/benchmarks.rb", __FILE__)
@@ -0,0 +1,13 @@
1
+ require 'perlin/version'
2
+
3
+ begin
4
+ RUBY_VERSION =~ /(\d+.\d+)/
5
+ require "perlin/#{$1}/perlin.so"
6
+ rescue LoadError
7
+ require "perlin/perlin.so"
8
+ end
9
+
10
+ require 'perlin/generator'
11
+
12
+ module Perlin
13
+ end
@@ -0,0 +1,161 @@
1
+ module Perlin
2
+ # Perlin noise generator.
3
+ #
4
+ # @!attribute [rw] seed
5
+ # @return [Integer]
6
+ #
7
+ # @!attribute [r] persistence
8
+ # @return [Float]
9
+ #
10
+ # @!attribute [r] octave
11
+ # @return [Integer]
12
+ class Generator
13
+ attr_reader :seed, :octave, :persistence
14
+ def classic?; @classic; end
15
+
16
+ # @!method initialize(seed, persistence, octave)
17
+ # Create a noise generator.
18
+ #
19
+ # Using the same seed will always produce the same pattern. Animate a perlin 'texture' by altering the seed based on time.
20
+ #
21
+ # @param seed [Integer] Seed value to create a different pattern.
22
+ # @param persistence [Float] Used to generate different frequencies/amplitudes of output.
23
+ # @param octave [Integer] Number of iterations to run (higher number of octaves takes more time)
24
+ # @option options :classic [Boolean] (false) Whether to use the slower Classic algorithm, rather than default (and much faster) Simplex.
25
+ def initialize(seed, persistence, octave, options = {})
26
+ options = {
27
+ :classic => false,
28
+ }.merge! options
29
+
30
+ initialize_(seed, persistence, octave, options[:classic])
31
+ end
32
+ protected :initialize_ # Underlying C implementation.
33
+
34
+ # @overload chunk(x, y, steps_x, steps_y, interval)
35
+ # Calculates a rectangular section of height (n) values and returns them as a 2D array.
36
+ #
37
+ # This is much faster than accessing each point separately using {#[]}
38
+ #
39
+ # @example
40
+ # noise = Perlin::Generator.new 123, 1.0, 1
41
+ # arr = noise.chunk 1, 1, 2, 3, 1.5
42
+ #
43
+ # # access position 1, 2 (remember that arr is offset by the x, y value of the chunk)
44
+ # puts arr[0, 1] #=> -0.2208995521068573
45
+ #
46
+ # p arr #= > [[0.05753844603896141, -0.2208995521068573, 0.3973901569843292], [0.1383310854434967, -0.22248442471027374, 0.15600799024105072]]
47
+ #
48
+ # @param x [Float]
49
+ # @param y [Float]
50
+ # @param steps_x [Integer]
51
+ # @param steps_y [Integer]
52
+ # @param interval [Float]
53
+ #
54
+ # @return [Array<Array<Float>>] height (n) values within the rectangle.
55
+ #
56
+ # @overload chunk(x, y, steps_x, steps_y, interval) {|h, x, y| }
57
+ # Calculates a rectangular section of height (n) values and returns them as a 2D array.
58
+ #
59
+ # This is much faster than accessing each point separately using {#[]}
60
+ #
61
+ # @example
62
+ # noise = Perlin::Generator.new 123, 0.5, 3
63
+ # noise.chunk 1.0, 2.3, 3, 2, 1.5 do |h, x, y|
64
+ # # Use the height value, which is at x, y.
65
+ # end
66
+ #
67
+ # @param x [Float]
68
+ # @param y [Float]
69
+ # @param steps_x [Integer]
70
+ # @param steps_y [Integer]
71
+ # @param interval [Float]
72
+ #
73
+ # @yieldparam h [Float] Height at x, y
74
+ # @yieldparam x [Float]
75
+ # @yieldparam y [Float]
76
+ #
77
+ # @return [nil]
78
+ #
79
+ # @overload chunk(x, y, z, size_x, size_y, size_z, interval)
80
+ # Calculates a rectangular section of height (n) values and returns them as a 3D array.
81
+ #
82
+ # This is much faster than accessing each point separately using {#[]}
83
+ #
84
+ # @example
85
+ # noise = Perlin::Generator.new 123, 0.5, 5
86
+ # arr = noise.chunk 6.0, 5.0, 4.0, 3, 2, 1, 1.5
87
+ #
88
+ # # access position 2, 1, 0 (remember that arr is offset by the x, y and z value of the chunk)
89
+ # puts arr[2, 1, 0] #=>
90
+ #
91
+ # p arr #= >
92
+ #
93
+ # @param x [Float]
94
+ # @param y [Float]
95
+ # @param z [Float]
96
+ # @param steps_x [Integer]
97
+ # @param steps_y [Integer]
98
+ # @param steps_z [Integer]
99
+ # @param interval [Float]
100
+ #
101
+ # @return [Array<Array<Float>>] height (n) values within the rectangle.
102
+ #
103
+ # @overload chunk(x, y, z, size_x, size_y, size_z, interval) {|h, x, y| }
104
+ # Calculates a rectangular section of height (n) values and returns them as a 3D array.
105
+ #
106
+ # This is much faster than accessing each point separately using {#[]}
107
+ #
108
+ # @example
109
+ # noise = Perlin::Generator.new 123, 0.8, 3
110
+ # noise.chunk 6.0, 5.0, 4.0, 3, 2, 1, 1.5 do |h, x, y, z|
111
+ # # Use the height value, which is at x, y, z.
112
+ # end
113
+ #
114
+ # @param x [Float]
115
+ # @param y [Float]
116
+ # @param z [Float]
117
+ # @param steps_x [Integer]
118
+ # @param steps_y [Integer]
119
+ # @param steps_z [Integer]
120
+ # @param interval [Float]
121
+ #
122
+ # @yieldparam h [Float] Height at x, y, z
123
+ # @yieldparam x [Float]
124
+ # @yieldparam y [Float]
125
+ # @yieldparam z [Float]
126
+ #
127
+ # @return [nil]
128
+
129
+ # Gets height (n) at a point in 2D or 3D space.
130
+ #
131
+ # This is much slower, if accessing many points, than using {#chunk}
132
+ #
133
+ # @overload [](x, y)
134
+ # Gets height (n) value at a specific 2D position.
135
+ #
136
+ # @example
137
+ # noise = Perlin::Generator.new 123, 1.0, 1
138
+ #
139
+ # # Returns a 'height' value for (x, y)
140
+ # puts noise[10, 20] #=> 0.9004574418067932
141
+ #
142
+ # @param x [Float]
143
+ # @param y [Float]
144
+ # @return [Float] height (n) value at the position
145
+ #
146
+ # @overload [](x, y, z)
147
+ # Gets height (n) value at a specific 3D position.
148
+ #
149
+ # @example
150
+ # noise = Perlin::Generator.new 123, 1.0, 1
151
+ #
152
+ # # Returns a 'height' value for (x, y, z)
153
+ # puts noise[10, 20, 30] #=> 0.017745036631822586
154
+ #
155
+ # @param x [Float]
156
+ # @param y [Float]
157
+ # @param z [Float]
158
+ # @return [Float] height (n) value at the position
159
+ alias_method :run, :[]
160
+ end
161
+ end
@@ -0,0 +1,5 @@
1
+ # Perlin noise generation.
2
+ module Perlin
3
+ # Current version of the gem.
4
+ VERSION = "0.1.1"
5
+ end
@@ -0,0 +1,4 @@
1
+ require "rspec"
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require "perlin"
@@ -0,0 +1,245 @@
1
+
2
+ require File.expand_path("../../helper.rb", __FILE__)
3
+
4
+ describe Perlin::Generator do
5
+ before :each do
6
+ @classic = Perlin::Generator.new 123, 1.5, 2, :classic => true
7
+ @simplex = Perlin::Generator.new 0, 1.5, 2
8
+ @accuracy = 0.00001
9
+ end
10
+
11
+ it "should have seed set correctly" do
12
+ @classic.seed.should eq 123
13
+ @classic.seed.should be_kind_of Integer
14
+ end
15
+
16
+ it "should have seed set uniquely on all generators" do
17
+ # This was a bug in the original code!
18
+ g = Perlin::Generator.new 99, 1, 1
19
+ g.seed.should eq 99
20
+ g.seed.should be_kind_of Integer
21
+
22
+ @classic.seed.should eq 123
23
+ g[0, 0].should_not eq @classic[0, 0]
24
+ end
25
+
26
+ it "should have persistence set correctly" do
27
+ @classic.persistence.should be_within(@accuracy).of 1.5
28
+ end
29
+
30
+ it "should have octave set correctly" do
31
+ @classic.octave.should eq 2
32
+ @classic.octave.should be_kind_of Integer
33
+ end
34
+
35
+ describe "SIMPLEX" do
36
+ it "should have classic? set correctly" do
37
+ @simplex.classic?.should be_false
38
+ end
39
+ end
40
+
41
+ describe "CLASSIC" do
42
+ it "should have classic? set correctly" do
43
+ @classic.classic?.should be_true
44
+ end
45
+ end
46
+
47
+ describe "seed=" do
48
+ it "should set seed correctly" do
49
+ @classic.seed = 12
50
+ @classic.seed.should eq 12
51
+ @classic.seed.should be_kind_of Integer
52
+ end
53
+ end
54
+
55
+ describe "persistence=" do
56
+ it "should set persistence correctly" do
57
+ @classic.persistence = 12
58
+ @classic.persistence.should eq 12
59
+ @classic.persistence.should be_kind_of Float
60
+ end
61
+ end
62
+
63
+ describe "octave=" do
64
+ it "should set octave correctly" do
65
+ @classic.octave = 12
66
+ @classic.octave.should eq 12
67
+ @classic.octave.should be_kind_of Integer
68
+ end
69
+ end
70
+
71
+ describe "classic=" do
72
+ it "should set classic? correctly" do
73
+ @simplex.classic = true
74
+ @simplex.classic?.should be_true
75
+ end
76
+ end
77
+
78
+ describe "[]" do
79
+ it "[x, y] should support float values" do
80
+ @simplex[0, 0].should_not be_within(@accuracy).of @simplex[0.2, 0.2]
81
+ end
82
+
83
+
84
+
85
+ it "[x, y, z] should support float values" do
86
+ @simplex[0, 0, 0].should_not be_within(@accuracy).of @simplex[0.2, 0.2, 0.2]
87
+ end
88
+
89
+ it "should fail if given too few arguments" do
90
+ lambda { @classic[0] }.should raise_error ArgumentError
91
+ end
92
+
93
+ it "should fail if given too many arguments" do
94
+ lambda { @classic[0, 0, 0, 0] }.should raise_error ArgumentError
95
+ end
96
+
97
+ describe "SIMPLEX" do
98
+ describe "[](x, y)" do
99
+ it "should return the appropriate value" do
100
+ @simplex[0, 1].should be_within(@accuracy).of 0.7600996515471077
101
+ end
102
+
103
+ it "should return different values based on seed" do
104
+ initial = @simplex[9, 5]
105
+ @simplex.seed = 95
106
+ initial.should_not be_within(@accuracy).of @simplex[9, 5]
107
+ end
108
+ end
109
+
110
+ describe "[](x, y, z)" do
111
+ it "should return the appropriate value" do
112
+ @simplex[0, 1, 2].should be_within(@accuracy).of -0.4994023090387083
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "CLASSIC" do
118
+ describe "[](x, y)" do
119
+ it "should return the appropriate value" do
120
+ @classic[0, 0].should be_within(@accuracy).of -1.0405873507261276
121
+ end
122
+
123
+ it "should return different values based on seed" do
124
+ initial = @classic[9, 5]
125
+ @classic.seed = 95
126
+ initial.should_not be_within(@accuracy).of @classic[9, 5]
127
+ end
128
+ end
129
+
130
+ describe "[](x, y, z)" do
131
+ it "should return the appropriate value" do
132
+ @classic[0, 0, 0].should be_within(@accuracy).of -1.5681833028793335
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "chunk" do
139
+ describe "chunk 2D" do
140
+
141
+ describe "SIMPLEX" do
142
+ it "should return the appropriate values" do
143
+ chunk = @simplex.chunk 1, 2, 3, 4, 1
144
+ chunk.should eq [[0.0, 0.19517135798668975, 0.19616149193873283, -5.932618130464163e-07], [0.10886869609093779, 0.10787834101090553, -5.932618130464163e-07, -0.19616171787047829], [-0.0431512326002121, 0.0, 0.260888409614563, 0.45605969740428703]]
145
+ end
146
+
147
+ it "should give the same results, regardless of x/y offset" do
148
+ chunk1 = @simplex.chunk 0, 0, 3, 3, 0.1
149
+ chunk2 = @simplex.chunk 0.1, 0.1, 3, 3, 0.1
150
+
151
+ chunk2[0][0].should eq chunk1[1][1]
152
+ chunk2[0][1].should eq chunk1[1][2]
153
+ chunk2[1][0].should eq chunk1[2][1]
154
+ chunk2[1][1].should eq chunk1[2][2]
155
+ end
156
+
157
+ it "should work with a block" do
158
+ arr = []
159
+ @simplex.chunk 1, 2, 3, 4, 1 do |h, x, y|
160
+ arr << [h, x, y]
161
+ end
162
+ arr.should eq [[0.0, 1.0, 2.0], [0.19517135798668975, 1.0, 3.0], [0.19616149193873283, 1.0, 4.0], [-5.932618130464163e-07, 1.0, 5.0], [0.10886869609093779, 2.0, 2.0], [0.10787834101090553, 2.0, 3.0], [-5.932618130464163e-07, 2.0, 4.0], [-0.19616171787047829, 2.0, 5.0], [-0.0431512326002121, 3.0, 2.0], [0.0, 3.0, 3.0], [0.260888409614563, 3.0, 4.0], [0.45605969740428703, 3.0, 5.0]]
163
+ end
164
+ end
165
+
166
+ describe "CLASSIC" do
167
+ it "should return the appropriate values" do
168
+ chunk = @classic.chunk 1, 2, 3, 4, 1
169
+ chunk.should eq [[-2.014809340238571, -0.7094215080142021, -0.5946878045797348, 0.4915006756782532], [-1.4068767204880714, -0.732808068394661, 0.07362580299377441, -0.325466126203537], [-0.857817449606955, -1.940980076789856, -0.5687579363584518, 1.4209578335285187]]
170
+ end
171
+
172
+ it "should give the same results, regardless of x/y offset" do
173
+ chunk1 = @classic.chunk 0, 0, 3, 3, 0.1
174
+ chunk2 = @classic.chunk 0.1, 0.1, 3, 3, 0.1
175
+ chunk2[0][0].should eq chunk1[1][1]
176
+ chunk2[0][1].should eq chunk1[1][2]
177
+ chunk2[1][0].should eq chunk1[2][1]
178
+ chunk2[1][1].should eq chunk1[2][2]
179
+ end
180
+
181
+ it "should work with a block" do
182
+ arr = []
183
+ @classic.chunk 1, 2, 3, 4, 1 do |h, x, y|
184
+ arr << [h, x, y]
185
+ end
186
+ arr.should eq [[-2.014809340238571, 1.0, 2.0], [-0.7094215080142021, 1.0, 3.0], [-0.5946878045797348, 1.0, 4.0], [0.4915006756782532, 1.0, 5.0], [-1.4068767204880714, 2.0, 2.0], [-0.732808068394661, 2.0, 3.0], [0.07362580299377441, 2.0, 4.0], [-0.325466126203537, 2.0, 5.0], [-0.857817449606955, 3.0, 2.0], [-1.940980076789856, 3.0, 3.0], [-0.5687579363584518, 3.0, 4.0], [1.4209578335285187, 3.0, 5.0]]
187
+ end
188
+ end
189
+
190
+ it "should fail if given negative size_x" do
191
+ lambda { @classic.chunk 0, 0, -1, 0 }.should raise_error ArgumentError
192
+ end
193
+
194
+ it "should fail if given negative size_y" do
195
+ lambda { @classic.chunk 0, 0, 0, -1 }.should raise_error ArgumentError
196
+ end
197
+
198
+ end
199
+
200
+ describe "chunk 3D" do
201
+ describe "SIMPLEX" do
202
+ it "should return the appropriate values" do
203
+ chunk = @simplex.chunk 6, 5, 4, 3, 2, 1, 1
204
+ chunk.should eq [[[-0.0506731136544405], [0.13219586780905937]], [[0.32796947870374366], [0.5241572306428496]], [[-0.10557871005195935], [-0.10961889028549195]]]
205
+ end
206
+
207
+ it "should work with a block" do
208
+ arr = []
209
+ @simplex.chunk 6, 5, 4, 3, 2, 1, 1 do |h, x, y, z|
210
+ arr << [h, x, y, z]
211
+ end
212
+ arr.should eq [[-0.0506731136544405, 6.0, 5.0, 4.0], [0.13219586780905937, 6.0, 6.0, 4.0], [0.32796947870374366, 7.0, 5.0, 4.0], [0.5241572306428496, 7.0, 6.0, 4.0], [-0.10557871005195935, 8.0, 5.0, 4.0], [-0.10961889028549195, 8.0, 6.0, 4.0]]
213
+ end
214
+ end
215
+
216
+ describe "CLASSIC" do
217
+ it "should return the appropriate values" do
218
+ chunk = @classic.chunk 6, 5, 4, 3, 2, 1, 1
219
+ chunk.should eq [[[0.7522532045841217], [0.3314518630504608]], [[0.3198353797197342], [0.967293307185173]], [[1.1024393141269684], [0.5659154206514359]]]
220
+ end
221
+
222
+ it "should work with a block" do
223
+ arr = []
224
+ @classic.chunk 6, 5, 4, 3, 2, 1, 1 do |h, x, y, z|
225
+ arr << [h, x, y, z]
226
+ end
227
+ arr.should eq [[0.7522532045841217, 6.0, 5.0, 4.0], [0.3314518630504608, 6.0, 6.0, 4.0], [0.3198353797197342, 7.0, 5.0, 4.0], [0.967293307185173, 7.0, 6.0, 4.0], [1.1024393141269684, 8.0, 5.0, 4.0], [0.5659154206514359, 8.0, 6.0, 4.0]]
228
+ end
229
+ end
230
+
231
+ it "should fail if given negative size_x" do
232
+ lambda { @classic.chunk 0, 0, 0, -1, 0, 0 }.should raise_error ArgumentError
233
+ end
234
+
235
+ it "should fail if given negative size_y" do
236
+ lambda { @classic.chunk 0, 0, 0, 0, -1, 0 }.should raise_error ArgumentError
237
+ end
238
+
239
+ it "should fail if given negative size_z" do
240
+ lambda { @classic.chunk 0, 0, 0, 0, 0, -1 }.should raise_error ArgumentError
241
+ end
242
+ end
243
+
244
+ end
245
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perlin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -129,6 +129,9 @@ files:
129
129
  - LICENSE
130
130
  - Rakefile
131
131
  - README.md
132
+ - lib/perlin/generator.rb
133
+ - lib/perlin/version.rb
134
+ - lib/perlin.rb
132
135
  - ext/perlin/classic.c
133
136
  - ext/perlin/generator.c
134
137
  - ext/perlin/perlin.c
@@ -144,6 +147,8 @@ files:
144
147
  - examples/index_in_3d.rb
145
148
  - examples/ogl/README.md
146
149
  - examples/ogl/run.rb
150
+ - spec/helper.rb
151
+ - spec/perlin/generator_spec.rb
147
152
  homepage: https://github.com/boj/ruby-perlin
148
153
  licenses:
149
154
  - MIT
@@ -157,22 +162,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
162
  - - ! '>='
158
163
  - !ruby/object:Gem::Version
159
164
  version: '0'
160
- segments:
161
- - 0
162
- hash: 176652013
163
165
  required_rubygems_version: !ruby/object:Gem::Requirement
164
166
  none: false
165
167
  requirements:
166
168
  - - ! '>='
167
169
  - !ruby/object:Gem::Version
168
170
  version: '0'
169
- segments:
170
- - 0
171
- hash: 176652013
172
171
  requirements: []
173
172
  rubyforge_project: ruby-perlin
174
173
  rubygems_version: 1.8.24
175
174
  signing_key:
176
175
  specification_version: 3
177
176
  summary: Perlin Noise C extension
178
- test_files: []
177
+ test_files:
178
+ - spec/helper.rb
179
+ - spec/perlin/generator_spec.rb