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