# Set the Rotation (in Quaternion WXZY which is calculated by two vectors) of a bone using API 2.7.9

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))


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.

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

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
0.33333332136784577

• Thank you for your answer, making it easier for me to achieve this. – CrazyForName Dec 21 '18 at 12:26
• 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? – CrazyForName Dec 21 '18 at 12:53
• 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. – batFINGER Dec 21 '18 at 13:52