Hello @harinath.
At first, please excuse my awkward English.
I’m also finding the method to constrain the joints in FABRIK algorithm to make a finger IK.
So far, I made progress to make a polygon from angles(Theta1 to Theta4), and it seems I can extract 2D figure.

However, I’ve wondered how to make a figure like (b), I have an idea but haven’t tried yet.
The idea is using Quaternion.Slerp to make curves like (b).
BTW, even if I make the figure, there is another problem, I have to calculate some point is inside or outside the figure.
If the figure is a polygon, there is a theory called Crossing Number Method.
I tested this for a polygon and it works well but, I have no idea for (b).
I’m still trying to make progress.
If you have any idea, please let me know.
Thank you.
And here’s my codes which based on this thread.
FABRIK.cs
using UnityEngine;
using System.Collections;
/**
* FABRIK Solver based on paper found here - www.andreasaristidou.com/publications/FABRIK.pdf
*
* http://forum.unity3d.com/threads/187838-INVERSE-KINEMATICS-Scripting-Tutorial-Searching?p=1283005&viewfull=1#post1283005
*/
public class FABRIK : MonoBehaviour
{
public int maxSolverIterations = 20; // 15 iterations is average solve time
public float solveAccuracy = 0.001f;
public IKChain myChain;
void Start()
{
this.myChain.Init();
}
void Update()
{
if (this.myChain.target != null)
{
this.Solve(this.myChain);
}
}
void OnDrawGizmos()
{
this.myChain.DebugDraw();
}
void Solve(IKChain chain)
{
var joints = chain.joints;
if (joints.Length < 2)
return;
var rootToTargetDist = Vector3.Distance(joints[0].position, chain.target.position);
var lambda = 0f;
// Target unreachable
if (rootToTargetDist > chain.length)
{
for (int i = 0; i < joints.Length - 1; i++)
{
lambda = chain.segLengths[i] / Vector3.Distance(joints[i].position, chain.target.position);
joints[i+1].position = (1 - lambda) * joints[i].position + lambda * chain.target.position;
}
}
else // Target within reach
{
chain.Reset();
var rootInitial = joints[0].position;
var tries = 0;
var targetDelta = Vector3.Distance(joints[joints.Length-1].position, chain.target.position);
while (targetDelta > this.solveAccuracy tries < this.maxSolverIterations)
{
// Forward reaching phase
joints[joints.Length-1].position = chain.target.position;
for (int i = joints.Length - 2; i > 0; i--)
{
lambda = chain.segLengths[i] / Vector3.Distance(joints[i+1].position, joints[i].position);
var pos = (1 - lambda) * joints[i+1].position + lambda * joints[i].position;
joints[i].position = pos;
joints[i].position = this.Constraints(joints[i+1], joints[i]);
}
// Backward reaching phase
joints[0].position = rootInitial;
for (int i = 0; i < joints.Length - 1; i++)
{
lambda = chain.segLengths[i] / Vector3.Distance(joints[i+1].position, joints[i].position);
var pos = (1 - lambda) * joints[i].position + lambda * joints[i+1].position;
joints[i+1].position = pos;
joints[i+1].position = this.Constraints(joints[i], joints[i+1]);
}
targetDelta = Vector3.Distance(joints[joints.Length-1].position, chain.target.position);
tries++;
}
}
}
Vector3 Constraints(IKJoint j, IKJoint j_1)
{
return j_1.position;
}
}
IKChain.cs
using UnityEngine;
using System.Collections;
[System.Serializable]
public class IKChain
{
public Transform target;
public IKJoint[] joints;
[System.NonSerialized]
public float[] segLengths;
[System.NonSerialized]
public float length;
private Vector3[] localPositions; //**temp
private Quaternion[] localRotations; //**temp
public bool Inited
{
get{ return this.segLengths != null; }
}
public void Init()
{
this.segLengths = new float[joints.Length];
for (int i = 0; i < this.joints.Length - 1; i++)
{
float dist = (this.joints[i].position - this.joints[i+1].position).magnitude;
{
this.segLengths[i] = dist;
this.length += dist;
}
}
this.localPositions = new Vector3[joints.Length];
this.localRotations = new Quaternion[joints.Length];
for (int i = 0; i < this.joints.Length; i++)
{
this.localPositions[i] = this.joints[i].localPosition;
this.localRotations[i] = this.joints[i].localRotation;
}
}
public void Reset()
{
for (int i = 0; i < this.joints.Length; i++)
{
this.joints[i].localPosition = this.localPositions[i];
this.joints[i].localRotation = this.localRotations[i];
}
}
public void DebugDraw()
{
if (!this.Inited)
this.Init();
for (int i = 0; i < this.joints.Length - 1; i++)
{
Gizmos.color = Color.cyan;
Gizmos.DrawLine(this.joints[i].position, this.joints[i+1].position);
var con = this.joints[i].constraints;
if (con == null)
continue;
var len = this.segLengths[i];
var a = this.joints[i].position;
var b = this.joints[i+1].position;
var ar = this.joints[i].rotation;
var br = this.joints[i+1].rotation;
var line1 = ar * con.upDir * 0.03f;
var line2 = -line1;
var line3 = br * con.rightDir * 0.03f;
var line4 = -line3;
Gizmos.color = Color.gray;
Gizmos.DrawLine(b, b + line1);
Gizmos.DrawLine(b, b + line2);
Gizmos.DrawLine(b, b + line3);
Gizmos.DrawLine(b, b + line4);
var upRad = Mathf.Deg2Rad * con.upDegree;
var downRad = Mathf.Deg2Rad * con.downDegree;
var leftRad = Mathf.Deg2Rad * con.leftDegree;
var rightRad = Mathf.Deg2Rad * con.rightDegree;
var line5 = len * (ar * new Vector3(-Mathf.Cos(upRad), Mathf.Sin(upRad), 0));
var line6 = len * (ar * new Vector3(-Mathf.Cos(downRad), -Mathf.Sin(downRad), 0));
var line7 = len * (ar * new Vector3(-Mathf.Cos(leftRad), 0, Mathf.Sin(leftRad)));
var line8 = len * (ar * new Vector3(-Mathf.Cos(rightRad), 0, -Mathf.Sin(rightRad)));
Gizmos.color = Color.blue;
Gizmos.DrawLine(a + line5, a + line6);
Gizmos.DrawLine(a + line7, a + line8);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(a, a + line5);
Gizmos.DrawLine(a, a + line6);
Gizmos.DrawLine(a, a + line7);
Gizmos.DrawLine(a, a + line8);
Gizmos.color = Color.green;
Gizmos.DrawLine(a + line5, a + line8);
Gizmos.DrawLine(a + line8, a + line6);
Gizmos.DrawLine(a + line6, a + line7);
Gizmos.DrawLine(a + line7, a + line5);
}
}
}
IKJoint.cs
using UnityEngine;
using System.Collections;
[System.Serializable]
public class IKConstraints
{
public float upDegree = 90;
public float downDegree = 5;
public float leftDegree = 0;
public float rightDegree = 0;
public Vector3 forwardDir = new Vector3(-1,0,0);
public Vector3 rightDir = new Vector3(0,0,1);
public Vector3 upDir = new Vector3(0,1,0);
};
[System.Serializable]
public class IKJoint
{
public Transform root;
public IKConstraints constraints;
public Vector3 position{
get{ return this.root.position; }
set{ this.root.position = value; }
}
public Quaternion rotation{
get{ return this.root.rotation; }
set{ this.root.rotation = value; }
}
public Vector3 localPosition{
get{ return this.root.localPosition; }
set{ this.root.localPosition = value; }
}
public Quaternion localRotation{
get{ return this.root.localRotation; }
set{ this.root.localRotation = value; }
}
public static implicit operator Transform(IKJoint joint){
return joint.root;
}
public static implicit operator IKJoint(Transform joint){
return new IKJoint(joint);
}
public IKJoint(){
}
public IKJoint(Transform t){
this.root = t;
}
};