unity实现任意多边形三角剖分
2017-08-12 13:39
1551 查看
项目有一个对任意形状截面生成3维物体的需求,需要用到三角化的算法。如果截面是凸多边形,那么非常简单,以任意一点为起点按顺序切分即可:
而对于凹多边形这种方法就无能为力了:
网上可以找到很多论文,我参考了其中一篇(主要是作者写的接地气,简单易懂),实现了需求。
论文地址:三维模型重建中的凹多边形三角剖分
c#代码:
/// <summary> /// 局限性三角剖分 /// </summary> /// <returns></returns> public static int[] LimitedTriangleIndex(Vector3[] verts) { int len = verts.Length; //若是闭环去除最后一点 if (len > 1 && MathUtil.IsEqual(verts[0], verts[len - 1])) { len--; } int triangleNum = len - 2; int[] triangles = new int[triangleNum * 3]; for (int i = 0; i < triangleNum; i++) { int start = i * 3; triangles[start] = 0; triangles[start + 1] = i + 1; triangles[start + 2] = i + 2; } return triangles; }
而对于凹多边形这种方法就无能为力了:
网上可以找到很多论文,我参考了其中一篇(主要是作者写的接地气,简单易懂),实现了需求。
论文地址:三维模型重建中的凹多边形三角剖分
c#代码:
/// <summary> /// 三角剖分 /// 1.寻找一个可划分顶点 /// 2.分割出新的多边形和三角形 /// 3.新多边形若为凸多边形,结束;否则继续剖分 /// /// 寻找可划分顶点 /// 1.顶点是否为凸顶点:顶点在剩余顶点组成的图形外 /// 2.新的多边形没有顶点在分割的三角形内 /// </summary> private static List<int> WidelyTriangleIndex(List<Vector2> verts, List<int> indexes) { int len = verts.Count; if (len <= 3) return ConvexTriangleIndex(indexes); int searchIndex = 0; List<int> covexIndex = new List<int>(); bool isCovexPolygon = true; for (searchIndex = 0; searchIndex < len; searchIndex++) { List<Vector2> polygon = new List<Vector2>(verts.ToArray()); polygon.RemoveAt(searchIndex); if (IsPointInsidePolygon(verts[searchIndex], polygon)) { isCovexPolygon = false; break; } else { covexIndex.Add(searchIndex); } } if (isCovexPolygon) return ConvexTriangleIndex(indexes); int canFragementIndex = -1; for (int i = 0; i < len; i++) { if (i > searchIndex) { List<Vector2> polygon = new List<Vector2>(verts.ToArray()); polygon.RemoveAt(i); if (!IsPointInsidePolygon(verts[i], polygon) && IsFragementIndex(i, verts)) { canFragementIndex = i; break; } } else { if (covexIndex.IndexOf(i) != -1 && IsFragementIndex(i, verts)) { canFragementIndex = i; break; } } } if (canFragementIndex < 0) { Debug.LogError("数据有误找不到可划分顶点"); return new List<int>(); } List<int> tTriangles = new List<int>(); int next = (canFragementIndex == len - 1) ? 0 : canFragementIndex + 1; int prev = (canFragementIndex == 0) ? len - 1 : canFragementIndex - 1; tTriangles.Add(indexes[prev]); tTriangles.Add(indexes[canFragementIndex]); tTriangles.Add(indexes[next]); verts.RemoveAt(canFragementIndex); indexes.RemoveAt(canFragementIndex); List<int> leaveTriangles = WidelyTriangleIndex(verts, indexes); return tTriangles.Concat(leaveTriangles).ToList(); } /// <summary> /// 是否是可划分顶点:新的多边形没有顶点在分割的三角形内 /// </summary> private static bool IsFragementIndex(int index, List<Vector2> verts) { int len = verts.Count; List<Vector2> triangleVert = new List<Vector2>(); int next = (index == len - 1) ? 0 : index + 1; int prev = (index == 0) ? len - 1 : index - 1; triangleVert.Add(verts[prev]); triangleVert.Add(verts[index]); triangleVert.Add(verts[next]); for (int i = 0; i < len; i++) { if (i != index && i != prev && i != next) { if (IsPointInsidePolygon(verts[i], triangleVert)) { return false; } } } return true; } /// <summary> /// 点与多边形的位置关系 /// </summary> /// <param name="point"></param> /// <param name="polygonVerts">多边形顶点按顺序排列</param> /// <returns></returns> public static bool IsPointInsidePolygon(Vector2 point, Vector2[] polygonVerts) { int len = polygonVerts.Length; Ray2D ray = new Ray2D(point, new Vector2(0, 1)); //测试射线 int interNum = 0; for (int i = 1; i < len; i++) { if (IsDetectIntersect(ray, polygonVerts[i - 1], polygonVerts[i])) { interNum++; } } if (!MathUtil.IsEqual(polygonVerts[0], polygonVerts[len - 1])) { if (IsDetectIntersect(ray, polygonVerts[len - 1], polygonVerts[0])) { interNum++; } } int remainder = interNum % 2; return remainder == 1; }
相关文章推荐
- 任意多边形裁剪圆的实现思路
- android实现使用绘图作出一种裁剪任意多边形快速算法 (转自 cafelette)
- 【狼】unity 鼠标拖拽物体实现任意角度自旋转
- 任意不自相交的凹多边形实现三角剖分
- Unity Flat Shading实现低多边形(low-poly)效果
- 计算几何---多边形三角剖分算法研究与实现
- [资源分享][UGUI][Unity好文章]如何用unity实现像DOTA2那样的多边形数据雷达图
- C# 实现 任意多边形切割折线算法
- 任意多边形切割/裁剪(附C#代码实现)
- unity 鼠标拖拽物体实现任意角度自旋转
- unity数据持久化-如何保存多个帐号密码并切换任意用户实现登陆
- Unity动态构建Mesh来绘制任意多边形
- google map上实现通过点击地图任意点进行标记并形成多边形
- hdoj2036 c语言实现(任意多边形的面积
- 使用VC6.0实现窗口的任意分割
- [Unity&C#]输入任意按键返回对应的字符串
- Unity- 实现 Building Plugins for iOS(含Demo)
- iOS-runtime-根据类名推送到任意控制器,且实现属性传值
- C++实现任意表达时候求值(栈)
- Unity中让一个物体一直对着另一个物体(任意轴向)