参考
- unity-procedural-mesh-bezier-curve:使用Bezier曲线建模。Bezier曲线不能经过每个控制点,所以放弃使用Bezier曲线来拟合离散点。但这个项目的建模方法不错,进行了优化,没有重叠的点或面,相邻的面共享了顶点。我借鉴这个项目改成了使用一条线段建模。
- Unity-Road-Generator:使用Catmull-Rom曲线建模。这个项目使用线段建模的方法很复杂,且没有进行过优化,有重叠的面,UV也是乱的。所以我只参考了这个项目根据离散度创建Catmull-Rom曲线上的点的代码。
效果
问题描述
输入一些离散的三维点坐标,输出一段Mesh。
- 输入:蓝色的球代表输入的控制点的三维坐标,一共有5个。这5个点代表了一条道路。控制点数据可以从.Shp文件的Polyline或者PolylineZ的points数组中获取,或者从Unity GameObject的Transform的position获取。
- 输出:一条道路用一个
road
游戏物体表示。road
包含两个子物体controlPointsObject
和meshObject
。前者有5个子物体,用来显示出控制点的位置。后者则添加了MeshFilter
和MeshRenderer
,负责渲染出我们创建出的Mesh。
子问题一:使用离散点构造一条Catmull-Rom曲线
学习了插值技术之Catmull-Rom Spline Interpolating(2)。
已知CatmullRom曲线的参数方程如下,我们需要求出此函数的输入:即start、end、tanPoint1,、tanPoint2。
public static Vector3 Interpolate(Vector3 start, Vector3 end, Vector3 tanPoint1, Vector3 tanPoint2, float t)
{
// Catmull-Rom splines are Hermite curves with special tangent values.
// Hermite curve formula:
// (2t^3 - 3t^2 + 1) * p0 + (t^3 - 2t^2 + t) * m0 + (-2t^3 + 3t^2) * p1 + (t^3 - t^2) * m1
// For points p0 and p1 passing through points m0 and m1 interpolated over t = [0, 1]
// Tangent M[k] = (P[k+1] - P[k-1]) / 2
// With [] indicating subscript
Vector3 position = (2.0f * t * t * t - 3.0f * t * t + 1.0f) * start
+ (t * t * t - 2.0f * t * t + t