pgtools 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +25 -25
  3. data/bin/bxm_decoder +2 -2
  4. data/bin/bxm_encoder +2 -2
  5. data/bin/clh_convert +2 -2
  6. data/bin/clp_convert +2 -2
  7. data/bin/clw_convert +2 -2
  8. data/bin/dat_creator +2 -2
  9. data/bin/dat_extractor +2 -2
  10. data/bin/dat_ls +2 -2
  11. data/bin/eff_idd_creator +2 -2
  12. data/bin/eff_idd_extractor +2 -2
  13. data/bin/exp_convert_wiiu_pc +2 -2
  14. data/bin/exp_tool +2 -2
  15. data/bin/mot_convert_wiiu_pc +2 -2
  16. data/bin/mot_tool +2 -2
  17. data/bin/pkz_extractor +2 -2
  18. data/bin/scr_creator +2 -2
  19. data/bin/scr_extractor +2 -2
  20. data/bin/wmb_cleanup +2 -2
  21. data/bin/wmb_common_bones +2 -2
  22. data/bin/wmb_convert_pc_switch +2 -2
  23. data/bin/wmb_convert_wiiu_pc +2 -2
  24. data/bin/wmb_export_assimp +2 -2
  25. data/bin/wmb_get_bone_map +2 -2
  26. data/bin/wmb_import_assimp +2 -2
  27. data/bin/wmb_import_nier +2 -2
  28. data/bin/wmb_import_wiiu +2 -2
  29. data/bin/wtb_convert_wiiu_pc +2 -2
  30. data/bin/wtx_creator +2 -2
  31. data/bin/wtx_extractor +2 -2
  32. data/lib/bayonetta/alignment.rb +0 -0
  33. data/lib/bayonetta/bone.rb +0 -0
  34. data/lib/bayonetta/bxm.rb +180 -180
  35. data/lib/bayonetta/clh.rb +159 -159
  36. data/lib/bayonetta/clp.rb +212 -212
  37. data/lib/bayonetta/clw.rb +166 -166
  38. data/lib/bayonetta/dat.rb +261 -261
  39. data/lib/bayonetta/eff.rb +314 -314
  40. data/lib/bayonetta/endianness.rb +0 -0
  41. data/lib/bayonetta/exp.rb +768 -768
  42. data/lib/bayonetta/linalg.rb +416 -416
  43. data/lib/bayonetta/material_database.yaml +2581 -2581
  44. data/lib/bayonetta/mot.rb +763 -763
  45. data/lib/bayonetta/pkz.rb +63 -63
  46. data/lib/bayonetta/scr.rb +0 -0
  47. data/lib/bayonetta/tools/bxm_decoder.rb +23 -23
  48. data/lib/bayonetta/tools/bxm_encoder.rb +37 -37
  49. data/lib/bayonetta/tools/clh_convert.rb +60 -60
  50. data/lib/bayonetta/tools/clp_convert.rb +70 -70
  51. data/lib/bayonetta/tools/clw_convert.rb +60 -60
  52. data/lib/bayonetta/tools/dat_creator.rb +57 -57
  53. data/lib/bayonetta/tools/dat_extractor.rb +94 -94
  54. data/lib/bayonetta/tools/dat_ls.rb +106 -106
  55. data/lib/bayonetta/tools/eff_idd_creator.rb +66 -66
  56. data/lib/bayonetta/tools/eff_idd_extractor.rb +73 -73
  57. data/lib/bayonetta/tools/exp_convert_wiiu_pc.rb +33 -33
  58. data/lib/bayonetta/tools/exp_tool.rb +48 -48
  59. data/lib/bayonetta/tools/mot_convert_wiiu_pc.rb +33 -33
  60. data/lib/bayonetta/tools/mot_tool.rb +0 -0
  61. data/lib/bayonetta/tools/pkz_extractor.rb +75 -75
  62. data/lib/bayonetta/tools/scr_creator.rb +63 -63
  63. data/lib/bayonetta/tools/scr_extractor.rb +78 -78
  64. data/lib/bayonetta/tools/wmb_cleanup.rb +250 -250
  65. data/lib/bayonetta/tools/wmb_common_bones.rb +45 -45
  66. data/lib/bayonetta/tools/wmb_convert_pc_switch.rb +35 -35
  67. data/lib/bayonetta/tools/wmb_convert_wiiu_pc.rb +33 -33
  68. data/lib/bayonetta/tools/wmb_export_assimp.rb +479 -479
  69. data/lib/bayonetta/tools/wmb_get_bone_map.rb +50 -50
  70. data/lib/bayonetta/tools/wmb_import_assimp.rb +735 -735
  71. data/lib/bayonetta/tools/wmb_import_geometry_wiiu_pc.rb +472 -472
  72. data/lib/bayonetta/tools/wmb_import_nier.rb +309 -309
  73. data/lib/bayonetta/tools/wtb_convert_wiiu_pc.rb +95 -95
  74. data/lib/bayonetta/tools/wtb_import_textures.rb +103 -103
  75. data/lib/bayonetta/tools/wtx_creator.rb +69 -69
  76. data/lib/bayonetta/tools/wtx_extractor.rb +85 -85
  77. data/lib/bayonetta/vertex_types.yaml +0 -0
  78. data/lib/bayonetta/vertex_types2.yaml +0 -0
  79. data/lib/bayonetta/vertex_types_nier.yaml +145 -145
  80. data/lib/bayonetta/wmb.rb +2455 -2443
  81. data/lib/bayonetta/wmb3.rb +759 -759
  82. data/lib/bayonetta/wtb.rb +481 -481
  83. data/lib/bayonetta.rb +60 -60
  84. metadata +2 -2
@@ -1,479 +1,479 @@
1
- require 'assimp-ffi'
2
- require 'optparse'
3
- require 'set'
4
- require_relative '../../bayonetta'
5
- require 'yaml'
6
- require 'nokogiri'
7
- include Bayonetta
8
-
9
- $options = {
10
- output: nil
11
- }
12
- parser = OptionParser.new do |opts|
13
- opts.banner = "Usage: wmb_export_assim.rb file [format]"
14
-
15
- opts.on("-h", "--help", "Prints this help") do
16
- puts opts
17
- exit
18
- end
19
-
20
- opts.on("-o", "--output=dirname", "directory to output result") do |name|
21
- $options[:output] = name
22
- end
23
-
24
- opts.on("-f", "--formats", "Prints supported formats (default collada)") do
25
- Assimp::export_format_descriptions.each { |d|
26
- puts "\t#{d.id.to_s} (.#{d.file_extension})"
27
- }
28
- exit
29
- end
30
-
31
- end
32
- parser.parse!
33
-
34
- source = ARGV[0]
35
- format = 'collada'
36
- format = ARGV[1] if ARGV[1]
37
-
38
- if !source
39
- puts "Invalid Arguments!"
40
- puts parser
41
- exit
42
- end
43
-
44
-
45
- raise "Invalid file #{source}" unless File::file?(source)
46
-
47
- #log = Assimp::LogStream::stderr
48
- #log.attach
49
- #Assimp::LogStream::verbose(1)
50
-
51
- module Assimp
52
- class SceneCreated < Scene
53
-
54
- def initialize
55
- @ref_ptr = FFI::MemoryPointer::new(Assimp::SceneCreated)
56
- super(FFI::Pointer::new(@ref_ptr))
57
- end
58
-
59
- def self.release
60
- end
61
- end
62
- end
63
-
64
- extension = nil
65
- Assimp::export_format_descriptions.each { |d|
66
- if d.id.to_s == format
67
- extension = d.file_extension
68
- end
69
- }
70
- raise "Unsupported format: #{format}!" unless extension
71
-
72
- $scene = Assimp::SceneCreated::new
73
- $scene.flags = [:FLAGS_ALLOW_SHARED]
74
- $root_node = Assimp::Node::new
75
- $root_node.name = File::basename(source, ".wmb")
76
- $scene[:root_node] = $root_node
77
-
78
- $meshes = []
79
- $num_meshes = 0
80
-
81
- $wmb = WMBFile::load(source)
82
- #$wmb.scale(100.0) if format == "fbx"
83
- tex_file_name = source.gsub(/wmb\z/,"wtb")
84
- $wtb = WTBFile::new(File::new(tex_file_name, "rb"))
85
- #Meshes
86
-
87
- def create_bone_hierarchy
88
- skeleton = Assimp::Node::new
89
- skeleton.name = "skeleton"
90
-
91
- $wmb_bones = bones = $wmb.get_bone_structure
92
- table = $wmb.bone_index_translate_table.table.invert
93
- $bone_nodes = bones.collect { |b|
94
- n = Assimp::Node::new
95
- n.name = "bone_%03d" % table[b.index]
96
- n.transformation = Assimp::Matrix4x4.translation(b.relative_position)
97
- n
98
- }
99
- sekeleton_children = []
100
- bones.zip($bone_nodes).each_with_index { |(b, n), i|
101
- if b.parent
102
- n.parent = $bone_nodes[b.parent.index]
103
- else
104
- n.parent = skeleton
105
- sekeleton_children.push(n)
106
- end
107
- n.children = b.children.collect { |c| $bone_nodes[c.index] }
108
- }
109
- skeleton.children = sekeleton_children
110
- skeleton
111
- end
112
-
113
- def create_vertex_properties(mesh, vertices, bone_refs)
114
- vertex_map = vertices.each_with_index.collect.to_h
115
- num_vertices = vertices.size
116
- mesh.num_vertices = num_vertices
117
- fields = $wmb.get_vertex_fields
118
- res = {}
119
- num_colors = 0
120
- num_texture_coords = 0
121
- bones = $bone_nodes.each_with_index.collect { |n, i|
122
- bone = Assimp::Bone::new
123
- bone.name = n.name
124
- bone.offset_matrix = Assimp::Matrix4x4.translation( -$wmb_bones[i].position )
125
- bone
126
- }
127
- fields.each { |field|
128
- case field
129
- when :position
130
- mesh.vertices = vertex_map.collect { |orig_index, index|
131
- p = Assimp::Vector3D::new
132
- o_p = $wmb.get_vertex_field(field, orig_index)
133
- p.x = o_p.x
134
- p.y = o_p.y
135
- p.z = o_p.z
136
- p
137
- }
138
- when :normal
139
- mesh.normals = vertex_map.collect { |orig_index, index|
140
- n = Assimp::Vector3D::new
141
- o_n = $wmb.get_vertex_field(field, orig_index)
142
- n.x = o_n.x
143
- n.y = o_n.y
144
- n.z = o_n.z
145
- n
146
- }
147
- when :tangents
148
- mesh.tangents = vertex_map.collect { |orig_index, index|
149
- t = Assimp::Vector3D::new
150
- o_t = $wmb.get_vertex_field(field, orig_index)
151
- t.x = o_t.x
152
- t.y = o_t.y
153
- t.z = o_t.z
154
- t
155
- }
156
- when :mapping, :mapping2, :mapping3, :mapping4, :mapping5
157
- coords = vertex_map.collect { |orig_index, index|
158
- m = Assimp::Vector3D::new
159
- m_o = $wmb.get_vertex_field(field, orig_index)
160
- m.x = m_o.u
161
- m.y = m_o.v
162
- m
163
- }
164
- mesh.num_uv_components[num_texture_coords] = 2
165
- mesh.set_texture_coords(num_texture_coords, coords)
166
- num_texture_coords += 1
167
- when :color, :color2
168
- colors = vertex_map.collect { |orig_index, index|
169
- c = Assimp::Color4D::new
170
- c_o = $wmb.get_vertex_field(field, orig_index)
171
- c.r = c_o.r.to_f / 255.0
172
- c.g = c_o.g.to_f / 255.0
173
- c.b = c_o.b.to_f / 255.0
174
- c.a = c_o.a.to_f / 255.0
175
- c
176
- }
177
- mesh.set_colors(num_colors, colors)
178
- num_colors += 1
179
- when :bone_infos
180
- vertex_map.each { |orig_index, index|
181
- b_i = $wmb.get_vertex_field(field, orig_index).get_indexes_and_weights
182
- b_i.each { |ind, wgt|
183
- bone_index = bone_refs[ind]
184
- bones[bone_index].add_weight(index, wgt/255.0)
185
- }
186
- }
187
- else
188
- puts "skipping #{field}" unless field == :bone_infos
189
- end
190
- }
191
- bones.select! { |b| b.num_weights > 0 }
192
- # p bones.collect { |b| b.name }
193
- mesh.bones = bones
194
- if mesh.normals? && mesh.tangents?
195
- tangents = mesh.tangents
196
- normals = mesh.normals
197
- mesh.bitangents = vertex_map.collect { |orig_index, index|
198
- b_t = Assimp::Vector3D::new
199
- o_t = $wmb.get_vertex_field(:tangents, orig_index)
200
- t = tangents[index]
201
- n = normals[index]
202
- n_b_t = (n ^ t)
203
- n_b_t = ( o_t.s > 0 ? n_b_t * -1.0 : n_b_t )
204
- b_t.x = n_b_t.x
205
- b_t.y = n_b_t.y
206
- b_t.z = n_b_t.z
207
- b_t
208
- }
209
- end
210
- end
211
-
212
-
213
-
214
- def create_mesh( m, i, b, j)
215
- uniq_vertices = b.vertex_indices.uniq.sort
216
- vertex_map = uniq_vertices.each_with_index.collect.to_h
217
- num_vertices = uniq_vertices.size
218
- first_index = uniq_vertices.first
219
- triangles = b.triangles
220
- num_triangles = triangles.size
221
-
222
- mesh = Assimp::Mesh::new
223
- mesh.primitive_types = :TRIANGLE
224
- mesh.name = ("batch_%02d_" % i) + m.header.name.unpack("Z*").first+("_%02d" % j)
225
- res = create_vertex_properties(mesh, uniq_vertices, b.bone_refs)
226
- if $wmb.tex_infos then
227
- mesh.material_index = b.header.ex_mat_id
228
- else
229
- mesh.material_index = b.header.material_id
230
- end
231
-
232
- mesh.faces = triangles.collect { |tri|
233
- f = Assimp::Face::new
234
- t = tri.collect{ |v| vertex_map[v] }
235
- f.indices = t
236
- f
237
- }
238
-
239
- $meshes.push mesh
240
-
241
- n = Assimp::Node::new
242
- n.name = mesh.name
243
- n.meshes = [$num_meshes]
244
- $num_meshes += 1
245
- n
246
- end
247
-
248
- $root_node.children =[create_bone_hierarchy] + $wmb.meshes.each_with_index.collect { |m, i|
249
- n = Assimp::Node::new
250
- n.name = ("mesh_%02d_"%i) + m.header.name
251
- n.children = m.batches.each_with_index.collect { |b, j|
252
- b = create_mesh(m, i, b, j)
253
- b.parent = n
254
- b
255
- }
256
- n.parent = $root_node
257
- n
258
- }
259
-
260
- $scene.meshes = $meshes
261
-
262
- $texture_names = $wtb.each.each_with_index.collect { |info_f, i|
263
- info, f = info_f
264
- ext, _, _ = info
265
- "./#{$root_node.name}_#{"%02d"%i}#{ext}"
266
- }
267
- $texture_count = $texture_names.count
268
- fields = $wmb.get_vertex_fields
269
- $scene.materials = $wmb.advanced_materials.each_with_index.collect { |m, i|
270
- mat = Assimp::Material::new
271
-
272
- mat.add_property(Assimp::MATKEY_NAME, "mat_%02d" % i)
273
- mat.add_property(Assimp::MATKEY_SHADING_MODEL, :Phong)
274
- mat.add_property(Assimp::MATKEY_TWOSIDED, false)
275
- mat.add_property(Assimp::MATKEY_ENABLE_WIREFRAME, false)
276
- # c = Assimp::Color4D::new.set(0.0, 0.0, 0.0, 1.0)
277
- # mat.add_property(Assimp::MATKEY_COLOR_EMISSIVE, c)
278
- # c = Assimp::Color4D::new.set(0.0, 0.0, 0.0, 0.0)
279
- # mat.add_property(Assimp::MATKEY_COLOR_REFLECTIVE, c)
280
- # mat.add_property(Assimp::MATKEY_REFLECTIVITY, 0.0)
281
- # mat.add_property(Assimp::MATKEY_REFRACTI, 1.55)
282
- # mat.add_property(Assimp::MATKEY_OPACITY, 1.0)
283
-
284
- if m.kind_of?(WMBFile::Bayo1Material)
285
- if m.parameters["diffuse"]
286
- c = Assimp::Color4D::new.set(m.parameters["diffuse"][0],
287
- m.parameters["diffuse"][1],
288
- m.parameters["diffuse"][2], 1.0)
289
- mat.add_property(Assimp::MATKEY_COLOR_DIFFUSE, c)
290
- end
291
- if m.parameters["ambient"]
292
- c = Assimp::Color4D::new.set(m.parameters["ambient"][0],
293
- m.parameters["ambient"][1],
294
- m.parameters["ambient"][2], 1.0)
295
- mat.add_property(Assimp::MATKEY_COLOR_AMBIENT, c)
296
- end
297
- if m.parameters["specular"]
298
- c = Assimp::Color4D::new.set(m.parameters["specular"][0],
299
- m.parameters["specular"][1],
300
- m.parameters["specular"][2], 1.0)
301
- mat.add_property(Assimp::MATKEY_COLOR_SPECULAR, c)
302
- end
303
- mat.add_property(Assimp::MATKEY_SHININESS, m.parameters["shine"]) if m.parameters["shine"]
304
- sampler_count = 0
305
- m.samplers.each { |name, value|
306
- case name
307
- when "Color_1", "Color_2", "Color_3"
308
- next if value >= $texture_count
309
- index = 0 if name == "Color_1"
310
- index = 1 if name == "Color_2"
311
- index = 2 if name == "Color_3"
312
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :DIFFUSE, index: index)
313
- # mat.add_property(Assimp::MATKEY_TEXOP, :Multiply, semantic: :DIFFUSE, index: index)
314
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :DIFFUSE, index: index)
315
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :DIFFUSE, index: index)
316
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :DIFFUSE, index: index)
317
- mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :DIFFUSE, index: index)
318
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :DIFFUSE, index: index)
319
- tr = Assimp::UVTransform::new
320
- tr.translation.x = 0
321
- tr.translation.y = 0
322
- if name == "Color_1" && m.parameters["Color_1_Tile"]
323
- tr.scaling.x = m.parameters["Color_1_Tile"][0]
324
- tr.scaling.y = m.parameters["Color_1_Tile"][1]
325
- elsif name == "Color_2" && m.parameters["Color_2_Tile"]
326
- tr.scaling.x = m.parameters["Color_2_Tile"][0]
327
- tr.scaling.y = m.parameters["Color_2_Tile"][1]
328
- elsif name == "Color_3" && m.parameters["Color_3_Tile"]
329
- tr.scaling.x = m.parameters["Color_3_Tile"][0]
330
- tr.scaling.y = m.parameters["Color_3_Tile"][1]
331
- else
332
- tr.scaling.x = 1.0
333
- tr.scaling.y = 1.0
334
- end
335
- tr.rotation = 0.0
336
- mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :DIFFUSE, index: index)
337
- sampler_count += 1
338
- when "effectmap"
339
- next if value >= $texture_count
340
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :EMISSIVE, index: sampler_count - 1)
341
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :EMISSIVE, index: sampler_count - 1)
342
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :EMISSIVE, index: sampler_count - 1)
343
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :EMISSIVE, index: sampler_count - 1)
344
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :EMISSIVE, index: sampler_count - 1)
345
- when "env_amb"
346
- next if value >= $texture_count || m.samplers.include?("envmap")
347
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :REFLECTION, index: sampler_count - 1)
348
- mat.add_property(Assimp::MATKEY_MAPPING, :BOX, semantic: :REFLECTION, index: sampler_count - 1)
349
- when "envmap"
350
- next if value >= $texture_count
351
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :REFLECTION, index: sampler_count - 1)
352
- mat.add_property(Assimp::MATKEY_MAPPING, :BOX, semantic: :REFLECTION, index: sampler_count - 1)
353
- when "lightmap"
354
- next if value >= $texture_count
355
- next unless fields.include?(:mapping2)
356
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :LIGHTMAP, index: sampler_count - 1)
357
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :LIGHTMAP, index: sampler_count - 1)
358
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :LIGHTMAP, index: sampler_count - 1)
359
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :LIGHTMAP, index: sampler_count - 1)
360
- mat.add_property(Assimp::MATKEY_UVWSRC, 1, semantic: :LIGHTMAP, index: sampler_count - 1)
361
- when "refractmap"
362
- next if value >= $texture_count
363
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :OPACITY, index: sampler_count - 1)
364
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :OPACITY, index: sampler_count - 1)
365
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :OPACITY, index: sampler_count - 1)
366
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :OPACITY, index: sampler_count - 1)
367
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :OPACITY, index: sampler_count - 1)
368
- when "reliefmap"
369
- next if value >= $texture_count
370
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :NORMALS, index: sampler_count - 1)
371
- # mat.add_property(Assimp::MATKEY_TEXOP, :Multiply, semantic: :NORMALS, index: sampler_count - 1)
372
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :NORMALS, index: sampler_count - 1)
373
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :NORMALS, index: sampler_count - 1)
374
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :NORMALS, index: sampler_count - 1)
375
- # mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :NORMALS, index: sampler_count - 1)
376
- uvsrc = 0
377
- uvsrc = 1 if fields.include?(:mapping2) && !m.parameters.include?("lightmap")
378
- mat.add_property(Assimp::MATKEY_UVWSRC, uvsrc, semantic: :NORMALS, index: sampler_count - 1)
379
- tr = Assimp::UVTransform::new
380
- tr.translation.x = 0
381
- tr.translation.y = 0
382
- tr.scaling.x = 1.0
383
- tr.scaling.y = 1.0
384
- tr.rotation = 0.0
385
- mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :NORMALS, index: sampler_count - 1)
386
- when "Spec_Mask"
387
- next if value >= $texture_count
388
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :SPECULAR, index: sampler_count - 1)
389
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :SPECULAR, index: sampler_count - 1)
390
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :SPECULAR, index: sampler_count - 1)
391
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :SPECULAR, index: sampler_count - 1)
392
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :SPECULAR, index: sampler_count - 1)
393
- when "Spec_Pow"
394
- next if value >= $texture_count
395
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :SHININESS, index: sampler_count - 1)
396
- mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :SHININESS, index: sampler_count - 1)
397
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :SHININESS, index: sampler_count - 1)
398
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :SHININESS, index: sampler_count - 1)
399
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :SHININESS, index: sampler_count - 1)
400
- end
401
- }
402
- else
403
- 4.times { |j|
404
- if m.material_data[j] < $texture_count
405
- mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[m.material_data[j]], semantic: :DIFFUSE)
406
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :DIFFUSE)
407
- mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :DIFFUSE)
408
- mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :DIFFUSE)
409
- mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :DIFFUSE)
410
- tr = Assimp::UVTransform::new
411
- tr.translation.x = 0
412
- tr.translation.y = 0
413
- tr.scaling.x = 1.0
414
- tr.scaling.y = 1.0
415
- tr.rotation = 0.0
416
- mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :DIFFUSE)
417
- break
418
- end
419
- }
420
- end
421
- mat
422
- }
423
-
424
- output_dir = $options[:output]
425
- if !output_dir
426
- Dir.mkdir("assimp_output") unless Dir.exist?("assimp_output")
427
- output_dir = File.join("assimp_output", "#{$root_node.name}_#{format}")
428
- else
429
- raise "Invalid directory provided: #{output_dir}!" unless Dir.exist?(output_dir)
430
- output_dir = File.join(output_dir, "#{$root_node.name}_#{format}")
431
- end
432
- Dir.mkdir(output_dir) unless Dir.exist?(output_dir)
433
- $wtb.each.each_with_index { |info_f, i|
434
- info, f = info_f
435
- ext, _, _ = info
436
- File::open(File.join(output_dir, "#{$root_node.name}_#{"%02d"%i}#{ext}"), "wb") { |f2|
437
- f.rewind
438
- f2.write(f.read)
439
- }
440
- }
441
- GC.start
442
- postprocess = [:FlipWindingOrder]
443
- #if format == "obj"
444
- postprocess.push :FlipUVs
445
- #end
446
- path = File.join(output_dir, "#{$root_node.name}.#{extension}")
447
- $scene.export(format, path, preprocessing: postprocess)
448
-
449
- if format == "collada"
450
- doc = Nokogiri::XML(File.read(path))
451
-
452
- doc.search("node").select { |n| n["id"].match("bone") && n["type"] == "NODE" }.each { |n| n["sid"] = n["id"]; n["type"] = "JOINT" }
453
- doc.search("skeleton").each { |s| s.child.replace( "#skeleton") }
454
-
455
- doc.search("bump").each { |b| b["bumptype"] = "NORMALMAP" }
456
-
457
- # rest is for Noesis
458
-
459
- mat_map = {}
460
- batch_map = {}
461
- doc.search("instance_material").each { |im|
462
- ansc = im.ancestors("instance_controller").first
463
- im["symbol"] = im["target"].tr("#","")
464
- str = ansc["url"].to_s
465
- str = str.tr("#","").gsub("-skin","")
466
- ansc = im.ancestors("node").first
467
- batch_map[str] = ansc["name"]
468
- mat_map[ str ]= im["symbol"]
469
- }
470
-
471
- doc.search("polylist").each { |p|
472
- ansc = p.ancestors("geometry").first
473
- batch = ansc["id"].to_s
474
- ansc["name"] = batch_map[batch]
475
- p["material"] = mat_map[batch]
476
- }
477
-
478
- File.open(path, "w") { |f| f.write doc.to_xml }
479
- end
1
+ require 'assimp-ffi'
2
+ require 'optparse'
3
+ require 'set'
4
+ require_relative '../../bayonetta'
5
+ require 'yaml'
6
+ require 'nokogiri'
7
+ include Bayonetta
8
+
9
+ $options = {
10
+ output: nil
11
+ }
12
+ parser = OptionParser.new do |opts|
13
+ opts.banner = "Usage: wmb_export_assim.rb file [format]"
14
+
15
+ opts.on("-h", "--help", "Prints this help") do
16
+ puts opts
17
+ exit
18
+ end
19
+
20
+ opts.on("-o", "--output=dirname", "directory to output result") do |name|
21
+ $options[:output] = name
22
+ end
23
+
24
+ opts.on("-f", "--formats", "Prints supported formats (default collada)") do
25
+ Assimp::export_format_descriptions.each { |d|
26
+ puts "\t#{d.id.to_s} (.#{d.file_extension})"
27
+ }
28
+ exit
29
+ end
30
+
31
+ end
32
+ parser.parse!
33
+
34
+ source = ARGV[0]
35
+ format = 'collada'
36
+ format = ARGV[1] if ARGV[1]
37
+
38
+ if !source
39
+ puts "Invalid Arguments!"
40
+ puts parser
41
+ exit
42
+ end
43
+
44
+
45
+ raise "Invalid file #{source}" unless File::file?(source)
46
+
47
+ #log = Assimp::LogStream::stderr
48
+ #log.attach
49
+ #Assimp::LogStream::verbose(1)
50
+
51
+ module Assimp
52
+ class SceneCreated < Scene
53
+
54
+ def initialize
55
+ @ref_ptr = FFI::MemoryPointer::new(Assimp::SceneCreated)
56
+ super(FFI::Pointer::new(@ref_ptr))
57
+ end
58
+
59
+ def self.release
60
+ end
61
+ end
62
+ end
63
+
64
+ extension = nil
65
+ Assimp::export_format_descriptions.each { |d|
66
+ if d.id.to_s == format
67
+ extension = d.file_extension
68
+ end
69
+ }
70
+ raise "Unsupported format: #{format}!" unless extension
71
+
72
+ $scene = Assimp::SceneCreated::new
73
+ $scene.flags = [:FLAGS_ALLOW_SHARED]
74
+ $root_node = Assimp::Node::new
75
+ $root_node.name = File::basename(source, ".wmb")
76
+ $scene[:root_node] = $root_node
77
+
78
+ $meshes = []
79
+ $num_meshes = 0
80
+
81
+ $wmb = WMBFile::load(source)
82
+ #$wmb.scale(100.0) if format == "fbx"
83
+ tex_file_name = source.gsub(/wmb\z/,"wtb")
84
+ $wtb = WTBFile::new(File::new(tex_file_name, "rb"))
85
+ #Meshes
86
+
87
+ def create_bone_hierarchy
88
+ skeleton = Assimp::Node::new
89
+ skeleton.name = "skeleton"
90
+
91
+ $wmb_bones = bones = $wmb.get_bone_structure
92
+ table = $wmb.bone_index_translate_table.table.invert
93
+ $bone_nodes = bones.collect { |b|
94
+ n = Assimp::Node::new
95
+ n.name = "bone_%03d" % table[b.index]
96
+ n.transformation = Assimp::Matrix4x4.translation(b.relative_position)
97
+ n
98
+ }
99
+ sekeleton_children = []
100
+ bones.zip($bone_nodes).each_with_index { |(b, n), i|
101
+ if b.parent
102
+ n.parent = $bone_nodes[b.parent.index]
103
+ else
104
+ n.parent = skeleton
105
+ sekeleton_children.push(n)
106
+ end
107
+ n.children = b.children.collect { |c| $bone_nodes[c.index] }
108
+ }
109
+ skeleton.children = sekeleton_children
110
+ skeleton
111
+ end
112
+
113
+ def create_vertex_properties(mesh, vertices, bone_refs)
114
+ vertex_map = vertices.each_with_index.collect.to_h
115
+ num_vertices = vertices.size
116
+ mesh.num_vertices = num_vertices
117
+ fields = $wmb.get_vertex_fields
118
+ res = {}
119
+ num_colors = 0
120
+ num_texture_coords = 0
121
+ bones = $bone_nodes.each_with_index.collect { |n, i|
122
+ bone = Assimp::Bone::new
123
+ bone.name = n.name
124
+ bone.offset_matrix = Assimp::Matrix4x4.translation( -$wmb_bones[i].position )
125
+ bone
126
+ }
127
+ fields.each { |field|
128
+ case field
129
+ when :position
130
+ mesh.vertices = vertex_map.collect { |orig_index, index|
131
+ p = Assimp::Vector3D::new
132
+ o_p = $wmb.get_vertex_field(field, orig_index)
133
+ p.x = o_p.x
134
+ p.y = o_p.y
135
+ p.z = o_p.z
136
+ p
137
+ }
138
+ when :normal
139
+ mesh.normals = vertex_map.collect { |orig_index, index|
140
+ n = Assimp::Vector3D::new
141
+ o_n = $wmb.get_vertex_field(field, orig_index)
142
+ n.x = o_n.x
143
+ n.y = o_n.y
144
+ n.z = o_n.z
145
+ n
146
+ }
147
+ when :tangents
148
+ mesh.tangents = vertex_map.collect { |orig_index, index|
149
+ t = Assimp::Vector3D::new
150
+ o_t = $wmb.get_vertex_field(field, orig_index)
151
+ t.x = o_t.x
152
+ t.y = o_t.y
153
+ t.z = o_t.z
154
+ t
155
+ }
156
+ when :mapping, :mapping2, :mapping3, :mapping4, :mapping5
157
+ coords = vertex_map.collect { |orig_index, index|
158
+ m = Assimp::Vector3D::new
159
+ m_o = $wmb.get_vertex_field(field, orig_index)
160
+ m.x = m_o.u
161
+ m.y = m_o.v
162
+ m
163
+ }
164
+ mesh.num_uv_components[num_texture_coords] = 2
165
+ mesh.set_texture_coords(num_texture_coords, coords)
166
+ num_texture_coords += 1
167
+ when :color, :color2
168
+ colors = vertex_map.collect { |orig_index, index|
169
+ c = Assimp::Color4D::new
170
+ c_o = $wmb.get_vertex_field(field, orig_index)
171
+ c.r = c_o.r.to_f / 255.0
172
+ c.g = c_o.g.to_f / 255.0
173
+ c.b = c_o.b.to_f / 255.0
174
+ c.a = c_o.a.to_f / 255.0
175
+ c
176
+ }
177
+ mesh.set_colors(num_colors, colors)
178
+ num_colors += 1
179
+ when :bone_infos
180
+ vertex_map.each { |orig_index, index|
181
+ b_i = $wmb.get_vertex_field(field, orig_index).get_indexes_and_weights
182
+ b_i.each { |ind, wgt|
183
+ bone_index = bone_refs[ind]
184
+ bones[bone_index].add_weight(index, wgt/255.0)
185
+ }
186
+ }
187
+ else
188
+ puts "skipping #{field}" unless field == :bone_infos
189
+ end
190
+ }
191
+ bones.select! { |b| b.num_weights > 0 }
192
+ # p bones.collect { |b| b.name }
193
+ mesh.bones = bones
194
+ if mesh.normals? && mesh.tangents?
195
+ tangents = mesh.tangents
196
+ normals = mesh.normals
197
+ mesh.bitangents = vertex_map.collect { |orig_index, index|
198
+ b_t = Assimp::Vector3D::new
199
+ o_t = $wmb.get_vertex_field(:tangents, orig_index)
200
+ t = tangents[index]
201
+ n = normals[index]
202
+ n_b_t = (n ^ t)
203
+ n_b_t = ( o_t.s > 0 ? n_b_t * -1.0 : n_b_t )
204
+ b_t.x = n_b_t.x
205
+ b_t.y = n_b_t.y
206
+ b_t.z = n_b_t.z
207
+ b_t
208
+ }
209
+ end
210
+ end
211
+
212
+
213
+
214
+ def create_mesh( m, i, b, j)
215
+ uniq_vertices = b.vertex_indices.uniq.sort
216
+ vertex_map = uniq_vertices.each_with_index.collect.to_h
217
+ num_vertices = uniq_vertices.size
218
+ first_index = uniq_vertices.first
219
+ triangles = b.triangles
220
+ num_triangles = triangles.size
221
+
222
+ mesh = Assimp::Mesh::new
223
+ mesh.primitive_types = :TRIANGLE
224
+ mesh.name = ("batch_%02d_" % i) + m.header.name.unpack("Z*").first+("_%02d" % j)
225
+ res = create_vertex_properties(mesh, uniq_vertices, b.bone_refs)
226
+ if $wmb.tex_infos then
227
+ mesh.material_index = b.header.ex_mat_id
228
+ else
229
+ mesh.material_index = b.header.material_id
230
+ end
231
+
232
+ mesh.faces = triangles.collect { |tri|
233
+ f = Assimp::Face::new
234
+ t = tri.collect{ |v| vertex_map[v] }
235
+ f.indices = t
236
+ f
237
+ }
238
+
239
+ $meshes.push mesh
240
+
241
+ n = Assimp::Node::new
242
+ n.name = mesh.name
243
+ n.meshes = [$num_meshes]
244
+ $num_meshes += 1
245
+ n
246
+ end
247
+
248
+ $root_node.children =[create_bone_hierarchy] + $wmb.meshes.each_with_index.collect { |m, i|
249
+ n = Assimp::Node::new
250
+ n.name = ("mesh_%02d_"%i) + m.header.name
251
+ n.children = m.batches.each_with_index.collect { |b, j|
252
+ b = create_mesh(m, i, b, j)
253
+ b.parent = n
254
+ b
255
+ }
256
+ n.parent = $root_node
257
+ n
258
+ }
259
+
260
+ $scene.meshes = $meshes
261
+
262
+ $texture_names = $wtb.each.each_with_index.collect { |info_f, i|
263
+ info, f = info_f
264
+ ext, _, _ = info
265
+ "./#{$root_node.name}_#{"%02d"%i}#{ext}"
266
+ }
267
+ $texture_count = $texture_names.count
268
+ fields = $wmb.get_vertex_fields
269
+ $scene.materials = $wmb.advanced_materials.each_with_index.collect { |m, i|
270
+ mat = Assimp::Material::new
271
+
272
+ mat.add_property(Assimp::MATKEY_NAME, "mat_%02d" % i)
273
+ mat.add_property(Assimp::MATKEY_SHADING_MODEL, :Phong)
274
+ mat.add_property(Assimp::MATKEY_TWOSIDED, false)
275
+ mat.add_property(Assimp::MATKEY_ENABLE_WIREFRAME, false)
276
+ # c = Assimp::Color4D::new.set(0.0, 0.0, 0.0, 1.0)
277
+ # mat.add_property(Assimp::MATKEY_COLOR_EMISSIVE, c)
278
+ # c = Assimp::Color4D::new.set(0.0, 0.0, 0.0, 0.0)
279
+ # mat.add_property(Assimp::MATKEY_COLOR_REFLECTIVE, c)
280
+ # mat.add_property(Assimp::MATKEY_REFLECTIVITY, 0.0)
281
+ # mat.add_property(Assimp::MATKEY_REFRACTI, 1.55)
282
+ # mat.add_property(Assimp::MATKEY_OPACITY, 1.0)
283
+
284
+ if m.kind_of?(WMBFile::Bayo1Material)
285
+ if m.parameters["diffuse"]
286
+ c = Assimp::Color4D::new.set(m.parameters["diffuse"][0],
287
+ m.parameters["diffuse"][1],
288
+ m.parameters["diffuse"][2], 1.0)
289
+ mat.add_property(Assimp::MATKEY_COLOR_DIFFUSE, c)
290
+ end
291
+ if m.parameters["ambient"]
292
+ c = Assimp::Color4D::new.set(m.parameters["ambient"][0],
293
+ m.parameters["ambient"][1],
294
+ m.parameters["ambient"][2], 1.0)
295
+ mat.add_property(Assimp::MATKEY_COLOR_AMBIENT, c)
296
+ end
297
+ if m.parameters["specular"]
298
+ c = Assimp::Color4D::new.set(m.parameters["specular"][0],
299
+ m.parameters["specular"][1],
300
+ m.parameters["specular"][2], 1.0)
301
+ mat.add_property(Assimp::MATKEY_COLOR_SPECULAR, c)
302
+ end
303
+ mat.add_property(Assimp::MATKEY_SHININESS, m.parameters["shine"]) if m.parameters["shine"]
304
+ sampler_count = 0
305
+ m.samplers.each { |name, value|
306
+ case name
307
+ when "Color_1", "Color_2", "Color_3"
308
+ next if value >= $texture_count
309
+ index = 0 if name == "Color_1"
310
+ index = 1 if name == "Color_2"
311
+ index = 2 if name == "Color_3"
312
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :DIFFUSE, index: index)
313
+ # mat.add_property(Assimp::MATKEY_TEXOP, :Multiply, semantic: :DIFFUSE, index: index)
314
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :DIFFUSE, index: index)
315
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :DIFFUSE, index: index)
316
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :DIFFUSE, index: index)
317
+ mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :DIFFUSE, index: index)
318
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :DIFFUSE, index: index)
319
+ tr = Assimp::UVTransform::new
320
+ tr.translation.x = 0
321
+ tr.translation.y = 0
322
+ if name == "Color_1" && m.parameters["Color_1_Tile"]
323
+ tr.scaling.x = m.parameters["Color_1_Tile"][0]
324
+ tr.scaling.y = m.parameters["Color_1_Tile"][1]
325
+ elsif name == "Color_2" && m.parameters["Color_2_Tile"]
326
+ tr.scaling.x = m.parameters["Color_2_Tile"][0]
327
+ tr.scaling.y = m.parameters["Color_2_Tile"][1]
328
+ elsif name == "Color_3" && m.parameters["Color_3_Tile"]
329
+ tr.scaling.x = m.parameters["Color_3_Tile"][0]
330
+ tr.scaling.y = m.parameters["Color_3_Tile"][1]
331
+ else
332
+ tr.scaling.x = 1.0
333
+ tr.scaling.y = 1.0
334
+ end
335
+ tr.rotation = 0.0
336
+ mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :DIFFUSE, index: index)
337
+ sampler_count += 1
338
+ when "effectmap"
339
+ next if value >= $texture_count
340
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :EMISSIVE, index: sampler_count - 1)
341
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :EMISSIVE, index: sampler_count - 1)
342
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :EMISSIVE, index: sampler_count - 1)
343
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :EMISSIVE, index: sampler_count - 1)
344
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :EMISSIVE, index: sampler_count - 1)
345
+ when "env_amb"
346
+ next if value >= $texture_count || m.samplers.include?("envmap")
347
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :REFLECTION, index: sampler_count - 1)
348
+ mat.add_property(Assimp::MATKEY_MAPPING, :BOX, semantic: :REFLECTION, index: sampler_count - 1)
349
+ when "envmap"
350
+ next if value >= $texture_count
351
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :REFLECTION, index: sampler_count - 1)
352
+ mat.add_property(Assimp::MATKEY_MAPPING, :BOX, semantic: :REFLECTION, index: sampler_count - 1)
353
+ when "lightmap"
354
+ next if value >= $texture_count
355
+ next unless fields.include?(:mapping2)
356
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :LIGHTMAP, index: sampler_count - 1)
357
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :LIGHTMAP, index: sampler_count - 1)
358
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :LIGHTMAP, index: sampler_count - 1)
359
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :LIGHTMAP, index: sampler_count - 1)
360
+ mat.add_property(Assimp::MATKEY_UVWSRC, 1, semantic: :LIGHTMAP, index: sampler_count - 1)
361
+ when "refractmap"
362
+ next if value >= $texture_count
363
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :OPACITY, index: sampler_count - 1)
364
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :OPACITY, index: sampler_count - 1)
365
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :OPACITY, index: sampler_count - 1)
366
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :OPACITY, index: sampler_count - 1)
367
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :OPACITY, index: sampler_count - 1)
368
+ when "reliefmap"
369
+ next if value >= $texture_count
370
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :NORMALS, index: sampler_count - 1)
371
+ # mat.add_property(Assimp::MATKEY_TEXOP, :Multiply, semantic: :NORMALS, index: sampler_count - 1)
372
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :NORMALS, index: sampler_count - 1)
373
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :NORMALS, index: sampler_count - 1)
374
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :NORMALS, index: sampler_count - 1)
375
+ # mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :NORMALS, index: sampler_count - 1)
376
+ uvsrc = 0
377
+ uvsrc = 1 if fields.include?(:mapping2) && !m.parameters.include?("lightmap")
378
+ mat.add_property(Assimp::MATKEY_UVWSRC, uvsrc, semantic: :NORMALS, index: sampler_count - 1)
379
+ tr = Assimp::UVTransform::new
380
+ tr.translation.x = 0
381
+ tr.translation.y = 0
382
+ tr.scaling.x = 1.0
383
+ tr.scaling.y = 1.0
384
+ tr.rotation = 0.0
385
+ mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :NORMALS, index: sampler_count - 1)
386
+ when "Spec_Mask"
387
+ next if value >= $texture_count
388
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :SPECULAR, index: sampler_count - 1)
389
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :SPECULAR, index: sampler_count - 1)
390
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :SPECULAR, index: sampler_count - 1)
391
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :SPECULAR, index: sampler_count - 1)
392
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :SPECULAR, index: sampler_count - 1)
393
+ when "Spec_Pow"
394
+ next if value >= $texture_count
395
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[value], semantic: :SHININESS, index: sampler_count - 1)
396
+ mat.add_property(Assimp::MATKEY_MAPPING, :UV, semantic: :SHININESS, index: sampler_count - 1)
397
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :SHININESS, index: sampler_count - 1)
398
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :SHININESS, index: sampler_count - 1)
399
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :SHININESS, index: sampler_count - 1)
400
+ end
401
+ }
402
+ else
403
+ 4.times { |j|
404
+ if m.material_data[j] < $texture_count
405
+ mat.add_property(Assimp::MATKEY_TEXTURE, $texture_names[m.material_data[j]], semantic: :DIFFUSE)
406
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_U, :Wrap, semantic: :DIFFUSE)
407
+ mat.add_property(Assimp::MATKEY_MAPPINGMODE_V, :Wrap, semantic: :DIFFUSE)
408
+ mat.add_property(Assimp::MATKEY_TEXBLEND, 1.0, semantic: :DIFFUSE)
409
+ mat.add_property(Assimp::MATKEY_UVWSRC, 0, semantic: :DIFFUSE)
410
+ tr = Assimp::UVTransform::new
411
+ tr.translation.x = 0
412
+ tr.translation.y = 0
413
+ tr.scaling.x = 1.0
414
+ tr.scaling.y = 1.0
415
+ tr.rotation = 0.0
416
+ mat.add_property(Assimp::MATKEY_UVTRANSFORM, tr, semantic: :DIFFUSE)
417
+ break
418
+ end
419
+ }
420
+ end
421
+ mat
422
+ }
423
+
424
+ output_dir = $options[:output]
425
+ if !output_dir
426
+ Dir.mkdir("assimp_output") unless Dir.exist?("assimp_output")
427
+ output_dir = File.join("assimp_output", "#{$root_node.name}_#{format}")
428
+ else
429
+ raise "Invalid directory provided: #{output_dir}!" unless Dir.exist?(output_dir)
430
+ output_dir = File.join(output_dir, "#{$root_node.name}_#{format}")
431
+ end
432
+ Dir.mkdir(output_dir) unless Dir.exist?(output_dir)
433
+ $wtb.each.each_with_index { |info_f, i|
434
+ info, f = info_f
435
+ ext, _, _ = info
436
+ File::open(File.join(output_dir, "#{$root_node.name}_#{"%02d"%i}#{ext}"), "wb") { |f2|
437
+ f.rewind
438
+ f2.write(f.read)
439
+ }
440
+ }
441
+ GC.start
442
+ postprocess = [:FlipWindingOrder]
443
+ #if format == "obj"
444
+ postprocess.push :FlipUVs
445
+ #end
446
+ path = File.join(output_dir, "#{$root_node.name}.#{extension}")
447
+ $scene.export(format, path, preprocessing: postprocess)
448
+
449
+ if format == "collada"
450
+ doc = Nokogiri::XML(File.read(path))
451
+
452
+ doc.search("node").select { |n| n["id"].match("bone") && n["type"] == "NODE" }.each { |n| n["sid"] = n["id"]; n["type"] = "JOINT" }
453
+ doc.search("skeleton").each { |s| s.child.replace( "#skeleton") }
454
+
455
+ doc.search("bump").each { |b| b["bumptype"] = "NORMALMAP" }
456
+
457
+ # rest is for Noesis
458
+
459
+ mat_map = {}
460
+ batch_map = {}
461
+ doc.search("instance_material").each { |im|
462
+ ansc = im.ancestors("instance_controller").first
463
+ im["symbol"] = im["target"].tr("#","")
464
+ str = ansc["url"].to_s
465
+ str = str.tr("#","").gsub("-skin","")
466
+ ansc = im.ancestors("node").first
467
+ batch_map[str] = ansc["name"]
468
+ mat_map[ str ]= im["symbol"]
469
+ }
470
+
471
+ doc.search("polylist").each { |p|
472
+ ansc = p.ancestors("geometry").first
473
+ batch = ansc["id"].to_s
474
+ ansc["name"] = batch_map[batch]
475
+ p["material"] = mat_map[batch]
476
+ }
477
+
478
+ File.open(path, "w") { |f| f.write doc.to_xml }
479
+ end