Home Website Youtube GitHub

Transform node on mirrored guides

Im getting the same issue as in this thread, also below the calf joint. However, mine is on the right side. I have set up the guides on the left side and mirrored to the right.
This my scene and outliner.

and this is the hierarchy that gets created (also it creates two twist joints on the mirrored side even though the other side only has one twist joint)

A picture of the guide scene

A picture of the rig scene after guides have been created

I am using the epic leg component.
If I have the Left side set as Right and mirror over everything works fine. But if the Left side is set to Left and I mirror the transform nodes are created on the Right side.
I am using Maya 2023 and the guide scene can be found here https://drive.google.com/file/d/1I7nJ5nJwlhag0uVQgoLAivTdkcJLfIqt/view?usp=sharing

Okay the issue seems to be with the Epic_Leg component as the Epic_mannequin_leg component works fine :grimacing:
This is all ive found so far

1 Like

Thanks for the feedback @nilusss

I have open a ticket to review/fix this

1 Like

Hello, I’m having problems when exporting the skeleton to Cascadeur when using the Epic leg component due to this transform node. Does anyone have a suggestion for a workaround I can use while it’s getting fixed? Thanks!

Edit:
This is the workaround I came up with. Probably not the cleanest thing ever and I’m not sure if I’m breaking something in the process but it does the job for me so far. I’m running it as a post custom step.

import pymel.core as pm
import mgear.shifter.custom_step as cstp
import maya.api.OpenMaya as om

class CustomShifterStep(cstp.customShifterMainStep):

    def setup(self):
            self.name = "fix_empty_transforms"

    def run(self):
        empties = [each for each in pm.ls(regex='transform\d$', type='transform')]

        for empty in empties:
            parent = pm.listRelatives(empty, parent=True)[0]
            joint = pm.listRelatives(empty, children=True)[0]

            mgear_mconstraint = None
            jconns = pm.listConnections(joint, c=True, p=True, sourceFirst=True)
            for conn in jconns:
                src = conn[0]
                dst = conn[1]
                if not mgear_mconstraint and src.find("mgear_matrixConstraint") != -1:
                    mgear_mconstraint = src.split(".")[0]
                pm.disconnectAttr(src, dst)

            pm.setAttr("{}.scaleX".format(empty),1)
            pm.setAttr("{}.scaleY".format(empty),1)
            pm.setAttr("{}.scaleZ".format(empty),1)
            
            pm.setAttr("{}.scaleX".format(joint),1)
            pm.setAttr("{}.scaleY".format(joint),1)
            pm.setAttr("{}.scaleZ".format(joint),1)
            

            # Reparenting
            pm.parent(joint, w=True)
            pm.delete(empty)
            pm.parent(joint, parent)
            

            # Reconnecting
            for conn in jconns:
                src = conn[0]
                dst = conn[1]
                pm.connectAttr(src, dst)
            
            
            # Edited code from JaschaW in mGear forum http://forum.mgear-framework.com/t/question-about-mgear-matrix-constraint/2113/9
            # -- get the driver and driven matrices
            loc = pm.listConnections(mgear_mconstraint+".driverMatrix", s=True, d=False)[0]
            matrix = om.MMatrix(pm.getAttr(loc+".worldMatrix[0]"))
            matrix_inverse = om.MMatrix(pm.getAttr(joint.name()+".parentInverseMatrix[0]"))
            # -- this will calculate the joint's orientation - we only care about rotation here
            final_matrix = om.MMatrix(pm.getAttr(mgear_mconstraint+".outputDriverOffsetMatrix")) * matrix_inverse
            pm.setAttr(mgear_mconstraint+".drivenRestMatrix", final_matrix, type="matrix")

            # Delete leftover empties
            empties = [each for each in pm.ls(regex='transform\d$', type='transform')]
            for empty in empties:
                pm.delete(empty)

Easiest would probably be to use the epic_mannequin_leg

1 Like

Not yet done, but I think I have the solution.
Meanwhile please check this video I recorded :wink:

3 Likes

This issue has been fixed and will be included in the next mGear release. :smiley: If you need it right now you can find the fix here:

4 Likes

I encountered this bug on 4.0.22, and one of my guide templates consistently causes it.

I dont kow the inner workings of mGear that causes it, but another forum topic made my try writing a script that enforces uniform scale on all guides and that seams to do the trick for me (Run on the root module of the guide):

import pymel.core as pm
import math

allNodes = pm.listRelatives(pm.selected(), ad=True, typ='transform')
for node in allNodes:

    xScale = node.scaleX.get()
    if not node.scaleY.isLocked():
        node.scaleY.set(math.copysign(xScale,node.scaleY.get()))
    if not node.scaleZ.isLocked():
        node.scaleZ.set(math.copysign(xScale,node.scaleZ.get()))