743 lines
29 KiB
C#
743 lines
29 KiB
C#
using UnityEngine;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using System;
|
||
|
||
namespace Dreamteck
|
||
{
|
||
public class MeshUtility
|
||
{
|
||
private static Vector3[] tan1 = new Vector3[0];
|
||
private static Vector3[] tan2 = new Vector3[0];
|
||
|
||
public static int[] GeneratePlaneTriangles(int x, int z, bool flip, int startTriangleIndex = 0, int startVertex = 0)
|
||
{
|
||
int nbFaces = x * (z - 1);
|
||
int[] triangles = new int[nbFaces * 6];
|
||
GeneratePlaneTriangles(ref triangles, x, z, flip);
|
||
return triangles;
|
||
}
|
||
|
||
public static int[] GeneratePlaneTriangles(ref int[] triangles, int x, int z, bool flip, int startTriangleIndex = 0, int startVertex = 0, bool reallocateArray = false)
|
||
{
|
||
int nbFaces = x * (z - 1);
|
||
if (reallocateArray && triangles.Length != nbFaces * 6)
|
||
{
|
||
if (startTriangleIndex > 0)
|
||
{
|
||
int[] newTris = new int[startTriangleIndex + nbFaces * 6];
|
||
for (int i = 0; i < startTriangleIndex; i++) newTris[i] = triangles[i];
|
||
triangles = newTris;
|
||
}
|
||
else triangles = new int[nbFaces * 6];
|
||
}
|
||
int g = x + 1;
|
||
int t = startTriangleIndex;
|
||
|
||
// for (int face = 0; face < nbFaces + z - 2; face++)
|
||
// {
|
||
// if ((float)(face + 1) % (float)g == 0f && face != 0) face++;
|
||
// if (flip)
|
||
// {
|
||
// triangles[t++] = face + x + 1 + startVertex;
|
||
// triangles[t++] = face + 1 + startVertex;
|
||
// triangles[t++] = face + startVertex;
|
||
|
||
// triangles[t++] = face + x + 1 + startVertex;
|
||
// triangles[t++] = face + x + 2 + startVertex;
|
||
// triangles[t++] = face + 1 + startVertex;
|
||
// }
|
||
// else
|
||
// {
|
||
// triangles[t++] = face + startVertex;
|
||
// triangles[t++] = face + 1 + startVertex;
|
||
// triangles[t++] = face + x + 1 + startVertex;
|
||
|
||
// triangles[t++] = face + 1 + startVertex;
|
||
// triangles[t++] = face + x + 2 + startVertex;
|
||
// triangles[t++] = face + x + 1 + startVertex;
|
||
// }
|
||
// }
|
||
|
||
int index = 0;
|
||
for (int row = 0; row < z - 1; row++)
|
||
{
|
||
for (int col = 0; col < x; col++)
|
||
{
|
||
int i = row * (x + 1) + col;
|
||
|
||
if (flip)
|
||
{
|
||
triangles[index++] = i + x + 1;
|
||
triangles[index++] = i + 1;
|
||
triangles[index++] = i;
|
||
|
||
triangles[index++] = i + x + 1;
|
||
triangles[index++] = i + x + 2;
|
||
triangles[index++] = i + 1;
|
||
}
|
||
else
|
||
{
|
||
triangles[index++] = i + startVertex;
|
||
triangles[index++] = i + 1 + startVertex;
|
||
triangles[index++] = i + x + 1 + startVertex;
|
||
|
||
triangles[index++] = i + 1 + startVertex;
|
||
triangles[index++] = i + x + 2 + startVertex;
|
||
triangles[index++] = i + x + 1 + startVertex;
|
||
}
|
||
}
|
||
}
|
||
return triangles;
|
||
}
|
||
|
||
public static void CalculateTangents(TS_Mesh mesh)
|
||
{
|
||
int vertexCount = mesh.vertexCount;
|
||
int triangleCount = mesh.triangles.Length / 3;
|
||
|
||
// 优化1:数组重用与按需分配
|
||
if (tan1.Length < vertexCount)
|
||
{
|
||
tan1 = new Vector3[vertexCount];
|
||
tan2 = new Vector3[vertexCount];
|
||
}
|
||
else
|
||
{
|
||
// 重用数组但需要清零
|
||
Array.Clear(tan1, 0, vertexCount);
|
||
Array.Clear(tan2, 0, vertexCount);
|
||
}
|
||
|
||
// 优化2:避免重复访问属性
|
||
Vector3[] vertices = mesh.vertices;
|
||
Vector2[] uvs = mesh.uv;
|
||
Vector3[] normals = mesh.normals;
|
||
int[] triangles = mesh.triangles;
|
||
|
||
// 优化3:预先检查数组长度
|
||
if (uvs.Length < vertexCount || normals.Length < vertexCount)
|
||
{
|
||
Debug.LogError("UV or Normal array size mismatch");
|
||
return;
|
||
}
|
||
|
||
// 优化4:缓存变量减少重复计算
|
||
Vector3 edge1 = Vector3.zero;
|
||
Vector3 edge2 = Vector3.zero;
|
||
Vector2 uvEdge1 = Vector2.zero;
|
||
Vector2 uvEdge2 = Vector2.zero;
|
||
|
||
// 优化5:循环展开减少分支预测失败
|
||
for (int i = 0; i < triangleCount; i++)
|
||
{
|
||
int triIndex = i * 3;
|
||
int i1 = triangles[triIndex];
|
||
int i2 = triangles[triIndex + 1];
|
||
int i3 = triangles[triIndex + 2];
|
||
|
||
// 计算边向量
|
||
edge1.x = vertices[i2].x - vertices[i1].x;
|
||
edge1.y = vertices[i2].y - vertices[i1].y;
|
||
edge1.z = vertices[i2].z - vertices[i1].z;
|
||
|
||
edge2.x = vertices[i3].x - vertices[i1].x;
|
||
edge2.y = vertices[i3].y - vertices[i1].y;
|
||
edge2.z = vertices[i3].z - vertices[i1].z;
|
||
|
||
// 计算UV差
|
||
uvEdge1.x = uvs[i2].x - uvs[i1].x;
|
||
uvEdge1.y = uvs[i2].y - uvs[i1].y;
|
||
|
||
uvEdge2.x = uvs[i3].x - uvs[i1].x;
|
||
uvEdge2.y = uvs[i3].y - uvs[i1].y;
|
||
|
||
// 优化6:避免除零检查的分支预测
|
||
float div = uvEdge1.x * uvEdge2.y - uvEdge2.x * uvEdge1.y;
|
||
float r = Mathf.Abs(div) < Mathf.Epsilon ? 0f : 1f / div;
|
||
|
||
// 计算切线向量
|
||
Vector3 sdir = new Vector3(
|
||
(uvEdge2.y * edge1.x - uvEdge1.y * edge2.x) * r,
|
||
(uvEdge2.y * edge1.y - uvEdge1.y * edge2.y) * r,
|
||
(uvEdge2.y * edge1.z - uvEdge1.y * edge2.z) * r
|
||
);
|
||
|
||
Vector3 tdir = new Vector3(
|
||
(uvEdge1.x * edge2.x - uvEdge2.x * edge1.x) * r,
|
||
(uvEdge1.x * edge2.y - uvEdge2.x * edge1.y) * r,
|
||
(uvEdge1.x * edge2.z - uvEdge2.x * edge1.z) * r
|
||
);
|
||
|
||
// 累加到顶点
|
||
tan1[i1] += sdir;
|
||
tan1[i2] += sdir;
|
||
tan1[i3] += sdir;
|
||
|
||
tan2[i1] += tdir;
|
||
tan2[i2] += tdir;
|
||
tan2[i3] += tdir;
|
||
}
|
||
|
||
// 优化7:确保切线数组已分配
|
||
if (mesh.tangents == null || mesh.tangents.Length != vertexCount)
|
||
{
|
||
mesh.tangents = new Vector4[vertexCount];
|
||
}
|
||
|
||
// 优化8:手动Gram-Schmidt正交化
|
||
for (int i = 0; i < vertexCount; i++)
|
||
{
|
||
Vector3 n = normals[i];
|
||
Vector3 t = tan1[i];
|
||
|
||
// 手动正交化 (比Vector3.OrthoNormalize更高效)
|
||
t = (t - n * Vector3.Dot(n, t)).normalized;
|
||
|
||
// 计算副法线方向
|
||
Vector3 b = Vector3.Cross(n, t);
|
||
float w = (Vector3.Dot(b, tan2[i]) < 0.0f) ? -1.0f : 1.0f;
|
||
|
||
mesh.tangents[i] = new Vector4(t.x, t.y, t.z, w);
|
||
}
|
||
}
|
||
public static void MakeDoublesided(Mesh input)
|
||
{
|
||
Vector3[] vertices = input.vertices;
|
||
Vector3[] normals = input.normals;
|
||
Vector2[] uvs = input.uv;
|
||
Color[] colors = input.colors;
|
||
int[] triangles = input.triangles;
|
||
List<int[]> submeshes = new List<int[]>();
|
||
for (int i = 0; i < input.subMeshCount; i++) submeshes.Add(input.GetTriangles(i));
|
||
|
||
Vector3[] newVertices = new Vector3[vertices.Length * 2];
|
||
Vector3[] newNormals = new Vector3[normals.Length * 2];
|
||
Vector2[] newUvs = new Vector2[uvs.Length * 2];
|
||
Color[] newColors = new Color[colors.Length * 2];
|
||
int[] newTris = new int[triangles.Length * 2];
|
||
List<int[]> newSubmeshes = new List<int[]>();
|
||
for (int i = 0; i < submeshes.Count; i++)
|
||
{
|
||
newSubmeshes.Add(new int[submeshes[i].Length * 2]);
|
||
submeshes[i].CopyTo(newSubmeshes[i], 0);
|
||
}
|
||
|
||
for (int i = 0; i < vertices.Length; i++)
|
||
{
|
||
newVertices[i] = vertices[i];
|
||
newNormals[i] = normals[i];
|
||
newUvs[i] = uvs[i];
|
||
if (colors.Length > i) newColors[i] = colors[i];
|
||
|
||
newVertices[i + vertices.Length] = vertices[i];
|
||
newNormals[i + vertices.Length] = -normals[i];
|
||
newUvs[i + vertices.Length] = uvs[i];
|
||
if (colors.Length > i) newColors[i + vertices.Length] = colors[i];
|
||
}
|
||
|
||
for (int i = 0; i < triangles.Length; i += 3)
|
||
{
|
||
int index1 = triangles[i];
|
||
int index2 = triangles[i + 1];
|
||
int index3 = triangles[i + 2];
|
||
newTris[i] = index1;
|
||
newTris[i + 1] = index2;
|
||
newTris[i + 2] = index3;
|
||
|
||
newTris[i + triangles.Length] = index3 + vertices.Length;
|
||
newTris[i + triangles.Length + 1] = index2 + vertices.Length;
|
||
newTris[i + triangles.Length + 2] = index1 + vertices.Length;
|
||
}
|
||
|
||
for (int i = 0; i < submeshes.Count; i++)
|
||
{
|
||
for (int n = 0; n < submeshes[i].Length; n += 3)
|
||
{
|
||
int index1 = submeshes[i][n];
|
||
int index2 = submeshes[i][n + 1];
|
||
int index3 = submeshes[i][n + 2];
|
||
newSubmeshes[i][n] = index1;
|
||
newSubmeshes[i][n + 1] = index2;
|
||
newSubmeshes[i][n + 2] = index3;
|
||
|
||
newSubmeshes[i][n + submeshes[i].Length] = index3 + vertices.Length;
|
||
newSubmeshes[i][n + submeshes[i].Length + 1] = index2 + vertices.Length;
|
||
newSubmeshes[i][n + submeshes[i].Length + 2] = index1 + vertices.Length;
|
||
}
|
||
}
|
||
|
||
input.vertices = newVertices;
|
||
input.normals = newNormals;
|
||
input.uv = newUvs;
|
||
input.colors = newColors;
|
||
input.triangles = newTris;
|
||
for (int i = 0; i < newSubmeshes.Count; i++) input.SetTriangles(newSubmeshes[i], i);
|
||
}
|
||
|
||
public static void MakeDoublesided(TS_Mesh input)
|
||
{
|
||
Vector3[] vertices = input.vertices;
|
||
Vector3[] normals = input.normals;
|
||
Vector2[] uvs = input.uv;
|
||
Color[] colors = input.colors;
|
||
int[] triangles = input.triangles;
|
||
List<int[]> submeshes = input.subMeshes;
|
||
|
||
Vector3[] newVertices = new Vector3[vertices.Length * 2];
|
||
Vector3[] newNormals = new Vector3[normals.Length * 2];
|
||
Vector2[] newUvs = new Vector2[uvs.Length * 2];
|
||
Color[] newColors = new Color[colors.Length * 2];
|
||
int[] newTris = new int[triangles.Length * 2];
|
||
List<int[]> newSubmeshes = new List<int[]>();
|
||
for (int i = 0; i < submeshes.Count; i++)
|
||
{
|
||
newSubmeshes.Add(new int[submeshes[i].Length * 2]);
|
||
submeshes[i].CopyTo(newSubmeshes[i], 0);
|
||
}
|
||
|
||
for (int i = 0; i < vertices.Length; i++)
|
||
{
|
||
newVertices[i] = vertices[i];
|
||
newNormals[i] = normals[i];
|
||
newUvs[i] = uvs[i];
|
||
if (colors.Length > i) newColors[i] = colors[i];
|
||
|
||
newVertices[i + vertices.Length] = vertices[i];
|
||
newNormals[i + vertices.Length] = -normals[i];
|
||
newUvs[i + vertices.Length] = uvs[i];
|
||
if (colors.Length > i) newColors[i + vertices.Length] = colors[i];
|
||
}
|
||
|
||
for (int i = 0; i < triangles.Length; i += 3)
|
||
{
|
||
int index1 = triangles[i];
|
||
int index2 = triangles[i + 1];
|
||
int index3 = triangles[i + 2];
|
||
newTris[i] = index1;
|
||
newTris[i + 1] = index2;
|
||
newTris[i + 2] = index3;
|
||
|
||
newTris[i + triangles.Length] = index3 + vertices.Length;
|
||
newTris[i + triangles.Length + 1] = index2 + vertices.Length;
|
||
newTris[i + triangles.Length + 2] = index1 + vertices.Length;
|
||
}
|
||
|
||
for (int i = 0; i < submeshes.Count; i++)
|
||
{
|
||
for (int n = 0; n < submeshes[i].Length; n += 3)
|
||
{
|
||
int index1 = submeshes[i][n];
|
||
int index2 = submeshes[i][n + 1];
|
||
int index3 = submeshes[i][n + 2];
|
||
newSubmeshes[i][n] = index1;
|
||
newSubmeshes[i][n + 1] = index2;
|
||
newSubmeshes[i][n + 2] = index3;
|
||
|
||
newSubmeshes[i][n + submeshes[i].Length] = index3 + vertices.Length;
|
||
newSubmeshes[i][n + submeshes[i].Length + 1] = index2 + vertices.Length;
|
||
newSubmeshes[i][n + submeshes[i].Length + 2] = index1 + vertices.Length;
|
||
}
|
||
}
|
||
|
||
input.vertices = newVertices;
|
||
input.normals = newNormals;
|
||
input.uv = newUvs;
|
||
input.colors = newColors;
|
||
input.triangles = newTris;
|
||
input.subMeshes = newSubmeshes;
|
||
}
|
||
|
||
public static void MakeDoublesidedHalf(TS_Mesh input)
|
||
{
|
||
int vertexHalf = input.vertices.Length / 2;
|
||
int trisHalf = input.triangles.Length / 2;
|
||
for (int i = 0; i < vertexHalf; i++)
|
||
{
|
||
input.vertices[i + vertexHalf] = input.vertices[i];
|
||
if (input.normals.Length > i) input.normals[i + vertexHalf] = -input.normals[i];
|
||
if (input.tangents.Length > i) input.tangents[i + vertexHalf] = input.tangents[i];
|
||
if (input.uv.Length > i) input.uv[i + vertexHalf] = input.uv[i];
|
||
if (input.uv2.Length > i) input.uv2[i + vertexHalf] = input.uv2[i];
|
||
if (input.uv3.Length > i) input.uv3[i + vertexHalf] = input.uv3[i];
|
||
if (input.uv4.Length > i) input.uv4[i + vertexHalf] = input.uv4[i];
|
||
if (input.colors.Length > i) input.colors[i + vertexHalf] = input.colors[i];
|
||
}
|
||
|
||
for (int i = 0; i < trisHalf; i += 3)
|
||
{
|
||
input.triangles[i + trisHalf + 2] = input.triangles[i] + vertexHalf;
|
||
input.triangles[i + trisHalf + 1] = input.triangles[i + 1] + vertexHalf;
|
||
input.triangles[i + trisHalf] = input.triangles[i + 2] + vertexHalf;
|
||
}
|
||
|
||
for (int i = 0; i < input.subMeshes.Count; i++)
|
||
{
|
||
trisHalf = input.subMeshes[i].Length / 2;
|
||
for (int n = 0; n < trisHalf; n += 3)
|
||
{
|
||
input.subMeshes[i][n + trisHalf + 2] = input.subMeshes[i][n] + vertexHalf;
|
||
input.subMeshes[i][n + trisHalf + 1] = input.subMeshes[i][n + 1] + vertexHalf;
|
||
input.subMeshes[i][n + trisHalf] = input.subMeshes[i][n + 2] + vertexHalf;
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void TransformMesh(TS_Mesh input, Matrix4x4 matrix)
|
||
{
|
||
if (input.vertices == null || input.normals == null) return;
|
||
for (int i = 0; i < input.vertices.Length; i++)
|
||
{
|
||
input.vertices[i] = matrix.MultiplyPoint3x4(input.vertices[i]);
|
||
input.normals[i] = matrix.MultiplyVector(input.normals[i]);
|
||
}
|
||
}
|
||
|
||
public static void TransformMesh(Mesh input, Matrix4x4 matrix)
|
||
{
|
||
Vector3[] vertices = input.vertices;
|
||
Vector3[] normals = input.vertices;
|
||
if (input.vertices == null || input.normals == null) return;
|
||
for (int i = 0; i < input.vertices.Length; i++)
|
||
{
|
||
vertices[i] = matrix.MultiplyPoint3x4(vertices[i]);
|
||
normals[i] = matrix.MultiplyVector(normals[i]);
|
||
}
|
||
input.vertices = vertices;
|
||
input.normals = normals;
|
||
}
|
||
|
||
|
||
public static void TransformVertices(Vector3[] vertices, Matrix4x4 matrix)
|
||
{
|
||
for (int i = 0; i < vertices.Length; i++)
|
||
{
|
||
vertices[i] = matrix.MultiplyPoint3x4(vertices[i]);
|
||
}
|
||
}
|
||
|
||
public static void TransformNormals(Vector3[] normals, Matrix4x4 matrix)
|
||
{
|
||
for (int i = 0; i < normals.Length; i++)
|
||
{
|
||
normals[i] = matrix.MultiplyVector(normals[i]);
|
||
}
|
||
}
|
||
|
||
public static string ToOBJString(Mesh mesh, Material[] materials)
|
||
{
|
||
int numVertices = 0;
|
||
if (mesh == null)
|
||
{
|
||
return "####Error####";
|
||
}
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
sb.Append("g " + mesh.name + "\n");
|
||
foreach (Vector3 v in mesh.vertices)
|
||
{
|
||
numVertices++;
|
||
sb.Append(string.Format("v {0} {1} {2}\n", -v.x, v.y, v.z));
|
||
}
|
||
sb.Append("\n");
|
||
foreach (Vector3 n in mesh.normals)
|
||
{
|
||
sb.Append(string.Format("vn {0} {1} {2}\n", -n.x, n.y, n.z));
|
||
}
|
||
sb.Append("\n");
|
||
foreach (Vector3 v in mesh.uv)
|
||
{
|
||
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
|
||
}
|
||
sb.Append("\n");
|
||
foreach (Vector2 v in mesh.uv2)
|
||
{
|
||
sb.Append(string.Format("vt2 {0} {1}\n", v.x, v.y));
|
||
}
|
||
sb.Append("\n");
|
||
foreach (Vector2 v in mesh.uv3)
|
||
{
|
||
sb.Append(string.Format("vt2 {0} {1}\n", v.x, v.y));
|
||
}
|
||
sb.Append("\n");
|
||
foreach (Color c in mesh.colors)
|
||
{
|
||
sb.Append(string.Format("vc {0} {1} {2} {3}\n", c.r, c.g, c.b, c.a));
|
||
}
|
||
for (int material = 0; material < mesh.subMeshCount; material++)
|
||
{
|
||
sb.Append("\n");
|
||
sb.Append("usemtl ").Append(materials[material].name).Append("\n");
|
||
sb.Append("usemap ").Append(materials[material].name).Append("\n");
|
||
|
||
int[] triangles = mesh.GetTriangles(material);
|
||
for (int i = 0; i < triangles.Length; i += 3)
|
||
{
|
||
sb.Append(string.Format("f {2}/{2}/{2} {1}/{1}/{1} {0}/{0}/{0}\n",
|
||
triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
|
||
}
|
||
}
|
||
return sb.ToString().Replace(',', '.');
|
||
}
|
||
|
||
public static Mesh Copy(Mesh input)
|
||
{
|
||
Mesh copy = new Mesh();
|
||
copy.name = input.name;
|
||
copy.vertices = input.vertices;
|
||
copy.normals = input.normals;
|
||
copy.colors = input.colors;
|
||
copy.uv = input.uv;
|
||
copy.uv2 = input.uv2;
|
||
copy.uv3 = input.uv3;
|
||
copy.uv4 = input.uv4;
|
||
copy.tangents = input.tangents;
|
||
copy.boneWeights = input.boneWeights;
|
||
copy.bindposes = input.bindposes;
|
||
copy.triangles = input.triangles;
|
||
copy.subMeshCount = input.subMeshCount;
|
||
for (int i = 0; i < input.subMeshCount; i++)
|
||
{
|
||
copy.SetTriangles(input.GetTriangles(i), i);
|
||
}
|
||
return copy;
|
||
}
|
||
|
||
public static void Triangulate(Vector2[] points, ref int[] output)
|
||
{
|
||
List<int> indices = new List<int>();
|
||
int pointsLength = points.Length;
|
||
if (pointsLength < 3)
|
||
{
|
||
output = new int[0];
|
||
return;
|
||
}
|
||
|
||
int[] V = new int[pointsLength];
|
||
if (Area(points, pointsLength) > 0)
|
||
{
|
||
for (int v = 0; v < pointsLength; v++)
|
||
V[v] = v;
|
||
}
|
||
else
|
||
{
|
||
for (int v = 0; v < pointsLength; v++)
|
||
V[v] = (pointsLength - 1) - v;
|
||
}
|
||
|
||
int nv = pointsLength;
|
||
int count = 2 * nv;
|
||
for (int m = 0, v = nv - 1; nv > 2;)
|
||
{
|
||
if ((count--) <= 0)
|
||
{
|
||
if (output.Length != indices.Count) output = new int[indices.Count];
|
||
indices.CopyTo(output, 0);
|
||
return;
|
||
}
|
||
|
||
int u = v;
|
||
if (nv <= u)
|
||
u = 0;
|
||
v = u + 1;
|
||
if (nv <= v)
|
||
v = 0;
|
||
int w = v + 1;
|
||
if (nv <= w)
|
||
w = 0;
|
||
|
||
if (Snip(points, u, v, w, nv, V))
|
||
{
|
||
int a, b, c, s, t;
|
||
a = V[u];
|
||
b = V[v];
|
||
c = V[w];
|
||
indices.Add(c);
|
||
indices.Add(b);
|
||
indices.Add(a);
|
||
m++;
|
||
for (s = v, t = v + 1; t < nv; s++, t++)
|
||
V[s] = V[t];
|
||
nv--;
|
||
count = 2 * nv;
|
||
}
|
||
}
|
||
|
||
indices.Reverse();
|
||
if (output.Length != indices.Count) output = new int[indices.Count];
|
||
indices.CopyTo(output, 0);
|
||
}
|
||
|
||
public static void FlipTriangles(ref int[] triangles)
|
||
{
|
||
for (int i = 0; i < triangles.Length; i += 3)
|
||
{
|
||
int temp = triangles[i];
|
||
triangles[i] = triangles[i + 2];
|
||
triangles[i + 2] = temp;
|
||
}
|
||
}
|
||
|
||
public static void FlipFaces(TS_Mesh input)
|
||
{
|
||
for (int i = 0; i < input.subMeshes.Count; i++)
|
||
{
|
||
int[] array = input.subMeshes[i];
|
||
FlipTriangles(ref array);
|
||
}
|
||
FlipTriangles(ref input.triangles);
|
||
for (int i = 0; i < input.normals.Length; i++)
|
||
{
|
||
input.normals[i] *= -1f;
|
||
}
|
||
}
|
||
|
||
public static void BreakMesh(Mesh input, bool keepNormals = true)
|
||
{
|
||
Vector3[] newVertices = new Vector3[input.triangles.Length];
|
||
Vector3[] newNormals = new Vector3[newVertices.Length];
|
||
Vector2[] newUVs = new Vector2[newVertices.Length];
|
||
Vector4[] newTangents = new Vector4[newVertices.Length];
|
||
Color[] newColors = new Color[newVertices.Length];
|
||
BoneWeight[] newBoneWeights = new BoneWeight[newVertices.Length];
|
||
|
||
Vector3[] oldVertices = input.vertices;
|
||
Vector2[] oldUvs = input.uv;
|
||
Vector3[] oldNormals = input.normals;
|
||
Vector4[] oldTangents = input.tangents;
|
||
Color[] oldColors = input.colors;
|
||
BoneWeight[] oldBoneWeights = input.boneWeights;
|
||
|
||
if (oldColors.Length != oldVertices.Length)
|
||
{
|
||
oldColors = new Color[oldVertices.Length];
|
||
for (int i = 0; i < oldColors.Length; i++) oldColors[i] = Color.white;
|
||
}
|
||
|
||
List<int[]> submeshList = new List<int[]>();
|
||
int submeshes = input.subMeshCount;
|
||
int vertIndex = 0;
|
||
for (int i = 0; i < submeshes; i++)
|
||
{
|
||
int[] submesh = input.GetTriangles(i);
|
||
for (int n = 0; n < submesh.Length; n += 3)
|
||
{
|
||
newVertices[vertIndex] = oldVertices[submesh[n]];
|
||
newVertices[vertIndex + 1] = oldVertices[submesh[n + 1]];
|
||
newVertices[vertIndex + 2] = oldVertices[submesh[n + 2]];
|
||
|
||
if (oldNormals.Length > submesh[n + 2])
|
||
{
|
||
if (!keepNormals)
|
||
{
|
||
newNormals[vertIndex] = newNormals[vertIndex + 1] = newNormals[vertIndex + 2] = (oldNormals[submesh[n]] + oldNormals[submesh[n + 1]] + oldNormals[submesh[n + 2]]).normalized;
|
||
}
|
||
else
|
||
{
|
||
newNormals[vertIndex] = oldNormals[submesh[n]];
|
||
newNormals[vertIndex + 1] = oldNormals[submesh[n + 1]];
|
||
newNormals[vertIndex + 2] = oldNormals[submesh[n + 2]];
|
||
}
|
||
|
||
}
|
||
|
||
if (oldColors.Length > submesh[n + 2])
|
||
newColors[vertIndex] = newColors[vertIndex + 1] = newColors[vertIndex + 2] = (oldColors[submesh[n]] + oldColors[submesh[n + 1]] + oldColors[submesh[n + 2]]) / 3f;
|
||
|
||
if (oldUvs.Length > submesh[n + 2])
|
||
{
|
||
newUVs[vertIndex] = oldUvs[submesh[n]];
|
||
newUVs[vertIndex + 1] = oldUvs[submesh[n + 1]];
|
||
newUVs[vertIndex + 2] = oldUvs[submesh[n + 2]];
|
||
}
|
||
|
||
if (oldTangents.Length > submesh[n + 2])
|
||
{
|
||
newTangents[vertIndex] = oldTangents[submesh[n]];
|
||
newTangents[vertIndex + 1] = oldTangents[submesh[n + 1]];
|
||
newTangents[vertIndex + 2] = oldTangents[submesh[n + 2]];
|
||
}
|
||
|
||
if (oldBoneWeights.Length > submesh[n + 2])
|
||
{
|
||
newBoneWeights[vertIndex] = oldBoneWeights[submesh[n]];
|
||
newBoneWeights[vertIndex + 1] = oldBoneWeights[submesh[n + 1]];
|
||
newBoneWeights[vertIndex + 2] = oldBoneWeights[submesh[n + 2]];
|
||
}
|
||
|
||
submesh[n] = vertIndex;
|
||
submesh[n + 1] = vertIndex + 1;
|
||
submesh[n + 2] = vertIndex + 2;
|
||
vertIndex += 3;
|
||
}
|
||
submeshList.Add(submesh);
|
||
}
|
||
|
||
input.vertices = newVertices;
|
||
input.normals = newNormals;
|
||
input.colors = newColors;
|
||
input.uv = newUVs;
|
||
input.tangents = newTangents;
|
||
input.subMeshCount = submeshList.Count;
|
||
input.boneWeights = newBoneWeights;
|
||
for (int i = 0; i < submeshList.Count; i++)
|
||
{
|
||
input.SetTriangles(submeshList[i], i);
|
||
}
|
||
}
|
||
|
||
private static float Area(Vector2[] points, int maxCount)
|
||
{
|
||
float A = 0.0f;
|
||
for (int p = maxCount - 1, q = 0; q < maxCount; p = q++)
|
||
{
|
||
Vector2 pval = points[p];
|
||
Vector2 qval = points[q];
|
||
A += pval.x * qval.y - qval.x * pval.y;
|
||
}
|
||
return (A * 0.5f);
|
||
}
|
||
|
||
private static bool Snip(Vector2[] points, int u, int v, int w, int n, int[] V)
|
||
{
|
||
int p;
|
||
Vector2 A = points[V[u]];
|
||
Vector2 B = points[V[v]];
|
||
Vector2 C = points[V[w]];
|
||
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))
|
||
return false;
|
||
for (p = 0; p < n; p++)
|
||
{
|
||
if ((p == u) || (p == v) || (p == w))
|
||
continue;
|
||
Vector2 P = points[V[p]];
|
||
if (InsideTriangle(A, B, C, P))
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
private static bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
|
||
{
|
||
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||
float cCROSSap, bCROSScp, aCROSSbp;
|
||
|
||
ax = C.x - B.x; ay = C.y - B.y;
|
||
bx = A.x - C.x; by = A.y - C.y;
|
||
cx = B.x - A.x; cy = B.y - A.y;
|
||
apx = P.x - A.x; apy = P.y - A.y;
|
||
bpx = P.x - B.x; bpy = P.y - B.y;
|
||
cpx = P.x - C.x; cpy = P.y - C.y;
|
||
|
||
aCROSSbp = ax * bpy - ay * bpx;
|
||
cCROSSap = cx * apy - cy * apx;
|
||
bCROSScp = bx * cpy - by * cpx;
|
||
|
||
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||
}
|
||
|
||
}
|
||
|
||
}
|