Beispiel #1
0
    /// <summary>
    ///  Sorts a set of three spherical coordinates in clockwise order
    /// </summary>
    /// <param name="s1"></param>
    /// <param name="s2"></param>
    /// <param name="s3"></param>
    /// <returns>The ordered arary of vertices in clockwise order</returns>
    public static SCoord[] SortClockwiseOrder(SCoord s1, SCoord s2, SCoord s3)
    {
        Vector3 v1 = s1.ToEuclidian();
        Vector3 v2 = s2.ToEuclidian();
        Vector3 v3 = s3.ToEuclidian();

        Vector3 centroid = (v1 + v2 + v3).normalized;
        Vector3 n        = Vector3.Cross(v2 - v1, v3 - v1);

        float w = Vector3.Dot(n, v2 - centroid);

        if (w > 0)
        {
            return(new SCoord[] { s1, s2, s3 });
        }
        return(new SCoord[] { s3, s2, s1 });
    }
Beispiel #2
0
    // 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);
        }
    }
Beispiel #3
0
 /// <summary>
 /// Gets the rotation of an object that would be on the surface of the sphere at this coordinate.
 /// </summary>
 /// <param name="coord">coordinate on the sphere</param>
 /// <returns>Rotation of an object if it was placed on the sphere at this coordinate<returns>
 public static Vector3 GetRotation(SCoord coord)
 {
     return(Quaternion.FromToRotation(Vector3.up, coord.ToEuclidian()).eulerAngles);
 }
Beispiel #4
0
 /// <summary>
 /// Gets the angle between two coordiantes on a sphere.
 /// </summary>
 /// <param name="coord1">First coordinate on the sphere. (From)</param>
 /// <param name="coord2">Second coordinate on the sphere. (To)</param>
 /// <returns>The angle representing the direction between the two coordinates in radians.</returns>
 public static float GetAngleBetween(SCoord coord1, SCoord coord2) => Mathf.Acos(Vector3.Dot(coord1.ToEuclidian(), coord2.ToEuclidian()));
Beispiel #5
0
    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();
    }
Beispiel #6
0
 /// <summary>
 /// Gets the euclidian coordinate of a point around the center of this icosphere.
 /// </summary>
 /// <param name="coordinate">Coordinate in lattitude and lnogitude relative to the spehre</param>
 /// <returns>The point at that lattitude and longitude the radius of the icosphere
 /// away from the center of the icosphere.</returns>
 public Vector3 GetPoint(SCoord coordinate) => coordinate.ToEuclidian() * radius + center;