Support concatinating multiple glTF files.

This commit is contained in:
Syoyo Fujita 2020-03-13 14:21:12 +09:00
parent 5dcf778b31
commit 6224e021ce
2 changed files with 132 additions and 71 deletions

View File

@ -6,12 +6,21 @@ Append(merge) mesh of glTF A to glTF B.
`skin`, `nodes`, etc are not appended(to be merged).
## Usage
concatenate sourceN.gltf to target.gltf and save it to merged.gltf
```
$ python concat_mesh.py source0.gltf <source1.gltf source2.gltf ...> target.gltf merged.gltf
```
## TODO
* [ ] Support multiple glTFs to merge
* [x] Support multiple glTFs to merge(concat)
* [ ] Support merging skin
* [ ] Support merging different node hierarchies
* [ ] `images`, `textures`
* [ ] Support `images`, `textures`, `materials`
* [ ] Support other glTF info
# replace_attrib.py

View File

@ -1,20 +1,116 @@
# concat mesh to glTF
# support multiple source glTF to me concatenated to target.gltf
import json
import sys, os
prefix = "added/"
g_prefix = "added/"
def concat(source, target, offsets, prefix, extraInfo):
# Args:
# source: dict(modified), target: dict(modified),
# offsets: dict(modified). contains offset table.
# prefix: str
# extraInfo: dict(inout)
num_source_meshes = len(source["meshes"])
num_source_buffers = len(source["buffers"])
num_source_bufferViews = len(source["bufferViews"])
num_source_accessors = len(source["accessors"])
num_source_materials = len(source["materials"]) if "materials" in source else 0
print("src =====")
print("num_src_meshes: ", num_source_meshes)
print("num_src_buffers: ", num_source_buffers)
print("num_src_bufferViews: ", num_source_bufferViews)
print("num_src_accessors: ", num_source_accessors)
print("num_src_materials: ", num_source_materials)
#
# Adjust name and index offset
#
for i in range(len(source["buffers"])):
if "name" in source["buffers"][i]:
source["buffers"][i]["name"] = prefix + source["buffers"][i]["name"]
for i in range(len(source["bufferViews"])):
if "name" in source["bufferViews"][i]:
source["bufferViews"][i]["name"] = prefix + source["bufferViews"][i]["name"]
source["bufferViews"][i]["buffer"] += offsets["buffers"]
for i in range(len(source["accessors"])):
if "name" in source["accessors"][i]:
source["accessors"][i]["name"] = prefix + source["accessors"][i]["name"]
source["accessors"][i]["bufferView"] += offsets["bufferViews"]
for i in range(len(source["meshes"])):
mesh = source["meshes"][i]
if "name" in mesh:
source["meshes"][i]["name"] = prefix + source["meshes"][i]["name"]
for primid in range(len(mesh["primitives"])):
for attrib in mesh["primitives"][primid]["attributes"]:
#print(source["meshes"][i]["primitives"][primid]["attributes"][attrib])
source["meshes"][i]["primitives"][primid]["attributes"][attrib] += offsets["accessors"]
source["meshes"][i]["primitives"][primid]["indices"] += offsets["accessors"]
if "material" in source["meshes"][i]["primitives"][primid]:
source["meshes"][i]["primitives"][primid]["material"] += offsets["materials"]
#
# Append mesh info
#
target["buffers"] += source["buffers"]
target["bufferViews"] += source["bufferViews"]
target["meshes"] += source["meshes"]
target["accessors"] += source["accessors"]
if "materials" in source:
target["materials"] += source["materials"]
# assume `prefix` is unique
extraInfo["num_{}_meshes".format(prefix)] = num_source_meshes
extraInfo["num_{}_buffers".format(prefix)] = num_source_buffers
extraInfo["num_{}_bufferViews".format(prefix)] = num_source_bufferViews
extraInfo["num_{}_accessors".format(prefix)] = num_source_accessors
extraInfo["num_{}_materials".format(prefix)] = num_source_materials
# update offsets
offsets["meshes"] += num_source_meshes
offsets["buffers"] += num_source_buffers
offsets["bufferViews"] += num_source_bufferViews
offsets["accessors"] += num_source_accessors
offsets["materials"] += num_source_materials
def main():
if len(sys.argv) < 4:
print("Needs source.gltf target.gltf output.gltf")
print("Needs source0.gltf <source1.gltf, ...> target.gltf output.gltf")
sys.exit(-1)
source_filename = sys.argv[1]
target_filename = sys.argv[2]
output_filename = sys.argv[3]
num_args = len(sys.argv)
print("num_args = ", num_args)
source = json.loads(open(source_filename).read())
source_filenames = []
num_srcs = num_args - 3
for i in range(num_srcs):
source_filenames.append(sys.argv[1+i])
print("source[{}] = {}".format(i, sys.argv[1+i]))
target_filename = sys.argv[num_args - 2]
output_filename = sys.argv[num_args - 1]
print("target = ", target_filename)
print("output = ", output_filename)
sources = []
for i in range(num_srcs):
sources.append(json.loads(open(source_filenames[i]).read()))
target = json.loads(open(target_filename).read())
num_target_meshes = len(target["meshes"])
@ -28,65 +124,8 @@ def main():
print("num_target_accessors: ", num_target_accessors)
print("num_target_materials: ", num_target_accessors)
num_source_meshes = len(source["meshes"])
num_source_buffers = len(source["buffers"])
num_source_bufferViews = len(source["bufferViews"])
num_source_accessors = len(source["accessors"])
num_source_materials = len(source["materials"]) if "materials" in source else 0
print("num_source_meshes: ", num_source_meshes)
print("num_source_buffers: ", num_source_buffers)
print("num_source_bufferViews: ", num_source_bufferViews)
print("num_source_accessors: ", num_source_accessors)
print("num_source_materials: ", num_source_materials)
#
# Adjust name and index
#
for i in range(len(source["buffers"])):
if "name" in source["buffers"][i]:
source["buffers"][i]["name"] = prefix + source["buffers"][i]["name"]
for i in range(len(source["bufferViews"])):
if "name" in source["bufferViews"][i]:
source["bufferViews"][i]["name"] = prefix + source["bufferViews"][i]["name"]
source["bufferViews"][i]["buffer"] += num_target_buffers
for i in range(len(source["accessors"])):
if "name" in source["accessors"][i]:
source["accessors"][i]["name"] = prefix + source["accessors"][i]["name"]
source["accessors"][i]["bufferView"] += num_target_bufferViews
for i in range(len(source["meshes"])):
mesh = source["meshes"][i]
if "name" in mesh:
source["meshes"][i]["name"] = prefix + source["meshes"][i]["name"]
for primid in range(len(mesh["primitives"])):
for attrib in mesh["primitives"][primid]["attributes"]:
#print(source["meshes"][i]["primitives"][primid]["attributes"][attrib])
source["meshes"][i]["primitives"][primid]["attributes"][attrib] += num_target_accessors
source["meshes"][i]["primitives"][primid]["indices"] += num_target_accessors
if "material" in source["meshes"][i]["primitives"][primid]:
source["meshes"][i]["primitives"][primid]["material"] += num_target_materials
#
# Append mesh info
#
target["buffers"] += source["buffers"]
target["bufferViews"] += source["bufferViews"]
target["meshes"] += source["meshes"]
target["accessors"] += source["accessors"]
if "materials" in source:
target["materials"] += source["materials"]
#
# add some info
# add some info to asset.extras
#
extraInfo = {}
extraInfo["num_target_meshes"] = num_target_meshes
@ -95,11 +134,24 @@ def main():
extraInfo["num_target_accessors"] = num_target_accessors
extraInfo["num_target_materials"] = num_target_materials
extraInfo["num_source_meshes"] = num_source_meshes
extraInfo["num_source_buffers"] = num_source_buffers
extraInfo["num_source_bufferViews"] = num_source_bufferViews
extraInfo["num_source_accessors"] = num_source_accessors
extraInfo["num_source_materials"] = num_source_materials
offsets = {}
offsets["meshes"] = num_target_meshes
offsets["buffers"] = num_target_buffers
offsets["bufferViews"] = num_target_bufferViews
offsets["accessors"] = num_target_accessors
offsets["materials"] = num_target_materials
for i in range(num_srcs):
source = sources[i]
prefix = g_prefix + "{}/".format(source_filenames[i])
concat(source, target, offsets, prefix, extraInfo)
extraInfo["num_total_meshes"] = offsets["meshes"]
extraInfo["num_total_buffers"] = offsets["buffers"]
extraInfo["num_total_bufferViews"] = offsets["bufferViews"]
extraInfo["num_total_accessors"] = offsets["accessors"]
extraInfo["num_total_materials"] = offsets["materials"]
target["asset"]["extras"] = extraInfo