perlin 0.1.0pre1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,13 @@
1
+ 0.1.0
2
+ -----
3
+
4
+ * Converted to gem (previously was just a .c file).
5
+ * Added 3D chunks.
6
+ * Optimised chunk operations.
7
+ * Added Generator#[x, y]
8
+ * Added Generator#[x, y, z]
9
+ * Added Generator#chunk x, y, size_x, size_y
10
+ * Added Generator#chunk x, y, z, size_x, size_y, size_z
11
+ * Added Generator#persistence, #seed and #octave accessors.
12
+ * Added Perlin's Simplex generation (much faster).
13
+ * A number of general fixes (added rspec tests).
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2009 Brian Jones
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ Perlin
2
+ ======
3
+
4
+ A Perlin noise implementation based off
5
+ <http://freespace.virgin.net/hugo.elias/models/m_perlin.htm>. Implemented as a Ruby C extension, it is considerably faster than the pure Ruby equivalent, [perlin_noise](https://github.com/junegunn/perlin_noise).
6
+
7
+ - Written by Brian 'bojo' Jones <mojobojo@gmail.com>
8
+ - Optimizations thanks to Camille Goudeseune, Univ of Illinois, <cog@illinois.edu>
9
+ - Made into gem and extended by Bil Bas (bil.bagpuss@gmail.com)
10
+
11
+ - [Simplex noise functions copyright (c) 2007-2012 Eliot Eshelman](http://www.6by9.net/b/2012/02/03/simplex-noise-for-c-and-python)
12
+
13
+ INSTALL
14
+ -------
15
+
16
+ $ gem install perlin
17
+
18
+ USAGE
19
+ -----
20
+
21
+ require 'perlin'
22
+
23
+ # Takes values seed, persistence, and octaves
24
+ noise = Perlin::Generator.new 123, 1.0, 1
25
+
26
+ # Returns a 'height' value for (x, y)
27
+ puts noise[10, 20] #=> 0.9004574418067932
28
+
29
+ # Returns a 2D array of 'heights' for a range (x, y, size_x, size_y, interval)
30
+ arr = noise.chunk 1, 1, 2, 3, 1
31
+
32
+ p arr #= > [[0.05753844603896141, -0.2208995521068573, 0.3973901569843292],
33
+ # [0.1383310854434967, -0.22248442471027374, 0.15600799024105072]]
data/Rakefile ADDED
@@ -0,0 +1,85 @@
1
+ require 'rake/clean'
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/extensiontask'
4
+ require 'yard'
5
+ require 'redcloth'
6
+ require 'launchy'
7
+
8
+
9
+ begin
10
+ require 'devkit' # only used on windows
11
+ rescue LoadError
12
+ end
13
+
14
+ require File.expand_path('../lib/perlin/version', __FILE__)
15
+
16
+ CLOBBER << "coverage"
17
+
18
+ # somewhere in your Rakefile, define your gem spec
19
+ spec = Gem::Specification.new do |s|
20
+ s.name = 'perlin'
21
+ s.version = Perlin::VERSION
22
+ s.date = Time.now.strftime '%Y-%m-%d'
23
+ s.authors = ["Brian 'bojo' Jones", 'Camille Goudeseune', 'Bil Bas']
24
+
25
+ s.summary = 'Perlin Noise C extension'
26
+ s.description = <<-END
27
+ #{s.summary}
28
+
29
+ A Perlin/Simplex noise implementation based of
30
+ <http://freespace.virgin.net/hugo.elias/models/m_perlin.htm>. Implemented as a Ruby C extension.
31
+ END
32
+
33
+ s.email = %w<mojobojo@gmail.com>
34
+ s.files = Dir.glob %w<CHANGELOG LICENSE Rakefile README.md lib/**/*.* lib ext/**/*.* examples/**/*.*>
35
+ s.homepage = 'https://github.com/boj/ruby-perlin'
36
+ s.licenses = %w<MIT>
37
+ s.extensions << 'ext/perlin/extconf.rb'
38
+ s.rubyforge_project = 'ruby-perlin'
39
+ s.test_files = []
40
+ s.has_rdoc = 'yard'
41
+
42
+ s.add_development_dependency 'rake-compile', '~> 0.8.1'
43
+ s.add_development_dependency 'simplecov', '~> 0.6.4'
44
+ s.add_development_dependency 'launchy', '~> 2.1.0'
45
+ end
46
+
47
+ Gem::PackageTask.new spec do
48
+ end
49
+
50
+ Rake::ExtensionTask.new 'perlin', spec do |ext|
51
+ RUBY_VERSION =~ /(\d+.\d+)/
52
+ ext.lib_dir = "lib/perlin/#{$1}"
53
+ end
54
+
55
+ YARD::Rake::YardocTask.new
56
+
57
+ task :default => :spec
58
+ task :spec => :compile
59
+
60
+ RSpec::Core::RakeTask.new do |t|
61
+ end
62
+
63
+ desc "Generate SimpleCov test coverage and open in your browser"
64
+ task :coverage do
65
+ rm_r "coverage" rescue nil
66
+
67
+ sh %q<ruby -rsimplecov -e "SimpleCov.command_name 'spec'; SimpleCov.start">
68
+
69
+ Launchy.open "coverage/index.html" rescue nil
70
+ end
71
+
72
+ desc "Open yard docs in browser"
73
+ task :browse_yard => :yard do
74
+ Launchy.open "doc/index.html" rescue nil
75
+ end
76
+
77
+ desc "Create platform-specific compiled gem"
78
+ task :native_gem do
79
+ Rake::Task["native"].invoke "gem"
80
+ end
81
+
82
+ desc "Run benchmarks"
83
+ task :bench => :compile do
84
+ require File.expand_path("../bench/benchmarks.rb", __FILE__)
85
+ end
@@ -0,0 +1,22 @@
1
+ require 'perlin'
2
+
3
+ def print_data(seed, persistence, octave, size_x, size_y, interval)
4
+ noise = Perlin::Generator.new seed, persistence, octave
5
+
6
+ puts
7
+
8
+ data = noise.chunk 0, 0, size_x, size_y, interval
9
+ size_y.times do |y|
10
+ str = ''
11
+
12
+ size_x.times do |x|
13
+ str << "%7.2f" % data[x][y]
14
+ end
15
+
16
+ puts str
17
+ end
18
+ end
19
+
20
+ print_data 5, 1.0, 1, 10, 500, 1
21
+
22
+ puts "\nDone!"
@@ -0,0 +1,24 @@
1
+ require 'perlin'
2
+
3
+ def print_data(seed, persistence, octave, size_x, size_y, size_z, interval)
4
+ noise = Perlin::Generator.new seed, persistence, octave
5
+
6
+ puts
7
+
8
+ data = noise.chunk 0, 0, 0, size_x, size_y, size_z, interval
9
+ size_z.times do |z|
10
+ size_y.times do |y|
11
+ str = ''
12
+
13
+ size_x.times do |x|
14
+ str << "%7.2f" % data[x][y]
15
+ end
16
+
17
+ puts str
18
+ end
19
+ end
20
+ end
21
+
22
+ print_data 5, 1.0, 1, 10, 500, 99, 1.9
23
+
24
+ puts "\nDone!"
@@ -0,0 +1,23 @@
1
+ require 'perlin'
2
+
3
+ def print_data(seed, persistence, octave, size_x, size_y)
4
+ noise = Perlin::Generator.new seed, persistence, octave
5
+
6
+ puts
7
+
8
+ # Note that it would be significantly faster to use #chunk in this example.
9
+ size_y.times do |y|
10
+ str = ''
11
+
12
+ size_x.times do |x|
13
+ n = noise.run2d x, y
14
+ str << "%7.2f" % n
15
+ end
16
+
17
+ puts str
18
+ end
19
+ end
20
+
21
+ print_data 5, 1.0, 1, 10, 500
22
+
23
+ puts "\nDone!"
@@ -0,0 +1,25 @@
1
+ require 'perlin'
2
+
3
+ def print_data(seed, persistence, octave, size_x, size_y, size_z)
4
+ noise = Perlin::Generator.new seed, persistence, octave
5
+
6
+ puts
7
+
8
+ # Note that it would be significantly faster to use #chunk in this example.
9
+ size_z.times do |z|
10
+ size_y.times do |y|
11
+ str = ''
12
+
13
+ size_x.times do |x|
14
+ n = noise.run3d x, y, z
15
+ str << "%7.2f" % n
16
+ end
17
+
18
+ puts str
19
+ end
20
+ end
21
+ end
22
+
23
+ print_data 5, 1.0, 1, 10, 200, 99
24
+
25
+ puts "\nDone!"
@@ -0,0 +1,3 @@
1
+ # Install
2
+
3
+ gem install ruby-opengl fxruby
@@ -0,0 +1,200 @@
1
+ require 'perlin'
2
+ require 'rubygems'
3
+ require 'fox16'
4
+
5
+ # Base framework borrowed from: http://www.fxruby.org/examples/gltest.rb
6
+
7
+ include Fox
8
+
9
+ class GLTestWindow < FXMainWindow
10
+
11
+ # How often our timer will fire (in milliseconds)
12
+ TIMER_INTERVAL = 100
13
+
14
+ def drawTerrain(width, length)
15
+ p = Perlin.new(@p_seed.to_s.to_i, @p_freq.to_s.to_f, @p_octave.to_s.to_i)
16
+
17
+ GL.Begin(GL::QUADS)
18
+ for x in 0..width
19
+ for y in 0..length
20
+ material = [rand, rand, rand]
21
+ GL.Material(GL::FRONT, GL::AMBIENT, material)
22
+ GL.Material(GL::FRONT, GL::DIFFUSE, material)
23
+ GL.Vertex(x, y, p.run(x, y))
24
+ GL.Vertex(x + 1, y, p.run(x + 1, y))
25
+ GL.Vertex(x + 1, y + 1, p.run(x + 1, y + 1))
26
+ GL.Vertex(x, y + 1, p.run(x, y + 1))
27
+ end
28
+ end
29
+ GL.End()
30
+ end
31
+
32
+ # Draw the GL scene
33
+ def drawScene
34
+ lightPosition = [5.0, 5.0, 5.0, 1.0]
35
+ lightAmbient = [ 0.5, 0.5, 0.5, 1.0]
36
+ lightDiffuse = [ 0.9, 0.9, 0.9, 1.0]
37
+
38
+ width = @glcanvas.width.to_f
39
+ height = @glcanvas.height.to_f
40
+ aspect = width / height
41
+
42
+ # Make context current
43
+ @glcanvas.makeCurrent()
44
+
45
+ GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
46
+
47
+ GL.ClearColor(0.0, 0.0, 0.0, 0.0)
48
+ GL.Clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT)
49
+ GL.Enable(GL::DEPTH_TEST)
50
+
51
+ GL.Disable(GL::DITHER)
52
+
53
+ GL.MatrixMode(GL::PROJECTION)
54
+ GL.LoadIdentity()
55
+ GLU.Perspective(90.0, aspect, 1.0, 100.0)
56
+
57
+ GL.MatrixMode(GL::MODELVIEW)
58
+ GL.LoadIdentity()
59
+ x = (@p_width.to_s.to_i / 2.0)
60
+ y = (@p_length.to_s.to_i / 2.0)
61
+ GLU.LookAt(5.0, 15.0, 5.0, x, y, 0.0, 0.0, -1.0, 0.0)
62
+
63
+ GL.ShadeModel(GL::SMOOTH)
64
+ GL.Light(GL::LIGHT0, GL::POSITION, lightPosition)
65
+ GL.Light(GL::LIGHT0, GL::AMBIENT, lightAmbient)
66
+ GL.Light(GL::LIGHT0, GL::DIFFUSE, lightDiffuse)
67
+ GL.Enable(GL::LIGHT0)
68
+ GL.Enable(GL::LIGHTING)
69
+
70
+ GL.PushMatrix()
71
+ drawTerrain(@p_width.to_s.to_i, @p_length.to_s.to_i)
72
+ GL.PopMatrix()
73
+
74
+ # Swap if it is double-buffered
75
+ if @glvisual.isDoubleBuffer
76
+ @glcanvas.swapBuffers
77
+ end
78
+
79
+ # Make context non-current
80
+ @glcanvas.makeNonCurrent
81
+ end
82
+
83
+ def initialize(app)
84
+ @p_seed = FXDataTarget.new(rand(100))
85
+ @p_freq = FXDataTarget.new(1.0)
86
+ @p_octave = FXDataTarget.new(1)
87
+ @p_width = FXDataTarget.new(10)
88
+ @p_length = FXDataTarget.new(10)
89
+
90
+ # Invoke the base class initializer
91
+ super(app, "Perlin Visualizer", :opts => DECOR_ALL, :width => 800, :height => 600)
92
+
93
+ # Construct the main window elements
94
+ frame = FXHorizontalFrame.new(self, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y)
95
+ frame.padLeft, frame.padRight = 0, 0
96
+ frame.padTop, frame.padBottom = 0, 0
97
+
98
+ # Left pane to contain the glcanvas
99
+ glcanvasFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT)
100
+
101
+ # Drawing glcanvas
102
+ glpanel = FXVerticalFrame.new(
103
+ glcanvasFrame, (FRAME_SUNKEN | FRAME_THICK | LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT)
104
+ )
105
+ glpanel.padLeft, glpanel.padRight = 0, 0
106
+ glpanel.padTop, glpanel.padBottom = 0, 0
107
+
108
+ # A visual to draw OpenGL
109
+ @glvisual = FXGLVisual.new(getApp(), VISUAL_DOUBLEBUFFER)
110
+
111
+ # Drawing glcanvas
112
+ @glcanvas = FXGLCanvas.new(glpanel, @glvisual, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT)
113
+ @glcanvas.connect(SEL_PAINT) { drawScene }
114
+ @glcanvas.connect(SEL_CONFIGURE) do
115
+ if @glcanvas.makeCurrent
116
+ GL.Viewport(0, 0, @glcanvas.width, @glcanvas.height)
117
+ @glcanvas.makeNonCurrent
118
+ end
119
+ end
120
+
121
+ # Right pane for the buttons
122
+ buttonFrame = FXVerticalFrame.new(frame, LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT)
123
+ buttonFrame.padLeft, buttonFrame.padRight = 10, 10
124
+ buttonFrame.padTop, buttonFrame.padBottom = 10, 10
125
+
126
+ # Redraw button
127
+ redrawBtn = FXButton.new(
128
+ buttonFrame,
129
+ "&Redraw\tRedraw the screen",
130
+ :opts => FRAME_THICK | FRAME_RAISED | LAYOUT_FILL_X | LAYOUT_TOP | LAYOUT_LEFT
131
+ )
132
+ redrawBtn.connect(SEL_COMMAND) do
133
+ x = (@p_width.to_s.to_i / 2.0)
134
+ y = (@p_length.to_s.to_i / 2.0)
135
+ GLU.LookAt(0.0, 0.0, 10.0, x, y, 0.0, 0.0, 1.0, 0.0)
136
+ drawScene
137
+ end
138
+ redrawBtn.padLeft, redrawBtn.padRight = 10, 10
139
+ redrawBtn.padTop, redrawBtn.padBottom = 5, 5
140
+
141
+ # Redraw button
142
+ redrawRndBtn = FXButton.new(
143
+ buttonFrame,
144
+ "&Redraw Random\tRedraw the screen after changing the seed",
145
+ :opts => FRAME_THICK | FRAME_RAISED | LAYOUT_FILL_X | LAYOUT_TOP | LAYOUT_LEFT
146
+ )
147
+ redrawRndBtn.connect(SEL_COMMAND) do
148
+ @p_seed = FXDataTarget.new(rand(100))
149
+ drawScene
150
+ end
151
+ redrawRndBtn.padLeft, redrawRndBtn.padRight = 10, 10
152
+ redrawRndBtn.padTop, redrawRndBtn.padBottom = 5, 5
153
+
154
+ FXLabel.new(buttonFrame, "Seed", nil, LAYOUT_CENTER_Y | LAYOUT_CENTER_X | JUSTIFY_RIGHT | LAYOUT_FILL_ROW)
155
+ FXTextField.new(buttonFrame, 10, @p_seed, FXDataTarget::ID_VALUE, TEXTFIELD_INTEGER | LAYOUT_FILL_ROW)
156
+
157
+ FXLabel.new(buttonFrame, "Frequency", nil, LAYOUT_CENTER_Y | LAYOUT_CENTER_X | JUSTIFY_RIGHT | LAYOUT_FILL_ROW)
158
+ FXTextField.new(buttonFrame, 10, @p_freq, FXDataTarget::ID_VALUE, TEXTFIELD_REAL | LAYOUT_FILL_ROW)
159
+
160
+ FXLabel.new(buttonFrame, "Octave", nil, LAYOUT_CENTER_Y | LAYOUT_CENTER_X | JUSTIFY_RIGHT | LAYOUT_FILL_ROW)
161
+ FXTextField.new(buttonFrame, 10, @p_octave, FXDataTarget::ID_VALUE, TEXTFIELD_INTEGER | LAYOUT_FILL_ROW)
162
+
163
+ FXLabel.new(buttonFrame, "Width", nil, LAYOUT_CENTER_Y | LAYOUT_CENTER_X | JUSTIFY_RIGHT | LAYOUT_FILL_ROW)
164
+ FXTextField.new(buttonFrame, 10, @p_width, FXDataTarget::ID_VALUE, TEXTFIELD_INTEGER | LAYOUT_FILL_ROW)
165
+
166
+ FXLabel.new(buttonFrame, "Length", nil, LAYOUT_CENTER_Y | LAYOUT_CENTER_X | JUSTIFY_RIGHT | LAYOUT_FILL_ROW)
167
+ FXTextField.new(buttonFrame, 10, @p_length, FXDataTarget::ID_VALUE, TEXTFIELD_INTEGER | LAYOUT_FILL_ROW)
168
+
169
+ # Exit button
170
+ exitBtn = FXButton.new(
171
+ buttonFrame,
172
+ "&Exit\tExit the application", nil,
173
+ getApp(),
174
+ FXApp::ID_QUIT,
175
+ FRAME_THICK | FRAME_RAISED | LAYOUT_FILL_X | LAYOUT_TOP | LAYOUT_LEFT
176
+ )
177
+ exitBtn.padLeft, exitBtn.padRight = 10, 10
178
+ exitBtn.padTop, exitBtn.padBottom = 5, 5
179
+ end
180
+
181
+ # Create and initialize
182
+ def create
183
+ super
184
+ show(PLACEMENT_SCREEN)
185
+ end
186
+ end
187
+
188
+ if __FILE__ == $0
189
+ application = FXApp.new("Perlin Data Viewer", "Perlin Data View")
190
+ application.disableThreads
191
+
192
+ # Construct the main window
193
+ GLTestWindow.new(application)
194
+
195
+ # Create the app's windows
196
+ application.create
197
+
198
+ # Run the application
199
+ application.run
200
+ end