diff options
author | Clyne Sullivan <tullivan99@gmail.com> | 2016-02-26 08:47:49 -0500 |
---|---|---|
committer | Clyne Sullivan <tullivan99@gmail.com> | 2016-02-26 08:47:49 -0500 |
commit | cd0236b94d5ecd2378518876820be201b9c635be (patch) | |
tree | 1cbe44dbf68f94c30f7f3cebce511ad7ce39ebac | |
parent | 26d71799f37bc325b6db0214268f4e72eb970ee9 (diff) |
c++'d texture loading
-rw-r--r-- | Changelog | 8 | ||||
-rw-r--r-- | include/Texture.h | 4 | ||||
-rw-r--r-- | include/common.h | 2 | ||||
-rw-r--r-- | include/world.h | 10 | ||||
-rw-r--r-- | src/Texture.cpp | 79 | ||||
-rw-r--r-- | src/gameplay.cpp | 1 | ||||
-rw-r--r-- | src/ui.cpp | 176 | ||||
-rw-r--r-- | src/world.cpp | 5 |
8 files changed, 174 insertions, 111 deletions
@@ -689,3 +689,11 @@ - very neatly documented/optimized ui.cpp (very neat) - looked into better automated Makefiles - improving villages, began work on shops + +2/26/2015: +========== + + - made fonts more memory-efficient + - C++-ified loaded texture handlers + - documented more stuff + - made merchant menu diff --git a/include/Texture.h b/include/Texture.h index c6376cb..659c32d 100644 --- a/include/Texture.h +++ b/include/Texture.h @@ -27,13 +27,13 @@ namespace Texture{ * later referencing of the texture. */ - GLuint loadTexture(const char *fileName); + GLuint loadTexture(std::string fileName); void freeTextures(void); void initColorIndex(); vec2 getIndex(Color c); - dim2 imageDim(const char *fileName); + dim2 imageDim(std::string fileName); } /** diff --git a/include/common.h b/include/common.h index 71335f2..6ba6f03 100644 --- a/include/common.h +++ b/include/common.h @@ -68,7 +68,7 @@ typedef struct { float z; } vec3; -typedef vec2 dim2; +typedef ivec2 dim2; /** * This structure contains two sets of coordinates for ray drawing. diff --git a/include/world.h b/include/world.h index 56f1577..c066865 100644 --- a/include/world.h +++ b/include/world.h @@ -129,6 +129,12 @@ public: */ Village(const char *meme, World *w); + + /** + * Destructor... + */ + + ~Village(void){} }; /** @@ -282,9 +288,7 @@ public: std::vector<Particles *> particles; - - - std::vector<Village * > village; + std::vector<Village *> village; /** * A vector of all light elements in this world. diff --git a/src/Texture.cpp b/src/Texture.cpp index 1487dcd..1aaadf6 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -1,45 +1,62 @@ #include <Texture.h> #include <string.h> +/** + * A structure for keeping track of loaded textures. + */ + struct texture_t { - char *name; - GLuint tex; - dim2 dim; -} __attribute__ ((packed)); + std::string name; /**< The file path of the texture. */ + GLuint tex; /**< The GLuint for the loaded texture. */ + dim2 dim; /**< The dimensions of the texture. */ +}; -struct index_t{ +struct index_t { Color color; int indexx; int indexy; }; -struct texture_t *LoadedTexture[256]; -unsigned int LoadedTextureCounter = 0; +/** + * A vector of all loaded textures. + * + * Should a texture be asked to be loaded twice, loadTexture() can reference + * this array and reuse GLuint's to save memory. + */ + +static std::vector<struct texture_t> LoadedTexture; namespace Texture{ Color pixels[8][4]; - GLuint loadTexture(const char *fileName){ + + GLuint loadTexture(std::string fileName){ SDL_Surface *image; GLuint object = 0; - for(unsigned int i=0;i<LoadedTextureCounter;i++){ - if(!strcmp(LoadedTexture[i]->name,fileName)){ + // check if texture is already loaded + for(auto &t : LoadedTexture){ + if(t.name == fileName){ + #ifdef DEBUG - DEBUG_printf("Reusing loaded texture for %s\n",fileName); + DEBUG_printf("Reusing loaded texture for %s\n", fileName.c_str()); #endif // DEBUG - return LoadedTexture[i]->tex; + + return t.tex; } } - if(!fileName) - return 0; - - if(!(image = IMG_Load(fileName))) + // load SDL_surface of texture + if(!(image = IMG_Load(fileName.c_str()))) return 0; + #ifdef DEBUG - DEBUG_printf("Loaded image file: %s\n", fileName); + DEBUG_printf("Loaded image file: %s\n", fileName.c_str()); #endif // DEBUG + /* + * Load texture through OpenGL. + */ + glGenTextures(1,&object); // Turns "object" into a texture glBindTexture(GL_TEXTURE_2D,object); // Binds "object" to the top of the stack glPixelStoref(GL_UNPACK_ALIGNMENT,1); @@ -61,33 +78,27 @@ namespace Texture{ image->pixels ); - LoadedTexture[LoadedTextureCounter] = new struct texture_t; //(struct texture_t *)malloc(sizeof(struct texture_t)); - LoadedTexture[LoadedTextureCounter]->name = new char[strlen(fileName)+1]; //(char *)malloc(safe_strlen(fileName)); - LoadedTexture[LoadedTextureCounter]->tex = object; - strcpy(LoadedTexture[LoadedTextureCounter]->name,fileName); - LoadedTexture[LoadedTextureCounter]->dim.x = image->w; - LoadedTexture[LoadedTextureCounter]->dim.y = image->h; - LoadedTextureCounter++; + // add texture to LoadedTexture + LoadedTexture.push_back((struct texture_t){fileName,object,{image->w,image->h}}); - SDL_FreeSurface(image); // Free the surface + // free the SDL_Surface + SDL_FreeSurface(image); return object; } - dim2 imageDim(const char *fileName){ - for(unsigned int i=0;i<LoadedTextureCounter;i++){ - if(!strcmp(LoadedTexture[i]->name,fileName)){ - return LoadedTexture[i]->dim; - } + dim2 imageDim(std::string fileName){ + for(auto &t : LoadedTexture){ + if(t.name == fileName) + return t.dim; } return {0,0}; } void freeTextures(void){ - for(unsigned int i=0;i<LoadedTextureCounter;i++){ - glDeleteTextures(1,&LoadedTexture[i]->tex); - delete[] LoadedTexture[i]->name; - delete LoadedTexture[i]; + while(!LoadedTexture.empty()){ + glDeleteTextures(1, &LoadedTexture.back().tex); + LoadedTexture.pop_back(); } } diff --git a/src/gameplay.cpp b/src/gameplay.cpp index 4bbc672..e3c1171 100644 --- a/src/gameplay.cpp +++ b/src/gameplay.cpp @@ -321,6 +321,7 @@ extern std::vector<NPC *> AIpreaddr; void destroyEverything(void){ currentWorld->save(); delete currentWorld; + delete[] currentXML; while(!AIpreload.empty()) AIpreload.pop_back(); @@ -35,7 +35,9 @@ typedef struct { ivec2 ad; /**< Number of pixels to advance cursor. */ } FT_Tex; -static FT_Tex ftmap[FT_CHAR_COUNT]; +static FT_Tex ftmap16[FT_CHAR_COUNT], + ftmap24[FT_CHAR_COUNT], + *ftmapptr; static FT_Library ftl; static FT_Face ftf; @@ -186,8 +188,13 @@ namespace ui { abort(); } - fontSize = 0; - memset(&ftmap, 0, FT_CHAR_COUNT * sizeof(FT_Tex)); + fontSize = 16; + + //ftmap16 = new FT_Tex[FT_CHAR_COUNT]; + //ftmap24 = new FT_Tex[FT_CHAR_COUNT]; + + memset(&ftmap16, 0, FT_CHAR_COUNT * sizeof(FT_Tex)); + memset(&ftmap24, 0, FT_CHAR_COUNT * sizeof(FT_Tex)); #ifdef DEBUG DEBUG_printf("Initialized FreeType2.\n",NULL); @@ -207,6 +214,9 @@ namespace ui { */ void destroyFonts(void){ + //delete[] ftmap16; + //delete[] ftmap24; + FT_Done_Face(ftf); FT_Done_FreeType(ftl); @@ -220,8 +230,13 @@ namespace ui { */ void setFontFace(const char *ttf){ - if(FT_New_Face(ftl,ttf,0,&ftf)){ - std::cout<<"Error! Couldn't open "<<ttf<<"."<<std::endl; + std::unique_ptr<uint8_t[]> rgbaBuf; + size_t rgbaBufSize, ftsize; + unsigned int i,j; + FT_Error fte; + + if((fte = FT_New_Face(ftl,ttf,0,&ftf))){ + std::cout<<"Error! Couldn't open "<<ttf<<" (Error "<<fte<<")."<<std::endl; abort(); } @@ -229,6 +244,77 @@ namespace ui { DEBUG_printf("Using font %s\n",ttf); #endif // DEBUG + /* + * Load the font in the two sizes we use, 16px and 24px. + */ + + ftmapptr = ftmap16; + ftsize = 16; + + do{ + FT_Set_Pixel_Sizes(ftf, 0, ftsize); + + // allocate texture space + for(i=0; i < FT_CHAR_COUNT; i++) + glGenTextures(1, &ftmapptr[i].tex); + + // Load all characters we expect to use + for(i=33; i<126; i++){ + + // Load the bitmap for the current character. + if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){ + std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl; + abort(); + } + + /* + * Set up the OpenGL texture thing. + */ + + glBindTexture(GL_TEXTURE_2D, ftmapptr[i-33].tex); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR ); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR ); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + /* + * Convert the bitmap font given to us from FreeType into an RGBA + * format, for ease of drawing. + */ + + rgbaBuf.reset(new uint8_t [(rgbaBufSize = ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4)]); + rgbaBufSize /= 4; + + // populate the buffer + for(j=0; j < rgbaBufSize; j++){ + rgbaBuf[j * 4] = rgbaBuf[j * 4 + 1] = rgbaBuf[j * 4 + 2] = 255; + rgbaBuf[j * 4 + 3] = ftf->glyph->bitmap.buffer[j] ? 255 : 0; + } + + // save important character information + ftmapptr[i-33].wh = { (int)ftf->glyph->bitmap.width, (int)ftf->glyph->bitmap.rows }; + ftmapptr[i-33].bl = { ftf->glyph->bitmap_left, ftf->glyph->bitmap_top }; + ftmapptr[i-33].ad = { ftf->glyph->advance.x >> 6, ftf->glyph->advance.y >> 6 }; + + // do the thing + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get()); + rgbaBuf.reset(); + } + + // repeat for 24px, or exit + if(ftmapptr == ftmap16){ + ftmapptr = ftmap24; + ftsize = 24; + }else{ + break; + } + + }while(1); + + setFontSize(16); } /** @@ -237,66 +323,14 @@ namespace ui { */ void setFontSize(unsigned int size){ - unsigned int i,j; - - std::unique_ptr<uint8_t[]> rgbaBuf; - size_t rgbaBufSize = 0; - - FT_Set_Pixel_Sizes(ftf,0,(fontSize = size)); - - // delete old characters, make space for new ones - for(i=0; i < FT_CHAR_COUNT; i++){ - glDeleteTextures(1, &ftmap[i].tex); - glGenTextures(1, &ftmap[i].tex); - } - - // Load all characters we expect to use - for(i=33;i<126;i++){ - - // Load the bitmap for the current character. - if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){ - std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl; - abort(); - } - - /* - * Set up the OpenGL texture thing. - */ - - glBindTexture(GL_TEXTURE_2D, ftmap[i-33].tex); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR ); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR ); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - /* - * Convert the bitmap font given to us from FreeType into an RGBA - * format, for ease of drawing. - */ - - rgbaBuf.reset(new uint8_t [(rgbaBufSize = ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4)]); - rgbaBufSize /= 4; - - // populate the buffer - for(j=0; j < rgbaBufSize; j++){ - rgbaBuf[j * 4 ] = - rgbaBuf[j * 4 + 1] = - rgbaBuf[j * 4 + 2] = 255; - rgbaBuf[j * 4 + 3] = ftf->glyph->bitmap.buffer[j] ? 255 : 0; - } - - // save important character information - ftmap[i-33].wh = { (int)ftf->glyph->bitmap.width, (int)ftf->glyph->bitmap.rows }; - ftmap[i-33].bl = { ftf->glyph->bitmap_left, ftf->glyph->bitmap_top }; - ftmap[i-33].ad = { ftf->glyph->advance.x >> 6, ftf->glyph->advance.y >> 6 }; - - // do the thing - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get()); - - rgbaBuf.release(); + switch((fontSize = size)){ + case 24: + ftmapptr = ftmap24; + break; + default: + case 16: + ftmapptr = ftmap16; + break; } } @@ -318,16 +352,16 @@ namespace ui { ivec2 c1,c2; // calculate coordinates - c1 = { (int)floor(x) + ftmap[c-33].bl.x, - (int)floor(y) + ftmap[c-33].bl.y }; - c2 = ftmap[c-33].wh; + c1 = { (int)floor(x) + ftmapptr[c-33].bl.x, + (int)floor(y) + ftmapptr[c-33].bl.y }; + c2 = ftmapptr[c-33].wh; /* * Draw the character */ glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, ftmap[c-33].tex); + glBindTexture(GL_TEXTURE_2D, ftmapptr[c-33].tex); glPushMatrix(); glTranslatef(0,-c2.y,0); @@ -346,7 +380,7 @@ namespace ui { glDisable(GL_TEXTURE_2D); // return the number of pixels the cursor should move - return ftmap[c-33].ad; + return ftmapptr[c-33].ad; } /** @@ -427,7 +461,7 @@ namespace ui { // handle everything else }else - width += ftmap[i].wh.x + fontSize * .1; + width += ftmapptr[i].wh.x + fontSize * .1; }while(s[++i]); diff --git a/src/world.cpp b/src/world.cpp index 303d53b..eb9f12e 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -140,6 +140,11 @@ void World::deleteEntities(void){ while(!light.empty()){ light.pop_back(); } + while(!village.empty()){ + delete village.back(); + village.pop_back(); + } + } World::~World(void){ |