public override void Generate(Chunk chunk, Biome biome = null) { SpatialHash spatialHash = chunk.defaultSpatialHash; if (!enabled) { output.SetObject(chunk, spatialHash); return; } if (chunk.stop) { return; } // Note - it's important that we *don't* change the seed based on the chunk coordinates, or else // we risk generating two different points. InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed /* + chunk.coord.x*1000 + chunk.coord.z */); Vector2 candidate = new Vector2(xMin + rnd.Random() * (xMax - xMin), zMin + rnd.Random() * (zMax - zMin)); // MM works with coordinates specified in "terrain space". If the user specifies coordinates in // absolute world position, need to scale these based on resolution and size of terrain before // adding to the spatialhash if (coordinateSpace == CoordinateSpace.World) { float scaleFactor = (float)MapMagic.instance.resolution / (float)MapMagic.instance.terrainSize; candidate *= scaleFactor; } // If the spatial hash for this chunk does not contain the candidate point, simply return the default // spatial hash if ( spatialHash.offset.x + spatialHash.size <= candidate.x || /* candidate point lies too far to the right */ spatialHash.offset.x > candidate.x || /* candidate point lies too far to the left */ spatialHash.offset.y + spatialHash.size <= candidate.y || /* candidate point lies too far forward */ spatialHash.offset.y > candidate.y /* candidate point lies too far backward */ ) { output.SetObject(chunk, spatialHash); return; } // If the candidate lies within this chunk's bounds, add it to the hash else { spatialHash.Add(candidate, 0, 0, 1); } if (chunk.stop) { return; } output.SetObject(chunk, spatialHash); }
public override void Generate(Chunk chunk, Biome biome = null) { //return on stop/disable if (chunk.stop || !enabled) { return; } InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed /* + chunk.coord.x*1000 + chunk.coord.z*/); // Calculate the total weight of all layers float sumOfWeights = 0f; for (int i = 0; i < layers.Length; i++) { sumOfWeights += layers[i].weight; } // Pick a random value less than the total weight float rouletteSelection = rnd.Random(0, sumOfWeights); // Loop through the layers, keeping a running sum of weights // The layer that contains the chosen rouletteWeight gets sent the input // All other layers get sent the default matrix float prevRunningWeight = 0f; float nextRunningWeight = 0f; for (int i = 0; i < layers.Length; i++) { nextRunningWeight = prevRunningWeight + layers[i].weight; if (prevRunningWeight < rouletteSelection && nextRunningWeight > rouletteSelection) { layers[i].output.SetObject(chunk, (Matrix)input.GetObject(chunk)); } else { layers[i].output.SetObject(chunk, chunk.defaultMatrix); } prevRunningWeight = nextRunningWeight; } }
public override void Generate(MapMagic.Chunk chunk) { Matrix matrix = (Matrix)input.GetObject(chunk); if (matrix != null) { matrix = matrix.Copy(null); } if (matrix == null) { matrix = chunk.defaultMatrix; } Matrix mask = (Matrix)maskIn.GetObject(chunk); if (chunk.stop) { return; } if (!enabled || intensity == 0 || cellCount == 0) { output.SetObject(chunk, matrix); return; } //NoiseGenerator.Noise(matrix,200,0.5f,Vector2.zero); //matrix.Multiply(amount); InstanceRandom random = new InstanceRandom(MapMagic.instance.seed + seed); //creating point matrix float cellSize = 1f * matrix.rect.size.x / cellCount; Matrix2 <Vector3> points = new Matrix2 <Vector3>(new CoordRect(0, 0, cellCount + 2, cellCount + 2)); points.rect.offset = new Coord(-1, -1); Coord matrixSpaceOffset = new Coord((int)(matrix.rect.offset.x / cellSize), (int)(matrix.rect.offset.z / cellSize)); //scattering points for (int x = -1; x < points.rect.size.x - 1; x++) { for (int z = -1; z < points.rect.size.z - 1; z++) { Vector3 randomPoint = new Vector3(x + random.CoordinateRandom(x + matrixSpaceOffset.x, z + matrixSpaceOffset.z), 0, z + random.NextCoordinateRandom()); Vector3 centerPoint = new Vector3(x + 0.5f, 0, z + 0.5f); Vector3 point = randomPoint * (1 - uniformity) + centerPoint * uniformity; point = point * cellSize + new Vector3(matrix.rect.offset.x, 0, matrix.rect.offset.z); point.y = random.NextCoordinateRandom(); points[x, z] = point; } } Coord min = matrix.rect.Min; Coord max = matrix.rect.Max; for (int x = min.x; x < max.x; x++) { for (int z = min.z; z < max.z; z++) { //finding current cell Coord cell = new Coord((int)((x - matrix.rect.offset.x) / cellSize), (int)((z - matrix.rect.offset.z) / cellSize)); //finding min dist float minDist = 200000000; float secondMinDist = 200000000; float minHeight = 0; //float secondMinHeight = 0; for (int ix = -1; ix <= 1; ix++) { for (int iz = -1; iz <= 1; iz++) { Coord nearCell = new Coord(cell.x + ix, cell.z + iz); //if (!points.rect.CheckInRange(nearCell)) continue; //no need to perform test as points have 1-cell border around matrix Vector3 point = points[nearCell]; float dist = (x - point.x) * (x - point.x) + (z - point.z) * (z - point.z); if (dist < minDist) { secondMinDist = minDist; minDist = dist; minHeight = point.y; } else if (dist < secondMinDist) { secondMinDist = dist; } } } float val = 0; switch (blendType) { case BlendType.flat: val = minHeight; break; case BlendType.closest: val = minDist / (MapMagic.instance.resolution * 16); break; case BlendType.secondClosest: val = secondMinDist / (MapMagic.instance.resolution * 16); break; case BlendType.cellular: val = (secondMinDist - minDist) / (MapMagic.instance.resolution * 16); break; case BlendType.organic: val = (secondMinDist + minDist) / 2 / (MapMagic.instance.resolution * 16); break; } if (mask == null) { matrix[x, z] += val * intensity; } else { matrix[x, z] += val * intensity * mask[x, z]; } } } if (chunk.stop) { return; //do not write object is generating is stopped } output.SetObject(chunk, matrix); }
public float uniformity = 0.1f; //aka candidatesNum/100 public override void Generate(Chunk chunk, Biome biome = null) { Matrix probMatrix = (Matrix)probability.GetObject(chunk); SpatialHash spatialHash = chunk.defaultSpatialHash; if (!enabled) { output.SetObject(chunk, spatialHash); return; } if (chunk.stop) { return; } InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z); //Rect terrainRect = terrain.coord.ToRect(terrain.size); //terrainRect.position += Vector2.one; terrainRect.size-=Vector2.one*2; //SpatialHash spatialHash = new SpatialHash(terrain.coord.ToVector2(terrain.size), terrain.size, 16); //float square = terrainRect.width * terrainRect.height; //float count = square*(density/1000000); //number of items per terrain //positioned scatter /*float sideCount = Mathf.Sqrt(count); * float step = spatialHash.size / sideCount; * * //int uniformity = 100; * //Random.seed = 12345; * for (float x=spatialHash.offset.x+step/2; x<spatialHash.offset.x+spatialHash.size-step/2; x+=step) * for (float y=spatialHash.offset.y+step/2; y<spatialHash.offset.y+spatialHash.size-step/2; y+=step) * { * Vector2 offset = new Vector2(((Random.value*2-1)*uniformity), ((Random.value*2-1)*uniformity)); * Vector2 point = new Vector2(x,y) + offset; * if (point.x > spatialHash.size) point.x -= spatialHash.size; if (point.x < 0) point.x += spatialHash.size; * if (point.y > spatialHash.size) point.y -= spatialHash.size; if (point.y < 0) point.y += spatialHash.size; * spatialHash.Add(point, 0,0,0); * }*/ //realRandom algorithm int candidatesNum = (int)(uniformity * 100); 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); if (dist > bestDist) { bestDist = dist; bestCandidate = candidate; } } if (bestDist > 0.001f) { spatialHash.Add(bestCandidate, 0, 0, 1); //adding only if some suitable candidate found } } if (chunk.stop) { return; } output.SetObject(chunk, spatialHash); }
public float uniformity = 0.1f; //aka candidatesNum/100 public override void Generate(Chunk chunk, Biome biome = null) { Matrix probMatrix = (Matrix)probability.GetObject(chunk); SpatialHash spatialHash = chunk.defaultSpatialHash; if (!enabled) { output.SetObject(chunk, spatialHash); return; } if (chunk.stop) { return; } // If the bounds of this chunk don't contain the specified zValue then return the // default spatialHash if (spatialHash.offset.y > zValue || spatialHash.offset.y + spatialHash.size <= zValue) { output.SetObject(chunk, spatialHash); return; } InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z); int candidatesNum = (int)(uniformity * 100); 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)), zValue); //checking if candidate available here according to probability map if (probMatrix != null && probMatrix[candidate] < rnd.Random()) { continue; } //checking if candidate is the furthest one float dist = spatialHash.MinDist(candidate); if (dist > bestDist) { bestDist = dist; bestCandidate = candidate; } } if (bestDist > 0.001f) { spatialHash.Add(bestCandidate, 0, 0, 1); //adding only if some suitable candidate found } } if (chunk.stop) { return; } output.SetObject(chunk, spatialHash); }