1
0
forked from 0ad/0ad
0ad/source/graphics/TextureEntry.cpp
Ykkrosh 2f53eea71a Actor Viewer: Added controls for wireframe, background colour, move-when-walking. Reduced CPU usage when 'playing' things with no animation.
Color: Moved SColor* structs into SColor.h, so they can be used without
indirectly including CVector[34]D.
Terrain: Added 'base colour', for the Actor Viewer to be able to
modulate the colour of normally-white terrain.
Removed some "using namespace std" (because it doesn't make the code
easier to read, and it defeats the point of namespaces, and the rest of
the code doesn't do it).

This was SVN commit r4392.
2006-09-26 01:44:20 +00:00

126 lines
3.7 KiB
C++

#include "precompiled.h"
#include <map>
#include "lib/ogl.h"
#include "lib/res/graphics/ogl_tex.h"
#include "ps/CLogger.h"
#include "TextureEntry.h"
#include "TextureManager.h"
#include "TerrainProperties.h"
#include "Texture.h"
#include "renderer/Renderer.h"
#define LOG_CATEGORY "graphics"
std::map<Handle, CTextureEntry *> CTextureEntry::m_LoadedTextures;
/////////////////////////////////////////////////////////////////////////////////////
// CTextureEntry constructor
CTextureEntry::CTextureEntry(CTerrainPropertiesPtr props, const CStr& path):
m_pProperties(props),
m_Bitmap(NULL),
m_Handle(-1),
m_BaseColor(0),
m_BaseColorValid(false),
m_TexturePath(path)
{
if (m_pProperties)
m_Groups = m_pProperties->GetGroups();
GroupVector::iterator it=m_Groups.begin();
for (;it!=m_Groups.end();++it)
(*it)->AddTerrain(this);
long slashPos=m_TexturePath.ReverseFind("/");
long dotPos=m_TexturePath.ReverseFind(".");
if (slashPos == -1)
slashPos = 0;
else
slashPos++; // Skip the actual slash
if (dotPos == -1)
dotPos = (long)m_TexturePath.Length();
m_Tag = m_TexturePath.GetSubstring(slashPos, dotPos-slashPos);
}
/////////////////////////////////////////////////////////////////////////////////////
// CTextureEntry destructor
CTextureEntry::~CTextureEntry()
{
std::map<Handle,CTextureEntry *>::iterator it=m_LoadedTextures.find(m_Handle);
if (it != m_LoadedTextures.end())
m_LoadedTextures.erase(it);
if (m_Handle > 0)
ogl_tex_free(m_Handle);
for (GroupVector::iterator it=m_Groups.begin();it!=m_Groups.end();++it)
(*it)->RemoveTerrain(this);
}
/////////////////////////////////////////////////////////////////////////////////////
// LoadTexture: actually load the texture resource from file
void CTextureEntry::LoadTexture()
{
CTexture texture;
texture.SetName(m_TexturePath);
if (g_Renderer.LoadTexture(&texture,GL_REPEAT)) {
m_Handle=texture.GetHandle();
m_LoadedTextures[m_Handle] = this;
} else {
m_Handle=0;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BuildBaseColor: calculate the root colour of the texture, used for coloring minimap, and store
// in m_BaseColor member
void CTextureEntry::BuildBaseColor()
{
if (m_pProperties && m_pProperties->HasBaseColor())
{
m_BaseColor=m_pProperties->GetBaseColor();
m_BaseColorValid=true;
return;
}
ogl_tex_bind(GetHandle());
// get root colour for coloring minimap by querying root level of the texture
// (this should decompress any compressed textures for us),
// then scaling it down to a 1x1 size
// - an alternative approach of just grabbing the top level of the mipmap tree fails
// (or gives an incorrect colour) in some cases:
// - suspect bug on Radeon cards when SGIS_generate_mipmap is used
// - any textures without mipmaps
// we'll just take the basic approach here.
//
// jw: this is horribly inefficient (taking 750ms for 10 texture types),
// but it is no longer called, since terrain XML files are supposed to
// include a minimap color attribute. therefore, leave it as-is.
GLint width,height;
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
unsigned char* buf=new unsigned char[width*height*4];
glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf);
gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf,
1,1,GL_UNSIGNED_BYTE,&m_BaseColor);
delete[] buf;
m_BaseColorValid=true;
}
CTextureEntry *CTextureEntry::GetByHandle(Handle handle)
{
std::map<Handle, CTextureEntry *>::iterator it=m_LoadedTextures.find(handle);
if (it != m_LoadedTextures.end())
return it->second;
else
return NULL;
}