public void AllocateBuffers(int trianglesNum) { if (lsHash == null || lsHash.Capacity() < trianglesNum * 2) { // Utils.Log("Allocating contour: " + trianglesNum); midPoints = new ArrayDictionary <MidPoint>(trianglesNum * 2); contour = new List <Dictionary <int, int> >(); lsHash = new LSHash(0.001f, trianglesNum * 2); } else { lsHash.Clear(); foreach (var item in contour) { item.Clear(); } contour.Clear(); if (midPoints.Size < trianglesNum * 2) { // Utils.Log("Re-allocating midPoint: " + trianglesNum); midPoints = new ArrayDictionary <MidPoint>(trianglesNum * 2); } else { midPoints.Clear(); } } }
/// <summary> /// find and isolate independent (not connecting) parts in a mesh /// </summary> public static List <CutterMesh> IsolateMeshIslands(Mesh mesh) { var triangles = mesh.triangles; var vertexCount = mesh.vertexCount; // cache mesh data var trianglesNum = mesh.triangles.Length; var tangents = mesh.tangents; var colors = mesh.colors32; var vertices = mesh.vertices; var normals = mesh.normals; var uvs = mesh.uv; var useMeshTangents = tangents != null && tangents.Length > 0; var useVertexColors = colors != null && colors.Length > 0; var useNormals = normals != null && normals.Length > 0; if (trianglesNum <= 3) { return(null); } ExploderUtils.Assert(trianglesNum > 3, "IsolateMeshIslands error: " + trianglesNum); var lsHash = new LSHash(0.1f, vertexCount); var vertHash = new int[trianglesNum]; for (int i = 0; i < trianglesNum; i++) { vertHash[i] = lsHash.Hash(vertices[triangles[i]]); } var islands = new List <HashSet <int> > { new HashSet <int> { vertHash[0], vertHash[1], vertHash[2] } }; var islandsIdx = new List <List <int> > { new List <int>(trianglesNum) { 0, 1, 2 } }; var triVisited = new bool[trianglesNum]; triVisited[0] = true; triVisited[1] = true; triVisited[2] = true; var currIsland = islands[0]; var currIslandIdx = islandsIdx[0]; var counter = 3; var lastInvalidIdx = -1; var loopCounter = 0; while (true) { var foundIsland = false; for (int j = 3; j < trianglesNum; j += 3) { if (triVisited[j]) { continue; } if (currIsland.Contains(vertHash[j]) || currIsland.Contains(vertHash[j + 1]) || currIsland.Contains(vertHash[j + 2])) { currIsland.Add(vertHash[j]); currIsland.Add(vertHash[j + 1]); currIsland.Add(vertHash[j + 2]); currIslandIdx.Add(j); currIslandIdx.Add(j + 1); currIslandIdx.Add(j + 2); triVisited[j] = true; triVisited[j + 1] = true; triVisited[j + 2] = true; counter += 3; foundIsland = true; } else { lastInvalidIdx = j; } } if (counter == trianglesNum) { break; } if (!foundIsland) { // create new island currIsland = new HashSet <int> { vertHash[lastInvalidIdx], vertHash[lastInvalidIdx + 1], vertHash[lastInvalidIdx + 2] }; currIslandIdx = new List <int>(trianglesNum / 2) { lastInvalidIdx, lastInvalidIdx + 1, lastInvalidIdx + 2 }; islands.Add(currIsland); islandsIdx.Add(currIslandIdx); } loopCounter++; if (loopCounter > 100) { ExploderUtils.Log("10000 loop exceeded, islands: " + islands.Count); break; } } var islandNum = islands.Count; ExploderUtils.Assert(islandNum >= 1, "No island found!"); // no more than one islands if (islandNum == 1) { return(null); } var result = new List <CutterMesh>(islands.Count); foreach (var island in islandsIdx) { var cutterMesh = new CutterMesh { mesh = new Mesh() }; var triCount = island.Count; var m = cutterMesh.mesh; var tt = new List <int>(triCount); var vs = new List <Vector3>(triCount); var ns = new List <Vector3>(triCount); var us = new List <Vector2>(triCount); var cs = new List <Color32>(triCount); var ts = new List <Vector4>(triCount); var triCache = new Dictionary <int, int>(trianglesNum); var centroid = Vector3.zero; var centroidCounter = 0; var triCounter = 0; foreach (var i in island) { var tri = triangles[i]; var id = 0; if (triCache.TryGetValue(tri, out id)) { tt.Add(id); continue; } tt.Add(triCounter); triCache.Add(tri, triCounter); triCounter++; centroid += vertices[tri]; centroidCounter++; vs.Add(vertices[tri]); us.Add(uvs[tri]); if (useNormals) { ns.Add(normals[tri]); } if (useVertexColors) { cs.Add(colors[tri]); } if (useMeshTangents) { ts.Add(tangents[tri]); } } m.vertices = vs.ToArray(); m.uv = us.ToArray(); if (useNormals) { m.normals = ns.ToArray(); } if (useVertexColors) { m.colors32 = cs.ToArray(); } if (useMeshTangents) { m.tangents = ts.ToArray(); } m.triangles = tt.ToArray(); cutterMesh.centroid = centroid / centroidCounter; result.Add(cutterMesh); } return(result); }
public void AllocateBuffers(int trianglesNum) { if (lsHash == null || lsHash.Capacity() < trianglesNum*2) { // Utils.Log("Allocating contour: " + trianglesNum); midPoints = new ArrayDictionary<MidPoint>(trianglesNum * 2); contour = new List<Dictionary<int, int>>(); lsHash = new LSHash(0.001f, trianglesNum * 2); } else { lsHash.Clear(); foreach (var item in contour) { item.Clear(); } contour.Clear(); if (midPoints.Size < trianglesNum*2) { // Utils.Log("Re-allocating midPoint: " + trianglesNum); midPoints = new ArrayDictionary<MidPoint>(trianglesNum * 2); } else { midPoints.Clear(); } } }