1
$\begingroup$

I have looked at the other questions that have been posted here and I am very sorry that this is such a similar question AGAIN but none of the issues solved it for my issue.

I am working on an application that converts 3d joint positions into an animation with the goal of saving the deformed mesh at certain points.

What I have right now is a mesh, an armature that is properly parented to it (I checked in pose mode) and all the 3d joint positions. What I would like to do now is "just" move the heads and tails of the bones (in edit/object/pose mode, whichever gives me a deformed mesh to export) to the correct position with a python script and then export the deformed mesh.

However, while I can change the armature in edit mode by positioning heads and tails of the edit_bones, the mesh stays the same (duh) and in pose mode I can only set the location of the entire pose_bone, heads and tails are read only. I would like to avoid the hassle of computing translation matrices, rotation matrices and scale factors for every joint - am I missing something?

It feels like I am so close to the solution and yet I can't progress.


Code version 1

Code with pose mode (the way I understand it this should move all bones randomly but the actual result is it just moves the root node and and therefore the whole mesh, all joints stay in the same relative position to the root node. If I try to move only the nose for example nothing happens but the pose_bone.location changes, maybe I am missing the bpy.context.scene.update() from the example but it causes an attribute error for me) as per this solution on stackexchange

import bpy
import numpy as np
import mathutils
import random
from bpy import context

bpy.ops.object.mode_set(mode='POSE')
armature = bpy.context.scene.objects['Armature']

for pose_bone in armature.pose.bones:

    print(pose_bone.location)
    x = pose_bone.location[0] + random.uniform(-0.2, 0.2)
    y = pose_bone.location[1] + random.uniform(-0.2, 0.2)
    z = pose_bone.location[2] + random.uniform(-0.2, 0.2)
    pose_bone.location[0] = x
    pose_bone.location[1] = y
    pose_bone.location[2] = z
    print(pose_bone.location)
    print('changed' + pose_bone.name)

Instead of directly assigning the coordinates i also tried this bone.location = armature.matrix_world.inverted() @ bone.bone.matrix_local.inverted() @ v in case there was an issue with coordinate systems but the result is the same, I cannot independently move individual bones.

Update on the pose mode solution: it seems like the issue was setting the location, this only works for my root node, the location change is ignored everywhere else (why is the functionality provided for non root bones then ?).

What does work is setting the rotation of individual bones but that brings me back to the problem that i would have to compute the rotation matrices (and potential scaling) for every frame of my data, which will probably result in errors at the ends of the limbs because of accumulating errors.


Code version 2

This version is in Edit Mode and changes heads and tails of the armature bones but the mesh remains unchanged (per this solution)

import bpy
import numpy as np
import mathutils
import random as rd
from bpy import context

bpy.ops.object.mode_set(mode='EDIT')
obj = context.object

for bone in obj.data.edit_bones:

    random_vector_1 = mathutils.Vector((rd.uniform(-0.2, 0.2), rd.uniform(-0.2, 0.2), rd.uniform(-0.2, 0.2)))
    bone.head += random_vector_1
    random_vector_2 = mathutils.Vector((rd.uniform(-0.2, 0.2), rd.uniform(-0.2, 0.2), rd.uniform(-0.2, 0.2)))
    bone.tail += random_vector_2

My data is not true mocap but .cdf (nasa, not wolfram alpha) so I have just raw 3d positions. Links to the similar issues: 1 2 3 4 5 6 7

$\endgroup$
  • 5
    $\begingroup$ Please post the code you have so far as well as how the data look like and the links to all the other questions you've mentioned. Thanks $\endgroup$ – p2or Jan 28 at 13:28
  • $\begingroup$ Consider setting up constraints pose bones to empties. Eg a forearm bone could track to the wrist joint. $\endgroup$ – batFINGER Jan 28 at 14:17
  • 1
    $\begingroup$ Related blender.stackexchange.com/questions/30835/… $\endgroup$ – batFINGER Jan 28 at 15:58
  • 1
    $\begingroup$ @batFINGER unfortunately my data is not true mocap but .cdf (nasa, not wolfram aplpha) so i have just raw 3d positions. i will however look into the issue, thank you $\endgroup$ – rmoeller Jan 28 at 16:17
  • $\begingroup$ @batFINGER i have not used constraints yet, how could they help me to move the heads and tails of the pose bones to a specific 3d location ? would it be like this (blender.stackexchange.com/questions/79344/…) ? $\endgroup$ – rmoeller Jan 29 at 11:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.