Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using SDL2;
- namespace ScenesSandbox
- {
- class DiamondSquareScene : IPlotter
- {
- public int32 Width=> 1024;
- public int32 Height=> 980;
- public int32 Resolution=> 2;
- float t = 0; bool recording;
- DiamondSquare ds = new DiamondSquare(9) ~ delete _;
- // Make sure the DiamondSquare is large enough to render with the current width, height and resolution!
- // (width and height divided by resolution must be equal or smaller than
- // two to the power of the magnitude of the diamond square
- // i.e 2 ^ 9 = 512, means a max width or height of 1024 with resolution 2, or 512 with resolution 1)
- public void Update(Engine.Context context)
- {
- System.String title = scope System.String();
- title.AppendF("FPS: {0}, t: {1}", context.AverageFPS, t);
- SDL.SetWindowTitle(context.Window, title);
- context.Recording = recording = recording && t < 2;
- t += 0.002f;
- }
- public uint32 Plot(int x, int y)
- {
- var sample = (float)ds[x / Resolution][y / Resolution] + t;
- sample -= (int)sample;
- sample *= 6;
- let faction = sample - (int)sample;
- if (sample < 1)
- return BlackToRed(faction / 2);
- if(sample < 2)
- return BlackToRed(0.5f + faction / 2);
- if(sample < 3)
- return RedToRed(faction);
- if(sample < 4)
- return RedToBlack(faction);
- if(sample < 5)
- return BlackToNoise(faction);
- return NoiseToBlack(faction);
- }
- public uint32 BlackToRed(float sample)
- {
- return Engine.MapHSL(sample, 1, System.Math.Min(1, sample / 0.1f) * 0.5f);
- }
- public uint32 RedToRed(float sample)
- {
- return Engine.MapHSL(sample, 1, 0.5f);
- }
- public uint32 RedToBlack(float sample)
- {
- return Engine.MapHSL(sample * 2, 1, 0.5f);
- }
- public uint32 BlackToNoise(float sample)
- {
- return Engine.MapHSL(sample + 2, 1f / (1 - sample), 0.5f / (1 - sample));
- }
- public uint32 NoiseToBlack(float sample)
- {
- return Engine.MapHSL(sample + 2, 1f / sample, 0.5f / sample);
- }
- public void HandleEvent(SDL.Event event, out bool quitApplication)
- {
- quitApplication = (event.type == .Quit);
- if (event.type == .KeyUp)
- {
- t = 0;
- if (event.key.keysym.scancode == .KpEnter)
- ds.Generate();
- if (event.type == .KeyUp && event.key.keysym.scancode == .R)
- recording = true;
- }
- }
- }
- public class DiamondSquare
- {
- public readonly uint32 Size;
- double[][] map;
- public this(uint8 magnitude)
- {
- Size = 1 + 1 << magnitude;
- map = new double[Size][];
- for (var i = 0; i < Size; i++) map[i] = new double[Size];
- Generate();
- }
- public ~this()
- {
- for (var i = 0; i < Size; i++) delete map[i];
- delete map;
- }
- public double[] this[int k] { get { return map[k]; } }
- public void Generate()
- {
- var d = Size - 1;
- map[0][0] = rng(); map[d][d] = rng();
- map[0][d] = rng(); map[d][0] = rng();
- while ((d /= 2) > 0)
- {
- var distance = (double)d / Size;
- for (var x = d; x < Size; x += d * 2) for (var y = d; y < Size; y += d * 2)
- map[x][y] = adjusted_average(diamond_average(x, y, d), distance);
- for (var x = d; x < Size; x += d * 2) for (var y = 0; y < Size; y += d * 2)
- map[x][y] = adjusted_average(square_average(x, y, d), distance);
- for (var x = 0; x < Size; x += d * 2) for (var y = d; y < Size; y += d * 2)
- map[x][y] = adjusted_average(square_average(x, y, d), distance);
- }
- }
- double adjusted_average(double average, double distance)
- {
- let rmin = average - distance;
- let rmax = average + distance;
- let sample = rmin + rng() * (rmax - rmin);
- return max(0, min(1, sample));
- }
- double diamond_average(int x, int y, int d)
- {
- return (map[x - d][y - d]
- + map[x - d][y + d]
- + map[x + d][y - d]
- + map[x + d][y + d]) / 4f;
- }
- double square_average(int x, int y, int d)
- {
- var sum = 0d, num = 0d;
- if (x - d > -1) { sum += map[x - d][y]; num++; }
- if (x + d < Size) { sum += map[x + d][y]; num++; }
- if (y - d > -1) { sum += map[x][y - d]; num++; }
- if (y + d < Size) { sum += map[x][y + d]; num++; }
- return sum / num;
- }
- // en.wikipedia.org/wiki/Lehmer_random_number_generator
- uint32 state = (uint32)System.Platform.BfpSystem_GetTimeStamp();
- double rng() => (double)(state = (uint32)((uint64)state * 279470273u % 0xfffffffb)) / uint32.MaxValue;
- double min(double a, double b) => a < b ? a : b;
- double max(double a, double b) => a > b ? a : b;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment