Cyclic Coordinate Descent Inverse Kinetics (CCD Ik)

Forward dynamics: According to the movement of the parent bone, the position of the child bone is deduced step by step forward.

Inverse dynamics: According to the movement of the end position of the bone, the position of the parent bone and other superior bones is deduced in reverse.

CCD Ik (Cyclic Coordinate Descent Inverse Kinetics):

2D: Take the starting point of the current bone as the axis, connect the target point and the end of the bone respectively, keep the connection between the target point and the starting point of the bone, and rotate the current bone (note that the sub-bone will also rotate accordingly), so that the position of the end of the bone is the same as the current bone The starting lines coincide. One rotation from the child bone to all the parent bones is regarded as one iteration. The more iterations, the better the effect.

 

Its core code ideas and related comments are as follows:

//bones[i].a表示骨骼起点,bones[i].b表示骨骼终点,bones[i].len表示骨骼长度,bones.Length表示骨骼数目,target表示目标点
    for (int n = 0; n<iterations; n++)//迭代次数
		{
			for (int i = arrows.Length - 1; i >= 0; i--)//遍历每根骨骼
			{
                bones[i].angle = (angle + Vector2.SignedAngle(bones[bones.Length - 1].b - a, target - a)) % 360f;//angle表示相对于父骨骼的角度,获取目标点到当前骨骼起点与末端位置到当前骨骼起点两条线间的夹角

                int j = i;

                Vector2 origin = bones[j].a;
                if(j!=0)
                        Vector2 right = bones[i - 1].forward;
                else
                        Vector2 right = Vector2.right; //(1,0)
                for(; j<bones.Length ; j++)//当前骨骼旋转后,变更子骨骼的位置
                {
                    bones[j].a = origin;
        
                    //变更骨骼位置
                    bones[j].b = bones[j].a + Vector2(Mathf.Cos(bones[j].angle* Math.Deg2Rad + Mathf.Atan2(right.y, right.x)),Mathf.Sin(bones[j].angle* Math.Deg2Rad + Mathf.Atan2(right.y, right.x)));
                    
                    //修改以下信息以便更改后续子骨骼的位置
                    origin = bones[j].b;  
			        right = bones[j].forward;
                }
			}
		}

 

3D: Connect the starting point of the current bone to the target point and the end of the bone, and then make the normal vector of the two intersecting vectors, and use the normal vector as the axis to perform the above rotation and iteration.

 

Its core code ideas and related comments are as follows:

for (int n = 0; n < iterations; n++)//迭代次数
		{
			for (int i = bones.Length - 1; i > 0; i--)//遍历骨骼
			{
				Vector3 tolastbone = bones[bones.Length - 1].b - bones[i].a;//当前骨骼起点到末端位置

				Vector3 totarget = target - bones[i].a;//当前骨骼起点到目标点

				Vector3 axis = Vector3.Cross(tolastbone, totarget).normalized;//去上述二向量的法向量做旋转轴

				float angle = Vector3.SignedAngle(tolastbone, totarget, axis);//以该旋转轴所需旋转的角度

				for (int j = i; j < bones.Length; j++)//依次修改每根骨骼及其子骨骼的位置
				{
					bones[j].b = bones[i - 1].b + Quaternion.AngleAxis(angle, axis) * (bones[j].b - bones[i - 1].b);
				}

			}
		}

references:

https://blog.csdn.net/f980511/article/details/123316988

https://zhuanlan.zhihu.com/p/469221237

Guess you like

Origin blog.csdn.net/qhd12/article/details/127491719