public Mesh GenerateMesh() { DebugUtil.StartStopwatch("GenerateMesh"); Mesh mesh = new Mesh(); mesh.name = m_name; Dictionary <int, Dictionary <DraggableMeshPoint, int> > smoothingGroups = new Dictionary <int, Dictionary <DraggableMeshPoint, int> >(); List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); int[] triangles = new int[m_triangles.Count * 3]; for (int i = 0; i < m_triangles.Count; i++) { if (!smoothingGroups.ContainsKey(m_triangles[i].m_smoothGroupIndex)) { smoothingGroups.Add(m_triangles[i].m_smoothGroupIndex, new Dictionary <DraggableMeshPoint, int>()); } for (int j = 0; j < m_triangles[i].m_points.Length; j++) { if (!smoothingGroups[m_triangles[i].m_smoothGroupIndex].ContainsKey(m_triangles[i].m_points[j])) { // Add vertex to vertices and smoothing group dictionary vertices.Add(m_triangles[i].m_points[j].transform.position); uvs.Add(m_triangles[i].m_uvs[j]); smoothingGroups[m_triangles[i].m_smoothGroupIndex].Add(m_triangles[i].m_points[j], vertices.Count - 1); triangles[3 * i + j] = vertices.Count - 1; } else { // Use the one that we already have triangles[3 * i + j] = smoothingGroups[m_triangles[i].m_smoothGroupIndex][m_triangles[i].m_points[j]]; } } } mesh.vertices = vertices.ToArray(); mesh.triangles = triangles; mesh.uv = uvs.ToArray(); mesh.RecalculateBounds(); mesh.RecalculateNormals(); DebugUtil.EndStopwatch("GenerateMesh"); return(mesh); }
private Vector2[] PackUVs(Dictionary <int, Vector2>[] uvs, int uvCount, float startScale, int triesLeft) { DebugUtil.StartStopwatch("UV Packing"); Vector2[] combinedUvs = new Vector2[uvCount]; if (triesLeft == 0) { Debug.LogWarning("No tries left for UV packing"); return(combinedUvs); } Dictionary <int, Vector2>[] originalUVs = (Dictionary <int, Vector2>[])uvs.Clone(); Rect[] rects = new Rect[uvs.Length]; Rect[] startRects = new Rect[uvs.Length]; for (int i = 0; i < uvs.Length; i++) { Vector2 min = new Vector2(9999, 9999); Vector2 max = new Vector2(-9999, -9999); var keys = new List <int>(uvs[i].Keys); foreach (var k in keys) { var uv = uvs[i][k]; uv.Scale(new Vector2(startScale, startScale)); if (uv.x < min.x) { min.x = uv.x; } if (uv.y < min.y) { min.y = uv.y; } if (uv.x > max.x) { max.x = uv.x; } if (uv.y > max.y) { max.y = uv.y; } uvs[i][k] = uv; } rects[i].min = min; rects[i].max = max; startRects[i].min = min; startRects[i].max = max; rects[i].position += new Vector2(0.01f, 0.01f) * i; } float stepSize = 0.08f; bool noOverlap = false; int iterations = 0; int maxIterations = 1000; while (!noOverlap && iterations < maxIterations) { noOverlap = true; iterations++; for (int i = 0; i < rects.Length; i++) { for (int k = 0; k < rects.Length; k++) { if (k == i) { continue; } if (rects[i].Overlaps(rects[k])) { noOverlap = false; // From k to i Vector2 dif = rects[i].position - rects[k].position; if (dif.sqrMagnitude > stepSize * stepSize) { dif = dif.normalized * stepSize; } Vector2 randOffset = Random.insideUnitCircle * 0.01f; dif += randOffset; if (dif.x < 0) { if (rects[i].xMin + dif.x < 0) { dif.x = 0 - rects[i].xMin; } } else { if (rects[i].xMax + dif.x > 1.0) { dif.x = 1 - rects[i].xMax; } } if (dif.y < 0) { if (rects[i].yMin + dif.y < 0) { dif.y = 0 - rects[i].yMin; } } else { if (rects[i].yMax + dif.y > 1.0) { dif.y = 1 - rects[i].yMax; } } rects[i].position += dif; } } } } for (int i = 0; i < uvs.Length; i++) { foreach (var uv in uvs[i]) { combinedUvs[uv.Key] = uv.Value + rects[i].position - startRects[i].position; } } DebugUtil.EndStopwatch("UV Packing"); if (noOverlap) { Debug.Log("Succes packing UVs"); } else { Debug.Log("Packing failed, retrying with smaller scale"); combinedUvs = PackUVs(originalUVs, uvCount, startScale * 0.8f, triesLeft - 1); } return(combinedUvs); }
public void Unwrap(ref List <MeshManager.Triangle> triangles) { DebugUtil.StartStopwatch("Unwrap"); List <Vector3> vertices; List <Vector3> normals; Dictionary <int, Dictionary <DraggableMeshPoint, int> > smoothingGroups; GetVertices(triangles, out vertices, out normals, out smoothingGroups); // 6 faces Dictionary <int, Vector2>[] uvs = new Dictionary <int, Vector2> [6]; for (int i = 0; i < uvs.Length; i++) { uvs[i] = new Dictionary <int, Vector2>(); } Vector3 min, max; //float minF, maxF; GetBoundingBox(vertices, out min, out max); //GetBoundingBox(vertices, out minF, out maxF); for (int i = 0; i < vertices.Count; i++) { Vector3 vec = vertices[i] - min; vec.x /= (max.x - min.x); vec.y /= (max.y - min.y); vec.z /= (max.z - min.z); float[] ang = new float[6]; ang[0] = Vector3.Angle(Vector3.right, normals[i]); //+x ang[1] = Vector3.Angle(Vector3.left, normals[i]); //-x ang[2] = Vector3.Angle(Vector3.up, normals[i]); //+y ang[3] = Vector3.Angle(Vector3.down, normals[i]); //-y ang[4] = Vector3.Angle(Vector3.forward, normals[i]); //+z ang[5] = Vector3.Angle(Vector3.back, normals[i]); //-z int minIndex = 0; float minVal = 9999.0f; for (int k = 0; k < ang.Length; k++) { if (ang[k] < minVal) { minVal = ang[k]; minIndex = k; } } Vector2 uv; switch (minIndex) { default: case 0: uv.x = vec.z; uv.y = vec.y; break; case 1: uv.x = 1.0f - vec.z; uv.y = vec.y; break; case 2: uv.x = vec.x; uv.y = vec.z; break; case 3: uv.x = vec.x; uv.y = 1.0f - vec.z; break; case 4: uv.x = 1.0f - vec.x; uv.y = vec.y; break; case 5: uv.x = vec.x; uv.y = vec.y; break; } uvs[minIndex][i] = uv; } // Pack UVs var combinedUvs = PackUVs(uvs, vertices.Capacity, 0.3f); // Update triangles with uvs foreach (var triangle in triangles) { for (int i = 0; i < triangle.m_points.Length; i++) { int index = smoothingGroups[triangle.m_smoothGroupIndex][triangle.m_points[i]]; triangle.m_uvs[i] = combinedUvs[index]; } } DebugUtil.EndStopwatch("Unwrap"); }