private static float GetScaleFactor(Icosphere sphere, float edgeLength) { List <SCoord> coordinates = new List <SCoord>(sphere.Coordinates); // Compute the scaling factor to meet the target edge length // Get the distance from the pole to one of its neighbors Vector3 scaleVec1 = sphere.GetPoint(coordinates[0]); IEnumerator <SCoord> scaleNeighbors = sphere.GetNeighbors(coordinates[0]).GetEnumerator(); scaleNeighbors.MoveNext(); Vector3 scaleVec2 = sphere.GetPoint(scaleNeighbors.Current); float dist = Vector3.Distance(scaleVec1, scaleVec2); // Compute the new scale factor and set this for the sphere float sf = edgeLength / dist; return(sf); }
public void RenderSphere(Transform parentObject, Material outlineHex, Material outlinePent) { int sphereLayer = LayerMask.NameToLayer("Sphere");; foreach (SCoord tile in hexSphere.Coordinates) { // Setup new game object with generated mesh GameObject newTile = new GameObject(); MeshFilter mf = newTile.AddComponent <MeshFilter>(); MeshRenderer mr = newTile.AddComponent <MeshRenderer>(); MeshCollider mc = newTile.AddComponent <MeshCollider>(); HexIdentifier hider = newTile.AddComponent <HexIdentifier>(); //GameObjectUtility.SetStaticEditorFlags(newTile, //StaticEditorFlags.OccludeeStatic | StaticEditorFlags.OccluderStatic); // Set the standard material shader mr.material = new Material(Shader.Find("Diffuse")); // Make the mesh and render the tile RenderTile(mf.mesh, tile, hexSphere); // Move the tile to its new position and rotation newTile.transform.position += parentObject.transform.position; newTile.transform.Rotate(parentObject.transform.eulerAngles); // set hierarchy relationship newTile.transform.SetParent(parentObject); // Set Name of the tile newTile.name = "Lat " + Mathf.Round(tile.GetTheta() * Mathf.Rad2Deg * 100) / 100 + " Lon " + Mathf.Round(tile.GetPhi() * Mathf.Rad2Deg * 100) / 100; tileMap[tile] = newTile; hider.center = hexSphere.GetPoint(tile); hider.location = tile; CameraHider.AddObject(hider); newTile.layer = sphereLayer; if (hexSphere.GetDegree(tile) == 5) { mr.material = outlinePent; } else if (hexSphere.GetDegree(tile) == 6) { mr.material = outlineHex; } mc.sharedMesh = mf.mesh; } }
// Start is called before the first frame update void Start() { // Make the icosphere sphere = new Icosphere(transform.position, radius); for (int sub = 0; sub < subdivsions; sub++) { sphere = sphere.SubdivideSphere(); } // Make the faces of the icosphere foreach (SCoord coord in sphere.Coordinates) { // Get the 3d coordinate of the sphere Vector3 point = sphere.GetPoint(coord); // Get the rotation of the face to make it tangent to the sphere Vector3 rotation = SCoord.GetRotation(coord); // Get the kind of object GameObject newObj = null; int degree = sphere.GetDegree(coord); if (degree == 5) { newObj = Instantiate(pentagonPrefab); } else { newObj = Instantiate(hexagonPrefab); } // Place and rotate object tangent to the sphere newObj.transform.eulerAngles = rotation; newObj.transform.position = point; newObj.transform.SetParent(this.transform); // Rotate the face to be line up correclty IEnumerator <SCoord> neighbors = sphere.GetNeighbors(coord).GetEnumerator(); neighbors.MoveNext(); SCoord neighbor = neighbors.Current; Vector3 targetVec = Vector3.ProjectOnPlane(neighbor.ToEuclidian() - coord.ToEuclidian(), newObj.transform.up).normalized; float angle = Mathf.Acos(Vector3.Dot(newObj.transform.right.normalized, targetVec)); if (float.IsNaN(angle)) { angle = 180; } Vector3 cross = Vector3.Cross(newObj.transform.right.normalized, targetVec); if (Vector3.Dot(newObj.transform.up.normalized, cross) < 0) { angle *= -1; } angle *= 180 / Mathf.PI; Debug.Log(angle); newObj.transform.Rotate(0, angle, 0, Space.Self); tiles.Add(coord, newObj); } }
public static void RenderTile(Mesh mesh, SCoord tileCenter, Icosphere hexSphere) { // Make a linked list of the coordinate's neighbors LinkedList <SCoord> neighbors; // hexes are not triangles neighbors = new LinkedList <SCoord>(hexSphere.GetNeighbors(tileCenter)); // Make list of vertices List <Vector3> vertices = new List <Vector3>(neighbors.Count + 1); // Make list of normals for each vertex List <Vector3> normals = new List <Vector3>(neighbors.Count + 1); // Make list of UV coordinates for each vertex List <Vector2> uvLocations = new List <Vector2>(neighbors.Count + 1); // Setup lookup table for vertices Dictionary <SCoord, int> keyLookup = new Dictionary <SCoord, int>(); keyLookup.Add(tileCenter, keyLookup.Count); uvLocations.Add(new Vector2(0.5f, 0.5f)); vertices.Add(hexSphere.GetPoint(tileCenter)); normals.Add(tileCenter.ToEuclidian()); float radPerVertex = Mathf.PI * 2 / neighbors.Count; SCoord startVertex = neighbors.First.Value; SCoord source = startVertex; neighbors.RemoveFirst(); // Get the order of neighbors (forward or backward just wrapping around center) LinkedList <SCoord> orderedNeighbors = new LinkedList <SCoord>(); orderedNeighbors.AddLast(startVertex); // Calculate the teselated edges of the hexagon/pentagon while (neighbors.Count > 1) { // Find the next SCoord in the sequence of neighbors (neighbor to origin that is // adjacent to the previous neighbor) LinkedListNode <SCoord> nextVertex = neighbors.First; while (!new List <SCoord>(hexSphere.GetNeighbors(nextVertex.Value)).Contains(source)) { nextVertex = nextVertex.Next; } orderedNeighbors.AddLast(nextVertex.Value); // Save current vertex as previous vertex source = nextVertex.Value; // Remove current vertex so it is not checked again neighbors.Remove(nextVertex); } // Finish list of ordered neighbors orderedNeighbors.AddLast(neighbors.First.Value); foreach (SCoord n in orderedNeighbors) { keyLookup.Add(n, keyLookup.Count); } List <SCoord> neighborList = new List <SCoord>(orderedNeighbors); List <int> triangleList = new List <int>(); for (int idx = 0; idx < neighborList.Count; idx++) { // Get the centroid of the three adjacent tiles SCoord vert = SCoord.GetCentroid(tileCenter, neighborList[idx], neighborList[(idx + 1) % neighborList.Count]); // Sort the coordinates in the correct order so the face is visible SCoord[] triangleCoords = SCoord.SortClockwiseOrder(tileCenter, neighborList[idx], neighborList[(idx + 1) % neighborList.Count]); // Add the vertex vertices.Add(hexSphere.GetPoint(vert)); // Add the normal vector of the vertex normals.Add(vert.ToEuclidian()); // Add UV coordinate for this vertex Vector2 uv = new Vector2(0.5f + Mathf.Cos(radPerVertex * idx) * 0.5f, 0.5f + Mathf.Sin(radPerVertex * idx) * 0.5f); uvLocations.Add(new Vector2(0.5f + Mathf.Cos(radPerVertex * idx) * 0.5f, 0.5f + Mathf.Sin(radPerVertex * idx) * 0.5f)); // Add the triangles (set of three vertices) triangleList.Add(keyLookup[triangleCoords[2]]); triangleList.Add(keyLookup[triangleCoords[1]]); triangleList.Add(keyLookup[triangleCoords[0]]); } // Flatten out the center of the hex so it doesn't arch out Vector3 flatCenter = Vector3.zero; for (int i = 1; i < vertices.Count; i++) { flatCenter += vertices[i]; } flatCenter /= (vertices.Count - 1); vertices[0] = flatCenter; // assign values to mesh mesh.vertices = vertices.ToArray(); mesh.normals = normals.ToArray(); mesh.triangles = triangleList.ToArray(); mesh.uv = uvLocations.ToArray(); }