budgie 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.
@@ -0,0 +1,59 @@
1
+ require 'opengl'
2
+
3
+ module Budgie; class DrawPalette
4
+ include GL
5
+
6
+ def initialize(palette, camera)
7
+ @palette = palette
8
+ @camera = camera
9
+ end
10
+
11
+ def fixed?
12
+ !!@fixed
13
+ end
14
+
15
+ def fix
16
+ @fixed = @camera.dup
17
+ @fixed.step = 10
18
+ @fixed.forward
19
+ end
20
+
21
+ def release
22
+ @fixed = nil
23
+ end
24
+
25
+ def draw
26
+ return unless @fixed
27
+
28
+ glMatrixMode GL_MODELVIEW
29
+ glPushMatrix
30
+
31
+ glTranslatef @fixed.x, @fixed.y, @fixed.z
32
+ glRotatef -@fixed.alpha, 0, 1, 0
33
+
34
+ draw!
35
+
36
+ glPopMatrix
37
+ end
38
+
39
+ private
40
+
41
+ def draw!
42
+ size = (Math.sqrt @palette.colors).floor
43
+ glTranslatef -size / 2, -size / 2, 0
44
+ glBegin GL_QUADS
45
+ size.times do |x|
46
+ size.times do |y|
47
+ index = 16 * x + y
48
+ @palette.rgb(index) do |r, g, b|
49
+ glColor3ub r, g, b
50
+ end
51
+ glVertex3f x, y, 0
52
+ glVertex3f x + 1, y, 0
53
+ glVertex3f x + 1, y + 1, 0
54
+ glVertex3f x, y + 1, 0
55
+ end
56
+ end
57
+ glEnd
58
+ end
59
+ end; end
@@ -0,0 +1,58 @@
1
+ require 'opengl'
2
+ require 'budgie/draw_cube'
3
+
4
+ module Budgie; class DrawPartial
5
+ include GL
6
+
7
+ def initialize(draw_map, x, y, z)
8
+ @draw_map = draw_map
9
+ @map = draw_map.map
10
+ @size = draw_map.partial_size
11
+ @x = x
12
+ @y = y
13
+ @z = z
14
+ @list = glGenLists 1
15
+ @cube = DrawCube.new
16
+ end
17
+
18
+ def draw
19
+ glCallList @list
20
+ end
21
+
22
+ def compile
23
+ dx = @x * @size
24
+ dy = @y * @size
25
+ dz = @z * @size
26
+
27
+ glNewList @list, GL_COMPILE
28
+ @size.times do |x|
29
+ @size.times do |y|
30
+ @size.times do |z|
31
+ cx = x + dx
32
+ cy = y + dy
33
+ cz = z + dz
34
+ index = @map[cx, cy, cz]
35
+ cube cx, cy, cz, index if index
36
+ end
37
+ end
38
+ end
39
+ glEndList
40
+ end
41
+
42
+ private
43
+
44
+ def cube(x, y, z, index)
45
+ @draw_map.cube_color x, y, z, index
46
+ glPushMatrix
47
+ glTranslatef x, y, z
48
+ @cube.draw do
49
+ @cube.front unless @map[x, y, z + 1]
50
+ @cube.back unless @map[x, y, z - 1]
51
+ @cube.right unless @map[x + 1, y, z]
52
+ @cube.left unless @map[x - 1, y, z]
53
+ @cube.top unless @map[x, y + 1, z]
54
+ @cube.bottom unless @map[x, y - 1, z]
55
+ end
56
+ glPopMatrix
57
+ end
58
+ end; end
@@ -0,0 +1,33 @@
1
+ require 'budgie/draw_cube'
2
+
3
+ module Budgie; class DrawPickerCube < DrawCube
4
+ def front
5
+ glColor3ub 2, 2, 3
6
+ super
7
+ end
8
+
9
+ def back
10
+ glColor3ub 2, 2, 1
11
+ super
12
+ end
13
+
14
+ def top
15
+ glColor3ub 2, 3, 2
16
+ super
17
+ end
18
+
19
+ def bottom
20
+ glColor3ub 2, 1, 2
21
+ super
22
+ end
23
+
24
+ def right
25
+ glColor3ub 3, 2, 2
26
+ super
27
+ end
28
+
29
+ def left
30
+ glColor3ub 1, 2, 2
31
+ super
32
+ end
33
+ end; end
@@ -0,0 +1,74 @@
1
+ require 'opengl'
2
+ require 'budgie/map'
3
+ require 'budgie/index'
4
+ require 'budgie/draw_partial'
5
+
6
+ # Splits map by 16x16x16 chunks and caches
7
+ # drawing commands for each of them
8
+ module Budgie; class DrawPickerMap
9
+ include GL
10
+
11
+ attr_reader :map, :partial_size
12
+
13
+ def initialize(map)
14
+ @map = map
15
+ @partial_size = 16
16
+ @partials = Map.new 1 + @map.max / @partial_size
17
+
18
+ compile
19
+ end
20
+
21
+ def update_partial(x, y, z)
22
+ x /= @partial_size
23
+ y /= @partial_size
24
+ z /= @partial_size
25
+ compile_partial x, y, z
26
+ # compile_partial x - 1, y, z
27
+ # compile_partial x + 1, y, z
28
+ # compile_partial x, y - 1, z
29
+ # compile_partial x, y + 1, z
30
+ # compile_partial x, y, z - 1
31
+ # compile_partial x, y, z + 1
32
+ end
33
+
34
+ def compile
35
+ @partials.each do |x, y, z|
36
+ compile_partial x, y, z
37
+ end
38
+ end
39
+
40
+ def draw
41
+ @partials.each do |x, y, z|
42
+ draw_partial x, y, z
43
+ end
44
+ end
45
+
46
+ def cube_color(x, y, z, index)
47
+ x = 1 + to_index(x)
48
+ y = 1 + to_index(y)
49
+ z = 1 + to_index(z)
50
+ glColor3ub x, y, z
51
+ end
52
+
53
+ private
54
+
55
+ include Index
56
+
57
+ def partial(x, y, z)
58
+ partial = @partials[x, y, z]
59
+ partial = @partials[x, y, z] = create_partial(x, y, z) unless partial
60
+ partial
61
+ end
62
+
63
+ def create_partial(x, y, z)
64
+ DrawPartial.new self, x, y, z
65
+ end
66
+
67
+ def compile_partial(x, y, z)
68
+ partial(x, y, z).compile
69
+ end
70
+
71
+ def draw_partial(x, y, z)
72
+ partial(x, y, z).draw
73
+ end
74
+ end; end
@@ -0,0 +1,25 @@
1
+ module Budgie; module Index
2
+ # Encodes negative values as positive ones
3
+ # 0 => 0
4
+ # 1 => 2
5
+ # 2 => 4
6
+ # -1 => 1
7
+ # -2 => 3
8
+ # etc
9
+ def to_index(value)
10
+ if value >= 0
11
+ 2 * value
12
+ else
13
+ -(1 + 2 * value)
14
+ end
15
+ end
16
+
17
+ # Reverses #to
18
+ def from_index(value)
19
+ if value % 2 == 0
20
+ value / 2
21
+ else
22
+ -(1 + value) / 2
23
+ end
24
+ end
25
+ end; end
data/lib/budgie/map.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'budgie/index'
2
+ require 'budgie/auto_array'
3
+
4
+ # Generic 3d array with negative indexes
5
+ # and auto-expand capability
6
+ module Budgie; class Map
7
+ attr_reader :max
8
+
9
+ def initialize(max = 0)
10
+ @max = max
11
+ @data = AutoArray.new { AutoArray.new { Array.new } }
12
+ end
13
+
14
+ def [](x, y, z)
15
+ @data[to_index x][to_index y][to_index z]
16
+ end
17
+
18
+ def []=(x, y, z, value)
19
+ self.max = x
20
+ self.max = y
21
+ self.max = z
22
+ @data[to_index x][to_index y][to_index z] = value
23
+ end
24
+
25
+ def each(&block)
26
+ (-@max).upto(@max) do |x|
27
+ (-@max).upto(@max) do |y|
28
+ (-@max).upto(@max) do |z|
29
+ yield x, y, z, self[x, y, z]
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ include Index
38
+
39
+ def max=(value)
40
+ value = value.abs
41
+ @max = value if value > @max
42
+ end
43
+ end; end
@@ -0,0 +1,37 @@
1
+ module Budgie; class Palette
2
+ attr_reader :colors
3
+
4
+ def initialize
5
+ @colors = 256
6
+ @red_colors = 8
7
+ @green_colors = 8
8
+ @blue_colors = 4
9
+ end
10
+
11
+ def white
12
+ @colors - 1
13
+ end
14
+
15
+ def rgb(index, &block)
16
+ index ||= 0
17
+ index %= @colors
18
+
19
+ r = index / @blue_colors / @green_colors
20
+ g = index / @blue_colors % @green_colors #/
21
+ b = index % @blue_colors
22
+
23
+ r = r * (@colors - 1) / (@red_colors - 1)
24
+ g = g * (@colors - 1) / (@green_colors - 1)
25
+ b = b * (@colors - 1) / (@blue_colors - 1)
26
+
27
+ yield r, g, b
28
+ end
29
+
30
+ def index(r, g, b)
31
+ r = r * @red_colors / @colors
32
+ g = g * @green_colors / @colors
33
+ b = b * @blue_colors / @colors
34
+
35
+ (r * @green_colors + g) * @blue_colors + b
36
+ end
37
+ end; end
@@ -0,0 +1,105 @@
1
+ require 'opengl'
2
+ require 'budgie/change_map'
3
+ require 'budgie/draw.rb'
4
+ require 'budgie/draw_map.rb'
5
+ require 'budgie/draw_palette'
6
+ require 'budgie/checker_texture'
7
+
8
+ module Budgie; class Scene
9
+ extend Forwardable
10
+ include GL
11
+
12
+ attr_reader :map, :palette, :camera, :selection, :draw_map, :draw_picker_map
13
+
14
+ def_delegators :@draw_palette, :fixed?, :fix, :release
15
+ def_delegators :@change_map, :place, :replace, :remove
16
+
17
+ def initialize(app)
18
+ @map = app.map
19
+ @camera = app.camera
20
+ @palette = app.palette
21
+ @selection = app.selection
22
+
23
+ @draw = Draw.new app
24
+ @draw_map = DrawMap.new @map, @palette
25
+ @draw_palette = DrawPalette.new @palette, @camera
26
+ @draw_picker_map = DrawPickerMap.new @map
27
+
28
+ @change_map = ChangeMap.new self
29
+ @checker_texture = CheckerTexture.new
30
+
31
+ glClearColor 0, 0, 0, 0
32
+ glClearDepth 1.0
33
+
34
+ glCullFace GL_FRONT
35
+ glDepthFunc GL_LEQUAL
36
+ glShadeModel GL_SMOOTH
37
+ glLightfv GL_LIGHT1, GL_AMBIENT, [0.25, 0.25, 0.25, 1.0]
38
+ glLightfv GL_LIGHT2, GL_DIFFUSE, [0.5, 0.5, 0.5, 1.0]
39
+ glLightfv GL_LIGHT3, GL_DIFFUSE, [0.25, 0.25, 0.25, 1.0]
40
+ end
41
+
42
+ def display
43
+ before_display
44
+
45
+ with GL_DEPTH_TEST, GL_CULL_FACE do
46
+ with GL_LIGHTING, GL_TEXTURE_2D, GL_COLOR_MATERIAL, GL_LIGHT1, GL_LIGHT2, GL_LIGHT3 do
47
+ @checker_texture.bind
48
+ @draw_map.draw
49
+ @checker_texture.unbind
50
+ end
51
+
52
+ with GL_POLYGON_OFFSET_FILL do
53
+ @draw.selection @selection
54
+ end
55
+ end
56
+
57
+ @draw_palette.draw
58
+ @draw.ortho { @draw.crosshair_with_outline }
59
+ end
60
+
61
+ def picker
62
+ before_display
63
+ with GL_DEPTH_TEST, GL_CULL_FACE do
64
+ @draw_picker_map.draw
65
+ end
66
+ end
67
+
68
+ def color_picker
69
+ before_display
70
+ with GL_DEPTH_TEST, GL_CULL_FACE do
71
+ @draw_map.draw
72
+ end
73
+ @draw_palette.draw
74
+ end
75
+
76
+ def normal_picker
77
+ before_display
78
+ with GL_DEPTH_TEST, GL_CULL_FACE do
79
+ @draw.picker_cube_at @selection.x, @selection.y, @selection.z
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def before_display
86
+ glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
87
+
88
+ glMatrixMode GL_MODELVIEW
89
+ glLoadIdentity
90
+ glScalef 1, 1, -1
91
+
92
+ glRotatef @camera.beta, 1, 0, 0
93
+ glRotatef @camera.alpha, 0, 1, 0
94
+ glTranslatef -@camera.x, -@camera.y, -@camera.z
95
+
96
+ glLightfv GL_LIGHT2, GL_POSITION, [@camera.x, @map.max * @map.max, @camera.z, 1.0]
97
+ glLightfv GL_LIGHT3, GL_POSITION, [@camera.x, @camera.y, @camera.z, 1.0]
98
+ end
99
+
100
+ def with(*states, &block)
101
+ states.each { |state| glEnable state }
102
+ yield
103
+ states.each { |state| glDisable state }
104
+ end
105
+ end; end
@@ -0,0 +1,45 @@
1
+ require 'budgie/index'
2
+
3
+ module Budgie; class Selection
4
+ attr_accessor :x, :y, :z, :normal_x, :normal_y, :normal_z, :selected, :r, :g, :b
5
+
6
+ def initialize
7
+ @x = @y = @z = @normal_x = @normal_y = @normal_z = @r = @g = @b = 0
8
+ @selected = false
9
+ end
10
+
11
+ def new_x
12
+ @x + @normal_x
13
+ end
14
+
15
+ def new_y
16
+ @y + @normal_y
17
+ end
18
+
19
+ def new_z
20
+ @z + @normal_z
21
+ end
22
+
23
+ # Nothing is selected when color is [0, 0, 0]
24
+ # Everything else maps to [x, y, z] indexes of the map
25
+ def from_color(r, g, b)
26
+ @selected = r * g * b != 0
27
+ if @selected
28
+ @x = from_index(r - 1)
29
+ @y = from_index(g - 1)
30
+ @z = from_index(b - 1)
31
+ end
32
+ end
33
+
34
+ # Cube normals can be [-1|0|1, -1|0|1, -1|0|1]
35
+ # Normals are encoded like [1|2|3, 1|2|3, 1|2|3]
36
+ def normal_from_color(r, g, b)
37
+ @normal_x = r - 2
38
+ @normal_y = g - 2
39
+ @normal_z = b - 2
40
+ end
41
+
42
+ private
43
+
44
+ include Index
45
+ end; end
@@ -0,0 +1,17 @@
1
+ module Budgie; class Settings
2
+ attr_reader :keymap, :free_mouse_mode_key, :palette_key
3
+
4
+ def initialize
5
+ @keymap = {
6
+ "\e" => 'escape',
7
+ 'w' => 'forward',
8
+ 's' => 'backward',
9
+ 'a' => 'left',
10
+ 'd' => 'right',
11
+ ' ' => 'up',
12
+ 'c' => 'down'
13
+ }
14
+ @free_mouse_mode_key = 'f'
15
+ @palette_key = 'e'
16
+ end
17
+ end; end
@@ -0,0 +1,90 @@
1
+ require 'oily_png'
2
+ require 'budgie/map'
3
+
4
+ module Budgie; class StoreMap
5
+ def initialize(filename, palette)
6
+ @filename = filename
7
+ @palette = palette
8
+ end
9
+
10
+ def create
11
+ map = Map.new
12
+ map[0, 0, 0] = @palette.white
13
+ map
14
+ end
15
+
16
+ def load
17
+ return create unless file_exists?
18
+
19
+ png = load_png
20
+ size = png.width
21
+ max = size / 2
22
+
23
+ map = Map.new
24
+
25
+ size.times do |x|
26
+ size.times do |y|
27
+ size.times do |z|
28
+ png_x = x
29
+ png_y = size * (z + 1) - (y + 1)
30
+ color = png[png_x, png_y] rescue nil
31
+ color = color_to_index color
32
+ map[x - max, y - max, z - max] = color if color
33
+ end
34
+ end
35
+ end
36
+
37
+ return map
38
+ end
39
+
40
+ def save(map)
41
+ max = map.max
42
+ size = 2 * max + 1 # [-max, max] including boundaries
43
+
44
+ width = size
45
+ height = size * size
46
+ png = new_png width, height
47
+
48
+ map.each do |x, y, z, index|
49
+ x += max
50
+ y += max
51
+ z += max
52
+ png_x = x
53
+ png_y = width * (z + 1) - (y + 1)
54
+ png[png_x, png_y] = index_to_color index
55
+ end
56
+
57
+ png.save @filename
58
+ end
59
+
60
+ private
61
+
62
+ def file_exists?
63
+ File.exists? @filename
64
+ end
65
+
66
+ def new_png(width, height)
67
+ ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
68
+ end
69
+
70
+ def load_png
71
+ ChunkyPNG::Image.from_file(@filename)
72
+ end
73
+
74
+ def index_to_color(index)
75
+ return ChunkyPNG::Color::TRANSPARENT unless index
76
+ @palette.rgb(index) do |r, g, b|
77
+ return ChunkyPNG::Color.rgba r, g, b, 0xff
78
+ end
79
+ end
80
+
81
+ def color_to_index(color)
82
+ return nil unless color
83
+ r = ChunkyPNG::Color.r color
84
+ g = ChunkyPNG::Color.g color
85
+ b = ChunkyPNG::Color.b color
86
+ a = ChunkyPNG::Color.a color
87
+ return nil unless a > 0
88
+ return @palette.index r, g, b
89
+ end
90
+ end; end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: budgie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - 4r2r
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: opengl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: glu
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: glut
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oily_png
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: ''
70
+ email: arthrrr@gmail.com
71
+ executables:
72
+ - budgie
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - bin/budgie
77
+ - lib/budgie/draw_map.rb
78
+ - lib/budgie/draw_picker_cube.rb
79
+ - lib/budgie/camera.rb
80
+ - lib/budgie/index.rb
81
+ - lib/budgie/application.rb
82
+ - lib/budgie/auto_array.rb
83
+ - lib/budgie/palette.rb
84
+ - lib/budgie/draw_palette.rb
85
+ - lib/budgie/checker_texture.rb
86
+ - lib/budgie/settings.rb
87
+ - lib/budgie/draw_partial.rb
88
+ - lib/budgie/scene.rb
89
+ - lib/budgie/map.rb
90
+ - lib/budgie/draw_cube.rb
91
+ - lib/budgie/draw.rb
92
+ - lib/budgie/selection.rb
93
+ - lib/budgie/change_map.rb
94
+ - lib/budgie/draw_picker_map.rb
95
+ - lib/budgie/store_map.rb
96
+ homepage: https://github.com/4r2r/budgie
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.0.3
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Voxel editor similar to creative mode from minecraft
120
+ test_files: []