cyberarm_engine 0.19.0 → 0.19.1

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +7 -7
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +74 -74
  8. data/Rakefile +10 -10
  9. data/bin/console +14 -14
  10. data/bin/setup +8 -8
  11. data/cyberarm_engine.gemspec +39 -39
  12. data/lib/cyberarm_engine/animator.rb +219 -219
  13. data/lib/cyberarm_engine/background.rb +179 -179
  14. data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
  15. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  16. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  17. data/lib/cyberarm_engine/cache/download_manager.rb +121 -121
  18. data/lib/cyberarm_engine/cache.rb +4 -4
  19. data/lib/cyberarm_engine/common.rb +113 -113
  20. data/lib/cyberarm_engine/config_file.rb +46 -46
  21. data/lib/cyberarm_engine/console/command.rb +157 -157
  22. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  23. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  24. data/lib/cyberarm_engine/console.rb +248 -248
  25. data/lib/cyberarm_engine/game_object.rb +248 -248
  26. data/lib/cyberarm_engine/game_state.rb +97 -97
  27. data/lib/cyberarm_engine/model/material.rb +21 -21
  28. data/lib/cyberarm_engine/model/model_object.rb +131 -131
  29. data/lib/cyberarm_engine/model/parser.rb +74 -74
  30. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  31. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  32. data/lib/cyberarm_engine/model.rb +212 -212
  33. data/lib/cyberarm_engine/model_cache.rb +31 -31
  34. data/lib/cyberarm_engine/opengl/light.rb +50 -50
  35. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  36. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -38
  37. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  38. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -164
  39. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +298 -298
  40. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -22
  41. data/lib/cyberarm_engine/opengl/shader.rb +406 -406
  42. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  43. data/lib/cyberarm_engine/opengl.rb +28 -28
  44. data/lib/cyberarm_engine/ray.rb +56 -56
  45. data/lib/cyberarm_engine/stats.rb +21 -21
  46. data/lib/cyberarm_engine/text.rb +197 -197
  47. data/lib/cyberarm_engine/timer.rb +23 -23
  48. data/lib/cyberarm_engine/transform.rb +296 -296
  49. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  50. data/lib/cyberarm_engine/ui/dsl.rb +139 -139
  51. data/lib/cyberarm_engine/ui/element.rb +488 -488
  52. data/lib/cyberarm_engine/ui/elements/button.rb +97 -97
  53. data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
  54. data/lib/cyberarm_engine/ui/elements/container.rb +256 -256
  55. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
  56. data/lib/cyberarm_engine/ui/elements/edit_line.rb +263 -263
  57. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  58. data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
  59. data/lib/cyberarm_engine/ui/elements/list_box.rb +88 -82
  60. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -51
  61. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  62. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -104
  63. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  64. data/lib/cyberarm_engine/ui/elements/text_block.rb +162 -162
  65. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -65
  66. data/lib/cyberarm_engine/ui/event.rb +54 -54
  67. data/lib/cyberarm_engine/ui/gui_state.rb +256 -256
  68. data/lib/cyberarm_engine/ui/style.rb +49 -49
  69. data/lib/cyberarm_engine/ui/theme.rb +207 -207
  70. data/lib/cyberarm_engine/vector.rb +293 -293
  71. data/lib/cyberarm_engine/version.rb +4 -4
  72. data/lib/cyberarm_engine/window.rb +120 -120
  73. data/lib/cyberarm_engine.rb +71 -71
  74. metadata +3 -3
@@ -1,296 +1,296 @@
1
- module CyberarmEngine
2
- # Basic 4x4 matrix operations
3
- class Transform
4
- attr_reader :elements
5
-
6
- def initialize(matrix)
7
- @elements = matrix
8
-
9
- raise "Transform is wrong size! Got #{@elements.size}, expected 16" if 16 != @elements.size
10
- raise "Invalid value for matrix, must all be numeric!" if @elements.any? { |e| e.nil? || !e.is_a?(Numeric) }
11
- end
12
-
13
- def self.identity
14
- Transform.new(
15
- [
16
- 1, 0, 0, 0,
17
- 0, 1, 0, 0,
18
- 0, 0, 1, 0,
19
- 0, 0, 0, 1
20
- ]
21
- )
22
- end
23
-
24
- ### 2D Operations meant for interacting with Gosu ###
25
-
26
- # 2d rotate operation, replicates Gosu's Gosu.rotate function
27
- def self.rotate(angle, rotate_around = nil)
28
- double c = Math.cos(angle).degrees_to_radians
29
- double s = Math.sin(angle).degrees_to_radians
30
- matrix = [
31
- +c, +s, 0, 0,
32
- -s, +c, 0, 0,
33
- 0, 0, 1, 0,
34
- 0, 0, 0, 1
35
- ]
36
-
37
- rotate_matrix = Transform.new(matrix, rows: 4, columns: 4)
38
-
39
- if rotate_around && (rotate_around.x != 0.0 || rotate_around.y != 0.0)
40
- negative_rotate_around = Vector.new(-rotate_around.x, -rotate_around.y, -rotate_around.z)
41
-
42
- rotate_matrix = concat(
43
- concat(translate(negative_rotate_around), rotate_matrix),
44
- translate(rotate_around)
45
- )
46
- end
47
-
48
- rotate_matrix
49
- end
50
-
51
- # 2d translate operation, replicates Gosu's Gosu.translate function
52
- def self.translate(vector)
53
- x, y, z = vector.to_a[0..2]
54
- matrix = [
55
- 1, 0, 0, 0,
56
- 0, 1, 0, 0,
57
- 0, 0, 1, 0,
58
- x, y, z, 1
59
- ]
60
-
61
- Transform.new(matrix)
62
- end
63
-
64
- # 2d scale operation, replicates Gosu's Gosu.rotate function
65
- def self.scale(vector, center_around = nil)
66
- scale_x, scale_y, scale_z = vector.to_a[0..2]
67
- matrix = [
68
- scale_x, 0, 0, 0,
69
- 0, scale_y, 0, 0,
70
- 0, 0, scale_z, 0,
71
- 0, 0, 0, 1
72
- ]
73
-
74
- scale_matrix = Transform.new(matrix)
75
-
76
- if center_around && (center_around.x != 0.0 || center_around.y != 0.0)
77
- negative_center_around = Vector.new(-center_around.x, -center_around.y, -center_around.z)
78
-
79
- scale_matrix = concat(
80
- concat(translate(negative_center_around), scale_matrix),
81
- translate(center_around)
82
- )
83
- end
84
-
85
- scale_matrix
86
- end
87
-
88
- def self.concat(left, right)
89
- matrix = Array.new(left.elements.size)
90
- rows = 4
91
-
92
- matrix.size.times do |i|
93
- matrix[i] = 0
94
-
95
- rows.times do |j|
96
- matrix[i] += left.elements[i / rows * rows + j] * right.elements[i % rows + j * rows]
97
- end
98
- end
99
-
100
- Transform.new(matrix)
101
- end
102
-
103
- #### 3D Operations meant for OpenGL ###
104
-
105
- def self.translate_3d(vector)
106
- x, y, z = vector.to_a[0..2]
107
- matrix = [
108
- 1, 0, 0, x,
109
- 0, 1, 0, y,
110
- 0, 0, 1, z,
111
- 0, 0, 0, 1
112
- ]
113
-
114
- Transform.new(matrix)
115
- end
116
-
117
- def self.rotate_3d(vector, _order = "zyx")
118
- x, y, z = vector.to_a[0..2].map { |axis| axis * Math::PI / 180.0 }
119
-
120
- rotation_x = Transform.new(
121
- [
122
- 1, 0, 0, 0,
123
- 0, Math.cos(x), -Math.sin(x), 0,
124
- 0, Math.sin(x), Math.cos(x), 0,
125
- 0, 0, 0, 1
126
- ]
127
- )
128
-
129
- rotation_y = Transform.new(
130
- [
131
- Math.cos(y), 0, Math.sin(y), 0,
132
- 0, 1, 0, 0,
133
- -Math.sin(y), 0, Math.cos(y), 0,
134
- 0, 0, 0, 1
135
- ]
136
- )
137
-
138
- rotation_z = Transform.new(
139
- [
140
- Math.cos(z), -Math.sin(z), 0, 0,
141
- Math.sin(z), Math.cos(z), 0, 0,
142
- 0, 0, 1, 0,
143
- 0, 0, 0, 1
144
- ]
145
- )
146
-
147
- rotation_z * rotation_y * rotation_x
148
- end
149
-
150
- # Implements glRotatef
151
- # https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml
152
- def self.rotate_gl(angle, axis)
153
- radians = angle * Math::PI / 180.0
154
- s = Math.sin(radians)
155
- c = Math.cos(radians)
156
-
157
- axis = axis.normalized
158
- x, y, z = axis.to_a[0..2]
159
-
160
- n = (1.0 - c)
161
-
162
- Transform.new(
163
- [
164
- x * x * n + c, x * y * n - z * s, x * z * n + y * s, 0,
165
- y * x * n + z * s, y * y * n + c, y * z * n - x * s, 0,
166
- x * z * n - y * s, y * z * n + x * s, z * z * n + c, 0,
167
- 0, 0, 0, 1.0
168
- ]
169
- )
170
- end
171
-
172
- def self.scale_3d(vector)
173
- x, y, z = vector.to_a[0..2]
174
-
175
- Transform.new(
176
- [
177
- x, 0, 0, 0,
178
- 0, y, 0, 0,
179
- 0, 0, z, 0,
180
- 0, 0, 0, 1
181
- ]
182
- )
183
- end
184
-
185
- def self.perspective(fov_y, aspect_ratio, near, far)
186
- f = 1.0 / Math.tan(fov_y.degrees_to_radians / 2.0) # cotangent
187
- zn = (far + near.to_f) / (near - far.to_f)
188
- zf = (2.0 * far * near.to_f) / (near - far.to_f)
189
-
190
- Transform.new(
191
- [
192
- f / aspect_ratio, 0.0, 0.0, 0.0,
193
- 0.0, f, 0.0, 0.0,
194
- 0.0, 0.0, zn, zf,
195
- 0.0, 0.0, -1.0, 0.0
196
- ]
197
- )
198
- end
199
-
200
- def self.orthographic(left, right, bottom, top, near, far)
201
- s = Vector.new(
202
- 2 / (right - left.to_f),
203
- 2 / (top - bottom.to_f),
204
- -2 / (far - near.to_f)
205
- )
206
-
207
- t = Vector.new(
208
- (right + left.to_f) / (right - left.to_f),
209
- (top + bottom.to_f) / (top - bottom.to_f),
210
- (far + near.to_f) / (far - near.to_f)
211
- )
212
-
213
- Transform.new(
214
- [
215
- s.x, 0.0, 0.0, t.x,
216
- 0.0, s.y, 0.0, t.y,
217
- 0.0, 0.0, s.z, t.z,
218
- 0.0, 0.0, 0.0, 1.0
219
- ]
220
- )
221
- end
222
-
223
- def self.view(eye, orientation)
224
- # https://www.3dgep.com/understanding-the-view-matrix/#The_View_Matrix
225
- cosPitch = Math.cos(orientation.z * Math::PI / 180.0)
226
- sinPitch = Math.sin(orientation.z * Math::PI / 180.0)
227
- cosYaw = Math.cos(orientation.y * Math::PI / 180.0)
228
- sinYaw = Math.sin(orientation.y * Math::PI / 180.0)
229
-
230
- x_axis = Vector.new(cosYaw, 0, -sinYaw)
231
- y_axis = Vector.new(sinYaw * sinPitch, cosPitch, cosYaw * sinPitch)
232
- z_axis = Vector.new(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw)
233
-
234
- Transform.new(
235
- [
236
- x_axis.x, y_axis.y, z_axis.z, 0,
237
- x_axis.x, y_axis.y, z_axis.z, 0,
238
- x_axis.x, y_axis.y, z_axis.z, 0,
239
- -x_axis.dot(eye), -y_axis.dot(eye), -z_axis.dot(eye), 1
240
- ]
241
- )
242
- end
243
-
244
- def *(other)
245
- case other
246
- when CyberarmEngine::Vector
247
- matrix = @elements.clone
248
- list = other.to_a
249
-
250
- @elements.each_with_index do |e, i|
251
- matrix[i] = e + list[i % 4]
252
- end
253
-
254
- Transform.new(matrix)
255
-
256
- when CyberarmEngine::Transform
257
- multiply_matrices(other)
258
- else
259
- p other.class
260
- raise TypeError, "Expected CyberarmEngine::Vector or CyberarmEngine::Transform got #{other.class}"
261
- end
262
- end
263
-
264
- def get(x, y)
265
- width = 4
266
-
267
- # puts "Transform|#{self.object_id} -> #{@elements[width * y + x].inspect} (index: #{width * y + x})"
268
- @elements[width * y + x]
269
- end
270
-
271
- def multiply_matrices(other)
272
- matrix = Array.new(16, 0)
273
-
274
- 4.times do |x|
275
- 4.times do |y|
276
- 4.times do |k|
277
- matrix[4 * y + x] += get(x, k) * other.get(k, y)
278
- end
279
- end
280
- end
281
-
282
- Transform.new(matrix)
283
- end
284
-
285
- # arranges Matrix in column major form
286
- def to_gl
287
- e = @elements
288
- [
289
- e[0], e[4], e[8], e[12],
290
- e[1], e[5], e[9], e[13],
291
- e[2], e[6], e[10], e[14],
292
- e[3], e[7], e[11], e[15]
293
- ]
294
- end
295
- end
296
- end
1
+ module CyberarmEngine
2
+ # Basic 4x4 matrix operations
3
+ class Transform
4
+ attr_reader :elements
5
+
6
+ def initialize(matrix)
7
+ @elements = matrix
8
+
9
+ raise "Transform is wrong size! Got #{@elements.size}, expected 16" if 16 != @elements.size
10
+ raise "Invalid value for matrix, must all be numeric!" if @elements.any? { |e| e.nil? || !e.is_a?(Numeric) }
11
+ end
12
+
13
+ def self.identity
14
+ Transform.new(
15
+ [
16
+ 1, 0, 0, 0,
17
+ 0, 1, 0, 0,
18
+ 0, 0, 1, 0,
19
+ 0, 0, 0, 1
20
+ ]
21
+ )
22
+ end
23
+
24
+ ### 2D Operations meant for interacting with Gosu ###
25
+
26
+ # 2d rotate operation, replicates Gosu's Gosu.rotate function
27
+ def self.rotate(angle, rotate_around = nil)
28
+ double c = Math.cos(angle).degrees_to_radians
29
+ double s = Math.sin(angle).degrees_to_radians
30
+ matrix = [
31
+ +c, +s, 0, 0,
32
+ -s, +c, 0, 0,
33
+ 0, 0, 1, 0,
34
+ 0, 0, 0, 1
35
+ ]
36
+
37
+ rotate_matrix = Transform.new(matrix, rows: 4, columns: 4)
38
+
39
+ if rotate_around && (rotate_around.x != 0.0 || rotate_around.y != 0.0)
40
+ negative_rotate_around = Vector.new(-rotate_around.x, -rotate_around.y, -rotate_around.z)
41
+
42
+ rotate_matrix = concat(
43
+ concat(translate(negative_rotate_around), rotate_matrix),
44
+ translate(rotate_around)
45
+ )
46
+ end
47
+
48
+ rotate_matrix
49
+ end
50
+
51
+ # 2d translate operation, replicates Gosu's Gosu.translate function
52
+ def self.translate(vector)
53
+ x, y, z = vector.to_a[0..2]
54
+ matrix = [
55
+ 1, 0, 0, 0,
56
+ 0, 1, 0, 0,
57
+ 0, 0, 1, 0,
58
+ x, y, z, 1
59
+ ]
60
+
61
+ Transform.new(matrix)
62
+ end
63
+
64
+ # 2d scale operation, replicates Gosu's Gosu.rotate function
65
+ def self.scale(vector, center_around = nil)
66
+ scale_x, scale_y, scale_z = vector.to_a[0..2]
67
+ matrix = [
68
+ scale_x, 0, 0, 0,
69
+ 0, scale_y, 0, 0,
70
+ 0, 0, scale_z, 0,
71
+ 0, 0, 0, 1
72
+ ]
73
+
74
+ scale_matrix = Transform.new(matrix)
75
+
76
+ if center_around && (center_around.x != 0.0 || center_around.y != 0.0)
77
+ negative_center_around = Vector.new(-center_around.x, -center_around.y, -center_around.z)
78
+
79
+ scale_matrix = concat(
80
+ concat(translate(negative_center_around), scale_matrix),
81
+ translate(center_around)
82
+ )
83
+ end
84
+
85
+ scale_matrix
86
+ end
87
+
88
+ def self.concat(left, right)
89
+ matrix = Array.new(left.elements.size)
90
+ rows = 4
91
+
92
+ matrix.size.times do |i|
93
+ matrix[i] = 0
94
+
95
+ rows.times do |j|
96
+ matrix[i] += left.elements[i / rows * rows + j] * right.elements[i % rows + j * rows]
97
+ end
98
+ end
99
+
100
+ Transform.new(matrix)
101
+ end
102
+
103
+ #### 3D Operations meant for OpenGL ###
104
+
105
+ def self.translate_3d(vector)
106
+ x, y, z = vector.to_a[0..2]
107
+ matrix = [
108
+ 1, 0, 0, x,
109
+ 0, 1, 0, y,
110
+ 0, 0, 1, z,
111
+ 0, 0, 0, 1
112
+ ]
113
+
114
+ Transform.new(matrix)
115
+ end
116
+
117
+ def self.rotate_3d(vector, _order = "zyx")
118
+ x, y, z = vector.to_a[0..2].map { |axis| axis * Math::PI / 180.0 }
119
+
120
+ rotation_x = Transform.new(
121
+ [
122
+ 1, 0, 0, 0,
123
+ 0, Math.cos(x), -Math.sin(x), 0,
124
+ 0, Math.sin(x), Math.cos(x), 0,
125
+ 0, 0, 0, 1
126
+ ]
127
+ )
128
+
129
+ rotation_y = Transform.new(
130
+ [
131
+ Math.cos(y), 0, Math.sin(y), 0,
132
+ 0, 1, 0, 0,
133
+ -Math.sin(y), 0, Math.cos(y), 0,
134
+ 0, 0, 0, 1
135
+ ]
136
+ )
137
+
138
+ rotation_z = Transform.new(
139
+ [
140
+ Math.cos(z), -Math.sin(z), 0, 0,
141
+ Math.sin(z), Math.cos(z), 0, 0,
142
+ 0, 0, 1, 0,
143
+ 0, 0, 0, 1
144
+ ]
145
+ )
146
+
147
+ rotation_z * rotation_y * rotation_x
148
+ end
149
+
150
+ # Implements glRotatef
151
+ # https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml
152
+ def self.rotate_gl(angle, axis)
153
+ radians = angle * Math::PI / 180.0
154
+ s = Math.sin(radians)
155
+ c = Math.cos(radians)
156
+
157
+ axis = axis.normalized
158
+ x, y, z = axis.to_a[0..2]
159
+
160
+ n = (1.0 - c)
161
+
162
+ Transform.new(
163
+ [
164
+ x * x * n + c, x * y * n - z * s, x * z * n + y * s, 0,
165
+ y * x * n + z * s, y * y * n + c, y * z * n - x * s, 0,
166
+ x * z * n - y * s, y * z * n + x * s, z * z * n + c, 0,
167
+ 0, 0, 0, 1.0
168
+ ]
169
+ )
170
+ end
171
+
172
+ def self.scale_3d(vector)
173
+ x, y, z = vector.to_a[0..2]
174
+
175
+ Transform.new(
176
+ [
177
+ x, 0, 0, 0,
178
+ 0, y, 0, 0,
179
+ 0, 0, z, 0,
180
+ 0, 0, 0, 1
181
+ ]
182
+ )
183
+ end
184
+
185
+ def self.perspective(fov_y, aspect_ratio, near, far)
186
+ f = 1.0 / Math.tan(fov_y.degrees_to_radians / 2.0) # cotangent
187
+ zn = (far + near.to_f) / (near - far.to_f)
188
+ zf = (2.0 * far * near.to_f) / (near - far.to_f)
189
+
190
+ Transform.new(
191
+ [
192
+ f / aspect_ratio, 0.0, 0.0, 0.0,
193
+ 0.0, f, 0.0, 0.0,
194
+ 0.0, 0.0, zn, zf,
195
+ 0.0, 0.0, -1.0, 0.0
196
+ ]
197
+ )
198
+ end
199
+
200
+ def self.orthographic(left, right, bottom, top, near, far)
201
+ s = Vector.new(
202
+ 2 / (right - left.to_f),
203
+ 2 / (top - bottom.to_f),
204
+ -2 / (far - near.to_f)
205
+ )
206
+
207
+ t = Vector.new(
208
+ (right + left.to_f) / (right - left.to_f),
209
+ (top + bottom.to_f) / (top - bottom.to_f),
210
+ (far + near.to_f) / (far - near.to_f)
211
+ )
212
+
213
+ Transform.new(
214
+ [
215
+ s.x, 0.0, 0.0, t.x,
216
+ 0.0, s.y, 0.0, t.y,
217
+ 0.0, 0.0, s.z, t.z,
218
+ 0.0, 0.0, 0.0, 1.0
219
+ ]
220
+ )
221
+ end
222
+
223
+ def self.view(eye, orientation)
224
+ # https://www.3dgep.com/understanding-the-view-matrix/#The_View_Matrix
225
+ cosPitch = Math.cos(orientation.z * Math::PI / 180.0)
226
+ sinPitch = Math.sin(orientation.z * Math::PI / 180.0)
227
+ cosYaw = Math.cos(orientation.y * Math::PI / 180.0)
228
+ sinYaw = Math.sin(orientation.y * Math::PI / 180.0)
229
+
230
+ x_axis = Vector.new(cosYaw, 0, -sinYaw)
231
+ y_axis = Vector.new(sinYaw * sinPitch, cosPitch, cosYaw * sinPitch)
232
+ z_axis = Vector.new(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw)
233
+
234
+ Transform.new(
235
+ [
236
+ x_axis.x, y_axis.y, z_axis.z, 0,
237
+ x_axis.x, y_axis.y, z_axis.z, 0,
238
+ x_axis.x, y_axis.y, z_axis.z, 0,
239
+ -x_axis.dot(eye), -y_axis.dot(eye), -z_axis.dot(eye), 1
240
+ ]
241
+ )
242
+ end
243
+
244
+ def *(other)
245
+ case other
246
+ when CyberarmEngine::Vector
247
+ matrix = @elements.clone
248
+ list = other.to_a
249
+
250
+ @elements.each_with_index do |e, i|
251
+ matrix[i] = e + list[i % 4]
252
+ end
253
+
254
+ Transform.new(matrix)
255
+
256
+ when CyberarmEngine::Transform
257
+ multiply_matrices(other)
258
+ else
259
+ p other.class
260
+ raise TypeError, "Expected CyberarmEngine::Vector or CyberarmEngine::Transform got #{other.class}"
261
+ end
262
+ end
263
+
264
+ def get(x, y)
265
+ width = 4
266
+
267
+ # puts "Transform|#{self.object_id} -> #{@elements[width * y + x].inspect} (index: #{width * y + x})"
268
+ @elements[width * y + x]
269
+ end
270
+
271
+ def multiply_matrices(other)
272
+ matrix = Array.new(16, 0)
273
+
274
+ 4.times do |x|
275
+ 4.times do |y|
276
+ 4.times do |k|
277
+ matrix[4 * y + x] += get(x, k) * other.get(k, y)
278
+ end
279
+ end
280
+ end
281
+
282
+ Transform.new(matrix)
283
+ end
284
+
285
+ # arranges Matrix in column major form
286
+ def to_gl
287
+ e = @elements
288
+ [
289
+ e[0], e[4], e[8], e[12],
290
+ e[1], e[5], e[9], e[13],
291
+ e[2], e[6], e[10], e[14],
292
+ e[3], e[7], e[11], e[15]
293
+ ]
294
+ end
295
+ end
296
+ end