mittsu 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.md +1 -1
- data/lib/mittsu/cameras/orthographic_camera.rb +13 -0
- data/lib/mittsu/cameras/perspective_camera.rb +11 -0
- data/lib/mittsu/core/geometry.rb +12 -9
- data/lib/mittsu/core/object_3d.rb +33 -66
- data/lib/mittsu/lights/ambient_light.rb +8 -0
- data/lib/mittsu/lights/directional_light.rb +9 -0
- data/lib/mittsu/lights/hemisphere_light.rb +9 -0
- data/lib/mittsu/lights/point_light.rb +11 -0
- data/lib/mittsu/lights/spot_light.rb +13 -0
- data/lib/mittsu/loaders.rb +1 -0
- data/lib/mittsu/loaders/mtl_loader.rb +5 -12
- data/lib/mittsu/loaders/obj_loader.rb +212 -0
- data/lib/mittsu/loaders/obj_mtl_loader.rb +11 -207
- data/lib/mittsu/materials/material.rb +5 -2
- data/lib/mittsu/materials/mesh_basic_material.rb +0 -9
- data/lib/mittsu/math/color.rb +44 -104
- data/lib/mittsu/math/matrix3.rb +8 -1
- data/lib/mittsu/math/matrix4.rb +6 -0
- data/lib/mittsu/math/vector.rb +251 -0
- data/lib/mittsu/math/vector2.rb +14 -213
- data/lib/mittsu/math/vector3.rb +61 -351
- data/lib/mittsu/math/vector4.rb +45 -295
- data/lib/mittsu/objects/line.rb +12 -2
- data/lib/mittsu/objects/mesh.rb +18 -9
- data/lib/mittsu/renderers/glfw_window.rb +15 -13
- data/lib/mittsu/renderers/opengl/core/opengl_geometry.rb +253 -0
- data/lib/mittsu/renderers/opengl/core/opengl_object_3d.rb +131 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_ambient_light.rb +26 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_directional_light.rb +35 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_hemisphere_light.rb +42 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_light.rb +52 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_point_light.rb +36 -0
- data/lib/mittsu/renderers/opengl/lights/opengl_spot_light.rb +47 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_line_basic_material.rb +16 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_material.rb +275 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_mesh_basic_material.rb +69 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_mesh_lambert_material.rb +29 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_mesh_phong_material.rb +40 -0
- data/lib/mittsu/renderers/opengl/materials/opengl_shader_material.rb +11 -0
- data/lib/mittsu/renderers/opengl/objects/opengl_group.rb +8 -0
- data/lib/mittsu/renderers/opengl/objects/opengl_line.rb +54 -0
- data/lib/mittsu/renderers/opengl/objects/opengl_mesh.rb +77 -0
- data/lib/mittsu/renderers/opengl/opengl_buffer.rb +5 -0
- data/lib/mittsu/renderers/opengl/opengl_debug.rb +49 -7
- data/lib/mittsu/renderers/opengl/opengl_default_target.rb +54 -0
- data/lib/mittsu/renderers/opengl/opengl_geometry_group.rb +763 -0
- data/lib/mittsu/renderers/opengl/opengl_geometry_like.rb +130 -0
- data/lib/mittsu/renderers/opengl/opengl_helper.rb +161 -0
- data/lib/mittsu/renderers/opengl/opengl_implementations.rb +61 -0
- data/lib/mittsu/renderers/opengl/opengl_light_renderer.rb +43 -0
- data/lib/mittsu/renderers/opengl/opengl_mittsu_params.rb +53 -0
- data/lib/mittsu/renderers/opengl/opengl_program.rb +147 -296
- data/lib/mittsu/renderers/opengl/opengl_state.rb +3 -5
- data/lib/mittsu/renderers/opengl/plugins/shadow_map_plugin.rb +12 -10
- data/lib/mittsu/renderers/opengl/scenes/opengl_scene.rb +8 -0
- data/lib/mittsu/renderers/opengl/textures/opengl_compressed_texture.rb +21 -0
- data/lib/mittsu/renderers/opengl/textures/opengl_cube_texture.rb +75 -0
- data/lib/mittsu/renderers/opengl/textures/opengl_data_texture.rb +23 -0
- data/lib/mittsu/renderers/opengl/textures/opengl_texture.rb +111 -0
- data/lib/mittsu/renderers/opengl_render_target.rb +117 -2
- data/lib/mittsu/renderers/opengl_renderer.rb +653 -2978
- data/lib/mittsu/renderers/shaders/rbsl_loader.rb +166 -0
- data/lib/mittsu/renderers/shaders/shader_chunk.rb +6 -9
- data/lib/mittsu/renderers/shaders/shader_chunk/shadowmap_fragment.glsl +36 -37
- data/lib/mittsu/renderers/shaders/shader_lib.rb +26 -403
- data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_fragment.rbsl +37 -0
- data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_uniforms.rbslu +3 -0
- data/lib/mittsu/renderers/shaders/shader_lib/basic/basic_vertex.rbsl +33 -0
- data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_fragment.rbsl +12 -0
- data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_uniforms.rbslu +2 -0
- data/lib/mittsu/renderers/shaders/shader_lib/cube/cube_vertex.rbsl +12 -0
- data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_fragment.rbsl +26 -0
- data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_uniforms.rbslu +0 -0
- data/lib/mittsu/renderers/shaders/shader_lib/depth_rgba/depth_rgba_vertex.rbsl +12 -0
- data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_fragment.rbsl +56 -0
- data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_uniforms.rbslu +7 -0
- data/lib/mittsu/renderers/shaders/shader_lib/lambert/lambert_vertex.rbsl +37 -0
- data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_fragment.rbsl +45 -0
- data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_uniforms.rbslu +11 -0
- data/lib/mittsu/renderers/shaders/shader_lib/phong/phong_vertex.rbsl +43 -0
- data/lib/mittsu/renderers/shaders/shader_templates/fragment.glsl.erb +105 -0
- data/lib/mittsu/renderers/shaders/shader_templates/vertex.glsl.erb +143 -0
- data/lib/mittsu/renderers/shaders/uniforms_lib.rb +54 -55
- data/lib/mittsu/textures/texture.rb +5 -2
- data/lib/mittsu/version.rb +1 -1
- data/run_all_examples.sh +7 -0
- metadata +77 -28
- data/.ruby-version +0 -1
- data/lib/mittsu/core/hash_object.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a116d4e3970e8c01c66d77f51eae67c987240017
|
4
|
+
data.tar.gz: ee8cf7cd8bbeeb6936b6609777d1c767a72b48fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fff4b0a5cba6d3088677d89434e7e2af7223d597dd10b438fd92eeb52aa6ab587fd3cb8e406e4a984d8b178d09bf97b9a1325b139ec200bfbf13ad0eecaeab3
|
7
|
+
data.tar.gz: fed0e180de0ae1f9e91af33817c73f2ece532ce8bf5ffcae87655f27278205e819188979a53b742e989c25ab777f5a32bf992d7601e2fd749c51855b85691651
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Mittsu
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/mittsu) [](https://gemnasium.com/jellymann/mittsu) [](https://circleci.com/gh/jellymann/mittsu/tree/master) [](https://badge.fury.io/rb/mittsu) [](https://gemnasium.com/jellymann/mittsu) [](https://circleci.com/gh/jellymann/mittsu/tree/master) [](https://coveralls.io/github/jellymann/mittsu?branch=master) [](https://codeclimate.com/github/jellymann/mittsu)
|
4
4
|
|
5
5
|
3D Graphics Library for Ruby
|
6
6
|
|
@@ -49,5 +49,18 @@ module Mittsu
|
|
49
49
|
|
50
50
|
camera
|
51
51
|
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def jsonify
|
56
|
+
data = super
|
57
|
+
data[:left] = self.left
|
58
|
+
data[:right] = self.right
|
59
|
+
data[:top] = self.top
|
60
|
+
data[:bottom] = self.bottom
|
61
|
+
data[:near] = self.near
|
62
|
+
data[:far] = self.far
|
63
|
+
data
|
64
|
+
end
|
52
65
|
end
|
53
66
|
end
|
data/lib/mittsu/core/geometry.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'mittsu'
|
3
|
-
require 'mittsu/core/hash_object'
|
4
3
|
|
5
4
|
module Mittsu
|
6
|
-
class Geometry
|
5
|
+
class Geometry
|
7
6
|
include EventDispatcher
|
8
7
|
|
9
8
|
MorphNormal = Struct.new(:face_normals, :vertex_normals)
|
@@ -17,7 +16,7 @@ module Mittsu
|
|
17
16
|
|
18
17
|
def initialize
|
19
18
|
super
|
20
|
-
|
19
|
+
|
21
20
|
@id = (@@id ||= 1).tap { @@id += 1 }
|
22
21
|
|
23
22
|
@name = ''
|
@@ -526,12 +525,12 @@ module Mittsu
|
|
526
525
|
faces << get_color_index(vertex_colors[2], colors_hash, colors)
|
527
526
|
end
|
528
527
|
end
|
529
|
-
output
|
530
|
-
output
|
531
|
-
output
|
532
|
-
output
|
533
|
-
output
|
534
|
-
output
|
528
|
+
output[:data] = {}
|
529
|
+
output[:data][:vertices] = vertices
|
530
|
+
output[:data][:normals] = normals
|
531
|
+
output[:data][:colors] = colors unless colors.empty?
|
532
|
+
output[:data][:uvs] = [uvs] unless uvs.empty? # temporal backward compatibility
|
533
|
+
output[:data][:faces] = faces
|
535
534
|
|
536
535
|
#
|
537
536
|
|
@@ -563,6 +562,10 @@ module Mittsu
|
|
563
562
|
self.dispatch_event type: :dispose
|
564
563
|
end
|
565
564
|
|
565
|
+
def implementation(renderer)
|
566
|
+
@_implementation ||= renderer.create_implementation(self)
|
567
|
+
end
|
568
|
+
|
566
569
|
private
|
567
570
|
|
568
571
|
def set_bit(value, position, enabled)
|
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'mittsu'
|
3
|
-
require 'mittsu/core/hash_object'
|
4
3
|
|
5
4
|
module Mittsu
|
6
|
-
class Object3D
|
5
|
+
class Object3D
|
7
6
|
include EventDispatcher
|
8
7
|
|
9
8
|
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
|
@@ -271,7 +270,7 @@ module Mittsu
|
|
271
270
|
|
272
271
|
def traverse_ancestors(&callback)
|
273
272
|
if @parent
|
274
|
-
callback.
|
273
|
+
callback.yield @parent
|
275
274
|
@parent.traverse_ancestors(&callback)
|
276
275
|
end
|
277
276
|
end
|
@@ -308,11 +307,12 @@ module Mittsu
|
|
308
307
|
}
|
309
308
|
@_geometries = {}
|
310
309
|
@_materials = {}
|
311
|
-
@_output[:object] =
|
310
|
+
@_output[:object] = self.jsonify
|
312
311
|
@_output
|
313
312
|
end
|
314
313
|
|
315
|
-
def clone(object =
|
314
|
+
def clone(object = nil, recursive = true)
|
315
|
+
object ||= Object3D.new
|
316
316
|
object.name = @name
|
317
317
|
object.up.copy(@up)
|
318
318
|
object.position.copy(@position)
|
@@ -336,9 +336,34 @@ module Mittsu
|
|
336
336
|
object
|
337
337
|
end
|
338
338
|
|
339
|
-
|
339
|
+
def implementation(renderer)
|
340
|
+
@_implementation ||= renderer.create_implementation(self)
|
341
|
+
end
|
342
|
+
|
343
|
+
protected
|
340
344
|
|
341
|
-
def
|
345
|
+
def jsonify
|
346
|
+
data = {
|
347
|
+
uuid: @uuid,
|
348
|
+
type: @type,
|
349
|
+
matrix: @matrix.to_a
|
350
|
+
}
|
351
|
+
data[:name] = @name unless @name.nil? || @name.empty?
|
352
|
+
data[:user_data] = @user_data unless @user_data.nil? || @user_data.empty?
|
353
|
+
data[:visible] = @visible unless @visible
|
354
|
+
|
355
|
+
if !self.children.empty?
|
356
|
+
data[:children] = @children.map do |child|
|
357
|
+
child.jsonify
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# TODO: implement jsonify for PointCloud
|
362
|
+
|
363
|
+
data
|
364
|
+
end
|
365
|
+
|
366
|
+
def jsonify_geometry(geometry)
|
342
367
|
@_output[:geometries] ||= []
|
343
368
|
if @_geometries[geometry.uuid].nil?
|
344
369
|
json = geometry.to_json
|
@@ -349,7 +374,7 @@ module Mittsu
|
|
349
374
|
geometry.uuid
|
350
375
|
end
|
351
376
|
|
352
|
-
def
|
377
|
+
def jsonify_material(material)
|
353
378
|
@_output[:materials] ||= []
|
354
379
|
if @_materials[material.uuid].nil?
|
355
380
|
json = material.to_json
|
@@ -359,63 +384,5 @@ module Mittsu
|
|
359
384
|
end
|
360
385
|
material.uuid
|
361
386
|
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
387
|
end
|
421
388
|
end
|
@@ -127,5 +127,14 @@ module Mittsu
|
|
127
127
|
light.shadow_cascade_near_z = @shadow_cascade_near_z.dup
|
128
128
|
light.shadow_cascade_far_z = @shadow_cascade_far_z.dup
|
129
129
|
end
|
130
|
+
|
131
|
+
protected
|
132
|
+
|
133
|
+
def jsonify
|
134
|
+
data = super
|
135
|
+
data[:color] = self.color.get_hex
|
136
|
+
data[:intensity] = self.intensity
|
137
|
+
data
|
138
|
+
end
|
130
139
|
end
|
131
140
|
end
|
@@ -23,5 +23,16 @@ module Mittsu
|
|
23
23
|
light.decay = @decay
|
24
24
|
light
|
25
25
|
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def jsonify
|
30
|
+
data = super
|
31
|
+
data[:color] = self.color.get_hex
|
32
|
+
data[:intensity] = self.intensity
|
33
|
+
data[:distance] = self.distance
|
34
|
+
data[:decay] = self.decay
|
35
|
+
data
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
@@ -100,5 +100,18 @@ module Mittsu
|
|
100
100
|
|
101
101
|
return light
|
102
102
|
end
|
103
|
+
|
104
|
+
protected
|
105
|
+
|
106
|
+
def jsonify
|
107
|
+
data = super
|
108
|
+
data[:color] = self.color.get_hex
|
109
|
+
data[:intensity] = self.intensity
|
110
|
+
data[:distance] = self.distance
|
111
|
+
data[:angle] = self.angle
|
112
|
+
data[:exponent] = self.exponent
|
113
|
+
data[:decay] = self.decay
|
114
|
+
data
|
115
|
+
end
|
103
116
|
end
|
104
117
|
end
|
data/lib/mittsu/loaders.rb
CHANGED
@@ -2,15 +2,13 @@ module Mittsu
|
|
2
2
|
class MTLLoader
|
3
3
|
include EventDispatcher
|
4
4
|
|
5
|
-
def initialize(base_url, options = {})
|
5
|
+
def initialize(base_url, options = {})
|
6
6
|
@base_url = base_url
|
7
7
|
@options = options
|
8
|
-
# @cross_origin = cross_origin
|
9
8
|
end
|
10
9
|
|
11
10
|
def load(url)
|
12
11
|
loader = FileLoader.new
|
13
|
-
# loader.cross_origin = @cross_origin
|
14
12
|
|
15
13
|
text = loader.load File.join(@base_url, url)
|
16
14
|
parse(text)
|
@@ -36,14 +34,11 @@ module Mittsu
|
|
36
34
|
value = value.strip
|
37
35
|
|
38
36
|
if key == "newmtl"
|
39
|
-
# New material
|
40
|
-
|
41
37
|
info = { name: value };
|
42
38
|
materials_info[value] = info
|
43
39
|
elsif info
|
44
40
|
if key == "ka" || key == "kd" || key == "ks"
|
45
|
-
|
46
|
-
info[key] = [ss[0].to_f, ss[1].to_f, ss[2].to_f]
|
41
|
+
info[key] = value.split(delimiter_pattern).take(3).map(&:to_f)
|
47
42
|
else
|
48
43
|
info[key] = value
|
49
44
|
end
|
@@ -81,8 +76,7 @@ module Mittsu
|
|
81
76
|
converted = {}
|
82
77
|
|
83
78
|
materials_info.each do |mn, mat|
|
84
|
-
covmat = {}
|
85
|
-
converted[mn] = covmat
|
79
|
+
covmat = converted[mn] ={}
|
86
80
|
|
87
81
|
mat.each do |prop, value|
|
88
82
|
save = true
|
@@ -97,7 +91,7 @@ module Mittsu
|
|
97
91
|
end
|
98
92
|
|
99
93
|
if @options && @options[:ignore_zero_rgbs]
|
100
|
-
if value.take(3).
|
94
|
+
if value.take(3).all?(&:zero?)
|
101
95
|
# ignore
|
102
96
|
save = false
|
103
97
|
end
|
@@ -108,7 +102,7 @@ module Mittsu
|
|
108
102
|
# factor of 1.0 is fully opaque, a factor of 0 is fully dissolved (completely transparent)
|
109
103
|
|
110
104
|
if @options && @options[:invert_transparency]
|
111
|
-
value = 1.0 - value
|
105
|
+
value = 1.0 - value.to_f
|
112
106
|
end
|
113
107
|
end
|
114
108
|
|
@@ -155,7 +149,6 @@ module Mittsu
|
|
155
149
|
texture = Texture.new
|
156
150
|
|
157
151
|
loader = ImageLoader.new
|
158
|
-
# loader.cross_origin = @cross_origin # TODO: ???
|
159
152
|
image = loader.load url
|
160
153
|
|
161
154
|
texture.image = ensure_power_of_two(image)
|
@@ -0,0 +1,212 @@
|
|
1
|
+
module Mittsu
|
2
|
+
class OBJLoader
|
3
|
+
include EventDispatcher
|
4
|
+
|
5
|
+
FLOAT = /[\d|.|+|\-|e]+/
|
6
|
+
|
7
|
+
VERTEX_PATTERN = /^v\s+(#{FLOAT})\s+(#{FLOAT})\s+(#{FLOAT})/
|
8
|
+
NORMAL_PATTERN = /^vn\s+(#{FLOAT})\s+(#{FLOAT})\s+(#{FLOAT})/
|
9
|
+
UV_PATTERN = /^vt\s+(#{FLOAT})\s+(#{FLOAT})/
|
10
|
+
|
11
|
+
FACE_PATTERN = /^f\s+/
|
12
|
+
FACE_V_PATTERN = /^f\s+(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+))?/
|
13
|
+
FACE_V_VT_PATTERN = /^f\s+(\d+)\/(\d+)\s+(\d+)\/(\d+)\s+(\d+)\/(\d+)(?:\s+(\d+)\/(\d+))?/
|
14
|
+
FACE_V_VN_PATTERN = /^f\s+(\d+)\/\/(\d+)\s+(\d+)\/\/(\d+)\s+(\d+)\/\/(\d+)(?:\s+(\d+)\/\/(\d+))?/
|
15
|
+
FACE_V_VT_VN_PATTERN = /^f\s+(\d+)\/(\d+)\/(\d+)\s+(\d+)\/(\d+)\/(\d+)\s+(\d+)\/(\d+)\/(\d+)(?:\s+(\d+)\/(\d+)\/(\d+))?/
|
16
|
+
|
17
|
+
OBJECT_PATTERN = /^o\s+(.+)$/
|
18
|
+
GROUP_PATTERN = /^g\s+(.+)$/
|
19
|
+
SMOOTH_GROUP_PATTERN = /^s\s+(\d|true|false|on|off)$/
|
20
|
+
|
21
|
+
USE_MTL_PATTERN = /^usemtl\s+(.+)$/
|
22
|
+
LOAD_MTL_PATTERN = /^mtllib\s+(.+)$/
|
23
|
+
|
24
|
+
def initialize(manager = DefaultLoadingManager)
|
25
|
+
@manager = manager
|
26
|
+
end
|
27
|
+
|
28
|
+
def load(url)
|
29
|
+
loader = FileLoader.new(@manager)
|
30
|
+
|
31
|
+
text = loader.load(url)
|
32
|
+
parse(text)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse(data)
|
36
|
+
init_parsing
|
37
|
+
relevant_lines(data).each { |line| parse_line(line) }
|
38
|
+
end_object
|
39
|
+
@group
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse_line(line)
|
45
|
+
case line
|
46
|
+
when VERTEX_PATTERN then handle_vertex($1.to_f, $2.to_f, $3.to_f)
|
47
|
+
when NORMAL_PATTERN then handle_normal($1.to_f, $2.to_f, $3.to_f)
|
48
|
+
when UV_PATTERN then handle_uv($1.to_f, $2.to_f)
|
49
|
+
|
50
|
+
when FACE_PATTERN then parse_face(line)
|
51
|
+
|
52
|
+
when OBJECT_PATTERN then new_object($1) and reset_vertices
|
53
|
+
when GROUP_PATTERN # ignore
|
54
|
+
when SMOOTH_GROUP_PATTERN # ignore
|
55
|
+
|
56
|
+
when USE_MTL_PATTERN then set_material($1)
|
57
|
+
when LOAD_MTL_PATTERN # TODO
|
58
|
+
else raise "Mittsu::OBJMTLLoader: Unhandled line #{line}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_face(line)
|
63
|
+
case line
|
64
|
+
when FACE_V_PATTERN then handle_face(
|
65
|
+
[$1, $2, $3, $4]) #face
|
66
|
+
#(uv)
|
67
|
+
#(normal)
|
68
|
+
when FACE_V_VT_PATTERN then handle_face(
|
69
|
+
[$1, $3, $5, $7], #face
|
70
|
+
[$2, $4, $6, $8]) #uv
|
71
|
+
#(normal)
|
72
|
+
when FACE_V_VN_PATTERN then handle_face(
|
73
|
+
[$1, $3, $5, $7 ], #face
|
74
|
+
[], #(uv)
|
75
|
+
[$2, $4, $6, $8 ]) #normal
|
76
|
+
when FACE_V_VT_VN_PATTERN then handle_face(
|
77
|
+
[$1, $4, $7, $10], #face
|
78
|
+
[$2, $5, $8, $11], #uv
|
79
|
+
[$3, $6, $9, $12]) #normal
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def face3(a, b, c, normals = nil)
|
84
|
+
Face3.new(a, b, c, normals)
|
85
|
+
end
|
86
|
+
|
87
|
+
def init_parsing
|
88
|
+
@face_offset = 0
|
89
|
+
@group = Group.new
|
90
|
+
@vertices = []
|
91
|
+
@normals = []
|
92
|
+
@uvs = []
|
93
|
+
end
|
94
|
+
|
95
|
+
def reset_vertices
|
96
|
+
@face_offset = @face_offset + @vertices.length
|
97
|
+
@vertices = []
|
98
|
+
end
|
99
|
+
|
100
|
+
def relevant_lines(raw_lines)
|
101
|
+
raw_lines.split("\n").map(&:strip).reject(&:empty?).reject{|l| l.start_with? '#'}
|
102
|
+
end
|
103
|
+
|
104
|
+
def new_object(object_name = '')
|
105
|
+
end_object
|
106
|
+
@object = Object3D.new
|
107
|
+
@object.name = object_name
|
108
|
+
end
|
109
|
+
|
110
|
+
def end_object
|
111
|
+
return if @object.nil?
|
112
|
+
end_mesh
|
113
|
+
@group.add(@object)
|
114
|
+
@object = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def new_mesh
|
118
|
+
end_mesh
|
119
|
+
new_object if @object.nil?
|
120
|
+
@geometry = Geometry.new
|
121
|
+
@mesh = Mesh.new(@geometry, @material || MeshLambertMaterial.new)
|
122
|
+
@mesh.name = @object.name
|
123
|
+
@mesh.name += " #{@material.name}" unless @material.nil?
|
124
|
+
end
|
125
|
+
|
126
|
+
def end_mesh
|
127
|
+
return if @mesh.nil? || @vertices.empty?
|
128
|
+
@geometry.vertices = @vertices
|
129
|
+
|
130
|
+
@geometry.merge_vertices
|
131
|
+
@geometry.compute_face_normals
|
132
|
+
@geometry.compute_bounding_sphere
|
133
|
+
|
134
|
+
@object.add(@mesh)
|
135
|
+
@mesh = nil
|
136
|
+
end
|
137
|
+
|
138
|
+
def set_material(material_name)
|
139
|
+
end_mesh
|
140
|
+
|
141
|
+
@material = MeshLambertMaterial.new
|
142
|
+
@material.name = material_name
|
143
|
+
end
|
144
|
+
|
145
|
+
def handle_vertex(x, y, z)
|
146
|
+
@vertices << Vector3.new(x, y, z)
|
147
|
+
end
|
148
|
+
|
149
|
+
def handle_normal(x, y, z)
|
150
|
+
@normals << Vector3.new(x, y, z)
|
151
|
+
end
|
152
|
+
|
153
|
+
def handle_uv(u, v)
|
154
|
+
@uvs << Vector2.new(u, v)
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_face(a, b, c, normal_inds = nil)
|
158
|
+
if normal_inds.nil?
|
159
|
+
@geometry.faces << face3(
|
160
|
+
a.to_i - (@face_offset + 1),
|
161
|
+
b.to_i - (@face_offset + 1),
|
162
|
+
c.to_i - (@face_offset + 1)
|
163
|
+
)
|
164
|
+
else
|
165
|
+
@geometry.faces << face3(
|
166
|
+
a.to_i - (@face_offset + 1),
|
167
|
+
b.to_i - (@face_offset + 1),
|
168
|
+
c.to_i - (@face_offset + 1),
|
169
|
+
normal_inds.take(3).map { |i| @normals[i.to_i - 1].clone }
|
170
|
+
)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_uvs(a, b, c)
|
175
|
+
@geometry.face_vertex_uvs[0] << [
|
176
|
+
@uvs[a.to_i - 1].clone,
|
177
|
+
@uvs[b.to_i - 1].clone,
|
178
|
+
@uvs[c.to_i - 1].clone
|
179
|
+
]
|
180
|
+
end
|
181
|
+
|
182
|
+
def handle_triangle(faces, uvs, normal_inds)
|
183
|
+
add_face(faces[0], faces[1], faces[2], normal_inds)
|
184
|
+
|
185
|
+
if !uvs.nil? && !uvs.empty?
|
186
|
+
add_uvs(uvs[0], uvs[1], uvs[2])
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def handle_face(faces, uvs = [], normal_inds = [])
|
191
|
+
new_mesh if @mesh.nil?
|
192
|
+
if faces[3].nil?
|
193
|
+
handle_triangle(faces, uvs, normal_inds)
|
194
|
+
else
|
195
|
+
handle_quad(faces, uvs, normal_inds)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def handle_quad(faces, uvs, normal_inds)
|
200
|
+
handle_quad_triangle(faces, uvs, normal_inds, [0, 1, 3])
|
201
|
+
handle_quad_triangle(faces, uvs, normal_inds, [1, 2, 3])
|
202
|
+
end
|
203
|
+
|
204
|
+
def handle_quad_triangle(faces, uvs, normal_inds, tri_inds)
|
205
|
+
handle_triangle(
|
206
|
+
faces.values_at(*tri_inds).compact,
|
207
|
+
uvs.values_at(*tri_inds).compact,
|
208
|
+
normal_inds.values_at(*tri_inds).compact
|
209
|
+
)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|