public override void DisplayMap(WorldMapData mapData) { if (!enabled) { return; } _mapData = mapData; _heightMap = _mapData.GetLayer <HeightMapLayerData>().heightMap; ClearChunks(); //Chunks var chunksWide = Mathf.CeilToInt(mapData.width / (float)chunkWidth); var chunksHigh = Mathf.CeilToInt(mapData.height / (float)chunkHeight); for (var chunkY = 0; chunkY < chunksHigh; chunkY++) { for (var chunkX = 0; chunkX < chunksWide; chunkX++) { //Create the mesh var startX = chunkX * chunkWidth; var startY = chunkY * chunkHeight; var chunkView = GetChunk(new Vector2Int(chunkX, chunkY)); chunkView.transform.localPosition = new Vector3(0, 0, 0); var mesh = HexMeshUtility.GenerateHexagonMesh(radius, border, startX, startY, chunkWidth, chunkHeight, mapData.width, mapData.height, _heightMap, GetColor, GetElevation); chunkView.SetMesh(mesh); } } }
public override void DisplayMap(WorldMapData mapData) { if (!enabled) { return; } var heightMap = mapData.GetLayer <HeightMapLayerData>().heightMap; int chunksWide = Mathf.CeilToInt(mapData.width / (float)chunkWidth); int chunksHigh = Mathf.CeilToInt(mapData.height / (float)chunkHeight); if (Application.isEditor) { ClearChunks(); } for (var y = 0; y < chunksHigh; y++) { for (var x = 0; x < chunksWide; x++) { var chunk = GetChunk(new Vector2Int(x, y)); var meshData = VoxelMeshUtility.CreateMeshData(heightMap, mapData.width, mapData.height, x, y, chunkWidth, chunkHeight, _terrainTable, edges, edgeThickness); chunk.SetMesh(meshData.CreateMesh()); } } }
private void DisplayMap(WorldMapData mapData) { var mapViews = GetComponents <IWorldMapView>(); foreach (var view in mapViews) { view.DisplayMap(mapData); } }
public void GenerateMap() { if (randomizeSeed) { seed = Random.Range(int.MinValue, Int32.MaxValue); } _mapData = _generator.GenerateMap(seed); DisplayMap(_mapData); }
public override void AddToWorld(WorldMapData mapData) { if (useRegions) { AddToWorldUsingRegions(mapData); return; } AddToWorldDefault(mapData); }
private void AddToWorldDefault(WorldMapData mapData) { var points = PoissonDiskSampling.GenerateIntPoints(radius, new Vector2Int(mapData.width, mapData.height), mapData.seed, maxSamplesPerPoint); var layer = new PoissonMapLayerData { points = points }; mapData.layers.Add(layer); }
private void AddToWorldUsingRegions(WorldMapData mapData) { var regionLayer = mapData.GetLayer <RegionMapLayerData>(); var regionMap = regionLayer.regionMap; //Only select points in valid regions var points = PoissonDiskSampling.GenerateIntPoints(radius, new Vector2Int(mapData.width, mapData.height), mapData.seed, maxSamplesPerPoint, (pt) => { if (regionMap[pt.y * mapData.width + pt.x] <= 0) { return(false); } if (edgeAvoidance == 0) { return(true); } //Check any points in radius for overlap with bad region var searchStartX = Mathf.Max(0, pt.x - edgeAvoidance); var searchEndX = Mathf.Min(pt.x + edgeAvoidance, mapData.width - 1); var searchStartY = Mathf.Max(0, pt.y - edgeAvoidance); var searchEndY = Mathf.Min(pt.y + edgeAvoidance, mapData.height - 1); for (var x = searchStartX; x <= searchEndX; x++) { for (var y = searchStartY; y <= searchEndY; y++) { //Index was stored with +1 so we could avoid initializing the grid to all -1 values int regionIndex = regionMap[y * mapData.width + x]; if (regionIndex <= 0) { return(false); } } } return(true); }); var layer = new PoissonMapLayerData { points = points }; mapData.layers.Add(layer); }
public WorldMapData GenerateMap(int seed) { var worldData = new WorldMapData { seed = seed, width = mapWidth, height = mapHeight }; for (int i = 0; i < layerGenerators.Count; i++) { layerGenerators[i].AddToWorld(worldData); } return(worldData); }
public override void DisplayMap(WorldMapData worldMapData) { if (!enabled) { return; } var heightMap = worldMapData.GetLayer <HeightMapLayerData>().heightMap; if (terrainTable == null) { var meshData = TerrainMeshUtility.GenerateMesh(heightMap, worldMapData.width, worldMapData.height, heightScale, levelOfDetail); _meshFilter.mesh = meshData.CreateMesh(); } else { var meshData = TerrainMeshUtility.GenerateMesh(heightMap, worldMapData.width, worldMapData.height, levelOfDetail, x => { var terrainType = terrainTable.GetTerrainType(x); if (smooth) { var t = Mathf.InverseLerp(terrainType.Floor, terrainType.Threshold, x); return(Mathf.Lerp(terrainType.MinElevation, terrainType.MaxElevation, t) * heightScale); } return(terrainTable.GetTerrainType(x).MinElevation *heightScale); }, x => { var terrainType = terrainTable.GetTerrainType(x); if (!useColorGradient) { return(terrainType.ColorGradient.Evaluate(0)); } var t = Mathf.InverseLerp(terrainType.Floor, terrainType.Threshold, x); return(terrainType.ColorGradient.Evaluate(t)); }); _meshFilter.mesh = meshData.CreateMesh(); } }
public abstract void AddToWorld(WorldMapData mapData);
public abstract void DisplayMap(WorldMapData mapData);
public void DisplayMap(WorldMapData mapData) { if (!enabled || prefab == null) { return; } prefab.gameObject.SetActive(false); ClearLines(); var positionOffset = new Vector3(mapData.width * -0.5f, 0, mapData.height * 0.5f) + offset; var regionLayer = mapData.GetLayer <RegionMapLayerData>(); foreach (var region in regionLayer.regions) { //Each region could have more than one border line to draw //Border point list is unordered so we need to also figure out what the lines are //Convert border points to 3D space var points = new List <Vector3>(region.borderPoints.Select((pt) => new Vector3(pt.x, 0, -pt.y) + positionOffset)); //Extract lines from list of points by getting closest points var lines = new List <List <Vector3> >(); var currentLine = new List <Vector3>(); lines.Add(currentLine); var currentPt = points[0]; points.RemoveAt(0); while (points.Count > 0) { float minDistance = float.MaxValue; int minIndex = -1; for (int i = 0; i < points.Count; i++) { var distance = (currentPt - points[i]).sqrMagnitude; if (distance < minDistance) { minDistance = distance; minIndex = i; } } if (minDistance > 2) { //Start a new line if the closest points was more than a certain distance away lines.Add(currentLine); currentLine = new List <Vector3>(); } currentPt = points[minIndex]; currentLine.Add(points[minIndex]); points.RemoveAt(minIndex); } var regionColor = regionColors.Length > 0 ? regionColors[(region.id - 1) % regionColors.Length] : Color.white; foreach (var line in lines) { //Don't draw anything with less than 2 points if (line.Count < minLineLength) { continue; } var lineRenderer = Instantiate(prefab, transform); lineRenderer.transform.localEulerAngles = new Vector3(90, 0, 0); lineRenderer.startColor = regionColor; lineRenderer.endColor = regionColor; //lineRenderer.positionCount = region.borderPoints.Count; lineRenderer.positionCount = line.Count; lineRenderer.SetPositions(line.ToArray()); var startPt = line[0]; var endPt = line[line.Count - 1]; //If the end is close enough to the start then complete the loop if ((startPt - endPt).sqrMagnitude <= 2) { lineRenderer.loop = true; } lineRenderer.gameObject.SetActive(true); lineRenderers.Add(lineRenderer); } } }
public override void AddToWorld(WorldMapData mapData) { var rng = new System.Random(mapData.seed); var regionLayer = new RegionMapLayerData(); var heightMapLayer = mapData.GetLayer <HeightMapLayerData>(); if (heightMapLayer == null) { throw new Exception("Cannot generate region layer without a height map"); } var heightMap = heightMapLayer.heightMap; //Generate stuff var regionMap = new int[mapData.width * mapData.height]; int emptyTileCount = 0; //Initialize map such that negative values are 'water' for (int i = 0; i < regionMap.Length; i++) { if (heightMap[i] > waterLevel) { emptyTileCount++; regionMap[i] = 0; } else { regionMap[i] = -1; } } List <RegionData> regions = new List <RegionData>(); for (int i = 0; i < 100 && regions.Count < regionCount; i++) { //Pick a random point Vector2Int pt = new Vector2Int(rng.Next(0, mapData.width), rng.Next(0, mapData.height)); int index = pt.y * mapData.width + pt.x; //If point is not empty try again if (regionMap[index] != 0) { continue; } //Regions are assigned id starting from 1 var region = new RegionData { id = regions.Count + 1, spawnPt = pt }; AddPointToRegion(region, regionMap, mapData.width, mapData.height, pt); emptyTileCount -= 1; regions.Add(region); } if (regions.Count != regionCount) { throw new Exception("Failed to create enough regions"); } var neighbors = new List <Vector2Int>(); int maxIterations = mapData.width * mapData.height; int count = 0; int emptyCount = 0; //Grow each region until there are no more empty tiles remaining while (emptyTileCount > 0 && emptyCount != regions.Count && count < maxIterations) { emptyCount = 0; foreach (var region in regions) { if (region.borderPoints.Count == 0) { //Count the number of regions that can no longer grow //Then we can early out if all regions are maxed out emptyCount++; continue; } if (TryExpandRegion(region, regionMap, mapData.width, mapData.height, rng, neighbors)) { emptyTileCount--; } } count++; } count = 0; while (emptyTileCount != 0 && count < maxIterations) { count++; //We may have islands so lets find one and expand the closest region into it int index = FindUnassignedRegion(regionMap); int y = index / mapData.width; int x = index - (y * mapData.width); var pt = new Vector2Int(x, y); //Find the region with spawn point closest to pt var closestRegion = FindClosestRegion(regions, pt); AddPointToRegion(closestRegion, regionMap, mapData.width, mapData.height, pt); emptyTileCount--; //Expand region until it has no border points left while (closestRegion.borderPoints.Count > 0) { if (TryExpandRegion(closestRegion, regionMap, mapData.width, mapData.height, rng, neighbors)) { emptyTileCount--; } } } if (emptyTileCount != 0) { Debug.LogError($"Failed to fill all tiles {emptyTileCount} (MaxIterations? {count >= maxIterations})"); } //Validate for (int i = 0; i < regionMap.Length; i++) { if (regionMap[i] == 0) { Debug.LogError("Found a zero. TODO: Handle Islands"); break; } } //Clear Border Points foreach (var region in regions) { region.borderPoints.Clear(); } //Find actual border points for (int y = 0; y < mapData.height; y++) { for (int x = 0; x < mapData.width; x++) { var index = y * mapData.width + x; if (regionMap[index] <= 0) { continue; } var region = regions[regionMap[index] - 1]; var pt = new Vector2Int(x, y); if (IsBorder(regionMap, mapData.width, mapData.height, pt)) { region.borderPoints.Add(pt); } } } regionLayer.regionMap = regionMap; regionLayer.regions = regions; mapData.layers.Add(regionLayer); }
public async void DisplayMap(WorldMapData worldMapData) { if (!enabled) { return; } var heightMapLayer = worldMapData.GetLayer <HeightMapLayerData>(); var regionMapLayer = worldMapData.GetLayer <RegionMapLayerData>(); var width = worldMapData.width; var height = worldMapData.height; var heightMap = heightMapLayer.heightMap; var regions = regionMapLayer.regions; var regionMap = regionMapLayer.regionMap; var terrainMap = _terrainTable.GetTerrainMap(heightMap); var colorMap = TerrainTable.GetColorMap(heightMap, terrainMap, gradiate); if (fillRegions && regionColors.Length > 0) { for (int i = 0; i < colorMap.Length; i++) { var regionIndex = regionMap[i]; if (regionIndex <= 0) { continue; } var regionColor = regionColors[(regionIndex - 1) % regionColors.Length]; var alpha = Mathf.Clamp01(regionColor.a * regionFillAlpha); colorMap[i] = regionColor * alpha + (1 - alpha) * colorMap[i]; } } if (drawBorders && regionColors.Length > 0) { foreach (var region in regions) { foreach (var pt in region.borderPoints) { int index = pt.y * width + pt.x; var regionIndex = regionMap[index]; var regionColor = regionColors[regionIndex - 1]; var alpha = regionColor.a * borderAlpha; colorMap[index] = regionColor * alpha + (1 - alpha) * colorMap[index]; colorMap[index].a = 1; } } } if (drawSpawnPoints) { foreach (var region in regions) { var pt = region.spawnPt; int index = pt.y * width + pt.x; colorMap[index] = Color.black; } } if (drawPoissonPoints) { var poissonLayer = worldMapData.GetLayer <PoissonMapLayerData>(); if (poissonLayer != null) { foreach (var pt in poissonLayer.points) { int index = pt.y * width + pt.x; colorMap[index] = Color.black; } } } var texture = TextureUtility.GetColorMap(colorMap, width, height); texture.filterMode = filterMode; SetTexture(texture); if (scaleTexture) { await TextureScale.BilinearAsync(texture, Mathf.Min(2048, Mathf.RoundToInt(width *textureScale)), Mathf.Min(2048, Mathf.RoundToInt(height *textureScale))); } }
public override void AddToWorld(WorldMapData worldMapData) { worldMapData.layers.Add(Generate(worldMapData.width, worldMapData.height, worldMapData.seed)); }