1
$\begingroup$

So, I'm trying to convert some transformation matrices from OpenGL to Blender but bone poses are wrong. I assume it's transformation matrix, I'm no expert in OpenGl but it's used in this function:

glUniformMatrix4fv(glGetUniformLocation(shader_character->program, "joints"), Character::JOINT_NUM, GL_FALSE, (float*)character->joint_mesh_xform);

So I assume it's transformation matrix also I've tested it's moving bones. But when applying those values to my rig, position is weird: How it looks in Blender

Compared to OpenGL: How it looks in OpenGL

I've tried applying it directly with bone.matrix_basis and all axis configurations when applying rotation (like (X, -Z, Y) in Blender but none of achieved poses looks right. Also for same matrix:

<Matrix 4x4 (  0.9997,  0.0193, -0.0118, 0.0000)
            ( -0.0189,  0.9994,  0.0289, 0.0000)
            (  0.0124, -0.0287,  0.9995, 0.0000)
            (-23.8805, -7.8834, -0.4667, 1.0000)>

Blender produces different results (using matrix.to_euler()):

(-0.028720224, -0.012384685, -0.01894982)

OpenGL (using glm::extractEulerAngleXYZ()):

(0.02872, 0.012385, 0.01895)

How to achieve same pose as in OpenGL having only this transformation matrix?

Original project in OpenGL

Also linking .blend file with full data form OpenGL and rig: Link to .blend file

Edit_1:

I'm not sure but do I need to recalculate matrices earlier? I'm calculating new rotations for child bones using this code:

def forward_kinematics(self):
    for i in range(self.JOINT_NUM):
        self.joint_global_anim_xform[i] = self.joint_anim_xform[i]
        self.joint_global_rest_xform[i] = self.joint_rest_xform[i]
        j = int(self.joint_parents[i])
        while j != -1:
            self.joint_global_anim_xform[i] = self.joint_global_anim_xform[i] @ self.joint_anim_xform[j]
            self.joint_global_rest_xform[i] = self.joint_global_rest_xform[i] @ self.joint_rest_xform[j]
            j = int(self.joint_parents[j])
​
        self.joint_mesh_xform[i] = self.joint_global_rest_xform[i].inverted() @ self.joint_global_anim_xform[i]

And I'm applying rotations using this code:

def apply_rotations(self, frame :int):
    for bone in self.armature.pose.bones:
        ind = self.bones.get(bone.name, -1)
        if ind != -1:
            bone.matrix_basis = mat.Matrix(self.joint_mesh_xform[ind])

Matrices used here have exact same values as ones used in OpenGL version

Edit_2:

Class definition for ealier code:

class Character:
    def __init__(self):
        self.JOINT_NUM = 31
        self.joint_anim_xform = np.empty(self.JOINT_NUM, dtype=mat.Matrix)
        self.joint_rest_xform = np.empty(self.JOINT_NUM, dtype=mat.Matrix)
        self.joint_mesh_xform = np.empty(self.JOINT_NUM, dtype=mat.Matrix)
        self.joint_global_rest_xform = np.empty(self.JOINT_NUM, dtype=mat.Matrix)
        self.joint_global_anim_xform = np.empty(self.JOINT_NUM, dtype=mat.Matrix)
        self.joint_parents = [0] * self.JOINT_NUM

rest_xform are default bones positions, anim_xform are calculated bones positions

Thanks in advance for help!

$\endgroup$
12
  • $\begingroup$ Blender matrices are defined in row order. Eg blender.stackexchange.com/a/192754/15543 Looks like it may need to be transposed. As explained here blender.stackexchange.com/a/192754/15543 the transpose of ortho matrix is also inverse. yet the 3x3 rotation matrix of above is not orthogonal. As a test if you set matrix above to matrix world of an object it will be converted such that it is orthogonal. $\endgroup$
    – batFINGER
    Commented Sep 17, 2020 at 21:51
  • $\begingroup$ I've tried transposing matrix with little to no success. You mean object.matrix_world? But PoseBones I'm assigning don't have that property. Only matrix, matrix_basis and matrix_channel. $\endgroup$
    – Kuro
    Commented Sep 18, 2020 at 10:59
  • $\begingroup$ Sorry for confusion, was suggestion re setting a matrix of cube or empty to matrix above by way of example. Eg in py console assign it C.object.matrix_world = M and then look at value of C.object.matrix_world Same principal as bone matrices. Blender expects the 3x3 rotation part to be orthogonal, and the translation to be in 4th column. $\endgroup$
    – batFINGER
    Commented Sep 18, 2020 at 11:18
  • $\begingroup$ It returned: <Matrix 4x4 ( 0.9997, 0.0193, -0.0118, 0.0000), ( -0.0189, 0.9994, 0.0289, 0.0000), ( 0.0124, -0.0287, 0.9995, 0.0000), (-23.8805, -7.8834, -0.4667, 1.0000)> So I don't think it's converting this matrix $\endgroup$
    – Kuro
    Commented Sep 18, 2020 at 14:57
  • $\begingroup$ pasteall.org/Zvjb $\endgroup$
    – batFINGER
    Commented Sep 18, 2020 at 15:12

0

You must log in to answer this question.

Browse other questions tagged .