算法主要的方法为 public static List<List<Vector3>> GetEndCuttingPolygonVerticles(List<Vector3> originPoints, Vector3 startPos, Vector3 endPos),
list数组存的是网格的顶点,第二个参数和第三个参数表示切割线段的起始节点和线段的末节点,首先我们会判断线段两头的点是否在多边形内,下面我就不讲原理了,直接给代码吧, 有兴趣的同学可以上wiki上搜搜相关的代码。
private static bool PointInPolygon(Vector3 pointToCheck, List<Vector3> polygon)
{
var flag = false;
if (polygon.Count >= 3)
{
var lastPoint = new Vector3(polygon[polygon.Count - 1].x, polygon[polygon.Count - 1].y);
for (var i = 0; i < polygon.Count; i++)
{
Vector3 minPoint;
Vector3 maxPoint;
var curPoint = new Vector3(polygon[i].x, polygon[i].y);
if (curPoint.x > lastPoint.x)
{
minPoint = lastPoint;
maxPoint = curPoint;
}
else
{
minPoint = curPoint;
maxPoint = lastPoint;
}
var p1 = pointToCheck - minPoint;
var p2 = maxPoint - minPoint;
bool b = (curPoint.x < pointToCheck.x) == (pointToCheck.x <= lastPoint.x);
if (b && (p1.x * p2.y - p1.y * p2.x > 0))
{
flag = !flag;
}
lastPoint = curPoint;
}
}
return flag;
}
如果都不在多边形内话,表示可以切割,反之则表示无法切割。如果可以切割的话,先取出线段与多边形的交点数组。方法如下:
public static List<VertexPoint> GetCuttingPoints(List<Vector3> originPoints, Vector3 startPos, Vector3 endPos)
{
List<VertexPoint> tempVertexPoints = new List<VertexPoint>();
var count = originPoints.Count;
for (int i = 0; i < count; i++)
{
var list = GetLinesIntersection(originPoints[i], originPoints[((i + 1) % count)], startPos, endPos);
if (list.Count == 1)
{
if (list.Count == 1)
{
var pre = 0;
var next = 0;
if (list[0].VeIndex == 0)
{
pre = i;
next = i;
}
else if (list[0].VeIndex == 1)
{
pre = (i + 1) % count;
next = (i + 1) % count;
}
else
{
pre = i;
next = (i + 1) % count;
}
tempVertexPoints.Add(new VertexPoint(list[0].Pos, pre, next));
}
else if (list.Count == 2)
{
tempVertexPoints.Add(new VertexPoint(list[0].Pos, i, i));
tempVertexPoints.Add(new VertexPoint(list[1].Pos, (i + 1) % count, (i + 1) % count));
}
}
}
tempVertexPoints = GetDistinctPoints(tempVertexPoints);
return tempVertexPoints;
}
最后主要方法也就是对外的方法是:
public static List<List<Vector3>> GetEndCuttingPolygonVerticles(List<Vector3> originPoints, Vector3 startPos, Vector3 endPos)
{
List<List<Vector3>> endValues = new List<List<Vector3>>();
bool[] visited = new bool[originPoints.Count];
originPoints = ReversePoints(originPoints);//将所有的点变成顺时针。
List<VertexPoint> tempPoints = GetCuttingPoints(originPoints, startPos, endPos);//得到所有的交点。
tempPoints = tempPoints.OrderBy(t => t.KeyVector3.x).ToList();//讲所有的交点由x排序
if (tempPoints.Count == 1)
return null;
for (int i = 0; i < tempPoints.Count - 1; i++)
{
int cur = i, next = i + 1;
List<Vector3> tempList = new List<Vector3>();
tempList = GetPointByTwoIntersec(cur, next, originPoints, tempPoints);//得到2个交点中间包含所有的节点。
if (tempList.Count >= 3)
{
if (Triangulate.Area(tempList) < 0)
{
endValues.Add(tempList);
for (int j = 0; j < tempList.Count; j++)
{
int index = GetVerticleIndex(tempList[j], originPoints);
if (index != 100)
visited[index] = true;
}
}
}
}
var lastTri = new List<Vector3>();
for (int i = 0; i < originPoints.Count; i++)
{
if (!visited[i])
{
lastTri.Add(originPoints[i]);
}
for (int j = 0; j < tempPoints.Count; j++)
{
var cur = tempPoints[j].PreIndex;
if (cur == i)
{
lastTri.Add(tempPoints[j].KeyVector3);
}
}
}
endValues.Add(lastTri);
return endValues;
}
这里贴出所有工具类,个人觉得对于网格的操作是非常重要的,同时也较基本的游戏-三消,塔防,卡牌类游戏制作较为麻烦,同时任何一个游戏引擎都会用到,这些都是关于渲染的问题,可能比一些游戏逻辑理解起来费劲,但是个人还是建议大家可以好好学学,这样才可能走的更远,接触到低层渲染问题。最后贴出网格生成和网格切割算法吧
还是欢迎大家有什么问题加qq讨论,http://pan.baidu.com/s/1mhBVkm8,下节可能会讲到无限动态2D曲面地图的生成。