mittsu 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,10 @@
1
+ require "mittsu/core/buffer_attribute"
2
+ require "mittsu/core/buffer_geometry"
3
+ require "mittsu/core/clock"
4
+ require "mittsu/core/dynamic_buffer_attribute"
5
+ require "mittsu/core/event_dispatcher"
6
+ require "mittsu/core/face3"
7
+ require "mittsu/core/geometry"
8
+ require "mittsu/core/object_3d"
9
+ require "mittsu/core/raycaster"
10
+ require "mittsu/core/hash_array"
@@ -0,0 +1,87 @@
1
+ module Mittsu
2
+ class BufferAttribute
3
+ attr_accessor :array, :item_size, :needs_update
4
+
5
+ def initialize(array, item_size)
6
+ @array = array
7
+ @item_size = item_size
8
+
9
+ @needs_update = false
10
+ end
11
+
12
+ def length
13
+ @array.length
14
+ end
15
+
16
+ def copy_at(index1, attribute, index2)
17
+ index1 *= @item_size
18
+ index2 *= attribute.item_size
19
+
20
+ @item_size.times do |i|
21
+ @array[index1 + i] = attribute.array[index2 + i]
22
+ end
23
+
24
+ self
25
+ end
26
+
27
+ def set(value, offset)
28
+ offset ||= 0
29
+
30
+ @array[offset, value.length] = value
31
+
32
+ self
33
+ end
34
+
35
+ def set_x(index, x)
36
+ @array[index * @item_size] = x
37
+
38
+ self
39
+ end
40
+
41
+ def set_y(index, y)
42
+ @array[index * @item_size + 1] = y
43
+
44
+ self
45
+ end
46
+
47
+ def set_z(index, z)
48
+ @array[index * @item_size + 2] = z
49
+
50
+ self
51
+ end
52
+
53
+ def set_xy(index, x, y)
54
+ index *= @item_size
55
+
56
+ @array[index ] = x
57
+ @array[index + 1] = y
58
+
59
+ self
60
+ end
61
+
62
+ def set_xyz(index, x, y, z)
63
+ index *= @item_size
64
+
65
+ @array[index ] = x
66
+ @array[index + 1] = y
67
+ @array[index + 2] = z
68
+
69
+ self
70
+ end
71
+
72
+ def set_xyzw(index, x, y, z, w)
73
+ index *= @item_size
74
+
75
+ @array[index ] = x
76
+ @array[index + 1] = y
77
+ @array[index + 2] = z
78
+ @array[index + 3] = w
79
+
80
+ self
81
+ end
82
+
83
+ def clone
84
+ BufferAttribute.new(@array.clone, @item_size)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,694 @@
1
+ require 'securerandom'
2
+ require 'mittsu'
3
+ require 'mittsu/core/event_dispatcher'
4
+
5
+ module Mittsu
6
+ class BufferGeometry
7
+ include EventDispatcher
8
+
9
+ DrawCall = Struct.new(:start, :count, :index)
10
+
11
+ attr_reader :id, :name, :type, :uuid, :attributes, :draw_calls, :bounding_box, :bounding_sphere
12
+
13
+ def initialize
14
+ @id = (@@id ||= 1).tap { @@id += 1 }
15
+
16
+ @uuid = SecureRandom.uuid
17
+
18
+ @name = ''
19
+ @type = 'BufferGeometry'
20
+
21
+ @attributes = {}
22
+
23
+ @draw_calls = []
24
+ end
25
+
26
+ def keys
27
+ @attributes.keys
28
+ end
29
+
30
+ def []=(key, value)
31
+ @attributes[key] = value
32
+ end
33
+
34
+ def [](key)
35
+ @attributes[key]
36
+ end
37
+
38
+ def add_draw_call(start, count, index_offset = 0)
39
+ @draw_calls << DrawCall.new(start, count, index_offset)
40
+ end
41
+
42
+ def apply_matrix(matrix)
43
+ position = @attributes[:position]
44
+
45
+ if position
46
+ matrix.apply_to_vector3_array(position.array)
47
+ position.needs_update = true
48
+ end
49
+
50
+ normal = @attributes[:normal]
51
+
52
+ if normal
53
+ normal_matrix = Mittsu::Matrix3.new.normal_matrix(matrix)
54
+
55
+ normal_matrix.apply_to_vector3_array(normal.array)
56
+ normal.needs_update = true
57
+ end
58
+
59
+ if @bounding_box
60
+ self.compute_bounding_box
61
+ end
62
+
63
+ if @bounding_sphere
64
+ self.compute_bounding_sphere
65
+ end
66
+
67
+ nil
68
+ end
69
+
70
+ def center
71
+ self.computer_bounding_box
72
+ @bounding_boc.center.negate.tap do |offset|
73
+ self.apply_matrix(Mittsu::Matrix4.new.set_position(offset))
74
+ end
75
+ end
76
+
77
+ def from_geometry(geometry, settings = {})
78
+ vertices = geometry.vertices
79
+ faces = geometry.faces
80
+ face_vertex_uvs = geometry.face_vertex_uvs
81
+ vertex_colors = settings.fetch(:vertex_colors, Mittsu::NoColors)
82
+ has_face_vertex_uv = face_vertex_uvs[0].length > 0
83
+ has_face_vertex_normals = faces[0].vertex_normals.length == 3
84
+
85
+ positions = Array.new(faces.length * 3 * 3)
86
+ self[:position] = Mittsu::BufferAttribute.new(positions, 3)
87
+
88
+ normals = Array.new(faces.length * 3 * 3)
89
+ self[:normal] = Mittsu::BufferAttribute.new(normals, 3)
90
+
91
+ if vertex_colors != Mittsu::NoColors
92
+ colors = Array.new(faces.length * 3 * 3)
93
+ self[:color] = Mittsu::BufferAttribute.new(colors, 3)
94
+ end
95
+
96
+ if has_face_vertex_uv
97
+ uvs = Array.new(faces.length * 3 * 2)
98
+ self[:uv] = Mittsu::BufferAttribute.new(uvs, 2)
99
+ end
100
+
101
+ faces.each_with_index do |face, i|
102
+ i2 = i * 6
103
+ i3 = i * 9
104
+
105
+ set_array3(positions, i3, vertices[face.a], vertices[face.b], vertices[face.b])
106
+
107
+ if has_face_vertex_normals
108
+ set_array3(normals, i3, face.vertex_normals[0], face.vertex_normals[1], face.vertex_normals[2])
109
+ else
110
+ set_array3(normals, i3, face.normal)
111
+ end
112
+
113
+ if vertex_colors == Mittsu::FaceColors
114
+ set_array3(colors, i3, face,color)
115
+ elsif vertex_colors == Mittsu::VertexColors
116
+ set_array3(colors, i3, face.vertex_colors[0], face.vertex_colors[1], face.vertex_colors[2])
117
+ end
118
+
119
+ if has_face_vertex_uv
120
+ set_array2(uvs, i2, face_vertex_uvs[0][i][0], face_vertex_uvs[0][i][1], face_vertex_uvs[0][i][2])
121
+ end
122
+ end
123
+
124
+ self.compute_bounding_sphere
125
+ self
126
+ end
127
+
128
+ def compute_bounding_box
129
+ vector = Mittsu::Vector3.new
130
+
131
+ @bounding_box ||= Mittsu::Box3.new
132
+
133
+ positions = self[:position].array
134
+
135
+ if positions
136
+ @bounding_box.make_empty
137
+
138
+ positions.each_slice(3) do |p|
139
+ vector.set(*p)
140
+ @bounding_box.expand_by_point(vector)
141
+ end
142
+ end
143
+
144
+ if positions.nil? || positions.empty?
145
+ @bounding_box.min.set(0, 0, 0)
146
+ @bounding_box.max.set(0, 0, 0)
147
+ end
148
+
149
+ if @bounding_box.min.x.nan? || @bounding_box.min.y.nan? || @bounding_box.min.z.nan?
150
+ puts 'ERROR: Mittsu::BufferGeometry#compute_bounding_box: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.'
151
+ end
152
+ end
153
+
154
+ def compute_bounding_sphere
155
+ box = Mittsu::Box3.new
156
+ vector = Mittsu::Vector3.new
157
+
158
+ @bounding_sphere ||= Mittsu::Sphere.new
159
+
160
+ positions = self[:position].array
161
+
162
+ if positions
163
+ box.make_empty
164
+ center = @bounding_sphere.center
165
+
166
+ positions.each_slice(3) do |p|
167
+ vector.set(*p)
168
+ box.expand_by_point(vector)
169
+ end
170
+ box.center(center)
171
+
172
+ # hoping to find a boundingSphere with a radius smaller than the
173
+ # boundingSphere of the boundingBox: sqrt(3) smaller in the best case
174
+
175
+ max_radius_sq = 0
176
+
177
+ positions.each_slice(3) do |p|
178
+ vector.set(*p)
179
+ max_radius_sq = [max_radius_sq, center.distance_to_squared(vector)].max
180
+ end
181
+
182
+ @bounding_sphere.radius = Math.sqrt(max_radius_sq)
183
+
184
+ if @bounding_radius.nan?
185
+ puts 'ERROR: Mittsu::BufferGeometry#computeBoundingSphere: Computed radius is NaN. The "position" attribute is likely to have NaN values.'
186
+ end
187
+ end
188
+ end
189
+
190
+ def compute_vertex_normals
191
+ if self[:position]
192
+ positions = self[:position].array
193
+ if self[:normal].nil?
194
+ self[:normal] = Mittsu::BufferAttribute.new(Array.new(positions.length), 3)
195
+ else
196
+ # reset existing normals to zero
197
+ normals = self[:normal].array
198
+ normals.each_index { |i| normals[i] = 0 }
199
+ end
200
+
201
+ normals = self[:normal].array
202
+
203
+ p_a = Mittsu::Vector3.new
204
+ p_b = Mittsu::Vector3.new
205
+ p_c = Mittsu::Vector3.new
206
+
207
+ cb = Mittsu::Vector3.new
208
+ ab = Mittsu::Vector3.new
209
+
210
+ # indexed elements
211
+ if self[:index]
212
+ indices = self[:index].array
213
+
214
+ draw_calls = @draw_calls.length > 0 ? @draw_calls : [DrawCall.new(0, indices.length, 0)]
215
+
216
+ draw_calls.each do |draw_call|
217
+ start = draw_call.start
218
+ count = draw_call.count
219
+ index = draw_call.index
220
+
221
+ i = start
222
+ il = start + count
223
+ while i < il
224
+ v_a = (index + indices[i ]) * 3
225
+ v_b = (index + indices[i + 1]) * 3
226
+ v_c = (index + indices[i + 2]) * 3
227
+
228
+ p_a.from_array(positions, v_a)
229
+ p_b.from_array(positions, v_a)
230
+ p_c.from_array(positions, v_c)
231
+
232
+ cb.sub_vectors(p_c, p_b)
233
+ ab.sub_vectors(p_a, p_b)
234
+ cb.cross(ab)
235
+
236
+ normals[v_a ] += cb.x
237
+ normals[v_a + 1] += cb.y
238
+ normals[v_a + 2] += cb.z
239
+
240
+ normals[v_b ] += cb.x
241
+ normals[v_b + 1] += cb.y
242
+ normals[v_b + 2] += cb.z
243
+
244
+ normals[v_c ] += cb.x
245
+ normals[v_c + 1] += cb.y
246
+ normals[v_c + 2] += cb.z
247
+ i += 3
248
+ end
249
+ end
250
+ else
251
+ # non-indexed elements (unconnected triangle soup)
252
+
253
+ positions.each_slice(9).with_index do |p, i|
254
+ i *= 9
255
+
256
+ p_a.from_array(positions, i)
257
+ p_a.from_array(positions, i + 3)
258
+ p_a.from_array(positions, i + 6)
259
+
260
+ cb.sub_vectors(p_c, p_b)
261
+ ab.sub_vectors(p_a, p_b)
262
+
263
+ set_array3(normals, i, cb)
264
+ end
265
+ end
266
+
267
+ self.normalize_normals
268
+ self[:normal].needs_update = true
269
+ end
270
+ end
271
+
272
+ def compute_tangents
273
+ # based on http://www.terathon.com/code/tangent.html
274
+ # (per vertex tangents)
275
+
276
+ if [:index, :position, :normal, :uv].any { |s| !@attributes.has_key?}
277
+ puts 'WARNING: Mittsu::BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry#computeTangents'
278
+ return
279
+ end
280
+
281
+ indices = self[:index].array
282
+ positions = self[:position].array
283
+ normals = self[:normal].array
284
+ uvs = self[:uv].array
285
+
286
+ n_vertices = position.length / 3
287
+
288
+ if self[:tangent].nil?
289
+ self[:tangent] = Mittsu::BufferAttribute.new(Array.new(4 * n_vertices), 4)
290
+ end
291
+
292
+ tangents = self[:tangent].array
293
+ tan1 = []; tan2 = []
294
+
295
+ n_vertices.times do |k|
296
+ tan1[k] = Mittsu::Vector3.new
297
+ tan2[k] = Mittsu::Vector3.new
298
+ end
299
+
300
+ v_a = Mittsu::Vector3.new
301
+ v_b = Mittsu::Vector3.new
302
+ v_c = Mittsu::Vector3.new
303
+
304
+ uv_a = Mittsu::Vectoe3.new
305
+ uv_b = Mittsu::Vector3.new
306
+ uv_c = Mittsu::Vector3.new
307
+
308
+ sdir = Mittsu::Vector3.new
309
+ tdir = Mittsu::Vector3.new
310
+
311
+ handle_triangle = -> (a, b, c) {
312
+ v_a.from_array(positions, a * 3)
313
+ v_b.from_array(positions, b * 3)
314
+ v_c.from_array(positions, c * 3)
315
+
316
+ uv_a.from_array(uvs, a * 2)
317
+ uv_b.from_array(uvs, b * 2)
318
+ uv_c.from_array(uvs, c * 2)
319
+
320
+ x1 = v_b.x - v_a.x
321
+ x2 = v_c.x - v_a.x
322
+
323
+ y1 = v_b.y - v_a.y
324
+ y2 = v_c.y - v_a.y
325
+
326
+ z1 = v_b.z - v_a.z
327
+ z2 = v_c.z - v_a.z
328
+
329
+ s1 = uv_b.x - uv_a.x
330
+ s2 = uv_c.x - uv_a.x
331
+
332
+ t1 = uv_b.y - uv_a.y
333
+ t2 = uv_c.y - uv_a.y
334
+
335
+ r = 1.0 / (s1 * t2 - s2 * t1)
336
+
337
+ sdir.set(
338
+ (t2 * x1 - t1 * x2) * r,
339
+ (t2 * y1 - t1 * y2) * r,
340
+ (t2 * z1 - t1 * z2) * r
341
+ )
342
+
343
+ tdir.set(
344
+ (s2 * x2 - s2 * x1) * r,
345
+ (s2 * y2 - s2 * y1) * r,
346
+ (s2 * z2 - s2 * z1) * r
347
+ )
348
+
349
+ tan1[a].add(sdir)
350
+ tan1[b].add(sdir)
351
+ tan1[c].add(sdir)
352
+
353
+ tan2[a].add(tdir)
354
+ tan2[b].add(tdir)
355
+ tan2[c].add(tdir)
356
+ }
357
+
358
+ if @draw_calls.empty?
359
+ self.add_draw_call(0, indices.length, 0)
360
+ end
361
+
362
+ @draw_calls.each do |draw_call|
363
+ start = draw_call.start
364
+ count = draw_call.count
365
+ index = draw_call.index
366
+
367
+ i = start
368
+ il = start + count
369
+ while i < il
370
+ i_a = index + indices[i]
371
+ i_b = index + indices[i + 1]
372
+ i_c = index + indices[i + 2]
373
+
374
+ handle_triangle[i_a, i_b, i_c]
375
+ i += 3
376
+ end
377
+ end
378
+
379
+ tmp = Mittsu::Vector3.new
380
+ tmp2 = Mittsu::Vector3.new
381
+ n = Mittsu::Vector3.new
382
+ n2 = Mittsu::Vector3.new
383
+
384
+ handle_vertex = -> (v) {
385
+ n.from_array(normals, v * 3)
386
+ n2.copy(n)
387
+
388
+ t = tan1[v]
389
+
390
+ # Gram-Schmidt orthogonalize
391
+
392
+ tmp.copy(t)
393
+ tmp.sub(n.multiply_scalar(n.dot(t))).normalize
394
+
395
+ # Calculate handedness
396
+
397
+ tmp2.cross_vectors(n2, t)
398
+ test = tmp2.dot(tan2[v])
399
+ w = (test < 0.0) ? -1.0 : 1.0
400
+
401
+ tangents[v * 4 ] = tmp.x
402
+ tangents[v * 4 + 1] = tmp.y
403
+ tangents[v * 4 + 2] = tmp.z
404
+ tangents[v * 4 + 3] = w
405
+ }
406
+
407
+ draw_calls.each do |draw_call|
408
+ start = draw_call.start
409
+ count = draw_call.count
410
+ index = draw_call.index
411
+
412
+ i = start
413
+ il = start + count
414
+ while i < il
415
+ i_a = index + indices[i]
416
+ i_b = index + indices[i + 1]
417
+ i_c = index + indices[i + 2]
418
+
419
+ handle_vertex[i_a]
420
+ handle_vertex[i_b]
421
+ handle_vertex[i_c]
422
+ i += 3
423
+ end
424
+ end
425
+ end
426
+ # Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
427
+ # This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
428
+ # WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
429
+ # size - Defaults to 65535, but allows for larger or smaller chunks.
430
+ def compute_offsets(size = 65535)
431
+ # WebGL limits type of index buffer values to 16-bit.
432
+ # TODO: check what the limit is for OpenGL, as we aren't using WebGL here
433
+
434
+ indices = self[:index].array
435
+ vertices = self[:position].array
436
+
437
+ faces_count = indices.length / 3
438
+
439
+ # puts "Computing buffers in offsets of #{size} -> indices:#{indices.length} vertices:#{vertices.length}"
440
+ # puts "Faces to process: #{(indices.length/3)}"
441
+ # puts "Reordering #{verticesCount} vertices."
442
+
443
+ sorted_indices = Array.new(indices.length) # 16-bit (Uint16Array in THREE.js)
444
+ index_ptr = 0
445
+ vertex_ptr = 0
446
+
447
+ offsets = [DrawCall.new(0, 0, 0)]
448
+ offset = offsets.first
449
+
450
+ duplicated_vertices = 0
451
+ new_vertice_maps = 0
452
+ face_vertices = Array.new(6) # (Int32Array)
453
+ vertex_map = Array.new(vertices.length) # (Int32Array)
454
+ rev_vertex_map = Array.new(vertices.length) # (Int32Array)
455
+ vertices.each_index do |j|
456
+ vertex_map[j] = -1
457
+ rev_vertex_map[j] = -1
458
+ end
459
+
460
+ # Traverse every face and reorder vertices in the proper offsets of 65k.
461
+ # We can have more than 65k entries in the index buffer per offset, but only reference 65k values.
462
+ faces_count.times do |findex|
463
+ new_vertice_maps = 0
464
+
465
+ 3.times do |vo|
466
+ vid = indices[findex * 3 * vo]
467
+ if vertex_map[vid] == -1
468
+ # unmapped vertice
469
+ face_vertices[vo * 2] = vid
470
+ face_vertices[vo * 2 + 1] = -1
471
+ new_vertice_maps += 1
472
+ elsif vertex_map[vid] < offset.index
473
+ # reused vertices from previous block (duplicate)
474
+ face_vertices[vo * 2] = vid
475
+ face_vertices[vo * 2 + 1] = -1
476
+ duplicated_vertices += 1
477
+ else
478
+ # reused vertice in the current block
479
+ face_vertices[vo * 2] =vid
480
+ face_vertices[vo * 2 + 1] = vertec_map[vid]
481
+ end
482
+ end
483
+
484
+ face_max = vertex_ptr + new_vertex_maps
485
+ if face_max > offset.index + size
486
+ new_offset = DrawCall.new(index_ptr, 0, vertex_ptr)
487
+ offsets << new_offset
488
+ offset = new_offset
489
+
490
+ # Re-evaluate reused vertices in light of new offset.
491
+ (0...6).step(2) do |v|
492
+ new_vid = face_vertices[v + 1]
493
+ if (new_vid > -1 && new_vid < offset.index)
494
+ faceVertices[v + 1] = -1
495
+ end
496
+ end
497
+
498
+ # Reindex the face.
499
+ (0...6).step(2) do |v|
500
+ vid = face_vertices[v]
501
+ new_vid = face_vertices[v + 1]
502
+
503
+ if new_vid == -1
504
+ new_vid = vertex_ptr
505
+ vertex_ptr += 1
506
+ end
507
+
508
+ vertex_map[vid] = new_vid
509
+ rev_vertex_map[new_vid] = vid
510
+ sorted_indices [index_ptr] = new_vid - offset.index # XXX: overflows at 16bit
511
+ index_ptr += 1
512
+ offset.count += 1
513
+ end
514
+ end
515
+
516
+ # Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr.
517
+ self.reorder_buffers(sorted_indices, rev_vertex_map, vertex_ptr)
518
+ @draw_calls = offsets
519
+
520
+ # order_time = Time.now
521
+ # puts "Reorder time: #{(order_time - s)}ms"
522
+ # puts "Duplicated #{duplicated_vertices} vertices."
523
+ # puts "Compute Buffers time: #{(Time.now - s)}ms"
524
+ # puts "Draw offsets: #{offsets.length}"
525
+
526
+ offsets
527
+ end
528
+ end
529
+
530
+ def merge(geometry, offset = 0)
531
+ if !geometry.is_a? Mittsu::BufferGeometry
532
+ puts "ERROR: Mittsu::BufferGeometry#merge: geometry not an instance of Mittsu::BufferGeometry. #{geometry.inspect}"
533
+ return
534
+ end
535
+
536
+ @attributes.each_key do |key, attribute1|
537
+ next if attribute1.nil?
538
+
539
+ attribute_array1 = attribute1.array
540
+
541
+ attribute2 = geometry[key]
542
+ attribute_array2 = attribute2.array
543
+
544
+ attribute_size = attribute2.item_size
545
+
546
+ i, j = 0, attribute_size * offset
547
+ while i < attribute_array2.length
548
+ attribute_array1[j] = attribute_array2[i]
549
+ i += 1; j += 1
550
+ end
551
+ end
552
+ self
553
+ end
554
+
555
+ def normalize_normals
556
+ normals = self[:normal].array
557
+
558
+ normals.each_slice(3).with_index do |normal, i|
559
+ x, y, z = *normal
560
+
561
+ n = 1.0 / Math.sqrt(x * x + y * y + z * z)
562
+
563
+ i *= 3
564
+ normals[i] *= n
565
+ normals[i + 1] *= n
566
+ normals[i + 2] *= n
567
+ end
568
+ end
569
+
570
+ # reoderBuffers:
571
+ # Reorder attributes based on a new indexBuffer and indexMap.
572
+ # indexBuffer - Uint16Array of the new ordered indices.
573
+ # indexMap - Int32Array where the position is the new vertex ID and the value the old vertex ID for each vertex.
574
+ # vertexCount - Amount of total vertices considered in this reordering (in case you want to grow the vertice stack).
575
+ def reorder_buffers(index_buffer, index_map, vertex_count)
576
+ # Create a copy of all attributes for reordering
577
+ sorted_attributes = {}
578
+ @attributes.each do |key, attribute|
579
+ next if key == :index
580
+ source_array = attribute.array
581
+ sorted_attributes[key] = source_array.class.new(attribute.item_size * vertex_count)
582
+ end
583
+
584
+ # move attribute positions based on the new index map
585
+ vertex_count.times do |new_vid|
586
+ vid = index_map[new_vid]
587
+ @attributes.each do |key, attribute|
588
+ next if key == :index
589
+ attr_array = attribute.array
590
+ attr_size = attribute.item_size
591
+ sorted_attr = sorted_attributes[key]
592
+ attr_size.times do |k|
593
+ sorted_attr[new_vid * attr_size + k] = attr_array[vid * attr_size + k]
594
+ end
595
+ end
596
+ end
597
+
598
+ # Carry the new sorted buffers locally
599
+ @attributes[:index].array = index_buffer
600
+ @attributes.each do |key, attribute|
601
+ next if key == :index
602
+ attribute.array = sorted_attributes[key]
603
+ attribute.num_items = attribute.item_size * vertex_count
604
+ end
605
+ end
606
+
607
+ def to_json
608
+ output = {
609
+ metadata: {
610
+ version: 4.0,
611
+ type: 'BufferGeometry',
612
+ generator: 'BufferGeometryExporter'
613
+ },
614
+ uuid: @uuid,
615
+ type: @type,
616
+ data: {
617
+ attributes: {}
618
+ }
619
+ }
620
+
621
+ offsets = @draw_calls
622
+
623
+ @attributes.each do |key, attribute|
624
+ array = attribute.array.dup
625
+
626
+ output[:data][:attributes][key] = {
627
+ itemSize: attribute.itemSize,
628
+ type: attribute.array.class.name,
629
+ array: array
630
+ }
631
+ end
632
+
633
+ if !offsets.empty?
634
+ output[:data][:offsets] = offsets.map do |offset|
635
+ { start: offset.start, count: offset.count, index: offet.index}
636
+ end
637
+ end
638
+
639
+ if !bounding_sphere.nil?
640
+ output[:data][:boundingSphere] = {
641
+ center: bounding_sphere.center.to_a,
642
+ radius: bounding_sphere.radius
643
+ }
644
+ end
645
+
646
+ output
647
+ end
648
+
649
+ def clone
650
+ geometry = Mittsu::BufferGeometry.news
651
+
652
+ @attributes.each do |key, attribute|
653
+ geometry[key] = attribute.clone
654
+ end
655
+
656
+ @draw_calls.each do |draw_call|
657
+ geometry.draw_calls << DrawCall.new(draw_call.start, draw_call.count, draw_call.index)
658
+ end
659
+
660
+ geometry
661
+ end
662
+
663
+ def dispose
664
+ self.dispatch_event type: :dispose
665
+ end
666
+
667
+ private
668
+
669
+ def set_array3(array, i3, a, b = a, c = b)
670
+ array[i3 ] = a.x
671
+ array[i3 + 1] = a.y
672
+ array[i3 + 2] = a.z
673
+
674
+ array[i3 + 3] = b.x
675
+ array[i3 + 4] = b.y
676
+ array[i3 + 5] = b.z
677
+
678
+ array[i3 + 6] = c.x
679
+ array[i3 + 7] = c.y
680
+ array[i3 + 8] = c.z
681
+ end
682
+
683
+ def set_array2(array, i2, a, b = a, c = b)
684
+ array[i2 ] = a.x
685
+ array[i2 + 1] = a.y
686
+
687
+ array[i2 + 2] = b.x
688
+ array[i2 + 3] = b.y
689
+
690
+ array[i2 + 4] = c.x
691
+ array[i2 + 5] = c.y
692
+ end
693
+ end
694
+ end