我曾经写过一篇文章,不规则图形uv地图。(http://blog.csdn.net/itolfn/article/details/17240131)我用三角算法。但是,这种方法已经不完全,有一个指明:最优:假设任意两个凸四边形对角线三角附近形成假字。两个三角形六个内角中最小的角度不会变大。就是取四变形的最大化三角形内角去连接对角线,分组两个三角形。可是有时候不是自己想要的那一个图形,如图:
三角剖分算法会算出ABC和ACD这两个三角形,可是我们须要ABD和BCD。这时候就不能用了。我研究三角剖分不深,按他的定律去算出就是取的第二个图形,有哪位大侠知道请告诉小弟,后来我就摒弃了这个算法,重写了一套,使用面积划分的算法,这样攻克了我全部的问题,不论什么不规则多边形都会使uv贴的正好
using System.Collections; using System.Collections.Generic; public class TriangleSubdivision :MonoBehaviour{ ///三角划分原理 ///每划分一个三角形后。推断切割成新三角形与切割后剩余多边形的面积和是否等于切割前多边形的面积。假设等于,则表示切割有效,继续划分。否则跳过一个顶点继续推断下一个三角形,循环到剩余多边形是三角形为止。 public static int[] TriangulatePolygon (Vector2[] XZofVertices , bool is3D) { int VertexCount = XZofVertices.Length; List<TriangleObj> TriangleList = new List<TriangleObj>(); List<Vector2> VerticesList = new List<Vector2>(); for(int i=0;i<VertexCount;i++) { VerticesList.Add(new Vector2(XZofVertices[i].x,XZofVertices[i].y)); } if(VertexCount<3) return null; int testindex=0; while (VerticesList.Count>=3&&testindex<100) { for (int i = 0; i < VerticesList.Count; i++) { testindex++; //假设数组仅仅剩余3个节点。 if(VerticesList.Count==3){ TriangleObj nobj = new TriangleObj(VerticesList[0], VerticesList[1], VerticesList[2]); TriangleList.Add(nobj); VerticesList.RemoveAt(1); break; } //全部角点暂存数组 List<Vector2> surplusVerticesList = new List<Vector2>(); surplusVerticesList.AddRange(VerticesList); if(i+2<VerticesList.Count){ //获取3个点组成一个3角形 Vector2[] trianglePoint = new Vector2[3]; trianglePoint[0] = VerticesList[i]; trianglePoint[1] = VerticesList[i+1]; trianglePoint[2] = VerticesList[i+2]; //移除三角形用到的中间点,剩余的多边形点集合. surplusVerticesList.RemoveAt(i+1); Vector2[] surplusPoints = new Vector2[surplusVerticesList.Count]; for(int m=0;m<surplusVerticesList.Count;m++){ surplusPoints[m]=surplusVerticesList[m]; } //移除前多边形点集合 Vector2[] allPoints = new Vector2[VerticesList.Count]; for (int n = 0; n < VerticesList.Count; n++) { allPoints[n]=VerticesList[n]; } bool isCrose = false;//推断该多边形的两条边是否相交 for(int ii_1 = 0;ii_1<surplusPoints.Length;ii_1++) { for(int ii_2 = 0;ii_2<surplusPoints.Length;ii_2++) { if(ii_1 < surplusPoints.Length - 1 && ii_2 < surplusPoints.Length - 1) { if((surplusPoints[ii_1].x == surplusPoints[ii_2].x && surplusPoints[ii_1].y == surplusPoints[ii_2].y) ||(surplusPoints[ii_1+1].x == surplusPoints[ii_2].x && surplusPoints[ii_1+1].y == surplusPoints[ii_2].y) ||(surplusPoints[ii_1].x == surplusPoints[ii_2+1].x && surplusPoints[ii_1].y == surplusPoints[ii_2+1].y) ||(surplusPoints[ii_1+1].x == surplusPoints[ii_2+1].x && surplusPoints[ii_1+1].y == surplusPoints[ii_2+1].y)) { continue; } if(GameObject.Find("Initial").GetComponent<ShareMethods>().CheckCrose(surplusPoints[ii_1],surplusPoints[ii_1+1],surplusPoints[ii_2],surplusPoints[ii_2+1]) &&GameObject.Find("Initial").GetComponent<ShareMethods>().CheckCrose(surplusPoints[ii_2],surplusPoints[ii_2+1],surplusPoints[ii_1],surplusPoints[ii_1+1])) { isCrose = true; break; } } } if(isCrose) { break; } } //推断切割成新三角形与切割后剩余多边形的面积和是否等于切割前多边形的面积? if(Mathf.Abs(trPolygonArea(trianglePoint,is3D)+trPolygonArea(surplusPoints,is3D)-trPolygonArea(allPoints,is3D))<=0.001f&&!isCrose){ //则表示切割有效,继续划分 TriangleObj tobj = new TriangleObj(VerticesList[i], VerticesList[i+1], VerticesList[i+2]); TriangleList.Add(tobj); VerticesList.RemoveAt(i+1); i--; break; }else{ //否则跳过一个顶点继续推断下一个三角形.把第一个点放到数组末尾. Vector2 zeropoint = new Vector2(VerticesList[i].x,VerticesList[i].y); VerticesList.RemoveAt(i); VerticesList.Add(zeropoint); break; } } } } int[] Triangles = new int[3 * TriangleList.Count]; for (int ii1 = 0; ii1 < TriangleList.Count; ii1++) { TriangleObj tempobj = TriangleList[ii1]; Triangles[3 * ii1 + 1] = indexofobjfromList(tempobj.p2,XZofVertices); if(is3D) { Triangles[3 * ii1+2] = indexofobjfromList(tempobj.p1,XZofVertices); Triangles[3 * ii1] = indexofobjfromList(tempobj.p3,XZofVertices); } else { Triangles[3 * ii1] = indexofobjfromList(tempobj.p1,XZofVertices); Triangles[3 * ii1+2] = indexofobjfromList(tempobj.p3,XZofVertices); } } return Triangles; } /// //依据点获取多边形面积 static float trPolygonArea(Vector2[] points,bool is3D) { float area = 0; if(is3D) { area = GameObject.Find("Initial").GetComponent<ShareMethods>().PolygonArea(null,points);//面积公式算法 } else { area = GameObject.Find("Initial").GetComponent<ShareMethods>().PolygonArea(null,points)/1000000; } return area; } static int indexofobjfromList(Vector2 point,Vector2[] points) { int index = 0; for(int i=0;i<points.Length;i++){ Vector2 temp=points[i]; if(Mathf.Abs(point.x-temp.x)<0.001f&&Mathf.Abs(point.y-temp.y)<0.001f){ index=i; break; } } return index; } } struct TriangleObj { public Vector2 p1; public Vector2 p2; public Vector2 p3; public TriangleObj(Vector2 point1, Vector2 point2, Vector2 point3) { p1 = point1; p2 = point2; p3 = point3; } }
这种方法没什么修改,仅仅是算法我改了一下。还是这个类。还是传你全部的点。会返回你的Mesh.triangles,这样就就完美的使自己的mesh依据点贴上自己想要的图形状uv该
版权声明:本文博客原创文章,博客,未经同意,不得转载。
时间: 2024-10-07 23:02:22