public bool[,] Generate(int sizeX, int sizeY, int nThreads, int seed) { bool[,] tiles = new bool[sizeX, sizeY]; Func <Vector3, float, float> sampler = (pos, scale) => NoiseAlgos3D.LinearNoise(pos * scale); float seedF = (float)seed; ThreadedRunner.Run(nThreads, sizeY, (startY, endY) => { for (int y = startY; y <= endY; ++y) { float yF = (float)y; for (int x = 0; x < sizeX; ++x) { float xF = (float)x; float val = Noise.Sample(new Vector3(xF, yF, seedF), sampler); val = Mathf.Pow(val, Exponent); tiles[x, y] = (val > Threshold); } } }); return(tiles); }
public BiomeTile[,] Generate(int sizeX, int sizeY, int nThreads, int seed) { BiomeTile[,] tiles = new BiomeTile[sizeX, sizeY]; Func <Vector3, float, float> sampler = (pos, scale) => NoiseAlgos3D.LinearNoise(pos * scale); float seedF = (float)seed; ThreadedRunner.Run(nThreads, sizeY, (startY, endY) => { for (int y = startY; y <= endY; ++y) { float yF = (float)y; for (int x = 0; x < sizeX; ++x) { float xF = (float)x; tiles[x, y] = new BiomeTile(); tiles[x, y].CaveSmoothness = Noise.Sample(new Vector3(xF, yF, seedF), sampler); } } }); return(tiles); }
/// <summary> /// Performs the DFT -- converting a 2D position-domain signal into a 2D frequency-domain signal. /// </summary> /// <param name="samples"> /// The samples from an input signal. /// </param> /// <param name="outResult"> /// The output array. /// If it's null or the wrong size, it will be automatically created. /// Contains the sine/cosine wave amplitudes for each frequency in the signal. /// </param> public static void Forward(Complex[,] samples, ref Complex[,] outResult) { //Make sure the output array is the right size. if (outResult == null || outResult.GetLength(0) != samples.GetLength(0) || outResult.GetLength(1) != samples.GetLength(1)) { outResult = new Complex[samples.GetLength(0), samples.GetLength(1)]; } //Perform the 1D DFT along every row and column. //Row: Complex[][] dftByRow = new Complex[samples.GetLength(1)][]; ThreadedRunner.Run(NThreads, samples.GetLength(1), (startY, endY) => { Complex[] sampleLine = new Complex[samples.GetLength(0)]; for (int sampleY = startY; sampleY <= endY; ++sampleY) { //Populate the sample array. for (int sampleX = 0; sampleX < samples.GetLength(0); ++sampleX) { sampleLine[sampleX] = samples[sampleX, sampleY]; } //Run the dft. dftByRow[sampleY] = Algo1D.Forward(sampleLine); } }); //Column: var _outResult = outResult; //ref variables can't be used inside a lambda. ThreadedRunner.Run(NThreads, samples.GetLength(0), (startX, endX) => { Complex[] sampleLine = new Complex[samples.GetLength(1)]; for (int sampleX = startX; sampleX <= endX; ++sampleX) { //Populate the sample array. for (int sampleY = 0; sampleY < samples.GetLength(1); ++sampleY) { sampleLine[sampleY] = dftByRow[sampleY][sampleX]; } //Run the dft. var results = Algo1D.Forward(sampleLine); for (int sampleY = 0; sampleY < samples.GetLength(1); ++sampleY) { _outResult[sampleX, sampleY] = results[sampleY]; } } }); }
/// <summary> /// Performs the inverse DFT -- converting a frequency-domain signal /// back into a 2D position-domain signal. /// </summary> /// <param name="dftResults"> /// The frequency-domain signal. /// </param> /// <param name="outSamples"> /// The position-domain signal samples. /// If the array is null or the wrong size, it will be automatically created. /// </param> public static void Inverse(Complex[,] dftResults, ref Complex[,] outSamples) { //Make sure the output array is the right size. if (outSamples == null || outSamples.GetLength(0) != dftResults.GetLength(0) || outSamples.GetLength(1) != dftResults.GetLength(1)) { outSamples = new Complex[dftResults.GetLength(0), dftResults.GetLength(1)]; } //Perform the 1D inverse DFT along each row/column. //Column: Complex[][] inverseDFTByCol = new Complex[dftResults.GetLength(0)][]; ThreadedRunner.Run(NThreads, dftResults.GetLength(0), (startX, endX) => { Complex[] sampleLine = new Complex[dftResults.GetLength(1)]; for (int sampleX = startX; sampleX <= endX; ++sampleX) { //Populate the sample array. for (int sampleY = 0; sampleY < dftResults.GetLength(1); ++sampleY) { sampleLine[sampleY] = dftResults[sampleX, sampleY]; } //Run the dft. inverseDFTByCol[sampleX] = Algo1D.Inverse(sampleLine); } }); //Row: var _outSamples = outSamples; //Can't use a ref variable in a lambda. ThreadedRunner.Run(NThreads, dftResults.GetLength(1), (startY, endY) => { Complex[] sampleLine = new Complex[dftResults.GetLength(0)]; for (int sampleY = startY; sampleY <= endY; ++sampleY) { //Populate the sample array. for (int sampleX = 0; sampleX < dftResults.GetLength(0); ++sampleX) { sampleLine[sampleX] = inverseDFTByCol[sampleX][sampleY]; } //Run the dft. var results = Algo1D.Inverse(sampleLine); for (int sampleX = 0; sampleX < dftResults.GetLength(0); ++sampleX) { _outSamples[sampleX, sampleY] = results[sampleX]; } } }); }
/// <summary> /// Returns the tiles as booleans indicating whether they're solid. /// </summary> public bool[,] Generate(BiomeTile[,] biomes, List <Room> rooms, int nThreads, int seed) { //Use a blend between a room's biome and the tile's own biome. BiomeTile[,] oldBiomes = biomes; biomes = new BiomeTile[oldBiomes.GetLength(0), oldBiomes.GetLength(1)]; foreach (Vector2i tilePos in biomes.AllIndices()) { Room r = rooms.FirstOrDefault(_r => _r.Spaces.Contains(tilePos)); if (r == null) { biomes.Set(tilePos, oldBiomes.Get(tilePos)); } else { biomes.Set(tilePos, new BiomeTile(r.Biome, oldBiomes.Get(tilePos), TileVariation)); } } //Turn the room data into a grid of tiles. bool[,] tiles1 = new bool[biomes.GetLength(0), biomes.GetLength(1)]; foreach (Vector2i tilePos in tiles1.AllIndices()) { tiles1.Set(tilePos, !rooms.Any(r => r.Spaces.Contains(tilePos))); } //Create a second copy to ping-pong back and forth between iterations. bool[,] tiles2 = new bool[tiles1.GetLength(0), tiles1.GetLength(1)]; foreach (Vector2i tilePos in tiles2.AllIndices()) { tiles2.Set(tilePos, tiles1.Get(tilePos)); } //Run the cellular automata. for (int i = 0; i < NIterations; ++i) { ThreadedRunner.Run(nThreads, tiles1.GetLength(1), (startI, endI) => RunIteration(startI, endI, biomes, seed, tiles1, tiles2)); //Swap tiles1 and tiles2. bool[,] _tiles1 = tiles1; tiles1 = tiles2; tiles2 = _tiles1; } return(tiles1); }