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,309 +1,309 @@
1
- require 'optparse'
2
- require 'set'
3
- require_relative '../../bayonetta.rb'
4
- require 'yaml'
5
- require 'shellwords'
6
- include Bayonetta
7
-
8
- def merge_bones(wmb1, wmb2)
9
-
10
- tt1 = wmb1.bone_index_translate_table.table
11
- tt2_orig = wmb2.bone_index_translate_table.table
12
- tt2 = tt2_orig.invert
13
-
14
- bones1 = wmb1.get_bone_structure
15
- if $options[:bone_map]
16
- common_mapping = YAML::load_file( $options[:bone_map] )
17
- else
18
- common_mapping = {}
19
- end
20
-
21
- mapping = {}
22
-
23
- tt2.each { |key, val|
24
- mapping[key] = tt1[common_mapping[val]]
25
- }
26
- mapping = mapping.to_a.sort { |e1, e2| e1.first <=> e2.first }.to_h
27
-
28
- if $options[:update_bones]
29
- mapping.select { |k,v| v }.each { |k,v|
30
- bones1[v].position = wmb2.bones[k].position
31
- }
32
- end
33
-
34
- mapping[-1] = -1
35
- missing_bones = mapping.select { |k,v| v.nil? }.collect { |k,v| k }
36
- if $options[:filter_bones]
37
- missing_bones -= $options[:filter_bones]
38
- end
39
- new_bone_index = bones1.size
40
- new_bone_indexes = []
41
- missing_bones.each { |bi|
42
- mapping[bi] = new_bone_index
43
- new_bone_indexes.push(new_bone_index)
44
-
45
- b = Bone::new(wmb2.bones[bi].position)
46
- b.index = new_bone_index
47
- b.parent = bones1[mapping[wmb2.bones[bi].parent_index]] if wmb2.bones[bi].parent_index != -1
48
- b.symmetric = -1
49
- b.flag = 5
50
-
51
- bones1.push b
52
- new_bone_index += 1
53
- }
54
- wmb1.set_bone_structure(bones1)
55
- missing_bones_count = missing_bones.length
56
- raise "Too many bones to add!" if missing_bones_count > 0x100
57
- (align(missing_bones_count, 0x10) - missing_bones_count).times {
58
- new_bone_indexes.push(0xfff)
59
- }
60
-
61
- used_indexes = tt1.keys
62
- start_index = nil
63
-
64
- (0x250..(0x1000-new_bone_indexes.size)).step(0x10) { |s_index|
65
- if (used_indexes & (s_index..(s_index+new_bone_indexes.size)).to_a) == []
66
- start_index = s_index
67
- break
68
- end
69
- }
70
- raise "No room available in translate table!" unless start_index
71
- new_tt = wmb1.bone_index_translate_table.table.dup
72
- new_bone_indexes.each_with_index { |ind, i|
73
- new_tt[i+start_index] = ind
74
- common_mapping[tt2[missing_bones[i]]] = i + start_index if i < missing_bones.length && missing_bones[i]
75
- }
76
- wmb1.bone_index_translate_table.table = new_tt
77
-
78
- if wmb1.bone_symmetries
79
- (-missing_bones_count..-1).each { |i|
80
- symmetric = common_mapping[wmb1.bone_symmetries[i]]
81
- symmetric = -1 unless symmetric
82
- wmb1.bone_symmetries[i] = symmetric
83
- }
84
- end
85
-
86
- [common_mapping, mapping]
87
- end
88
-
89
- def get_texture_map(tex1, tex2)
90
- offset = tex1.each.count
91
- tex_map = {}
92
- tex2.each.each_with_index { |t,i|
93
- info, _ = t
94
- _, _, idx = info
95
- idx = i unless idx
96
- tex_map[idx] = i+offset
97
- }
98
- tex_map
99
- end
100
-
101
- def merge_geometry(wmb1, wmb2, bone_mapping)
102
- new_meshes = wmb2.header.info_meshes.number.times.collect { WMBFile::Mesh::new }
103
- new_meshes.each_with_index { |m, i|
104
- m.header.name = wmb2.meshes[i].name
105
- m.header.id = i + wmb1.header.num_meshes
106
- }
107
-
108
- batch_infos_map = {}
109
- wmb2.lods.each { |l|
110
- l.batch_infos.each_with_index { |batch_info, i|
111
- batch_infos_map[i+l.header.batch_start] = batch_info
112
- }
113
- }
114
-
115
- vertex_types = wmb1.get_vertex_types
116
-
117
- wmb2.batches.each_with_index { |n_b, batch_index|
118
- v_g = wmb2.vertex_groups[n_b.vertex_group_index]
119
- b_s = wmb2.bone_sets[n_b.bone_set_index]
120
- b = WMBFile::Batch::new
121
- first_vertex_index = wmb1.vertexes.length
122
- indices = v_g.indices.slice(n_b.index_start, n_b.num_indices)
123
- index_set = indices.uniq.sort
124
- num_vertex = index_set.length
125
- index_map = index_set.each_with_index.collect { |ind, i|
126
- [ind, i+first_vertex_index]
127
- }
128
-
129
-
130
- wmb1.vertexes += num_vertex.times.collect {
131
- vertex_types[0]::new
132
- }
133
- if wmb1.vertexes_ex_data
134
- wmb1.vertexes_ex_data += num_vertex.times.collect {
135
- vertex_types[1]::new
136
- }
137
- end
138
- wmb1.header.num_vertexes += num_vertex
139
-
140
- fields = wmb1.get_vertex_fields
141
- fields.each { |field|
142
- unless v_g.get_vertex_field(field, 0)
143
- warn "Couldn't find vertex field #{field} in model 2"
144
- if field == :color
145
- warn "Using default value 0xc0 0xc0 0xc0 0xff"
146
- c = Color::new
147
- c.r = 0xc0
148
- c.g = 0xc0
149
- c.b = 0xc0
150
- c.a = 0xff
151
- index_map.each { |ind, i|
152
- wmb1.set_vertex_field(field, i, c)
153
- }
154
- elsif field == :mapping2
155
- warn "Using mapping as default"
156
- index_map.each { |ind, i|
157
- wmb1.set_vertex_field(field, i, v_g.get_vertex_field(:mapping, ind))
158
- }
159
- else
160
- warn "No suitable default found"
161
- end
162
- else
163
- if field == :normal
164
- index_map.each { |ind, i|
165
- n = Normal::new
166
- n2 = v_g.get_vertex_field(:normal, ind)
167
- n.x = n2.x
168
- n.y = n2.y
169
- n.z = n2.z
170
- wmb1.set_vertex_field(field, i, n)
171
- }
172
- else
173
- index_map.each { |ind, i|
174
- wmb1.set_vertex_field(field, i, v_g.get_vertex_field(field, ind))
175
- }
176
- end
177
- end
178
- }
179
-
180
- index_map = index_map.to_h
181
-
182
- batch_info = batch_infos_map[batch_index]
183
- mesh = new_meshes[batch_info.mesh_index]
184
-
185
- b.header.material_id = batch_info.material_index + wmb1.header.num_materials
186
- b.header.mesh_id = mesh.header.id
187
- b.header.num_indices = indices.length
188
- b.indices = indices.collect { |ind| index_map[ind] }
189
- b.recompute_from_absolute_indices
190
- b.bone_refs = b_s.bone_indices.collect { |bi| bone_mapping[wmb2.bone_map[bi]] }
191
- b.num_bone_ref = b.bone_refs.length
192
-
193
- mesh.batches.push b
194
- mesh.header.num_batch += 1
195
- }
196
-
197
- wmb1.meshes += new_meshes
198
- wmb1.header.num_meshes += new_meshes.length
199
-
200
- end
201
-
202
- def merge_materials(wmb1, wmb2, tex_map)
203
- new_mat_offset = wmb1.header.num_materials
204
- mat_offset = wmb1.materials_offsets.last + wmb1.materials.last.__size
205
- new_materials_offsets = []
206
- new_materials = []
207
-
208
- wmb2.materials.each_with_index { |e, i|
209
- #biggest known material( in fact biggset is 0x174)
210
- new_materials_offsets.push(mat_offset + i*0x124)
211
- m = WMBFile::Material::new
212
- m.type = 0x0
213
- m.flag = 0x0
214
- m.material_data = [0x0]*(0x120/4)
215
- albedo = e.textures.find { |t| t.name.match("g_AlbedoMap") }
216
- normal = e.textures.find { |t| t.name.match("g_NormalMap") }
217
- m.material_data[0] = (albedo ? tex_map[albedo.texture_id] : 0x80000000)
218
- m.material_data[1] = (normal ? tex_map[normal.texture_id] : 0x80000000)
219
- m.material_data[0] = (m.material_data[0] ? m.material_data[0] : 0x80000000)
220
- m.material_data[1] = (m.material_data[1] ? m.material_data[1] : 0x80000000)
221
- new_materials.push(m)
222
- }
223
-
224
- wmb1.header.num_materials += wmb2.header.info_materials.number
225
- wmb1.materials += new_materials
226
- wmb1.materials_offsets += new_materials_offsets
227
- end
228
-
229
- $options = {}
230
-
231
- OptionParser.new do |opts|
232
- opts.banner = "Usage: wmb_import_geometry_wiiu_pc.rb target_file source_file [options]"
233
-
234
- opts.on("-bFILE", "--bone-map=FILE", "Bone map") do |bone_map|
235
- $options[:bone_map] = bone_map
236
- end
237
-
238
- opts.on("-u", "--update-bones", "Update recognized bone positions") do |update_bones|
239
- $options[:update_bones] = update_bones
240
- end
241
-
242
- opts.on("-t", "--[no-]import-textures", "Import textures also") do |import_textures|
243
- $options[:import_textures] = import_textures
244
- end
245
-
246
- opts.on("-o", "--[no-]overwrite", "Overwrite destination files") do |overwrite|
247
- $options[:overwrite] = overwrite
248
- end
249
-
250
- opts.on("-f", "--filter-bones=REJECT_LIST", "Don't import all bones") do |filter_bones|
251
- $options[:filter_bones] = eval(filter_bones)
252
- end
253
-
254
- opts.on("-h", "--help", "Prints this help") do
255
- puts opts
256
- exit
257
- end
258
-
259
- end.parse!
260
-
261
- input_file1 = ARGV[0]
262
- input_file2 = ARGV[1]
263
-
264
- raise "Invalid file #{input_file1}" unless File::file?(input_file1)
265
- raise "Invalid file #{input_file2}" unless File::file?(input_file2)
266
-
267
- Dir.mkdir("wmb_output") unless Dir.exist?("wmb_output")
268
-
269
- wmb1 = WMBFile::load(input_file1)
270
- wmb2 = WMBFile::load(input_file2)
271
-
272
- tex_map = {}
273
-
274
- if $options[:import_textures]
275
- tex1_file_name = input_file1.gsub(/wmb\z/,"wtb")
276
- tex1 = WTBFile::new(File::new(tex1_file_name, "rb"))
277
- begin
278
- tex2_file_name = input_file2.gsub(/wmb\z/,"wta")
279
- tex2 = WTBFile::new(File::new(tex2_file_name, "rb"), true, File::new(input_file2.gsub(/wmb\z/,"wtp"), "rb"))
280
- rescue
281
- tex2_file_name = input_file2.gsub(/wmb\z/,"wtb")
282
- tex2 = WTBFile::new(File::new(tex2_file_name, "rb"))
283
- end
284
-
285
- tex_map = get_texture_map(tex1, tex2)
286
- end
287
-
288
- common_mapping, bone_mapping = merge_bones(wmb1, wmb2)
289
-
290
- merge_geometry(wmb1, wmb2, bone_mapping)
291
-
292
- merge_materials(wmb1, wmb2, tex_map)
293
-
294
- wmb1.recompute_relative_positions
295
- wmb1.recompute_layout
296
-
297
- File::open(File.join("wmb_output", "#{File::basename(input_file2,".wmb")}_#{File::basename(input_file1,".wmb")}_bone_map.yaml"), "w") { |f|
298
- f.write YAML::dump(common_mapping)
299
- }
300
-
301
- if $options[:overwrite]
302
- wmb1.dump(input_file1)
303
- else
304
- wmb1.dump(File.join("wmb_output", File.basename(input_file1)))
305
- end
306
-
307
- if $options[:import_textures]
308
- `ruby #{Shellwords.escape File.join(__dir__,"wtb_import_textures.rb")} #{Shellwords.escape tex1_file_name} #{Shellwords.escape tex2_file_name}#{$options[:overwrite] ? " --overwrite" : ""}`
309
- end
1
+ require 'optparse'
2
+ require 'set'
3
+ require_relative '../../bayonetta.rb'
4
+ require 'yaml'
5
+ require 'shellwords'
6
+ include Bayonetta
7
+
8
+ def merge_bones(wmb1, wmb2)
9
+
10
+ tt1 = wmb1.bone_index_translate_table.table
11
+ tt2_orig = wmb2.bone_index_translate_table.table
12
+ tt2 = tt2_orig.invert
13
+
14
+ bones1 = wmb1.get_bone_structure
15
+ if $options[:bone_map]
16
+ common_mapping = YAML::load_file( $options[:bone_map] )
17
+ else
18
+ common_mapping = {}
19
+ end
20
+
21
+ mapping = {}
22
+
23
+ tt2.each { |key, val|
24
+ mapping[key] = tt1[common_mapping[val]]
25
+ }
26
+ mapping = mapping.to_a.sort { |e1, e2| e1.first <=> e2.first }.to_h
27
+
28
+ if $options[:update_bones]
29
+ mapping.select { |k,v| v }.each { |k,v|
30
+ bones1[v].position = wmb2.bones[k].position
31
+ }
32
+ end
33
+
34
+ mapping[-1] = -1
35
+ missing_bones = mapping.select { |k,v| v.nil? }.collect { |k,v| k }
36
+ if $options[:filter_bones]
37
+ missing_bones -= $options[:filter_bones]
38
+ end
39
+ new_bone_index = bones1.size
40
+ new_bone_indexes = []
41
+ missing_bones.each { |bi|
42
+ mapping[bi] = new_bone_index
43
+ new_bone_indexes.push(new_bone_index)
44
+
45
+ b = Bone::new(wmb2.bones[bi].position)
46
+ b.index = new_bone_index
47
+ b.parent = bones1[mapping[wmb2.bones[bi].parent_index]] if wmb2.bones[bi].parent_index != -1
48
+ b.symmetric = -1
49
+ b.flag = 5
50
+
51
+ bones1.push b
52
+ new_bone_index += 1
53
+ }
54
+ wmb1.set_bone_structure(bones1)
55
+ missing_bones_count = missing_bones.length
56
+ raise "Too many bones to add!" if missing_bones_count > 0x100
57
+ (align(missing_bones_count, 0x10) - missing_bones_count).times {
58
+ new_bone_indexes.push(0xfff)
59
+ }
60
+
61
+ used_indexes = tt1.keys
62
+ start_index = nil
63
+
64
+ (0x250..(0x1000-new_bone_indexes.size)).step(0x10) { |s_index|
65
+ if (used_indexes & (s_index..(s_index+new_bone_indexes.size)).to_a) == []
66
+ start_index = s_index
67
+ break
68
+ end
69
+ }
70
+ raise "No room available in translate table!" unless start_index
71
+ new_tt = wmb1.bone_index_translate_table.table.dup
72
+ new_bone_indexes.each_with_index { |ind, i|
73
+ new_tt[i+start_index] = ind
74
+ common_mapping[tt2[missing_bones[i]]] = i + start_index if i < missing_bones.length && missing_bones[i]
75
+ }
76
+ wmb1.bone_index_translate_table.table = new_tt
77
+
78
+ if wmb1.bone_symmetries
79
+ (-missing_bones_count..-1).each { |i|
80
+ symmetric = common_mapping[wmb1.bone_symmetries[i]]
81
+ symmetric = -1 unless symmetric
82
+ wmb1.bone_symmetries[i] = symmetric
83
+ }
84
+ end
85
+
86
+ [common_mapping, mapping]
87
+ end
88
+
89
+ def get_texture_map(tex1, tex2)
90
+ offset = tex1.each.count
91
+ tex_map = {}
92
+ tex2.each.each_with_index { |t,i|
93
+ info, _ = t
94
+ _, _, idx = info
95
+ idx = i unless idx
96
+ tex_map[idx] = i+offset
97
+ }
98
+ tex_map
99
+ end
100
+
101
+ def merge_geometry(wmb1, wmb2, bone_mapping)
102
+ new_meshes = wmb2.header.info_meshes.number.times.collect { WMBFile::Mesh::new }
103
+ new_meshes.each_with_index { |m, i|
104
+ m.header.name = wmb2.meshes[i].name
105
+ m.header.id = i + wmb1.header.num_meshes
106
+ }
107
+
108
+ batch_infos_map = {}
109
+ wmb2.lods.each { |l|
110
+ l.batch_infos.each_with_index { |batch_info, i|
111
+ batch_infos_map[i+l.header.batch_start] = batch_info
112
+ }
113
+ }
114
+
115
+ vertex_types = wmb1.get_vertex_types
116
+
117
+ wmb2.batches.each_with_index { |n_b, batch_index|
118
+ v_g = wmb2.vertex_groups[n_b.vertex_group_index]
119
+ b_s = wmb2.bone_sets[n_b.bone_set_index]
120
+ b = WMBFile::Batch::new
121
+ first_vertex_index = wmb1.vertexes.length
122
+ indices = v_g.indices.slice(n_b.index_start, n_b.num_indices)
123
+ index_set = indices.uniq.sort
124
+ num_vertex = index_set.length
125
+ index_map = index_set.each_with_index.collect { |ind, i|
126
+ [ind, i+first_vertex_index]
127
+ }
128
+
129
+
130
+ wmb1.vertexes += num_vertex.times.collect {
131
+ vertex_types[0]::new
132
+ }
133
+ if wmb1.vertexes_ex_data
134
+ wmb1.vertexes_ex_data += num_vertex.times.collect {
135
+ vertex_types[1]::new
136
+ }
137
+ end
138
+ wmb1.header.num_vertexes += num_vertex
139
+
140
+ fields = wmb1.get_vertex_fields
141
+ fields.each { |field|
142
+ unless v_g.get_vertex_field(field, 0)
143
+ warn "Couldn't find vertex field #{field} in model 2"
144
+ if field == :color
145
+ warn "Using default value 0xc0 0xc0 0xc0 0xff"
146
+ c = Color::new
147
+ c.r = 0xc0
148
+ c.g = 0xc0
149
+ c.b = 0xc0
150
+ c.a = 0xff
151
+ index_map.each { |ind, i|
152
+ wmb1.set_vertex_field(field, i, c)
153
+ }
154
+ elsif field == :mapping2
155
+ warn "Using mapping as default"
156
+ index_map.each { |ind, i|
157
+ wmb1.set_vertex_field(field, i, v_g.get_vertex_field(:mapping, ind))
158
+ }
159
+ else
160
+ warn "No suitable default found"
161
+ end
162
+ else
163
+ if field == :normal
164
+ index_map.each { |ind, i|
165
+ n = Normal::new
166
+ n2 = v_g.get_vertex_field(:normal, ind)
167
+ n.x = n2.x
168
+ n.y = n2.y
169
+ n.z = n2.z
170
+ wmb1.set_vertex_field(field, i, n)
171
+ }
172
+ else
173
+ index_map.each { |ind, i|
174
+ wmb1.set_vertex_field(field, i, v_g.get_vertex_field(field, ind))
175
+ }
176
+ end
177
+ end
178
+ }
179
+
180
+ index_map = index_map.to_h
181
+
182
+ batch_info = batch_infos_map[batch_index]
183
+ mesh = new_meshes[batch_info.mesh_index]
184
+
185
+ b.header.material_id = batch_info.material_index + wmb1.header.num_materials
186
+ b.header.mesh_id = mesh.header.id
187
+ b.header.num_indices = indices.length
188
+ b.indices = indices.collect { |ind| index_map[ind] }
189
+ b.recompute_from_absolute_indices
190
+ b.bone_refs = b_s.bone_indices.collect { |bi| bone_mapping[wmb2.bone_map[bi]] }
191
+ b.num_bone_ref = b.bone_refs.length
192
+
193
+ mesh.batches.push b
194
+ mesh.header.num_batch += 1
195
+ }
196
+
197
+ wmb1.meshes += new_meshes
198
+ wmb1.header.num_meshes += new_meshes.length
199
+
200
+ end
201
+
202
+ def merge_materials(wmb1, wmb2, tex_map)
203
+ new_mat_offset = wmb1.header.num_materials
204
+ mat_offset = wmb1.materials_offsets.last + wmb1.materials.last.__size
205
+ new_materials_offsets = []
206
+ new_materials = []
207
+
208
+ wmb2.materials.each_with_index { |e, i|
209
+ #biggest known material( in fact biggset is 0x174)
210
+ new_materials_offsets.push(mat_offset + i*0x124)
211
+ m = WMBFile::Material::new
212
+ m.type = 0x0
213
+ m.flag = 0x0
214
+ m.material_data = [0x0]*(0x120/4)
215
+ albedo = e.textures.find { |t| t.name.match("g_AlbedoMap") }
216
+ normal = e.textures.find { |t| t.name.match("g_NormalMap") }
217
+ m.material_data[0] = (albedo ? tex_map[albedo.texture_id] : 0x80000000)
218
+ m.material_data[1] = (normal ? tex_map[normal.texture_id] : 0x80000000)
219
+ m.material_data[0] = (m.material_data[0] ? m.material_data[0] : 0x80000000)
220
+ m.material_data[1] = (m.material_data[1] ? m.material_data[1] : 0x80000000)
221
+ new_materials.push(m)
222
+ }
223
+
224
+ wmb1.header.num_materials += wmb2.header.info_materials.number
225
+ wmb1.materials += new_materials
226
+ wmb1.materials_offsets += new_materials_offsets
227
+ end
228
+
229
+ $options = {}
230
+
231
+ OptionParser.new do |opts|
232
+ opts.banner = "Usage: wmb_import_geometry_wiiu_pc.rb target_file source_file [options]"
233
+
234
+ opts.on("-bFILE", "--bone-map=FILE", "Bone map") do |bone_map|
235
+ $options[:bone_map] = bone_map
236
+ end
237
+
238
+ opts.on("-u", "--update-bones", "Update recognized bone positions") do |update_bones|
239
+ $options[:update_bones] = update_bones
240
+ end
241
+
242
+ opts.on("-t", "--[no-]import-textures", "Import textures also") do |import_textures|
243
+ $options[:import_textures] = import_textures
244
+ end
245
+
246
+ opts.on("-o", "--[no-]overwrite", "Overwrite destination files") do |overwrite|
247
+ $options[:overwrite] = overwrite
248
+ end
249
+
250
+ opts.on("-f", "--filter-bones=REJECT_LIST", "Don't import all bones") do |filter_bones|
251
+ $options[:filter_bones] = eval(filter_bones)
252
+ end
253
+
254
+ opts.on("-h", "--help", "Prints this help") do
255
+ puts opts
256
+ exit
257
+ end
258
+
259
+ end.parse!
260
+
261
+ input_file1 = ARGV[0]
262
+ input_file2 = ARGV[1]
263
+
264
+ raise "Invalid file #{input_file1}" unless File::file?(input_file1)
265
+ raise "Invalid file #{input_file2}" unless File::file?(input_file2)
266
+
267
+ Dir.mkdir("wmb_output") unless Dir.exist?("wmb_output")
268
+
269
+ wmb1 = WMBFile::load(input_file1)
270
+ wmb2 = WMBFile::load(input_file2)
271
+
272
+ tex_map = {}
273
+
274
+ if $options[:import_textures]
275
+ tex1_file_name = input_file1.gsub(/wmb\z/,"wtb")
276
+ tex1 = WTBFile::new(File::new(tex1_file_name, "rb"))
277
+ begin
278
+ tex2_file_name = input_file2.gsub(/wmb\z/,"wta")
279
+ tex2 = WTBFile::new(File::new(tex2_file_name, "rb"), true, File::new(input_file2.gsub(/wmb\z/,"wtp"), "rb"))
280
+ rescue
281
+ tex2_file_name = input_file2.gsub(/wmb\z/,"wtb")
282
+ tex2 = WTBFile::new(File::new(tex2_file_name, "rb"))
283
+ end
284
+
285
+ tex_map = get_texture_map(tex1, tex2)
286
+ end
287
+
288
+ common_mapping, bone_mapping = merge_bones(wmb1, wmb2)
289
+
290
+ merge_geometry(wmb1, wmb2, bone_mapping)
291
+
292
+ merge_materials(wmb1, wmb2, tex_map)
293
+
294
+ wmb1.recompute_relative_positions
295
+ wmb1.recompute_layout
296
+
297
+ File::open(File.join("wmb_output", "#{File::basename(input_file2,".wmb")}_#{File::basename(input_file1,".wmb")}_bone_map.yaml"), "w") { |f|
298
+ f.write YAML::dump(common_mapping)
299
+ }
300
+
301
+ if $options[:overwrite]
302
+ wmb1.dump(input_file1)
303
+ else
304
+ wmb1.dump(File.join("wmb_output", File.basename(input_file1)))
305
+ end
306
+
307
+ if $options[:import_textures]
308
+ `ruby #{Shellwords.escape File.join(__dir__,"wtb_import_textures.rb")} #{Shellwords.escape tex1_file_name} #{Shellwords.escape tex2_file_name}#{$options[:overwrite] ? " --overwrite" : ""}`
309
+ end