#include <iostream>
#include <sstream>
#include <GL/glew.h>
#include "Texture.hpp"
Texture::KeyIndexedTextures Texture::__texture_registry;
Texture::BoundMap Texture::__current_texture;
Texture::ModeMap Texture::__mode_to_glmode;
const unsigned Texture::REPEAT(1);
const unsigned Texture::NO_MIPMAP(2);
Texture::Texture():
__width(0)
,__height(0)
,__mode("NONE")
,__flags(0)
,__dimension(GL_TEXTURE_2D)
,__texture_id(0)
{
return;
}
Texture::Texture(const Texture& other):
__width(other.__width)
,__height(other.__height)
,__mode(other.__mode)
,__flags(other.__flags)
,__dimension(other.__dimension)
,__texture_id(other.__texture_id)
{
return;
}
Texture::Texture(const GLvoid* data
,unsigned width
,unsigned height
,const std::string mode
,const unsigned flags):
__width(width)
,__height(height)
,__mode(mode)
,__flags(flags)
,__dimension(GL_TEXTURE_2D)
//__dimension = if_then_else(len(size) == 2, GL_TEXTURE_2D, GL_TEXTURE_3D)
,__texture_id(0)
{
glGenTextures(1, &__texture_id);
__set_texture_data(data);
}
Texture::~Texture()
{
//glDeleteTextures(1, &__texture_id);
//if __texture_id in Texture::__texture_registry.values():
//for n, id in Texture::__texture_registry.iteritems():
//if id == __texture_id:
//del Texture::__texture_registry[n]
}
/* static */
void Texture::init()
{
Texture::__current_texture[GL_TEXTURE0] = 0;
Texture::__current_texture[GL_TEXTURE1] = 0;
Texture::__current_texture[GL_TEXTURE2] = 0;
Texture::__current_texture[GL_TEXTURE3] = 0;
Texture::__current_texture[GL_TEXTURE4] = 0;
Texture::__current_texture[GL_TEXTURE5] = 0;
Texture::__current_texture[GL_TEXTURE6] = 0;
Texture::__current_texture[GL_TEXTURE7] = 0;
Texture::__mode_to_glmode["RGB"] = GL_RGB;
Texture::__mode_to_glmode["RGBA"] = GL_RGBA;
Texture::__mode_to_glmode["L"] = GL_LUMINANCE;
Texture::__mode_to_glmode["LA"] = GL_LUMINANCE_ALPHA;
}
void Texture::__set_texture_data(const GLvoid* data)
{
bind();
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//if(__dimension == GL_TEXTURE_2D) {
glTexImage2D(GL_TEXTURE_2D
,0
,__mode.length()
,__width
,__height
,0
,__mode_to_glmode[__mode]
,GL_UNSIGNED_BYTE
,data);
//} else if(__dimension == GL_TEXTURE_3D) {
//std::cout << "Building 3D texture..." << __size << std::endl;
//for i, d, size in data:
//glTexImage3D(GL_TEXTURE_3D, i, len(__mode), \
size[0], size[1], size[2], 0, \
__mode_to_glmode[__mode], GL_UNSIGNED_BYTE, d)
//} else {
//std::cerr << "ERROR: Invalid texture dimension!" << __dimension << std::endl;
//}
glTexParameterf(__dimension, GL_TEXTURE_WRAP_S, __flags & Texture::REPEAT ? GL_REPEAT : GL_CLAMP);
glTexParameterf(__dimension, GL_TEXTURE_WRAP_T, __flags & Texture::REPEAT ? GL_REPEAT : GL_CLAMP);
//if 'no mipmap' not in __flags and __dimension == GL_TEXTURE_2D:
glTexParameterf(__dimension, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
//gluBuild2DMipmaps(GL_TEXTURE_2D, __mode_to_glmode[__mode],
//__width, __height, __mode_to_glmode[__mode],
//GL_UNSIGNED_BYTE, data );
//else:
//glTexParameterf(__dimension, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
done();
}
void Texture::reset_image(Magick::Image& image)
{
Magick::Blob blob;
image.write(&blob, "RGBA");
__set_texture_data(blob.data());
}
void Texture::bind(unsigned number)
{
if(Texture::__current_texture[number] == __texture_id) {
return; //# The texture is already bound
}
glActiveTexture(number);
glEnable( __dimension );
glBindTexture(__dimension, __texture_id);
Texture::__current_texture[number] = __texture_id;
}
void Texture::done(unsigned number)
{
//std::cout << "Done texture " << number << " " << __dimension << " " << __texture_id << "\n";
glActiveTexture(number);
glDisable(__dimension );
Texture::__current_texture[number] = 0;
}
/* static */
void Texture::reset()
{
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D );
}
/* static */
void Texture::disable()
{
glActiveTexture(GL_TEXTURE0);
glDisable( GL_TEXTURE_2D );
glDisable( GL_TEXTURE_3D );
}
/* static */
std::string Texture::__make_key(std::string pref, unsigned flags)
{
std::stringstream ss;
ss << pref << flags;
return ss.str();
}
/* static */
Texture::Ptr Texture::from_file(std::string file,
unsigned flags,
boost::filesystem::path prefix)
{
std::string key = Texture::__make_key(file, flags);
if(Texture::__texture_registry.find(key) != Texture::__texture_registry.end()) {
return Texture::__texture_registry[key];
}
Magick::Image image((prefix /= file).string().c_str());
return Texture::from_image(image, file, flags);
}
/* static */
Texture::Ptr Texture::from_image(Magick::Image& image,
std::string prekey,
unsigned flags)
{
std::string key(Texture::__make_key(prekey, flags));
if(Texture::__texture_registry.find(key) != Texture::__texture_registry.end()) {
return Texture::__texture_registry[key];
}
Magick::Blob blob;
image.write(&blob, "RGBA");
Texture::__texture_registry[key] = Texture::Ptr(new Texture(blob.data(), image.columns(), image.rows(), "RGBA", flags));
return Texture::__texture_registry[key];
}