mittsu 0.1.1 → 0.1.2

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +1 -1
  4. data/lib/mittsu/cameras/orthographic_camera.rb +13 -0
  5. data/lib/mittsu/cameras/perspective_camera.rb +11 -0
  6. data/lib/mittsu/core/geometry.rb +12 -9
  7. data/lib/mittsu/core/object_3d.rb +33 -66
  8. data/lib/mittsu/lights/ambient_light.rb +8 -0
  9. data/lib/mittsu/lights/directional_light.rb +9 -0
  10. data/lib/mittsu/lights/hemisphere_light.rb +9 -0
  11. data/lib/mittsu/lights/point_light.rb +11 -0
  12. data/lib/mittsu/lights/spot_light.rb +13 -0
  13. data/lib/mittsu/loaders.rb +1 -0
  14. data/lib/mittsu/loaders/mtl_loader.rb +5 -12
  15. data/lib/mittsu/loaders/obj_loader.rb +212 -0
  16. data/lib/mittsu/loaders/obj_mtl_loader.rb +11 -207
  17. data/lib/mittsu/materials/material.rb +5 -2
  18. data/lib/mittsu/materials/mesh_basic_material.rb +0 -9
  19. data/lib/mittsu/math/color.rb +44 -104
  20. data/lib/mittsu/math/matrix3.rb +8 -1
  21. data/lib/mittsu/math/matrix4.rb +6 -0
  22. data/lib/mittsu/math/vector.rb +251 -0
  23. data/lib/mittsu/math/vector2.rb +14 -213
  24. data/lib/mittsu/math/vector3.rb +61 -351
  25. data/lib/mittsu/math/vector4.rb +45 -295
  26. data/lib/mittsu/objects/line.rb +12 -2
  27. data/lib/mittsu/objects/mesh.rb +18 -9
  28. data/lib/mittsu/renderers/glfw_window.rb +15 -13
  29. data/lib/mittsu/renderers/opengl/core/opengl_geometry.rb +253 -0
  30. data/lib/mittsu/renderers/opengl/core/opengl_object_3d.rb +131 -0
  31. data/lib/mittsu/renderers/opengl/lights/opengl_ambient_light.rb +26 -0
  32. data/lib/mittsu/renderers/opengl/lights/opengl_directional_light.rb +35 -0
  33. data/lib/mittsu/renderers/opengl/lights/opengl_hemisphere_light.rb +42 -0
  34. data/lib/mittsu/renderers/opengl/lights/opengl_light.rb +52 -0
  35. data/lib/mittsu/renderers/opengl/lights/opengl_point_light.rb +36 -0
  36. data/lib/mittsu/renderers/opengl/lights/opengl_spot_light.rb +47 -0
  37. data/lib/mittsu/renderers/opengl/materials/opengl_line_basic_material.rb +16 -0
  38. data/lib/mittsu/renderers/opengl/materials/opengl_material.rb +275 -0
  39. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_basic_material.rb +69 -0
  40. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_lambert_material.rb +29 -0
  41. data/lib/mittsu/renderers/opengl/materials/opengl_mesh_phong_material.rb +40 -0
  42. data/lib/mittsu/renderers/opengl/materials/opengl_shader_material.rb +11 -0
  43. data/lib/mittsu/renderers/opengl/objects/opengl_group.rb +8 -0
  44. data/lib/mittsu/renderers/opengl/objects/opengl_line.rb +54 -0
  45. data/lib/mittsu/renderers/opengl/objects/opengl_mesh.rb +77 -0
  46. data/lib/mittsu/renderers/opengl/opengl_buffer.rb +5 -0
  47. data/lib/mittsu/renderers/opengl/opengl_debug.rb +49 -7
  48. data/lib/mittsu/renderers/opengl/opengl_default_target.rb +54 -0
  49. data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +763 -0
  50. data/lib/mittsu/renderers/opengl/opengl_geometry_like.rb +130 -0
  51. data/lib/mittsu/renderers/opengl/opengl_helper.rb +161 -0
  52. data/lib/mittsu/renderers/opengl/opengl_implementations.rb +61 -0
  53. data/lib/mittsu/renderers/opengl/opengl_light_renderer.rb +43 -0
  54. data/lib/mittsu/renderers/opengl/opengl_mittsu_params.rb +53 -0
  55. data/lib/mittsu/renderers/opengl/opengl_program.rb +147 -296
  56. data/lib/mittsu/renderers/opengl/opengl_state.rb +3 -5
  57. data/lib/mittsu/renderers/opengl/plugins/shadow_map_plugin.rb +12 -10
  58. data/lib/mittsu/renderers/opengl/scenes/opengl_scene.rb +8 -0
  59. data/lib/mittsu/renderers/opengl/textures/opengl_compressed_texture.rb +21 -0
  60. data/lib/mittsu/renderers/opengl/textures/opengl_cube_texture.rb +75 -0
  61. data/lib/mittsu/renderers/opengl/textures/opengl_data_texture.rb +23 -0
  62. data/lib/mittsu/renderers/opengl/textures/opengl_texture.rb +111 -0
  63. data/lib/mittsu/renderers/opengl_render_target.rb +117 -2
  64. data/lib/mittsu/renderers/opengl_renderer.rb +653 -2978
  65. data/lib/mittsu/renderers/shaders/rbsl_loader.rb +166 -0
  66. data/lib/mittsu/renderers/shaders/shader_chunk.rb +6 -9
  67. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_fragment.glsl +36 -37
  68. data/lib/mittsu/renderers/shaders/shader_lib.rb +26 -403
  69. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_fragment.rbsl +37 -0
  70. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_uniforms.rbslu +3 -0
  71. data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_vertex.rbsl +33 -0
  72. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_fragment.rbsl +12 -0
  73. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_uniforms.rbslu +2 -0
  74. data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_vertex.rbsl +12 -0
  75. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
  76. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
  77. data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
  78. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_fragment.rbsl +56 -0
  79. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_uniforms.rbslu +7 -0
  80. data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_vertex.rbsl +37 -0
  81. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_fragment.rbsl +45 -0
  82. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_uniforms.rbslu +11 -0
  83. data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_vertex.rbsl +43 -0
  84. data/lib/mittsu/renderers/shaders/shader_templates/fragment.glsl.erb +105 -0
  85. data/lib/mittsu/renderers/shaders/shader_templates/vertex.glsl.erb +143 -0
  86. data/lib/mittsu/renderers/shaders/uniforms_lib.rb +54 -55
  87. data/lib/mittsu/textures/texture.rb +5 -2
  88. data/lib/mittsu/version.rb +1 -1
  89. data/run_all_examples.sh +7 -0
  90. metadata +77 -28
  91. data/.ruby-version +0 -1
  92. data/lib/mittsu/core/hash_object.rb +0 -19
@@ -1,140 +1,48 @@
1
1
  require 'mittsu/math'
2
+ require 'mittsu/math/vector'
2
3
 
3
4
  module Mittsu
4
- class Vector4
5
- attr_accessor :x, :y, :z, :w
6
- def initialize(x = 0.0, y = 0.0, z = 0.0, w = 1.0)
7
- self.set(x, y, z, w)
8
- end
9
-
10
- def set(x, y, z, w)
11
- @x, @y, @z, @w = x.to_f, y.to_f, z.to_f, w.to_f
12
- self
13
- end
14
-
15
- def set_x(x)
16
- @x = x.to_f
17
- self
18
- end
19
-
20
- def set_y(y)
21
- @y = y.to_f
22
- self
23
- end
24
-
25
- def set_z(z)
26
- @z = z.to_f
27
- self
28
- end
5
+ class Vector4 < Vector
6
+ ELEMENTS = { x: 0, y: 1, z: 2, w: 3 }
7
+ DIMENSIONS = ELEMENTS.count
29
8
 
30
- def set_w(w)
31
- @w = w.to_f
32
- self
33
- end
34
-
35
- def set_component(index, value)
36
- case index
37
- when 0 then @x = value.to_f
38
- when 1 then @y = value.to_f
39
- when 2 then @z = value.to_f
40
- when 3 then @w = value.to_f
41
- else raise IndexError.new
42
- end
43
- end
44
-
45
- def get_component(index)
46
- case index
47
- when 0 then return @x
48
- when 1 then return @y
49
- when 2 then return @z
50
- when 3 then return @w
51
- else raise IndexError.new
52
- end
53
- end
54
-
55
- def copy(v)
56
- @x = v.x
57
- @y = v.y
58
- @z = v.z
59
- @w = v.w || 1.0
60
- self
61
- end
62
-
63
- def add(v)
64
- @x += v.x
65
- @y += v.y
66
- @z += v.z
67
- @w += v.w
68
- self
9
+ def initialize(x = 0, y = 0, z = 0, w = 1)
10
+ super [x.to_f, y.to_f, z.to_f, w.to_f]
69
11
  end
70
12
 
71
- def add_scalar(s)
72
- @x += s
73
- @y += s
74
- @z += s
75
- @w += s
76
- self
77
- end
78
-
79
- def add_vectors(a, b)
80
- @x = a.x + b.x
81
- @y = a.y + b.y
82
- @z = a.z + b.z
83
- @w = a.w + b.w
84
- self
85
- end
86
-
87
- def sub(v)
88
- @x -= v.x
89
- @y -= v.y
90
- @z -= v.z
91
- @w -= v.w
92
- self
93
- end
94
-
95
- def sub_scalar(s)
96
- @x -= s
97
- @y -= s
98
- @z -= s
99
- @w -= s
100
- self
13
+ def set(x, y, z, w)
14
+ super [x.to_f, y.to_f, z.to_f, w.to_f]
101
15
  end
102
16
 
103
- def sub_vectors(a, b)
104
- @x = a.x - b.x
105
- @y = a.y - b.y
106
- @z = a.z - b.z
107
- @w = a.w - b.w
108
- self
109
- end
17
+ def x; @elements[0]; end
18
+ def y; @elements[1]; end
19
+ def z; @elements[2]; end
20
+ def w; @elements[3]; end
110
21
 
111
- def multiply_scalar(scalar)
112
- @x *= scalar
113
- @y *= scalar
114
- @z *= scalar
115
- @w *= scalar
116
- self
117
- end
22
+ def x=(value); @elements[0] = value.to_f; end
23
+ def y=(value); @elements[1] = value.to_f; end
24
+ def z=(value); @elements[2] = value.to_f; end
25
+ def w=(value); @elements[3] = value.to_f; end
118
26
 
119
27
  def apply_matrix4(m)
120
- x1, y1, z1, w1 = @x, @y, @z, @w
28
+ _x, _y, _z, _w = *@elements
121
29
  e = m.elements
122
- @x = e[0] * x1 + e[4] * y1 + e[8] * z1 + e[12] * w1
123
- @y = e[1] * x1 + e[5] * y1 + e[9] * z1 + e[13] * w1
124
- @z = e[2] * x1 + e[6] * y1 + e[10] * z1 + e[14] * w1
125
- @w = e[3] * x1 + e[7] * y1 + e[11] * z1 + e[15] * w1
30
+ @elements[0] = e[0] * _x + e[4] * _y + e[8] * _z + e[12] * _w
31
+ @elements[1] = e[1] * _x + e[5] * _y + e[9] * _z + e[13] * _w
32
+ @elements[2] = e[2] * _x + e[6] * _y + e[10] * _z + e[14] * _w
33
+ @elements[3] = e[3] * _x + e[7] * _y + e[11] * _z + e[15] * _w
126
34
  self
127
35
  end
128
36
 
129
37
  def divide_scalar(scalar)
130
38
  if scalar != 0.0
131
39
  inv_scalar = 1.0 / scalar
132
- @x *= inv_scalar
133
- @y *= inv_scalar
134
- @z *= inv_scalar
135
- @w *= inv_scalar
40
+ @elements[0] *= inv_scalar
41
+ @elements[1] *= inv_scalar
42
+ @elements[2] *= inv_scalar
43
+ @elements[3] *= inv_scalar
136
44
  else
137
- @x, @y, @z, @w = 0.0, 0.0, 0.0, 1.0
45
+ @elements = [0.0, 0.0, 0.0, 1.0]
138
46
  end
139
47
  self
140
48
  end
@@ -142,16 +50,16 @@ module Mittsu
142
50
  def set_axis_angle_from_quaternion(q)
143
51
  # http:#www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
144
52
  # q is assumed to be normalized
145
- @w = 2.0 * Math.acos(q.w)
53
+ @elements[3] = 2.0 * Math.acos(q.w)
146
54
  s = Math.sqrt(1.0 - q.w * q.w)
147
55
  if s < 0.0001
148
- @x = 1.0
149
- @y = 0.0
150
- @z = 0.0
56
+ @elements[0] = 1.0
57
+ @elements[1] = 0.0
58
+ @elements[2] = 0.0
151
59
  else
152
- @x = q.x / s
153
- @y = q.y / s
154
- @z = q.z / s
60
+ @elements[0] = q.x / s
61
+ @elements[1] = q.y / s
62
+ @elements[2] = q.z / s
155
63
  end
156
64
  self
157
65
  end
@@ -177,7 +85,7 @@ module Mittsu
177
85
  ((m23 + m32).abs < epsilon2) &&
178
86
  ((m11 + m22 + m33 - 3).abs < epsilon2))
179
87
  # self singularity is identity matrix so angle = 0
180
- self.set(1, 0, 0, 0)
88
+ @elements = [1.0, 0.0, 0.0, 0.0]
181
89
  return self # zero angle, arbitrary axis
182
90
  end
183
91
  # otherwise self singularity is angle = 180
@@ -219,7 +127,7 @@ module Mittsu
219
127
  y1 = yz / z1
220
128
  end
221
129
  end
222
- self.set(x1, y1, z1, angle)
130
+ @elements = [x1, y1, z1, angle]
223
131
  return self # return 180 deg rotation
224
132
  end
225
133
  # as we have reached here there are no singularities so we can handle normally
@@ -229,186 +137,28 @@ module Mittsu
229
137
  s = 1.0 if (s.abs < 0.001)
230
138
  # prevent divide by zero, should not happen if matrix is orthogonal and should be
231
139
  # caught by singularity test above, but I've left it in just in case
232
- @x = (m32 - m23) / s
233
- @y = (m13 - m31) / s
234
- @z = (m21 - m12) / s
235
- @w = Math.acos((m11 + m22 + m33 - 1.0) / 2.0)
236
- self
237
- end
238
-
239
- def min(v)
240
- if @x > v.x
241
- @x = v.x
242
- end
243
- if @y > v.y
244
- @y = v.y
245
- end
246
- if @z > v.z
247
- @z = v.z
248
- end
249
- if @w > v.w
250
- @w = v.w
251
- end
252
- self
253
- end
254
-
255
- def max(v)
256
- if @x < v.x
257
- @x = v.x
258
- end
259
- if @y < v.y
260
- @y = v.y
261
- end
262
- if @z < v.z
263
- @z = v.z
264
- end
265
- if @w < v.w
266
- @w = v.w
267
- end
268
- self
269
- end
270
-
271
- def clamp(min, max)
272
- # This function assumes min < max, if self assumption isn't true it will not operate correctly
273
- if @x < min.x
274
- @x = min.x
275
- elsif @x > max.x
276
- @x = max.x
277
- end
278
- if @y < min.y
279
- @y = min.y
280
- elsif @y > max.y
281
- @y = max.y
282
- end
283
- if @z < min.z
284
- @z = min.z
285
- elsif @z > max.z
286
- @z = max.z
287
- end
288
- if @w < min.w
289
- @w = min.w
290
- elsif @w > max.w
291
- @w = max.w
292
- end
293
- self
294
- end
295
-
296
- def floor
297
- @x = (@x).floor
298
- @y = (@y).floor
299
- @z = (@z).floor
300
- @w = (@w).floor
301
- self
302
- end
303
-
304
- def ceil
305
- @x = (@x).ceil
306
- @y = (@y).ceil
307
- @z = (@z).ceil
308
- @w = (@w).ceil
309
- self
310
- end
311
-
312
- def round
313
- @x = (@x).round
314
- @y = (@y).round
315
- @z = (@z).round
316
- @w = (@w).round
317
- self
318
- end
319
-
320
- def round_to_zero
321
- @x = (@x < 0) ? (@x).ceil : (@x).floor
322
- @y = (@y < 0) ? (@y).ceil : (@y).floor
323
- @z = (@z < 0) ? (@z).ceil : (@z).floor
324
- @w = (@w < 0) ? (@w).ceil : (@w).floor
325
- self
326
- end
327
-
328
- def negate
329
- @x = - @x
330
- @y = - @y
331
- @z = - @z
332
- @w = - @w
140
+ @elements[0] = (m32 - m23) / s
141
+ @elements[1] = (m13 - m31) / s
142
+ @elements[2] = (m21 - m12) / s
143
+ @elements[3] = Math.acos((m11 + m22 + m33 - 1.0) / 2.0)
333
144
  self
334
145
  end
335
146
 
336
147
  def dot(v)
337
- @x * v.x + @y * v.y + @z * v.z + @w * v.w
338
- end
339
-
340
- def length_sq
341
- @x * @x + @y * @y + @z * @z + @w * @w
342
- end
343
-
344
- def length
345
- Math.sqrt(@x * @x + @y * @y + @z * @z + @w * @w)
148
+ x * v.x + y * v.y + z * v.z + w * v.w
346
149
  end
347
150
 
348
151
  def length_manhattan
349
- (@x).abs + (@y).abs + (@z).abs + (@w).abs
350
- end
351
-
352
- def normalize
353
- self.divide_scalar(self.length)
354
- end
355
-
356
- def set_length(l)
357
- old_length = self.length
358
- if old_length != 0 && l != old_length
359
- self.multiply_scalar(l / old_length)
360
- end
361
- self
362
- end
363
-
364
- def lerp(v, alpha)
365
- @x += (v.x - @x) * alpha
366
- @y += (v.y - @y) * alpha
367
- @z += (v.z - @z) * alpha
368
- @w += (v.w - @w) * alpha
369
- self
370
- end
371
-
372
- def lerp_vectors(v1, v2, alpha)
373
- self.sub_vectors(v2, v1).multiply_scalar(alpha).add(v1)
374
- self
375
- end
376
-
377
- def ==(v)
378
- ((v.x == @x) && (v.y == @y) && (v.z == @z) && (v.w == @w))
379
- end
380
-
381
- def from_array(array, offset = 0)
382
- @x = array[offset]
383
- @y = array[offset + 1]
384
- @z = array[offset + 2]
385
- @w = array[offset + 3]
386
- self
387
- end
388
-
389
- def to_array(array = [], offset = 0)
390
- array[offset] = @x
391
- array[offset + 1] = @y
392
- array[offset + 2] = @z
393
- array[offset + 3] = @w
394
- array
152
+ x.abs + y.abs + z.abs + w.abs
395
153
  end
396
154
 
397
155
  def from_attribute(attribute, index, offset = 0)
398
156
  index = index * attribute.itemSize + offset
399
- @x = attribute.array[index]
400
- @y = attribute.array[index + 1]
401
- @z = attribute.array[index + 2]
402
- @w = attribute.array[index + 3]
157
+ @elements[0] = attribute.array[index]
158
+ @elements[1] = attribute.array[index + 1]
159
+ @elements[2] = attribute.array[index + 2]
160
+ @elements[3] = attribute.array[index + 3]
403
161
  self
404
162
  end
405
-
406
- def clone
407
- Mittsu::Vector4.new @x, @y, @z, @w
408
- end
409
-
410
- def to_s
411
- "[#{x}, #{y}, #{z}, #{w}]"
412
- end
413
163
  end
414
164
  end
@@ -1,6 +1,6 @@
1
1
  module Mittsu
2
2
  class Line < Object3D
3
- attr_accessor :geometry, :material, :mode, :type
3
+ attr_accessor :geometry, :material, :mode, :type, :morph_target_base
4
4
 
5
5
  def initialize(geometry = nil, material = nil, mode = nil)
6
6
  super()
@@ -8,7 +8,7 @@ module Mittsu
8
8
  @type = 'Line'
9
9
 
10
10
  @geometry = geometry || Geometry.new
11
- @material = material || LineBasicMaterial.new(color: rand * 0xffffff)
11
+ @material = material || LineBasicMaterial.new(color: (rand * 0xffffff).to_i)
12
12
 
13
13
  @mode = mode || LineStrip
14
14
 
@@ -139,5 +139,15 @@ module Mittsu
139
139
  super(object)
140
140
  object
141
141
  end
142
+
143
+ protected
144
+
145
+ def jsonify
146
+ data = super
147
+ data[:geometry] = jsonify_geometry(self.geometry)
148
+ data[:material] = jsonify_material(self.material)
149
+ data[:mode] = self.mode
150
+ data
151
+ end
142
152
  end
143
153
  end
@@ -5,7 +5,7 @@ module Mittsu
5
5
  class Mesh < Object3D
6
6
  attr_accessor :material, :morph_target_base
7
7
 
8
- def initialize(geometry = Geometry.new, material = MeshBasicMaterial.new(color: rand * 0xffffff))
8
+ def initialize(geometry = Geometry.new, material = MeshBasicMaterial.new(color: (rand * 0xffffff).to_i))
9
9
  super()
10
10
 
11
11
  @type = 'Mesh'
@@ -16,7 +16,7 @@ module Mittsu
16
16
  end
17
17
 
18
18
  def update_morph_targets
19
- if !@morph_targets.nil? && !@morph_targets.empty?
19
+ if !@geometry.morph_targets.nil? && !@geometry.morph_targets.empty?
20
20
  @morph_targets_base = -1
21
21
  @morph_target_forced_order = []
22
22
  @morph_targets_influences = []
@@ -38,13 +38,13 @@ module Mittsu
38
38
  end
39
39
 
40
40
  def raycast(raycaster, intersects)
41
- @_inverse_matrix = Matrix4.new
42
- @_ray = Ray.new
43
- @_sphere = Sphere.new
41
+ @_inverse_matrix ||= Matrix4.new
42
+ @_ray ||= Ray.new
43
+ @_sphere ||= Sphere.new
44
44
 
45
- @_v_a = Vector3.new
46
- @_v_b = Vector3.new
47
- @_v_c = Vector3.new
45
+ @_v_a ||= Vector3.new
46
+ @_v_b ||= Vector3.new
47
+ @_v_c ||= Vector3.new
48
48
 
49
49
  # Checking bounding_sphere distance to ray
50
50
 
@@ -60,7 +60,7 @@ module Mittsu
60
60
  inverse_matrix.inverse(@matrix_world)
61
61
  ray.copy(raycaster.ray).apply_matrix4(inverse_matrix)
62
62
 
63
- if !geometry.bounding_bounding_box
63
+ if !geometry.bounding_bounding_box.nil?
64
64
  return unless ray.intersection_box?(geometry.bounding_box)
65
65
  end
66
66
 
@@ -239,5 +239,14 @@ module Mittsu
239
239
  super(object, recursive)
240
240
  return object
241
241
  end
242
+
243
+ protected
244
+
245
+ def jsonify
246
+ data = super
247
+ data[:geometry] = jsonify_geometry(@geometry)
248
+ data[:material] = jsonify_material(@material)
249
+ data
250
+ end
242
251
  end
243
252
  end