游戏编程精粹学习 - CatmullRom路径/线段平滑
来自《游戏编程精粹1》寻路部分文章,使用CatmullRom插值来达到平滑,算是对书中内容的练习。
using UnityEngine; using System.Collections; public class Practice : MonoBehaviour { public Transform[] points; void OnDrawGizmos() { //DrawSegmentPath(); DrawSmoothPath(); } void DrawSegmentPath() { for (int i = 1, j = 0; i < points.Length; i++, j++) { var a = points[i]; var b = points[j]; Gizmos.DrawLine(a.position, b.position); } } void DrawSmoothPath() { for (int i = 3; i < points.Length; i++) { var a = points[i - 3]; var b = points[i - 2]; var c = points[i - 1]; var d = points[i]; DrawCurve(a.position, b.position, c.position, d.position); } var fixA = points[0]; var fixB = points[1]; var fixC = points[2]; var diff = fixB.position - fixA.position; var fill = fixA.position + diff.normalized * diff.magnitude; DrawCurve(fill, fixA.position, fixB.position, fixC.position); fixA = points[points.Length - 3]; fixB = points[points.Length - 2]; fixC = points[points.Length - 1]; diff = fixC.position - fixB.position; fill = fixC.position + diff.normalized * diff.magnitude; DrawCurve(fixA.position, fixB.position, fixC.position, fill); } void DrawCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { for (float i = 1, j = 0, iMax = 20f; i <= iMax; i++, j++) { var t1 = i / iMax; var t2 = j / iMax; var tempP0 = CatmullRom(p0, p1, p2, p3, t1); var tempP1 = CatmullRom(p0, p1, p2, p3, t2); Gizmos.DrawLine(tempP0, tempP1); } } Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float u) { var r = p0 * (-0.5f * u * u * u + u * u - 0.5f * u) + p1 * (1.5f * u * u * u + -2.5f * u * u + 1f) + p2 * (-1.5f * u * u * u + 2f * u * u + 0.5f * u) + p3 * (0.5f * u * u * u - 0.5f * u * u); return r; } }