/* Ronny Andr�Reierstad http://www.morrowland.com http://www.morrowland.com/apron/tut_gl.php apron@morrowland.com */ #include "filesystem/filesystem.h" #include "render/tga.h" #include "sys/sys.h" #include "GL/gl.h" #include namespace render { ///////////////////////////////////////////////////////////////////////////////////////////////// // TGA TEXTURE LOADER ///////////////////////////////////////////////////////////////////////////////////////////////// bool TGA::texture(GLuint textureArray[], const char *filename, int ID) { if (!filename) return false; image *pBitMap = load(filename); if (!pBitMap) { con_warn << "Could not load " << filename << std::endl; return false; } glGenTextures(1, &textureArray[ID]); glBindTexture(GL_TEXTURE_2D, textureArray[ID]); int textureType = GL_RGB; if (pBitMap->channels == 4) textureType = GL_RGBA; gluBuild2DMipmaps(GL_TEXTURE_2D, pBitMap->channels, pBitMap->size_x, pBitMap->size_y, textureType, GL_UNSIGNED_BYTE, pBitMap->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); if (pBitMap) { if (pBitMap->data) { free(pBitMap->data); } free(pBitMap); } return true; } TGA::image *TGA::load(const char *filename) { image *pImgData = NULL; //FILE *pFile = NULL; GLushort width = 0; GLushort height = 0; GLubyte length = 0; GLubyte imgType = 0; GLubyte bits = 0; GLushort channels = 0; GLushort stride = 0; filesystem::File *f = filesystem::open(filename); if (!f) return 0; pImgData = (image*)malloc(sizeof(image)); f->read((void *)&length, sizeof(GLubyte)); f->skip(1); f->read((void *)&imgType, sizeof(GLubyte)); f->skip(9); f->read((void *)&width, sizeof(GLushort)); f->read((void *)&height, sizeof(GLushort)); f->read((void *)&bits, sizeof(GLubyte)); f->skip(length +1); con_debug << "TGA loading " << width << "x" << height << " " << (int) bits << "bpp" << std::endl; if (imgType != TGA_RLE) { // Check for 24 or 32 Bit if (bits == 24 || bits == 32) { channels = bits / 8; stride = channels * width; pImgData->data = new unsigned char[stride * height]; for (GLushort y = 0; y < height; y++) { unsigned char *pLine = &(pImgData->data[stride * y]); f->read((void *)pLine, stride); for (GLushort i = 0; i < stride; i += channels) { int temp = pLine[i]; pLine[i] = pLine[i + 2]; pLine[i + 2] = temp; } } } // Check for 16 Bit else if (bits == 16) { unsigned short pixels = 0; int r=0, g=0, b=0; channels = 3; stride = channels * width; pImgData->data = new unsigned char[stride * height]; for (int i = 0; i < width*height; i++) { f->read((void *)&pixels, sizeof(GLushort)); b = (pixels & 0x1f) << 3; g = ((pixels >> 5) & 0x1f) << 3; r = ((pixels >> 10) & 0x1f) << 3; pImgData->data[i * 3 + 0] = r; pImgData->data[i * 3 + 1] = g; pImgData->data[i * 3 + 2] = b; } } else return NULL; } else { GLubyte rleID = 0; int colorsRead = 0; channels = bits / 8; stride = channels * width; pImgData->data = new unsigned char[stride * height]; GLubyte *pColors = new GLubyte [channels]; int i = 0; while (i < width*height) { f->read((void *)&rleID, sizeof(GLubyte)); if (rleID < 128) { rleID++; while (rleID) { f->read((void *)pColors, sizeof(GLubyte) * channels); pImgData->data[colorsRead + 0] = pColors[2]; pImgData->data[colorsRead + 1] = pColors[1]; pImgData->data[colorsRead + 2] = pColors[0]; if (bits == 32) pImgData->data[colorsRead + 3] = pColors[3]; i++; rleID--; colorsRead += channels; } } else { rleID -= 127; f->read((void *)pColors, sizeof(GLubyte) * channels); while (rleID) { pImgData->data[colorsRead + 0] = pColors[2]; pImgData->data[colorsRead + 1] = pColors[1]; pImgData->data[colorsRead + 2] = pColors[0]; if (bits == 32) pImgData->data[colorsRead + 3] = pColors[3]; i++; rleID--; colorsRead += channels; } } } delete[] pColors; } filesystem::close(f); pImgData->channels = channels; pImgData->size_x = width; pImgData->size_y = height; return pImgData; } }