CCD IK(循环坐标下降逆动态学)

编程入门 行业动态 更新时间:2024-10-25 14:30:30

CCD IK(循环<a href=https://www.elefans.com/category/jswz/34/1771040.html style=坐标下降逆动态学)"/>

CCD IK(循环坐标下降逆动态学)

CCDIK(循环坐标下降逆动态学)

策略思路
1.骨骼间的结构为子父层次链接(父节点的变换会影响子节点的)
2.每个骨骼都以【自身轴点到尾叶子节点的方向】旋转到【自身轴点到目标点方向】,开始趋近
3.最终效果与迭代次数成正比

更多细节查看 IK

Arrow类

    [Serializable]public class Arrow{public float len;		//箭头长度public float angle;		//相对父箭头方向的角度public Vector2 angleLimt = new Vector2(-180f,180f);		//角度限制public Color color;			//Gizmo Colorpublic Vector2 a { get; private set; }  //起点public Vector2 b { get; private set; }  //终点public Vector2 forward { get { return (b - a).normalized; } }/// <summary>/// 箭头看向目标位置/// </summary>/// <param name="target">目标位置</param>/// <param name="end">评估节点位置</param>/// <param name="limt">角度限制</param>public void Follow(Vector2 target, Vector2 end, bool limt){angle = (angle + Vector2.SignedAngle(end - a, target - a)) % 360f;if (limt && (angleLimt.x != -180 || angleLimt.y != 180)){angle = Mathf.Clamp(angle, angleLimt.x, angleLimt.y);}}/// <summary>/// 计算箭头 A、B 点位置/// </summary>/// <param name="origin">起点</param>/// <param name="right">父箭头方向</param>public void Calculate_AB(Vector2 origin, Vector2 right){a = origin;b = a + Rotate(right, angle) * len;}/// <summary>/// 返回旋转后的角度/// </summary>/// <param name="v">normal</param>/// <param name="a">rad</param>private Vector2 Rotate(Vector2 v, float a){a = a * Mathf.Deg2Rad + Mathf.Atan2(v.y, v.x);return new Vector2(Mathf.Cos(a), Mathf.Sin(a));}}

IKSolverCCD 类

    [Serializable]public class IKSolverCCD {public Arrow[] arrows = new Arrow[] { };    //箭头集合public Vector2 target;  //目标位置public bool useLimt = false;        //是否启用角度限制public int iterations = 4;      //迭代次数/// <summary>/// 箭头线段跟踪目标位置/// </summary>/// <param name="maxIterations">迭代次数</param>public void FollowTarget(){for (int n = 0; n < iterations; n++){for (int i = arrows.Length - 1; i >= 0; i--){arrows[i].Follow(target, arrows[arrows.Length - 1].b, useLimt);UpdatePosition(i == 0 ? Vector2.right : arrows[i - 1].forward, i);}}}/// <summary>/// 集合箭头从指定顺序索引开始更新箭头 A、B 点位置/// </summary>/// <param name="arrows">箭头集合</param>/// <param name="right">父箭头方向</param>/// <param name="n">指定顺序索引</param>public void UpdatePosition(Vector2 right, int n = 0){Vector2 origin = arrows[n].a;for (; n < arrows.Length; n++){arrows[n].Calculate_AB(origin, right);origin = arrows[n].b;right = arrows[n].forward;}}}

CCDTest类

    public class CCDTest : MonoBehaviour{public IKSolverCCD iKSolverCCD;     //CCD 解算器public Transform targetP;       //目标位置public Transform anchorP;       //固定位置public bool useLimt = true;     //使用限制public bool update = false;     //实时更新[Range(1,10)]public int iterations = 1;      //迭代次数[Button("UpdateAnchor")]void UpdateAnchor(){iKSolverCCD.useLimt = useLimt;iKSolverCCD.iterations = iterations;iKSolverCCD.arrows[0].Calculate_AB(anchorP.position, Vector2.right);iKSolverCCD.UpdatePosition(Vector2.right);iKSolverCCD.FollowTarget();}[Button("Calculate")]void Calculate(){iKSolverCCD.useLimt = useLimt;iKSolverCCD.iterations = iterations;iKSolverCCD.target = targetP.position;iKSolverCCD.FollowTarget();}private void OnDrawGizmos(){if (update) {Calculate();}Arrow last = null;foreach (var item in iKSolverCCD.arrows){Gizmos.color = item.color;Mov.GizmeDrawArrow(item.a, item.b);if (useLimt){Mov.GizmeDrawCircleLimt(item.a, item.forward, item.angleLimt, 0, item.len / 4f, last == null ? (item.a-Vector2.right): last.a);}last = item;}}}

更多推荐

CCD IK(循环坐标下降逆动态学)

本文发布于:2024-02-26 15:22:41,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1702984.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:坐标   动态   CCD   IK

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!