Reputation: 18244
I am on blender 3.6.
Goal is to simulate a running/walking animation of a loaded BaseMesh as obj file via python.
Here is my python code:
import bpy
import math
def import_basemesh(filepath):
# Import the BaseMesh OBJ file
bpy.ops.import_scene.obj(filepath=filepath)
basemesh = bpy.context.selected_objects[0]
basemesh.name = "BaseMesh"
return basemesh
def create_rig():
# Create an armature
bpy.ops.object.armature_add(enter_editmode=True, location=(0, 0, 0))
armature = bpy.context.object
armature.name = "Rig"
armature.show_in_front = True
# Add bones in Edit Mode
bones = armature.data.edit_bones
# Rename default bone to "Spine"
bones["Bone"].head = (0, 0, 18)
bones["Bone"].tail =(0, 0, 11)
bones["Bone"].name = "Spine"
# Add head bone
head_bone = bones.new("Head")
head_bone.head = (0, 0, 20)
head_bone.tail = (0, 0, 18)
head_bone.parent = bones["Spine"]
# Add left leg bone
left_leg_bone = bones.new("Left_Leg")
left_leg_bone.head = (0, 0, 11)
left_leg_bone.tail = (0, -2, 1)
left_leg_bone.parent = bones["Spine"]
# Add right leg bone
right_leg_bone = bones.new("Right_Leg")
right_leg_bone.head = (0, 0, 11)
right_leg_bone.tail = (0, 2, 1)
right_leg_bone.parent = bones["Spine"]
# Add left arm bone
left_arm_bone = bones.new("Left_Arm")
left_arm_bone.head = (0, 0, 18)
left_arm_bone.tail = (0, -6, 9)
left_arm_bone.parent = bones["Spine"]
# Add right arm bone
right_arm_bone = bones.new("Right_Arm")
right_arm_bone.head = (0, 0, 18)
right_arm_bone.tail = (0, 6, 9)
right_arm_bone.parent = bones["Spine"]
bpy.ops.object.mode_set(mode='OBJECT')
return armature
def rig_basemesh(basemesh, armature):
"""
Parent the BaseMesh to the rig with automatic weights.
"""
# Select the BaseMesh and the Armature
bpy.ops.object.mode_set(mode='OBJECT')
bpy.context.view_layer.objects.active = armature
bpy.ops.object.select_all(action='DESELECT')
basemesh.select_set(True)
armature.select_set(True)
# Set Parent to Armature with Automatic Weights
bpy.ops.object.parent_set(type='ARMATURE_AUTO')
print(f"Parented '{basemesh.name}' to '{armature.name}' with Automatic Weights.")
def rotate_basemesh(basemesh, angle_degrees):
"""
Rotates the BaseMesh around the Z-axis by a given angle (in degrees).
"""
import math
# Convert degrees to radians
angle_radians = math.radians(angle_degrees)
# Apply rotation
basemesh.rotation_euler[2] += angle_radians # Z-axis rotation (XY plane)
print(f"Rotated '{basemesh.name}' by {angle_degrees} degrees counterclockwise on the XY plane.")
def animate_running(armature):
"""
Create a running animation for the rig's bones.
"""
# Ensure animation data exists
if not armature.animation_data:
armature.animation_data_create()
# Switch to Pose Mode
bpy.context.view_layer.objects.active = armature
bpy.ops.object.mode_set(mode='POSE')
pose_bones = armature.pose.bones
# Verify the bones exist
required_bones = ["Left_Leg", "Right_Leg", "Left_Arm", "Right_Arm"]
missing_bones = [bone for bone in required_bones if bone not in pose_bones]
if missing_bones:
print(f"ERROR: Missing bones: {missing_bones}")
return
print("Available bones in armature:")
for bone in pose_bones:
print(bone.name)
# Set animation frame range
frame_start = 1
frame_end = 200
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end
# Insert keyframes for each bone
print("Inserting keyframes for running animation...")
try:
while frame_start<frame_end:
# Animate the Right Leg's location (opposite phase)
# Set the starting rotation
pose_bones["Left_Leg"].rotation_quaternion = (1, 0, 0, math.sin(math.radians(45/2)))
pose_bones["Left_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start)
pose_bones["Left_Leg"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Left_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 5)
pose_bones["Left_Leg"].rotation_quaternion = (1, 0, 0, -math.sin(math.radians(45/2)))
pose_bones["Left_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 10)
pose_bones["Left_Leg"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Left_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 15)
# Animate the Right Leg's location (opposite phase)
pose_bones["Right_Leg"].rotation_quaternion = (1, 0, 0, -math.sin(math.radians(45/2)))
pose_bones["Right_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start)
pose_bones["Right_Leg"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Right_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 5)
pose_bones["Right_Leg"].rotation_quaternion = (1, 0, 0, math.sin(math.radians(45/2)))
pose_bones["Right_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 10)
pose_bones["Right_Leg"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Right_Leg"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 15)
# Animate the Left Arm's location (opposite to legs)
pose_bones["Left_Arm"].rotation_quaternion = (1, 0, 0, math.sin(math.radians(45/2)))
pose_bones["Left_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start)
pose_bones["Left_Arm"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Left_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 5)
pose_bones["Left_Arm"].rotation_quaternion = (1, 0, 0, -math.sin(math.radians(45/2)))
pose_bones["Left_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 10)
pose_bones["Left_Arm"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Left_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 15)
# Animate the Right Arm's location (opposite phase to Left Arm)
pose_bones["Right_Arm"].rotation_quaternion = (1, 0, 0, -math.sin(math.radians(45/2)))
pose_bones["Right_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start)
pose_bones["Right_Arm"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Right_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 5)
pose_bones["Right_Arm"].rotation_quaternion = (1, 0, 0, math.sin(math.radians(45/2)))
pose_bones["Right_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 10)
pose_bones["Right_Arm"].rotation_quaternion = (1, 0, 0, 0)
pose_bones["Right_Arm"].keyframe_insert(data_path="rotation_quaternion", frame=frame_start + 15)
print("Location keyframes successfully inserted.")
frame_start += 20
except Exception as e:
print(f"ERROR: Failed to insert keyframes: {e}")
bpy.ops.object.mode_set(mode='OBJECT')
def main(filepath):
basemesh = import_basemesh(filepath)
armature = create_rig()
rig_basemesh(basemesh, armature)
basemesh = bpy.data.objects["BaseMesh"]
rotate_basemesh(basemesh, 90)
animate_running(armature)
obj_filepath = "C:/Users/hp/Downloads/fdx54mtvuz28-FinalBaseMesh/FinalBaseMesh.obj"
main(obj_filepath)
Expectation is the rig bones to attach to corresponding body parts , instead it seems like they are attached randomly as the entire body sways back and forth instead of running animation. Here is the obj file of the basemesh
https://sketchfab.com/3d-models/fdx54mtvuz28-final-base-mesh-bfa060fcbce64195be4fe5098b88b1a7
Upvotes: 0
Views: 25