mittsu 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/mittsu.svg)](https://badge.fury.io/rb/mittsu) [![Dependency Status](https://gemnasium.com/jellymann/mittsu.svg)](https://gemnasium.com/jellymann/mittsu) [![Circle CI](https://circleci.com/gh/jellymann/mittsu/tree/master.svg?style=shield)](https://circleci.com/gh/jellymann/mittsu/tree/master) [![
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/mittsu.svg)](https://badge.fury.io/rb/mittsu) [![Dependency Status](https://gemnasium.com/jellymann/mittsu.svg)](https://gemnasium.com/jellymann/mittsu) [![Circle CI](https://circleci.com/gh/jellymann/mittsu/tree/master.svg?style=shield)](https://circleci.com/gh/jellymann/mittsu/tree/master) [![Coverage Status](https://coveralls.io/repos/github/jellymann/mittsu/badge.svg?branch=master)](https://coveralls.io/github/jellymann/mittsu?branch=master) [![Code Climate](https://codeclimate.com/github/jellymann/mittsu/badges/gpa.svg)](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
|