mandelbrot.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. Simple SAF program for exploring the Mandelbrot set, arrows to move, A/B to
  3. zoom.
  4. by drummyfish, released under CC0 1.0, public domain
  5. */
  6. #define SAF_PROGRAM_NAME "Mandelbrot"
  7. #define SAF_SETTING_ENABLE_SOUND 0
  8. #include "../saf.h"
  9. /*
  10. Checks whether the point is in the mandelbrot set, returns number of
  11. iterations, up until 255, to which the point did not diverge to infinity, i.e.
  12. 255 means probably inside the set.
  13. */
  14. uint8_t iteratePoint(double x, double y)
  15. {
  16. // writing this without floats is left as an excercise for the reader
  17. double current[2];
  18. current[0] = x;
  19. current[1] = y;
  20. uint8_t iterations = 0;
  21. while (1)
  22. {
  23. double
  24. newX = current[0] * current[0] - current[1] * current[1] + x,
  25. newY = 2 * current[0] * current[1] + y;
  26. current[0] = newX;
  27. current[1] = newY;
  28. #define INF 999999999999
  29. if (iterations == 255 ||
  30. current[0] > INF || current[0] < -INF ||
  31. current[1] > INF || current[1] < -INF)
  32. break;
  33. #undef INF
  34. iterations++;
  35. }
  36. return iterations;
  37. }
  38. double
  39. cx = -1,
  40. cy = -1,
  41. step = 2.0 / SAF_SCREEN_WIDTH;
  42. void draw(void)
  43. {
  44. double dx, dy = cy, halfStep = step / 2;
  45. for (int y = 0; y < SAF_SCREEN_HEIGHT; ++y)
  46. {
  47. dx = cx;
  48. for (int x = 0; x < SAF_SCREEN_WIDTH; ++x)
  49. {
  50. // antialias (sample at 4 points):
  51. uint8_t r = 0,g = 0,b = 0;
  52. uint16_t rr = 0, gg = 0, bb = 0;
  53. SAF_colorToRGB(iteratePoint(dx,dy), &r, &g, &b);
  54. rr = r; gg = g; bb = b;
  55. SAF_colorToRGB(iteratePoint(dx + halfStep,dy), &r, &g, &b);
  56. rr += r; gg += g; bb += b;
  57. SAF_colorToRGB(iteratePoint(dx,dy + halfStep), &r, &g, &b);
  58. rr += r; gg += g; bb += b;
  59. SAF_colorToRGB(iteratePoint(dx + halfStep,dy + halfStep), &r, &g, &b);
  60. rr += r; gg += g; bb += b;
  61. SAF_drawPixel(x,y,SAF_colorFromRGB(rr / 4, gg / 4, bb / 4));
  62. dx += step;
  63. }
  64. dy += step;
  65. }
  66. }
  67. void SAF_init(void)
  68. {
  69. draw();
  70. }
  71. uint8_t SAF_loop(void)
  72. {
  73. uint8_t redraw = 1;
  74. #define STEP 10
  75. if (SAF_buttonJustPressed(SAF_BUTTON_LEFT))
  76. cx -= step * STEP;
  77. else if (SAF_buttonJustPressed(SAF_BUTTON_RIGHT))
  78. cx += step * STEP;
  79. else if (SAF_buttonJustPressed(SAF_BUTTON_UP))
  80. cy -= step * STEP;
  81. else if (SAF_buttonJustPressed(SAF_BUTTON_DOWN))
  82. cy += step * STEP;
  83. else if (SAF_buttonJustPressed(SAF_BUTTON_A))
  84. {
  85. // zoom and shift
  86. step /= 2;
  87. cx += step / 2 * SAF_SCREEN_WIDTH;
  88. cy += step / 2 * SAF_SCREEN_HEIGHT;
  89. }
  90. else if (SAF_buttonJustPressed(SAF_BUTTON_B))
  91. {
  92. step *= 2;
  93. cx -= step / 4 * SAF_SCREEN_WIDTH;
  94. cy -= step / 4 * SAF_SCREEN_HEIGHT;
  95. }
  96. else
  97. redraw = 0;
  98. #undef STEP
  99. if (redraw) // only redraw when needed, it's expensive
  100. draw();
  101. return 1;
  102. }