/* QGL TextureManager Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "gltexture_manager.h" #include "gltypes.h" QStringList TextureManager::search_pathes("."); QVector3D colorVector(QRgb c) { return QVector3D(((uchar *)(&c))[0] / 255.f, ((uchar *)(&c))[1] / 255.f, ((uchar *)(&c))[2] / 255.f); } QString TextureManager::findFile(const QString & path) { return ::findFile(path, search_pathes); } GLuint TextureManager::loadTexture(const QString & path, bool ownership, bool bump) { QString p = findFile(path); if (p.isEmpty()) return 0; int tid = textureID(p, bump); if (tid > 0) { // qDebug() << "[TextureManager] Found" << path << "as" << tid; return tid; } QImage image(p); if (bump) convertToNormal(image); // qDebug() << p << image.width() << image.height() << image.format() << bump; GLuint tid_ = tid; createGLTexture(f, tid_, image); tid = tid_; if (tid == 0) { qDebug() << "[TextureManager] Can`t load" << p; return tid; } qDebug() << "[TextureManager] Loaded" << p << "as" << tid; if (ownership) { tex_ids[bump ? 1 : 0].insert(p, tid); tex_im[bump ? 1 : 0].insert(p, image); } return tid; } GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool bump) { if (im.isNull()) return 0; QImage image(im); if (bump) convertToNormal(image); GLuint tid = 0; createGLTexture(f, tid, im); if (tid == 0) { qDebug() << "[TextureManager] Can`t load image"; return tid; } // qDebug() << "[TextureManager] Loaded image as" << tid; return tid; } QImage TextureManager::loadTextureImage(const QString & path, bool bump) { QString p = findFile(path); if (p.isEmpty()) return QImage(); QImage ret = tex_im[bump ? 1 : 0].value(p); if (!ret.isNull()) return ret; ret = QImage(p); if (bump) convertToNormal(ret); tex_im[bump ? 1 : 0].insert(p, ret); return ret; } void TextureManager::reloadTexture(GLuint tid, const QString & path) { QString p = findFile(path); if (p.isEmpty() || (tid == 0)) return; QImage image(p); createGLTexture(f, tid, image); if (tid == 0) { qDebug() << "[TextureManager] Can`t load" << p; return; } qDebug() << "[TextureManager] Reloaded" << p << "as" << tid; } void TextureManager::reloadTexture(GLuint tid, const QImage & im) { if (im.isNull() || (tid == 0)) return; QImage image(im); createGLTexture(f, tid, image); qDebug() << "[TextureManager] Reloaded" << tid; } void TextureManager::convertToNormal(QImage & im) { if (im.isNull()) return; QImage sim = im.convertToFormat(QImage::Format_ARGB32); float sum[3] = {0., 0., 0.}; llong a = 0; const uchar * sd = sim.constBits(); for (int i = 0; i < sim.height(); i++) { for (int j = 0; j < sim.width(); j++) { sum[2] += sd[a] / 255.f - 0.5f; ++a; sum[1] += sd[a] / 255.f - 0.5f; ++a; sum[0] += sd[a] / 255.f - 0.5f; ++a; ++a; } } float wh = sim.width() * sim.height(); sum[0] /= wh; sum[1] /= wh; sum[2] /= wh; // qDebug() << sum[0] << sum[1] << sum[2]; if ((qAbs(sum[0]) <= 0.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// already normal return; // qDebug() << "convert to normal"; QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32); int tx, ty, w = sim.width(), h = sim.height(); a = 0; uchar * dd = dim.bits(); for (int i = 0; i < sim.height(); i++) { for (int j = 0; j < sim.width(); j++) { tx = j - 1; tx = tx < 0 ? w + tx : tx % w; ty = i - 1; ty = ty < 0 ? h + ty : ty % h; QVector3D p[3], res; p[0] = colorVector(sim.pixel(j, i)); p[1] = colorVector(sim.pixel(j, ty)); p[2] = colorVector(sim.pixel(tx, i)); res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); tx = (j + 1) % w; ty = (i + 1) % h; p[1] = colorVector(sim.pixel(j, ty)); p[2] = colorVector(sim.pixel(tx, i)); res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); res.setZ(1.f); dd[a] = res.z() * 255; ++a; dd[a] = res.y() * 255; ++a; dd[a] = res.x() * 255; ++a; dd[a] = 255; ++a; } } im = dim; // im.save("_normal.png"); } bool TextureManager::loadTextures() { QFileInfoList fil; foreach(const QString & i, tex_pathes) loadTexture(i, true); tex_pathes.clear(); return true; } void TextureManager::deleteTextures() { for (int i = 0; i < 2; ++i) { QList texs = tex_ids[i].values(); qDebug() << "[TextureManager] Delete" << texs.size() << "textures"; if (!texs.isEmpty()) f->glDeleteTextures(texs.size(), &texs[0]); tex_ids[i].clear(); tex_im[i].clear(); } } void TextureManager::deleteTexture(const QString & name) { for (int i = 0; i < 2; ++i) { if (tex_ids[i].contains(name)) { GLuint id = tex_ids[i][name]; f->glDeleteTextures(1, &id); tex_ids[i].remove(name); tex_im[i].remove(name); } } } void TextureManager::clearImageCache() { tex_im[0].clear(); tex_im[1].clear(); }