#include #include #include #include #include #include "gltexture.h" #include "engine.h" #define _(x) x #define DEBUG 1 #ifdef TRACE_TEXTURES mogltk::texture * mogltk::texture::header = 0; mogltk::texture * mogltk::texture::footer = 0; #endif mogltk::texture * mogltk::texture::active = 0; mogltk::texture::texture(int w, int h, bool plane) throw (GeneralException) : width(w), height(h), texture_allocated(false), planar(plane), tainted(true) { if ((BITCOUNT(w) != 1) || (BITCOUNT(h) != 1)) throw GeneralException(_("Size of the texture not a power of 2!")); if (!(surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, #if SDL_BYTEORDER == SDL_BIG_ENDIAN 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #else 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #endif ))) { throw GeneralException(_("Can't create RGB Surface")); } #ifdef TRACE_TEXTURES next = 0; prev = footer; footer = this; if (!header) { header = this; } if (prev) { prev->next = this; } #endif } mogltk::texture::texture(Handle * h, bool plane) throw (GeneralException) : texture_allocated(false), planar(plane), tainted(true) { SDL_Surface * temp; if (!(temp = IMG_Load_RW(engine::RWFromHandle(h), 1))) throw GeneralException(_("Can't load image from Handle ") + h->GetName()); width = temp->w; height = temp->h; if ((BITCOUNT(width) != 1) || (BITCOUNT(height) != 1)) { SDL_FreeSurface(temp); throw GeneralException(_("Size of the texture not a power of 2!")); } if (!(surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, #if SDL_BYTEORDER == SDL_BIG_ENDIAN 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #else 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #endif ))) { SDL_FreeSurface(temp); throw GeneralException(_("Can't create RGB Surface")); } SDL_BlitSurface(temp, 0, surface, 0); SDL_FreeSurface(temp); #ifdef TRACE_TEXTURES next = 0; prev = footer; footer = this; if (!header) { header = this; } if (prev) { prev->next = this; } #endif } mogltk::texture::~texture() { if (surface) { SDL_FreeSurface(surface); } if (texture_allocated) { glDeleteTextures(1, &tex); } #ifdef TRACE_TEXTURES if (prev) { prev->next = next; } if (next) { next->prev = prev; } if (this == footer) { footer = prev; } if (this == header) { header = next; } #endif } SDL_Surface * mogltk::texture::GetSurface() { return surface; } void mogltk::texture::Generate() { if (texture_allocated) { glDeleteTextures(1, &tex); } glGenTextures(1, &tex); #ifdef DEBUG printm(M_INFO, _("Generated texture index: %i\n"), tex); #endif glBindTexture(GL_TEXTURE_2D, tex); if (planar) { #ifdef DEBUG printm(M_INFO, _("Generating planar texture: %i\n"), tex); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); } else { #ifdef DEBUG printm(M_INFO, _("Generating 3D texture: %i\n"), tex); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels); } texture_allocated = true; tainted = false; } void mogltk::texture::Bind(bool expand) { if ((!texture_allocated) || tainted) Generate(); glEnable(GL_TEXTURE_2D); if (active == this) return; #ifdef DEBUG printm(M_INFO, _("Binding texture index %i.\n"), tex); #endif glBindTexture(GL_TEXTURE_2D, tex); if (expand) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScaled(1 / (double) width, 1 / (double) height, 1); glMatrixMode(GL_MODELVIEW); } active = this; #ifdef TRACE_TEXTURES if (header == this) return; if (prev) { prev->next = next; } if (next) { next->prev = prev; } if (footer = this) { footer = prev; } header->prev = this; header = this; #endif } GLuint mogltk::texture::GetWidth() { return width; } GLuint mogltk::texture::GetHeight() { return height; } void mogltk::texture::Unbind(void) { glDisable(GL_TEXTURE_2D); active = 0; #ifdef DEBUG printm(M_INFO, _("Unbinding texture.\n")); #endif } void mogltk::texture::Taint(void) { tainted = true; }