Guest User

Untitled

a guest
Aug 28th, 2020
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.40 KB | None | 0 0
  1. using SDL2;
  2. namespace ScenesSandbox
  3. {
  4. class DiamondSquareScene : IPlotter
  5. {
  6. public int32 Width=> 1024;
  7. public int32 Height=> 980;
  8. public int32 Resolution=> 2;
  9.  
  10. float t = 0; bool recording;
  11. DiamondSquare ds = new DiamondSquare(9) ~ delete _;
  12. // Make sure the DiamondSquare is large enough to render with the current width, height and resolution!
  13. // (width and height divided by resolution must be equal or smaller than
  14. // two to the power of the magnitude of the diamond square
  15.  
  16. // i.e 2 ^ 9 = 512, means a max width or height of 1024 with resolution 2, or 512 with resolution 1)
  17. public void Update(Engine.Context context)
  18. {
  19. System.String title = scope System.String();
  20. title.AppendF("FPS: {0}, t: {1}", context.AverageFPS, t);
  21. SDL.SetWindowTitle(context.Window, title);
  22. context.Recording = recording = recording && t < 2;
  23. t += 0.002f;
  24. }
  25.  
  26. public uint32 Plot(int x, int y)
  27. {
  28.  
  29. var sample = (float)ds[x / Resolution][y / Resolution] + t;
  30. sample -= (int)sample;
  31.  
  32. sample *= 6;
  33. let faction = sample - (int)sample;
  34.  
  35. if (sample < 1)
  36. return BlackToRed(faction / 2);
  37. if(sample < 2)
  38. return BlackToRed(0.5f + faction / 2);
  39. if(sample < 3)
  40. return RedToRed(faction);
  41. if(sample < 4)
  42. return RedToBlack(faction);
  43. if(sample < 5)
  44. return BlackToNoise(faction);
  45. return NoiseToBlack(faction);
  46. }
  47.  
  48. public uint32 BlackToRed(float sample)
  49. {
  50. return Engine.MapHSL(sample, 1, System.Math.Min(1, sample / 0.1f) * 0.5f);
  51. }
  52. public uint32 RedToRed(float sample)
  53. {
  54. return Engine.MapHSL(sample, 1, 0.5f);
  55. }
  56. public uint32 RedToBlack(float sample)
  57. {
  58. return Engine.MapHSL(sample * 2, 1, 0.5f);
  59. }
  60. public uint32 BlackToNoise(float sample)
  61. {
  62. return Engine.MapHSL(sample + 2, 1f / (1 - sample), 0.5f / (1 - sample));
  63. }
  64. public uint32 NoiseToBlack(float sample)
  65. {
  66. return Engine.MapHSL(sample + 2, 1f / sample, 0.5f / sample);
  67. }
  68.  
  69. public void HandleEvent(SDL.Event event, out bool quitApplication)
  70. {
  71. quitApplication = (event.type == .Quit);
  72. if (event.type == .KeyUp)
  73. {
  74. t = 0;
  75. if (event.key.keysym.scancode == .KpEnter)
  76. ds.Generate();
  77. if (event.type == .KeyUp && event.key.keysym.scancode == .R)
  78. recording = true;
  79. }
  80. }
  81. }
  82.  
  83. public class DiamondSquare
  84. {
  85. public readonly uint32 Size;
  86.  
  87. double[][] map;
  88. public this(uint8 magnitude)
  89. {
  90. Size = 1 + 1 << magnitude;
  91. map = new double[Size][];
  92. for (var i = 0; i < Size; i++) map[i] = new double[Size];
  93. Generate();
  94. }
  95. public ~this()
  96. {
  97. for (var i = 0; i < Size; i++) delete map[i];
  98. delete map;
  99. }
  100. public double[] this[int k] { get { return map[k]; } }
  101.  
  102. public void Generate()
  103. {
  104. var d = Size - 1;
  105. map[0][0] = rng(); map[d][d] = rng();
  106. map[0][d] = rng(); map[d][0] = rng();
  107.  
  108. while ((d /= 2) > 0)
  109. {
  110. var distance = (double)d / Size;
  111. for (var x = d; x < Size; x += d * 2) for (var y = d; y < Size; y += d * 2)
  112. map[x][y] = adjusted_average(diamond_average(x, y, d), distance);
  113. for (var x = d; x < Size; x += d * 2) for (var y = 0; y < Size; y += d * 2)
  114. map[x][y] = adjusted_average(square_average(x, y, d), distance);
  115. for (var x = 0; x < Size; x += d * 2) for (var y = d; y < Size; y += d * 2)
  116. map[x][y] = adjusted_average(square_average(x, y, d), distance);
  117. }
  118. }
  119. double adjusted_average(double average, double distance)
  120. {
  121. let rmin = average - distance;
  122. let rmax = average + distance;
  123. let sample = rmin + rng() * (rmax - rmin);
  124. return max(0, min(1, sample));
  125. }
  126. double diamond_average(int x, int y, int d)
  127. {
  128. return (map[x - d][y - d]
  129. + map[x - d][y + d]
  130. + map[x + d][y - d]
  131. + map[x + d][y + d]) / 4f;
  132. }
  133. double square_average(int x, int y, int d)
  134. {
  135. var sum = 0d, num = 0d;
  136. if (x - d > -1) { sum += map[x - d][y]; num++; }
  137. if (x + d < Size) { sum += map[x + d][y]; num++; }
  138. if (y - d > -1) { sum += map[x][y - d]; num++; }
  139. if (y + d < Size) { sum += map[x][y + d]; num++; }
  140. return sum / num;
  141. }
  142.  
  143. // en.wikipedia.org/wiki/Lehmer_random_number_generator
  144. uint32 state = (uint32)System.Platform.BfpSystem_GetTimeStamp();
  145. double rng() => (double)(state = (uint32)((uint64)state * 279470273u % 0xfffffffb)) / uint32.MaxValue;
  146.  
  147. double min(double a, double b) => a < b ? a : b;
  148. double max(double a, double b) => a > b ? a : b;
  149. }
  150. }
  151.  
Advertisement
Add Comment
Please, Sign In to add comment