From cd158e5102f844de89048a86efbbc9254c8ca4b1 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Fri, 19 Jul 2013 14:25:15 +0100
Subject: [PATCH] [Add] Nebulae almost working, There is a major graphical bug
 however.

---
 src/menu.c    |   2 +-
 src/nebulae.c | 164 +++++++++++++++++---------------------------------
 src/opengl.c  |  32 +++++++---
 src/opengl.h  |   3 +-
 src/perlin.c  |  14 -----
 src/perlin.h  |   2 -
 6 files changed, 80 insertions(+), 137 deletions(-)

diff --git a/src/menu.c b/src/menu.c
index 6f4a386..e6747fc 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -69,7 +69,7 @@ void menu_main(void) {
 
   /* Create background image window. */
   bwid = window_create("BG", -1, -1, SCREEN_W, SCREEN_H);
-  /*window_addRect(bwid, 0, 0, SCREEN_W, SCREEN_H, "rctBG", &cBlack, 0);*/
+  window_addRect(bwid, 0, 0, SCREEN_W, SCREEN_H, "rctBG", &cBlack, 0);
   window_addCust(bwid, 0, 0, SCREEN_W, SCREEN_H, "cstBG", 0,
       (void(*)(double, double, double, double))nebu_render, NULL);
 
diff --git a/src/nebulae.c b/src/nebulae.c
index a00533f..a1b40d6 100644
--- a/src/nebulae.c
+++ b/src/nebulae.c
@@ -1,11 +1,7 @@
 #include <errno.h>
 #include "nebulae.h"
 
-#ifdef _POSIX_SOURCE
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#endif
+#include "SDL_image.h"
 
 #include "lephisto.h"
 #include "log.h"
@@ -22,7 +18,7 @@
 #define NEBU_VERSION          "1" /* Will be used for version checking. */
 
 #define NEBULAE_Z             32  /* Z plane. */
-#define NEBULAE_PATH          "gen/nebu_%02d.nebu"
+#define NEBULAE_PATH          "gen/nebu_%02d.png"
 
 /* The nebulae textures. */
 static GLuint nebu_textures[NEBULAE_Z];
@@ -31,15 +27,13 @@ static int nebu_w, nebu_h, nebu_pw, nebu_ph;
 static int nebu_checkCompat(const char* file);
 static void saveNebulae(float* map, const uint32_t w, const uint32_t h,
     const char* file);
-static unsigned char* loadNebulae(const char* file, int* w, int* h);
+static SDL_Surface* loadNebulae(const char* file);
 
 /* Initialize the nebulae. */
 void nebu_init(void) {
-  int i, y;
+  int i;
   char nebu_file[PATH_MAX];
-  unsigned char* nebu_padded;
-  int w, h;
-  unsigned char* nebu_data;
+  SDL_Surface* nebu_sur;
 
   /* Set expected sizes. */
   nebu_w = SCREEN_W;
@@ -48,7 +42,6 @@ void nebu_init(void) {
   nebu_ph = gl_pot(nebu_h);
 
   /* Load each, checking for compatibility and padding. */
-  nebu_padded = malloc(nebu_pw * nebu_ph);
   glGenTextures(NEBULAE_Z, nebu_textures);
   for(i = 0; i < NEBULAE_Z; i++) {
     snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i);
@@ -57,34 +50,35 @@ void nebu_init(void) {
       LOG("No nebulae found, generating (this may take a while).");
 
       /* So we generate and reload. */
-      free(nebu_padded);
       nebu_generate(nebu_w, nebu_h);
       nebu_init();
       return;
     }
 
     /* Load the file. */
-    nebu_data = loadNebulae(nebu_file, &w, &h);
-    for(y = 0; y < nebu_h; y++) { /* Copy lines over. */
-      /* nebu_padded = [ nebu_data 0000000000000 ] */
-      memmove(&nebu_padded[y*nebu_pw], &nebu_data[y*nebu_w], nebu_w);
-      memset(&nebu_padded[y*nebu_pw+nebu_w], 0, nebu_pw-nebu_w); /* Pad the end. */
-    }
-    /* End it with 0's. */
-    memset(&nebu_padded[nebu_h*nebu_pw+nebu_w], 0,
-        nebu_ph*nebu_w - nebu_h*nebu_pw);
+    nebu_sur = loadNebulae(nebu_file);
+    if((nebu_sur->w != nebu_w) || (nebu_sur->h != nebu_h))
+      WARN("Nebulae raw size doesn't match expected! (%dx%d instead of %dx%d)",
+          nebu_sur->w, nebu_sur->h, nebu_pw, nebu_ph);
+
+    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);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, nebu_pw, nebu_ph,
-        0, GL_ALPHA, GL_UNSIGNED_BYTE, nebu_padded);
-    gl_checkErr();
+    
+    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);
 
-    free(nebu_data); /* No longer need the data. */
+    SDL_FreeSurface(nebu_sur);
+    gl_checkErr();
   }
-  free(nebu_padded);
 
   DEBUG("Loaded %d Nebulae Layers", NEBULAE_Z);
 }
@@ -97,29 +91,38 @@ void nebu_exit(void) {
 /* Render the nebulae. */
 void nebu_render(void) {
   int n;
-  double tw, th;
+  double x, y, w, h, tx, ty, tw, th;
 
   n = 0;
 
+  x = -SCREEN_W/2.;
+  y = -SCREEN_H/2.;
+
+  w = SCREEN_W;
+  h = SCREEN_H;
+
+  tx = 0.;
+  ty = 0.;
+
   tw = nebu_w / nebu_pw;
   th = nebu_h / nebu_ph;
 
   glEnable(GL_TEXTURE_2D);
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  /*glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);*/
   glBindTexture(GL_TEXTURE_2D, nebu_textures[n]);
-  glColor4d(1., 1., 1., 1.);
+  COLOUR(cPurple);
   glBegin(GL_QUADS);
-    glTexCoord2d(0., 0.);
-    glVertex2d(-SCREEN_W/2., -SCREEN_H/2.);
+    glTexCoord2d(tx, ty);
+    glVertex2d(x, y);
 
-    glTexCoord2d(tw, th);
-    glVertex2d(SCREEN_W/2., -SCREEN_H/2.);
+    glTexCoord2d(tx+tw, ty);
+    glVertex2d(x+w, y);
 
-    glTexCoord2d(tw, th);
-    glVertex2d(SCREEN_W/2., SCREEN_H/2.);
+    glTexCoord2d(tx+tw, ty+th);
+    glVertex2d(x+w, y+h);
 
-    glTexCoord2d(0., th);
-    glVertex2d(-SCREEN_W/2., SCREEN_H/2.);
+    glTexCoord2d(tx, ty+th);
+    glVertex2d(x, y+h);
   glEnd();
   glDisable(GL_TEXTURE_2D);
 
@@ -158,90 +161,31 @@ static int nebu_checkCompat(const char* file) {
 static void saveNebulae(float* map, const uint32_t w, const uint32_t h,
     const char* file) {
   
-  int x, y;
-  char* buf;
-  unsigned char c;
-  int cur;
-  ssize_t size;
   char file_path[PATH_MAX];
+  SDL_Surface* sur;
 
-  size = w*h + 16 + 4;
-  buf = malloc(size);
-
-  /* Write the header. */
-  memset(buf, '0', 16);
-  snprintf(buf, NEBU_FORMAT_HEADER, "LEPHISTO NEBU v" NEBU_VERSION);
-  cur = 16;
-  memcpy(&buf[cur], &w, 4);
-  cur += 4;
-  memcpy(&buf[cur], &h, 4);
-  cur += 4;
-
-  /* The Body. */
-  for(y = 0; y < (int)h; y++)
-    for(x = 0; x < (int)w; x++) {
-      c = (unsigned char) 255.*map[y*w + x];
-      memcpy(&buf[cur++], &c, 1);
-    }
-
-  /* Write to a file. */
+  sur = noise_surfaceFromNebulaeMap(map, w, h);
+  
   snprintf(file_path, PATH_MAX, "%s%s", lfile_basePath(), file);
-#ifdef _POSIX_SOURCE
-  int fd;
-  fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC,
-      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 
-  if(fd < 0) {
-    ERR("Unable to open file %s: %s", file, strerror(errno));
-    return;
-  }
-  if(write(fd, buf, size) != size) {
-    ERR("Error writing nebulae to %s: %s", file, strerror(errno));
-    return;
-  }
-  close(fd);
-#else
-#error "Needs implementation."
-#endif
+  SDL_savePNG(sur, file_path);
+
+  SDL_FreeSurface(sur);
 }
 
 /* Load the nebulae from file. */
-static unsigned char* loadNebulae(const char* file, int* w, int* h) {
-  unsigned char* buf;
-  char header[16];
-  uint32_t tw, th;
-  ssize_t len;
+static SDL_Surface* loadNebulae(const char* file) {
   char file_path[PATH_MAX];
+  SDL_Surface* sur;
 
-#ifdef _POSIX_SOURCE
-#define READ(b, l) \
-  len = read(fd, b, l); \
-  if(len < l) {\
-    WARN("Read too few bytes from %s: %s", file, strerror(errno)); \
-    return NULL; \
-  }
-
-  int fd;
-  int cur;
   snprintf(file_path, PATH_MAX, "%s%s", lfile_basePath(), file);
-  fd = open(file_path, O_RDONLY);
-  if(fd < 0) {
-    ERR("Unable to open file %s: %s", file_path, strerror(errno));
+
+  sur = IMG_Load(file_path);
+  if(sur == NULL) {
+    ERR("Unable to load Nebulae image: %s", file);
     return NULL;
   }
-  READ(header, 16);
-  READ(&tw, 4);
-  READ(&th, 4);
-  buf = malloc(tw*th);
-  cur = 0;
-  while((len = read(fd, &buf[cur], tw*th - cur)) != 0)
-    cur += len;
-#else
-#error "Needs implementation."
-#endif
-  (*w) = (int)tw;
-  (*h) = (int)th;
 
-  return buf;
+  return sur;
 }
 
diff --git a/src/opengl.c b/src/opengl.c
index e7e9e1d..b39df7f 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -233,14 +233,16 @@ int SDL_savePNG(SDL_Surface* surface, const char* file) {
   return r;
 }
 
-/* ================ */
-/* TEXTURE! */
-/* ================ */
+/*
+ * ================
+ * TEXTURE!
+ * ================ 
+ */
 
-/* Returns the texture ID. */
-/* Stores real sizes in rw/rh (from POT padding). */
-static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh) {
-  GLuint texture;
+/* Returns the texture ID.
+ * Stores real sizes in rw/rh (from POT padding).
+ */
+SDL_Surface* gl_prepareSurface(SDL_Surface* surface) {
   SDL_Surface* tmp;
   Uint32 saved_flags;
   Uint8  saved_alpha;
@@ -250,8 +252,6 @@ static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh) {
   /* Make size power of two. */
   potw = gl_pot(surface->w);
   poth = gl_pot(surface->h);
-  if(rw)*rw = potw;
-  if(rh)*rh = poth;
 
   rtemp.x = rtemp.y = 0;
   rtemp.w = surface->w;
@@ -287,6 +287,20 @@ static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh) {
   if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA) 
     SDL_SetAlpha(surface, 0, 0);
 
+  return surface;
+}
+
+/*
+ * Return the texture id.
+ * Stores real sizes in rw/rh (from POT padding).
+ */
+static GLuint gl_loadSurface(SDL_Surface* surface, int *rw, int* rh) {
+  GLuint texture;
+
+  surface = gl_prepareSurface(surface);
+  if(rw != NULL) (*rw) = surface->w;
+  if(rh != NULL) (*rh) = surface->h;
+
   /* Opengl texture binding. */
   glGenTextures(1, &texture); /* Create the texure. */
   glBindTexture(GL_TEXTURE_2D, texture); /* Load the texture. */
diff --git a/src/opengl.h b/src/opengl.h
index 200bb4a..2314080 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -63,7 +63,8 @@ typedef struct glTexture_ {
   uint8_t flags;      /**< Flags used for texture properties. */
 } glTexture;
 
-/* gl_texute loading/freeing. */
+/* glTextyre loading/freeing. */
+SDL_Surface* gl_prepareSurface(SDL_Surface* surface); /* Only preps it. */
 glTexture* gl_loadImage(SDL_Surface* surface); /* Frees the surface. */
 glTexture* gl_newImage(const char* path);
 glTexture* gl_newSprite(const char* path, const int sx, const int sy);
diff --git a/src/perlin.c b/src/perlin.c
index 7b7c89d..ba199fe 100644
--- a/src/perlin.c
+++ b/src/perlin.c
@@ -248,17 +248,3 @@ SDL_Surface* noise_surfaceFromNebulaeMap(float* map, const int w, const int h) {
   return sur;
 }
 
-glTexture* noise_genCloud(const int w, const int h, double rug) {
-  float* map;
-  SDL_Surface* sur;
-  glTexture* tex;
-
-  map = noise_genNebulaeMap(w, h, 1, rug);
-  sur = noise_surfaceFromNebulaeMap(map, w, h);
-  free(map);
-
-  tex = gl_loadImage(sur);
-
-  return tex;
-}
-
diff --git a/src/perlin.h b/src/perlin.h
index af976ec..57c57b4 100644
--- a/src/perlin.h
+++ b/src/perlin.h
@@ -5,5 +5,3 @@ float* noise_genNebulaeMap(const int w, const int h, const int n, float rug);
 
 SDL_Surface* noise_surfaceFromNebulaeMap(float* map, const int w, const int h);
 
-glTexture* noise_genCloud(const int w, const int h, double rug);
-