pgtools 1.0.0 → 1.0.1

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.
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