protected override IEnumerator GetSimplifiedMesh(Utils.WorkingMesh origin, float quality, Action <Utils.WorkingMesh> resultCallback) { var meshSimplifier = new global::UnityMeshSimplifier.MeshSimplifier(); meshSimplifier.Vertices = origin.vertices; meshSimplifier.Normals = origin.normals; meshSimplifier.Tangents = origin.tangents; meshSimplifier.UV1 = origin.uv; meshSimplifier.UV2 = origin.uv2; meshSimplifier.UV3 = origin.uv3; meshSimplifier.UV4 = origin.uv4; meshSimplifier.Colors = origin.colors; var triangles = new int[origin.subMeshCount][]; for (var submesh = 0; submesh < origin.subMeshCount; submesh++) { triangles[submesh] = origin.GetTriangles(submesh); } meshSimplifier.AddSubMeshTriangles(triangles); meshSimplifier.SimplifyMesh(quality); int triCount = 0; for (int i = 0; i < meshSimplifier.SubMeshCount; ++i) { triCount += meshSimplifier.GetSubMeshTriangles(i).Length; } Utils.WorkingMesh nwm = new WorkingMesh(Allocator.Persistent, meshSimplifier.Vertices.Length, triCount, meshSimplifier.SubMeshCount, 0); nwm.name = origin.name; nwm.vertices = meshSimplifier.Vertices; nwm.normals = meshSimplifier.Normals; nwm.tangents = meshSimplifier.Tangents; nwm.uv = meshSimplifier.UV1; nwm.uv2 = meshSimplifier.UV2; nwm.uv3 = meshSimplifier.UV3; nwm.uv4 = meshSimplifier.UV4; nwm.colors = meshSimplifier.Colors; nwm.subMeshCount = meshSimplifier.SubMeshCount; for (var submesh = 0; submesh < nwm.subMeshCount; submesh++) { nwm.SetTriangles(meshSimplifier.GetSubMeshTriangles(submesh), submesh); } if (resultCallback != null) { resultCallback(nwm); } yield break; }
protected override IEnumerator GetSimplifiedMesh(Utils.WorkingMesh origin, float quality, Action <Utils.WorkingMesh> resultCallback) { var meshSimplifier = new global::UnityMeshSimplifier.MeshSimplifier(); meshSimplifier.SimplificationOptions = new global::UnityMeshSimplifier.SimplificationOptions { PreserveBorderEdges = m_options.PreserveBorderEdges, PreserveUVSeamEdges = m_options.PreserveUVSeamEdges, PreserveUVFoldoverEdges = m_options.PreserveUVFoldoverEdges, PreserveSurfaceCurvature = m_options.PreserveSurfaceCurvature, EnableSmartLink = m_options.EnableSmartLink, VertexLinkDistance = m_options.VertexLinkDistance, MaxIterationCount = m_options.MaxIterationCount, Agressiveness = m_options.Agressiveness, ManualUVComponentCount = m_options.ManualUVComponentCount, UVComponentCount = m_options.UVComponentCount, }; meshSimplifier.Vertices = origin.vertices; meshSimplifier.Normals = origin.normals; meshSimplifier.Tangents = origin.tangents; meshSimplifier.UV1 = origin.uv; meshSimplifier.UV2 = origin.uv2; meshSimplifier.UV3 = origin.uv3; meshSimplifier.UV4 = origin.uv4; meshSimplifier.Colors = origin.colors; var triangles = new int[origin.subMeshCount][]; for (var submesh = 0; submesh < origin.subMeshCount; submesh++) { triangles[submesh] = origin.GetTriangles(submesh); } meshSimplifier.AddSubMeshTriangles(triangles); meshSimplifier.SimplifyMesh(quality); int triCount = 0; for (int i = 0; i < meshSimplifier.SubMeshCount; ++i) { triCount += meshSimplifier.GetSubMeshTriangles(i).Length; } Utils.WorkingMesh nwm = new WorkingMesh(Allocator.Persistent, meshSimplifier.Vertices.Length, triCount, meshSimplifier.SubMeshCount, 0); nwm.name = origin.name; nwm.vertices = meshSimplifier.Vertices; nwm.normals = meshSimplifier.Normals; nwm.tangents = meshSimplifier.Tangents; nwm.uv = meshSimplifier.UV1; nwm.uv2 = meshSimplifier.UV2; nwm.uv3 = meshSimplifier.UV3; nwm.uv4 = meshSimplifier.UV4; nwm.colors = meshSimplifier.Colors; nwm.subMeshCount = meshSimplifier.SubMeshCount; for (var submesh = 0; submesh < nwm.subMeshCount; submesh++) { nwm.SetTriangles(meshSimplifier.GetSubMeshTriangles(submesh), submesh); } if (resultCallback != null) { resultCallback(nwm); } yield break; }
private WorkingMesh MakeFillHoleMesh(WorkingMesh source) { int totalTris = 0; List <int[]> newTris = new List <int[]>(); for (int si = 0; si < source.subMeshCount; ++si) { List <int> tris = source.GetTriangles(si).ToList(); List <Vector2Int> edgeList = GetEdgeList(tris); List <EdgeGroup> groups = new List <EdgeGroup>(); for (int i = 0; i < edgeList.Count; ++i) { EdgeGroup group = new EdgeGroup(); group.Begin = edgeList[i].x; group.End = edgeList[i].y; group.EdgeList.Add(edgeList[i]); groups.Add(group); } bool isFinish = false; while (isFinish == false) { isFinish = true; for (int gi1 = 0; gi1 < groups.Count; ++gi1) { for (int gi2 = gi1 + 1; gi2 < groups.Count; ++gi2) { EdgeGroup g1 = groups[gi1]; EdgeGroup g2 = groups[gi2]; if (g1.End == g2.Begin) { g1.End = g2.End; g1.EdgeList.AddRange(g2.EdgeList); groups[gi2] = groups[groups.Count - 1]; groups.RemoveAt(groups.Count - 1); gi2 -= 1; isFinish = false; } else if (g1.Begin == g2.End) { g2.End = g1.End; g2.EdgeList.AddRange(g1.EdgeList); groups[gi1] = groups[gi2]; groups[gi2] = groups[groups.Count - 1]; groups.RemoveAt(groups.Count - 1); gi2 -= 1; isFinish = false; } } } } for (int gi = 0; gi < groups.Count; ++gi) { EdgeGroup group = groups[gi]; for (int ei1 = 1; ei1 < group.EdgeList.Count - 1; ++ei1) { for (int ei2 = ei1 + 1; ei2 < group.EdgeList.Count; ++ei2) { if (group.EdgeList[ei1].x == group.EdgeList[ei2].y) { EdgeGroup ng = new EdgeGroup(); ng.Begin = group.EdgeList[ei1].x; ng.End = group.EdgeList[ei2].y; for (int i = ei1; i <= ei2; ++i) { ng.EdgeList.Add(group.EdgeList[i]); } for (int i = ei2; i >= ei1; --i) { group.EdgeList.RemoveAt(i); } groups.Add(ng); ei1 = 0; // goto first break; } } } } if (groups.Count == 0) { continue; } groups.Sort((g1, g2) => { return(g2.EdgeList.Count - g1.EdgeList.Count); }); //first group( longest group ) is outline. for (int i = 1; i < groups.Count; ++i) { EdgeGroup group = groups[i]; for (int ei = 1; ei < group.EdgeList.Count - 1; ++ei) { tris.Add(group.Begin); tris.Add(group.EdgeList[ei].y); tris.Add(group.EdgeList[ei].x); } } totalTris += tris.Count; newTris.Add(tris.ToArray()); } WorkingMesh mesh = new WorkingMesh(Allocator.Persistent, source.vertexCount, totalTris, source.subMeshCount, 0); mesh.name = source.name; mesh.vertices = source.vertices; mesh.normals = source.normals; mesh.uv = source.uv; for (int i = 0; i < newTris.Count; ++i) { mesh.SetTriangles(newTris[i], i); } return(mesh); }
private WorkingMesh MakeBorder(WorkingMesh source, Heightmap heightmap, int borderCount) { List <Vector3> vertices = source.vertices.ToList(); List <Vector3> normals = source.normals.ToList(); List <Vector2> uvs = source.uv.ToList(); List <int[]> subMeshTris = new List <int[]>(); int maxTris = 0; for (int si = 0; si < source.subMeshCount; ++si) { List <int> tris = source.GetTriangles(si).ToList(); List <Vector2Int> edges = GetEdgeList(tris); HashSet <int> vertexIndces = new HashSet <int>(); List <BorderVertex> edgeVertices = new List <BorderVertex>(); for (int ei = 0; ei < edges.Count; ++ei) { vertexIndces.Add(edges[ei].x); vertexIndces.Add(edges[ei].y); } List <BorderVertex> borderVertices = GenerateBorderVertices(heightmap, borderCount); //calculate closest vertex from border vertices. for (int i = 0; i < borderVertices.Count; ++i) { float closestDistance = Single.MaxValue; BorderVertex v = borderVertices[i]; foreach (var index in vertexIndces) { Vector3 pos = vertices[index]; float dist = Vector3.SqrMagnitude(pos - borderVertices[i].Pos); if (dist < closestDistance) { closestDistance = dist; v.ClosestIndex = index; } } borderVertices[i] = v; } //generate tris int startAddIndex = vertices.Count; for (int bi = 0; bi < borderVertices.Count; ++bi) { int next = (bi == borderVertices.Count - 1) ? 0 : bi + 1; tris.Add(bi + startAddIndex); tris.Add(borderVertices[bi].ClosestIndex); tris.Add(next + startAddIndex); Vector2 uv; uv.x = (borderVertices[bi].Pos.x - heightmap.Offset.x) / heightmap.Size.x; uv.y = (borderVertices[bi].Pos.z - heightmap.Offset.z) / heightmap.Size.z; vertices.Add(borderVertices[bi].Pos); if (m_hlod.UseNormal) { normals.Add(Vector3.up); } else { normals.Add(heightmap.GetInterpolatedNormal(uv.x, uv.y)); } uvs.Add(uv); if (borderVertices[bi].ClosestIndex == borderVertices[next].ClosestIndex) { continue; } tris.Add(borderVertices[bi].ClosestIndex); tris.Add(borderVertices[next].ClosestIndex); tris.Add(next + startAddIndex); } maxTris += tris.Count; subMeshTris.Add(tris.ToArray()); } WorkingMesh mesh = new WorkingMesh(Allocator.Persistent, vertices.Count, maxTris, subMeshTris.Count, 0); mesh.name = source.name; mesh.vertices = vertices.ToArray(); mesh.normals = normals.ToArray(); mesh.uv = uvs.ToArray(); for (int i = 0; i < subMeshTris.Count; ++i) { mesh.SetTriangles(subMeshTris[i], i); } return(mesh); }
private WorkingMesh CreateBakedGeometry(string name, Heightmap heightmap, Bounds bounds, int distance) { int borderWidth = CalcBorderWidth(heightmap, distance); int borderWidth2x = borderWidth * 2; WorkingMesh mesh = new WorkingMesh(Allocator.Persistent, heightmap.Width * heightmap.Height, (heightmap.Width - borderWidth2x - 1) * (heightmap.Height - borderWidth2x - 1) * 6, 1, 0); mesh.name = name + "_Mesh"; Vector3[] vertices = new Vector3[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)]; Vector3[] normals = new Vector3[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)]; Vector2[] uvs = new Vector2[(heightmap.Width - borderWidth2x) * (heightmap.Height - borderWidth2x)]; int[] triangles = new int[(heightmap.Width - borderWidth2x - 1) * (heightmap.Height - borderWidth2x - 1) * 6]; int vi = 0; //except boder line for (int z = borderWidth; z < heightmap.Height - borderWidth; ++z) { for (int x = borderWidth; x < heightmap.Width - borderWidth; ++x) { int index = vi++; vertices[index].x = bounds.size.x * (x) / (heightmap.Width - 1) + bounds.min.x; vertices[index].y = heightmap.Size.y * heightmap[z, x]; vertices[index].z = bounds.size.z * (z) / (heightmap.Height - 1) + bounds.min.z; uvs[index].x = (float)x / (heightmap.Width - 1); uvs[index].y = (float)z / (heightmap.Height - 1); if (m_hlod.UseNormal) { normals[index] = Vector3.up; } else { normals[index] = heightmap.GetInterpolatedNormal(uvs[index].x, uvs[index].y); } } } int ii = 0; for (int z = 0; z < heightmap.Height - borderWidth2x - 1; ++z) { for (int x = 0; x < heightmap.Width - borderWidth2x - 1; ++x) { int i00 = z * (heightmap.Width - borderWidth2x) + x; int i10 = z * (heightmap.Width - borderWidth2x) + x + 1; int i01 = (z + 1) * (heightmap.Width - borderWidth2x) + x; int i11 = (z + 1) * (heightmap.Width - borderWidth2x) + x + 1; triangles[ii + 0] = i00; triangles[ii + 1] = i11; triangles[ii + 2] = i10; triangles[ii + 3] = i11; triangles[ii + 4] = i00; triangles[ii + 5] = i01; ii += 6; } } mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uvs; mesh.SetTriangles(triangles, 0); return(mesh); }
public WorkingMesh CombineMesh(Allocator allocator, List <CombineInfo> infos) { //I didn't consider animation mesh combine. int verticesCount = 0; int normalCount = 0; int tangentCount = 0; int UV1Count = 0; int UV2Count = 0; int UV3Count = 0; int UV4Count = 0; int colorCount = 0; int trianglesCount = 0; List <Dictionary <int, int> > remappers = new List <Dictionary <int, int> >(infos.Count); for (int i = 0; i < infos.Count; ++i) { int[] meshIndices = infos[i].Mesh.GetTriangles(infos[i].MeshIndex); Dictionary <int, int> remapper = CalculateMeshRemap(meshIndices); verticesCount += (infos[i].Mesh.vertices.Length > 0) ? remapper.Count : 0; normalCount += (infos[i].Mesh.normals.Length > 0) ? remapper.Count : 0; tangentCount += (infos[i].Mesh.tangents.Length > 0) ? remapper.Count : 0; UV1Count += (infos[i].Mesh.uv.Length > 0) ? remapper.Count : 0; UV2Count += (infos[i].Mesh.uv2.Length > 0) ? remapper.Count : 0; UV3Count += (infos[i].Mesh.uv3.Length > 0) ? remapper.Count : 0; UV4Count += (infos[i].Mesh.uv4.Length > 0) ? remapper.Count : 0; colorCount += (infos[i].Mesh.colors.Length > 0) ? remapper.Count : 0; trianglesCount += meshIndices.Length; remappers.Add(remapper); } WorkingMesh combinedMesh = new WorkingMesh(allocator, verticesCount, trianglesCount, 1, 0); List <Vector3> vertices = new List <Vector3>(verticesCount); List <Vector3> normals = new List <Vector3>(verticesCount); List <Vector4> tangents = new List <Vector4>(verticesCount); List <Vector2> uv1s = new List <Vector2>(verticesCount); List <Vector2> uv2s = new List <Vector2>(verticesCount); List <Vector2> uv3s = new List <Vector2>(verticesCount); List <Vector2> uv4s = new List <Vector2>(verticesCount); List <Color> colors = new List <Color>(colorCount); List <int> triangles = new List <int>(trianglesCount); for (int i = 0; i < infos.Count; ++i) { WorkingMesh mesh = infos[i].Mesh; Dictionary <int, int> remapper = remappers[i]; int startIndex = vertices.Count; if (verticesCount > 0) { FillBuffer(ref vertices, mesh.vertices, remapper, Vector3.zero); for (int vi = startIndex; vi < vertices.Count; ++vi) { vertices[vi] = infos[i].Transform.MultiplyPoint(vertices[vi]); } } if (normalCount > 0) { FillBuffer(ref normals, mesh.normals, remapper, Vector3.up); for (int ni = startIndex; ni < normals.Count; ++ni) { normals[ni] = infos[i].Transform.MultiplyVector(normals[ni]); } } if (tangentCount > 0) { FillBuffer(ref tangents, mesh.tangents, remapper, new Vector4(1, 0, 0, 1)); for (int ti = startIndex; ti < tangents.Count; ++ti) { Vector3 tanVec = new Vector3(tangents[ti].x, tangents[ti].y, tangents[ti].z); tanVec = infos[i].Transform.MultiplyVector(tanVec); Vector4 transTan = new Vector4(tanVec.x, tanVec.y, tanVec.z, tangents[ti].w); tangents[ti] = transTan; } } if (UV1Count > 0) { FillBuffer(ref uv1s, mesh.uv, remapper, Vector2.zero); } if (UV2Count > 0) { FillBuffer(ref uv2s, mesh.uv2, remapper, Vector2.zero); } if (UV3Count > 0) { FillBuffer(ref uv3s, mesh.uv3, remapper, Vector2.zero); } if (UV4Count > 0) { FillBuffer(ref uv4s, mesh.uv4, remapper, Vector2.zero); } if (colorCount > 0) { FillBuffer(ref colors, mesh.colors, remapper, Color.white); } FillIndices(ref triangles, mesh.GetTriangles(infos[i].MeshIndex), remapper, startIndex); } combinedMesh.name = "CombinedMesh"; combinedMesh.vertices = vertices.ToArray(); combinedMesh.normals = normals.ToArray(); combinedMesh.tangents = tangents.ToArray(); combinedMesh.uv = uv1s.ToArray(); combinedMesh.uv2 = uv2s.ToArray(); combinedMesh.uv3 = uv3s.ToArray(); combinedMesh.uv4 = uv4s.ToArray(); combinedMesh.colors = colors.ToArray(); combinedMesh.SetTriangles(triangles.ToArray(), 0); return(combinedMesh); }