public void Generate() { switch (ShapeType) { case ShapeTypes.Wythoff: var wythoff = new WythoffPoly(PolyType, PrismP, PrismQ); wythoff.BuildFaces(); poly = new ConwayPoly(wythoff); break; case ShapeTypes.Johnson: poly = JohnsonPoly.Build(JohnsonPolyType, PrismP); break; case ShapeTypes.Grid: poly = Grids.Grids.MakeGrid(GridType, GridShape, PrismP, PrismQ); break; } if (ApplyOp) { var o1 = new OpParams { valueA = op1Amount1, valueB = op1Amount2, facesel = op1Facesel }; poly = poly.ApplyOp(op1, o1); } if (PreCanonicalize) { poly = poly.Canonicalize(0.01, 0.01); } if (Canonicalize) { poly = poly.Canonicalize(0.01, 0.01); } if (ApplyOp) { var o2 = new OpParams { valueA = op2Amount1, valueB = op2Amount2, facesel = op2Facesel }; poly = poly.ApplyOp(op2, o2); var o3 = new OpParams { valueA = op3Amount1, valueB = op3Amount2, facesel = op3Facesel }; poly = poly.ApplyOp(op3, o3); } var points = poly.ListVerticesByPoints().ToList(); if (JitterAmount > 0) { for (int i = 0; i < points.Count(); i++) { var point = points[i]; points[i] = new Vector3( point.x + Random.value * JitterAmount, point.y + Random.value * JitterAmount, point.z + Random.value * JitterAmount ); } } var faceIndices = poly.ListFacesByVertexIndices(); // This whole mess is because I can't find a way to regenerate // a probuilder mesh and therefore have to continually create/destroy gameobjects // (which is a mess in edit mode) // If anyone can explain how to simply take an existing probuilder object clear it // and pass in a list of Vector3's and lists of ordered indexes for faces // then please do. if (pbmesh != null && pbmesh.gameObject != null) { if (Application.isPlaying) { Destroy(pbmesh.gameObject); } else { var go = pbmesh.gameObject; UnityEditor.EditorApplication.delayCall += () => { DestroyImmediate(go); }; } } var colors = Enumerable.Range(0, 8).Select(x => Colors.Evaluate(((x / 8f) * ColorRange + ColorOffset) % 1)).ToArray(); pbmesh = ProBuilderMesh.Create(points, new List <Face>()); var faces = new List <PBFace>(); for (var i = 0; i < faceIndices.Length; i++) { var face = faceIndices[i]; var result = AppendElements.CreatePolygon(pbmesh, face, false); if (result != null) { pbmesh.SetFaceColor(result, colors[(int)poly.FaceRoles[i]]); faces.Add(result); } } if (faces.Count < 1 || pbmesh == null) { return; } pbmesh.SetMaterial(faces, material); pbmesh.ToMesh(); pbmesh.Refresh(); }
// new Color(1.0f, 0.75f, 0.75f), // new Color(1.0f, 0.5f, 0.5f), // new Color(0.8f, 0.4f, 0.4f), // new Color(0.8f, 0.8f, 0.8f), // new Color(0.5f, 0.6f, 0.6f), // new Color(0.6f, 0.0f, 0.0f), // new Color(1.0f, 1.0f, 1.0f), // new Color(0.6f, 0.6f, 0.6f), // new Color(0.5f, 1.0f, 0.5f), // new Color(0.5f, 0.5f, 1.0f), // new Color(0.5f, 1.0f, 1.0f), // new Color(1.0f, 0.5f, 1.0f), public static Mesh BuildMeshFromConwayPoly( ConwayPoly conway, bool generateSubmeshes = false, Color[] colors = null, PolyHydraEnums.ColorMethods colorMethod = PolyHydraEnums.ColorMethods.ByRole, PolyHydraEnums.UVMethods uvMethod = PolyHydraEnums.UVMethods.FirstEdge, bool largeMeshFormat = true ) { Vector2 calcUV(Vector3 point, Vector3 xAxis, Vector3 yAxis) { float u, v; u = Vector3.Project(point, xAxis).magnitude; u *= Vector3.Dot(point, xAxis) > 0 ? 1 : -1; v = Vector3.Project(point, yAxis).magnitude; v *= Vector3.Dot(point, yAxis) > 0 ? 1 : -1; return(new Vector2(u, v)); } if (colors == null) { colors = DefaultFaceColors; } var target = new Mesh(); if (largeMeshFormat) { target.indexFormat = IndexFormat.UInt32; } var meshTriangles = new List <int>(); var meshVertices = new List <Vector3>(); var meshNormals = new List <Vector3>(); var meshColors = new List <Color32>(); var meshUVs = new List <Vector2>(); var edgeUVs = new List <Vector2>(); var barycentricUVs = new List <Vector3>(); var miscUVs1 = new List <Vector4>(); var miscUVs2 = new List <Vector4>(); List <ConwayPoly.Roles> uniqueRoles = null; List <int> uniqueSides = null; List <string> uniqueTags = null; var submeshTriangles = new List <List <int> >(); // TODO // var hasNaked = conway.HasNaked(); // Strip down to Face-Vertex structure var points = conway.ListVerticesByPoints(); var faceIndices = conway.ListFacesByVertexIndices(); // Add faces int index = 0; if (generateSubmeshes) { switch (colorMethod) { case PolyHydraEnums.ColorMethods.ByRole: uniqueRoles = new HashSet <ConwayPoly.Roles>(conway.FaceRoles).ToList(); for (int i = 0; i < uniqueRoles.Count; i++) { submeshTriangles.Add(new List <int>()); } break; case PolyHydraEnums.ColorMethods.BySides: for (int i = 0; i < colors.Length; i++) { submeshTriangles.Add(new List <int>()); } break; case PolyHydraEnums.ColorMethods.ByFaceDirection: for (int i = 0; i < colors.Length; i++) { submeshTriangles.Add(new List <int>()); } break; case PolyHydraEnums.ColorMethods.ByTags: var flattenedTags = conway.FaceTags.SelectMany(d => d.Select(i => i.Item1)); uniqueTags = new HashSet <string>(flattenedTags).ToList(); for (int i = 0; i < uniqueTags.Count + 1; i++) { submeshTriangles.Add(new List <int>()); } break; } } for (var i = 0; i < faceIndices.Length; i++) { var faceIndex = faceIndices[i]; var face = conway.Faces[i]; var faceNormal = face.Normal; var faceCentroid = face.Centroid; ConwayPoly.Roles faceRole = conway.FaceRoles[i]; // Axes for UV mapping Vector3 xAxis = Vector3.right; Vector3 yAxis = Vector3.up; switch (uvMethod) { case PolyHydraEnums.UVMethods.FirstEdge: xAxis = face.Halfedge.Vector; yAxis = Vector3.Cross(xAxis, faceNormal); break; case PolyHydraEnums.UVMethods.BestEdge: xAxis = face.GetBestEdge().Vector; yAxis = Vector3.Cross(xAxis, faceNormal); break; case PolyHydraEnums.UVMethods.FirstVertex: yAxis = face.Centroid - face.GetVertices()[0].Position; xAxis = Vector3.Cross(yAxis, faceNormal); break; case PolyHydraEnums.UVMethods.BestVertex: yAxis = face.Centroid - face.GetBestEdge().Vertex.Position; xAxis = Vector3.Cross(yAxis, faceNormal); break; case PolyHydraEnums.UVMethods.ObjectAligned: // Align towards the highest vertex or edge midpoint (measured in the y direction) Vertex chosenVert = face.GetVertices().OrderBy(vert => vert.Position.y).First(); Halfedge chosenEdge = face.GetHalfedges().OrderBy(edge => edge.Midpoint.y).First(); Vector3 chosenPoint; if (chosenVert.Position.y > chosenEdge.Midpoint.y + 0.01f) // favour edges slightly { chosenPoint = chosenVert.Position; } else { chosenPoint = chosenEdge.Midpoint; } yAxis = face.Centroid - chosenPoint; xAxis = Vector3.Cross(yAxis, faceNormal); break; } Color32 color = CalcFaceColor(conway, colors, colorMethod, i); float faceScale = 0; foreach (var v in face.GetVertices()) { faceScale += Vector3.Distance(v.Position, faceCentroid); } faceScale /= face.Sides; var miscUV1 = new Vector4(faceScale, face.Sides, faceCentroid.magnitude, ((float)i) / faceIndices.Length); var miscUV2 = new Vector4(faceCentroid.x, faceCentroid.y, faceCentroid.z, i); var faceTris = new List <int>(); if (face.Sides > 3) { for (var edgeIndex = 0; edgeIndex < faceIndex.Count; edgeIndex++) { meshVertices.Add(faceCentroid); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); edgeUVs.Add(new Vector2(0, 0)); barycentricUVs.Add(new Vector3(0, 0, 1)); meshVertices.Add(points[faceIndex[edgeIndex]]); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); edgeUVs.Add(new Vector2(1, 1)); barycentricUVs.Add(new Vector3(0, 1, 0)); meshVertices.Add(points[faceIndex[(edgeIndex + 1) % face.Sides]]); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); edgeUVs.Add(new Vector2(1, 1)); barycentricUVs.Add(new Vector3(1, 0, 0)); meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3)); meshColors.AddRange(Enumerable.Repeat(color, 3)); miscUVs1.AddRange(Enumerable.Repeat(miscUV1, 3)); miscUVs2.AddRange(Enumerable.Repeat(miscUV2, 3)); } } else { meshVertices.Add(points[faceIndex[0]]); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); barycentricUVs.Add(new Vector3(0, 0, 1)); meshVertices.Add(points[faceIndex[1]]); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); barycentricUVs.Add(new Vector3(0, 1, 0)); meshVertices.Add(points[faceIndex[2]]); meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis)); faceTris.Add(index++); barycentricUVs.Add(new Vector3(1, 0, 0)); edgeUVs.AddRange(Enumerable.Repeat(new Vector2(1, 1), 3)); meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3)); meshColors.AddRange(Enumerable.Repeat(color, 3)); miscUVs1.AddRange(Enumerable.Repeat(miscUV1, 3)); miscUVs2.AddRange(Enumerable.Repeat(miscUV2, 3)); } if (generateSubmeshes) { switch (colorMethod) { case PolyHydraEnums.ColorMethods.ByRole: int uniqueRoleIndex = uniqueRoles.IndexOf(faceRole); submeshTriangles[uniqueRoleIndex].AddRange(faceTris); break; case PolyHydraEnums.ColorMethods.BySides: submeshTriangles[face.Sides].AddRange(faceTris); break; case PolyHydraEnums.ColorMethods.ByFaceDirection: submeshTriangles[CalcDirectionIndex(face, colors.Length - 1)].AddRange(faceTris); break; case PolyHydraEnums.ColorMethods.ByTags: if (conway.FaceTags[i].Count > 0) { string htmlColor = conway.FaceTags[i].First(t => t.Item1.StartsWith("#")).Item1; int uniqueTagIndex = uniqueTags.IndexOf(htmlColor); submeshTriangles[uniqueTagIndex + 1].AddRange(faceTris); } else { submeshTriangles[0].AddRange(faceTris); } break; } } else { meshTriangles.AddRange(faceTris); } } target.vertices = meshVertices.Select(x => Jitter(x)).ToArray(); target.normals = meshNormals.ToArray(); if (generateSubmeshes) { target.subMeshCount = submeshTriangles.Count; for (var i = 0; i < submeshTriangles.Count; i++) { target.SetTriangles(submeshTriangles[i], i); } } else { target.triangles = meshTriangles.ToArray(); } target.colors32 = meshColors.ToArray(); target.SetUVs(0, meshUVs); target.SetUVs(1, edgeUVs); target.SetUVs(2, barycentricUVs); target.SetUVs(3, miscUVs1); target.SetUVs(4, miscUVs2); target.RecalculateTangents(); return(target); }
public Mesh BuildMeshFromConwayPoly(bool forceTwosided) { //var originalFaceSides = KisTriangulate(); var target = new Mesh(); var meshTriangles = new List <int>(); var meshVertices = new List <Vector3>(); var meshNormals = new List <Vector3>(); var meshColors = new List <Color32>(); var hasNaked = _conwayPoly.HasNaked(); hasNaked = false; // TODO // for (int i = 0; i < conway.Faces.Count; i++) // { // if (conway.Faces[i].Sides > 3) // { // conway.Faces.Triangulate(i, false); // } // } // Strip down to Face-Vertex structure var points = _conwayPoly.ListVerticesByPoints(); var faceIndices = _conwayPoly.ListFacesByVertexIndices(); // Add faces int index = 0; for (var i = 0; i < faceIndices.Length; i++) { var faceIndex = faceIndices[i]; var face = _conwayPoly.Faces[i]; var faceNormal = face.Normal; Color32 color; switch (ColorMethod) { case AppearancePreset.ColorMethods.ByRole: color = faceColors[(int)_conwayPoly.FaceRoles[i]]; break; case AppearancePreset.ColorMethods.BySides: color = faceColors[face.Sides % faceColors.Length]; break; default: color = Color.red; break; } if (face.Sides > 3) { for (var edgeIndex = 0; edgeIndex < faceIndex.Count; edgeIndex++) { meshVertices.Add(face.Centroid); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[edgeIndex]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[(edgeIndex + 1) % face.Sides]]); meshTriangles.Add(index++); meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3)); meshColors.AddRange(Enumerable.Repeat(color, 3)); } } else { meshVertices.Add(points[faceIndex[0]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[1]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[2]]); meshTriangles.Add(index++); meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3)); meshColors.AddRange(Enumerable.Repeat(color, 3)); } if (hasNaked || forceTwosided) { if (faceIndex.Count > 3) { for (var edgeIndex = 0; edgeIndex < faceIndex.Count; edgeIndex++) { meshVertices.Add(face.Centroid); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[(edgeIndex + 1) % face.Sides]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[edgeIndex]]); meshTriangles.Add(index++); meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3)); meshColors.AddRange(Enumerable.Repeat(color, 3)); } } else { meshVertices.Add(points[faceIndex[0]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[2]]); meshTriangles.Add(index++); meshVertices.Add(points[faceIndex[1]]); meshTriangles.Add(index++); meshNormals.AddRange(Enumerable.Repeat(-faceNormal, faceIndex.Count)); meshColors.AddRange(Enumerable.Repeat(color, faceIndex.Count)); } } } target.vertices = meshVertices.ToArray(); target.normals = meshNormals.ToArray(); target.triangles = meshTriangles.ToArray(); target.colors32 = meshColors.ToArray(); if (hasNaked || forceTwosided) { target.RecalculateNormals(); } return(target); }