A mandelbrot renderer for the pokitto.

Dependencies:   PokittoLib

Committer:
ensonic
Date:
Sun Jun 17 18:44:38 2018 +0000
Revision:
0:8a49a4178a0e
Mandelbrot renderer for pokitto.

Who changed what in which revision?

UserRevisionLine numberNew 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 }