From 0890ce4a2e017bfa58bf53650692af3be0032bf6 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Thu, 28 Mar 2013 17:20:29 +0000
Subject: [PATCH] [Add] Hellz YEAH! Here's some initial plasma fractals, all
 working and stuff.

---
 src/colour.c  |  1 +
 src/colour.h  |  1 +
 src/menu.c    |  8 +++++
 src/plasmaf.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/plasmaf.h |  5 +++
 src/toolkit.c | 12 ++++++-
 src/toolkit.h |  2 ++
 7 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 src/plasmaf.c
 create mode 100644 src/plasmaf.h

diff --git a/src/colour.c b/src/colour.c
index 49d220a..d04a8c4 100644
--- a/src/colour.c
+++ b/src/colour.c
@@ -19,6 +19,7 @@ glColour cRed       = { .r = 0.80, .g = 0.20, .b = 0.20, .a = 1. };
 glColour cYellow    = { .r = 0.80, .g = 0.80, .b = 0.00, .a = 1. };
 glColour cDarkBlue  = { .r = 0.10, .g = 0.20, .b = 0.80, .a = 1. };
 glColour cBlue      = { .r = 0.20, .g = 0.20, .b = 0.80, .a = 1. };
+glColour cPurple    = { .r = 0.90, .g = 0.10, .b = 0.90, .a = 1. };
 
 // Game specific.
 glColour cConsole           = { .r = 0.1, .g = 0.9, .b = 0.1, .a = 1. };
diff --git a/src/colour.h b/src/colour.h
index a53467c..817f34c 100644
--- a/src/colour.h
+++ b/src/colour.h
@@ -28,6 +28,7 @@ extern glColour cRed;
 extern glColour cYellow;
 extern glColour cDarkBlue;
 extern glColour cBlue;
+extern glColour cPurple;
 
 // Game specific.
 extern glColour cConsole;
diff --git a/src/menu.c b/src/menu.c
index b602d30..013d383 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -8,6 +8,7 @@
 #include "pilot.h"
 #include "space.h"
 #include "player.h"
+#include "plasmaf.h"
 #include "menu.h"
 
 #define MAIN_WIDTH          130
@@ -45,10 +46,15 @@ static void menu_death_main(char* str);
 
 void menu_main(void) {
   unsigned int bwid, wid;
+  glTexture* tex;
+
+  tex = pf_genFractal(gl_screen.w, gl_screen.h, 10.);
 
   // Create background image window.
   bwid = window_create("BG", -1, -1, gl_screen.w, gl_screen.h);
   window_addRect(bwid, 0, 0, gl_screen.w, gl_screen.h, "rctBG", &cBlack, 0);
+  window_addImage(bwid, 0, 0, "imgBG", tex, 0);
+  window_imgColour(bwid, "imgBG", &cPurple);
 
   // Create menu window.
   wid = window_create("Main Menu", -1, -1, MAIN_WIDTH, MAIN_HEIGHT);
@@ -69,6 +75,8 @@ void menu_main(void) {
 
 static void menu_main_close(void) {
   window_destroy(window_get("Main Menu"));
+
+  gl_freeTexture(window_getImage(window_get("BG"), "imgBG"));
   window_destroy(window_get("BG"));
 
   menu_Close(MENU_MAIN);
diff --git a/src/plasmaf.c b/src/plasmaf.c
new file mode 100644
index 0000000..7b6903e
--- /dev/null
+++ b/src/plasmaf.c
@@ -0,0 +1,99 @@
+#include "SDL.h"
+
+#include "log.h"
+#include "rng.h"
+#include "opengl.h"
+#include "plasmaf.h"
+
+static double* pf_genFractalMap(const int w, const int h, double rug);
+static void pf_divFractal(double* map, const double x, const double y,
+                          const double w, const double h, const 
+                          double rw, const double rh, double c1,
+                          double c2, double c3, double c4, double rug);
+
+// Acutally generate the fractal and loads it up in an opengl texture.
+glTexture* pf_genFractal(const int w, const int h, double rug) {
+  int i;
+  double* map;
+  SDL_Surface* sur;
+  uint32_t* pix;
+  glTexture* tex;
+
+  map = pf_genFractalMap(w, h, rug);
+
+  sur = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RGBMASK);
+  pix = sur->pixels;
+
+  // Convert from mapping to actual colours.
+  SDL_LockSurface(sur);
+  for(i = 0; i < h*w; i++) {
+    pix[i] = RMASK + BMASK + GMASK + (AMASK & (uint32_t)(AMASK*5000*map[i]));
+    //DEBUG("amask [%d]: %f [%u]", i, 1000*map[i],
+           //(AMASK & (uint32_t)(AMASK*1000*map[i])));
+  }
+  SDL_UnlockSurface(sur);
+
+  free(map);
+
+  tex = gl_loadImage(sur);
+
+  return tex;
+}
+
+static double* pf_genFractalMap(const int w, const int h, double rug) {
+  double* map; // We'll use it to map out the fractal before saving.
+  double cx, cy;
+
+  map = malloc(w*h * sizeof(double));
+
+  // Set up initial values.
+  cx = (double)w/2;
+  cy = (double)h/2;
+
+  // Start by doing the four squares.
+  pf_divFractal(map, 0,   0,  cx, cy, w, h, 0., 0., 1., 0., rug);
+  pf_divFractal(map, cx,  0,  cx, cy, w, h, 0., 0., 0., 1., rug);
+  pf_divFractal(map, cx,  cy, cx, cy, w, h, 1., 0., 0., 0., rug);
+  pf_divFractal(map, 0,   cy, cx, cy, w, h, 0., 1., 0., 0., rug); 
+
+  return map;
+}
+
+static void pf_divFractal(double* map, const double x, const double y,
+                          const double w, const double h, const double rw,
+                          const double rh, double c1, double c2, double c3,
+                          double c4, double rug) {
+
+  double nw, nh; // New dimensions.
+  double m, e1, e2, e3, e4; // Middle and edges.
+
+  // Still need to subdivide.
+  if((w>1.) || (h>1.)) {
+    // Calculate new dimensions.
+    nw = w/2.;
+    nh = h/2.;
+
+    // Edges.
+    m   = (c1 + c2 + c3 + c4)/4.;
+    e1  = (c1 + c2)/2.;
+    e2  = (c2 + c3)/2.;
+    e3  = (c3 + c4)/2.;
+    e4  = (c4 + c1)/2.;
+
+    // Now change the middle colour.
+    //DEBUG("%f + %f", m, rug*(RNGF()-0.5) * ((nw+nh)/(rw+rh)*1000));
+    m += rug*(RNGF()-0.5)*((nw+nh)/(rw+rh)*3.);
+    if(m < 0.) m = 0.;
+    else if(m>1.) m = 1.;
+
+    // Recursivation.
+    pf_divFractal(map, x,    y,     nw, nh, rw, rh, c1, e1, m,  e4, rug);
+    pf_divFractal(map, x+nw, y,     nw, nh, rw, rh, e1, c2, e2, m,  rug);
+    pf_divFractal(map, x+nw, y+nh,  nw, nh, rw, rh, m,  e2, c3, e3, rug);
+    pf_divFractal(map, x,    y+nh,  nw, nh, rw, rh, e4, m,  e3, c4, rug);
+  } else
+    // Actually write the pixel.
+    //map[y*rw+x] = (c1 + c2 + c3 + c4)/4.;
+    map[(int)round(y)*(int)rw+(int)round(x)] = (c1 + c2 + c3 + c4)/4.;
+}
+
diff --git a/src/plasmaf.h b/src/plasmaf.h
new file mode 100644
index 0000000..6bb5435
--- /dev/null
+++ b/src/plasmaf.h
@@ -0,0 +1,5 @@
+#pragma once
+#include "opengl.h"
+
+glTexture* pf_genFractal(const int w, const int h, const double rug);
+
diff --git a/src/toolkit.c b/src/toolkit.c
index c19bb0d..e54228c 100644
--- a/src/toolkit.c
+++ b/src/toolkit.c
@@ -50,6 +50,7 @@ typedef struct Widget_ {
     struct {
       // Widget image.
       glTexture* image;
+      glColour*  colour;
       int border;
     } img;
     struct {
@@ -218,6 +219,8 @@ void window_addImage(const unsigned int wid, const int x, const int y,
   // Set the properties.
   wgt->dat.img.image  = image;
   wgt->dat.img.border = border;
+  wgt->dat.img.colour = NULL; // Normal colour.
+
   wgt->w = (image == NULL) ? 0 : wgt->dat.img.image->sw;
   wgt->h = (image == NULL) ? 0 : wgt->dat.img.image->sh;
   if(x < 0) wgt->x = wdw->w - wgt->w + x;
@@ -375,6 +378,12 @@ void window_modifyImage(const unsigned int wid, char* name, glTexture* image) {
   wgt->dat.img.image = image;
 }
 
+void window_imgColour(const unsigned int wid, char* name, glColour* colour) {
+  Widget* wgt = window_getwgt(wid, name);
+
+  wgt->dat.img.colour = colour;
+}
+
 glTexture* window_getImage(const unsigned int wid, char* name) {
   Widget* wgt = window_getwgt(wid, name);
   return (wgt) ? wgt->dat.img.image : NULL;
@@ -849,7 +858,8 @@ static void toolkit_renderImage(Widget* img, double bx, double by) {
   // Image.
   gl_blitStatic(img->dat.img.image,
                 x + (double)gl_screen.w/2.,
-                y + (double)gl_screen.h/2., NULL);
+                y + (double)gl_screen.h/2.,
+                img->dat.img.colour);
 
   if(img->dat.img.border) {
     // Inner outline (outwards).
diff --git a/src/toolkit.h b/src/toolkit.h
index 302d658..f6d2a46 100644
--- a/src/toolkit.h
+++ b/src/toolkit.h
@@ -51,7 +51,9 @@ char* dialogue_input(char* title, int min, int max, const char* fmt, ...);
 // Modification.
 void window_setFptr(const unsigned int wid, void(*fptr)(char*));
 void window_modifyText(const unsigned int wid, char* name, char* newstring);
+// Image.
 void window_modifyImage(const unsigned int wid, char* name, glTexture* image);
+void window_imgColour(const unsigned int wid, char* name, glColour* colour);
 
 // Get the window by name.
 int window_exists(const char* wdwname);