通常项目中为了游戏运行的顺畅会对模型进行相应的减面操作,但也有特例。这次就研究下给模型加面,尤其是给模型水平方向加面,类似于水平切割模型。 一般的加面算法,是在三角形内部取各条线的中点连接成新三角进行加面。
如下图:
项目中实现如下:
但项目中需要始终水平切割三角面的线,此种加面方法不太可行,只能另找方法。
主要思路是考虑切割线与三角形的位置关系,先获取某一面的所有三角形,然后通过切割线进行位置比较最后再进行切割三角形。
首先几种情况下无需进行分割:
需要进行切割的情况如下:
逐个分析下,第一种是切割线过三角形的某一点并且和另两点所成线段相交。 第二种是切割线不经过任一点且与三角形两条边相交。
第一种:原本的三角形序列为 abc,经过切割线切割后得到bda 和 dca两个三角形。
第二种:原本的三角形序列为 abc,经过切割线切割后得到bda、dea和dce三个三角形。
处理数据时加入新的三角形序列,同时删除掉原有的三角形即可。下面以一个面为例实验:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshSubdivide : MonoBehaviour
{
private List<Vector3> vertices;
private List<Vector3> normals;
private List<Color> colors;
private List<Vector2> uv;
private List<Vector2> uv1;
private List<Vector2> uv2;
private List<int> trangles;
private MeshFilter meshfilter;
private List<Vector3> inVertices = new List<Vector3>();
/// <summary>
/// 所有三角面的索引列表
/// </summary>
private List<Vector3> trianglesIndexList = new List<Vector3>();
private List<Vector3> inIndexList = new List<Vector3>();
void Start()
{
meshfilter = GetComponent<MeshFilter>();
StartSubdivide(meshfilter.mesh);
}
private void InitArrays(Mesh mesh)
{
vertices = new List<Vector3>(mesh.vertices);
normals = new List<Vector3>(mesh.normals);
colors = new List<Color>(mesh.colors);
uv = new List<Vector2>(mesh.uv);
uv1 = new List<Vector2>(mesh.uv2);
uv2 = new List<Vector2>(mesh.uv2);
trangles = new List<int>();
}
private void CleanUp()
{
vertices = null;
normals = null;
colors = null;
uv = null;
uv1 = null;
uv2 = null;
}
#region Subdivide4 (2x2)
private int GetNewVertex4(int i1, int i2, float rate)
{
int newIndex = vertices.Count;
//vertices.Add((vertices[i1] + vertices[i2]) * rate);
if (normals.Count > 0)
normals.Add((normals[i1] + normals[i2]).normalized);
if (colors.Count > 0)
colors.Add((colors[i1] + colors[i2]) * rate);
if (uv.Count > 0)
uv.Add((uv[i1] + uv[i2]) * rate);
if (uv1.Count > 0)
uv1.Add((uv1[i1] + uv1[i2]) * rate);
if (uv2.Count > 0)
uv2.Add((uv2[i1] + uv2[i2]) * rate);
return newIndex;
}
/// <summary>
/// 横向加面算法
/// </summary>
/// <param name="mesh"></param>
public void StartSubdivide(Mesh mesh)
{
//初始化Mesh信息
InitArrays(mesh);
//获得最外层顶点序列
GetInVertices();
//获得初始三角形序列
GetInitTriangles(mesh);
//开始切割增加三角形
StartSliceAddTriangles();
mesh.vertices = vertices.ToArray();
if (normals.Count > 0)
mesh.normals = normals.ToArray();
if (colors.Count > 0)
mesh.colors = colors.ToArray();
if (uv.Count