rabidus-test/Assets/Dreamteck/Utilities/TS_Mesh.cs

393 lines
16 KiB
C#
Raw Permalink Normal View History

2023-07-24 16:38:13 +03:00
namespace Dreamteck
{
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//Thread-safe mesh & bounds classes for working with threads.
public class TS_Mesh
{
public int vertexCount
{
get { return vertices.Length; }
set { }
}
public Vector3[] vertices = new Vector3[0];
public Vector3[] normals = new Vector3[0];
public Vector4[] tangents = new Vector4[0];
public Color[] colors = new Color[0];
public Vector2[] uv = new Vector2[0];
public Vector2[] uv2 = new Vector2[0];
public Vector2[] uv3 = new Vector2[0];
public Vector2[] uv4 = new Vector2[0];
public int[] triangles = new int[0];
public List<int[]> subMeshes = new List<int[]>();
public TS_Bounds bounds = new TS_Bounds(Vector3.zero, Vector3.zero);
public UnityEngine.Rendering.IndexFormat indexFormat = UnityEngine.Rendering.IndexFormat.UInt16;
public volatile bool hasUpdate = false;
private int[] _submeshTrisCount = new int[0];
private int[] _submeshOffsets = new int[0];
public TS_Mesh()
{
}
public TS_Mesh(Mesh mesh)
{
CreateFromMesh(mesh);
}
public void Clear()
{
vertices = new Vector3[0];
normals = new Vector3[0];
tangents = new Vector4[0];
colors = new Color[0];
uv = new Vector2[0];
uv2 = new Vector2[0];
uv3 = new Vector2[0];
uv4 = new Vector2[0];
triangles = new int[0];
subMeshes = new List<int[]>();
bounds = new TS_Bounds(Vector3.zero, Vector3.zero);
}
public void CreateFromMesh(Mesh mesh)
{
vertices = mesh.vertices;
normals = mesh.normals;
tangents = mesh.tangents;
colors = mesh.colors;
uv = mesh.uv;
uv2 = mesh.uv2;
uv3 = mesh.uv3;
uv4 = mesh.uv4;
triangles = mesh.triangles;
bounds = new TS_Bounds(mesh.bounds);
indexFormat = mesh.indexFormat;
for (int i = 0; i < mesh.subMeshCount; i++)
{
subMeshes.Add(mesh.GetTriangles(i));
}
}
/// <summary>
/// Writes the combineMeshes array to the current TS_Mesh object and tries to not allocate memory
/// </summary>
/// <param name="combineMeshes"></param>
public void Combine(List<TS_Mesh> combineMeshes)
{
int totalVertexCount = 0;
int totalTrisCount = 0;
int addedSubmeshCount = 0;
for (int i = 0; i < combineMeshes.Count; i++)
{
totalVertexCount += combineMeshes[i].vertices.Length;
totalTrisCount += combineMeshes[i].triangles.Length;
if (combineMeshes[i].subMeshes.Count > addedSubmeshCount)
{
addedSubmeshCount = combineMeshes[i].subMeshes.Count;
}
}
if (_submeshTrisCount.Length != addedSubmeshCount)
{
_submeshTrisCount = new int[addedSubmeshCount];
}
else
{
for (int i = 0; i < _submeshTrisCount.Length; i++)
{
_submeshTrisCount[i] = 0;
}
}
for (int i = 0; i < combineMeshes.Count; i++)
{
for (int j = 0; j < combineMeshes[i].subMeshes.Count; j++)
{
_submeshTrisCount[j] += combineMeshes[i].subMeshes[j].Length;
}
}
if (vertices.Length != totalVertexCount) vertices = new Vector3[totalVertexCount];
if (normals.Length != totalVertexCount) normals = new Vector3[totalVertexCount];
if (uv.Length != totalVertexCount) uv = new Vector2[totalVertexCount];
if (uv2.Length != totalVertexCount) uv2 = new Vector2[totalVertexCount];
if (uv3.Length != totalVertexCount) uv3 = new Vector2[totalVertexCount];
if (uv4.Length != totalVertexCount) uv4 = new Vector2[totalVertexCount];
if (colors.Length != totalVertexCount) colors = new Color[totalVertexCount];
if (tangents.Length != totalVertexCount) tangents = new Vector4[totalVertexCount];
if (triangles.Length != totalTrisCount) triangles = new int[totalTrisCount];
if (subMeshes.Count > addedSubmeshCount) subMeshes.Clear();
int vertexOffset = 0;
int trisOffset = 0;
if(_submeshOffsets.Length != addedSubmeshCount)
{
_submeshOffsets = new int[addedSubmeshCount];
} else
{
for (int i = 0; i < _submeshOffsets.Length; i++)
{
_submeshOffsets[i] = 0;
}
}
for (int i = 0; i < combineMeshes.Count; i++)
{
combineMeshes[i].vertices.CopyTo(vertices, vertexOffset);
combineMeshes[i].normals.CopyTo(normals, vertexOffset);
combineMeshes[i].uv.CopyTo(uv, vertexOffset);
combineMeshes[i].uv2.CopyTo(uv2, vertexOffset);
combineMeshes[i].uv3.CopyTo(uv3, vertexOffset);
combineMeshes[i].uv4.CopyTo(uv4, vertexOffset);
combineMeshes[i].colors.CopyTo(colors, vertexOffset);
combineMeshes[i].tangents.CopyTo(tangents, vertexOffset);
for (int t = 0; t < combineMeshes[i].triangles.Length; t++)
{
int index = t + trisOffset;
triangles[index] = combineMeshes[i].triangles[t] + vertexOffset;
}
trisOffset += combineMeshes[i].triangles.Length;
for (int j = 0; j < combineMeshes[i].subMeshes.Count; j++)
{
if (j >= subMeshes.Count)
{
subMeshes.Add(new int[_submeshTrisCount[j]]);
}
else if (subMeshes[j].Length != _submeshTrisCount[j])
{
subMeshes[j] = new int[_submeshTrisCount[j]];
}
int[] submesh = combineMeshes[i].subMeshes[j];
for (int x = 0; x < submesh.Length; x++)
{
int index = _submeshOffsets[j] + x;
subMeshes[j][index] = submesh[x] + vertexOffset;
}
_submeshOffsets[j] += submesh.Length;
}
vertexOffset += combineMeshes[i].vertices.Length;
}
}
/// <summary>
/// Adds the provieded mesh list to the current mesh and allocates memory
/// </summary>
/// <param name="addedMeshes"></param>
public void AddMeshes(List<TS_Mesh> addedMeshes)
{
int newVerts = 0;
int newTris = 0;
int submeshCount = 0;
for (int i = 0; i < addedMeshes.Count; i++)
{
newVerts += addedMeshes[i].vertexCount;
newTris += addedMeshes[i].triangles.Length;
if (addedMeshes[i].subMeshes.Count > submeshCount)
{
submeshCount = addedMeshes[i].subMeshes.Count;
}
}
int[] submeshTrisCount = new int[submeshCount];
int[] submeshOffsets = new int[submeshCount];
for (int i = 0; i < addedMeshes.Count; i++)
{
for (int j = 0; j < addedMeshes[i].subMeshes.Count; j++)
{
submeshTrisCount[j] += addedMeshes[i].subMeshes[j].Length;
}
}
Vector3[] newVertices = new Vector3[vertices.Length + newVerts];
Vector3[] newNormals = new Vector3[vertices.Length + newVerts];
Vector2[] newUvs = new Vector2[vertices.Length + newVerts];
Vector2[] newUvs2 = new Vector2[vertices.Length + newVerts];
Vector2[] newUvs3 = new Vector2[vertices.Length + newVerts];
Vector2[] newUvs4 = new Vector2[vertices.Length + newVerts];
Color[] newColors = new Color[vertices.Length + newVerts];
Vector4[] newTangents = new Vector4[tangents.Length + newVerts];
int[] newTriangles = new int[triangles.Length + newTris];
List<int[]> newSubmeshes = new List<int[]>();
for (int i = 0; i < submeshTrisCount.Length; i++)
{
newSubmeshes.Add(new int[submeshTrisCount[i]]);
if (i < subMeshes.Count)
{
submeshTrisCount[i] = subMeshes[i].Length;
}
else
{
submeshTrisCount[i] = 0;
}
}
newVerts = vertexCount;
newTris = triangles.Length;
vertices.CopyTo(newVertices, 0);
normals.CopyTo(newNormals, 0);
uv.CopyTo(newUvs, 0);
uv2.CopyTo(newUvs2, 0);
uv3.CopyTo(newUvs3, 0);
uv4.CopyTo(newUvs4, 0);
colors.CopyTo(newColors, 0);
tangents.CopyTo(newTangents, 0);
triangles.CopyTo(newTriangles, 0);
for (int i = 0; i < addedMeshes.Count; i++)
{
addedMeshes[i].vertices.CopyTo(newVertices, newVerts);
addedMeshes[i].normals.CopyTo(newNormals, newVerts);
addedMeshes[i].uv.CopyTo(newUvs, newVerts);
addedMeshes[i].uv2.CopyTo(newUvs2, newVerts);
addedMeshes[i].uv3.CopyTo(newUvs3, newVerts);
addedMeshes[i].uv4.CopyTo(newUvs4, newVerts);
addedMeshes[i].colors.CopyTo(newColors, newVerts);
addedMeshes[i].tangents.CopyTo(newTangents, newVerts);
for (int n = newTris; n < newTris + addedMeshes[i].triangles.Length; n++)
{
newTriangles[n] = addedMeshes[i].triangles[n - newTris] + newVerts;
}
for (int n = 0; n < addedMeshes[i].subMeshes.Count; n++)
{
for (int x = submeshTrisCount[n]; x < submeshTrisCount[n] + addedMeshes[i].subMeshes[n].Length; x++)
{
newSubmeshes[n][x] = addedMeshes[i].subMeshes[n][x - submeshTrisCount[n]] + newVerts;
}
submeshTrisCount[n] += addedMeshes[i].subMeshes[n].Length;
}
newTris += addedMeshes[i].triangles.Length;
newVerts += addedMeshes[i].vertexCount;
}
vertices = newVertices;
normals = newNormals;
uv = newUvs;
uv2 = newUvs2;
uv3 = newUvs3;
uv4 = newUvs4;
colors = newColors;
tangents = newTangents;
triangles = newTriangles;
subMeshes = newSubmeshes;
}
public static TS_Mesh Copy(TS_Mesh input)
{
TS_Mesh result = new TS_Mesh();
result.vertices = new Vector3[input.vertices.Length];
input.vertices.CopyTo(result.vertices, 0);
result.normals = new Vector3[input.normals.Length];
input.normals.CopyTo(result.normals, 0);
result.uv = new Vector2[input.uv.Length];
input.uv.CopyTo(result.uv, 0);
result.uv2 = new Vector2[input.uv2.Length];
input.uv2.CopyTo(result.uv2, 0);
result.uv3 = new Vector2[input.uv3.Length];
input.uv3.CopyTo(result.uv3, 0);
result.uv4 = new Vector2[input.uv4.Length];
input.uv4.CopyTo(result.uv4, 0);
result.colors = new Color[input.colors.Length];
input.colors.CopyTo(result.colors, 0);
result.tangents = new Vector4[input.tangents.Length];
input.tangents.CopyTo(result.tangents, 0);
result.triangles = new int[input.triangles.Length];
input.triangles.CopyTo(result.triangles, 0);
result.subMeshes = new List<int[]>();
for(int i = 0; i < input.subMeshes.Count; i++)
{
result.subMeshes.Add(new int[input.subMeshes[i].Length]);
input.subMeshes[i].CopyTo(result.subMeshes[i], 0);
}
result.bounds = new TS_Bounds(input.bounds.center, input.bounds.size);
result.indexFormat = input.indexFormat;
return result;
}
public void Absorb(TS_Mesh input)
{
if (vertices.Length != input.vertexCount) vertices = new Vector3[input.vertexCount];
if (normals.Length != input.normals.Length) normals = new Vector3[input.normals.Length];
if (colors.Length != input.colors.Length) colors = new Color[input.colors.Length];
if (uv.Length != input.uv.Length) uv = new Vector2[input.uv.Length];
if (uv2.Length != input.uv2.Length) uv2 = new Vector2[input.uv2.Length];
if (uv3.Length != input.uv3.Length) uv3 = new Vector2[input.uv3.Length];
if (uv4.Length != input.uv4.Length) uv4 = new Vector2[input.uv4.Length];
if (tangents.Length != input.tangents.Length) tangents = new Vector4[input.tangents.Length];
if (triangles.Length != input.triangles.Length) triangles = new int[input.triangles.Length];
input.vertices.CopyTo(vertices, 0);
input.normals.CopyTo(normals, 0);
input.colors.CopyTo(colors, 0);
input.uv.CopyTo(uv, 0);
input.uv2.CopyTo(uv2, 0);
input.uv3.CopyTo(uv3, 0);
input.uv4.CopyTo(uv4, 0);
input.tangents.CopyTo(tangents, 0);
input.triangles.CopyTo(triangles, 0);
if (subMeshes.Count == input.subMeshes.Count)
{
for (int i = 0; i < subMeshes.Count; i++)
{
if (input.subMeshes[i].Length != subMeshes[i].Length) subMeshes[i] = new int[input.subMeshes[i].Length];
input.subMeshes[i].CopyTo(subMeshes[i], 0);
}
}
else
{
subMeshes = new List<int[]>();
for (int i = 0; i < input.subMeshes.Count; i++)
{
subMeshes.Add(new int[input.subMeshes[i].Length]);
input.subMeshes[i].CopyTo(subMeshes[i], 0);
}
}
bounds = new TS_Bounds(input.bounds.center, input.bounds.size);
}
public void WriteMesh(ref Mesh input)
{
if (input == null) input = new Mesh();
input.Clear();
input.indexFormat = indexFormat;
input.vertices = vertices;
input.normals = normals;
if (tangents.Length == vertices.Length) input.tangents = tangents;
if (colors.Length == vertices.Length) input.colors = colors;
if (uv.Length == vertices.Length) input.uv = uv;
if (uv2.Length == vertices.Length) input.uv2 = uv2;
if (uv3.Length == vertices.Length) input.uv3 = uv3;
if (uv4.Length == vertices.Length) input.uv4 = uv4;
input.triangles = triangles;
if (subMeshes.Count > 0)
{
input.subMeshCount = subMeshes.Count;
for (int i = 0; i < subMeshes.Count; i++)
{
input.SetTriangles(subMeshes[i], i);
}
}
input.RecalculateBounds();
hasUpdate = false;
}
}
}