cyberarm_engine 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/assets/textures/default.png +0 -0
- data/cyberarm_engine.gemspec +10 -8
- data/lib/cyberarm_engine.rb +13 -2
- data/lib/cyberarm_engine/animator.rb +6 -4
- data/lib/cyberarm_engine/background.rb +19 -15
- data/lib/cyberarm_engine/background_nine_slice.rb +125 -0
- data/lib/cyberarm_engine/bounding_box.rb +18 -18
- data/lib/cyberarm_engine/cache.rb +4 -0
- data/lib/cyberarm_engine/cache/download_manager.rb +121 -0
- data/lib/cyberarm_engine/common.rb +13 -13
- data/lib/cyberarm_engine/config_file.rb +2 -2
- data/lib/cyberarm_engine/game_object.rb +63 -72
- data/lib/cyberarm_engine/game_state.rb +6 -3
- data/lib/cyberarm_engine/model.rb +207 -0
- data/lib/cyberarm_engine/model/material.rb +21 -0
- data/lib/cyberarm_engine/model/model_object.rb +131 -0
- data/lib/cyberarm_engine/model/parser.rb +74 -0
- data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -0
- data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -0
- data/lib/cyberarm_engine/model_cache.rb +31 -0
- data/lib/cyberarm_engine/opengl.rb +28 -0
- data/lib/cyberarm_engine/opengl/light.rb +50 -0
- data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -0
- data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -0
- data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -0
- data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -0
- data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +289 -0
- data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -0
- data/lib/cyberarm_engine/{shader.rb → opengl/shader.rb} +51 -43
- data/lib/cyberarm_engine/opengl/texture.rb +69 -0
- data/lib/cyberarm_engine/ray.rb +5 -5
- data/lib/cyberarm_engine/stats.rb +2 -2
- data/lib/cyberarm_engine/text.rb +41 -27
- data/lib/cyberarm_engine/timer.rb +1 -1
- data/lib/cyberarm_engine/transform.rb +43 -20
- data/lib/cyberarm_engine/ui/border_canvas.rb +4 -3
- data/lib/cyberarm_engine/ui/dsl.rb +25 -11
- data/lib/cyberarm_engine/ui/element.rb +30 -20
- data/lib/cyberarm_engine/ui/elements/button.rb +86 -16
- data/lib/cyberarm_engine/ui/elements/check_box.rb +1 -1
- data/lib/cyberarm_engine/ui/elements/container.rb +44 -20
- data/lib/cyberarm_engine/ui/elements/edit_box.rb +175 -2
- data/lib/cyberarm_engine/ui/elements/edit_line.rb +121 -37
- data/lib/cyberarm_engine/ui/elements/flow.rb +1 -1
- data/lib/cyberarm_engine/ui/elements/image.rb +12 -9
- data/lib/cyberarm_engine/ui/elements/label.rb +93 -14
- data/lib/cyberarm_engine/ui/elements/list_box.rb +64 -2
- data/lib/cyberarm_engine/ui/elements/progress.rb +5 -5
- data/lib/cyberarm_engine/ui/elements/radio.rb +1 -1
- data/lib/cyberarm_engine/ui/elements/slider.rb +13 -16
- data/lib/cyberarm_engine/ui/elements/stack.rb +1 -1
- data/lib/cyberarm_engine/ui/elements/toggle_button.rb +27 -19
- data/lib/cyberarm_engine/ui/event.rb +7 -7
- data/lib/cyberarm_engine/ui/gui_state.rb +44 -10
- data/lib/cyberarm_engine/ui/style.rb +10 -9
- data/lib/cyberarm_engine/ui/theme.rb +28 -20
- data/lib/cyberarm_engine/vector.rb +33 -30
- data/lib/cyberarm_engine/version.rb +2 -2
- data/lib/cyberarm_engine/window.rb +27 -18
- metadata +65 -15
@@ -5,7 +5,7 @@ module CyberarmEngine
|
|
5
5
|
attr_accessor :options, :global_pause
|
6
6
|
attr_reader :game_objects
|
7
7
|
|
8
|
-
def initialize(options={})
|
8
|
+
def initialize(options = {})
|
9
9
|
@options = options
|
10
10
|
@game_objects = []
|
11
11
|
@global_pause = false
|
@@ -26,7 +26,10 @@ module CyberarmEngine
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def draw_bounding_box(box)
|
29
|
-
x
|
29
|
+
x = box.x
|
30
|
+
y = box.y
|
31
|
+
max_x = box.max_x
|
32
|
+
max_y = box.max_y
|
30
33
|
|
31
34
|
color = Gosu::Color.rgba(255, 127, 64, 240)
|
32
35
|
|
@@ -86,4 +89,4 @@ module CyberarmEngine
|
|
86
89
|
@game_objects << object
|
87
90
|
end
|
88
91
|
end
|
89
|
-
end
|
92
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
class Model
|
3
|
+
attr_accessor :objects, :materials, :vertices, :uvs, :texures, :normals, :faces, :colors, :bones, :material_file,
|
4
|
+
:current_material, :current_object, :vertex_count, :smoothing
|
5
|
+
attr_reader :position, :bounding_box, :textured_material, :file_path, :positions_buffer_id, :colors_buffer_id,
|
6
|
+
:normals_buffer_id, :uvs_buffer_id, :textures_buffer_id, :vertex_array_id, :aabb_tree
|
7
|
+
|
8
|
+
def initialize(file_path:)
|
9
|
+
@file_path = file_path
|
10
|
+
|
11
|
+
@material_file = nil
|
12
|
+
@current_object = nil
|
13
|
+
@current_material = nil
|
14
|
+
@vertex_count = 0
|
15
|
+
|
16
|
+
@objects = []
|
17
|
+
@materials = {}
|
18
|
+
@vertices = []
|
19
|
+
@colors = []
|
20
|
+
@uvs = []
|
21
|
+
@normals = []
|
22
|
+
@faces = []
|
23
|
+
@bones = []
|
24
|
+
@smoothing = 0
|
25
|
+
|
26
|
+
@bounding_box = BoundingBox.new
|
27
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
28
|
+
|
29
|
+
type = File.basename(file_path).split(".").last.to_sym
|
30
|
+
parser = Model::Parser.find(type)
|
31
|
+
raise "Unsupported model type '.#{type}', supported models are: #{Model::Parser.supported_formats}" unless parser
|
32
|
+
|
33
|
+
parse(parser)
|
34
|
+
|
35
|
+
@has_texture = false
|
36
|
+
|
37
|
+
@materials.each do |_key, material|
|
38
|
+
@has_texture = true if material.texture_id
|
39
|
+
end
|
40
|
+
|
41
|
+
allocate_gl_objects
|
42
|
+
populate_vertex_buffer
|
43
|
+
configure_vao
|
44
|
+
|
45
|
+
@objects.each { |o| @vertex_count += o.vertices.size }
|
46
|
+
|
47
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
48
|
+
# build_collision_tree
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse(parser)
|
52
|
+
parser.new(self).parse
|
53
|
+
end
|
54
|
+
|
55
|
+
def calculate_bounding_box(vertices, bounding_box)
|
56
|
+
unless bounding_box.min.x.is_a?(Float)
|
57
|
+
vertex = vertices.last
|
58
|
+
bounding_box.min.x = vertex.x
|
59
|
+
bounding_box.min.y = vertex.y
|
60
|
+
bounding_box.min.z = vertex.z
|
61
|
+
|
62
|
+
bounding_box.max.x = vertex.x
|
63
|
+
bounding_box.max.y = vertex.y
|
64
|
+
bounding_box.max.z = vertex.z
|
65
|
+
end
|
66
|
+
|
67
|
+
vertices.each do |vertex|
|
68
|
+
bounding_box.min.x = vertex.x if vertex.x <= bounding_box.min.x
|
69
|
+
bounding_box.min.y = vertex.y if vertex.y <= bounding_box.min.y
|
70
|
+
bounding_box.min.z = vertex.z if vertex.z <= bounding_box.min.z
|
71
|
+
|
72
|
+
bounding_box.max.x = vertex.x if vertex.x >= bounding_box.max.x
|
73
|
+
bounding_box.max.y = vertex.y if vertex.y >= bounding_box.max.y
|
74
|
+
bounding_box.max.z = vertex.z if vertex.z >= bounding_box.max.z
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def allocate_gl_objects
|
79
|
+
# Allocate arrays for future use
|
80
|
+
@vertex_array_id = nil
|
81
|
+
buffer = " " * 4
|
82
|
+
glGenVertexArrays(1, buffer)
|
83
|
+
@vertex_array_id = buffer.unpack1("L2")
|
84
|
+
|
85
|
+
# Allocate buffers for future use
|
86
|
+
@positions_buffer_id = nil
|
87
|
+
buffer = " " * 4
|
88
|
+
glGenBuffers(1, buffer)
|
89
|
+
@positions_buffer_id = buffer.unpack1("L2")
|
90
|
+
|
91
|
+
@colors_buffer_id = nil
|
92
|
+
buffer = " " * 4
|
93
|
+
glGenBuffers(1, buffer)
|
94
|
+
@colors_buffer_id = buffer.unpack1("L2")
|
95
|
+
|
96
|
+
@normals_buffer_id = nil
|
97
|
+
buffer = " " * 4
|
98
|
+
glGenBuffers(1, buffer)
|
99
|
+
@normals_buffer_id = buffer.unpack1("L2")
|
100
|
+
|
101
|
+
@uvs_buffer_id = nil
|
102
|
+
buffer = " " * 4
|
103
|
+
glGenBuffers(1, buffer)
|
104
|
+
@uvs_buffer_id = buffer.unpack1("L2")
|
105
|
+
end
|
106
|
+
|
107
|
+
def populate_vertex_buffer
|
108
|
+
pos = []
|
109
|
+
colors = []
|
110
|
+
norms = []
|
111
|
+
uvs = []
|
112
|
+
|
113
|
+
@faces.each do |face|
|
114
|
+
pos << face.vertices.map { |vert| [vert.x, vert.y, vert.z] }
|
115
|
+
colors << face.colors.map { |color| [color.red, color.green, color.blue] }
|
116
|
+
norms << face.normals.map { |vert| [vert.x, vert.y, vert.z, vert.weight] }
|
117
|
+
|
118
|
+
uvs << face.uvs.map { |vert| [vert.x, vert.y, vert.z] } if has_texture?
|
119
|
+
end
|
120
|
+
|
121
|
+
glBindBuffer(GL_ARRAY_BUFFER, @positions_buffer_id)
|
122
|
+
glBufferData(GL_ARRAY_BUFFER, pos.flatten.size * Fiddle::SIZEOF_FLOAT, pos.flatten.pack("f*"), GL_STATIC_DRAW)
|
123
|
+
|
124
|
+
glBindBuffer(GL_ARRAY_BUFFER, @colors_buffer_id)
|
125
|
+
glBufferData(GL_ARRAY_BUFFER, colors.flatten.size * Fiddle::SIZEOF_FLOAT, colors.flatten.pack("f*"),
|
126
|
+
GL_STATIC_DRAW)
|
127
|
+
|
128
|
+
glBindBuffer(GL_ARRAY_BUFFER, @normals_buffer_id)
|
129
|
+
glBufferData(GL_ARRAY_BUFFER, norms.flatten.size * Fiddle::SIZEOF_FLOAT, norms.flatten.pack("f*"), GL_STATIC_DRAW)
|
130
|
+
|
131
|
+
if has_texture?
|
132
|
+
glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id)
|
133
|
+
glBufferData(GL_ARRAY_BUFFER, uvs.flatten.size * Fiddle::SIZEOF_FLOAT, uvs.flatten.pack("f*"), GL_STATIC_DRAW)
|
134
|
+
end
|
135
|
+
|
136
|
+
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
137
|
+
end
|
138
|
+
|
139
|
+
def configure_vao
|
140
|
+
glBindVertexArray(@vertex_array_id)
|
141
|
+
gl_error?
|
142
|
+
|
143
|
+
# index, size, type, normalized, stride, pointer
|
144
|
+
# vertices (positions)
|
145
|
+
glBindBuffer(GL_ARRAY_BUFFER, @positions_buffer_id)
|
146
|
+
gl_error?
|
147
|
+
|
148
|
+
# inPosition
|
149
|
+
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nil)
|
150
|
+
gl_error?
|
151
|
+
# colors
|
152
|
+
glBindBuffer(GL_ARRAY_BUFFER, @colors_buffer_id)
|
153
|
+
# inColor
|
154
|
+
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nil)
|
155
|
+
gl_error?
|
156
|
+
# normals
|
157
|
+
glBindBuffer(GL_ARRAY_BUFFER, @normals_buffer_id)
|
158
|
+
# inNormal
|
159
|
+
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, nil)
|
160
|
+
gl_error?
|
161
|
+
|
162
|
+
if has_texture?
|
163
|
+
# uvs
|
164
|
+
glBindBuffer(GL_ARRAY_BUFFER, @uvs_buffer_id)
|
165
|
+
# inUV
|
166
|
+
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, nil)
|
167
|
+
gl_error?
|
168
|
+
end
|
169
|
+
|
170
|
+
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
171
|
+
glBindVertexArray(0)
|
172
|
+
end
|
173
|
+
|
174
|
+
def build_collision_tree
|
175
|
+
@aabb_tree = AABBTree.new
|
176
|
+
|
177
|
+
@faces.each do |face|
|
178
|
+
box = BoundingBox.new
|
179
|
+
box.min = face.vertices.first.dup
|
180
|
+
box.max = face.vertices.first.dup
|
181
|
+
|
182
|
+
face.vertices.each do |vertex|
|
183
|
+
if vertex.sum < box.min.sum
|
184
|
+
box.min = vertex.dup
|
185
|
+
elsif vertex.sum > box.max.sum
|
186
|
+
box.max = vertex.dup
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# FIXME: Handle negatives
|
191
|
+
box.min *= 1.5
|
192
|
+
box.max *= 1.5
|
193
|
+
@aabb_tree.insert(face, box)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def has_texture?
|
198
|
+
@has_texture
|
199
|
+
end
|
200
|
+
|
201
|
+
def release_gl_resources
|
202
|
+
if @vertex_array_id
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
class Model
|
3
|
+
class Material
|
4
|
+
attr_accessor :name, :ambient, :diffuse, :specular
|
5
|
+
attr_reader :texture_id
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
@ambient = Color.new(1, 1, 1, 1)
|
10
|
+
@diffuse = Color.new(1, 1, 1, 1)
|
11
|
+
@specular = Color.new(1, 1, 1, 1)
|
12
|
+
@texture = nil
|
13
|
+
@texture_id = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_texture(texture_path)
|
17
|
+
@texture_id = Texture.new(path: texture_path).id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
class Model
|
3
|
+
class ModelObject
|
4
|
+
attr_reader :id, :name, :vertices, :uvs, :normals, :materials, :bounding_box, :debug_color
|
5
|
+
attr_accessor :faces, :scale
|
6
|
+
|
7
|
+
def initialize(id, name)
|
8
|
+
@id = id
|
9
|
+
@name = name
|
10
|
+
@vertices = []
|
11
|
+
@uvs = []
|
12
|
+
@normals = []
|
13
|
+
@faces = []
|
14
|
+
@materials = []
|
15
|
+
@bounding_box = BoundingBox.new
|
16
|
+
@debug_color = Color.new(1.0, 1.0, 1.0)
|
17
|
+
|
18
|
+
@scale = 1.0
|
19
|
+
|
20
|
+
# Faces array packs everything:
|
21
|
+
# vertex = index[0]
|
22
|
+
# uv = index[1]
|
23
|
+
# normal = index[2]
|
24
|
+
# material = index[3]
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_texture?
|
28
|
+
@materials.find { |mat| mat.texture_id } ? true : false
|
29
|
+
end
|
30
|
+
|
31
|
+
def reflatten
|
32
|
+
@vertices_list = nil
|
33
|
+
@uvs_list = nil
|
34
|
+
@normals_list = nil
|
35
|
+
|
36
|
+
flattened_vertices
|
37
|
+
flattened_uvs
|
38
|
+
flattened_normals
|
39
|
+
end
|
40
|
+
|
41
|
+
def flattened_vertices
|
42
|
+
unless @vertices_list
|
43
|
+
@debug_color = @faces.first.material.diffuse
|
44
|
+
|
45
|
+
list = []
|
46
|
+
@faces.each do |face|
|
47
|
+
face.vertices.each do |v|
|
48
|
+
next unless v
|
49
|
+
|
50
|
+
list << v.x * @scale
|
51
|
+
list << v.y * @scale
|
52
|
+
list << v.z * @scale
|
53
|
+
list << v.weight
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
@vertices_list_size = list.size
|
58
|
+
@vertices_list = list.pack("f*")
|
59
|
+
end
|
60
|
+
|
61
|
+
@vertices_list
|
62
|
+
end
|
63
|
+
|
64
|
+
def flattened_vertices_size
|
65
|
+
@vertices_list_size
|
66
|
+
end
|
67
|
+
|
68
|
+
def flattened_uvs
|
69
|
+
unless @uvs_list
|
70
|
+
list = []
|
71
|
+
@faces.each do |face|
|
72
|
+
face.uvs.each do |v|
|
73
|
+
next unless v
|
74
|
+
|
75
|
+
list << v.x
|
76
|
+
list << v.y
|
77
|
+
list << v.z
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
@uvs_list_size = list.size
|
82
|
+
@uvs_list = list.pack("f*")
|
83
|
+
end
|
84
|
+
|
85
|
+
@uvs_list
|
86
|
+
end
|
87
|
+
|
88
|
+
def flattened_normals
|
89
|
+
unless @normals_list
|
90
|
+
list = []
|
91
|
+
@faces.each do |face|
|
92
|
+
face.normals.each do |n|
|
93
|
+
next unless n
|
94
|
+
|
95
|
+
list << n.x
|
96
|
+
list << n.y
|
97
|
+
list << n.z
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
@normals_list_size = list.size
|
102
|
+
@normals_list = list.pack("f*")
|
103
|
+
end
|
104
|
+
|
105
|
+
@normals_list
|
106
|
+
end
|
107
|
+
|
108
|
+
def flattened_materials
|
109
|
+
unless @materials_list
|
110
|
+
list = []
|
111
|
+
@faces.each do |face|
|
112
|
+
material = face.material
|
113
|
+
next unless material
|
114
|
+
|
115
|
+
face.vertices.each do # Add material to each vertex
|
116
|
+
list << material.diffuse.red
|
117
|
+
list << material.diffuse.green
|
118
|
+
list << material.diffuse.blue
|
119
|
+
# list << material.alpha
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
@materials_list_size = list.size
|
124
|
+
@materials_list = list.pack("f*")
|
125
|
+
end
|
126
|
+
|
127
|
+
@materials_list
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module CyberarmEngine
|
2
|
+
TextureCoordinate = Struct.new(:u, :v, :weight)
|
3
|
+
Point = Struct.new(:x, :y)
|
4
|
+
Color = Struct.new(:red, :green, :blue, :alpha)
|
5
|
+
Face = Struct.new(:vertices, :uvs, :normals, :colors, :material, :smoothing)
|
6
|
+
|
7
|
+
class Model
|
8
|
+
class Parser
|
9
|
+
@@parsers = []
|
10
|
+
|
11
|
+
def self.handles
|
12
|
+
raise NotImplementedError,
|
13
|
+
"Model::Parser#handles must return an array of file extensions that this parser supports"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.inherited(parser)
|
17
|
+
@@parsers << parser
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find(file_type)
|
21
|
+
@@parsers.find do |parser|
|
22
|
+
parser.handles.include?(file_type)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.supported_formats
|
27
|
+
@@parsers.map { |parser| parser.handles }.flatten.map { |s| ".#{s}" }.join(", ")
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(model)
|
31
|
+
@model = model
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_object(id: nil, name: nil)
|
38
|
+
_model = nil
|
39
|
+
|
40
|
+
if id
|
41
|
+
_model = @model.objects.find { |o| o.id == id }
|
42
|
+
elsif name
|
43
|
+
_model = @model.objects.find { |o| o.name == name }
|
44
|
+
else
|
45
|
+
raise "Must provide either an id: or name:"
|
46
|
+
end
|
47
|
+
|
48
|
+
if _model
|
49
|
+
@model.current_object = _model
|
50
|
+
else
|
51
|
+
raise "Couldn't find ModelObject!"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def change_object(id, name)
|
56
|
+
@model.objects << Model::ModelObject.new(id, name)
|
57
|
+
@model.current_object = @model.objects.last
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_material(name)
|
61
|
+
@model.current_material = name
|
62
|
+
@model.current_object.materials << current_material
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_material(name, material)
|
66
|
+
@model.materials[name] = material
|
67
|
+
end
|
68
|
+
|
69
|
+
def current_material
|
70
|
+
@model.materials[@model.current_material]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|