mittsu 0.1.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 (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +3 -0
  4. data/CODE_OF_CONDUCT.md +13 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +39 -0
  8. data/Rakefile +7 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/examples/01_-_Default1noCulling.png +0 -0
  12. data/examples/01_scene_example.rb +14 -0
  13. data/examples/02_box_mesh_example.rb +30 -0
  14. data/examples/02_sphere_mesh_example.rb +30 -0
  15. data/examples/03_complex_object_example.rb +52 -0
  16. data/examples/04_ambient_light_example.rb +33 -0
  17. data/examples/04_dir_light_example.rb +36 -0
  18. data/examples/04_hemi_light_example.rb +30 -0
  19. data/examples/04_point_light_example.rb +50 -0
  20. data/examples/04_spot_light_example.rb +44 -0
  21. data/examples/05_earth_example.rb +42 -0
  22. data/examples/05_earth_moon_example.rb +46 -0
  23. data/examples/05_texture_example.rb +32 -0
  24. data/examples/06_cube_texture_example.rb +36 -0
  25. data/examples/06_skybox_example.rb +60 -0
  26. data/examples/07_earth_normal_example.rb +36 -0
  27. data/examples/08_shadow_example.rb +87 -0
  28. data/examples/09_line_example.rb +52 -0
  29. data/examples/10_obj_loader_example.rb +68 -0
  30. data/examples/11_character_input_example.rb +18 -0
  31. data/examples/11_continuous_keyboard_input_example.rb +35 -0
  32. data/examples/11_keyboard_input_example.rb +43 -0
  33. data/examples/12_mouse_click_example.rb +38 -0
  34. data/examples/12_mouse_motion_example.rb +35 -0
  35. data/examples/12_mouse_scroll_example.rb +36 -0
  36. data/examples/12_orbit_zoom_example.rb +68 -0
  37. data/examples/13_joystick_example.rb +80 -0
  38. data/examples/cubemap/tron_bk.png +0 -0
  39. data/examples/cubemap/tron_dn.png +0 -0
  40. data/examples/cubemap/tron_ft.png +0 -0
  41. data/examples/cubemap/tron_lf.png +0 -0
  42. data/examples/cubemap/tron_rt.png +0 -0
  43. data/examples/cubemap/tron_up.png +0 -0
  44. data/examples/earth.png +0 -0
  45. data/examples/earth_normal.png +0 -0
  46. data/examples/example_helper.rb +2 -0
  47. data/examples/male-02-1noCulling.png +0 -0
  48. data/examples/male02.mtl +54 -0
  49. data/examples/male02.obj +13888 -0
  50. data/examples/moon.png +0 -0
  51. data/examples/orig_02_-_Defaul1noCulling.png +0 -0
  52. data/examples/texture.png +0 -0
  53. data/lib/mittsu.rb +15 -0
  54. data/lib/mittsu/cameras.rb +4 -0
  55. data/lib/mittsu/cameras/camera.rb +34 -0
  56. data/lib/mittsu/cameras/cube_camera.rb +74 -0
  57. data/lib/mittsu/cameras/orthographic_camera.rb +53 -0
  58. data/lib/mittsu/cameras/perspective_camera.rb +115 -0
  59. data/lib/mittsu/constants.rb +160 -0
  60. data/lib/mittsu/core.rb +10 -0
  61. data/lib/mittsu/core/buffer_attribute.rb +87 -0
  62. data/lib/mittsu/core/buffer_geometry.rb +694 -0
  63. data/lib/mittsu/core/clock.rb +44 -0
  64. data/lib/mittsu/core/dynamic_buffer_attribute.rb +16 -0
  65. data/lib/mittsu/core/event_dispatcher.rb +39 -0
  66. data/lib/mittsu/core/face3.rb +30 -0
  67. data/lib/mittsu/core/geometry.rb +596 -0
  68. data/lib/mittsu/core/hash_array.rb +36 -0
  69. data/lib/mittsu/core/hash_object.rb +19 -0
  70. data/lib/mittsu/core/object_3d.rb +421 -0
  71. data/lib/mittsu/core/raycaster.rb +78 -0
  72. data/lib/mittsu/extras.rb +3 -0
  73. data/lib/mittsu/extras/geometries.rb +2 -0
  74. data/lib/mittsu/extras/geometries/box_geometry.rb +108 -0
  75. data/lib/mittsu/extras/geometries/sphere_geometry.rb +88 -0
  76. data/lib/mittsu/extras/helpers.rb +1 -0
  77. data/lib/mittsu/extras/helpers/camera_helper.rb +155 -0
  78. data/lib/mittsu/extras/image.rb +3 -0
  79. data/lib/mittsu/extras/image_utils.rb +80 -0
  80. data/lib/mittsu/lights.rb +7 -0
  81. data/lib/mittsu/lights/ambient_light.rb +16 -0
  82. data/lib/mittsu/lights/area_light.rb +24 -0
  83. data/lib/mittsu/lights/directional_light.rb +131 -0
  84. data/lib/mittsu/lights/hemisphere_light.rb +29 -0
  85. data/lib/mittsu/lights/light.rb +21 -0
  86. data/lib/mittsu/lights/point_light.rb +27 -0
  87. data/lib/mittsu/lights/spot_light.rb +104 -0
  88. data/lib/mittsu/loaders.rb +7 -0
  89. data/lib/mittsu/loaders/cache.rb +53 -0
  90. data/lib/mittsu/loaders/file_loader.rb +22 -0
  91. data/lib/mittsu/loaders/image_loader.rb +32 -0
  92. data/lib/mittsu/loaders/loader.rb +212 -0
  93. data/lib/mittsu/loaders/loading_manager.rb +17 -0
  94. data/lib/mittsu/loaders/mtl_loader.rb +242 -0
  95. data/lib/mittsu/loaders/obj_mtl_loader.rb +225 -0
  96. data/lib/mittsu/materials.rb +7 -0
  97. data/lib/mittsu/materials/line_basic_material.rb +39 -0
  98. data/lib/mittsu/materials/material.rb +156 -0
  99. data/lib/mittsu/materials/mesh_basic_material.rb +122 -0
  100. data/lib/mittsu/materials/mesh_face_material.rb +30 -0
  101. data/lib/mittsu/materials/mesh_lambert_material.rb +126 -0
  102. data/lib/mittsu/materials/mesh_phong_material.rb +152 -0
  103. data/lib/mittsu/materials/shader_material.rb +108 -0
  104. data/lib/mittsu/math.rb +105 -0
  105. data/lib/mittsu/math/box2.rb +135 -0
  106. data/lib/mittsu/math/box3.rb +194 -0
  107. data/lib/mittsu/math/color.rb +252 -0
  108. data/lib/mittsu/math/color_keywords.rb +151 -0
  109. data/lib/mittsu/math/euler.rb +182 -0
  110. data/lib/mittsu/math/frustum.rb +106 -0
  111. data/lib/mittsu/math/line3.rb +76 -0
  112. data/lib/mittsu/math/matrix3.rb +163 -0
  113. data/lib/mittsu/math/matrix4.rb +581 -0
  114. data/lib/mittsu/math/plane.rb +128 -0
  115. data/lib/mittsu/math/quaternion.rb +309 -0
  116. data/lib/mittsu/math/ray.rb +292 -0
  117. data/lib/mittsu/math/sphere.rb +91 -0
  118. data/lib/mittsu/math/spline.rb +128 -0
  119. data/lib/mittsu/math/triangle.rb +121 -0
  120. data/lib/mittsu/math/vector2.rb +238 -0
  121. data/lib/mittsu/math/vector3.rb +491 -0
  122. data/lib/mittsu/math/vector4.rb +414 -0
  123. data/lib/mittsu/objects.rb +3 -0
  124. data/lib/mittsu/objects/group.rb +8 -0
  125. data/lib/mittsu/objects/line.rb +143 -0
  126. data/lib/mittsu/objects/mesh.rb +243 -0
  127. data/lib/mittsu/renderers.rb +1 -0
  128. data/lib/mittsu/renderers/glfw_window.rb +216 -0
  129. data/lib/mittsu/renderers/opengl/opengl_debug.rb +38 -0
  130. data/lib/mittsu/renderers/opengl/opengl_program.rb +402 -0
  131. data/lib/mittsu/renderers/opengl/opengl_shader.rb +58 -0
  132. data/lib/mittsu/renderers/opengl/opengl_state.rb +207 -0
  133. data/lib/mittsu/renderers/opengl/plugins/shadow_map_plugin.rb +416 -0
  134. data/lib/mittsu/renderers/opengl_render_target.rb +87 -0
  135. data/lib/mittsu/renderers/opengl_renderer.rb +3376 -0
  136. data/lib/mittsu/renderers/shaders/shader_chunk.rb +12 -0
  137. data/lib/mittsu/renderers/shaders/shader_chunk/alphamap_fragment.glsl +5 -0
  138. data/lib/mittsu/renderers/shaders/shader_chunk/alphamap_pars_fragment.glsl +5 -0
  139. data/lib/mittsu/renderers/shaders/shader_chunk/alphatest_fragment.glsl +5 -0
  140. data/lib/mittsu/renderers/shaders/shader_chunk/bumpmap_pars_fragment.glsl +40 -0
  141. data/lib/mittsu/renderers/shaders/shader_chunk/color_fragment.glsl +5 -0
  142. data/lib/mittsu/renderers/shaders/shader_chunk/color_pars_fragment.glsl +5 -0
  143. data/lib/mittsu/renderers/shaders/shader_chunk/color_pars_vertex.glsl +5 -0
  144. data/lib/mittsu/renderers/shaders/shader_chunk/color_vertex.glsl +5 -0
  145. data/lib/mittsu/renderers/shaders/shader_chunk/common.glsl +60 -0
  146. data/lib/mittsu/renderers/shaders/shader_chunk/default_vertex.glsl +15 -0
  147. data/lib/mittsu/renderers/shaders/shader_chunk/defaultnormal_vertex.glsl +21 -0
  148. data/lib/mittsu/renderers/shaders/shader_chunk/envmap_fragment.glsl +62 -0
  149. data/lib/mittsu/renderers/shaders/shader_chunk/envmap_pars_fragment.glsl +21 -0
  150. data/lib/mittsu/renderers/shaders/shader_chunk/envmap_pars_vertex.glsl +7 -0
  151. data/lib/mittsu/renderers/shaders/shader_chunk/envmap_vertex.glsl +17 -0
  152. data/lib/mittsu/renderers/shaders/shader_chunk/fog_fragment.glsl +26 -0
  153. data/lib/mittsu/renderers/shaders/shader_chunk/fog_pars_fragment.glsl +15 -0
  154. data/lib/mittsu/renderers/shaders/shader_chunk/lightmap_fragment.glsl +5 -0
  155. data/lib/mittsu/renderers/shaders/shader_chunk/lightmap_pars_fragment.glsl +6 -0
  156. data/lib/mittsu/renderers/shaders/shader_chunk/lightmap_pars_vertex.glsl +5 -0
  157. data/lib/mittsu/renderers/shaders/shader_chunk/lightmap_vertex.glsl +5 -0
  158. data/lib/mittsu/renderers/shaders/shader_chunk/lights_lambert_pars_vertex.glsl +43 -0
  159. data/lib/mittsu/renderers/shaders/shader_chunk/lights_lambert_vertex.glsl +196 -0
  160. data/lib/mittsu/renderers/shaders/shader_chunk/lights_phong_fragment.glsl +243 -0
  161. data/lib/mittsu/renderers/shaders/shader_chunk/lights_phong_pars_fragment.glsl +58 -0
  162. data/lib/mittsu/renderers/shaders/shader_chunk/lights_phong_pars_vertex.glsl +5 -0
  163. data/lib/mittsu/renderers/shaders/shader_chunk/lights_phong_vertex.glsl +5 -0
  164. data/lib/mittsu/renderers/shaders/shader_chunk/linear_to_gamma_fragment.glsl +2 -0
  165. data/lib/mittsu/renderers/shaders/shader_chunk/logdepthbuf_fragment.glsl +5 -0
  166. data/lib/mittsu/renderers/shaders/shader_chunk/logdepthbuf_pars_fragment.glsl +12 -0
  167. data/lib/mittsu/renderers/shaders/shader_chunk/logdepthbuf_pars_vertex.glsl +11 -0
  168. data/lib/mittsu/renderers/shaders/shader_chunk/logdepthbuf_vertex.glsl +15 -0
  169. data/lib/mittsu/renderers/shaders/shader_chunk/map_fragment.glsl +9 -0
  170. data/lib/mittsu/renderers/shaders/shader_chunk/map_pars_fragment.glsl +11 -0
  171. data/lib/mittsu/renderers/shaders/shader_chunk/map_pars_vertex.glsl +6 -0
  172. data/lib/mittsu/renderers/shaders/shader_chunk/map_particle_fragment.glsl +5 -0
  173. data/lib/mittsu/renderers/shaders/shader_chunk/map_particle_pars_fragment.glsl +6 -0
  174. data/lib/mittsu/renderers/shaders/shader_chunk/map_vertex.glsl +5 -0
  175. data/lib/mittsu/renderers/shaders/shader_chunk/morphnormal_vertex.glsl +12 -0
  176. data/lib/mittsu/renderers/shaders/shader_chunk/morphtarget_pars_vertex.glsl +13 -0
  177. data/lib/mittsu/renderers/shaders/shader_chunk/morphtarget_vertex.glsl +20 -0
  178. data/lib/mittsu/renderers/shaders/shader_chunk/normalmap_pars_fragment.glsl +27 -0
  179. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_fragment.glsl +217 -0
  180. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_pars_fragment.glsl +19 -0
  181. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_pars_vertex.glsl +6 -0
  182. data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_vertex.glsl +9 -0
  183. data/lib/mittsu/renderers/shaders/shader_chunk/skinbase_vertex.glsl +8 -0
  184. data/lib/mittsu/renderers/shaders/shader_chunk/skinning_pars_vertex.glsl +47 -0
  185. data/lib/mittsu/renderers/shaders/shader_chunk/skinning_vertex.glsl +20 -0
  186. data/lib/mittsu/renderers/shaders/shader_chunk/skinnormal_vertex.glsl +20 -0
  187. data/lib/mittsu/renderers/shaders/shader_chunk/specularmap_fragment.glsl +12 -0
  188. data/lib/mittsu/renderers/shaders/shader_chunk/specularmap_pars_fragment.glsl +5 -0
  189. data/lib/mittsu/renderers/shaders/shader_chunk/worldpos_vertex.glsl +17 -0
  190. data/lib/mittsu/renderers/shaders/shader_lib.rb +420 -0
  191. data/lib/mittsu/renderers/shaders/uniforms_lib.rb +107 -0
  192. data/lib/mittsu/renderers/shaders/uniforms_utils.rb +31 -0
  193. data/lib/mittsu/scenes.rb +1 -0
  194. data/lib/mittsu/scenes/scene.rb +27 -0
  195. data/lib/mittsu/textures.rb +5 -0
  196. data/lib/mittsu/textures/compressed_texture.rb +30 -0
  197. data/lib/mittsu/textures/cube_texture.rb +19 -0
  198. data/lib/mittsu/textures/data_texture.rb +17 -0
  199. data/lib/mittsu/textures/texture.rb +92 -0
  200. data/lib/mittsu/textures/video_texture.rb +17 -0
  201. data/lib/mittsu/version.rb +4 -0
  202. data/mittsu.gemspec +31 -0
  203. metadata +357 -0
@@ -0,0 +1,36 @@
1
+ module Mittsu
2
+ class HashArray
3
+ include Enumerable
4
+
5
+ def initialize()
6
+ @array = []
7
+ @hash = {}
8
+ end
9
+
10
+ def [](key)
11
+ if key.is_a? Fixnum
12
+ @array[key]
13
+ else
14
+ @hash[key]
15
+ end
16
+ end
17
+
18
+ def []=(key, value)
19
+ if key.is_a? Fixnum
20
+ @array[key] = value
21
+ else
22
+ @hash[key] = value
23
+ end
24
+ end
25
+
26
+ def each(&block)
27
+ @array.each(&block)
28
+ end
29
+
30
+ def length
31
+ @array.length
32
+ end
33
+ alias_method :count, :length
34
+ alias_method :size, :length
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module Mittsu
2
+ class HashObject
3
+ def initialize
4
+ @_hash = {}
5
+ end
6
+
7
+ def [](key)
8
+ @_hash[key]
9
+ end
10
+
11
+ def []=(key, value)
12
+ @_hash[key] = value
13
+ end
14
+
15
+ def delete(key)
16
+ @_hash.delete(key)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,421 @@
1
+ require 'securerandom'
2
+ require 'mittsu'
3
+ require 'mittsu/core/hash_object'
4
+
5
+ module Mittsu
6
+ class Object3D < HashObject
7
+ include EventDispatcher
8
+
9
+ attr_accessor :name, :children, :up, :position, :rotation, :quaternion, :scale, :rotation_auto_update, :matrix, :matrix_world, :matrix_auto_update, :matrix_world_needs_update, :visible, :cast_shadow, :receive_shadow, :frustum_culled, :render_order, :user_data, :parent, :geometry
10
+
11
+ attr_reader :id, :uuid, :type
12
+
13
+ DefaultUp = Vector3.new(0.0, 1.0, 0.0)
14
+
15
+ def initialize
16
+ super
17
+ @id = (@@id ||= 1).tap { @@id += 1 }
18
+
19
+ @uuid = SecureRandom.uuid
20
+
21
+ @name = ''
22
+ @type = 'Object3D'
23
+
24
+ @children = []
25
+
26
+ @up = DefaultUp.clone
27
+
28
+ @position = Vector3.new
29
+ @rotation = Euler.new
30
+ @quaternion = Quaternion.new
31
+ @scale = Vector3.new(1.0, 1.0, 1.0)
32
+
33
+ @rotation.on_change do
34
+ @quaternion.set_from_euler(rotation, false)
35
+ end
36
+
37
+ @quaternion.on_change do
38
+ @rotation.set_from_quaternion(quaternion, false)
39
+ end
40
+
41
+ @rotation_auto_update = true
42
+
43
+ @matrix = Matrix4.new
44
+ @matrix_world = Matrix4.new
45
+
46
+ @matrix_auto_update = true
47
+ @matrix_world_needs_update = false
48
+
49
+ @visible = true
50
+
51
+ @cast_shadow = false
52
+ @receive_shadow = false
53
+
54
+ @frustum_culled = true
55
+ @render_order = 0
56
+
57
+ @user_data = {}
58
+ end
59
+
60
+ def apply_matrix(matrix)
61
+ @matrix.multiply_matrices(matrix, @matrix)
62
+ @matrix.decompose(@position, @quaternion, @scale)
63
+ end
64
+
65
+ def set_rotation_from_axis_angle(axis, angle)
66
+ # assumes axis is normalized
67
+ @quaternion.set_from_axis_angle(axis, angle)
68
+ end
69
+
70
+ def set_rotation_from_euler(euler)
71
+ @quaternion.set_from_euler(euler, true)
72
+ end
73
+
74
+ def set_rotation_from_matrix(m)
75
+ # assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
76
+ @quaternion.set_from_rotation_matrix(m)
77
+ end
78
+
79
+ def set_rotation_from_quaternion(q)
80
+ # assumes q is normalized
81
+ @quaternion.copy(q)
82
+ end
83
+
84
+ def rotate_on_axis(axis, angle)
85
+ # rotate object on axis in object space
86
+ # axis is assumed to be normalized
87
+ @_q1 ||= Quaternion.new
88
+ @_q1.set_from_axis_angle(axis, angle)
89
+ @quaternion.multiply(@_q1)
90
+ self
91
+ end
92
+
93
+ def rotate_x(angle)
94
+ @_v1 ||= Vector3.new(1, 0, 0)
95
+ self.rotate_on_axis(@_v1, angle)
96
+ end
97
+
98
+ def rotate_y(angle)
99
+ @_v1 ||= Vector3.new(0, 1, 0)
100
+ self.rotate_on_axis(@_v1, angle)
101
+ end
102
+
103
+ def rotate_z(angle)
104
+ @_v1 ||= Vector3.new(0, 0, 1)
105
+ self.rotate_on_axis(@_v1, angle)
106
+ end
107
+
108
+ def translate_on_axis(axis, distance)
109
+ # translate object by distance along axis in object space
110
+ # axis is assumed to be normalized
111
+ @_v1 ||= Vector3.new
112
+ @_v1.copy(axis).apply_quaternion(@quaternion)
113
+ @position.add(@_v1.multiply_scalar(distance))
114
+ self
115
+ end
116
+
117
+ def translate_x(distance)
118
+ @_x_axis ||= Vector3.new(1, 0, 0)
119
+ self.translate_on_axis(@_x_axis, distance)
120
+ end
121
+
122
+ def translate_y(distance)
123
+ @_y_axis ||= Vector3.new(0, 1, 0)
124
+ self.translate_on_axis(@_y_axis, distance)
125
+ end
126
+
127
+ def translate_z(distance)
128
+ @_z_axis ||= Vector3.new(0, 0, 1)
129
+ self.translate_on_axis(@_z_axis, distance)
130
+ end
131
+
132
+ def local_to_world(vector)
133
+ vector.apply_matrix4(@matrix_world)
134
+ end
135
+
136
+ def world_to_local(vector)
137
+ @_m1 ||= Matrix4.new
138
+ vector.apply_matrix4(@_m1.get_inverse(@matrix_world))
139
+ end
140
+
141
+ def look_at(vector)
142
+ # This routine does not support objects with rotated and/or translated parent(s)
143
+ @_m1 ||= Matrix4.new
144
+ @_m1.look_at(vector, @position, self.up)
145
+ @quaternion.set_from_rotation_matrix(@_m1)
146
+ end
147
+
148
+ def add(*arguments)
149
+ if arguments.length > 1
150
+ arguments.each do |arg|
151
+ self.add(arg)
152
+ end
153
+ return self
154
+ end
155
+ object = arguments.first
156
+ if object == self
157
+ puts("ERROR: Mittsu::Object3D#add: object can't be added as a child of itself.", object.inspect)
158
+ return self
159
+ end
160
+ if object.is_a? Object3D
161
+ object.parent.remove(object) unless object.parent.nil?
162
+ object.parent = self
163
+ object.dispatch_event type: :added
164
+ @children << object
165
+ else
166
+ puts('ERROR: Mittsu::Object3D#add: object not an instance of Object3D.', object.inspect)
167
+ end
168
+ self
169
+ end
170
+
171
+ def remove(*arguments)
172
+ if arguments.length > 1
173
+ arguments.each do |arg|
174
+ self.remove(arg)
175
+ end
176
+ return
177
+ end
178
+ object = arguments.first
179
+ index = @children.index(object)
180
+ if index
181
+ object.parent = nil
182
+ object.dispatch_event type: :removed
183
+ @children.delete_at index
184
+ end
185
+ nil
186
+ end
187
+
188
+ def get_object_by_id(id)
189
+ self.get_object_by_property(:id, id)
190
+ end
191
+
192
+ def get_object_by_name(name)
193
+ self.get_object_by_property(:name, name)
194
+ end
195
+
196
+ def get_object_by_property(name, value)
197
+ return self if self.send(name) == value
198
+ @children.each do |child|
199
+ object = child.get_object_by_property(name, value)
200
+ return object unless object.nil?
201
+ end
202
+ nil
203
+ end
204
+
205
+ def get_world_position(target = Vector3.new)
206
+ self.update_matrix_world(true)
207
+ target.set_from_matrix_position(@matrix_world)
208
+ end
209
+
210
+ def get_world_quaternion(target = Quaternion.new)
211
+ @_position ||= Vector3.new
212
+ @_scale ||= Vector3.new
213
+ self.update_matrix_world(true)
214
+ @matrix_world.decompose(@_position, target, @_scale)
215
+ target
216
+ end
217
+
218
+ def get_world_rotation(target = Euler.new)
219
+ @_quaternion ||= Quaternion.new
220
+ self.get_world_quaternion(quaternion)
221
+ target.set_from_quaternion(quaternion, @rotation.order, false)
222
+ end
223
+
224
+ def get_world_scale(target = Vector3.new)
225
+ @_position ||= Vector3.new
226
+ @_quaternion ||= Quaternion.new
227
+ self.update_matrix_world(true)
228
+ @matrix_world.decompose(@_position, @_quaternion, target)
229
+ target
230
+ end
231
+
232
+ def get_world_direction(target = Vector3.new)
233
+ @_quaternion ||= Quaternion.new
234
+ self.get_world_quaternion(@_quaternion)
235
+ target.set(0.0, 0.0, 1.0).apply_quaternion(@_quaternion)
236
+ end
237
+
238
+ def raycast; end
239
+
240
+ def traverse(&callback)
241
+ callback.yield self
242
+ @children.each do |child|
243
+ child.traverse(&callback)
244
+ end
245
+ end
246
+
247
+ def print_tree(lines=[])
248
+ if lines.empty?
249
+ puts self
250
+ else
251
+ last = !lines.last
252
+ indent = lines[0..-2].map{|l| l ? '┃ ' : ' '}.join
253
+ puts "#{indent}#{last ? '┗' : '┣'}╸#{self}"
254
+ end
255
+ @children.each do |child|
256
+ child.print_tree(lines + [child != @children.last])
257
+ end
258
+ end
259
+
260
+ def to_s
261
+ "#{type} (#{name}) #{position}"
262
+ end
263
+
264
+ def traverse_visible(&callback)
265
+ return unless @visible
266
+ callback.yield self
267
+ @children.each do |child|
268
+ child.traverse_visible(&callback)
269
+ end
270
+ end
271
+
272
+ def traverse_ancestors(&callback)
273
+ if @parent
274
+ callback.yielf @parent
275
+ @parent.traverse_ancestors(&callback)
276
+ end
277
+ end
278
+
279
+ def update_matrix
280
+ @matrix.compose(@position, @quaternion, @scale)
281
+ @matrix_world_needs_update = true
282
+ end
283
+
284
+ def update_matrix_world(force = false)
285
+ self.update_matrix if @matrix_auto_update
286
+ if @matrix_world_needs_update || force
287
+ if @parent.nil?
288
+ @matrix_world.copy(@matrix)
289
+ else
290
+ @matrix_world.multiply_matrices(@parent.matrix_world, @matrix)
291
+ end
292
+ @matrix_world_needs_update = false
293
+ force = true
294
+ end
295
+ # update children
296
+ @children.each do |child|
297
+ child.update_matrix_world(force)
298
+ end
299
+ end
300
+
301
+ def to_json
302
+ @_output = {
303
+ metadata: {
304
+ version: 4.3,
305
+ type: 'Object',
306
+ generator: 'ObjectExporter'
307
+ }
308
+ }
309
+ @_geometries = {}
310
+ @_materials = {}
311
+ @_output[:object] = parse_object(self)
312
+ @_output
313
+ end
314
+
315
+ def clone(object = Object3D.new, recursive = true)
316
+ object.name = @name
317
+ object.up.copy(@up)
318
+ object.position.copy(@position)
319
+ object.quaternion.copy(@quaternion)
320
+ object.scale.copy(@scale)
321
+ object.rotation_auto_update = @rotation_auto_update
322
+ object.matrix.copy(@matrix)
323
+ object.matrix_world.copy(@matrix_world)
324
+ object.matrix_auto_update = @matrix_auto_update
325
+ object.matrix_world_needs_update = @matrix_world_needs_update
326
+ object.visible = @visible
327
+ object.cast_shadow = @cast_shadow
328
+ object.receive_shadow = @receive_shadow
329
+ object.frustum_culled = @frustum_culled
330
+ object.user_data = @user_data
331
+ if recursive
332
+ @children.each do |child|
333
+ object.add(child.clone)
334
+ end
335
+ end
336
+ object
337
+ end
338
+
339
+ private
340
+
341
+ def parse_geometry(geometry)
342
+ @_output[:geometries] ||= []
343
+ if @_geometries[geometry.uuid].nil?
344
+ json = geometry.to_json
345
+ json.delete :metadata
346
+ @_geometries[geometry.uuid] = json
347
+ @_output[:geometries] << json
348
+ end
349
+ geometry.uuid
350
+ end
351
+
352
+ def parse_material(material)
353
+ @_output[:materials] ||= []
354
+ if @_materials[material.uuid].nil?
355
+ json = material.to_json
356
+ json.delete :metadata
357
+ @_materials[material.uuid] = json
358
+ @_output[:materials] << json
359
+ end
360
+ material.uuid
361
+ end
362
+
363
+ def parse_object(object)
364
+ data = {}
365
+ data[:uuid] = object.uuid
366
+ data[:type] = object.type
367
+ data[:name] = object.name unless object.name.nil? || object.name.empty?
368
+ data.user_data = object.user_data unless object.user_data.nil? || object.user_data.empty?
369
+ data[:visible] = object.visible unless object.visible
370
+
371
+ case object
372
+ when PerspectiveCamera
373
+ data[:fov] = object.fov
374
+ data[:aspect] = object.aspect
375
+ data[:near] = object.near
376
+ data[:far] = object.far
377
+ when OrthographicCamera
378
+ data[:left] = object.left
379
+ data[:right] = object.right
380
+ data[:top] = object.top
381
+ data[:bottom] = object.bottom
382
+ data[:near] = object.near
383
+ data[:far] = object.far
384
+ when AmbientLight
385
+ data[:color] = object.color.get_hex
386
+ when DirectionalLight
387
+ data[:color] = object.color.get_hex
388
+ data[:intensity] = object.intensity
389
+ when PointLight
390
+ data[:color] = object.color.get_hex
391
+ data[:intensity] = object.intensity
392
+ data[:distance] = object.distance
393
+ data[:decay] = object.decay
394
+ when SpotLight
395
+ data[:color] = object.color.get_hex
396
+ data[:intensity] = object.intensity
397
+ data[:distance] = object.distance
398
+ data[:angle] = object.angle
399
+ data[:exponent] = object.exponent
400
+ data[:decay] = object.decay
401
+ when HemisphereLight
402
+ data[:color] = object.color.get_hex
403
+ data[:ground_color] = object.ground_color.get_hex
404
+ when Mesh, Line, PointCloud
405
+ data[:geometry] = parse_geometry(object.geometry)
406
+ data[:material] = parse_material(object.material)
407
+ data[:mode] = object.mode if object.is_a? Line
408
+ when Sprite
409
+ data[:material] = parse_material(object.material)
410
+ end
411
+ data[:matrix] = object.matrix.to_a
412
+ if !object.children.length.empty?
413
+ data[:children] = []
414
+ object.children.each do |child|
415
+ data[:children] << parse_object(child)
416
+ end
417
+ end
418
+ data
419
+ end
420
+ end
421
+ end