Live update to DazBone details?

Issue #1903 closed
Eve Tess created an issue

BACKGROUND

This mostly spawned from an issue from my own pipeline .

In blender, I create armatures and weight maps for geografts in specific orientations. I found a cheat method to essentially export the created item as a .pmx file and import into daz. Taking the original obj mesh and fitting it to the pmx mesh, I can easily transfer over the rigging and weight maps (mostly).

pmx doesn’t export in the daz native bone orientations, so it must be done manually. However, the start and end points of the bone get transferred over correctly. This is where daz starts to become the problem; using align nodes snaps the bones to the end points, but really messes up when it comes to the correct orientation.

PROBLEM

Blender uses a ‘Roll’ function to determine bone orientation while daz uses a weird xyz format. I’ve done some experimenting, and it doesn’t seem like there’s an easy way to recreate their controls in blender. Diffeo can calculate the roll initially, and does display it under properties, but it is never updated whenever an armature is edited.

SOLUTION

Digging though the code, I did see some parameters such as ‘tmat, rmat, dmat, wmat… ect’ that seem to hold those original values from the .duf and there are some matrix transforms to calculate roll, but this is only executed once during import. Is it possible to update the property values based on the roll after an armature is no longer under an edit control (move, rotate, scale, etc.)? Maybe vise-versa as well?

related ask if this can’t/won’t be done: does anyone know how to calculate the dazOrient values based off roll, tail, and head? I’ve tried several methods with no success because of the how daz controls their bone orientations.

Comments (3)

  1. Thomas Larsson repo owner

    The orientation of the bone in DS, i.e. DazOrient, is essentially what is called the local matrix in Blender. Except that you need to make a 90 degree rotation around the global X axis, to account for the difference in the global coordinate systems (Y up versus Z up). The following code snippet essentially shows how to calculate the roll and orientation from the local matrix.

    import bpy
    import math
    from mathutils import Vector, Matrix
    
    R = 180/math.pi
    
    def get_roll(bone):
        quat = bone.matrix_local.to_quaternion()
        if abs(quat.w) < 1e-4:
            return math.pi
        else:
            return 2*math.atan(quat.y/quat.w)
    
    def get_daz_orientation(bone):
        RX = Matrix.Rotation(-math.pi/2, 4, 'X')
        mat = RX @ bone.matrix_local
        euler = mat.to_euler('XYZ')
        return Vector(euler)
    
    pb = bpy.context.active_pose_bone
    roll = get_roll(pb.bone)
    orient = get_daz_orientation(pb.bone)
    print("%s %.4f %s" % (pb.name, roll*R, orient*R))
    

    However, whereas the roll angle is always right, the value of the orientation is only correct up to some multiple of 90 degrees. This happens because the plugin interchanges the local bone axes. In DS the local system can be orieinted in any way, but in Blender we want the local Y axis to be parallel to the bone, and point towards the tail. The map between the DS and Blender systems is defined by the DazAxes and DazFlips properties. It is a mess to get it right.

  2. Log in to comment