//fix pole vertices incorrect U private static Dictionary <int, float> FindAndFixPoleVertices(IPlatonicSolid solid, ref List <TriangleFace> faces, ref List <Vector3> vertices) { Vector3 north = solid.NorthPole; Vector3 south = -solid.NorthPole; List <int> poleVerticeInd = new List <int>(); Dictionary <int, float> poleVertIndicesCorrectU = new Dictionary <int, float>(); foreach (TriangleFace face in faces) { if (vertices[face.IndA] == north || vertices[face.IndA] == south) { if (!poleVerticeInd.Contains(face.IndA)) { poleVerticeInd.Add(face.IndA); } else { vertices.Add(vertices[face.IndA] == north ? north : south); face.SetIndA(vertices.Count - 1); } float xCoordB = GetUvCoordinates(vertices[face.IndB]).x; float xCoordC = GetUvCoordinates(vertices[face.IndC]).x; float correctedU = (xCoordB + xCoordC) / 2f + 0.5f; // I am not sure why it is needed but it seems needed... poleVertIndicesCorrectU[face.IndA] = correctedU; } } return(poleVertIndicesCorrectU); }
private void GenerateSphereMeshThread(object obj) { if (SphereType == SphereType.uvsphere) { _sphereMesh = UvSphereBuilder.Generate(Radius, Resolution); } else { IPlatonicSolid baseSolid = GetBaseSolid(SphereType); _sphereMesh = SphereBuilder.Build(baseSolid, Radius, Resolution, Smooth, RemapVertices); } Debug.Log(SphereType.ToString() + " generated: " + _sphereMesh.Triangles.Length + " tris and " + _sphereMesh.Vertices.Length + " verts."); }
/// <summary> /// Generate a UV sphere. /// </summary> /// <param name="resolution">Number of latitude lines (vertices on the y axis).</param> public static MeshData Build(IPlatonicSolid platonic, float radius, int resolution, bool smooth, bool remapVertices) { List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <TriangleFace> faces = new List <TriangleFace>(); Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>(); Dictionary <int, int> vertWithWarpedU = new Dictionary <int, int>(); Dictionary <int, float> poleVertIndicesCorrectU = new Dictionary <int, float>(); Vector2[] uv; Vector3[] normals; Vector4[] tangents; Vector4 tangent = new Vector4(1f, 0f, 0f, -1f); // create the base cube primitive vertices = platonic.Vertices; faces = platonic.Faces; // subdivide the triangles faces for (int i = 1; i < resolution; i++) { List <TriangleFace> newFaces = new List <TriangleFace>(); foreach (var tri in faces) { // replace triangle by 4 triangles int a = GetMiddlePoint(tri.IndA, tri.IndB, ref vertices, ref middlePointIndexCache); int b = GetMiddlePoint(tri.IndB, tri.IndC, ref vertices, ref middlePointIndexCache); int c = GetMiddlePoint(tri.IndC, tri.IndA, ref vertices, ref middlePointIndexCache); newFaces.Add(new TriangleFace(tri.IndA, a, c)); newFaces.Add(new TriangleFace(tri.IndB, b, a)); newFaces.Add(new TriangleFace(tri.IndC, c, b)); newFaces.Add(new TriangleFace(a, b, c)); } faces = newFaces; } // fix warped uv on seam vertWithWarpedU = FindAndFixeWarpedFaces(ref faces, ref vertices); poleVertIndicesCorrectU = FindAndFixPoleVertices(platonic, ref faces, ref vertices); // makes unique vertice to have a non smooth sphere if (!smooth) { MakeVerticesUnique(ref faces, ref vertices, ref vertWithWarpedU, ref poleVertIndicesCorrectU); } // create mesh triangles for (int i = 0; i < faces.Count; i++) { triangles.Add(faces[i].IndA); triangles.Add(faces[i].IndB); triangles.Add(faces[i].IndC); } if (remapVertices) { vertices = platonic.RemapVertices(vertices, faces); } // generate uv, normals, and tangents uv = new Vector2[vertices.Count]; normals = new Vector3[vertices.Count]; tangents = new Vector4[vertices.Count]; for (int i = 0; i < vertices.Count; i++) { Vector3 normal = vertices[i].normalized; float u = (Mathf.Atan2(normal.z, normal.x) / (2f * Mathf.PI)) + 0.5f; // remove the 0.5f float v = (Mathf.Asin(normal.y) / Mathf.PI) + 0.5f; vertices[i] = normal * radius; // correct uv issues if (poleVertIndicesCorrectU.ContainsKey(i)) { u = poleVertIndicesCorrectU[i]; } if (vertWithWarpedU.ContainsValue(i)) { u += 1; } if (vertWithWarpedU.ContainsValue(i) && poleVertIndicesCorrectU.ContainsKey(i)) { u -= 0.5f; // found through trial and error, it was working so I had to remove the 0.5 added when recalculating } uv[i] = new Vector2(u, v); normals[i] = normal; tangents[i] = tangent; } // recompute normals if (!smooth) { foreach (TriangleFace face in faces) { Vector3 normal = GetFaceCenter(face, vertices); normals[face.IndA] = normal; normals[face.IndB] = normal; normals[face.IndC] = normal; } } return(new MeshData(vertices.ToArray(), triangles.ToArray(), uv, normals, tangents)); }