} //no extend, non-generic public void Add(SpatialHash addHash) { if (addHash.cells.Length != cells.Length) { UnityEngine.Debug.LogError("Add SpatialHash: cell number is different"); return; } for (int c = 0; c < cells.Length; c++) { cells[c].objs.AddRange(addHash.cells[c].objs); Count += cells[c].objs.Count; } }
public void ChangeResolution(int newResolution) { SpatialHash newHash = new SpatialHash(offset, size, newResolution); foreach (SpatialObject obj in AllObjs()) { newHash.Add(obj); } resolution = newResolution; cells = newHash.cells; }
public SpatialHash Copy() { SpatialHash result = new SpatialHash(offset, size, resolution); for (int i = 0; i < cells.Length; i++) { result.cells[i].min = cells[i].min; result.cells[i].max = cells[i].max; result.cells[i].objs = new List <SpatialObject>(cells[i].objs); List <SpatialObject> objs = result.cells[i].objs; for (int o = objs.Count - 1; o >= 0; o--) { objs[o] = objs[o].Copy(); } } result.Count = Count; return(result); }
public void RandomScatter(int count, SpatialHash spatialHash, InstanceRandom rnd, Matrix probMatrix) { int candidatesNum = (int)(uniformity * 100); if (candidatesNum < 1) { candidatesNum = 1; } for (int i = 0; i < count; i++) { Vector2 bestCandidate = Vector3.zero; float bestDist = 0; for (int c = 0; c < candidatesNum; c++) { Vector2 candidate = new Vector2((spatialHash.offset.x + 1) + (rnd.Random() * (spatialHash.size - 2.01f)), (spatialHash.offset.y + 1) + (rnd.Random() * (spatialHash.size - 2.01f))); //checking if candidate available here according to probability map //if (probMatrix!=null && probMatrix[candidate] < rnd.Random()+0.0001f) continue; //checking if candidate is the furthest one float dist = spatialHash.MinDist(candidate); //distance to the edge float bd = (candidate.x - spatialHash.offset.x) * 2; if (bd < dist) { dist = bd; } bd = (candidate.y - spatialHash.offset.y) * 2; if (bd < dist) { dist = bd; } bd = (spatialHash.offset.x + spatialHash.size - candidate.x) * 2; if (bd < dist) { dist = bd; } bd = (spatialHash.offset.y + spatialHash.size - candidate.y) * 2; if (bd < dist) { dist = bd; } if (dist > bestDist) { bestDist = dist; bestCandidate = candidate; } } if (bestDist > 0.001f) { spatialHash.Add(bestCandidate, 0, 0, 1); //adding only if some suitable candidate found } } //masking for (int c = 0; c < spatialHash.cells.Length; c++) { SpatialHash.Cell cell = spatialHash.cells[c]; for (int i = cell.objs.Count - 1; i >= 0; i--) { Vector2 pos = cell.objs[i].pos; if (pos.x < spatialHash.offset.x + safeBorders || pos.y < spatialHash.offset.y + safeBorders || pos.x > spatialHash.offset.x + spatialHash.size - safeBorders || pos.y > spatialHash.offset.y + spatialHash.size - safeBorders) { cell.objs.RemoveAt(i); continue; } if (probMatrix != null && probMatrix[pos] < rnd.Random() + 0.0001f) { cell.objs.RemoveAt(i); continue; } } } }
public void Generate(SpatialHash spatialHash, int seed, Matrix probability) { InstanceRandom rnd = new InstanceRandom(seed ^ this.seed); RandomScatter(count, spatialHash, rnd, probability); }
//public MapMagic.GeneratorsAsset mapMagicGens; #endif public void Generate(Data.Area area, Func <float, bool> stop = null) { if (area.pinned) { return; } change = false; if (stop != null && stop(0)) { return; } //special case for preserving a demo scene on generator change // if (area.coord.x==0 && area.coord.z==0) return; Data.Area savedArea = null; if (leaveDemoUntouched && area.coord.x == 0 && area.coord.z == 0) { savedArea = (Data.Area)area.Clone(); } if (generatorType == GeneratorType.Planar) { area.ClearLand(); area.ClearObjects(); area.ClearGrass(); Matrix matrix = new Matrix(area.rect); planarGen.Generate(matrix, stop); area.AddLayer(matrix, planarGen.blockType, heightFactor: 1, noise: null); } if (generatorType == GeneratorType.Noise) { area.ClearLand(); area.ClearObjects(); area.ClearGrass(); Noise noise = new Noise(123, permutationCount: 512); //random to floor floats Matrix noiseMatrix = new Matrix(area.rect); if (stop != null && stop(0)) { return; } if (noiseGen.enabled) { noiseGen.Generate(noiseMatrix, seed, stop); } if (stop != null && stop(0)) { return; } if (curveGen.enabled) { curveGen.Generate(noiseMatrix, stop); } if (stop != null && stop(0)) { return; } area.AddLayer(noiseMatrix, noiseGen.blockType, heightFactor: heightFactor, noise: noise); //TODO: set block types instead of magical numbers if (slopeGen.enabled) { if (stop != null && stop(0)) { return; } Matrix slopeMatrix = slopeGen.Generate(noiseMatrix, stop); area.PaintLayer(slopeMatrix, slopeGen.blockType, noise: noise, paintThickness: slopeGen.thickness); } if (cavityGen.enabled) { if (stop != null && stop(0)) { return; } Matrix cavityMatrix = cavityGen.Generate(noiseMatrix, stop); area.PaintLayer(cavityMatrix, cavityGen.blockType, noise: noise, paintThickness: cavityGen.thickness); } Matrix blurMatrix; if (blurGen.enabled) { if (stop != null && stop(0)) { return; } blurMatrix = blurGen.Generate(noiseMatrix, stop); blurMatrix.Max(noiseMatrix); area.ClampAppendLayer(blurMatrix, blurGen.blockType, noise: noise, heightFactor: heightFactor); } else { blurMatrix = noiseMatrix; } if (stainsGen.enabled) { Matrix matrix = area.GetSoilMatrix(stainsGen.soilOpacity); //Matrix stains = new Matrix(area.rect); stainsGen.Generate(matrix, seed, stop); area.PaintLayer(matrix, stainsGen.blockType, noise: noise, paintThickness: stainsGen.thickness); } if (noiseGenB.enabled) { Matrix matrix = new Matrix(area.rect); noiseGenB.Generate(matrix, seed, stop); area.SetLayer(matrix, null, noiseGenB.blockType, heightFactor: heightFactor, noise: noise); } if (scatterGen.enabled) { if (stop != null && stop(0)) { return; } SpatialHash spatialHash = new SpatialHash(new Vector2(area.rect.offset.x, area.rect.offset.z), area.rect.size.x, 16); Matrix soil = area.GetSoilMatrix(scatterGen.soilOpacity); scatterGen.Generate(spatialHash, seed, soil); foreach (SpatialObject obj in spatialHash.AllObjs()) { int x = (int)(obj.pos.x + 0.5f); int z = (int)(obj.pos.y + 0.5f); int y = (int)((obj.height + blurMatrix[x, z]) * heightFactor); area.AddObject(new CoordDir(x, y, z), (short)scatterGen.blockType); } } for (int g = 0; g < grassGens.gens.Length; g++) { GrassGenerator grassGen = grassGens.gens[g]; //if (grassGen.enabled) { if (stop != null && stop(0)) { return; } Matrix grassMatrix = area.GetSoilMatrix(grassGen.soilOpacity); grassGen.Generate(grassMatrix, seed); area.SetGrassLayer(grassMatrix, (byte)grassGen.grassType, 1, noise); } } } else if (generatorType == GeneratorType.Heightmap) { area.ClearLand(); area.ClearObjects(); area.ClearGrass(); Noise noise = new Noise(123, permutationCount: 512); //random to floor floats Matrix matrix = new Matrix(area.rect); if (stop != null && stop(0)) { return; } if (standaloneHeightGen.enabled) { standaloneHeightGen.Generate(matrix, seed, stop); } area.AddLayer(matrix, noiseGen.blockType, heightFactor: heightFactor, noise: noise); //TODO: set block types instead of magical numbers } else if (generatorType == GeneratorType.MapMagic) { #if MAPMAGIC if (stop != null && stop(0)) { return; } if (area.results == null) { area.results = new MapMagic.Chunk.Results(); } //MapMagic.Chunk.Size size = new MapMagic.Chunk.Size(area.rect.size.x,area.rect.size.x,heightFactor); if (stop != null && stop(0)) { return; } if (mapMagicGens != null) { //mapMagicGens.Calculate(area.rect.offset.x, area.rect.offset.z, area.rect.size.x, area.results, new MapMagic.Chunk.Size(area.rect.size.x,area.rect.size.x,heightFactor), seed, stop); mapMagicGens.Generate(area.results, area.rect.offset.x, area.rect.offset.z, area.rect.size.x, area.rect.size.x, heightFactor, seed, stop); } else { area.ClearLand(); area.ClearObjects(); area.ClearGrass(); } #else area.ClearLand(); area.ClearObjects(); area.ClearGrass(); #endif } if (stop != null && stop(0)) { return; } if (removeThinLayers) { area.RemoveThinLayers(minLayerThickness); } if (stop != null && stop(0)) { return; } if (polish) { area.Polish(); } //special case for preserving a demo scene on generator change if (leaveDemoUntouched && area.coord.x == 0 && area.coord.z == 0) { Matrix mask = new Matrix(new CoordRect(0, 0, area.lines.Length, area.lines.Length)); for (int x = 0; x < mask.rect.size.x; x++) { for (int z = 0; z < mask.rect.size.z; z++) { int distFromEdge = Mathf.Min(x, mask.rect.size.x - x, z, mask.rect.size.z - z); mask[x, z] = Mathf.Clamp01(distFromEdge / 50f); } } Matrix maskInverted = (Matrix)mask.Clone(); maskInverted.InvertOne(); area.MixAreas(new Data.Area[] { (Data.Area)area.Clone(), savedArea }, new Matrix[] { maskInverted, mask }); area.objects = savedArea.objects; } //area.generated = true; //area.serializable = true; }