Ejemplo n.º 1
0
    public void spawnTree(Hex hex, float heightSeed)
    {
        GameObject newTree      = Instantiate(treePrefab);
        Vector2    treePosition = Random.insideUnitCircle * this.getHexSize();

        treePosition += HexMathHelper.hexToWorldCoords(hex.getPosition(), this.getHexSize());
        float   spawnHeight = TerrainHelper.getHeight(heightSeed, treePosition, hex, this.getHexSize(), elevatedHeightmap, mountainHeightmap);
        float   yScale      = Random.Range(0.05f, 0.08f);
        Vector3 newScale    = newTree.transform.localScale;

        newScale.y = yScale;
        newTree.transform.localScale = newScale;
        newTree.transform.position   = new Vector3(treePosition.x, treePosition.y, spawnHeight - 0.12f);
    }
Ejemplo n.º 2
0
    public static List <Vector3> getRiversMesh(List <List <Vector2> > rivers, float riverDensity, float hexSize, float heightSeed,
                                               Texture2D mountainHeightmap, Texture2D elevatedHeightmap, Map map)
    {
        Debug.Log(rivers.Count);
        float          perlinNoiseX     = 15.004f;
        float          perlinNoiseStep  = 0.1f;
        List <Vector3> allRriversPoints = new List <Vector3>();
        float          riverThickness   = riverDensity;

        List <Vector3> vertices  = new List <Vector3>();
        List <int>     triangles = new List <int>();
        List <Color32> colours   = new List <Color32>();

        foreach (List <Vector2> river in rivers)
        {
            Debug.Log(river[0]);
            Debug.Log(river.Count);
            List <Vector3> riverShorePoints = new List <Vector3>();
            List <Vector3> riverPoints      = new List <Vector3>();
            for (int i = 0; i < river.Count - 1; i++)
            {
                Vector2 firstRiverPoint  = getHexRiverPoint(river[i], hexSize, map);
                Vector2 secondRiverPoint = getHexRiverPoint(river[i + 1], hexSize, map);
                Vector2 direction        = secondRiverPoint - firstRiverPoint;
                Vector2 normal           = new Vector2(-direction.y, direction.x).normalized;
                int     pointsNumber     = Mathf.CeilToInt(direction.magnitude / riverDensity);

                for (int pointIndex = 0; pointIndex < pointsNumber; pointIndex++)
                {
                    Vector3 derivativeDirection;
                    float   t                = pointIndex * 1.0f / pointsNumber;
                    Vector2 newPoint         = Vector2.Lerp(firstRiverPoint, secondRiverPoint, t);
                    float   scaleShiftFactor = pointIndex <= pointsNumber / 2 ? pointIndex * 2.0f / pointsNumber : (pointsNumber - pointIndex) * 2.0f / pointsNumber;
                    newPoint = Vector2.Lerp(firstRiverPoint, secondRiverPoint, t);
                    float shift = Mathf.PerlinNoise(perlinNoiseX, riverPoints.Count * perlinNoiseStep) * 0.4f - 0.2f;
                    newPoint += normal * shift * scaleShiftFactor;

                    if (i != 0 || pointIndex != 0)
                    {
                        if (pointIndex == 0)
                        {
                            float   nextPointT           = (pointIndex + 1) * 1.0f / pointsNumber;
                            Vector2 nextPoint            = Vector2.Lerp(firstRiverPoint, secondRiverPoint, nextPointT);
                            float   nextScaleShiftFactor = pointIndex + 1 <= pointsNumber / 2 ? (pointIndex + 1) * 2.0f / pointsNumber : (pointsNumber - pointIndex - 1) * 2.0f / pointsNumber;
                            float   nextPointShift       = Mathf.PerlinNoise(perlinNoiseX, (riverPoints.Count + 1) * perlinNoiseStep) * 0.4f - 0.2f;
                            nextPoint += normal * nextPointShift * nextScaleShiftFactor;

                            Vector2 previousPoint = riverPoints[riverPoints.Count - 1];

                            float derivativeT = 0.5f;
                            derivativeDirection = 2f * (1f - derivativeT) * (newPoint - previousPoint) + 2f * derivativeT * (nextPoint - newPoint);

                            newPoint = Vector2.Lerp(Vector2.Lerp(previousPoint, newPoint, 0.5f), Vector2.Lerp(newPoint, nextPoint, 0.5f), 0.5f);
                        }
                        else
                        {
                            Vector2 previousPoint = riverPoints[riverPoints.Count - 1];
                            derivativeDirection = newPoint - previousPoint;
                        }

                        Vector3 perpendicular         = new Vector3(-derivativeDirection.y, derivativeDirection.x).normalized;
                        Vector3 actualNewPoint        = new Vector3(newPoint.x, newPoint.y, 0);
                        Vector3 firstShorePoint       = actualNewPoint + perpendicular * riverThickness;
                        Hex     firstPointHex         = map.getHex(HexMathHelper.worldToHexCoords(firstShorePoint, hexSize));
                        float   firstShorePointHeight = TerrainHelper.getHeight(heightSeed, firstShorePoint, firstPointHex, hexSize, elevatedHeightmap, mountainHeightmap);
                        firstShorePoint += new Vector3(0, 0, firstShorePointHeight);

                        Vector3 secondShorePoint       = actualNewPoint - perpendicular * riverThickness;
                        Hex     secondPointHex         = map.getHex(HexMathHelper.worldToHexCoords(secondShorePoint, hexSize));
                        float   secondShorePointHeight = TerrainHelper.getHeight(heightSeed, secondShorePoint, secondPointHex, hexSize, elevatedHeightmap, mountainHeightmap);
                        secondShorePoint += new Vector3(0, 0, secondShorePointHeight);

                        riverShorePoints.Add(firstShorePoint);
                        riverShorePoints.Add(secondShorePoint);
                    }

                    Hex   newPointHex    = map.getHex(HexMathHelper.worldToHexCoords(newPoint, hexSize));
                    float newPointHeight = TerrainHelper.getHeight(heightSeed, newPoint, newPointHex, hexSize, elevatedHeightmap, mountainHeightmap);
                    riverPoints.Add(new Vector3(newPoint.x, newPoint.y, newPointHeight));
                }
            }
            Vector3 veryFirstShorePoint     = riverShorePoints[0];
            Vector3 verySecondShorePoint    = riverShorePoints[1];
            Vector3 firstPointShift         = new Vector2(riverPoints[0].x, riverPoints[0].y) - new Vector2(riverPoints[1].x, riverPoints[1].y);
            Vector3 missingFirstPoint       = verySecondShorePoint + firstPointShift;
            float   missingFirstPointHeight = TerrainHelper.getHeight(heightSeed, missingFirstPoint,
                                                                      map.getHex(HexMathHelper.worldToHexCoords(missingFirstPoint, hexSize)), hexSize, elevatedHeightmap, mountainHeightmap);
            missingFirstPoint += new Vector3(0, 0, missingFirstPointHeight);
            riverShorePoints.Insert(0, missingFirstPoint);

            Vector3 missingSecondPoint       = veryFirstShorePoint + firstPointShift;
            float   missingSecondPointHeight = TerrainHelper.getHeight(heightSeed, missingSecondPoint,
                                                                       map.getHex(HexMathHelper.worldToHexCoords(missingSecondPoint, hexSize)), hexSize, elevatedHeightmap, mountainHeightmap);
            missingSecondPoint += new Vector3(0, 0, missingSecondPointHeight);
            riverShorePoints.Insert(0, missingSecondPoint);

            riverPoints.AddRange(riverShorePoints);
            //allRriversPoints.AddRange(riverPoints);
            allRriversPoints.AddRange(riverShorePoints);
            for (int i = 0, vertextIndex = 0; i <= riverShorePoints.Count - 4; i += 2, vertextIndex += 6)
            {
                vertices.Add(riverShorePoints[i + 2]);
                vertices.Add(riverShorePoints[i + 1]);
                vertices.Add(riverShorePoints[i]);

                vertices.Add(riverShorePoints[i + 3]);
                vertices.Add(riverShorePoints[i + 1]);
                vertices.Add(riverShorePoints[i + 2]);

                for (int triangleIndex = vertextIndex; triangleIndex < vertextIndex + 6; triangleIndex++)
                {
                    triangles.Add(triangleIndex);
                    colours.Add(Color.blue);
                }
            }
        }

        Mesh mesh = new Mesh();

        mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
        mesh.name        = "Rivers";
        mesh.vertices    = vertices.ToArray();
        mesh.triangles   = triangles.ToArray();
        mesh.colors32    = colours.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        return(allRriversPoints);
    }
Ejemplo n.º 3
0
    public MapMesh generateTerrain(Map map, List <List <Vector2> > riverPoints, TriangleNet.Mesh mapTriangulation)
    {
        MapMesh terrain = new MapMesh();

        List <Vector3> landVertices       = new List <Vector3>();
        List <Vector3> oceanVertices      = new List <Vector3>();
        List <Vector3> innerWaterVertices = new List <Vector3>();
        Dictionary <Vector2, float> mapVerticesHeights = new Dictionary <Vector2, float>();

        foreach (Triangle triangle in mapTriangulation.Triangles)
        {
            List <MapVertex> mapVertices = triangle.vertices
                                           .Select(vertex => vertex is MapVertex ? (MapVertex)vertex : convertToMapVertex(vertex))
                                           .Reverse()
                                           .ToList();

            List <Vector3> underWaterShifts = new List <Vector3>(new Vector3[3]);

            List <bool> needsShoreAdjustments = new List <bool>(new bool[3]);

            if (mapVertices.Any(mapVertice => mapVertice.hex == null))
            {
                for (int i = 0; i < mapVertices.Count; i++)
                {
                    if (mapVertices[i].hex != null)
                    {
                        needsShoreAdjustments[i] = true;
                    }
                }
            }

            MapVertex shoreMapVertex = mapVertices.FirstOrDefault(mapVertex => mapVertex.hex != null && (mapVertex.hex.biome == null || mapVertex.hex.biome.name != "Fresh lake"));
            if (shoreMapVertex != null)
            {
                Vector2 shoreCenter = HexMathHelper.hexToWorldCoords(new Vector2(shoreMapVertex.hex.x, shoreMapVertex.hex.y), this.hexSize);
                //if shore triangle push it underwater to create shore slope
                for (int i = 0; i < mapVertices.Count; i++)
                {
                    if (mapVertices[i].hex == null)
                    {
                        underWaterShifts[i]  = (new Vector2((float)mapVertices[i].x, (float)mapVertices[i].y) - shoreCenter).normalized * 0.3f;
                        underWaterShifts[i] += new Vector3(0, 0, 0.03f);
                    }
                }
            }

            List <Vector3> triangleVertices = new List <Vector3>();
            for (int i = 0; i < mapVertices.Count; i++)
            {
                float   height    = TerrainHelper.getHeight(heightSeed, mapVertices[i], this.hexSize, elevatedHeightmap, mountainHeightmap);
                Vector3 newVertex = mapVertices[i].toVector3() + underWaterShifts[i] + new Vector3(0, 0, height);

                if (!mapVerticesHeights.ContainsKey(newVertex) && needsShoreAdjustments[i])
                {
                    newVertex.z = Random.Range(0.08f, 0.13f);
                    mapVerticesHeights[newVertex] = newVertex.z;
                }

                if (mapVertices[i].isRiver && (mapVertices[i].hex == null || !mapVertices[i].hex.hasTag(RiverHelper.FRESH_LAKE_TAG)))
                {
                    newVertex += TerrainHelper.getRiverHeightAdjustment(newVertex);
                }

                triangleVertices.Add(newVertex);
            }

            if (mapVertices.All(mapVertex => mapVertex.hex == null))
            {
                oceanVertices.AddRange(triangleVertices);
            }
            else if (mapVertices.All(mapVertex => mapVertex.isRiver))
            {
                innerWaterVertices.AddRange(triangleVertices);
            }
            else if (mapVertices.All(mapVertex => mapVertex.hex != null && mapVertex.hex.hasTag(RiverHelper.FRESH_LAKE_TAG)))
            {
                innerWaterVertices.AddRange(triangleVertices);
            }
            else
            {
                landVertices.AddRange(triangleVertices);
            }
        }

        //smooth shore
        for (int i = 0; i < landVertices.Count; i++)
        {
            Vector3 vertex = landVertices[i];
            if (mapVerticesHeights.ContainsKey(vertex))
            {
                vertex.z        = mapVerticesHeights[landVertices[i]];
                landVertices[i] = vertex;
            }
        }

        terrain.landMesh       = this.createMesh("Land", landVertices);
        terrain.oceanMesh      = this.createMesh("Ocean", oceanVertices);
        terrain.innerWaterMesh = this.createMesh("Lakes and Rivers", innerWaterVertices);

        return(terrain);
    }