#include #include "nebulae.h" #ifdef _POSIX_SOURCE #include #include #include #endif #include "lephisto.h" #include "log.h" #include "lfile.h" #include "perlin.h" /* -- CUSTOM NEBULAE FORMAT. -- * Header (16 byte string). * Dimesnions (4 byte w and 4 byte h). * Body (1 byte per pixel). */ #define NEBU_FORMAT_HEADER 16 /* Size of header. */ #define NEBU_VERSION "1" /* Will be used for version checking. */ #define NEBULAE_Z 32 /* Z plane. */ #define NEBULAE_PATH "gen/nebu_%02d.nebu" /* The nebulae textures. */ static GLuint nebu_textures[NEBULAE_Z]; 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); void nebu_init(void) { int i; char nebu_file[PATH_MAX]; unsigned char* nebu_padded; int w, h; unsigned char* nebu_data; /* Set expected sizes. */ nebu_w = SCREEN_W; nebu_h = SCREEN_H; nebu_pw = gl_pot(nebu_w); 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); if(nebu_checkCompat(nebu_file)) { /* Incompatable. */ 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); memcpy(nebu_padded, nebu_data, w*h); /* 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(); free(nebu_data); /* No longer need the data. */ } free(nebu_padded); } /* Clean up the nebu subsystem. */ void nebu_exit(void) { glDeleteTextures(NEBULAE_Z, nebu_textures); } /* Force generation of new nebulae. */ void nebu_generate(const int w, const int h) { int i; float* nebu; char nebu_file[PATH_MAX]; /* Generate all the nebulae. */ nebu = noise_genNebulaeMap(w, h, NEBULAE_Z, 15.); lfile_dirMakeExist("gen"); /* Save each nebulae as an image. */ for(i = 0; i < NEBULAE_Z; i++) { snprintf(nebu_file, PATH_MAX, NEBULAE_PATH, i); saveNebulae(&nebu[i*w*h], w, h, nebu_file); } /* Cleanup. */ free(nebu); } /* 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. */ return -1; return 0; } /* Save a nebulae. */ 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]; 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); memcpy(&buf[cur], &h, 4); cur += 8; /* 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. */ 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 } /* 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; char file_path[PATH_MAX]; #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; snprintf(file_path, PATH_MAX, "%s%s", lfile_basePath(), file); fd = open(file, O_RDONLY); if(fd < 0) { ERR("Unable to open file %s: %s", file_path, strerror(errno)); return NULL; } READ(header, 16); READ(&tw, 4); READ(&th, 4); buf = malloc(tw*th); READ(buf, tw*th); #else #error "Needs implementation." #endif (*w) = (int)tw; (*h) = (int)th; return buf; }