samples/guiAndGfx: Added a Mandelbrot sample (simpler than 'fractals')
authorJerome St-Louis <jerome@ecere.com>
Fri, 1 Apr 2016 21:12:40 +0000 (17:12 -0400)
committerJerome St-Louis <jerome@ecere.com>
Fri, 29 Apr 2016 16:27:01 +0000 (12:27 -0400)
samples/guiAndGfx/mandelbrot/mandelbrot.ec [new file with mode: 0644]
samples/guiAndGfx/mandelbrot/mandelbrot.epj [new file with mode: 0644]
samples/guiAndGfx/mandelbrot/mandelbrotUI.ec [new file with mode: 0644]

diff --git a/samples/guiAndGfx/mandelbrot/mandelbrot.ec b/samples/guiAndGfx/mandelbrot/mandelbrot.ec
new file mode 100644 (file)
index 0000000..18294c3
--- /dev/null
@@ -0,0 +1,57 @@
+#ifdef ECERE_STATIC
+import static "ecere"
+#else
+import "ecere"
+#endif
+
+struct Complex { double a, b; };
+
+void drawMandelbrot(Bitmap bmp, float range, Complex center, ColorAlpha * palette, int nPalEntries, int nIterations, float scale)
+{
+   int x, y;
+   int w = bmp.width, h = bmp.height;
+   ColorAlpha * picture = (ColorAlpha *)bmp.picture;
+   double logOf2 = log(2);
+   Complex d
+   {
+      w > h ? range : range * w / h,
+      h > w ? range : range * h / w
+   };
+   Complex C0 { center.a - d.a/2, center.b - d.b/2 };
+   Complex C = C0;
+   double delta = d.a / w;
+
+   for(y = 0; y < h; y++, C.a = C0.a, C.b += delta)
+   {
+      for(x = 0; x < w; x++, picture++, C.a += delta)
+      {
+         Complex Z { };
+         int i;
+         double ii = 0;
+         bool out = false;
+         for(i = 0; i < nIterations; i++)
+         {
+            double zm;
+            Z = { Z.a*Z.a - Z.b*Z.b, Z.a*Z.b + Z.b*Z.a };
+            Z.a += C.a;
+            Z.b += C.b;
+            zm = sqrt(Z.a * Z.a + Z.b * Z.b);
+
+            if(zm >= 2)
+            {
+               ii = (double)(i + 1 - log(log(zm)) / logOf2);
+               out = true;
+               break;
+            }
+         }
+         if(out)
+         {
+            float si = (float)(ii * scale);
+            int i0 = ((int)si) % nPalEntries;
+            *picture = palette[i0];
+         }
+         else
+            *picture = black;
+      }
+   }
+}
diff --git a/samples/guiAndGfx/mandelbrot/mandelbrot.epj b/samples/guiAndGfx/mandelbrot/mandelbrot.epj
new file mode 100644 (file)
index 0000000..ae8686b
--- /dev/null
@@ -0,0 +1,90 @@
+{
+   "Version" : 0.2,
+   "ModuleName" : "mandelbrot",
+   "Options" : {
+      "Warnings" : "All",
+      "TargetType" : "Executable",
+      "TargetFileName" : "mandelbrot",
+      "Libraries" : [
+         "ecere"
+      ]
+   },
+   "Configurations" : [
+      {
+         "Name" : "Debug",
+         "Options" : {
+            "Debug" : true,
+            "Optimization" : "Speed",
+            "PreprocessorDefinitions" : [
+               "_DEBUG"
+            ],
+            "CompilerOptions" : [
+               "-mmmx",
+               "-msse",
+               "-msse2",
+               "-msse3",
+               "-msse4"
+            ],
+            "FastMath" : true
+         }
+      },
+      {
+         "Name" : "Release",
+         "Options" : {
+            "Debug" : false,
+            "Optimization" : "Speed",
+            "FastMath" : true
+         }
+      },
+      {
+         "Name" : "Emscripten",
+         "Options" : {
+            "PreprocessorDefinitions" : [
+               "ECERE_STATIC"
+            ],
+            "TargetFileName" : "mandelbrot.html",
+            "Libraries" : [
+               "ecereStatic",
+               "z",
+               "jpeg",
+               "png",
+               "freetype"
+            ],
+            "LibraryDirs" : [
+               "../../../ecere/obj/emscripten.linux.emscripten"
+            ],
+            "FastMath" : true
+         }
+      }
+   ],
+   "Files" : [
+      "mandelbrot.ec",
+      "mandelbrotUI.ec"
+   ],
+   "ResourcesPath" : "",
+   "Resources" : [
+      {
+         "Folder" : "ecere",
+         "Files" : [
+            {
+               "Folder" : "shaders",
+               "Files" : [
+                  "../../../ecere/src/gfx/drivers/gl3/fixed.frag",
+                  "../../../ecere/src/gfx/drivers/gl3/fixed.vertex"
+               ]
+            }
+         ],
+         "Options" : {
+            "ExcludeFromBuild" : true
+         },
+         "Configurations" : [
+            {
+               "Name" : "Emscripten",
+               "Options" : {
+                  "ExcludeFromBuild" : false
+               }
+            }
+         ]
+      }
+   ]
+}
diff --git a/samples/guiAndGfx/mandelbrot/mandelbrotUI.ec b/samples/guiAndGfx/mandelbrot/mandelbrotUI.ec
new file mode 100644 (file)
index 0000000..3cf72bf
--- /dev/null
@@ -0,0 +1,148 @@
+import "mandelbrot"
+
+class Mandelbrot : Window
+{
+   caption = $"Mandelbrot";
+#if defined(__EMSCRIPTEN__)
+   anchor = { 0,0,0,0 };
+#else
+   borderStyle = sizable;
+   hasMaximize = true;
+   hasMinimize = true;
+   hasClose = true;
+   clientSize = { 600, 600 };
+#endif
+
+   Point mouseStart, mouseEnd;
+   bool dragging;
+   bool needUpdate;
+
+   float scale;
+   int nIterations; nIterations = 256;
+   ColorAlpha * palette;
+   int nPalEntries;
+   Complex center { -0.75, 0 };
+
+   float range; range = 4;
+   Bitmap bmp { };
+
+   Mandelbrot()
+   {
+      static ColorKey keys[] =
+      {
+         { navy, 0.0f },
+         { Color { 146, 213, 237 }, 0.198606268f },
+         { white, 0.3f },
+         { Color { 255, 255, 124 }, 0.444250882f },
+         { Color { 255, 100, 0 }, 0.634146333f },
+         { navy, 1 }
+      };
+
+      nPalEntries = 30000;
+      palette = new ColorAlpha[nPalEntries];
+      scale = nPalEntries / 175.0f;
+      PaletteGradient(palette, nPalEntries, keys, sizeof(keys)/sizeof(keys[0]), 1.0);
+      needUpdate = true;
+   }
+
+   ~Mandelbrot() { delete palette; }
+
+   void OnRedraw(Surface surface)
+   {
+      if(needUpdate)
+      {
+#if defined(__EMSCRIPTEN__)
+         bmp.Free();
+         bmp.Allocate(null, clientSize.w, clientSize.h, 0, pixelFormat888, false);
+#endif
+         drawMandelbrot(bmp, range, center, palette, nPalEntries, nIterations, scale);
+#if defined(__EMSCRIPTEN__)
+         bmp.MakeDD(displaySystem);
+#endif
+         needUpdate = false;
+      }
+      surface.Blit(bmp, 0,0, 0,0, bmp.width, bmp.height);
+
+      if(dragging)
+      {
+         surface.foreground = lime;
+         surface.Rectangle(mouseStart.x, mouseStart.y, mouseEnd.x, mouseEnd.y);
+      }
+   }
+
+   bool OnLeftButtonDown(int x, int y, Modifiers mods)
+   {
+      mouseEnd = mouseStart = { x, y };
+      Capture();
+      dragging = true;
+      Update(null);
+      return true;
+   }
+
+   bool OnLeftButtonUp(int x, int y, Modifiers mods)
+   {
+      if(dragging)
+      {
+         int dx = Abs(mouseEnd.x - mouseStart.x), dy = Abs(mouseEnd.y - mouseStart.y);
+         if(dx > 4 && dy > 4)
+         {
+            int w = clientSize.w, h = clientSize.h;
+            float rangeX = w > h ? range : range * w / h;
+            float rangeY = h > w ? range : range * h / w;
+
+            center.a += ((mouseStart.x + mouseEnd.x) - w) / 2.0f * rangeX / w;
+            center.b += ((mouseStart.y + mouseEnd.y) - h) / 2.0f * rangeY / h;
+
+            range = dy > dx ? dy * range / h : dx * range / w;
+
+            needUpdate = true;
+            Update(null);
+         }
+         ReleaseCapture();
+         dragging = false;
+      }
+      return true;
+   }
+
+   bool OnMouseMove(int x, int y, Modifiers mods)
+   {
+      if(dragging)
+      {
+         mouseEnd = { x, y };
+         Update(null);
+      }
+      return true;
+   }
+
+   bool OnRightButtonDown(int x, int y, Modifiers mods)
+   {
+      range = 4;
+      nIterations = 256;
+      center = { -0.75, 0 };
+      needUpdate = true;
+      Update(null);
+      return true;
+   }
+
+   void OnResize(int width, int height)
+   {
+      bmp.Allocate(null, width, height, 0, pixelFormat888, false);
+      needUpdate = true;
+      Update(null);
+   }
+
+   bool OnKeyHit(Key key, unichar ch)
+   {
+      switch(key)
+      {
+         case space: case keyPadPlus: case plus:
+            nIterations += 256;
+            needUpdate = true;
+            Update(null);
+            break;
+      }
+      return true;
+   }
+}
+
+Mandelbrot mandelbrotForm {};