Пример #1
0
        private void SetRegions()
        {
            Dictionary <Vector2Int, Vertex> posToVertex = new Dictionary <Vector2Int, Vertex>();
            List <Region> regions = new List <Region>();

            foreach (Vector2 sitePos in voronoi.SiteCoords())
            {
                List <Vertex> vertices = new List <Vertex>();
                foreach (Vector2Int vertPos in MathVert.ToVector2Int(voronoi.Region(sitePos)))
                {
                    //Drawer.DrawHLine(edgePos, Color.blue);
                    if (!posToVertex.ContainsKey(vertPos))
                    {
                        posToVertex.Add(vertPos, new Vertex(vertPos));
                    }
                    vertices.Add(posToVertex[vertPos]);
                }

                Region region = new Region(sitePos, vertices.ToArray());
                siteToRegion[sitePos] = region;
                regions.Add(region);
            }

            foreach (Vector2 site in voronoi.SiteCoords())
            {
                foreach (Vector2 nSite in voronoi.NeighborSitesForSite(site))
                {
                    siteToRegion[site].neighbours.Add(siteToRegion[nSite]);
                }
            }

            this.regions        = regions.ToArray();
            RegionsInfo.regions = this.regions;
            RegionsInfo.UpdateRegionsMap();
        }
Пример #2
0
    private List <SuperRegion> MakeTerrainRegions(List <Vector2> poisson, Voronoi voronoi)
    {
        var regions = new List <SuperRegion>();

        foreach (var regionCentre in poisson)
        {
            var x = (int)regionCentre.x;
            var y = (int)regionCentre.y;

            var height = GetNoise(x, y, baseScale, baseOffset);

            var biome =
                height > 0.75f ? SuperBiome.Mountain :
                height < 0.3f ? SuperBiome.Lake :
                SuperBiome.Plains;

            var points = voronoi.Region(regionCentre);

            var bounds = GetBounds(points);

            var v = new Voronoi(points, null, bounds);

            regions.Add(new SuperRegion
            {
                Centre     = regionCentre,
                Points     = points,
                Bounds     = bounds,
                Triangles  = v.Triangles(),
                Biome      = biome,
                Neighbours = voronoi.NeighborSitesForSite(regionCentre)
            });
        }

        return(regions);
    }
Пример #3
0
    void Update()
    {
        List <Vector2f> points = new List <Vector2f>();

        // prepare for Fortunes algorithm and clear neighbours
        foreach (GinelliController sheep in sheepList)
        {
            // prepare data for Voronoi
            Vector2 point = new Vector2(sheep.transform.position.x, sheep.transform.position.z);
            points.Add(new Vector2f(point.x, point.y, sheep.id));
        }

        // get metric neighbours
        List <GinelliController>[] metricNeighbours = new List <GinelliController> [sheepList.Count];
        foreach (GinelliController sheep in sheepList)
        {
            metricNeighbours[sheep.id] = new List <GinelliController>();
        }
        GinelliController firstSheep, secondSheep;

        for (int i = 0; i < sheepList.Count; i++)
        {
            firstSheep = sheepList[i];

            for (int j = i + 1; j < sheepList.Count; j++)
            {
                secondSheep = sheepList[j];

                // dist?
                if ((firstSheep.transform.position - secondSheep.transform.position).sqrMagnitude < GM.r_o2)
                {
                    metricNeighbours[firstSheep.id].Add(secondSheep);
                    metricNeighbours[secondSheep.id].Add(firstSheep);
                }
            }
        }
        foreach (GinelliController sheep in sheepList)
        {
            sheep.metricNeighbours = metricNeighbours[sheep.id];
        }

        // voronoi neighbours
        Rectf   bounds  = new Rectf(0f, 0f, GM.fieldSize, GM.fieldSize); // bounds actually irrelevant as Fortunes algoritghm does not use them
        Voronoi voronoi = new Voronoi(points, bounds);

        foreach (Vector2f pt in points)
        {
            GinelliController        sheep             = sheepList[pt.id];
            List <GinelliController> voronoiNeighbours = new List <GinelliController>();
            foreach (Vector2f neighbourPt in voronoi.NeighborSitesForSite(pt))
            {
                GinelliController neighbour = sheepList[neighbourPt.id];
                voronoiNeighbours.Add(neighbour);
            }
            sheep.voronoiNeighbours = voronoiNeighbours;
        }
    }
Пример #4
0
    private List <BiomeRegion> MakeBiomes(List <Vector2> poisson, Voronoi voronoi)
    {
        var regions = new List <BiomeRegion>();

        foreach (var regionCentre in poisson)
        {
            var x = (int)regionCentre.x;
            var y = (int)regionCentre.y;

            var superBiome = GetSuperBiomesAt(regionCentre.x, regionCentre.y).OrderBy(b => b.Proportion).LastOrDefault();

            Biome biome;

            if (superBiome != null && superBiome.BiomeDescriptor.Biome == SuperBiome.Lake)
            {
                biome = Biome.Lake;
            }
            else if (superBiome != null && superBiome.BiomeDescriptor.Biome == SuperBiome.Mountain)
            {
                biome = Biome.Mountain;
            }
            else
            {
                var temp = GetNoise(x, y, tempScale, tempOffset);
                var rain = GetNoise(x, y, rainScale, rainOffset);

                biome = GetBiome(rain, temp);
            }

            var points = voronoi.Region(regionCentre);

            var bounds = GetBounds(points);

            var v = new Voronoi(points, null, bounds);

            regions.Add(new BiomeRegion
            {
                Centre     = regionCentre,
                Points     = points,
                Bounds     = bounds,
                Triangles  = v.Triangles(),
                Biome      = biome,
                Neighbours = voronoi.NeighborSitesForSite(regionCentre)
            });
        }

        return(regions);
    }
Пример #5
0
    private void UpdateNeighbours()
    {
        List <Vector2f> points = new List <Vector2f>();

        // prepare for Fortunes algorithm and clear neighbours
        foreach (SheepController sheep in sheepList)
        {
            sheep.metricNeighbours.Clear();
            sheep.voronoiNeighbours.Clear();

            points.Add(new Vector2f(sheep.transform.position.x, sheep.transform.position.z, sheep.id));
        }

        // get metric neighbours
        SheepController firstSheep, secondSheep;

        for (int i = 0; i < sheepList.Count; i++)
        {
            firstSheep = sheepList[i];

            for (int j = i + 1; j < sheepList.Count; j++)
            {
                secondSheep = sheepList[j];

                // dist?
                if ((firstSheep.transform.position - secondSheep.transform.position).sqrMagnitude < firstSheep.r_o2)
                {
                    firstSheep.metricNeighbours.Add(secondSheep);
                    secondSheep.metricNeighbours.Add(firstSheep);
                }
            }
        }

        // voronoi neighbours
        Rectf   bounds  = new Rectf(0.0f, 0.0f, fieldSize, fieldSize);
        Voronoi voronoi = new Voronoi(points, bounds);

        foreach (Vector2f pt in points)
        {
            SheepController sheep = sheepList[pt.id];
            foreach (Vector2f neighbourPt in voronoi.NeighborSitesForSite(pt))
            {
                SheepController neighbour = sheepList[neighbourPt.id];
                sheep.voronoiNeighbours.Add(neighbour);
            }
        }
    }
Пример #6
0
    private void MakeSettlements(Rect bounds)
    {
        var settlementPoissonEnum = Poisson.generate_poisson(random, size, settlementSeparation, poissonRetries);

        var settlementPoisson = new List <Vector2>();

        while (settlementPoissonEnum.MoveNext())
        {
            settlementPoisson.Add(settlementPoissonEnum.Current);
        }

        var settlementVoronoi = new Voronoi(settlementPoisson, null, bounds);

        settlements = settlementPoisson.Select(p => new Settlement
        {
            Centre     = p,
            Biome      = GetBiomeAt(p.x, p.y),
            Neighbours = settlementVoronoi.NeighborSitesForSite(p).Where(n => Vector2.Distance(p, n) < settlementSeparation * 2).ToList()
        }).ToList();
        settlementLookup = settlements.ToDictionary(x => x.Centre);
    }
Пример #7
0
    /// <summary>
    /// Generate a room by selecting a random cell from a given voronoi grid and adding the surrounding cells
    /// to it until the required size has been met.
    /// </summary>
    /// <param name="voronoi"></param>
    /// <returns></returns>
    public List <List <Vector2> > GenerateRoom(Voronoi voronoi, int size, string seed)
    {
        if (size < 1)
        {
            return(null);
        }

        //Select a random site from the voronoi diagram
        Vector2 coord = RandomUtil.RandomElement(voronoi.SiteCoords(), false, seed);

        //Start building the final room from the cell at the coord
        List <LineSegment>     baseRoom          = voronoi.VoronoiBoundaryForSite(coord);
        List <List <Vector2> > finalRoomVertices = new List <List <Vector2> >();

        finalRoomVertices.Add(GetVerticesFromLineSegments(baseRoom));

        //Get the sites neighboring the base room
        List <Vector2> neighborSites = voronoi.NeighborSitesForSite(coord);

        //Add neighboring cells to the final room until the required room size has been met.
        //WARNING: Currently adds duplicate vertices to the final room in order to be able to triangulate each room-piece seperately later on.
        for (int i = 0; i < size - 1; i++)
        {
            List <LineSegment> neighbor = voronoi.VoronoiBoundaryForSite(neighborSites[i]);
            finalRoomVertices.Add(GetVerticesFromLineSegments(neighbor));
        }

        //Sort all room piece vertices clockwise for triangulation
        List <List <Vector2> > clockwiseVertices = new List <List <Vector2> >();

        foreach (List <Vector2> vertexSet in finalRoomVertices)
        {
            clockwiseVertices.Add(VectorUtil.SortClockwise(vertexSet));
        }

        return(clockwiseVertices);
    }
Пример #8
0
    // Create a graph containing all connected empty areas
    private void CreateBaseGraph(int lloydIterations)
    {
        // Create uniform random point distribution and Voronoi Diagram
        var centers = new List <Vector2f>();

        for (int i = 0; i < _voronoiSamples; i++)
        {
            var x = Random.Range(0f, MapSize);
            var y = Random.Range(0f, MapSize);
            centers.Add(new Vector2f(x, y));
        }
        VoronoiDiagram = new Voronoi(centers, new Rectf(0, 0, MapSize, MapSize));

        // Apply Lloyd Relaxation
        VoronoiDiagram.LloydRelaxation(lloydIterations);

        // Assign area segments to initial areas
        foreach (var site in VoronoiDiagram.SiteCoords())
        {
            bool isOnBorder = false;
            var  segments   = VoronoiDiagram.VoronoiBoundaryForSite(site);

            foreach (var segment in segments)
            {
                if (!(segment.p0.x <= VoronoiDiagram.PlotBounds.left) &&
                    !(segment.p0.x >= VoronoiDiagram.PlotBounds.right) &&
                    !(segment.p0.y <= VoronoiDiagram.PlotBounds.top) &&
                    !(segment.p0.y >= VoronoiDiagram.PlotBounds.bottom) &&
                    !(segment.p1.x <= VoronoiDiagram.PlotBounds.left) &&
                    !(segment.p1.x >= VoronoiDiagram.PlotBounds.right) &&
                    !(segment.p1.y <= VoronoiDiagram.PlotBounds.top) &&
                    !(segment.p1.y >= VoronoiDiagram.PlotBounds.bottom))
                {
                    continue;
                }

                isOnBorder = true;
                break;
            }

            // Assign areaSegment to site and corresponding area
            var areaSegment = new AreaSegment(isOnBorder ? AreaSegment.EAreaSegmentType.Border : AreaSegment.EAreaSegmentType.Empty);

            var nodeID = AreaSegmentGraph.AddNode(areaSegment);
            _siteAreaSegmentMap.Add(site, nodeID);
            _areaSegmentCenterMap.Add(nodeID, site.ToUnityVector2());
        }

        // Create navigation graph - for each area segment that is not a border, add reachable neighbors
        foreach (var id in _siteAreaSegmentMap)
        {
            var areaSegment = AreaSegmentGraph.GetNodeData(id.Value);
            if (areaSegment.Type == AreaSegment.EAreaSegmentType.Border)
            {
                continue;
            }

            Vector2 center = _areaSegmentCenterMap[id.Value];
            foreach (var neighbor in VoronoiDiagram.NeighborSitesForSite(new Vector2f(center.x, center.y)))
            {
                var neighborSegment = AreaSegmentGraph.GetNodeData(_siteAreaSegmentMap[neighbor]);
                if (neighborSegment.Type != AreaSegment.EAreaSegmentType.Border)
                {
                    AreaSegmentGraph.AddEdge(_siteAreaSegmentMap[neighbor], id.Value, (int)AreaSegment.EAreaSegmentEdgeType.NonNavigable);
                }
            }
        }
    }
Пример #9
0
 /// <summary>
 /// 取得指定地區的鄰居地區中心座標列表
 /// </summary>
 /// <param name="point">地區中心座標</param>
 /// <returns>座標列表</returns>
 public Vector2f[] getNeighborCenters(Vector2f point)
 {
     return(voronoi.NeighborSitesForSite(point).ToArray());
 }
Пример #10
0
    void Draw()
    {
        texture = new Texture2D(mapWidth, mapHeight);
        cells   = new List <MapCell>();
        Debug.Log(map_points.Count);
        for (int i = 0; i < map_points.Count; i++)
        {
            Vector2 site = map_points[i];
            MapCell cell = new MapCell
            {
                Position   = site,
                edges      = new List <MapEdge>(),
                neighbours = voronoi.NeighborSitesForSite(site),
                ID         = i,
            };
            //cell.isBorder = IsBorder(voronoi.VoronoiBoundaryForSite(site));
            cell.isBorder = HullContainsSite(site);



            foreach (LineSegment segment in voronoi.VoronoiBoundaryForSite(site))
            {
                cell.edges.Add(new MapEdge(segment.P0, segment.P1));
            }


            // Paint edges
            for (int j = 0; j < cell.edges.Count; j++)
            {
                MapEdge        edge   = cell.edges[j];
                List <Vector2> points = new List <Vector2>
                {
                    edge.p0,
                    edge.p1
                };
                Vector2 p0 = points[0];
                Vector2 p1 = points[1];

                int distance = (int)Mathf.Abs(Vector2.Distance(p0, p1));
                for (int k = 0; k <= distance; k++)
                {
                    Vector2 temp = p1 - p0;
                    temp.Normalize();
                    Vector2 pos = k * temp + p0;

                    int x;
                    int y;

                    if ((int)pos.x >= mapWidth)
                    {
                        x = ((int)pos.x) - 1;
                    }
                    else
                    {
                        x = (int)pos.x;
                    }

                    if ((int)pos.y >= mapHeight)
                    {
                        y = ((int)pos.y) - 1;
                    }
                    else
                    {
                        y = (int)pos.y;
                    }

                    texture.SetPixel(x, y, borderColour);
                }
            }

            //Fill Center
            //Temporary fill to have land and water

            int tempx = (int)site.x; int tempy = (int)site.y;
            if (cell.isBorder)
            {
                cell.biome = Biomes.GetBiome("Ocean");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
                continue;
            }


            float[,] noiseLayer = Noise.GenerateNoiseMap(mapWidth, mapHeight, seed, NOISE_SCALE, OCTAVES, PERSISTANCE, LACUNARITY, new Vector2(0, 0));

            if (noiseLayer[tempx, tempy] > waterThreshold)
            {
                cell.biome = Biomes.GetBiome("Grasslands");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
            }

            else
            {
                cell.biome = Biomes.GetBiome("Ocean");
                texture.FloodFillBorder(tempx, tempy, cell.biome.biomeColour, borderColour);
            }
        }
        texture.Apply();
        plane.GetComponent <MeshRenderer>().sharedMaterial.mainTexture = texture;
    }