Home Website Youtube GitHub

mGear spline components give strange joint transforms

I was working with the chain_IK_spline_variable_FK_01 component and found that the final joint output was giving much poorer results than an ordinary spline IK solver. I then tested all the other spline components (chain_FK_spline, chain_spline_variable…) and found they were generating the exact same behavior.

When binding joints to a spline IK solver, each joint always points along the path to the next joint so that each joint is only translated along its X axis. When using the mGear solution which attaches joints to a motionPath, you get the joints oriented at various tangents of a spline. Since the tangent does not point directly toward the next joint, you get translation in the Y and Z axes of each joint. The result is that the transforms of each joint do not blend nicely into one another like they do with a standard spline IK. It’s possible to get a smooth looking output by smoothing the skin weights until they’re all blurred together, but my current task (custom wing component) requires more rigid weighting between the joints.

Is there a solution to this? I was considering swapping my component to use a standard spline IK solver instead.

1 Like

This does seem wrong and possibly a bug. I wonder if there is an index offset somewhere in the component.

Here is a rough quick fix you could consider if you’re in a rush. Below each FK control is an empty transform. You can aim those to the next FK controller. In my aimConstraint I use “none” as an upvector, but since they are parented under the FK controls, I think they should remain stable without an upvector. And twisting still appears to work correctly.

You might have to adjust those pm.ls() commands to match your naming conventions properly.

import pymel.core as pm

chainRefs = pm.ls('chain_C0_*_scl_ref', type='transform')

fkControls = pm.ls('chain_C0_fk*_ctl', type='transform')

for chainRef, fkControl in zip(chainRefs, fkControls[1:]):
    pm.aimConstraint(
        fkControl,
        chainRef,
        maintainOffset=False,
        aimVector=(1,0,0),
        upVector=(0,-1,0),
        worldUpType='none',
        )

This is not a bug. Is how the rollSplin solver interpolate. I think I have the explanation somewhe in one of the videos. But I will try to illustrate here the difference.

How to do the skinning:

remember some components use Maya spline solver. it is up to you what to choose :wink:

3 Likes

Thank you @chrislesage and @Miquel, I completely understand now. Using the offset weighting does give better results that are comparable to spline IK. It does make rotation with the FK controls a bit strange though, since the rotation center is changed. (Screenshot attached) I think to write my component, the best solution is spline IK, so I’ll take a look at arm_2jnt_freeTangents.

So if none of the chain spline components have the aim pointed to the next bone, then, ironically a chain link will not work with any of these.

Can we apply chris’ aimConstraint hack to all of these chain spline components somehow?

Are there any cases where you would want to have the y-axis use the curve tangent? Isn’t that very hard to paint skin weights for that?

Does the arm_2jnt_freeTangents_01use the Maya spline solver and are you recommending using that for long chains somehow?

I tend to agree. I can’t really imagine ever wanting that orientation.

I haven’t thought it through much, but would it make sense to include an option on the component, where the tangent was sampled at the position of the index+1 of each joint on the curve? Rather than adding a bunch of aim nodes, it would just offset where it read the tangent. So joint4 would get it’s orientation from the tangent of the position of joint5. And the final joint could just match the orientation of the final-1 index joint.

I can’t visualize if that would result in an identical result to aiming or not. I’m curious to test it someday and see how it behaves.

1 Like