Created
August 30, 2020 23:48
-
-
Save awforsythe/f132a0f67ad5608af98362e7d53b759b to your computer and use it in GitHub Desktop.
Quick Maya script that uses the OpenMaya API to make one joint hierarchy match the pose of another. Created so I could take a Unreal SkeletalMeshes authored in T-pose and rebind them in A-pose to exactly match the UE4 Mannequin from the AnimStarterPack.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This is a quick Maya script designed to update a skeletal mesh (dst) to match | |
the joint transforms of a different skeletal mesh (src). This will only work | |
if both meshes have the same set of joints with identical names and joint | |
orientations. | |
My initial rationale for needing this script: | |
The UE4 Mannequin included in Epic's Animation Starter Pack is authored in | |
A-Pose, whereas the meshes in the Prototype Characters pack (from Ying Pei | |
Games on the UE4 Marketplace) are authored in T-Pose. The joint hierarchies | |
are otherwise identical, so rather than messing around with retargeting all | |
the ASP assets to the HeroTPP characters in-editor, I decided to just edit | |
the Prototype Characters so that their bind pose matches the Mannequin, so | |
I could then reimport them to use the Mannequin skeleton directly. | |
How I used this script to accomplish that: | |
1. Reference the A-pose mannequin into a new Z-up Maya scene, with a namespace | |
2. Import the T-pose character to be modified, from an FBX | |
3. Ensure that __src_root_name__ and __dst_root_name__ are set below | |
4. Run this script: the imported character should now match the reference | |
5. Delete the mannequin reference | |
6. Export the original skin weights- I used this script: | |
https://github.com/Animatic33/MayaPython/tree/master/agMayaJSONSkinExport | |
7. Unbind the character mesh, baking history so it stays in A-pose | |
8. Delete the old bindPose node | |
9. Re-bind the mesh to the skeleton | |
10. Restore the original skin weights | |
11. Clean up scene hierarchy, export to FBX, import into Unreal | |
You can probably skip all the bind pose stuff and just enable T0 as ref pose | |
when importing into Unreal, but this way makes sure everything's squeaky-clean | |
if we need to use the mesh in DCC apps (for authoring animations etc). | |
""" | |
import maya.api.OpenMaya as om | |
__src_root_name__ = 'SK_Mannequin:root' | |
__dst_root_name__ = 'SK_Player_Male|root' | |
def get_transform(name): | |
""" Returns an MFnTransform given a (full or partial) dag path string. """ | |
sl = om.MSelectionList() | |
sl.add(name) | |
return om.MFnTransform(sl.getDagPath(0)) | |
def visit_joints(top_transform, f): | |
""" Recurses over the given transform and all descendant joints. """ | |
f(top_transform) | |
for i in xrange(top_transform.childCount()): | |
child_obj = top_transform.child(i) | |
if child_obj.apiType() == om.MFn.kJoint: | |
child_dagpath = om.MDagPath.getAPathTo(child_obj) | |
child_transform = om.MFnTransform(child_dagpath) | |
visit_joints(child_transform, f) | |
def update_dst_joint(src_joint_transform): | |
""" Finds the corresponding dst joint and aligns it with the src joint. """ | |
name = src_joint_transform.name().rsplit(':', 1)[-1] | |
dst_joint_transform = get_transform(name) | |
joint_transformation = src_joint_transform.transformation() | |
dst_joint_transform.setTransformation(joint_transformation) | |
if __name__ == '__main__': | |
visit_joints(get_transform(__src_root_name__), find_dst_joint) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment