From 092b48651dc53e7ce5875150ea3f9e09574c35cb Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Mon, 22 Jul 2013 15:53:09 +0100
Subject: [PATCH] [Change] Restructured a little to prepare for puffs of
 nebulae.

---
 src/lephisto.c |  25 ++------
 src/nebulae.c  | 153 ++++++++++++++++++++++++++++++++++++++++---------
 src/nebulae.h  |   3 +-
 src/perlin.c   |  57 ++++++++++++++++++
 src/perlin.h   |   1 +
 src/space.c    |  12 ++--
 src/space.h    |   4 +-
 7 files changed, 199 insertions(+), 56 deletions(-)

diff --git a/src/lephisto.c b/src/lephisto.c
index 6993cc8..f1ecf44 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -94,13 +94,13 @@ int main(int argc, char** argv) {
   /* Initialize SDL for possible warnings. */
   SDL_Init(0);
 
-  /* Input must be initialized for config to work. */
-  input_init();
-
   /* Create the home directory if needed. */
   if(lfile_dirMakeExist("."))
     WARN("Unable to create lephisto directory '%s'", lfile_basePath());
 
+  /* Input must be initialized for config to work. */
+  input_init();
+
   /* Set the configuration. */
   snprintf(buf, PATH_MAX, "%s"CONF_FILE, lfile_basePath());
   conf_setDefaults(); /* Default config values. */
@@ -115,22 +115,6 @@ int main(int argc, char** argv) {
   /* Random numbers. */
   rng_init();
 
-  if(gl_init()) {
-    /* Initializes video output. */
-    ERR("Initializing video output failed, exiting...");
-    SDL_Quit();
-    exit(EXIT_FAILURE);
-  }
-
-  /* See if the data file is valid. */
-  if(pack_check(data)) {
-    ERR("Data file '%s' not found", DATA);
-    WARN("You can specify what data file you want to use with '-d'");
-    WARN("See -h or -- help for more infoamtion.");
-    SDL_Quit();
-    exit(EXIT_FAILURE);
-  }
-
   /* OpenGL */
   if(gl_init()) { /* Init video output. */
     ERR("Initializing video output failed, exiting...");
@@ -256,6 +240,7 @@ void unload_all(void) {
   missions_free();
   factions_free();
   commodity_free();
+  var_cleanup();    /* Clean up mission variables. */
 }
 
 /**
@@ -371,7 +356,7 @@ static void render_all(void) {
   pilots_render();
   weapons_render(WEAPON_LAYER_FG);
   spfx_render(SPFX_LAYER_BACK);
-  space_renderOverlay();
+  space_renderOverlay(cur_dt);
   /* FG. */
   player_render();
   spfx_render(SPFX_LAYER_FRONT);
diff --git a/src/nebulae.c b/src/nebulae.c
index 7ea9e4f..c140733 100644
--- a/src/nebulae.c
+++ b/src/nebulae.c
@@ -9,10 +9,13 @@
 #include "lfile.h"
 #include "rng.h"
 #include "menu.h"
+#include "player.h"
 #include "perlin.h"
 
 #define NEBULAE_Z             16  /* Z plane. */
-#define NEBULAE_PATH          "gen/nebu_%02d.png"
+#define NEBULAE_PUFFS         32  /* Amount of puffs to generate. */
+#define NEBULAE_PATH_BG       "gen/nebu_bg_%dx%d_%02d.png"
+#define NEBULAE_PATH_PUFF     "gen/nebu_puff_%02d.png"
 
 /* Extern. */
 extern double gui_xoff, gui_yoff;
@@ -32,8 +35,28 @@ static unsigned int last_render = 0;
 static double nebu_view = 0.;
 static double nebu_dt   = 0.;
 
+/* Puff textures. */
+typedef struct NebulaePuffTex_ {
+  GLuint tex;     /* Actualy texture. */
+  double w, h;    /* Real dimensions. */
+  double pw, ph;  /* Padding. */
+} NebulaePuffTex;
+static NebulaePuffTex nebu_pufftexs[NEBULAE_PUFFS];
+
+/* Puff handling. */
+typedef struct NebulaePuff_ {
+  double x, y;          /* Position. */
+  double a, va;         /* Alpha, alpha velocity. */
+  double height;        /* Height vs player. */
+  NebulaePuffTex* tex;  /* Texture. */
+} NebulaePuff;
+static NebulaePuff* nebu_puffs = NULL;
+static int nebu_npuffs = 0;
+
 static int nebu_checkCompat(const char* file);
+static void nebu_loadTexture(SDL_Surface* sur, int w, int h, GLuint tex);
 static void nebu_generate(void);
+static void nebu_generatePuffs(void);
 static void saveNebulae(float* map, const uint32_t w, const uint32_t h,
     const char* file);
 static SDL_Surface* loadNebulae(const char* file);
@@ -55,10 +78,12 @@ void nebu_init(void) {
   nebu_pw = gl_pot(nebu_w);
   nebu_ph = gl_pot(nebu_h);
 
+  nebu_generatePuffs();
+
   /* Load each, checking for compatibility and padding. */
   glGenTextures(NEBULAE_Z, nebu_textures);
   for(i = 0; i < NEBULAE_Z; i++) {
-    snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i);
+    snprintf(nebu_file, PATH_MAX, NEBULAE_PATH_BG, nebu_w, nebu_h, i);
 
     if(nebu_checkCompat(nebu_file)) { /* Incompatable. */
       LOG("No nebulae found, generating (this may take a while).");
@@ -75,33 +100,49 @@ void nebu_init(void) {
       WARN("Nebulae raw size doesn't match expected! (%dx%d instead of %dx%d)",
           nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph);
 
-    /* Prepare to load into OpenGL. */
-    nebu_sur = gl_prepareSurface(nebu_sur);
-    if((nebu_sur->w != nebu_pw) || (nebu_sur->h != nebu_ph))
-      WARN("Nebulae size doesn't match expected! (%dx%d instead of %dx%d)",
-          nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph);
-
     /* Load the textures. */
-    glBindTexture(GL_TEXTURE_2D, nebu_textures[i]);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    
-    /* Store into opengl saving only alpha channel in video memory. */
-    SDL_LockSurface(nebu_sur);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, nebu_sur->w, nebu_sur->h,
-        0, GL_RGBA, GL_UNSIGNED_BYTE, nebu_sur->pixels);
-    SDL_UnlockSurface(nebu_sur);
-
-    SDL_FreeSurface(nebu_sur);
-    gl_checkErr();
+    nebu_loadTexture(nebu_sur, nebu_pw, nebu_ph, nebu_textures[i]);
   }
 
   DEBUG("Loaded %d Nebulae Layers", NEBULAE_Z);
 }
 
+/* Load sur into tex, check for expected size of w and h. */
+static void nebu_loadTexture(SDL_Surface* sur, int w, int h, GLuint tex) {
+  SDL_Surface* nebu_sur;
+
+  nebu_sur = gl_prepareSurface(sur);
+  if((w != 0) && (h != 0) &&
+      ((nebu_sur->w != w) || (nebu_sur->h != h))) {
+    
+    WARN("Nebulae size doesn't match expected! (%dx%d instead of %dx%d)",
+        nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph);
+    return;
+  }
+
+  /* Load the textures. */
+  glBindTexture(GL_TEXTURE_2D, tex);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+  /* Store into opengl saving only alpha channel in video memory. */
+  SDL_LockSurface(nebu_sur);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, nebu_sur->w, nebu_sur->h,
+      0, GL_RGBA, GL_UNSIGNED_BYTE, nebu_sur->pixels);
+  SDL_UnlockSurface(nebu_sur);
+
+  SDL_FreeSurface(nebu_sur);
+  gl_checkErr();
+}
+
 /* Clean up the nebu subsystem. */
 void nebu_exit(void) {
+  int i;
+
   glDeleteTextures(NEBULAE_Z, nebu_textures);
+
+  for(i = 0; i < NEBULAE_PUFFS; i++)
+    glDeleteTextures(1, &nebu_pufftexs[i].tex);
 }
 
 /* Render the nebulae. */
@@ -209,16 +250,19 @@ void nebu_render(void) {
   gl_checkErr();
 }
 
-void nebu_renderOverlay(void) {
+void nebu_renderOverlay(const double dt) {
 #define ANG45   0.70710678118654757
 #define COS225  0.92387953251128674
 #define SIN225  0.38268343236508978
-  glShadeModel(GL_SMOOTH);
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   glTranslated(gui_xoff+shake_pos.x, gui_yoff+shake_pos.y, 0.);
 
-  /* Stuff player partially sees. */
+  /* Render the puffs. */
+  nebu_renderPuffs(dt, 0);
+
+  /* Mask for area player can still see (partially). */
+  glShadeModel(GL_SMOOTH);
   glBegin(GL_TRIANGLE_FAN);
     ACOLOUR(cPurple,                0.);
     glVertex2d(0.,                  0.);
@@ -242,10 +286,10 @@ void nebu_renderOverlay(void) {
     glVertex2d(-nebu_view,          0.);
   glEnd(); /* GL_TRIANGLE_FAN */
 
+  /* Solid nebulae for areas the player can't see. */
   glShadeModel(GL_FLAT);
   ACOLOUR(cPurple, 1.);
 
-  /* Stuff player can't see. */
   glBegin(GL_TRIANGLE_FAN);
     /* Top left. */
     glVertex2d(-SCREEN_W/2.-gui_xoff,     SCREEN_H/2.-gui_yoff);
@@ -296,6 +340,34 @@ void nebu_renderOverlay(void) {
 #undef SIN225
 }
 
+/* Render the puffs. */
+void nebu_renderPuffs(const double dt, int below_player) {
+  int i;
+
+  glPushMatrix(); /* GL_PROJECTION */
+  glTranslated(-(double)SCREEN_W/2., -(double)SCREEN_H/2., 0.);
+
+  for(i = 0; i < nebu_npuffs; i++) {
+    if((below_player && (nebu_puffs[i].height < 1.)) ||
+        (!below_player && (nebu_puffs[i].height > 1.))) {
+      
+      /* Calculate new position. */
+      nebu_puffs[i].x -= player->solid->vel.x * nebu_puffs[i].height * dt;
+      nebu_puffs[i].y -= player->solid->vel.y * nebu_puffs[i].height * dt;
+
+      /* Calculate new alpha. */
+      /*nebu_puffs[i].a += nebu_puffs[i].va * dt;*/
+
+      /* Check boundaries. */
+
+      /* Render. */
+      ACOLOUR(cPurple, nebu_puffs[i].a);
+      glBegin(GL_QUADS);
+      glEnd(); /* GL_QUADS */
+    }
+  }
+}
+
 /* Prepare the nebulae. */
 void nebu_prep(double density, double volatility) {
   (void)volatility;
@@ -305,7 +377,7 @@ void nebu_prep(double density, double volatility) {
 
 /* Force generation of new nebulae. */
 void nebu_forceGenerate(void) {
-  nebu_w = nebu_h = -9;
+  nebu_w = nebu_h = -9; /* Magic numbers. ^.^ */
 }
 
 /* Generate the nebulae. */
@@ -318,13 +390,13 @@ static void nebu_generate(void) {
   w = SCREEN_W;
   h = SCREEN_H;
 
-  /* Generate all the nebulae. */
+  /* Generate all the nebulae backgrounds. */
   nebu = noise_genNebulaeMap(w, h, NEBULAE_Z, 5.);
   lfile_dirMakeExist("gen");
 
   /* Save each nebulae as an image. */
   for(i = 0; i < NEBULAE_Z; i++) {
-    snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i);
+    snprintf(nebu_file, PATH_MAX, NEBULAE_PATH_BG, w, h, i);
     saveNebulae(&nebu[i*w*h], w, h, nebu_file);
   }
 
@@ -332,6 +404,33 @@ static void nebu_generate(void) {
   free(nebu);
 }
 
+/* Generate the nebulae puffs. */
+static void nebu_generatePuffs(void) {
+  int i;
+  int w, h;
+  SDL_Surface* sur;
+  float* nebu;
+
+  /* Generate the nebulae puffs. */
+  for(i = 0; i < NEBULAE_PUFFS; i++) {
+    /* Generate the nebulae. */
+    w = h = RNG(20, 64);
+    nebu = noise_genNebulaePuffMap(w, h, 1.);
+    sur = nebu_surfaceFromNebulaeMap(nebu, w, h);
+    free(nebu);
+
+    /* Set dimensions. */
+    nebu_pufftexs[i].w = w;
+    nebu_pufftexs[i].h = h;
+    nebu_pufftexs[i].pw = gl_pot(w);
+    nebu_pufftexs[i].ph = gl_pot(h);
+
+    /* Actually create the texture. */
+    glGenTextures(1, &nebu_pufftexs[i].tex);
+    nebu_loadTexture(sur, 0, 0, nebu_pufftexs[i].tex);
+  }
+}
+
 /* Check the validity of a nebulae. 0 on success. */
 static int nebu_checkCompat(const char* file) {
   if(lfile_fileExists(file) == 0) /* First check to see if file exists. */
diff --git a/src/nebulae.h b/src/nebulae.h
index 4b8b0ea..65256ef 100644
--- a/src/nebulae.h
+++ b/src/nebulae.h
@@ -6,7 +6,8 @@ void nebu_exit(void);
 
 /* Render. */
 void nebu_render(void);
-void nebu_renderOverlay(void);
+void nebu_renderOverlay(const double dt);
+void nebu_renderPuffs(const double dt, int below_player);
 
 /* Misc. */
 void nebu_prep(double density, double volatility);
diff --git a/src/perlin.c b/src/perlin.c
index 89cc255..703a946 100644
--- a/src/perlin.c
+++ b/src/perlin.c
@@ -2,6 +2,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "SDL.h"
+
 #include "lephisto.h"
 #include "log.h"
 #include "rng.h"
@@ -239,3 +241,58 @@ float* noise_genNebulaeMap(const int w, const int h, const int n, float rug) {
   return nebulae;
 }
 
+/* Generate tiny nebuale puffs */
+float* noise_genNebulaePuffMap(const int w, const int h, float rug) {
+  int x, y;
+  float f[3];
+  int octaves;
+  float hurst;
+  float lacunarity;
+  perlin_data_t* noise;
+  float* nebulae;
+  float value;
+  float zoom;
+  float max;
+
+  /* Pretty default values. */
+  octaves = 3;
+  hurst = NOISE_DEFAULT_HURST;
+  lacunarity = NOISE_DEFAULT_LACUNARITY;
+  zoom = rug;
+
+  /* Create noise and data. */
+  noise = noise_new(hurst, lacunarity);
+  nebulae = malloc(sizeof(float)*w*h);
+  if(nebulae == NULL) {
+    WARN("Out of memory!");
+    return NULL;
+  }
+
+  /* Start to create the nebulae. */
+  max = 0.;
+  f[2] = 0.;
+  for(y = 0; y < h; y++) {
+    f[1] = zoom * (float)y / (float)h;
+    for(x = 0; x < w; x++) {
+      f[0] = zoom * (float)x / (float)w;
+
+      value = noise_turbulence(noise, f, octaves);
+      if(max < value) max = value;
+
+      nebulae[y*w + x] = value;
+    }
+  }
+
+  /* Post filtering. */
+  value = 1. - max;
+  for(y = 0; y < h; y++)
+    for(x = 0; x < w; x++)
+      nebulae[y*w + x] += value;
+
+  /* Clean up. */
+  noise_delete(noise);
+
+  /* Results. */
+  return nebulae;
+}
+
diff --git a/src/perlin.h b/src/perlin.h
index 5db966d..c473674 100644
--- a/src/perlin.h
+++ b/src/perlin.h
@@ -2,4 +2,5 @@
 #include "opengl.h"
 
 float* noise_genNebulaeMap(const int w, const int h, const int n, float rug);
+float* noise_genNebulaePuffMap(const int w, const int h, float rug);
 
diff --git a/src/space.c b/src/space.c
index c92ef30..f1fba39 100644
--- a/src/space.c
+++ b/src/space.c
@@ -71,7 +71,7 @@ static int mstars = 0;      /* Memory stars are taking. */
 
 /* Intern. */
 static Planet* planet_pull(const char* name);
-static void space_renderStars(double dt);
+static void space_renderStars(const double dt);
 static void space_addFleet(Fleet* fleet);
 static StarSystem* system_parse(const xmlNodePtr parent);
 static void system_parseJumps(const xmlNodePtr parent);
@@ -805,7 +805,7 @@ int space_load(void) {
 }
 
 /* Render the system. -- Just playing god now. */
-void space_render(double dt) {
+void space_render(const double dt) {
   if(cur_system == NULL) return;
 
   if(cur_system->nebu_density > 0.)
@@ -815,15 +815,15 @@ void space_render(double dt) {
 }
 
 /* Render the overlay. */
-void space_renderOverlay(void) {
+void space_renderOverlay(const double dt) {
   if(cur_system == NULL) return; 
 
   if(cur_system->nebu_density > 0.)
-    nebu_renderOverlay();
+    nebu_renderOverlay(dt);
 }
 
 /* Render stars. */
-static void space_renderStars(double dt) {
+static void space_renderStars(const double dt) {
   int i;
   unsigned int t, timer;
   double x, y, m, b;
@@ -835,7 +835,7 @@ static void space_renderStars(double dt) {
   t = SDL_GetTicks();
   if(!player_isFlag(PLAYER_DESTROYED) && !player_isFlag(PLAYER_CREATING) &&
      pilot_isFlag(player, PILOT_HYPERSPACE) && /* Hyperspace fancy effect. */
-     !paused && (player->ptimer-HYPERSPACE_STARS_BLUR < t)) {
+     (player->ptimer-HYPERSPACE_STARS_BLUR < t)) {
 
     timer = player->ptimer - HYPERSPACE_STARS_BLUR;
 
diff --git a/src/space.h b/src/space.h
index cc36881..a9ae244 100644
--- a/src/space.h
+++ b/src/space.h
@@ -120,8 +120,8 @@ char* planet_getSystem(char* planetname);
 Planet* planet_get(char* planetname);
 
 /* Render. */
-void space_render(double dt);
-void space_renderOverlay(void);
+void space_render(const double dt);
+void space_renderOverlay(const double dt);
 void planets_render(void);
 
 /* Update. */