static public int CompareByZReverse(TriFace a, TriFace b) { if (a.vc.z == b.vc.z) { return(0); } return((a.vc.z < b.vc.z) ? 1 : -1); }
static public int CompareByZ(TriFace a, TriFace b) { if (a.vc.z == b.vc.z) { return(0); } return((a.vc.z < b.vc.z) ? -1 : 1); }
private int?FindAdjacentFace(int vertexAIndex, int vertexBIndex, List <int> nGonTriFaces, int currentTriFaceIndex) { foreach (int triFaceIndex in nGonTriFaces) { if (triFaceIndex == currentTriFaceIndex) { continue; } TriFace triangle = TriFaces[triFaceIndex]; if ((triangle.A == vertexAIndex || triangle.B == vertexAIndex || triangle.C == vertexAIndex) && (triangle.A == vertexBIndex || triangle.B == vertexBIndex || triangle.C == vertexBIndex)) { return(triFaceIndex); } } return(null); }
public Dictionary <int, List <int> > TriFacesGroupedByVertex() { Dictionary <int, List <int> > vertToFaces = new Dictionary <int, List <int> >(); for (int i = 0; i < TriFaces.Count; i++) { TriFace triangle = TriFaces[i]; if (vertToFaces.ContainsKey(triangle.A)) { vertToFaces[triangle.A].Add(i); } else { vertToFaces.Add(triangle.A, new List <int> { i }); } if (vertToFaces.ContainsKey(triangle.B)) { vertToFaces[triangle.B].Add(i); } else { vertToFaces.Add(triangle.B, new List <int> { i }); } if (vertToFaces.ContainsKey(triangle.C)) { vertToFaces[triangle.C].Add(i); } else { vertToFaces.Add(triangle.C, new List <int> { i }); } } return(vertToFaces); }
protected override void OnPopulateMesh(VertexHelper vh) { var recttransform = gameObject.transform as RectTransform; var rect = recttransform.rect; rect.xMin += margin.left; rect.xMax -= margin.right; rect.yMin += margin.bottom; rect.yMax -= margin.top; // Debug.Log("rect:" + rect.ToString() + "\ncenter:" + rect.center.ToString()); if (sourceMesh == null) { PolulateQuad(vh, rect); return; } var meshsize = sourceMesh.bounds.size; // Calc scale var scale = Vector3.one; switch (scalingMode) { case ScalingMode.Stretch: scale.x = rect.width / meshsize.x; scale.y = rect.height / meshsize.y; scale.z = Mathf.Min(scale.x, scale.y); break; case ScalingMode.Fit: scale.x = rect.width / meshsize.x; scale.y = rect.height / meshsize.y; scale.x = Mathf.Min(scale.x, scale.y); scale.y = scale.x; scale.z = scale.x; break; case ScalingMode.NoScale: scale = Vector3.one; break; } float extraScaleZ = keepMeshZ? 1.0f : 0.0f; // Debug.Log("rect w:" + rect.width + ",h:" + rect.height); // Debug.Log("bounds:(w:" + meshsize.x + ",h:" + meshsize.y); // Debug.Log("scale:" + scale.ToString()); // Calc offsets var meshcenter = keepMeshOrigin ? Vector3.zero : sourceMesh.bounds.center; var rectoffset = Vector3.zero; rectoffset.x = rect.center.x; rectoffset.y = rect.center.y; // vh.Clear(); // Vertices var vcount = sourceMesh.vertexCount; UIVertex uiv = UIVertex.simpleVert; var uiverts = new List <UIVertex>(vcount); var vertposs = new List <Vector3>(vcount); for (int i = 0; i < vcount; i++) { var pos = sourceMesh.vertices[i] - meshcenter; pos.Scale(scale); pos += rectoffset; vertposs.Add(pos); pos.z *= extraScaleZ; uiv.position = pos; uiv.normal = sourceMesh.normals[i]; uiv.tangent = sourceMesh.tangents[i]; if (useMeshVertexColor) { uiv.color = (i < sourceMesh.colors.Length) ? sourceMesh.colors[i] : Color.black; uiv.color *= color; } else { uiv.color = color; } uiv.uv0 = (i < sourceMesh.uv.Length) ? sourceMesh.uv[i] : Vector2.zero; uiv.uv1 = (i < sourceMesh.uv2.Length) ? sourceMesh.uv2[i] : Vector2.zero; uiv.uv2 = (i < sourceMesh.uv3.Length) ? sourceMesh.uv3[i] : Vector2.zero; uiv.uv3 = (i < sourceMesh.uv4.Length) ? sourceMesh.uv4[i] : Vector2.zero; uiverts.Add(uiv); } // Faces int tricount = sourceMesh.triangles.Length; var indices = new List <int>(tricount); if (!removeBackFace && (sortTriangles == SortMode.None)) { // No backface culling and z sort indices.AddRange(sourceMesh.triangles); } else { // Some mesh processing needed var faces = new List <TriFace>(tricount / 3); var triface = new TriFace(); if (removeBackFace) { // Backface culling for (int i = 0; i < tricount; i += 3) { int i0 = sourceMesh.triangles[i]; int i1 = sourceMesh.triangles[i + 1]; int i2 = sourceMesh.triangles[i + 2]; var v0 = vertposs[i0]; var v1 = vertposs[i1]; var v2 = vertposs[i2]; var v01 = v1 - v0; var v02 = v2 - v0; var n = Vector3.Cross(v01, v02); if (n.z < 0.0f) // Front face normal is (0,0,-1) { triface.SetFace(i0, i1, i2); triface.SetVertices(v0, v1, v2); faces.Add(triface); } } } else { // Use all triangles for (int i = 0; i < tricount; i += 3) { triface.SetFace( sourceMesh.triangles[i], sourceMesh.triangles[i + 1], sourceMesh.triangles[i + 2] ); triface.SetVertices( vertposs[triface.i0], vertposs[triface.i1], vertposs[triface.i2] ); faces.Add(triface); } } // Sorting. Camera's foward is (0,0,1) switch (sortTriangles) { case SortMode.Normal: // Descending order faces.Sort(TriFace.CompareByZReverse); break; case SortMode.Reverse: // Ascending order faces.Sort(TriFace.CompareByZ); break; // case SortMode.None: // default: // break; } // Add triangle foreach (var f in faces) { indices.Add(f.i0); indices.Add(f.i1); indices.Add(f.i2); } } vh.AddUIVertexStream(uiverts, indices); }
public Tile(TriFace face, TileType type) { this.face = face; this.type = type; }
public override void GenerateUVs() { for (int i = 0; i < Vertices.Count; i++) { Vertex vertex = Vertices[i]; vertex.UV = new Vector2(0.5f + Mathf.Atan2(vertex.Position.z, vertex.Position.x) / (2f * Mathf.PI), 0.5f + Mathf.Asin(vertex.Position.y) / Mathf.PI); Vertices[i] = vertex; } //detect... Dictionary <int, int> visited = new Dictionary <int, int>(); int vertexIndex = Vertices.Count - 1; List <int> wrapped = new List <int>(); for (int i = 0; i < TriFaces.Count; i++) { Vector3 texA = Vertices[TriFaces[i].A].UV; Vector3 texB = Vertices[TriFaces[i].B].UV; Vector3 texC = Vertices[TriFaces[i].C].UV; Vector3 texNormal = Vector3.Cross(texB - texA, texC - texA); if (texNormal.z > 0) { wrapped.Add(i); } } //...and fix foreach (int i in wrapped) { int ta = TriFaces[i].A; int tb = TriFaces[i].B; int tc = TriFaces[i].C; Vertex A = Vertices[ta]; Vertex B = Vertices[tb]; Vertex C = Vertices[tc]; if (A.UV.x < 0.25f) { int tempA = ta; if (!visited.TryGetValue(ta, out tempA)) { A.UV.x += 1; Vertices.Add(A); vertexIndex++; visited[ta] = vertexIndex; tempA = vertexIndex; } ta = tempA; } if (B.UV.x < 0.25f) { int tempB = tb; if (!visited.TryGetValue(tb, out tempB)) { B.UV.x += 1; Vertices.Add(B); vertexIndex++; visited[tb] = tempB = vertexIndex; } tb = tempB; } if (C.UV.x < 0.25f) { int tempC = tc; if (!visited.TryGetValue(tc, out tempC)) { C.UV.x += 1; Vertices.Add(C); vertexIndex++; visited[tc] = tempC = vertexIndex; } tc = tempC; } TriFaces[i] = new TriFace(ta, tb, tc); } //fix polar UVs Vertex north = Vertices.Find(v => v.Position.y == 1); Vertex south = Vertices.Find(v => v.Position.y == -1); int northIndex = Vertices.IndexOf(north); int southIndex = Vertices.IndexOf(south); vertexIndex = Vertices.Count - 1; for (int i = 0; i < TriFaces.Count; i++) { if (TriFaces[i].A == northIndex) { Vertex B = Vertices[TriFaces[i].B]; Vertex C = Vertices[TriFaces[i].C]; Vertex newNorth = north; newNorth.UV.x = (B.UV.x + C.UV.x) / 2; vertexIndex++; Vertices.Add(newNorth); TriFaces[i] = new TriFace(vertexIndex, TriFaces[i].B, TriFaces[i].C); } else if (TriFaces[i].A == southIndex) { Vertex B = Vertices[TriFaces[i].B]; Vertex C = Vertices[TriFaces[i].C]; Vertex newSouth = south; vertexIndex++; newSouth.UV.x = (B.UV.x + C.UV.x) / 2; Vertices.Add(newSouth); TriFaces[i] = new TriFace(vertexIndex, TriFaces[i].B, TriFaces[i].C); } } }
public ProceduralIcosphere Truncated() { ProceduralIcosphere truncated = new ProceduralIcosphere(); Dictionary <int, List <int> > triFacesGroupedByVertex = TriFacesGroupedByVertex(); int originalVertexCount = Vertices.Count; //originalVertexCount = 2; List <Vertex> dualVertices = TriFaces.Select(t => new Vertex(t.Centroid(Vertices))).ToList(); Dictionary <int, Vertex> midPointCache = new Dictionary <int, Vertex>(); int hexCount = 0; int pentCount = 0; //build new n-gons from each vertex in the original shape for (int vertexIndex = 0; vertexIndex < originalVertexCount; vertexIndex++) { List <int> vertexTriFaces = triFacesGroupedByVertex[vertexIndex]; if (vertexTriFaces.Count == 6) { hexCount++; } else { pentCount++; } Vertex nGonCentreVertex = FindNgonCentre(vertexTriFaces, dualVertices); //for each of the TriFaces connected to this vertex for (int j = vertexTriFaces.Count - 1; j >= 0; j--) { int triIndex = vertexTriFaces[j]; TriFace triangle = TriFaces[triIndex]; List <int> otherVerts = new List <int> { triangle.A, triangle.B, triangle.C }; //sort the triangle- ORIGINAL CODE TRANSCRIBED FROM RUST - DOESN'T WORK //otherVerts.Remove(vertexIndex); //TriFace sortedTriangle = new TriFace(vertexIndex, otherVerts[0], otherVerts[1]); //ROTATE the triangle until the first elelemtn is the right one works while (otherVerts[0] != vertexIndex) { int first = otherVerts[0]; otherVerts.RemoveAt(0); otherVerts.Add(first); } TriFace sortedTriangle = new TriFace(otherVerts.ToArray()); Vertex newPoint = dualVertices[triIndex]; Vertex midABPoint = GetMidPoint(sortedTriangle.A, sortedTriangle.B, vertexTriFaces, triIndex, newPoint, dualVertices, midPointCache); Vertex midACPoint = GetMidPoint(sortedTriangle.A, sortedTriangle.C, vertexTriFaces, triIndex, newPoint, dualVertices, midPointCache); int nGonCentreIndex = truncated.AddVertex(nGonCentreVertex); int newPointIndex = truncated.AddVertex(newPoint); int midABIndex = truncated.AddVertex(midABPoint); int midACIndex = truncated.AddVertex(midACPoint); truncated.TriFaces.Add(new TriFace(newPointIndex, midACIndex, nGonCentreIndex)); truncated.TriFaces.Add(new TriFace(midABIndex, newPointIndex, nGonCentreIndex)); } } Debug.Log($"Total hexagons: {hexCount}"); Debug.Log($"Total pentagons: {pentCount}"); return(truncated); }