So, I was hoping there was a way to get very specific information but I seem unable to find it.

I'm planning on assembling various parts of an object (a tree) generated in Blender using code. To assemble these parts I need the XYZ angles of each face relative to the original rotation as it transitions from part to part.

I have assembled, from various answers and the Blender API reference, the following code block:

import bpy
from mathutils import Matrix, Vector
import bmesh
context = bpy.context
obj = context.edit_object
mw = obj.matrix_world.copy()
bm = bmesh.from_edit_mesh(obj.data)
# for this example jmake a face active
face = bm.select_history.active
o = face.calc_center_median()
# calculate the axis dif in local coords

axis_src = face.normal
# local z-axis
axis_dst = Vector((-1, 0, 0))

matrix_rotate = mw.to_3x3()
matrix_rotate = matrix_rotate @ axis_src.rotation_difference(axis_dst).to_matrix()
matrix_translation = Matrix.Translation(mw @ o) # 

obj2 = context.scene.objects.get("Branch_New")
obj2.matrix_world = matrix_translation @ matrix_rotate.to_4x4()

This takes the 'inner part' in this picture: Blender Screenshot

And attaches it at the appropriate location with the appropriate rotation.

Yay success awesome but not really what I need

This means that what I'm looking for is in here somewhere.

What I need is a way to duplicate this functionality in Unity without hand-recording a 3x3 matrix for each joint I create. And then being able to keep it all proportional in code if the objects change size. I could do this, I think with a quaternion and an angle for each joint?

So I guess my question is how I get matrix_rotate (in its final form) to represent one more simple part of that quaternion, since matrix_translation is the 3-d coordinates of the other part. I think.

Now that I have the code working I can probably get through the rest on my own, and will provide an answer within a few days. But if someone else has faced this problem before and can help I would definitely appreciate it.

  • 1
    $\begingroup$ Do you mean 'without using Python', or is that a typo?.. and in what form do you want the information? ( in the API, polygons have a 'normal' property) $\endgroup$ – Robin Betts Apr 3 at 19:02
  • $\begingroup$ Yeah, I was / am a bit confused. I see the 'normal' property, now that I'm working through the problem on my own, but it is apparently a little off. I'm sorry the question is a little muddled. $\endgroup$ – Dylan Brams Apr 3 at 19:04
  • $\begingroup$ The normal is in Object space. You've taken mw, but not used it, (if you wanted it in World space) .. acos of what angle? $\endgroup$ – Robin Betts Apr 3 at 19:45
  • $\begingroup$ Ok, so you've pinpointed the problem, I think. My original plan was to have the coordinate system set up so there was an 'origin' at the X axis and all measurements came from there. So when I'm talking about a set of 'angles,' they are relative to a plane along the YZ axis. The 'normal vector' for this plane is changing oddly when I join the secondary object to the primary object facing along this normal. Sorry, I'm still new at Blender. $\endgroup$ – Dylan Brams Apr 3 at 19:54
  • $\begingroup$ np ... Just trying to help you define your problem clearly enough for someone to come along and help you solve it. maybe a picture would help. $\endgroup$ – Robin Betts Apr 3 at 20:35

The way to get the information I want per-face out is to run:

euler_rotation = matrix_rotate.to_euler()

for the Euler rotation, and


for the translation, taking only the magnitude portion of the matrix's x, y, and z rows. This is as a Euler transformation. To do it as a Quaternion, I can simply run:

my_quaternion = matrix_translation @ matrix_rotate.to_4x4()

and get a 4-number output that I believe includes both position and rotation transformations for the joint.


Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.