循环坐标下降反向动力学(CCD Ik)

正向动力学:根据父骨骼的移动,一步步正向推导出子骨骼的位置。

反向动力学:根据骨骼末端位置的移动,反向推导出父骨骼及其余上级骨骼的位置。

CCD Ik(循环坐标下降反向动力学):

2D:以当前骨骼起点为轴,分别连接目标点与骨骼末端,保持目标点与骨骼起点的连线不动,旋转当前骨骼(注意子骨骼也会随之转动),使得骨骼末端位置与当前骨骼起点的连线重合。从子骨骼开始到全部父骨骼完成一次转动,视为一次迭代,迭代次数越多,效果越好。

 

其核心代码思想及相关注释如下:

//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:将当前骨骼起点连接目标点和骨骼末端,再做这两条相交向量的法向量,以该法向量为轴,做上述旋转,迭代。

 

其核心代码思想及相关注释如下:

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);
				}

			}
		}

参考文献:

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值