以前我写过一篇文章,不规则图形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了