-
Notifications
You must be signed in to change notification settings - Fork 0
/
usdSkelAppleFixup.py
93 lines (70 loc) · 3.81 KB
/
usdSkelAppleFixup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import sys, os
import argparse
progName = os.path.basename(sys.argv[0])
descr = """
$prog: This fixes what is likely a temporary situation where Apple's UsdSkel spec requires
an animationSource and skeleton relationship on every skinned mesh, but the official UsdSkel
schema requires an animationSource relationship on the skeleton, and skeleton relationships can
be inherited. This inconsistency will likely be fixed soon, but it doesn't hurt to have
redundant relationships for now. So, this script simply finds all the animationSource relationships
on skeletons and copies them over to the corresponding skinned meshes. Meshes also get a redundant
skeleton relationhip defined. If exporting a UsdSkel asset from Maya or another DCC/process,
you can run this script afterwards for this temp fix.
HUGE CAVEAT: At this time, iOS doesn't accept USDZ files with more than one skinned mesh. maOS
should accept these files just fine though.
"""
parser = argparse.ArgumentParser(usage=progName+" <in> <out>",description=descr.replace("$prog", progName))
parser.add_argument('inusd', help='input usd')
parser.add_argument('outusd', help='output usd')
args = parser.parse_args()
#------------------------------------------------------------------------------#
# Traverses up to the root for a given prim looking for the closest
# skel binding. Note the skinningQuery is the better API but this is
# temporary until we get a python GetPrim() binding.
def FindSkelBindingRel(stage,prim):
while(prim != stage.GetPseudoRoot() and prim != None):
for rel in prim.GetRelationships():
if rel.GetName() == "skel:skeleton":
return(rel)
else:
prim = prim.GetParent()
def main():
print("UsdSkelAppleFixup Begin.")
# Create a new out usd file that sublayers the in usd file. All edits
# will go to the out usd file. Start and end time is copied over.
inFile = args.inusd
outFile = args.outusd
from pxr import Usd, UsdGeom, UsdSkel, Sdf
dstLyr = Sdf.Layer.CreateNew(outFile)
srcLyr = Sdf.Layer.FindOrOpen(inFile)
stage = Usd.Stage.Open(dstLyr)
stage.SetEditTarget(dstLyr)
layerStack = dstLyr.subLayerPaths
layerStack.insert(len(layerStack),inFile)
start = int(srcLyr.startTimeCode)
end = int(srcLyr.endTimeCode)
stage.SetStartTimeCode(start)
stage.SetEndTimeCode(end)
# Find all the skinned meshes and copy over the animation source to them
# The the skel, anim, and mesh prims.
skelPrims = [prim for prim in Usd.PrimRange(stage.GetPseudoRoot()) if prim.IsA(UsdSkel.Skeleton)]
meshPrims = [prim for prim in Usd.PrimRange(stage.GetPseudoRoot()) if prim.IsA(UsdGeom.Mesh)]
for skelPrim in skelPrims:
skelCache = UsdSkel.Cache()
skel = UsdSkel.Skeleton(skelPrim)
skelQuery = skelCache.GetSkelQuery(skel)
skelAnimQuery = skelQuery.GetAnimQuery()
skelAnim = UsdSkel.Animation(skelAnimQuery.GetPrim())
for mesh in meshPrims:
rel = FindSkelBindingRel(stage,mesh)
if rel:
for target in rel.GetTargets():
if target == skelPrim.GetPath():
print("Copying the animationSource relationship to "+mesh.GetName())
# wire up the skeleton and animation source rels for temporary compatbility with Apple's expectations
mesh.CreateRelationship(UsdSkel.Tokens.skelAnimationSource).AddTarget(skelAnim.GetPrim().GetPath())
mesh.CreateRelationship(UsdSkel.Tokens.skelSkeleton).AddTarget(skelPrim.GetPath())
dstLyr.Save()
#------------------------------------------------------------------------------#
if __name__ == "__main__":
main()