Home Website Youtube GitHub

SOLVED: Does anyone have any issues with Softness control

I was wondering if anyone had experienced any issues with the GrimIK’s softness attribute. When it’s applied at a rest pose the limb moves noticeably. I have used other compiled ikSolvers such as GitHub - Toolchefs/softIkSolver: Maya Soft IK Solver

I don’t notice much of an effect if at all when the dampening effect is applied. Is anyone else having this problem or is it only on my end?

I didn’t use grimIK yet. But usually, that offset is what does the trick with softIK. The mGear solver does the same.
ToolChef solver doesn’t have this behavior?

EDIT: looks like it does the same. Note that the elbow position change when the softness is set to 3.00

I can’t remember, but does the mGear solver’s softness work when the limb is stretching or just when the stretch is off?

stretch is needed to get a good result

Hey Miquel I made a quick video illustrating one of the main differences between the two solvers were. TC solver is by no means ready for production as it has some issues setting the IK handle.

You can see the differences with the dampening effect. TC solver doesn’t seem to be reliant on scaling/stretching the joint chain at all. I have no idea why this is and I am really curious as I don’t like using stretch limbs for my characters if It is not required.

I hope you find this interesting.

1 Like

I see what you mean. The stretch and softness seem to have some unintended reliance/influence on each other. And at 1:52, you show it in action and it is more like a C-shaped snapping, and some of the softness is lost.

btw, I always wondered if it would be possible (I’m sure it must be) to come up with a softness formula that centered around the rest pose, so that the limb didn’t push outwards when you turn softness on.

Hello @dew
Thanks for the video. The issue with the damping effect when there is not enough stretch is clear.
But as you guest correctly all the behavior is in the C++ solver math. So we need to review that and get a better formula.

I have logged it here

This may take a while. But I will look at it.

Thanks,
Miquel

Hey Miquel thank you for looking into this. I had found another proof of concept algorithm for the softIK effect. I just tried it out and it seems to work okay. I don’t know about working with stretch since it’s a very small plug in just barely 100 lines of code.

SoftIk

as you can see here you only need to use a very small amount to get the effect without moving the joints at rest.

The code is free to look at and see how it’s running the math. I have not looked at the mGear solver so I can’t compare them to see how they differ.

I’m looking at the ikfk2Bone.cpp to look for the code snippet controlling the softness algorithm. Seems I found it and maybe some folks could chime in what could potentially be causing the issue. I’m guessing it’s possibly the if statement but I’m not entirely sure how the rest of the code below is being calculated. I don’t see any other calls to the softness.

// Distance with MaxStretch ---------------------
double restLength = (data.lengthA * data.scaleA + data.lengthB * data.scaleB) * global_scale;
double distance = rootEffDistance;
double distance2 = distance;
if (distance > (restLength * data.maxstretch))
    distance = restLength * data.maxstretch;

// Adapt Softness value to chain length --------
data.softness = data.softness * restLength * .1;

// Stretch and softness ------------------------
// We use the real distance from root to controler to calculate the softness
// This way we have softness working even when there is no stretch
double stretch = std::max(1.0, distance / restLength);
double da = restLength - data.softness;
if ((data.softness > 0) && (distance2 > da)){
    double newlen = data.softness*(1.0 - exp(-(distance2 -da)/data.softness)) + da;
    stretch = distance / newlen;
}

data.lengthA = data.lengthA * stretch * data.scaleA * global_scale;
data.lengthB = data.lengthB * stretch * data.scaleB * global_scale;

It seems the Length A and B are entirely dependent on the Stretch being added into the variable. And the softness is only if the if statement is true.

    double newlen = data.softness*(1.0 - exp(-(distance2 -da)/data.softness)) + da;
    stretch = distance / newlen;

My understanding, looking at the logic of the original algorithm may be something more like this.

RestLength - Length of joint chain (Joint A) + (Joint B)

RestLength = (JointA) + (JointB)
softAmount = (Whatever 1.0)
SoftDistance = RestLength - softAmount
distance = (Distance between Joint A and Joint B)

if (distance > SoftDistance)
IKHandle = SoftDistance + softAmount * (1-exp( -(distance - SoftDistance))
else
IKHandle = distance

I have no idea if what I wrote makes sense, it’s not any specific language just what i found from reading and researching. Any thoughts?

1 Like

A quote from that old article:

In XSI, we need a way of allowing the chain to gradually fall behind the position of the effector.

This is the original assumption that ends up necessitating a bit of stretch. Because if the effector “falls behind”, it eventually has to catch up, and one way is by making it catch up further than the straight length of the IK chain.

So… I don’t have a math formula, but here is how you could imagine reversing this assumption. Instead of the effector falling behind, it could race ahead slightly. And then they could meet exactly at the final length of the IK chain. (And thus be completely separate from the stretchy limb.) Beyond the length of the straight IK, the position of the effector would match 1:1 linearly.

This is what the formula could look like expressed as a function curve.

Which would animate like this. Black is the soft effect. Faint green is original snappy IK.
ik_softness

2 Likes

Makes sense Chris, that old XSI article pretty much has the formula posted on it.

I never considered doing it in reverse. But someone smarter then me could probably answer that better.

image

From what i read in the code there is an issue (I think) with the distance2 and distance call

either by removing or changing the calls to distance2 alltogether or just changing

stretch = distance / newlen;

to

stretch = distance2 / newlen;

I really don’t know myself unless I try and mess with the code and compile it.

I’m also not sure if the code is changing the length of the bones themselves or adjusting the effector or both.

1 Like

So my findings did not reveal much. The way the IKFK2Bone solver works with the softness is by changing the length of the bones to adjust for the algorithm. This however does not work if the IK does not have stretch applied to it. Normally how soft IK solvers work is the softness is applied to the IK handle position itself to achieve this effect. I tested this by running the mGear IK handle without stretch and parent constraining it’s IK effector to an node with an expression added.

This works very nicely with mGear. So I know fixing this is possible I am just still a bit new at maya’s API and am unsure how to add new output attributes to the node, and have them access as variables. Unless someone can find something to fix with the math or run the calculation based on a matrix position instead and a quaternion output attribute the node spits out so things can be updated in Shifter.

Just my thoughts.

Nice finding @dew
Thanks for all the research you are doing. All this information will be very useful when we tackle the ticket. :slight_smile:

Ty Miquel. I seemed to have checked the math on the algorithm itself and aside from some small differences I can’t see any issues with the equation in itself.

I’m beginning to suspect it has something to do with the way the elbow position is calculated. As we can see here when the “softness” value is changed in a default position the elbow is moving to compensate for the softness distance.

So that is definitely being added into the final calculation of it’s position. However something is preventing its position to lag behind like you would normally find in a softIK system. When the MaxStretch value is at 1, as in no stretch being applied. We can still see the soft IK calculation being done onto the Length A and B sides of the bones however the elbow snaps into position as if it were a normal IK.

I am still able to move the elbow freely, however there is something positional not being added up correctly. Since the bones become completely straight then change their lengths instead of forcing a triangular shape and changing the elbows position mostly. I’m pretty sure the end bone (Wrist does not move past it’s max length but eases into it instead.

I checked the code sections of where the elbow position is being calculated and the only thing I can find is some commented out code for scale. I did not uncomment it to check if it removed the bug. But any thoughts from folks as to where I should look in the code would be very welcome.

So I’ve reached the conclusion that there is no possible way to add soft IK to the bone lengths and have the elbow ease into position. I changed the math to absolutely make sure the end and root are following the soft IK distance algorithm correctly. However this means the lengths of each Bone will shorten temporarily to account for the sudden dampening effect. By doing that the elbow now sees the lengths have suddenly shortened and snaps down because it’s calculating it’s new position.

The only solution I see possible to fix this is to run the soft IK calculation independent of everything else. This would mean the If statement would run and output a new matrix attribute controlling the IK handle Null/Ref, which that can be constrained normally to all of the components. It would only change the structure of things slightly. I wanted to see about fixing this and leaving everything else in tact but that does not look possible unless there is a way to calculate the elbow’s position to compensate and that does not seem like a straight forward fix.

Any thoughts would be greatly appreciated.

Never mind I apparently figured it out. I was looking in the wrong place. The law of cosign had to be factored in.

It works, and works VERY well. I just need to get the stretch working back with this and it will be non destructive to everyone’s rig.

easy fix once you know what the issue was. (Isn’t it always, 4 days of doing this says otherwise)

I will upload the source code once I get the stretch and everything working with it.

Thank you! For allowing me to help out and solve some bugs.

1 Like

@Miquel Would it be possible to change this topic name somehow to solved?

@dew thanks to you for all the research and information shared :smiley:

done! :wink:

1 Like

I’ll finish fixing up the stretch with the Softness this weekend. When I have this code fixed how do I send it back to you guys to make sure it gets pushed through with the new release? @Miquel

1 Like

Please use Github PR (pull Request)

are you doing the change on the C++ code?