Skip to content

Instantly share code, notes, and snippets.

@stevenctl
Created November 25, 2023 23:50
Show Gist options
  • Save stevenctl/c9038df936f741e8ac52387de2f24e94 to your computer and use it in GitHub Desktop.
Save stevenctl/c9038df936f741e8ac52387de2f24e94 to your computer and use it in GitHub Desktop.
Fix Mixamo Root Bone

Instructions

General Prep

  1. Download the rig with animation(s) from https://mixamo.com
  2. I prefer to import the FBX for each animation into an "animation library" .blend file.
  3. Delete all but 1 armature and rename the actions to something human readable.

Using the Add-On/Script:

  1. Put the python file into a zip for easy installation in blender
  2. Edit the armature and add a bone named root. Parent the mixamorig:Hips bone to root (keep offsets)
  3. Make the playback frame range include the keyframes you want captured
  4. Click the Fix Root Motion Bone button and the keyframes will be edited
import bpy
bl_info = {
"name": "Mixamo Root Fixer",
"description": "Moves location xz from mixamo hips to root bone",
"author": "Steven Landow",
"version": (1, 0),
"blender": (3, 6, 0),
"category": "Animation",
}
class OperatorRootMotionFix(bpy.types.Operator):
bl_idname = "stevenctl.mixamo_root_motion_fix"
bl_label = "Fix Root Motion Bone"
def execute(self, context):
try:
hip_motion_to_root()
except Exception as e:
self.report({"ERROR"}, e)
return {"FINISHED"}
class RootMotionFixPanel(bpy.types.Panel):
bl_label = "Fix Root Motion Bone"
bl_category = "Mixamo Fix"
bl_idname = "stevenctl.mixamo_fix_panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
self.layout.operator(OperatorRootMotionFix.bl_idname)
def hip_motion_to_root():
scene = bpy.context.scene
if not scene:
return
obj = bpy.context.active_object
if not obj or obj.type != "ARMATURE":
print("no selected armature")
return
action = obj.animation_data.action
if not action:
print("no selected action")
return
if not obj.pose.bones['mixamorig:Hips']:
print("no hips")
return
if not obj.pose.bones['root']:
print("no root")
return
for frame in range(scene.frame_start, scene.frame_end+1):
scene.frame_set(frame)
root = obj.pose.bones['root']
hips = obj.pose.bones['mixamorig:Hips']
xz = hips.location.xz
root.location.xz = xz
root.keyframe_insert("location", frame=frame)
hips.location.xz = (0, 0)
hips.keyframe_insert("location", frame=frame)
def register():
bpy.utils.register_class(OperatorRootMotionFix)
bpy.utils.register_class(RootMotionFixPanel)
def unregister():
bpy.utils.unregister_class(OperatorRootMotionFix)
bpy.utils.unregister_class(RootMotionFixPanel)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment