贝塞尔曲线的应用
2015-08-04 22:32
218 查看
在Unity设计过程中,我们常常会想让游戏中的人群或者相机延一组点进行移动,若想使其平滑运动,这时我们便会用到贝塞尔曲线。
贝塞尔曲线公式如下:
一条贝塞尔曲线直接使用公式可使两点连接,代码如下:
通过这段代码可使两点间的曲线自由变换,其效果如图:
如此,两点间的贝塞尔曲线就做好了。那么现在需要把多条贝塞尔曲线连接到一起,注意,起始点和终点的切线设为0,其余点的切线设为其相邻点的差。
多条贝塞尔曲线效果图:
用这样的曲线去模拟人群行走,就会变得平滑许多啦!
贝塞尔曲线公式如下:
一条贝塞尔曲线直接使用公式可使两点连接,代码如下:
using UnityEngine; using System.Collections; using System.Collections.Generic; public class Curve : MonoBehaviour { public GameObject[] objs; //要连接的物体 List<Vector3> points; //所有点的位置 public static Material lineMaterial; static void CreateLineMaterial() { if (!lineMaterial) { lineMaterial = new Material("Shader \"Lines/Colored Blended\" {" + "SubShader { Pass { " + " Blend SrcAlpha OneMinusSrcAlpha " + " ZWrite Off Cull Off Fog { Mode Off } " + " BindChannels {" + " Bind \"vertex\", vertex Bind \"color\", color }" + "} } }"); lineMaterial.hideFlags = HideFlags.HideAndDontSave; lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave; } } void OnPostRender() { points = Line (objs); CreateLineMaterial(); lineMaterial.SetPass(0); GL.Begin(GL.LINES); GL.Color(Color.red); //画出贝塞尔曲线 for (int i = 0; i < points.Count - 1; i++) { GL.Vertex(points[i]); GL.Vertex(points[i + 1]); } //切线 GL.Vertex (objs[0].transform.position); GL.Vertex (objs[1].transform.position); GL.Vertex (objs[2].transform.position); GL.Vertex (objs[3].transform.position); GL.End(); } //计算贝塞尔曲线 List<Vector3> Line (GameObject[] objs) { List<Vector3> line = new List<Vector3> (); for (float i = 0; i < 1; i+=0.02f) { Vector3 temp = new Vector3(0,0,0); for (int j = 0; j < objs.Length; j++) { temp += nCr (objs.Length - 1,j) * Mathf.Pow((1 - i),objs.Length - 1 - j) * Mathf.Pow(i, j) * objs[j].transform.position; } line.Add (temp); } return line; } //组合 int nCr (int n,int r) { return Factorial (n) / (Factorial (r) * Factorial (n - r)); } //阶乘 int Factorial (int value) { if (value == 0) { return 1; } int sum = 1; for (int i = 0; i < value; i++) { sum *= (i + 1); } return sum; } }
通过这段代码可使两点间的曲线自由变换,其效果如图:
如此,两点间的贝塞尔曲线就做好了。那么现在需要把多条贝塞尔曲线连接到一起,注意,起始点和终点的切线设为0,其余点的切线设为其相邻点的差。
using UnityEngine; using System.Collections; using System.Collections.Generic; public class Curve2 : MonoBehaviour { public GameObject[] objs; //所要连接物体 List<Vector3> points; //所有点的位置 public float tangentSize = 1f; //切线大小 public static Material lineMaterial; static void CreateLineMaterial() { if (!lineMaterial) { lineMaterial = new Material("Shader \"Lines/Colored Blended\" {" + "SubShader { Pass { " + " Blend SrcAlpha OneMinusSrcAlpha " + " ZWrite Off Cull Off Fog { Mode Off } " + " BindChannels {" + " Bind \"vertex\", vertex Bind \"color\", color }" + "} } }"); lineMaterial.hideFlags = HideFlags.HideAndDontSave; lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave; } } void OnPostRender() { Vector3[] pos = new Vector3[objs.Length]; for (int i = 0; i < objs.Length; i++) { pos[i] = objs[i].transform.position; } points = WholeLine (pos); CreateLineMaterial(); lineMaterial.SetPass(0); GL.Begin(GL.LINES); GL.Color(Color.red); for (int i = 0; i < points.Count - 1; i++) { GL.Vertex(points[i]); GL.Vertex(points[i + 1]); } GL.End(); } //画出所有曲线 List<Vector3> WholeLine (Vector3[] value) { List<Vector3> line = new List<Vector3> (); Vector3[] tempPoint = new Vector3[4]; for (int i = 0; i < value.Length - 1; i++) { tempPoint[0] = value[i]; if (i == 0) { tempPoint[1] = value[i]; } else { tempPoint[1] = value[i] + Vector3.Normalize(value[i + 1] - value[i - 1]) * tangentSize; } tempPoint[3] = value[i + 1]; if (i == value.Length - 2) { tempPoint[2] = value[i + 1]; } else { tempPoint[2] = value[i + 1] + Vector3.Normalize(value[i] - value[i + 2]) * tangentSize; } List<Vector3> temp = Line (tempPoint); for (int j = 0; j < temp.Count; j++) { line.Add(temp[j]); } } return line; } //画出单条曲线 List<Vector3> Line (Vector3[] p) { List<Vector3> line = new List<Vector3> (); for (float i = 0; i < 1; i+=0.02f) { Vector3 temp = new Vector3(0,0,0); for (int j = 0; j < p.Length; j++) { temp += nCr (p.Length - 1,j) * Mathf.Pow((1 - i),p.Length - 1 - j) * Mathf.Pow(i, j) * p[j]; } line.Add (temp); } return line; } //组合 int nCr (int n,int r) { return Factorial (n) / (Factorial (r) * Factorial (n - r)); } //阶乘 int Factorial (int value) { if (value == 0) { return 1; } int sum = 1; for (int i = 0; i < value; i++) { sum *= (i + 1); } return sum; } }
多条贝塞尔曲线效果图:
用这样的曲线去模拟人群行走,就会变得平滑许多啦!
相关文章推荐
- 超图的地图慧
- 分布式与集群的区别通俗解释
- 什么是逻辑分区管理 LVM ,如何在Ubuntu中使用?
- 什么是逻辑分区管理 LVM ,如何在Ubuntu中使用?
- swagger整合spring mvc教程
- 输入一个字符串,如果第一个字符是大写并且其他字符不是大写,那么输出true,否则输出false。
- 服务器数据库挂掉 Can 't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock '(2) ";
- vsftpd的工作原理和配置
- 【更博冒泡一下.】
- hdu 5344 MZL's xor (2015多校第五场第2题) 简单化简
- hdoj 1016 素数圆环问题(深度优先搜索z和道题 )
- php判断是否为一维数组--count的妙用
- 模积和
- poj 1830 开关问题高斯消元
- UVA 11478 Halum
- First Missing Positive
- Docker容器的跨主机访问
- Git 版本控制使用
- POJ 1160:Post Office 邮局经典DP
- PCIe 配置空间读写内核实现