Code:
UINT TextureManager::LoadTGA(char *FileName)
{
int i;
WORD width, height;
byte *data = NULL;
byte type, bits, length;
int rowlength, channels, filesize;
byte *pBuffer = NULL;
byte *ptr = NULL;
FILE *pFile = fopen(FileName, "rb");
if(!pFile)
{
TextureData << "TextureManager::LoadTGA: could not load tga file: " << FileName << "\n";
return NULL;
}
fseek(pFile, 0, SEEK_END);
filesize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
pBuffer = new byte[filesize];
fread(pBuffer, 1, filesize, pFile);
fclose(pFile);
ptr = pBuffer;
length = *(byte*)ptr;
ptr+=2;
type = *(byte*)ptr;
ptr += 10;
width = *(WORD*)ptr;
ptr += sizeof(WORD);
height = *(WORD*)ptr;
ptr += sizeof(WORD);
bits = *(byte*)ptr;
ptr++;
ptr += length+1;
if(bits == 16)
{
MessageBox(NULL, "LoadTGA: Doesn't support 16bit","ERROR", MB_OK);
return NULL;
}
channels = bits / 8;
rowlength = channels * width;//length of a row in bytes
data = new byte[rowlength * height];
unsigned int y;
if(type != TGA_RLE)
{
if(channels == 3)
{
for(i = 0; i < height; i++)
{
for(y = 0; y < rowlength; y++)
{
data[(i*rowlength)+y] = *(byte*)ptr;
ptr++;
}
}
GLenum GLtype = GL_BGR_EXT;
return GenerateInternalTexture(data, channels, width, height, GLtype);
}
else
{
if(channels == 4)
{
for(i = 0; i < height; i++)
{
for(y = 0; y < rowlength; y++)
{
data[(i*rowlength)+y] = *(byte*)ptr;
ptr++;
}
}
}
GLenum GLtype = GL_BGRA_EXT;
ptr = NULL;
delete [] pBuffer;
delete ptr;
return GenerateInternalTexture(data, channels, width, height, GLtype);
}
//FIXME: make sure all of the data is cleaned up!
}
else if(type == TGA_RLE) //NOTE: LoadTGA_RLE must delete data when done!
return LoadTGA_RLE(pBuffer, ptr, bits, channels, width, height, data);
}
UINT TextureManager::LoadTGA_RLE(byte*pBuffer, byte*ptr, byte bits, byte channels, WORD width, WORD height, byte *data)
{
byte *pColor = new byte[channels];
int pixelsleft = 0;
int colorsread = 0;
int pixelsread = 0;
int totalpixels = width * height;
unsigned int y; //counter
//FIXME: must have an error logging system!
if(!ptr)
return NULL;
if(!pBuffer)
return NULL;
while(pixelsread < totalpixels)
{
pixelsleft = *(byte*)ptr;
ptr++;
if(pixelsleft < 128)
{
pixelsleft++;
if(channels == 4)
{
while(pixelsleft)
{
for(y = 0; y < channels; y++)
{
pColor[y] = *(byte*)ptr;
ptr++;
}
data[colorsread + 0] = pColor[0];
data[colorsread + 1] = pColor[1];
data[colorsread + 2] = pColor[2];
data[colorsread + 3] = pColor[3];
pixelsread++;
pixelsleft--;
colorsread += channels;
}
}
else if(channels == 3)
{
while(pixelsleft)
{
for(y = 0; y < channels; y++)
{
pColor[y] = *(byte*)ptr;
ptr++;
}
data[colorsread + 0] = pColor[0];
data[colorsread + 1] = pColor[1];
data[colorsread + 2] = pColor[2];
pixelsread++;
pixelsleft--;
colorsread += channels;
}
}
}
else
{
pixelsleft -= 127;
for(y = 0; y < channels; y++)
{
pColor[y] = *(byte*)ptr;
ptr++;
}
if(channels == 4)
{
while(pixelsleft)
{
data[colorsread + 0] = pColor[0];
data[colorsread + 1] = pColor[1];
data[colorsread + 2] = pColor[2];
data[colorsread + 3] = pColor[3];
pixelsread++;
pixelsleft--;
colorsread += channels;
}
}
else if(channels == 3)
{
while(pixelsleft)
{
data[colorsread + 0] = pColor[0];
data[colorsread + 1] = pColor[1];
data[colorsread + 2] = pColor[2];
pixelsread++;
pixelsleft--;
colorsread += channels;
}
}
}
}
ptr=NULL;
delete [] pBuffer;
delete ptr;
GLenum GLtype;
if(channels == 4)
GLtype = GL_BGRA_EXT;
if(channels == 3)
GLtype = GL_BGR_EXT;
return GenerateInternalTexture(data, channels, width, height, GLtype);
}
UINT TextureManager::GenerateInternalTexture(byte * data, int channels, int width, int height, GLenum type)
{
UINT texture;
gpNTGLAPI->ntglGenTextures(1, &texture);
gpNTGLAPI->ntglPixelStorei (GL_UNPACK_ALIGNMENT, 1);
gpNTGLAPI->ntglBindTexture(GL_TEXTURE_2D, texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, channels,width,height, type, GL_UNSIGNED_BYTE, data);
gpNTGLAPI->ntglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //GL_LINEAR_MIPMAP_NEAREST is faster than GL_LINEAR_MIPMAP_LINEAR
gpNTGLAPI->ntglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gpNTGLAPI->ntglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
return texture;
}