2

I'm doing an "aim-gun-towards mouse" with a 2D skeletal character with 2 bones, ArmUpper and ArmLower (hand is fixed) and I think I need some kind of IK solver. Here are the parameters:

  • ArmUpper: Fixed position in the shoulder, but can rotate freely
  • ArmLower: Has a fixed rotation (depending on weapon type), and it's position is set by rotating ArmUpper, which makes it end up somewhere in the green circle

How can I calculate the rotation of ArmUpper so that both ends of ArmLower aims towards the target reticle?

I'm making this with Unity in C#, but any pseudo-code or formula will help.

Thanks!

enter image description here

Niclas
  • 1,362
  • 1
  • 11
  • 24

1 Answers1

1

We know the coordinates of the point(mouse position) and the circle center (shoulder position), and also we could know the angle of the elbow:
e, P, C
enter image description here

you should notice that the line going through the circle could be cut in one or two points in case of one point it's the tangent to the circle and also h==r another thing to note is that the line could cut the circle in two possible ways (the pink and red lines) based on your calculations you might see that the arm is rotating the wrong way or it's facing the opposite direction I'm not exactly sure why but in any case you could play with the variables to get the right behavior.

enter image description here

enter image description here

Note that the elbow angle should be between 0 and 180

here is an implemetaion in Unity:

        Vector2 mousePos = _camera.ScreenToWorldPoint(Input.mousePosition);
        Vector2 circlePos = shoulder.position;
        float radius = _elbowDistance;
        float e = elbow.localEulerAngles.z;

        float distance = Vector2.Distance(mousePos, circlePos);
        if (distance < radius) return;
        
        Vector2 direction = mousePos - circlePos;
        e = (180-e) * Mathf.Deg2Rad; //i dont know why exactly but i had to reverse this
        float ePrime = Mathf.PI - e;
        float h = Mathf.Abs(Mathf.Sin(ePrime) * radius);
        float gamma = Mathf.Acos(h / distance);
        float alpha = Mathf.Atan2(direction.y, direction.x);
        float beta = gamma - ((Mathf.PI / 2) - ePrime);
        float angle = beta- alpha;
        Vector2 contactPos = new Vector2(circlePos.x + (Mathf.Cos(angle) * radius), circlePos.y - (Mathf.Sin(angle) * radius));
        
        visualize.position = contactPos;

        Vector2 armDirection = contactPos - circlePos;
        var rotation = Quaternion.Euler(0, 0, Mathf.Atan2(armDirection .y, armDirection .x) * Mathf.Rad2Deg);
        shoulder.rotation = rotation;

and the result:
enter image description here

It's a late answer but for anyone having the same problem I hope this is helpful.

MohMehdi
  • 111
  • 3