GUI
This commit is contained in:
193
SQCSim2021/textureatlas.cpp
Normal file
193
SQCSim2021/textureatlas.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
#include "textureatlas.h"
|
||||
#include <cmath>
|
||||
|
||||
// TODO
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include "tool.h"
|
||||
|
||||
|
||||
TextureAtlas::TextureAtlas(unsigned int nbTexture) : m_isValid(false), m_currentTextureIndex(0)
|
||||
{
|
||||
if(nbTexture < 4)
|
||||
nbTexture = 4;
|
||||
|
||||
// Arrondir sur la puissance de 2 superieure
|
||||
m_nbTexturePerSide = (int)sqrt((float)nbTexture);
|
||||
if(m_nbTexturePerSide * m_nbTexturePerSide < nbTexture)
|
||||
m_nbTexturePerSide++;
|
||||
while(!IsPowerOfTwo(m_nbTexturePerSide))
|
||||
m_nbTexturePerSide++;
|
||||
}
|
||||
|
||||
TextureAtlas::~TextureAtlas()
|
||||
{
|
||||
if(IsValid())
|
||||
glDeleteTextures(1, &m_textureId);
|
||||
}
|
||||
|
||||
|
||||
TextureAtlas::TextureIndex TextureAtlas::AddTexture(const std::string& fname) {
|
||||
TextureList::iterator it = m_textureList.find(fname);
|
||||
|
||||
if(it != m_textureList.end())
|
||||
return it->second.texIdx;
|
||||
|
||||
TextureIndex id = m_currentTextureIndex++;
|
||||
m_textureList.insert(std::make_pair(fname, TextureInfo((ILuint)-1, id)));
|
||||
return id;
|
||||
}
|
||||
|
||||
bool TextureAtlas::Generate(int textureSize, bool mipmap) {
|
||||
// TODO mipmap pas encore 100% parfait...
|
||||
assert(!mipmap);
|
||||
|
||||
if(!IsPowerOfTwo(textureSize))
|
||||
return false;
|
||||
|
||||
// Initialize Devil only once:
|
||||
static bool alreadyInitialized = false;
|
||||
if(!alreadyInitialized)
|
||||
{
|
||||
ilInit();
|
||||
iluInit();
|
||||
alreadyInitialized = true;
|
||||
}
|
||||
|
||||
for(TextureList::iterator it = m_textureList.begin(); it != m_textureList.end(); ++it)
|
||||
{
|
||||
ILuint texid = it->second.texId;
|
||||
if(texid == (ILuint)-1)
|
||||
{
|
||||
std::cout << "Loading " << it->first << " (id=" << it->second.texIdx << ")..." << std::endl;
|
||||
ilGenImages(1, &texid);
|
||||
ilBindImage(texid);
|
||||
|
||||
ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
|
||||
ilEnable(IL_ORIGIN_SET);
|
||||
|
||||
if (!ilLoadImage((const ILstring)it->first.c_str()))
|
||||
return false;
|
||||
|
||||
if (!ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE))
|
||||
return false;
|
||||
|
||||
iluScale(textureSize, textureSize, 1);
|
||||
|
||||
it->second.texId = texid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//std::cout << ilGetInteger(IL_IMAGE_BPP) << std::endl;
|
||||
//std::cout << ilGetInteger(IL_IMAGE_FORMAT) << std::endl;
|
||||
//std::cout << ilGetInteger(IL_IMAGE_DEPTH) << std::endl;
|
||||
//std::cout << ilGetInteger(IL_IMAGE_TYPE) << std::endl;
|
||||
//std::cout << ilGetInteger(IL_IMAGE_WIDTH) << std::endl;
|
||||
//std::cout << ilGetInteger(IL_IMAGE_HEIGHT) << std::endl;
|
||||
|
||||
|
||||
|
||||
glGenTextures(1, &m_textureId);
|
||||
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||
if(mipmap)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR );
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
int level = textureSize;
|
||||
int oglLevel = 0;
|
||||
int mipmapSize = textureSize * m_nbTexturePerSide;
|
||||
while(mipmapSize != 0)
|
||||
{
|
||||
ILuint atlasTex;
|
||||
ilGenImages(1, &atlasTex);
|
||||
ilBindImage(atlasTex);
|
||||
ilTexImage(mipmapSize, mipmapSize, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, 0);
|
||||
ilClearColour(1, 0, 0, 1);
|
||||
ilClearImage();
|
||||
|
||||
for(TextureList::iterator it = m_textureList.begin(); it != m_textureList.end(); ++it)
|
||||
{
|
||||
ILuint tmpImg;
|
||||
ilGenImages(1, &tmpImg);
|
||||
ilBindImage(tmpImg);
|
||||
ilCopyImage(it->second.texId);
|
||||
|
||||
iluImageParameter(ILU_FILTER, ILU_NEAREST);
|
||||
//iluImageParameter(ILU_FILTER, ILU_BILINEAR);
|
||||
if(level != textureSize)
|
||||
iluScale(level, level, 1);
|
||||
|
||||
char* data = new char[level * level * 4];
|
||||
ilCopyPixels(0, 0, 0, level, level, 1, IL_RGBA, IL_UNSIGNED_BYTE, data);
|
||||
|
||||
|
||||
int imgIdx = it->second.texIdx;
|
||||
int x = imgIdx % m_nbTexturePerSide;
|
||||
int y = m_nbTexturePerSide - 1 - imgIdx / m_nbTexturePerSide;
|
||||
ilBindImage(atlasTex);
|
||||
ilSetPixels(x * level, y * level, 0, level, level, 1, IL_RGBA, IL_UNSIGNED_BYTE, data);
|
||||
//ilOverlayImage(tmpImg, x * level, y * level, 0);
|
||||
|
||||
delete [] data;
|
||||
ilDeleteImages(1, &tmpImg);
|
||||
}
|
||||
|
||||
// TODO
|
||||
//if(level == textureSize)
|
||||
//{
|
||||
//ilEnable(IL_FILE_OVERWRITE);
|
||||
//ilSaveImage("textureatlas.png");
|
||||
//}
|
||||
|
||||
//std::cout << oglLevel << ":" << level << ":" << mipmapSize << std::endl;
|
||||
glTexImage2D(GL_TEXTURE_2D, oglLevel++, GL_RGBA, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGBA, GL_UNSIGNED_BYTE, ilGetData());
|
||||
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
|
||||
ilDeleteImages(1, &atlasTex);
|
||||
|
||||
if(!mipmap)
|
||||
break;
|
||||
|
||||
level /= 2;
|
||||
mipmapSize /= 2;
|
||||
}
|
||||
|
||||
m_isValid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TextureAtlas::IsValid() const { return m_isValid; }
|
||||
|
||||
void TextureAtlas::Bind() const
|
||||
{
|
||||
assert(IsValid());
|
||||
glBindTexture(GL_TEXTURE_2D, m_textureId);
|
||||
}
|
||||
|
||||
void TextureAtlas::TextureIndexToCoord(TextureIndex idx, float& u, float& v, float& w, float& h) const
|
||||
{
|
||||
w = 1.f / (float)m_nbTexturePerSide;
|
||||
h = 1.f / (float)m_nbTexturePerSide;
|
||||
|
||||
u = (float)((unsigned int)idx % m_nbTexturePerSide) * w;
|
||||
v = (float)(m_nbTexturePerSide - 1 - (unsigned int)idx / m_nbTexturePerSide) * h;
|
||||
}
|
Reference in New Issue
Block a user