public void From(WorkingMesh mesh) { m_name = mesh.name; m_vertices = ArrayToBytes(mesh.vertices); m_normals = ArrayToBytes(mesh.normals); m_tangents = ArrayToBytes(mesh.tangents); m_uvs = ArrayToBytes(mesh.uv); m_uvs2 = ArrayToBytes(mesh.uv2); m_uvs3 = ArrayToBytes(mesh.uv3); m_uvs4 = ArrayToBytes(mesh.uv4); m_colors = ArrayToBytes(mesh.colors); m_indices = new List <int[]>(); for (int i = 0; i < mesh.subMeshCount; ++i) { m_indices.Add(mesh.GetTriangles(i)); } }
private void ConvertMesh(WorkingMesh mesh, DisposableList <WorkingMaterial> materials, TexturePacker.TextureAtlas atlas, string mainTextureName) { var uv = mesh.uv; var updated = new bool[uv.Length]; // Some meshes have submeshes that either aren't expected to render or are missing a material, so go ahead and skip int subMeshCount = Mathf.Min(mesh.subMeshCount, materials.Count); for (int mi = 0; mi < subMeshCount; ++mi) { int[] indices = mesh.GetTriangles(mi); foreach (var i in indices) { if (updated[i] == false) { var uvCoord = uv[i]; var texture = materials[mi].GetTexture(mainTextureName); if (texture == null || texture.GetGUID() == Guid.Empty) { // Sample at center of white texture to avoid sampling edge colors incorrectly uvCoord.x = 0.5f; uvCoord.y = 0.5f; } else { var uvOffset = atlas.GetUV(texture.GetGUID()); uvCoord.x = Mathf.Lerp(uvOffset.xMin, uvOffset.xMax, uvCoord.x); uvCoord.y = Mathf.Lerp(uvOffset.yMin, uvOffset.yMax, uvCoord.y); } uv[i] = uvCoord; updated[i] = true; } } } mesh.uv = uv; }
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); }
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); }