// Update is called once per frame void Update() { HexSphere hexSphere = sphere.GetSphere(); Icosphere gameSphere = hexSphere.GetHexMap(); if (gameSphere == null) { return; } if (Input.GetButtonDown("Select")) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, Mathf.Infinity, LayerMask.GetMask("Sphere"))) { if (outlineHighlight != null) { GameObject.Destroy(outlineHighlight); } GameObject obj = hit.collider.gameObject; HexIdentifier hex = obj.GetComponent <HexIdentifier>(); if (hex != null) { selected = hex.location; float rad = gameSphere.Radius; gameSphere.SetRadius(rad + 0.001f); outlineHighlight = new GameObject(); outlineHighlight.transform.position += sphere.transform.position; outlineHighlight.transform.Rotate(sphere.transform.eulerAngles); outlineHighlight.name = "Outline Highlight"; MeshFilter mf = outlineHighlight.AddComponent <MeshFilter>(); MeshRenderer mr = outlineHighlight.AddComponent <MeshRenderer>(); mr.material = new Material(Shader.Find("Transparent/Diffuse")); HexSphere.RenderTile(mf.mesh, selected, gameSphere); if (new List <SCoord>(gameSphere.GetNeighbors(selected)).Count == 5) { mr.material.SetTexture("_MainTex", pentHighlight); } else { mr.material.SetTexture("_MainTex", hexHighlight); } gameSphere.SetRadius(rad); } } } }
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); }
// 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(); }