Details of the problem:

I already have two vectors A and B (A is converted to B by a certain rotation), and I can now calculate the quaternion of its rotation. Also insert a bone in the blender so that its coordinates are A, and rotate the bone using the quaternion obtained. In theory, the rotated bone coordinates should be B, but it is not. I don't know where I am wrong at the moment? The following is a specific example of my operation.

First, I inserted a single-segment bone with a length of 1 and the direction that is in the same direction as the positive z-axis. object_name = Armature, bone_name = Bone.

>>> bpy.data.objects['Armature'].pose.bones['Bone'].head
Vector((0.0, 0.0, 0.0))
>>> bpy.data.objects['Armature'].pose.bones['Bone'].tail
Vector((0.0, 0.0, 1.0))
>>> bpy.data.objects['Armature'].pose.bones['Bone'].rotation_quaternion
Quaternion((1.0, 0.0, 0.0, 0.0))

enter image description here

Then, I find that the quaternion between (0,0,1) and (√3/3,√3/3,√3/3) is (0.8881, -0.3251, 0.3251, 0). Next, calling Blender's API to rotate the bone.

>>>bpy.data.objects['Armature'].pose.bones['Bone'].rotation_quaternion = mathutils.Quaternion((0.8881, -0.3251, 0.3251, 0))

However, the coordinates after the bone is rotated are not (√3/3, √3/3, √3/3), and the following is the bone information after the rotation.

>>> bpy.data.objects['Armature'].pose.bones['Bone'].head
Vector((0.0, 0.0, 0.0))
>>> bpy.data.objects['Armature'].pose.bones['Bone'].tail
Vector((-0.21132488548755646, 0.5773503184318542, 0.7886751294136047))
>>> bpy.data.objects['Armature'].pose.bones['Bone'].rotation_quaternion
Quaternion((0.8880738615989685, -0.32505759596824646, 0.32505759596824646, 0.0))

It can be seen that the quaternion has been successfully passed in but the coordinates of the bone are not the desired coordinates.

enter image description here

I don't know where I am doing wrong or what I understand wrong.

There is a problem that is very similar to my question, but he does not mention whether the rotated bones match the expected look. In fact, I think the two respondents to this question may be able to solve my problem, but I don't know how to contact them. Set the Rotation (in Quaternion WXZY) of a bone using API 2.49


1 Answer 1


Apply the rotation

Apply the rotational difference between to vectors to the pose bone, rather than setting the pose bones rotation with it.

The rot diff has an axis and angle. Applying the rotation rotates the pose bone, which in this case is angle 54.7 degrees about axis (-1, 1, 0).

Think of it like the rotation from 12 o'clock to 3 o'clock on a clockface, is 90 degrees about the axis of the hands. Applying to hand at 12 o'clock moves to 3 o'clock. Applying again from 3 to 6 o'clock and so on.

import bpy
from mathutils import Vector

up = Vector((0, 0, 1))
dest = Vector((1, 1, 1))

R = up.rotation_difference(dest).to_matrix().to_4x4()

pb = bpy.context.active_pose_bone
pb.matrix = R * pb.matrix
pb.matrix = R @ pb.matrix #  2.8

To set the bone absolutely from the vector, can use Vector.track_to_quat(to, up) For bones track to the 'Y' axis, along the bone. I have arbitrarily chosen 'Z" as up.

>>> v = Vector((1, 1, 1))
>>> q = v.to_track_quat('Y', 'Z')
>>> C.active_pose_bone.rotation_quaternion = q
>>> x = C.active_pose_bone.tail.x
>>> x * x
  • $\begingroup$ Thank you for your answer, making it easier for me to achieve this. $\endgroup$ Commented Dec 21, 2018 at 12:26
  • $\begingroup$ But I still have a question, my quaternion is based on the vector before and after. Why is the rotation effect after passing this parameter not as expected? $\endgroup$ Commented Dec 21, 2018 at 12:53
  • $\begingroup$ Ok then think of it as a "delta" rotation. How much to rotate from point a to point b. It is neither the rotation at point a nor point b. $\endgroup$
    – batFINGER
    Commented Dec 21, 2018 at 13:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .