A mandelbrot renderer for the pokitto.
main.cpp@0:8a49a4178a0e, 2018-06-17 (annotated)
- Committer:
- ensonic
- Date:
- Sun Jun 17 18:44:38 2018 +0000
- Revision:
- 0:8a49a4178a0e
Mandelbrot renderer for pokitto.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ensonic | 0:8a49a4178a0e | 1 | #include "Pokitto.h" |
ensonic | 0:8a49a4178a0e | 2 | |
ensonic | 0:8a49a4178a0e | 3 | Pokitto::Core game; |
ensonic | 0:8a49a4178a0e | 4 | |
ensonic | 0:8a49a4178a0e | 5 | #define RGB888_565(r, g, b) ((r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11)) |
ensonic | 0:8a49a4178a0e | 6 | #define GRAY888_565(g) ((g >> 3) | ((g >> 2) << 5) | ((g >> 3) << 11)) |
ensonic | 0:8a49a4178a0e | 7 | |
ensonic | 0:8a49a4178a0e | 8 | // TODO: need more colors, palette is always PALETTE_SIZE=256 |
ensonic | 0:8a49a4178a0e | 9 | const uint16_t palette[] = |
ensonic | 0:8a49a4178a0e | 10 | { |
ensonic | 0:8a49a4178a0e | 11 | GRAY888_565(0x00), |
ensonic | 0:8a49a4178a0e | 12 | GRAY888_565(0x10), |
ensonic | 0:8a49a4178a0e | 13 | GRAY888_565(0x20), |
ensonic | 0:8a49a4178a0e | 14 | GRAY888_565(0x30), |
ensonic | 0:8a49a4178a0e | 15 | GRAY888_565(0x40), |
ensonic | 0:8a49a4178a0e | 16 | GRAY888_565(0x50), |
ensonic | 0:8a49a4178a0e | 17 | GRAY888_565(0x60), |
ensonic | 0:8a49a4178a0e | 18 | GRAY888_565(0x70), |
ensonic | 0:8a49a4178a0e | 19 | GRAY888_565(0x80), |
ensonic | 0:8a49a4178a0e | 20 | GRAY888_565(0x90), |
ensonic | 0:8a49a4178a0e | 21 | GRAY888_565(0xA0), |
ensonic | 0:8a49a4178a0e | 22 | GRAY888_565(0xB0), |
ensonic | 0:8a49a4178a0e | 23 | GRAY888_565(0xC0), |
ensonic | 0:8a49a4178a0e | 24 | GRAY888_565(0xD0), |
ensonic | 0:8a49a4178a0e | 25 | GRAY888_565(0xE0), |
ensonic | 0:8a49a4178a0e | 26 | GRAY888_565(0xF0), |
ensonic | 0:8a49a4178a0e | 27 | }; |
ensonic | 0:8a49a4178a0e | 28 | |
ensonic | 0:8a49a4178a0e | 29 | /* calculate mandelbrot/julia set |
ensonic | 0:8a49a4178a0e | 30 | * KEYS |
ensonic | 0:8a49a4178a0e | 31 | * - color cycle: left, right |
ensonic | 0:8a49a4178a0e | 32 | * - zoom-in/out: up, down |
ensonic | 0:8a49a4178a0e | 33 | * - move center: A + up/down/left/right |
ensonic | 0:8a49a4178a0e | 34 | * |
ensonic | 0:8a49a4178a0e | 35 | * TODO: |
ensonic | 0:8a49a4178a0e | 36 | * - increase/decrease max iter: B + up/down |
ensonic | 0:8a49a4178a0e | 37 | * - switch between mandel/julia: C |
ensonic | 0:8a49a4178a0e | 38 | * - will also reset x1/x2/y1/y2 and max-iter |
ensonic | 0:8a49a4178a0e | 39 | */ |
ensonic | 0:8a49a4178a0e | 40 | |
ensonic | 0:8a49a4178a0e | 41 | static const uint8_t width = (POK_LCD_W / 2); |
ensonic | 0:8a49a4178a0e | 42 | static const uint8_t height = (POK_LCD_H / 2); |
ensonic | 0:8a49a4178a0e | 43 | |
ensonic | 0:8a49a4178a0e | 44 | static float x1 = -2.2; |
ensonic | 0:8a49a4178a0e | 45 | static float x2 = 1.5; |
ensonic | 0:8a49a4178a0e | 46 | static float xd = x2 - x1; |
ensonic | 0:8a49a4178a0e | 47 | static float xs = xd / width; |
ensonic | 0:8a49a4178a0e | 48 | static float y1 = -1.5; |
ensonic | 0:8a49a4178a0e | 49 | static float y2 = 1.5; |
ensonic | 0:8a49a4178a0e | 50 | static float yd = y2 - y1; |
ensonic | 0:8a49a4178a0e | 51 | static float ys = yd / height; |
ensonic | 0:8a49a4178a0e | 52 | |
ensonic | 0:8a49a4178a0e | 53 | static uint16_t mandel_pixel(float startReal, float startImag) { |
ensonic | 0:8a49a4178a0e | 54 | float zReal = startReal; |
ensonic | 0:8a49a4178a0e | 55 | float zImag = startImag; |
ensonic | 0:8a49a4178a0e | 56 | |
ensonic | 0:8a49a4178a0e | 57 | for (uint16_t counter = 0; counter < 50; counter++) { |
ensonic | 0:8a49a4178a0e | 58 | // z := z*z + c |
ensonic | 0:8a49a4178a0e | 59 | float r2 = zReal * zReal; |
ensonic | 0:8a49a4178a0e | 60 | float i2 = zImag * zImag; |
ensonic | 0:8a49a4178a0e | 61 | if (r2 + i2 > 4.0) { |
ensonic | 0:8a49a4178a0e | 62 | return counter; |
ensonic | 0:8a49a4178a0e | 63 | } |
ensonic | 0:8a49a4178a0e | 64 | zImag = 2.0 * zReal * zImag + startImag; |
ensonic | 0:8a49a4178a0e | 65 | zReal = r2 - i2 + startReal; |
ensonic | 0:8a49a4178a0e | 66 | } |
ensonic | 0:8a49a4178a0e | 67 | return 0; |
ensonic | 0:8a49a4178a0e | 68 | } |
ensonic | 0:8a49a4178a0e | 69 | |
ensonic | 0:8a49a4178a0e | 70 | static void mandel_screen(void) { |
ensonic | 0:8a49a4178a0e | 71 | for (uint8_t ypos = 0; ypos < height; ypos++) { |
ensonic | 0:8a49a4178a0e | 72 | float startImag = y1 + (ys * ypos); |
ensonic | 0:8a49a4178a0e | 73 | for (uint8_t xpos = 0; xpos < width; xpos++) { |
ensonic | 0:8a49a4178a0e | 74 | float startReal = x1 + (xs * xpos); |
ensonic | 0:8a49a4178a0e | 75 | uint8_t color = mandel_pixel(startReal, startImag) % 0x0f; |
ensonic | 0:8a49a4178a0e | 76 | game.display.drawPixel(xpos, ypos, color); |
ensonic | 0:8a49a4178a0e | 77 | } |
ensonic | 0:8a49a4178a0e | 78 | game.display.update(); |
ensonic | 0:8a49a4178a0e | 79 | } |
ensonic | 0:8a49a4178a0e | 80 | } |
ensonic | 0:8a49a4178a0e | 81 | |
ensonic | 0:8a49a4178a0e | 82 | int main () { |
ensonic | 0:8a49a4178a0e | 83 | game.begin(); |
ensonic | 0:8a49a4178a0e | 84 | game.display.load565Palette(palette); |
ensonic | 0:8a49a4178a0e | 85 | |
ensonic | 0:8a49a4178a0e | 86 | // don't clear the screen |
ensonic | 0:8a49a4178a0e | 87 | game.display.persistence = 1; |
ensonic | 0:8a49a4178a0e | 88 | bool recalc = true; |
ensonic | 0:8a49a4178a0e | 89 | |
ensonic | 0:8a49a4178a0e | 90 | while (game.isRunning()) { |
ensonic | 0:8a49a4178a0e | 91 | if (game.update()) { |
ensonic | 0:8a49a4178a0e | 92 | if (game.aBtn()) { |
ensonic | 0:8a49a4178a0e | 93 | // scroll |
ensonic | 0:8a49a4178a0e | 94 | if (game.leftBtn()) { |
ensonic | 0:8a49a4178a0e | 95 | float mx = 10.0 * xs; |
ensonic | 0:8a49a4178a0e | 96 | x1 -= mx; |
ensonic | 0:8a49a4178a0e | 97 | x2 -= mx; |
ensonic | 0:8a49a4178a0e | 98 | recalc = true; |
ensonic | 0:8a49a4178a0e | 99 | } else if (game.rightBtn()) { |
ensonic | 0:8a49a4178a0e | 100 | float mx = 10.0 * xs; |
ensonic | 0:8a49a4178a0e | 101 | x1 += mx; |
ensonic | 0:8a49a4178a0e | 102 | x2 += mx; |
ensonic | 0:8a49a4178a0e | 103 | recalc = true; |
ensonic | 0:8a49a4178a0e | 104 | } else if (game.upBtn()) { |
ensonic | 0:8a49a4178a0e | 105 | float my = 10.0 * ys; |
ensonic | 0:8a49a4178a0e | 106 | y1 -= my; |
ensonic | 0:8a49a4178a0e | 107 | y2 -= my; |
ensonic | 0:8a49a4178a0e | 108 | recalc = true; |
ensonic | 0:8a49a4178a0e | 109 | } else if (game.downBtn()) { |
ensonic | 0:8a49a4178a0e | 110 | float my = 10.0 * ys; |
ensonic | 0:8a49a4178a0e | 111 | y1 += my; |
ensonic | 0:8a49a4178a0e | 112 | y2 += my; |
ensonic | 0:8a49a4178a0e | 113 | recalc = true; |
ensonic | 0:8a49a4178a0e | 114 | } |
ensonic | 0:8a49a4178a0e | 115 | } else { |
ensonic | 0:8a49a4178a0e | 116 | // cycle colors & zoom |
ensonic | 0:8a49a4178a0e | 117 | if (game.leftBtn()) { |
ensonic | 0:8a49a4178a0e | 118 | game.display.rotatePalette(-1); |
ensonic | 0:8a49a4178a0e | 119 | } else if (game.rightBtn()) { |
ensonic | 0:8a49a4178a0e | 120 | game.display.rotatePalette(1); |
ensonic | 0:8a49a4178a0e | 121 | } else if (game.upBtn()) { |
ensonic | 0:8a49a4178a0e | 122 | // zoom in |
ensonic | 0:8a49a4178a0e | 123 | xd /= 2.0; |
ensonic | 0:8a49a4178a0e | 124 | float xm = x1 + xd; |
ensonic | 0:8a49a4178a0e | 125 | x1 = xm - xd / 2.0; |
ensonic | 0:8a49a4178a0e | 126 | x2 = xm + xd / 2.0; |
ensonic | 0:8a49a4178a0e | 127 | xs = xd / width; |
ensonic | 0:8a49a4178a0e | 128 | |
ensonic | 0:8a49a4178a0e | 129 | yd /= 2.0; |
ensonic | 0:8a49a4178a0e | 130 | float ym = y1 + yd; |
ensonic | 0:8a49a4178a0e | 131 | y1 = ym - yd / 2.0; |
ensonic | 0:8a49a4178a0e | 132 | y2 = ym + yd / 2.0; |
ensonic | 0:8a49a4178a0e | 133 | ys = yd / height; |
ensonic | 0:8a49a4178a0e | 134 | |
ensonic | 0:8a49a4178a0e | 135 | recalc = true; |
ensonic | 0:8a49a4178a0e | 136 | } else if (game.downBtn()) { |
ensonic | 0:8a49a4178a0e | 137 | // zoom out |
ensonic | 0:8a49a4178a0e | 138 | float xm = x1 + xd / 2.0; |
ensonic | 0:8a49a4178a0e | 139 | x1 = xm - xd; |
ensonic | 0:8a49a4178a0e | 140 | x2 = xm + xd; |
ensonic | 0:8a49a4178a0e | 141 | xd *= 2.0; |
ensonic | 0:8a49a4178a0e | 142 | xs = xd / width; |
ensonic | 0:8a49a4178a0e | 143 | |
ensonic | 0:8a49a4178a0e | 144 | float ym = y1 + yd / 2.0; |
ensonic | 0:8a49a4178a0e | 145 | y1 = ym - yd; |
ensonic | 0:8a49a4178a0e | 146 | y2 = ym + yd; |
ensonic | 0:8a49a4178a0e | 147 | yd *= 2.0; |
ensonic | 0:8a49a4178a0e | 148 | ys = yd / height; |
ensonic | 0:8a49a4178a0e | 149 | |
ensonic | 0:8a49a4178a0e | 150 | recalc = true; |
ensonic | 0:8a49a4178a0e | 151 | } |
ensonic | 0:8a49a4178a0e | 152 | } |
ensonic | 0:8a49a4178a0e | 153 | if (recalc) { |
ensonic | 0:8a49a4178a0e | 154 | mandel_screen(); |
ensonic | 0:8a49a4178a0e | 155 | recalc = false; |
ensonic | 0:8a49a4178a0e | 156 | } |
ensonic | 0:8a49a4178a0e | 157 | } |
ensonic | 0:8a49a4178a0e | 158 | } |
ensonic | 0:8a49a4178a0e | 159 | } |