/* 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 ///////////////////////////////////////////////////////////////////////////////////////////////// void TGA::texture(GLuint textureArray[], const char *filename, int ID) { if(!filename) return; filesystem::File f; f.open(filename); if (!f.is_open()) return; f.close(); image *pBitMap = load(f.path().c_str()); if(pBitMap == 0) { con_warn << "could not load " << f.path().c_str() << std::endl; return; } 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); } } 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; pFile = fopen(filename, "rb"); if (!pFile) return 0; pImgData = (image*)malloc(sizeof(image)); fread(&length, sizeof(GLubyte), 1, pFile); fseek(pFile,1,SEEK_CUR); fread(&imgType, sizeof(GLubyte), 1, pFile); fseek(pFile, 9, SEEK_CUR); fread(&width, sizeof(GLushort), 1, pFile); fread(&height, sizeof(GLushort), 1, pFile); fread(&bits, sizeof(GLubyte), 1, pFile); con_debug << "TGA loading " << width << "x" << height << " " << (int) bits << "bpp" << std::endl; fseek(pFile, length + 1, SEEK_CUR); 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]); fread(pLine, stride, 1, pFile); 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++) { fread(&pixels, sizeof(GLushort), 1, pFile); 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) { fread(&rleID, sizeof(GLubyte), 1, pFile); if(rleID < 128) { rleID++; while(rleID) { fread(pColors, sizeof(GLubyte) * channels, 1, pFile); 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; fread(pColors, sizeof(GLubyte) * channels, 1, pFile); 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; } fclose(pFile); pImgData->channels = channels; pImgData->size_x = width; pImgData->size_y = height; return pImgData; } }