cyberarm_engine 0.25.0 → 0.25.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 (94) 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/Gemfile.lock +25 -25
  7. data/LICENSE.txt +21 -21
  8. data/README.md +74 -74
  9. data/Rakefile +10 -10
  10. data/assets/shaders/fragment/g_buffer.glsl +30 -30
  11. data/assets/shaders/fragment/lighting.glsl +115 -115
  12. data/assets/shaders/include/light_struct.glsl +11 -11
  13. data/assets/shaders/include/material_struct.glsl +16 -16
  14. data/assets/shaders/vertex/g_buffer.glsl +28 -28
  15. data/assets/shaders/vertex/lighting.glsl +24 -24
  16. data/bin/console +14 -14
  17. data/bin/setup +8 -8
  18. data/cyberarm_engine.gemspec +36 -36
  19. data/lib/cyberarm_engine/animator.rb +219 -219
  20. data/lib/cyberarm_engine/background.rb +158 -158
  21. data/lib/cyberarm_engine/background_image.rb +93 -93
  22. data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
  23. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  24. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  25. data/lib/cyberarm_engine/cache/download_manager.rb +123 -123
  26. data/lib/cyberarm_engine/cache.rb +4 -4
  27. data/lib/cyberarm_engine/common.rb +131 -131
  28. data/lib/cyberarm_engine/config_file.rb +46 -46
  29. data/lib/cyberarm_engine/console/command.rb +157 -157
  30. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  31. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  32. data/lib/cyberarm_engine/console.rb +248 -248
  33. data/lib/cyberarm_engine/game_object.rb +244 -244
  34. data/lib/cyberarm_engine/game_state.rb +124 -124
  35. data/lib/cyberarm_engine/gosu_ext/draw_arc.rb +111 -111
  36. data/lib/cyberarm_engine/gosu_ext/draw_circle.rb +30 -30
  37. data/lib/cyberarm_engine/gosu_ext/draw_path.rb +17 -17
  38. data/lib/cyberarm_engine/model/material.rb +21 -21
  39. data/lib/cyberarm_engine/model/mesh.rb +131 -131
  40. data/lib/cyberarm_engine/model/parser.rb +74 -74
  41. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  42. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  43. data/lib/cyberarm_engine/model.rb +216 -216
  44. data/lib/cyberarm_engine/model_cache.rb +31 -31
  45. data/lib/cyberarm_engine/notification.rb +82 -82
  46. data/lib/cyberarm_engine/notification_manager.rb +241 -241
  47. data/lib/cyberarm_engine/opengl/light.rb +52 -52
  48. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  49. data/lib/cyberarm_engine/opengl/perspective_camera.rb +41 -41
  50. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  51. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +167 -167
  52. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +307 -307
  53. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +33 -33
  54. data/lib/cyberarm_engine/opengl/shader.rb +408 -408
  55. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  56. data/lib/cyberarm_engine/opengl.rb +53 -53
  57. data/lib/cyberarm_engine/ray.rb +56 -56
  58. data/lib/cyberarm_engine/result.rb +20 -0
  59. data/lib/cyberarm_engine/stats.rb +200 -200
  60. data/lib/cyberarm_engine/text.rb +260 -260
  61. data/lib/cyberarm_engine/timer.rb +23 -23
  62. data/lib/cyberarm_engine/transform.rb +296 -296
  63. data/lib/cyberarm_engine/trees/aabb_node.rb +126 -126
  64. data/lib/cyberarm_engine/trees/aabb_tree.rb +55 -55
  65. data/lib/cyberarm_engine/trees/aabb_tree_debug.rb +29 -29
  66. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  67. data/lib/cyberarm_engine/ui/dsl.rb +142 -142
  68. data/lib/cyberarm_engine/ui/element.rb +662 -662
  69. data/lib/cyberarm_engine/ui/elements/button.rb +100 -100
  70. data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
  71. data/lib/cyberarm_engine/ui/elements/container.rb +407 -407
  72. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
  73. data/lib/cyberarm_engine/ui/elements/edit_line.rb +297 -297
  74. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  75. data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
  76. data/lib/cyberarm_engine/ui/elements/list_box.rb +79 -79
  77. data/lib/cyberarm_engine/ui/elements/menu.rb +27 -27
  78. data/lib/cyberarm_engine/ui/elements/menu_item.rb +6 -6
  79. data/lib/cyberarm_engine/ui/elements/progress.rb +93 -93
  80. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  81. data/lib/cyberarm_engine/ui/elements/slider.rb +107 -107
  82. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  83. data/lib/cyberarm_engine/ui/elements/text_block.rb +222 -222
  84. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +67 -67
  85. data/lib/cyberarm_engine/ui/event.rb +54 -54
  86. data/lib/cyberarm_engine/ui/gui_state.rb +326 -326
  87. data/lib/cyberarm_engine/ui/style.rb +61 -61
  88. data/lib/cyberarm_engine/ui/theme.rb +225 -225
  89. data/lib/cyberarm_engine/vector.rb +312 -312
  90. data/lib/cyberarm_engine/version.rb +4 -4
  91. data/lib/cyberarm_engine/window.rb +195 -195
  92. data/lib/cyberarm_engine.rb +77 -76
  93. data/mrbgem.rake +29 -29
  94. metadata +4 -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