Add pixmap cache during texture generator

master
Jeremy Hu 2019-11-04 00:01:13 +09:30
parent 67881213f4
commit ac61cee164
2 changed files with 103 additions and 82 deletions

View File

@ -158,14 +158,6 @@ void TextureGenerator::addPartAmbientOcclusionMap(QUuid partId, const QImage *im
m_partAmbientOcclusionTextureMap[partId] = std::make_pair(*image, tileScale);
}
QPainterPath TextureGenerator::expandedPainterPath(const QPainterPath &painterPath, int expandSize)
{
QPainterPathStroker stroker;
stroker.setWidth(expandSize);
stroker.setJoinStyle(Qt::RoundJoin);
return (stroker.createStroke(painterPath) + painterPath).simplified();
}
void TextureGenerator::prepare()
{
if (nullptr == m_snapshot)
@ -320,6 +312,76 @@ void TextureGenerator::generate()
}
}
auto drawTexture = [&](const std::map<QUuid, std::pair<QPixmap, QPixmap>> &map, QPainter &painter, bool useAlpha) {
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
float alpha = 1.0;
if (useAlpha) {
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
alpha = color.alphaF();
}
}
auto findTextureResult = map.find(partId);
if (findTextureResult != map.end()) {
const auto &pixmap = findTextureResult->second.first;
const auto &rotatedPixmap = findTextureResult->second.second;
painter.setOpacity(alpha);
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize,
rect.top() * TextureGenerator::m_textureSize,
rect.width() * TextureGenerator::m_textureSize,
rect.height() * TextureGenerator::m_textureSize
};
if (translatedRect.width() < translatedRect.height()) {
painter.drawTiledPixmap(translatedRect, rotatedPixmap);
} else {
painter.drawTiledPixmap(translatedRect, pixmap);
}
}
painter.setOpacity(1.0);
}
}
};
auto convertTextureImageToPixmap = [&](const std::map<QUuid, std::pair<QImage, float>> &sourceMap,
std::map<QUuid, std::pair<QPixmap, QPixmap>> &targetMap) {
for (const auto &it: sourceMap) {
float tileScale = it.second.second;
const auto &image = it.second.first;
auto newSize = image.size() * tileScale;
QImage scaledImage = image.scaled(newSize);
QPoint center = scaledImage.rect().center();
QMatrix matrix;
matrix.translate(center.x(), center.y());
matrix.rotate(90);
auto rotatedImage = scaledImage.transformed(matrix);
targetMap[it.first] = std::make_pair(QPixmap::fromImage(scaledImage),
QPixmap::fromImage(rotatedImage));
}
};
std::map<QUuid, std::pair<QPixmap, QPixmap>> partColorTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partNormalTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partMetalnessTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partRoughnessTexturePixmaps;
std::map<QUuid, std::pair<QPixmap, QPixmap>> partAmbientOcclusionTexturePixmaps;
convertTextureImageToPixmap(m_partColorTextureMap, partColorTexturePixmaps);
convertTextureImageToPixmap(m_partNormalTextureMap, partNormalTexturePixmaps);
convertTextureImageToPixmap(m_partMetalnessTextureMap, partMetalnessTexturePixmaps);
convertTextureImageToPixmap(m_partRoughnessTextureMap, partRoughnessTexturePixmaps);
convertTextureImageToPixmap(m_partAmbientOcclusionTextureMap, partAmbientOcclusionTexturePixmaps);
drawTexture(partColorTexturePixmaps, texturePainter, true);
drawTexture(partNormalTexturePixmaps, textureNormalPainter, false);
drawTexture(partMetalnessTexturePixmaps, textureMetalnessPainter, false);
drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false);
drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false);
auto drawGradient = [&](const QUuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
const QUuid &neighborPartId) {
const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex];
@ -332,9 +394,11 @@ void TextureGenerator::generate()
const auto &secondPoint = uv[secondVertexIndex];
auto edgeLength = firstPoint.distanceToPoint(secondPoint);
auto middlePoint = (firstPoint + secondPoint) / 2.0;
float alpha = 1.0;
const auto &findColor = partColorMap.find(partId);
if (findColor == partColorMap.end())
return;
alpha = findColor->second.alphaF();
const auto &findNeighborColorSolubility = partColorSolubilityMap.find(neighborPartId);
if (findNeighborColorSolubility == partColorSolubilityMap.end())
return;
@ -359,11 +423,34 @@ void TextureGenerator::generate()
(finalRadius + finalRadius),
(finalRadius + finalRadius));
auto clippedRect = it.intersected(fillTarget);
texturePainter.fillRect(clippedRect.left() * TextureGenerator::m_textureSize,
QRectF translatedRect = {
clippedRect.left() * TextureGenerator::m_textureSize,
clippedRect.top() * TextureGenerator::m_textureSize,
clippedRect.width() * TextureGenerator::m_textureSize,
clippedRect.height() * TextureGenerator::m_textureSize,
gradient);
clippedRect.height() * TextureGenerator::m_textureSize
};
texturePainter.setOpacity(alpha);
auto findTextureResult = partColorTexturePixmaps.find(neighborPartId);
if (findTextureResult != partColorTexturePixmaps.end()) {
//const auto &pixmap = findTextureResult->second.first;
//const auto &rotatedPixmap = findTextureResult->second.second;
//if (it.width() < it.height()) {
//texturePainter.drawTiledPixmap(translatedRect, rotatedPixmap);
//} else {
//texturePainter.drawTiledPixmap(translatedRect, pixmap);
//}
//QImage mask(translatedRect.width(), translatedRect.height(), QImage::Format_ARGB32);
//QPainter maskPainter;
//maskPainter.begin(&mask);
//maskPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
//maskPainter.fillRect(translatedRect, gradient);
//maskPainter.end();
// FIXME: fix gradient fill by image
} else {
texturePainter.fillRect(translatedRect, gradient);
}
texturePainter.setOpacity(1.0);
break;
}
}
@ -395,77 +482,11 @@ void TextureGenerator::generate()
drawGradient(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
}
auto drawTexture = [&](const std::map<QUuid, std::pair<QImage, float>> &map, QPainter &painter, bool useAlpha) {
for (const auto &it: partUvRects) {
const auto &partId = it.first;
const auto &rects = it.second;
float alpha = 1.0;
if (useAlpha) {
auto findSourceColorResult = partColorMap.find(partId);
if (findSourceColorResult != partColorMap.end()) {
const auto &color = findSourceColorResult->second;
alpha = color.alphaF();
}
}
auto findTextureResult = map.find(partId);
if (findTextureResult != map.end()) {
float tileScale = findTextureResult->second.second;
const auto &image = findTextureResult->second.first;
auto newSize = image.size() * tileScale;
QImage scaledImage = image.scaled(newSize);
auto pixmap = QPixmap::fromImage(scaledImage);
QPixmap rotatedPixmap;
painter.setOpacity(alpha);
for (const auto &rect: rects) {
QRectF translatedRect = {
rect.left() * TextureGenerator::m_textureSize,
rect.top() * TextureGenerator::m_textureSize,
rect.width() * TextureGenerator::m_textureSize,
rect.height() * TextureGenerator::m_textureSize
};
if (translatedRect.width() < translatedRect.height()) {
if (rotatedPixmap.isNull()) {
QPoint center = scaledImage.rect().center();
QMatrix matrix;
matrix.translate(center.x(), center.y());
matrix.rotate(90);
auto rotatedImage = scaledImage.transformed(matrix);
rotatedPixmap = QPixmap::fromImage(rotatedImage);
}
painter.drawTiledPixmap(translatedRect, rotatedPixmap);
} else {
painter.drawTiledPixmap(translatedRect, pixmap);
}
}
}
}
};
hasNormalMap = !m_partNormalTextureMap.empty();
hasMetalnessMap = !m_partMetalnessTextureMap.empty();
hasRoughnessMap = !m_partRoughnessTextureMap.empty();
hasAmbientOcclusionMap = !m_partAmbientOcclusionTextureMap.empty();
drawTexture(m_partColorTextureMap, texturePainter, true);
drawTexture(m_partNormalTextureMap, textureNormalPainter, false);
drawTexture(m_partMetalnessTextureMap, textureMetalnessPainter, false);
drawTexture(m_partRoughnessTextureMap, textureRoughnessPainter, false);
drawTexture(m_partAmbientOcclusionTextureMap, textureAmbientOcclusionPainter, false);
for (auto i = 0u; i < triangleVertexUvs.size(); i++) {
const std::pair<QUuid, QUuid> &source = triangleSourceNodes[i];
auto findNormalTextureResult = m_partNormalTextureMap.find(source.first);
if (findNormalTextureResult != m_partNormalTextureMap.end()) {
hasNormalMap = true;
}
auto findMetalnessTextureResult = m_partMetalnessTextureMap.find(source.first);
if (findMetalnessTextureResult != m_partMetalnessTextureMap.end()) {
hasMetalnessMap = true;
}
auto findRoughnessTextureResult = m_partRoughnessTextureMap.find(source.first);
if (findRoughnessTextureResult != m_partRoughnessTextureMap.end()) {
hasRoughnessMap = true;
}
auto findAmbientOcclusionTextureResult = m_partAmbientOcclusionTextureMap.find(source.first);
if (findAmbientOcclusionTextureResult != m_partAmbientOcclusionTextureMap.end()) {
hasAmbientOcclusionMap = true;
}
}
auto paintTextureEndTime = countTimeConsumed.elapsed();
pen.setWidth(0);

View File

@ -4,6 +4,7 @@
#include <vector>
#include <QImage>
#include <QColor>
#include <QPixmap>
#include "outcome.h"
#include "meshloader.h"
#include "snapshot.h"
@ -40,7 +41,6 @@ public:
static QColor m_defaultTextureColor;
private:
void prepare();
QPainterPath expandedPainterPath(const QPainterPath &painterPath, int expandSize=7);
private:
Outcome *m_outcome;
QImage *m_resultTextureGuideImage;