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,44 @@
1
+ module Mittsu
2
+ class Clock
3
+ attr_accessor :auto_start, :start_time, :old_time, :elapsed_time, :running
4
+
5
+ def initialize(auto_start = true)
6
+ @auto_start = auto_start
7
+ @start_time = 0
8
+ @old_time = 0
9
+ @elapsed_time = 0
10
+ @running = false
11
+ end
12
+
13
+ def start
14
+ @start_time = Time.now
15
+ @old_time = @start_time
16
+ @running = true
17
+ end
18
+
19
+ def stop
20
+ self.get_elapsed_time
21
+ @running = false
22
+ end
23
+
24
+ def get_elapsed_time
25
+ self.get_delta
26
+ @elapsed_time
27
+ end
28
+
29
+ def get_delta
30
+ diff = 0
31
+ if @auto_start && ! @running
32
+ self.start
33
+ end
34
+ if @running
35
+ new_time = Time.now
36
+ diff = 0.001 * (new_time - @old_time)
37
+ @old_time = new_time
38
+ @elapsed_time += diff
39
+ end
40
+ diff
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ module Mittsu
2
+ class DynamicBufferAttribute < Mittsu::BufferAttribute
3
+ UpdateRange = Struct.new(:offset, :count)
4
+
5
+ attr_accessor :update_range
6
+
7
+ def initialize(array, item_size)
8
+ super
9
+ @update_range = UpdateRange.new(0, -1)
10
+ end
11
+
12
+ def clone
13
+ Mittsu::DynamicBufferAttribute(self.array.dup, self.item_size)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Mittsu
2
+ module EventDispatcher
3
+ Event = Struct.new(:type, :target)
4
+
5
+ def add_event_listener(type, listener)
6
+ @_listeners ||= {}
7
+ @_listeners[type] ||= []
8
+ if !@_listeners[type].include? listener
9
+ @_listeners[type] << (listener)
10
+ end
11
+ end
12
+
13
+ def has_event_listener(type, listener)
14
+ return false if @_listeners.nil?
15
+ return false if @_listeners[type].nil?
16
+ @_listeners[type].include? listener
17
+ end
18
+
19
+ def remove_event_listener(type, listener)
20
+ return if @_listeners.nil?
21
+ listener_array = @_listeners[type]
22
+ if listener_array
23
+ listener_array.delete(listener)
24
+ end
25
+ end
26
+
27
+ def dispatch_event(event = {})
28
+ return if @_listeners.nil?
29
+ listener_array = @_listeners[event.type]
30
+ if listener_array
31
+ evt = Event.new(event[:type], self)
32
+ array = listener_array.dup
33
+ array.each do |l|
34
+ l.call(self, evt)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ require 'mittsu/math'
2
+
3
+ module Mittsu
4
+ class Face3
5
+ attr_accessor :a, :b, :c, :normal, :vertex_normals, :color, :vertex_colors, :vertex_tangents, :material_index
6
+
7
+ def initialize(a, b, c, normal = nil, color = nil, material_index = nil)
8
+ @a = a
9
+ @b = b
10
+ @c = c
11
+ @normal = normal.is_a?(Vector3) ? normal : Mittsu::Vector3.new
12
+ @vertex_normals = normal.is_a?(Array) ? normal : []
13
+ @color = color.is_a?(Color) ? color : Mittsu::Color.new
14
+ @vertex_colors = color.is_a?(Array) ? normal : []
15
+ @vertex_tangents = []
16
+ @material_index = material_index.nil? ? 0 : material_index
17
+ end
18
+
19
+ def clone
20
+ face = THREE.face3.new(@a, @b, @c)
21
+ face.normal.copy(@normal)
22
+ face.color.copy(@color)
23
+ face.material_index = @material_index
24
+ face.vertex_normals = @vertex_normals.map(&:clone)
25
+ face.vertex_colors = @vertex_colors.map(&:clone)
26
+ face.vertex_tangents = @vertex_tangents.map(&:clone)
27
+ face
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,596 @@
1
+ require 'securerandom'
2
+ require 'mittsu'
3
+ require 'mittsu/core/hash_object'
4
+
5
+ module Mittsu
6
+ class Geometry < HashObject
7
+ include EventDispatcher
8
+
9
+ MorphNormal = Struct.new(:face_normals, :vertex_normals)
10
+ Normal = Struct.new(:a, :b, :c)
11
+
12
+ attr_accessor :name, :vertices, :colors, :faces, :face_vertex_uvs, :morph_targets, :morph_colors, :morph_normals, :skin_weights, :skin_indices, :line_distances, :bounding_box, :bounding_sphere, :has_tangents, :dynamic
13
+
14
+ attr_accessor(*%w(vertices morph_targets elements uvs normals tangents colors line_distances groups).map { |s| "#{s}_need_update".to_sym })
15
+
16
+ attr_reader :id, :uuid, :type
17
+
18
+ def initialize
19
+ super
20
+
21
+ @id = (@@id ||= 1).tap { @@id += 1 }
22
+
23
+ @name = ''
24
+ @type = 'Geometry'
25
+
26
+ @vertices = []
27
+ @colors = [] # one-to-one vertex colors, used in Points and Line
28
+
29
+ @faces = []
30
+
31
+ @face_vertex_uvs = [[]]
32
+
33
+ @morph_targets = []
34
+ @morph_colors = []
35
+ @morph_normals = []
36
+
37
+ @skin_weights = []
38
+ @skin_indices = []
39
+
40
+ @line_distances = []
41
+
42
+ @has_tangents = false
43
+
44
+ @vertices_need_update = false
45
+ @morph_targets_need_update = false
46
+ @elements_need_update = false
47
+ @uvs_need_update = false
48
+ @normals_need_update = false
49
+ @tangents_need_update = false
50
+ @colors_need_update = false
51
+ @line_distances_need_update = false
52
+ @groups_need_update = false
53
+ end
54
+
55
+ def apply_matrix(matrix)
56
+ normal_matrix = Mittsu::Matrix3.new.get_normal_matrix(matrix)
57
+ @vertices.each do |vertex|
58
+ vertex.apply_matrix4(matrix)
59
+ end
60
+ @faces.each do |face|
61
+ face.normal.apply_matrix3(normal_matrix).normalize
62
+ face.vertex_normals.each do |vertex_normal|
63
+ vertex_normal.apply_matrix3(normal_matrix).normalize
64
+ end
65
+ end
66
+ if @bounding_box
67
+ self.compute_bounding_box
68
+ end
69
+ if @bounding_sphere
70
+ self.compute_bounding_sphere
71
+ end
72
+ @vertices_need_update = true
73
+ @normals_need_update = true
74
+ end
75
+
76
+ def from_buffer_geometry(geometry)
77
+ scope = self
78
+ vertices = geometry[:position].array
79
+ indices = geometry[:index].nil? ? nil : geometry[:index].array
80
+ normals = geometry[:normal].nil? ? nil : geometry[:normal].array
81
+ colors = geometry[:color].nil? ? nil : geometry[:color].array
82
+ uvs = geometry[:uv].nil? ? nil : geometry[:uv].array
83
+ temp_normals = []
84
+ temp_uvs = []
85
+ i, j = 0, 0
86
+ while i < vertices.length
87
+ scope.vertices << Mittsu::Vector3.new(vertices[i], vertices[i + 1], vertices[i + 2])
88
+ if normals
89
+ temp_normals << Mittsu::Vector3.new(normals[i], normals[i + 1], normals[i + 2])
90
+ end
91
+ if colors
92
+ scope.colors << Mittsu::Color.new(colors[i], colors[i + 1], colors[i + 2])
93
+ end
94
+ if uvs
95
+ temp_uvs << Mittsu::Vector2.new(uvs[j], uvs[j + 1])
96
+ end
97
+ i += 3; j += 2
98
+ end
99
+ add_face = -> (a, b, c) {
100
+ vertex_normals = normals.nil? ? [] : [temp_normals[a].clone, temp_normals[b].clone, temp_normals[c].clone]
101
+ vertex_colors = colors.nil? ? [] : [scope.colors[a].clone, scope.colors[b].clone, scope.colors[c].clone]
102
+ scope.faces << Mittsu::Face3.new(a, b, c, vertex_normals, vertex_colors)
103
+ if uvs
104
+ scope.face_vertex_uvs[0] << [temp_uvs[a].clone, temp_uvs[b].clone, temp_uvs[c].clone]
105
+ end
106
+ }
107
+ if indices
108
+ draw_calls = geometry.draw_calls
109
+ if !draw_calls.length.empty?
110
+ draw_calls.each do |draw_call|
111
+ start = draw_call.start
112
+ count = draw_call.count
113
+ index = draw_call.index
114
+ j = start
115
+ jl = start + count
116
+ while j < jl
117
+ add_face[index + indices[j], index + indices[j + 1], index + indices[j + 2]]
118
+ j += 3
119
+ end
120
+ end
121
+ else
122
+ indices.each_slice(3).with_index do |index|
123
+ add_face(*index)
124
+ end
125
+ end
126
+ else
127
+ i = 0, il = vertices.length / 3
128
+ while i < il
129
+ add_face[i, i + 1, i + 2]
130
+ i += 3
131
+ end
132
+ end
133
+ self.compute_face_normals
134
+ if geometry.boundingBox
135
+ @bounding_box = geometry.bounding_box.clone
136
+ end
137
+ if geometry.boundingSphere
138
+ @bounding_sphere = geometry.bounding_sphere.clone
139
+ end
140
+ self
141
+ end
142
+
143
+ def center
144
+ self.compute_bounding_box
145
+ offset = @bounding_box.center.negate
146
+ self.apply_matrix(Mittsu::Matrix4.new.set_position(offset))
147
+ offset
148
+ end
149
+
150
+ def compute_face_normals
151
+ cb, ab = Mittsu::Vector3.new, Mittsu::Vector3.new
152
+ @faces.each do |face|
153
+ v_a = @vertices[face.a]
154
+ v_b = @vertices[face.b]
155
+ v_c = @vertices[face.c]
156
+ cb.sub_vectors(v_c, v_b)
157
+ ab.sub_vectors(v_a, v_b)
158
+ cb.cross(ab)
159
+ cb.normalize
160
+ face.normal.copy(cb)
161
+ end
162
+ end
163
+
164
+ def compute_vertex_normals(area_weigted)
165
+ vertices = Array.new(@vertices.length)
166
+ @vertices.length.times do |v|
167
+ vertices[v] = Mittsu::Vector3.new
168
+ end
169
+ if area_weigted
170
+ # vertex normals weighted by triangle areas
171
+ # http:#www.iquilezles.org/www/articles/normals/normals.htm
172
+ cb = Mittsu::Vector3.new, ab = Mittsu::Vector3.new
173
+ @faces.each do |face|
174
+ v_a = @vertices[face.a]
175
+ v_b = @vertices[face.b]
176
+ v_c = @vertices[face.c]
177
+ cb.sub_vectors(v_c, v_b)
178
+ ab.sub_vectors(v_a, v_b)
179
+ cb.cross(ab)
180
+ vertices[face.a].add(cb)
181
+ vertices[face.b].add(cb)
182
+ vertices[face.c].add(cb)
183
+ end
184
+ else
185
+ @faces.each do |face|
186
+ vertices[face.a].add(face.normal)
187
+ vertices[face.b].add(face.normal)
188
+ vertices[face.c].add(face.normal)
189
+ end
190
+ end
191
+ @vertices.each(&:normalize)
192
+ @faces.each do |face|
193
+ face.vertex_normals[0] = vertices[face.a].clone
194
+ face.vertex_normals[1] = vertices[face.b].clone
195
+ face.vertex_normals[2] = vertices[face.c].clone
196
+ end
197
+ end
198
+
199
+ def compute_morph_normals
200
+ # save original normals
201
+ # - create temp variables on first access
202
+ # otherwise just copy (for faster repeated calls)
203
+ @_original_face_normal ||= []
204
+ @_original_vertex_normals ||= []
205
+ @faces.each_with_index do |face, f|
206
+ if !@_original_face_normal[f]
207
+ @_original_face_normal[f] = face.normal.clone
208
+ else
209
+ @_original_face_normal[f].copy(face.normal)
210
+ end
211
+ @_original_vertex_normals[f] ||= []
212
+ face.vertex_normals.each_with_index do |vnorm, i|
213
+ if !@_original_vertex_normals[f][i]
214
+ @_original_vertex_normals[f][i] = vnorm.clone
215
+ else
216
+ @_original_vertex_normals[f][i].copy(face.vertex_normals[i])
217
+ end
218
+ end
219
+ end
220
+
221
+ # use temp geometry to compute face and vertex normals for each morph
222
+ tmp_geo = Mittsu::Geometry.new
223
+ tmp_geo.faces = @faces
224
+ @morph_targets.each_with_index do |morph_target, i|
225
+ # create on first access
226
+ if !@morph_normals[i]
227
+ @morph_normals[i] = MorphNormal.new([], [])
228
+ dst_normals_face = @morph_normals[i].face_normals
229
+ dst_normals_vertex = @morph_normals[i].vertex_normals
230
+ @faces.each do
231
+ face_normal = Mittsu::Vector3.new
232
+ vertex_normals = Normal.new(Mittsu::Vector3.new, Mittsu::Vector3.new, Mittsu::Vector3.new)
233
+ dst_normals_face << face_normal
234
+ dst_normals_vertex << vertex_normals
235
+ end
236
+ end
237
+ # set vertices to morph target
238
+ tmp_geo.vertices = @morph_targets[i].vertices
239
+ # compute morph normals
240
+ tmp_geo.compute_face_normals
241
+ tmp_geo.compute_vertex_normals
242
+ # store morph normals
243
+ @faces.each_with_index do |face, f|
244
+ face_normal = @morph_normals[i].face_normals[f]
245
+ vertex_normals = @morph_normals[i].vertex_normals[f]
246
+ face_normal.copy(face.normal)
247
+ vertex_normals.a.copy(face.vertex_normals[0])
248
+ vertex_normals.b.copy(face.vertex_normals[1])
249
+ vertex_normals.c.copy(face.vertex_normals[2])
250
+ end
251
+ end
252
+ # restore original normals
253
+ @faces.each_with_index do |face, f|
254
+ face.normal = @_original_face_normal[f]
255
+ face.vertex_normals = @_original_vertex_normals[f]
256
+ end
257
+ end
258
+
259
+ def compute_tangents
260
+ # based on http:#www.terathon.com/code/tangent.html
261
+ # tangents go to vertices
262
+ tan1 = []; tan2 = [],
263
+ sdir = Mittsu::Vector3.new; tdir = Mittsu::Vector3.new
264
+ tmp = Mittsu::Vector3.new; tmp2 = Mittsu::Vector3.new
265
+ n = Mittsu::Vector3.new
266
+ uv = []
267
+ @vertices.each_index do |v|
268
+ tan1[v] = Mittsu::Vector3.new
269
+ tan2[v] = Mittsu::Vector3.new
270
+ end
271
+ handle_triangle = -> (context, a, b, c, ua, ub, uc) {
272
+ v_a = context.vertices[a]
273
+ v_b = context.vertices[b]
274
+ v_c = context.vertices[c]
275
+ uv_a = uv[ua]
276
+ uv_b = uv[ub]
277
+ uv_c = uv[uc]
278
+ x1 = v_b.x - v_a.x
279
+ x2 = v_c.x - v_a.x
280
+ y1 = v_b.y - v_a.y
281
+ y2 = v_c.y - v_a.y
282
+ z1 = v_b.z - v_a.z
283
+ z2 = v_c.z - v_a.z
284
+ s1 = uv_b.x - uv_a.x
285
+ s2 = uv_c.x - uv_a.x
286
+ t1 = uv_b.y - uv_a.y
287
+ t2 = uv_c.y - uv_a.y
288
+ r = 1.0 / (s1 * t2 - s2 * t1)
289
+ sdir.set((t2 * x1 - t1 * x2) * r,
290
+ (t2 * y1 - t1 * y2) * r,
291
+ (t2 * z1 - t1 * z2) * r)
292
+ tdir.set((s1 * x2 - s2 * x1) * r,
293
+ (s1 * y2 - s2 * y1) * r,
294
+ (s1 * z2 - s2 * z1) * r)
295
+ tan1[a].add(sdir)
296
+ tan1[b].add(sdir)
297
+ tan1[c].add(sdir)
298
+ tan2[a].add(tdir)
299
+ tan2[b].add(tdir)
300
+ tan2[c].add(tdir)
301
+ }
302
+ @faces.each_with_index do |face, f|
303
+ uv = @face_vertex_uvs[0][f] # use UV layer 0 for tangents
304
+ handle_triangle[self, face.a, face.b, face.c, 0, 1, 2]
305
+ end
306
+ face_index = ['a', 'b', 'c', 'd']
307
+ @faces.each_with_index do |face, f|
308
+ [face.vertex_normals.length, 3].min.times do |i|
309
+ n.copy(face.vertex_normals[i])
310
+ vertex_index = face[face_index[i]]
311
+ t = tan1[vertex_index]
312
+ # Gram-Schmidt orthogonalize
313
+ tmp.copy(t)
314
+ tmp.sub(n.multiply_scalar(n.dot(t))).normalize
315
+ # Calculate handedness
316
+ tmp2.cross_vectors(face.vertex_normals[i], t)
317
+ test = tmp2.dot(tan2[vertex_index])
318
+ w = (test < 0.0) ? - 1.0 : 1.0
319
+ face.vertex_tangents[i] = Mittsu::Vector4.new(tmp.x, tmp.y, tmp.z, w)
320
+ end
321
+ end
322
+ @has_tangents = true
323
+ end
324
+
325
+ def compute_line_distances
326
+ d = 0
327
+ @vertices.each_with_index do |vertex, i|
328
+ if i > 0
329
+ d += vertex.distance_to(@vertices[i - 1])
330
+ end
331
+ @line_distances[i] = d
332
+ end
333
+ end
334
+
335
+ def compute_bounding_box
336
+ @bounding_box ||= Mittsu::Box3.new
337
+ @bounding_box.set_from_points(@vertices)
338
+ end
339
+
340
+ def compute_bounding_sphere
341
+ @bounding_sphere ||= Mittsu::Sphere.new
342
+ @bounding_sphere.set_from_points(@vertices)
343
+ end
344
+
345
+ def merge(geometry, matrix = nil, material_index_offset = nil)
346
+ if !geometry.is_a? Mittsu::Geometry
347
+ puts('ERROR: Mittsu::Geometry#merge: geometry not an instance of Mittsu::Geometry.', geometry.inspect)
348
+ return
349
+ end
350
+ vertexOffset = @vertices.length
351
+ vertices1 = @vertices
352
+ vertices2 = geometry.vertices
353
+ faces1 = @faces
354
+ faces2 = geometry.faces
355
+ uvs1 = @face_vertex_uvs[0]
356
+ uvs2 = geometry.face_vertex_uvs[0]
357
+ material_index_offset ||= 0
358
+ normal_matrix = matrix.nil? ? nil : Mittsu::Matrix3.new.get_normal_matrix(matrix)
359
+ # vertices
360
+ vertices2.each do |vertex|
361
+ vertex_copy = vertex.clone
362
+ vertex_copy.apply_matrix4(matrix) unless matrix.nil?
363
+ vertices1 << vertex_copy
364
+ end
365
+ # faces
366
+ faces2.each do |face|
367
+ face_vertex_normals = face.vertex_normals
368
+ face_vertex_colors = face.vertex_colors
369
+ face_copy = Mittsu::Face3.new(face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset)
370
+ face_copy.normal.copy(face.normal)
371
+ if normal_matrix != nil
372
+ face_copy.normal.apply_matrix3(normal_matrix).normalize unless normal_matrix.nil?
373
+ end
374
+ face_vertex_normals.each do |normal|
375
+ normal = normal.clone
376
+ normal.apply_matrix3(normal_matrix).normalize unless normal_matrix.nil?
377
+ face_copy.vertex_normals << normal
378
+ end
379
+ face_copy.color.copy(face.color)
380
+ face_vertex_colors.each do |color|
381
+ face_copy.vertex_colors << color.clone
382
+ end
383
+ face_copy.materialIndex = face.materialIndex + material_index_offset
384
+ faces1 << face_copy
385
+ end
386
+ # uvs
387
+ uvs2.each do |uv|
388
+ continue if uv.nil?
389
+ uv_copy = []
390
+ uv.each do |u|
391
+ uv_copy << u.clone
392
+ end
393
+ uvs1 << uv_copy
394
+ end
395
+ end
396
+
397
+ def merge_mesh(mesh)
398
+ if mesh instanceof Mittsu::Mesh == false
399
+ puts('ERROR: Mittsu::Geometry#merge_mesh: mesh not an instance of Mittsu::Mesh.', mesh.inspect)
400
+ return
401
+ end
402
+ mesh.matrix_auto_update && mesh.update_matrix
403
+ self.merge(mesh.geometry, mesh.matrix)
404
+ end
405
+
406
+ def merge_vertices
407
+ vertices_map = {} # Hashmap for looking up vertice by position coordinates (and making sure they are unique)
408
+ unique = []; changes = []
409
+ precision_points = 4 # number of decimal points, eg. 4 for epsilon of 0.0001
410
+ precision = 10 ** precision_points
411
+ @vertices.each_with_index do |v, i|
412
+ key = "#{(v.x * precision).round}_#{(v.y * precision).round}_#{(v.z * precision).round}"
413
+ if vertices_map[key].nil?
414
+ vertices_map[key] = i
415
+ unique << v
416
+ changes[i] = unique.length - 1
417
+ else
418
+ #console.log('Duplicate vertex found. ', i, ' could be using ', vertices_map[key])
419
+ changes[i] = changes[vertices_map[key]]
420
+ end
421
+ end
422
+ # if faces are completely degenerate after merging vertices, we
423
+ # have to remove them from the geometry.
424
+ face_indices_to_remove = []
425
+ @faces.each_with_index do |face, i|
426
+ face.a = changes[face.a]
427
+ face.b = changes[face.b]
428
+ face.c = changes[face.c]
429
+ indices = [face.a, face.b, face.c]
430
+ dup_index = -1
431
+ # if any duplicate vertices are found in a Face3
432
+ # we have to remove the face as nothing can be saved
433
+ 3.times do |n|
434
+ if indices[n] == indices[(n + 1) % 3]
435
+ dup_index = n
436
+ face_indices_to_remove << i
437
+ break
438
+ end
439
+ end
440
+ end
441
+ face_indices_to_remove.reverse_each do |idx|
442
+ idx = face_indices_to_remove[i]
443
+ @faces.delete_at idx
444
+ @face_vertex_uvs.each do |uv|
445
+ uv.delete_at idx
446
+ end
447
+ end
448
+ # Use unique set of vertices
449
+ diff = @vertices.length - unique.length
450
+ @vertices = unique
451
+ diff
452
+ end
453
+
454
+ def to_json
455
+ output = {
456
+ metadata: {
457
+ version: 4.0,
458
+ type: 'BufferGeometry',
459
+ generator: 'BufferGeometryExporter'
460
+ },
461
+ uuid: self.uuid,
462
+ type: @type
463
+ }
464
+ output.name = @name unless @name.nil? || @name.empty?
465
+ if @parameters
466
+ @parameters.each do |(key, parameter)|
467
+ output[key] = parameter unless parameter.nil?
468
+ end
469
+ return output
470
+ end
471
+ vertices = []
472
+ @vertices.each do |vert|
473
+ vertices << vertex.x << vertex.y << vertex.z
474
+ end
475
+ faces = []
476
+ normals = []
477
+ normals_hash = {}
478
+ colors = []
479
+ colors_hash = {}
480
+ uvs = []
481
+ uvs_hash = {}
482
+ @faces.each_with_index do |face, i|
483
+ has_material = false # face.materialIndex != nil
484
+ has_face_uv = false # deprecated
485
+ has_face_vertex_uv = @face_vertex_uvs[0][i] != nil
486
+ has_face_normal = face.normal.length > 0
487
+ has_face_vertex_normal = face.vertex_normals.length > 0
488
+ has_face_color = face.color.r != 1 || face.color.g != 1 || face.color.b != 1
489
+ has_face_vertex_color = face.vertex_colors.length > 0
490
+ face_type = 0
491
+ face_type = set_bit(face_type, 0, 0)
492
+ face_type = set_bit(face_type, 1, has_material)
493
+ face_type = set_bit(face_type, 2, has_face_uv)
494
+ face_type = set_bit(face_type, 3, has_face_vertex_uv)
495
+ face_type = set_bit(face_type, 4, has_face_normal)
496
+ face_type = set_bit(face_type, 5, has_face_vertex_normal)
497
+ face_type = set_bit(face_type, 6, has_face_color)
498
+ face_type = set_bit(face_type, 7, has_face_vertex_color)
499
+ faces << face_type
500
+ faces << face.a << face.b << face.c
501
+ # if has_material
502
+ # faces << face.materialIndex
503
+ # end
504
+ if has_face_vertex_uv
505
+ face_vertex_uvs = @face_vertex_uvs[0][i]
506
+ faces << get_uv_index(face_vertex_uvs[0], uvs_hash, uvs)
507
+ faces << get_uv_index(face_vertex_uvs[1], uvs_hash, uvs)
508
+ faces << get_uv_index(face_vertex_uvs[2], uvs_hash, uvs)
509
+ end
510
+ if has_face_normal
511
+ faces << get_normal_index(face.normal)
512
+ end
513
+ if has_face_vertex_normal
514
+ vertex_normals = face.vertex_normals
515
+ faces << get_normal_index(vertex_normals[0], normals_hash, normals)
516
+ faces << get_normal_index(vertex_normals[1], normals_hash, normals)
517
+ faces << get_normal_index(vertex_normals[2], normals_hash, normals)
518
+ end
519
+ if has_face_color
520
+ faces << get_color_index(face.color)
521
+ end
522
+ if has_face_vertex_color
523
+ vertex_colors = face.vertex_colors
524
+ faces << get_color_index(vertex_colors[0], colors_hash, colors)
525
+ faces << get_color_index(vertex_colors[1], colors_hash, colors)
526
+ faces << get_color_index(vertex_colors[2], colors_hash, colors)
527
+ end
528
+ end
529
+ output.data = {}
530
+ output.data.vertices = vertices
531
+ output.data.normals = normals
532
+ output.data.colors = colors unless colors.empty?
533
+ output.data.uvs = [uvs] unless uvs.empty? # temporal backward compatibility
534
+ output.data.faces = faces
535
+
536
+ #
537
+
538
+ output
539
+ end
540
+
541
+ def clone
542
+ geometry = Mittsu::Geometry.new
543
+ @vertices.each do |v|
544
+ geometry.vertices << v.clone
545
+ end
546
+ @faces.each do |f|
547
+ geometry.faces << f.clone
548
+ end
549
+ @face_vertex_uvs.each_with_index do |face_vertex_uvs, i|
550
+ geometry.face_vertex_uvs[i] ||= []
551
+ face_vertex_uvs.each do |uvs|
552
+ uvs_copy = []
553
+ uvs.each do |uv|
554
+ uvs_copy << uv.clone
555
+ end
556
+ geometry.face_vertex_uvs[i] << uvs_copy
557
+ end
558
+ end
559
+ geometry
560
+ end
561
+
562
+ def dispose
563
+ self.dispatch_event type: :dispose
564
+ end
565
+
566
+ private
567
+
568
+ def set_bit(value, position, enabled)
569
+ enabled ? value | (1 << position) : value & (~(1 << position))
570
+ end
571
+
572
+ def get_normal_index(normal, normals_hash, normals)
573
+ hash = normal.x.to_s + normal.y.to_s + normal.z.to_s
574
+ return normals_hash[hash] unless normals_hash[hash].nil?
575
+ normals_hash[hash] = normals.length / 3
576
+ normals << normal.x << normal.y << normal.z
577
+ normals_hash[hash]
578
+ end
579
+
580
+ def get_color_index(color, color_hash, colors)
581
+ hash = color.r.to_s + color.g.to_s + color.b.to_s
582
+ return colors_hash[hash] unless colors_hash[hash].nil?
583
+ colors_hash[hash] = colors.length
584
+ colors << color.get_hex
585
+ colors_hash[hash]
586
+ end
587
+
588
+ def get_uv_index(uv, uvs_hash, uvs)
589
+ hash = uv.x.to_s + uv.y.to_s
590
+ return uvs_hash[hash] unless uvs_hash[hash].nil?
591
+ uvs_hash[hash] = uvs.length / 2
592
+ uvs << uv.x << uv.y
593
+ return uvs_hash[hash]
594
+ end
595
+ end
596
+ end