texture manager update + updating panoramic camera

This commit is contained in:
Vladislav Khorev 2013-04-18 20:21:19 +00:00
parent 8fdd1da938
commit c657c91851
11 changed files with 581 additions and 193 deletions

View File

@ -52,10 +52,12 @@
<ClInclude Include="..\include\Utils\DataTypes\NewDataTypes.h" />
<ClInclude Include="..\include\Utils\ErrorTypes\ErrorTypes.h" />
<ClInclude Include="..\include\Utils\FileUtils\FileUtils.h" />
<ClInclude Include="..\include\Utils\JpegHelper.h" />
<ClInclude Include="..\include\Utils\Network\Network.h" />
<ClInclude Include="..\include\Utils\Network\SignalSender.h" />
<ClInclude Include="..\include\Utils\PngHelper.h" />
<ClInclude Include="..\include\Utils\SerializeInterface\SerializeInterface.h" />
<ClInclude Include="..\include\Utils\TgaLoader.h" />
<ClInclude Include="..\include\Utils\ThreadUtils.h" />
<ClInclude Include="..\include\Utils\ThreadUtilsImpl.h" />
<ClInclude Include="..\include\Utils\Utils.h" />
@ -94,10 +96,12 @@
<ClCompile Include="..\src\Utils\DataTypes\DataTypes.cpp" />
<ClCompile Include="..\src\Utils\DataTypes\NewDataTypes.cpp" />
<ClCompile Include="..\src\Utils\FileUtils\FileUtils.cpp" />
<ClCompile Include="..\src\Utils\JpegHelper.cpp" />
<ClCompile Include="..\src\Utils\Network\Network.cpp" />
<ClCompile Include="..\src\Utils\PngHelper.cpp" />
<ClCompile Include="..\src\Utils\SerializeInterface\SerializeInterface.cpp" />
<ClCompile Include="..\src\Utils\SimpleTimer.cpp" />
<ClCompile Include="..\src\Utils\TgaLoader.cpp" />
<ClCompile Include="..\src\Utils\ThreadUtils.cpp" />
<ClCompile Include="..\src\Utils\WinApi\WinApi.cpp" />
</ItemGroup>
@ -152,7 +156,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>TARGET_WIN32;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0501;DEBUG</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SalmonEnginePath);$(LibsPath)\boost_1_52_0;$(LibsPath)\openal\OpenAL11_windows_sdk;$(LibsPath)\libogg-1.3.0\include;$(LibsPath)\libvorbis-1.3.2\include;$(LibsPath)\sqplus\sqplus;$(LibsPath)\sqplus\include;$(LibsPath)\DirectXsdk\Include;$(LibsPath)\lpng1510</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SalmonEnginePath);$(LibsPath)\boost_1_52_0;$(LibsPath)\openal\OpenAL11_windows_sdk;$(LibsPath)\libogg-1.3.0\include;$(LibsPath)\libvorbis-1.3.2\include;$(LibsPath)\sqplus\sqplus;$(LibsPath)\sqplus\include;$(LibsPath)\DirectXsdk\Include;$(LibsPath)\lpng1510;$(LibsPath)\jpeg-9;$(LibsPath)\jpeg-9\vc10</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4503</DisableSpecificWarnings>
</ClCompile>
<Link>

View File

@ -43,6 +43,8 @@ struct TPanoramicCamera : public TCameraInterface
void CalcCamVec();
void SetCamView();
void SetCamShift(const vec3& camShift);
};
struct TPitCamera : public TCameraInterface

View File

@ -16,6 +16,8 @@ This code contains texture manager
#include "include/Utils/Utils.h"
#include "include/Utils/PngHelper.h"
#include "include/Utils/JpegHelper.h"
#include "include/Utils/TgaLoader.h"
#include "include/ScriptManager/ScriptManager.h"
namespace SE
@ -40,7 +42,7 @@ struct TTextureData
boost::shared_array<char> Data;
};
typedef std::map<std::string, TTextureInfo, std::less<std::string> > TTextureMap;
typedef std::map<std::string, TTextureInfo, std::less<std::string>> TTextureMap;
class TTextureListClass : public TSerializeInterface, public TFunctionBinderInterface
@ -58,6 +60,7 @@ protected:
bool CreateTexDataFromBmp32(const std::string& filename, TTextureData& texData);
bool CreateTexDataFromTga(const std::string& filename, TTextureData& texData);
bool CreateTexDataFromPng(const std::string& filename, TTextureData& texData);
bool CreateTexDataFromJpg(const std::string& filename, TTextureData& texData);
cardinal AddTextureBmp24Data(const TTextureData& texData); //MAIN THREAD ONLY
cardinal AddTextureBmp32Data(const TTextureData& texData); //MAIN THREAD ONLY

View File

@ -38,13 +38,83 @@ bool findString(char* in, char* list);
bool IsFileExistsInUserData(const std::string& filename);
std::string GetFilePathUserData(const std::string& filename);
//utitily to process texture uploading
inline char* GetFileName(const char* filename)
{
char* fname = (char*)filename + strlen(filename);
while ((*fname != '\\')&&(*fname != '/')&&(fname >= filename ))
--fname;
++fname;
return fname;
}
inline std::string GetFileName(const std::string& filename)
{
std::string::const_iterator i = filename.end() - 1;
while ((i > filename.begin() )&&(*i != '\\')&&(*i != '/'))
--i;
if (*i == '\\' || *i == '/')
{
i++;
}
return std::string(i, filename.end());
}
//utitily to process texture uploading
inline char* GetFileExt(const char* filename)
{
char* fext = (char*)filename + strlen(filename);
while (*fext != '.')
--fext;
return fext;
}
inline std::string GetFileExt(const std::string& filename)
{
std::string::const_iterator i = filename.end() - 1;
while (*i != '.')
--i;
return std::string(i, filename.end());
}
inline std::string GetFileNameWithoutExt(const std::string& filename)
{
std::string result = GetFileName(filename);
std::string::const_iterator i = result.end() - 1;
while (*i != '.')
--i;
return std::string(result.begin(), i);
}
std::string GetFilePath(const std::string& filename);
#ifdef TARGET_WIN32
void GetFileList(const std::string& searchkey, std::vector<std::string> &list);
std::string AutocompleteExtension(const std::string& fileName);
template<typename TYPENAME>
boost::shared_array<TYPENAME> CreateMemFromFile(const std::string& fileName, cardinal& intCount)
{
@ -57,11 +127,9 @@ boost::shared_array<TYPENAME> CreateMemFromFile(const std::string& fileName, car
size_t result;
TYPENAME* fileData;
std::string realFileName = fileName;
if (fopen_s(&pFile, realFileName.c_str(), "rb" ) != 0)
if (fopen_s(&pFile, fileName.c_str(), "rb" ) != 0)
{
throw ErrorToLog("File not loaded: " + fileName);
}
@ -196,70 +264,6 @@ boost::shared_array<TYPENAME> CreateMemFromFile(const std::string& fileName, car
#endif
//utitily to process texture uploading
inline char* GetFileName(const char* filename)
{
char* fname = (char*)filename + strlen(filename);
while ((*fname != '\\')&&(*fname != '/')&&(fname >= filename ))
--fname;
++fname;
return fname;
}
inline std::string GetFileName(const std::string& filename)
{
std::string::const_iterator i = filename.end() - 1;
while ((i > filename.begin() )&&(*i != '\\')&&(*i != '/'))
--i;
if (*i == '\\' || *i == '/')
{
i++;
}
return std::string(i, filename.end());
}
//utitily to process texture uploading
inline char* GetFileExt(const char* filename)
{
char* fext = (char*)filename + strlen(filename);
while (*fext != '.')
--fext;
return fext;
}
inline std::string GetFileExt(const std::string& filename)
{
std::string::const_iterator i = filename.end() - 1;
while (*i != '.')
--i;
return std::string(i, filename.end());
}
inline std::string GetFileNameWithoutExt(const std::string& filename)
{
std::string result = GetFileName(filename);
std::string::const_iterator i = result.end() - 1;
while (*i != '.')
--i;
return std::string(result.begin(), i);
}
std::string GetFilePath(const std::string& filename);
#ifdef TARGET_IOS
//Special for IOS, because Foundation.h conflicts with sq_plus.h

View File

@ -0,0 +1,16 @@
#ifndef JPEG_HELPER_H_INCLUDED
#define JPEG_HELPER_H_INCLUDED
#include <string>
namespace SE
{
struct TTextureData; // Find it in SalmonTexture.h
bool LoadJpg(const std::string& filename, TTextureData& texData);
} //namespace SE
#endif //JPEG_HELPER_H_INCLUDED

55
include/Utils/TgaLoader.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef TGA_LOADER_H_INCLUDED
#define TGA_LOADER_H_INCLUDED
#include "include/Utils/Utils.h"
//Thanks to NeHe
namespace SE
{
const int CONST_TGA_OUTER_HEADER_SIZE = 12;
typedef struct
{
GLubyte Header[CONST_TGA_OUTER_HEADER_SIZE]; // TGA File Header
} TGAHeader;
const int CONST_TGA_INNER_HEADER_SIZE = 6;
typedef struct
{
GLubyte header[CONST_TGA_INNER_HEADER_SIZE]; // First 6 Useful Bytes From The Header
GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File
GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram
GLuint temp; // Temporary Variable
GLuint type;
GLuint Height; //Height of Image
GLuint Width; //Width ofImage
GLuint Bpp; // Bits Per Pixel
} TGA;
//TGAHeader tgaheader; // TGA header
//TGA tga; // TGA image data
extern GLubyte uTGAcompare[12]; // Uncompressed TGA Header
extern GLubyte cTGAcompare[12]; // Compressed TGA Header
struct TTextureData; // Find it in SalmonTexture.h
bool LoadTGA(const std::string& filename, TTextureData& texture);
bool LoadUncompressedTGA(TTextureData& texture, boost::shared_array<char> fTGA); // Load an Uncompressed file
bool LoadCompressedTGA(TTextureData& texture, boost::shared_array<char> fTGA); // Load a Compressed file
} //namespace SE
#endif //TGA_LOADER_H_INCLUDED

View File

@ -197,6 +197,14 @@ void TPanoramicCamera::SetCamView()
}
void TPanoramicCamera::SetCamShift(const vec3& camShift)
{
CamShift = camShift;
Renderer->CalcCamPos();
}
void TPitCamera::SetCamView()
{
Renderer->LoadIdentity();

View File

@ -9,6 +9,9 @@
#include "boost/assign.hpp"
#include "jpeglib.h"
#include <setjmp.h>
namespace SE
{
@ -22,13 +25,9 @@ TTextureListClass::TTextureListClass()
CreateFunctionMap[".bmp32"] = boost::bind(&TTextureListClass::CreateTexDataFromBmp32, this, _1, _2);
CreateFunctionMap[".png"] = boost::bind(&TTextureListClass::CreateTexDataFromPng, this, _1, _2);
CreateFunctionMap[".tga"] = boost::bind(&TTextureListClass::CreateTexDataFromTga, this, _1, _2);
/*
AddFunctionMap["bmp24"] = boost::bind(&TTextureListClass::AddTextureBmp24Data, this, _1);
AddFunctionMap["bmp32"] = boost::bind(&TTextureListClass::AddTextureBmp32Data, this, _1);
Let's use inner functions!
*/
CreateFunctionMap[".jpg"] = boost::bind(&TTextureListClass::CreateTexDataFromJpg, this, _1, _2);
CreateFunctionMap[".jpeg"] = boost::bind(&TTextureListClass::CreateTexDataFromJpg, this, _1, _2);
AddFunctionMap["bmp24"] = [this](TTextureData& texData) -> cardinal
{
@ -396,121 +395,22 @@ bool TTextureListClass::CreateTexDataFromBmp32(const std::string& filename, TTex
bool TTextureListClass::CreateTexDataFromTga(const std::string& filename, TTextureData& texData)
{
bool result = LoadTGA(filename, texData);
cardinal fileSize;
boost::shared_array<char> fileArr = CreateMemFromFile<char>(filename, fileSize);
if (fileSize < 22)
if (!result)
{
throw ErrorFileNotCorrect(filename);
texData.Width = *reinterpret_cast<unsigned short int*>(&fileArr[12]);
texData.Height = *reinterpret_cast<unsigned short int*>(&fileArr[14]);
char textLength = fileArr[0];
char dataType = fileArr[2];
char bitsPerPixel = fileArr[16];
if (bitsPerPixel == 24)
{
texData.DataSize = texData.Height * texData.Width * 3;
texData.Data = boost::shared_array<char>(new char [texData.DataSize]);
strcpy(texData.Format, "bmp24");
}
else
if (bitsPerPixel == 32)
{
texData.DataSize = texData.Height * texData.Width * 4;
texData.Data = boost::shared_array<char>(new char [texData.DataSize]);
strcpy(texData.Format, "bmp32");
}
else
throw ErrorFileNotCorrect(filename);
int bytesPerPixel = bitsPerPixel / 8;
return result;
unsigned char blockInfo;
char whatItIs;
unsigned int numPixels;
}
cardinal n = 0;
int filePos = textLength + 18;
if (dataType == 2)
{
for(cardinal n = 0; n < texData.Height * texData.Width; n++)
{
texData.Data[n*bytesPerPixel + 2] = fileArr[filePos++];
texData.Data[n*bytesPerPixel + 1] = fileArr[filePos++];
texData.Data[n*bytesPerPixel + 0] = fileArr[filePos++];
if (bitsPerPixel == 32)
{
texData.Data[n*bytesPerPixel + 3] = fileArr[filePos++];
}
}
}
else if (dataType == 10)
{
throw ErrorToLog("RLE-compressed TGA is not supported yet: "+filename);
while (n < texData.Height * texData.Width)
{
blockInfo = fileArr[filePos++];
whatItIs = blockInfo & 128;
numPixels = blockInfo & 127;
if (whatItIs)
{
for (cardinal i=0; i<numPixels; i++)
{
texData.Data[n*bytesPerPixel + 0] = fileArr[filePos + 0];
texData.Data[n*bytesPerPixel + 1] = fileArr[filePos + 1];
texData.Data[n*bytesPerPixel + 2] = fileArr[filePos + 2];
if (bitsPerPixel == 32)
{
texData.Data[n*bytesPerPixel + 3] = fileArr[filePos + 3];
}
n++;
}
if (bitsPerPixel == 32)
{
filePos += 4;
}
else
{
filePos += 3;
}
}
else
{
for (cardinal i=0; i<numPixels; i++)
{
texData.Data[n*bytesPerPixel + 0] = fileArr[filePos++];
texData.Data[n*bytesPerPixel + 1] = fileArr[filePos++];
texData.Data[n*bytesPerPixel + 2] = fileArr[filePos++];
if (bitsPerPixel == 32)
{
texData.Data[n*bytesPerPixel + 3] = fileArr[filePos++];
}
n++;
}
}
}
}
else
throw ErrorFileNotCorrect(filename);
return true;
bool TTextureListClass::CreateTexDataFromJpg(const std::string& filename, TTextureData& texData)
{
return LoadJpg(filename, texData);
}
@ -682,11 +582,6 @@ cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std:
{
cardinal TexID;
if (texName == "")
{
texName = GetFileName(filename);
}
//Basically:
if (filename == "")
return 0;
@ -730,14 +625,29 @@ cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std:
cardinal TTextureListClass::AddTexture(const std::string& fileName)
{
return AddTexture(fileName, "");
return AddTexture(fileName, GetFileName(fileName));
}
cardinal TTextureListClass::AddTexture(const std::string& fileName, std::string texName)
{
std::string fullFileName = ST::PathToResources + fileName;
std::string fullFileName = ST::PathToResources + fileName;
return AddTextureDirectly(fullFileName, texName);
std::string realFileName;
if (GetFileName(fileName).find('.') == std::string::npos)
{
realFileName = AutocompleteExtension(fullFileName); //AutocompleteExtension works for Windows only
}
else
{
realFileName = fullFileName; //AutocompleteExtension works for Windows only
}
return AddTextureDirectly(realFileName, texName);
}

View File

@ -111,6 +111,30 @@ void GetFileList(const std::string& searchkey, std::vector<std::string> &list)
break;
}
}
std::string AutocompleteExtension(const std::string& fileName)
{
std::string filePath = GetFilePath(fileName);
std::vector<std::string> list;
GetFileList(fileName+".bmp", list);
GetFileList(fileName+".bmp32", list);
GetFileList(fileName+".tga", list);
GetFileList(fileName+".png", list);
GetFileList(fileName+".jpg", list);
if (list.size() == 0)
{
throw ErrorToLog("AutocompleteExtension - file not found!");
}
return filePath+list[0];
}
#endif
#ifdef TARGET_IOS

116
src/Utils/JpegHelper.cpp Normal file
View File

@ -0,0 +1,116 @@
#include "include/Utils/JpegHelper.h"
#include "include/Utils/Utils.h"
#include "include/TextureManager/SalmonTexture.h"
#include "boost/gil/gil_all.hpp"
#include "boost/gil/extension/numeric/sampler.hpp"
#include "boost/gil/extension/numeric/resample.hpp"
#include "boost/assign.hpp"
#include "jpeglib.h"
#include <setjmp.h>
namespace SE
{
struct my_error_mgr
{
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
my_error_mgr* myerr = (my_error_mgr*) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
throw ErrorToLog("JPEG Error!");
}
bool LoadJpg(const std::string& filename, TTextureData& texData)
{
jpeg_decompress_struct cinfo;
my_error_mgr jerr;
JSAMPARRAY buffer;
int row_stride;
cardinal fileSize;
boost::shared_array<unsigned char> fileArr = CreateMemFromFile<unsigned char>(filename, fileSize);
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo, &fileArr[0], fileSize);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
if (cinfo.output_components == 3)
{
strcpy(texData.Format, "bmp24");
}
else if (cinfo.output_components == 4)
{
strcpy(texData.Format, "bmp32");
}
else
{
throw ErrorToLog("cinfo.output_components unknown value!");
}
texData.Width = cinfo.output_width;
texData.Height = cinfo.output_height;
texData.DataSize = cinfo.output_height * cinfo.output_width * cinfo.output_components;
texData.Data = boost::shared_array<char>(new char[texData.DataSize]);
while (cinfo.output_scanline < cinfo.output_height)
{
JDIMENSION read_now = jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(&texData.Data[(cinfo.output_scanline - read_now) * cinfo.output_width * cinfo.output_components], buffer[0], row_stride);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
using namespace boost::gil;
boost::shared_array<char> newData(new char[texData.Height * texData.Width * 3]);
rgb8_view_t oldView = interleaved_view(texData.Width, texData.Height, reinterpret_cast<const rgb8_ptr_t>(texData.Data.get()), texData.DataSize / texData.Height);
rgb8_view_t newView = interleaved_view(texData.Width, texData.Height, reinterpret_cast<const rgb8_ptr_t>(newData.get()), texData.DataSize / texData.Height);
copy_pixels(flipped_up_down_view(oldView), newView);
texData.Data = newData;
return true;
}
} //namespace SE

246
src/Utils/TgaLoader.cpp Normal file
View File

@ -0,0 +1,246 @@
#include "include/Utils/TgaLoader.h"
#include "include/Utils/Utils.h"
#include "include/TextureManager/SalmonTexture.h"
//Thanks to NeHe
namespace SE
{
GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; // Compressed TGA Header
//bool LoadTGA(Texture * texture, char * filename) // Load a TGA file
bool LoadTGA(const std::string& filename, TTextureData& texture) // Load a TGA file
{
cardinal byteCount;
boost::shared_array<char> fTGA = CreateMemFromFile<char>(filename, byteCount);
TGAHeader tgaheader;
tgaheader = *(reinterpret_cast<TGAHeader*>(&fTGA[0]));
if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of
{ // an Uncompressed TGA image
return LoadUncompressedTGA(texture, fTGA); // If so, jump to Uncompressed TGA loading code
}
else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of
{ // an RLE compressed TGA image
return LoadCompressedTGA(texture, fTGA); // If so, jump to Compressed TGA loading code
}
else // If header matches neither type
{
return false; // Exit function
}
// All went well, continue on
}
//bool LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA) // Load an uncompressed TGA (note, much of this code is based on NeHe's
bool LoadUncompressedTGA(TTextureData& texture, boost::shared_array<char> fTGA) // Load an uncompressed TGA (note, much of this code is based on NeHe's
{ // TGA Loading code nehe.gamedev.net)
TGA tga;
int shift = sizeof(TGAHeader);
memcpy(tga.header, &fTGA[shift], CONST_TGA_INNER_HEADER_SIZE);
shift += CONST_TGA_INNER_HEADER_SIZE;
texture.Width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture.Height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
int bitsPerPixel = tga.header[4];
if (bitsPerPixel == 24)
{
strcpy(texture.Format, "bmp24");
}
else if (bitsPerPixel == 32)
{
strcpy(texture.Format, "bmp32");
}
else
{
return false;
}
//texture->bpp = tga.header[4]; // Determine the bits per pixel
tga.Width = texture.Width; // Copy width into local structure
tga.Height = texture.Height; // Copy height into local structure
tga.Bpp = bitsPerPixel; // Copy BPP into local structure
if((texture.Width <= 0) || (texture.Height <= 0)) // Make sure all information is valid
{
return false; // Return failed
}
tga.bytesPerPixel = (tga.Bpp / 8); // Compute the number of BYTES per pixel
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute the total amout ofmemory needed to store data
texture.DataSize = tga.imageSize;
texture.Data = boost::shared_array<char>(new char [texture.DataSize]);
memcpy(&texture.Data[0], &fTGA[shift], texture.DataSize);
// Byte Swapping Optimized By Steve Thomas
for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)
{
texture.Data[cswap] ^= texture.Data[cswap+2] ^=
texture.Data[cswap] ^= texture.Data[cswap+2];
}
return true;
}
//bool LoadCompressedTGA(Texture * texture, char * filename, FILE * fTGA) // Load COMPRESSED TGAs
bool LoadCompressedTGA(TTextureData& texture, boost::shared_array<char> fTGA) // Load COMPRESSED TGAs
{
TGA tga;
int shift = sizeof(TGAHeader);
memcpy(tga.header, &fTGA[shift], CONST_TGA_INNER_HEADER_SIZE);
shift += CONST_TGA_INNER_HEADER_SIZE;
texture.Width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture.Height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
int bitsPerPixel = tga.header[4];
if (bitsPerPixel == 24)
{
strcpy(texture.Format, "bmp24");
}
else if (bitsPerPixel == 32)
{
strcpy(texture.Format, "bmp32");
}
else
{
return false;
}
tga.Width = texture.Width; // Copy width into local structure
tga.Height = texture.Height; // Copy height into local structure
tga.Bpp = bitsPerPixel; // Copy BPP into local structure
if((texture.Width <= 0) || (texture.Height <= 0)) //Make sure all texture info is ok
{
return false; // Return failed
}
tga.bytesPerPixel = (tga.Bpp / 8); // Compute BYTES per pixel
tga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute amout of memory needed to store image
texture.DataSize = tga.imageSize;
texture.Data = boost::shared_array<char>(new char [texture.DataSize]);
GLuint pixelcount = tga.Height * tga.Width; // Nuber of pixels in the image
GLuint currentpixel = 0; // Current pixel being read
GLuint currentbyte = 0; // Current byte
//GLubyte* colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel); // Storage for 1 pixel
boost::shared_array<GLubyte> colorbuffer(new GLubyte[tga.bytesPerPixel]);
do
{
GLubyte chunkheader = 0; // Storage for "chunk" header
chunkheader = static_cast<GLubyte>(fTGA[shift]);
shift += sizeof(GLubyte);
if(chunkheader < 128) // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
{ // that follow the header
chunkheader++; // add 1 to get number of following color values
for(short counter = 0; counter < chunkheader; counter++) // Read RAW color values
{
memcpy(&colorbuffer[0], &fTGA[shift], tga.bytesPerPixel);
shift += tga.bytesPerPixel;
texture.Data[currentbyte] = static_cast<char>(colorbuffer[2]);
texture.Data[currentbyte + 1] = static_cast<char>(colorbuffer[1]);
texture.Data[currentbyte + 2] = static_cast<char>(colorbuffer[0]);
if(tga.bytesPerPixel == 4) // if its a 32 bpp image
{
texture.Data[currentbyte + 3] = static_cast<char>(colorbuffer[3]);
}
currentbyte += tga.bytesPerPixel; // Increase thecurrent byte by the number of bytes per pixel
currentpixel++; // Increase current pixel by 1
if(currentpixel > pixelcount) // Make sure we havent read too many pixels
{
return false; // Return failed
}
}
}
else // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
{
chunkheader -= 127; // Subteact 127 to get rid of the ID bit
memcpy(&colorbuffer[0], &fTGA[shift], tga.bytesPerPixel);
shift += tga.bytesPerPixel;
for(short counter = 0; counter < chunkheader; counter++) // copy the color into the image data as many times as dictated
{ // by the header
texture.Data[currentbyte] = static_cast<char>(colorbuffer[2]);
texture.Data[currentbyte + 1] = static_cast<char>(colorbuffer[1]);
texture.Data[currentbyte + 2] = static_cast<char>(colorbuffer[0]);
if(tga.bytesPerPixel == 4) // if its a 32 bpp image
{
texture.Data[currentbyte + 3] = static_cast<char>(colorbuffer[3]);
}
currentbyte += tga.bytesPerPixel; // Increase current byte by the number of bytes per pixel
currentpixel++; // Increase pixel count by 1
if(currentpixel > pixelcount) // Make sure we havent written too many pixels
{
return false; // Return failed
}
}
}
} while(currentpixel < pixelcount); // Loop while there are still pixels left
return true; // return success
}
} //namespace SE