Inverse Kinematics + mass instances

@weitjong please do not lock this even if you find similar topic

@TheComet this topic is mainly addressed to you, but I think it should be interesting to others.

As work on bug #1957 looks like done by @TheComet and IK should be usable on mass instances.

I tried to test it today, but I could not make it work in my case of 100 NPCs.

I’m probably stupid, but I see no effect, but lets clarify proper setup procedure. I know IK is not ready to run Makehuman characters, but anyway I want to see some effect over there.

So what I do: I create IKEffector on foot.L and foot.R
I set chain length to 4 for each.
I add IKSolver
I disable auto-solving
I subscribe to events
I call Solve() from event

void Init()
...
        Node@ leftFoot  = node.GetChild("foot.L", true);
        Node@ rightFoot = node.GetChild("foot.R", true);
        IKEffector@ leftEffector  = leftFoot.CreateComponent("IKEffector");
        leftEffector.chainLength = 4;
        IKEffector@ rightEffector = rightFoot.CreateComponent("IKEffector");
        rightEffector.chainLength = 4;
        Node@ spine = node.GetChild("spine02", true);
        IKSolver@ solver = spine.CreateComponent("IKSolver");
        solver.algorithm = IKAlgorithm::FABRIK;
        solver.SetFeature(IKFeature::AUTO_SOLVE, false);
        SubscribeToEvent("SceneDrawableUpdateFinished", "HandleSceneDrawableUpdateFinished");
...
}
void HandleSceneDrawableUpdateFinished(StringHash eventType, VariantMap& eventData)
{
    Node@ rfoot = node.GetChild("foot.R", true);
    Node@ spine = node.GetChild("spine02", true);
    IKSolver@ solver = spine.GetComponent("IKSolver");
    IKEffector@ re = rfoot.GetComponent("IKEffector");
    re.targetPosition = Vector3(0, -1, 0);
    solver.SetFeature(IKFeature::UPDATE_ORIGINAL_POSE, true);
    solver.Solve();
}

Do I miss anything?

The test blend file is available here: http://ossfans.org/man-suit-hidden.blend.gz

OK, I found what needs to be done (probably needed to be documented) - IK solver should be put
close to chains, if IK do not work it is better to put solver very close to a chain.

I took a look at your .blend file, the problem is that you are attaching IKSolver to a bone that is not a parent of the feet bones (spine02 is not a parent of Foot.L or Foot.R). The solver will only regard nodes that are “below” it in a tree.

The first bone in your model that is a parent of the two effector bones is the bone called root and you should be creating IKSolver as a component of this bone.

Node@ root = node.GetChild("root", true);
IKSolver@ solver = root.CreateComponent("IKSolver");

Thanks for answer, I got from here. But there are some bad news.

To me it looks like IK sanity depends on root bone rotation, which provides weird effects.

I do not update effector targets here (no difference if I do though), just run Solve().

Any pointers? (same skeleton).
The player character do not have IK, only NPCs.

p.s.
Very nice to hear from you!!!

1 Like

Are you calling Solve() on every IKSolver component? I’d need to see your update code, but to me it looks like you’re only calling Solve() for your player.

Player have no IK at all.

This is for NPC - (every NPC).

    void Init()
    {
...
        Node@ leftFoot  = node.GetChild("foot.L", true);
        Node@ rightFoot = node.GetChild("foot.R", true);
        IKEffector@ leftEffector  = leftFoot.CreateComponent("IKEffector");
        leftEffector.chainLength = 3;
        IKEffector@ rightEffector = rightFoot.CreateComponent("IKEffector");
        rightEffector.chainLength = 3;
        Node@ spine = node.GetChild("root", true);
        solver = spine.CreateComponent("IKSolver");
        solver.algorithm = IKAlgorithm::FABRIK;
        solver.SetFeature(IKFeature::AUTO_SOLVE, false);
        
        SubscribeToEvent("SceneDrawableUpdateFinished", "HandleSceneDrawableUpdateFinished");
}
    void HandleSceneDrawableUpdateFinished(StringHash eventType, VariantMap& eventData)
    {
        Node@ rfoot = node.GetChild("foot.R", true);
        Node@ lfoot = node.GetChild("foot.L", true);
        IKEffector@ re = rfoot.GetComponent("IKEffector");
        IKEffector@ le = lfoot.GetComponent("IKEffector");
        solver.SetFeature(IKFeature::UPDATE_ORIGINAL_POSE, true);
        solver.Solve();
    }

If I run without IK, NPCs look normal (legs are where they are supposed to be).

Are your NPCs animated?

As you could notice from video, yes. I could upload video w/o IK enabed for you to see…

Here I run with IK enabled but I do not run Solve, so animations work, but no IK correction functions.

So you can see how it was looking without Solve() running.

Sorry for video quality - Urho can’t be recorded properly under Linux (at least with nvidia driver).

This is really weird. I was actually able to reproduce exactly the behaviour you were having, where the feet of all of the NPCs are pointing to 0,0,0. I undid changes (which fixed it), redid everything again, and then it just started working correctly.

There is certainly a bug here that causes all feet to point to 0,0,0 but I don’t think we’re sure yet what causes it.

I modified 45_InverseKinematics so it would spawn 25 Jacks instead of just 1. Here, have a play around with it.
https://pastebin.com/zvqxBd9K

Multiple solvers appear to work fine.

1 Like

Do you have plans to make actual Makehuman skeleton (the same like with that file) supported?
This requies bone skipping. I will wait until Makehuman character is supported, so I could integrate IK in my game.
At least this offsetting of legs should be resolved somehow…

Thank you for your work!

Also another question - will it be possible to run feet IK + arm IK at the same time?
Are several solvers supported for the same skeleton?

Yes, this looks like all targets point to (0, 0, 0) regardless of what I set them to, which is strange,
and this reproduces for me always, I can’t get correct behavior…

I also see this warning when I set effectors then solver:

[Wed Aug  2 02:35:35 2017] INFO: [IK] Warning: Tried iterating the tree, but no tree was set

The code, which produce the warning is the following -

        IKEffector@ leftEffector  = leftFoot.CreateComponent("IKEffector");
        leftEffector.chainLength = 2;
        IKEffector@ rightEffector = rightFoot.CreateComponent("IKEffector");
        rightEffector.chainLength = 2;
        Node@ spine = node.GetChild("root", true);
        solver = spine.CreateComponent("IKSolver");

Warning is produced by last line.

Also I tried setting different chain length and tried TWO_BONE algorithm, there is
no difference at all.

Yes, so what I see is targetPosition setting is complely ignored by IK components which results all targets being at (0, 0, 0). Probably I will try to debug this on weekend unless you see what is going on before that.

At first glance:

  • setting targetPosition to Vector3(0, -1, 0) is a request for straight legs (for example, if floor is at 0, you are trying to reach 1 unit below floor level)
  • solver.SetFeature(IKFeature::UPDATE_ORIGINAL_POSE, true); is set in HandleSceneDrawableUpdateFinished, should be set only once in Init()
  • your chain length seems to vary between 3 and 4
1 Like