224 lines
5.3 KiB
C++
224 lines
5.3 KiB
C++
/*********************/
|
|
/*** Texture Cache ***/
|
|
/*********************/
|
|
|
|
#include "stdafx.h"
|
|
#include <gl\gl.h>
|
|
#include <gl\glu.h>
|
|
#include <frame.hpp>
|
|
#include <gfname.hpp>
|
|
#include <Vector>
|
|
|
|
#include "TexCache.h"
|
|
#include "utils.h"
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
// Checks loaded files for dups, assumes all passed RGB is unique
|
|
int CTexCache::ProcessTexture(const char *Filename,sRGBData *RGBData)
|
|
{
|
|
int ListSize=TexList.size();
|
|
sTex NewTex;
|
|
sRGBData ThisRGB;
|
|
GFName FName=Filename;
|
|
|
|
NewTex.Name=FName.File();
|
|
NewTex.Filename=Filename;
|
|
|
|
if (!RGBData) // Need to load file
|
|
{
|
|
int Idx=GetTexIdx(NewTex); // Is already loaded?
|
|
if (Idx!=-1) return(Idx);
|
|
|
|
// TRACE1("Loading Texture %s\n",NewTex.Filename);
|
|
|
|
if (!LoadBMP(NewTex.Filename,ThisRGB))
|
|
{
|
|
exit(-1);
|
|
return(ListSize);
|
|
}
|
|
RGBData=&ThisRGB;
|
|
LoadTex(NewTex,RGBData);
|
|
FreeBMP(ThisRGB);
|
|
NewTex.Loaded=true;
|
|
}
|
|
else
|
|
{
|
|
LoadTex(NewTex,RGBData);
|
|
NewTex.Loaded=FALSE;
|
|
}
|
|
|
|
TexList.push_back(NewTex);
|
|
|
|
return(ListSize);
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
/**************************************************************************************/
|
|
/**************************************************************************************/
|
|
void CTexCache::CreateAlignTex(Frame &ThisFrame,sRGBData &RGBData)
|
|
{
|
|
int FrameW=ThisFrame.GetWidth();
|
|
int FrameH=ThisFrame.GetHeight();
|
|
int AlignW=AlignSize(FrameW);
|
|
int AlignH=AlignSize(FrameH);
|
|
|
|
RGBData.RGB=(u8*)MemAlloc(AlignW*AlignH*3);
|
|
ThisFrame.FlipY();
|
|
RGBData.OldW=FrameW;
|
|
RGBData.OldH=FrameH;
|
|
RGBData.TexW=AlignW;
|
|
RGBData.TexH=AlignH;
|
|
RGBData.ScaleU=(float)FrameW/(float)AlignW;
|
|
RGBData.ScaleV=(float)FrameH/(float)AlignH;
|
|
|
|
if (FrameW==AlignW && FrameH==AlignH)
|
|
{
|
|
ThisFrame.MakeRGB(RGBData.RGB);
|
|
return;
|
|
}
|
|
// Tex is mis aligned, so align and fill borders with pure pink
|
|
|
|
u8 *Buffer=(u8*)MemAlloc(FrameW*FrameH*3);
|
|
u8 *Src,*Dst;
|
|
int X,Y;
|
|
ThisFrame.MakeRGB(Buffer);
|
|
|
|
Dst=RGBData.RGB;
|
|
|
|
Src=Buffer;
|
|
Dst=RGBData.RGB;
|
|
for (Y=0; Y<FrameH; Y++)
|
|
{
|
|
for (X=0; X<FrameW; X++)
|
|
{
|
|
*Dst++=*Src++;
|
|
*Dst++=*Src++;
|
|
*Dst++=*Src++;
|
|
}
|
|
for (X; X<AlignW; X++)
|
|
{
|
|
*Dst++=BlankRGB.rgbRed;
|
|
*Dst++=BlankRGB.rgbGreen;
|
|
*Dst++=BlankRGB.rgbBlue;
|
|
}
|
|
}
|
|
for (Y; Y<AlignH; Y++)
|
|
{
|
|
for (X=0; X<AlignW; X++)
|
|
{
|
|
*Dst++=BlankRGB.rgbRed;
|
|
*Dst++=BlankRGB.rgbGreen;
|
|
*Dst++=BlankRGB.rgbBlue;
|
|
}
|
|
}
|
|
|
|
MemFree(Buffer);
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
bool CTexCache::LoadBMP(const char *Filename,sRGBData &RGBData)
|
|
{
|
|
Frame ThisFrame;
|
|
FILE *File;
|
|
// Check File exists
|
|
File=fopen(Filename,"r");
|
|
|
|
if (!File)
|
|
{
|
|
CString mexstr;
|
|
mexstr.Format("%s Not Found\n", Filename);
|
|
AfxMessageBox(mexstr,MB_OK | MB_ICONEXCLAMATION);
|
|
exit(EXIT_FAILURE );
|
|
return(false);
|
|
}
|
|
|
|
fclose(File);
|
|
ThisFrame.LoadBMP(Filename);
|
|
|
|
CreateAlignTex(ThisFrame,RGBData);
|
|
return(true);
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
void CTexCache::FreeBMP(sRGBData &RGBData)
|
|
{
|
|
if (RGBData.RGB)
|
|
{
|
|
MemFree(RGBData.RGB);
|
|
RGBData.RGB=0;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
void CTexCache::LoadTex(sTex &ThisTex,sRGBData *RGBData)
|
|
{
|
|
u8 *Buffer;
|
|
u8 *Src,*Dst;
|
|
|
|
// create RGB & alpha texture & ensuse texture is correct size for GL
|
|
Buffer=(u8*)MemAlloc(RGBData->TexW*RGBData->TexH*4);
|
|
ASSERT(Buffer);
|
|
|
|
Src=RGBData->RGB;
|
|
Dst=Buffer;
|
|
|
|
for (int Y=0; Y<RGBData->TexH; Y++)
|
|
{
|
|
for (int X=0; X<RGBData->TexW; X++)
|
|
{
|
|
u8 R,G,B,A;
|
|
|
|
R=*Src++;
|
|
G=*Src++;
|
|
B=*Src++;
|
|
A=255;
|
|
if ((R==BlankRGB.rgbRed && G==BlankRGB.rgbGreen && B==BlankRGB.rgbBlue)) // Create alpha for transparent pixels (flagged with PINK!!)
|
|
{
|
|
A=0;
|
|
}
|
|
*Dst++=R;
|
|
*Dst++=G;
|
|
*Dst++=B;
|
|
*Dst++=A;
|
|
}
|
|
}
|
|
|
|
ThisTex.OldW=RGBData->OldW;
|
|
ThisTex.OldH=RGBData->OldH;
|
|
ThisTex.TexW=RGBData->TexW;
|
|
ThisTex.TexH=RGBData->TexH;
|
|
ThisTex.ScaleU=RGBData->ScaleU;
|
|
ThisTex.ScaleV=RGBData->ScaleV;
|
|
|
|
glGenTextures(1, &ThisTex.TexID);
|
|
glBindTexture(GL_TEXTURE_2D, ThisTex.TexID);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, RGBData->TexW, RGBData->TexH, 0, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
MemFree(Buffer);
|
|
}
|
|
|
|
/**************************************************************************************/
|
|
/**************************************************************************************/
|
|
/**************************************************************************************/
|
|
void CTexCache::Purge()
|
|
{
|
|
int ListSize=TexList.size();
|
|
|
|
// TRACE1("Purging %i textures\n",ListSize);
|
|
|
|
for (int i=0; i<ListSize; i++)
|
|
{
|
|
glDeleteTextures(1,&TexList[i].TexID);
|
|
}
|
|
|
|
TexList.clear();
|
|
}
|
|
|
|
/**************************************************************************************/
|