Avoid unnecessary mesh regeneration while only texture map changed
parent
73d20da08f
commit
5f2a46be9c
|
@ -245,6 +245,9 @@ HEADERS += src/materialpreviewsgenerator.h
|
|||
SOURCES += src/materialwidget.cpp
|
||||
HEADERS += src/materialwidget.h
|
||||
|
||||
SOURCES += src/material.cpp
|
||||
HEADERS += src/material.h
|
||||
|
||||
SOURCES += src/main.cpp
|
||||
|
||||
HEADERS += src/version.h
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#include "material.h"
|
||||
#include "imageforever.h"
|
||||
#include "dust3dutil.h"
|
||||
|
||||
void initializeMaterialTexturesFromSnapshot(const SkeletonSnapshot &snapshot, const QUuid &materialId, MaterialTextures &materialTextures)
|
||||
{
|
||||
QString materialIdString = materialId.toString();
|
||||
for (const auto &materialItem: snapshot.materials) {
|
||||
if (materialIdString != valueOfKeyInMapOrEmpty(materialItem.first, "id"))
|
||||
continue;
|
||||
for (const auto &layer: materialItem.second) {
|
||||
//FIXME: Only support one layer currently
|
||||
for (const auto &mapItem: layer.second) {
|
||||
auto textureType = TextureTypeFromString(valueOfKeyInMapOrEmpty(mapItem, "for").toUtf8().constData());
|
||||
if (textureType != TextureType::None) {
|
||||
int index = (int)textureType - 1;
|
||||
if (index >= 0 && index < (int)TextureType::Count - 1) {
|
||||
if ("imageId" == valueOfKeyInMapOrEmpty(mapItem, "linkDataType")) {
|
||||
auto imageIdString = valueOfKeyInMapOrEmpty(mapItem, "linkData");
|
||||
materialTextures.textureImages[index] = ImageForever::get(QUuid(imageIdString));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef MATERIAL_H
|
||||
#define MATERIAL_H
|
||||
#include <QImage>
|
||||
#include <QUuid>
|
||||
#include "texturetype.h"
|
||||
#include "skeletonsnapshot.h"
|
||||
|
||||
struct Material
|
||||
{
|
||||
QColor color;
|
||||
QUuid materialId;
|
||||
};
|
||||
|
||||
struct MaterialTextures
|
||||
{
|
||||
const QImage *textureImages[(int)TextureType::Count - 1] = {nullptr};
|
||||
};
|
||||
|
||||
void initializeMaterialTexturesFromSnapshot(const SkeletonSnapshot &snapshot, const QUuid &materialId, MaterialTextures &materialTextures);
|
||||
|
||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||
#include "meshquadify.h"
|
||||
#include "meshweldseam.h"
|
||||
#include "imageforever.h"
|
||||
#include "material.h"
|
||||
|
||||
bool MeshGenerator::m_enableDebug = false;
|
||||
PositionMap<int> *MeshGenerator::m_forMakePositionKey = new PositionMap<int>;
|
||||
|
@ -257,27 +258,8 @@ void *MeshGenerator::combinePartMesh(QString partId)
|
|||
materialId = QUuid(materialIdString);
|
||||
|
||||
Material partMaterial;
|
||||
for (const auto &material: m_snapshot->materials) {
|
||||
if (materialIdString != valueOfKeyInMapOrEmpty(material.first, "id"))
|
||||
continue;
|
||||
for (const auto &layer: material.second) {
|
||||
//FIXME: Only support one layer currently
|
||||
for (const auto &mapItem: layer.second) {
|
||||
auto textureType = TextureTypeFromString(valueOfKeyInMapOrEmpty(mapItem, "for").toUtf8().constData());
|
||||
if (textureType != TextureType::None) {
|
||||
int index = (int)textureType - 1;
|
||||
if (index >= 0 && index < (int)TextureType::Count - 1) {
|
||||
if ("imageId" == valueOfKeyInMapOrEmpty(mapItem, "linkDataType")) {
|
||||
auto imageIdString = valueOfKeyInMapOrEmpty(mapItem, "linkData");
|
||||
partMaterial.textureImages[index] = ImageForever::get(QUuid(imageIdString));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
partMaterial.color = partColor;
|
||||
partMaterial.materialId = materialId;
|
||||
|
||||
QString mirroredPartId;
|
||||
QUuid mirroredPartIdNotAsString;
|
||||
|
|
|
@ -8,15 +8,10 @@
|
|||
#include "positionmap.h"
|
||||
#include "skeletonbonemark.h"
|
||||
#include "texturetype.h"
|
||||
#include "material.h"
|
||||
|
||||
#define MAX_WEIGHT_NUM 4
|
||||
|
||||
struct Material
|
||||
{
|
||||
QColor color;
|
||||
const QImage *textureImages[(int)TextureType::Count - 1] = {nullptr};
|
||||
};
|
||||
|
||||
struct BmeshNode
|
||||
{
|
||||
QUuid partId;
|
||||
|
|
|
@ -1524,26 +1524,11 @@ void SkeletonDocument::generateTexture()
|
|||
|
||||
m_isTextureObsolete = false;
|
||||
|
||||
SkeletonSnapshot *snapshot = new SkeletonSnapshot;
|
||||
toSnapshot(snapshot);
|
||||
|
||||
QThread *thread = new QThread;
|
||||
m_textureGenerator = new TextureGenerator(*m_postProcessedResultContext);
|
||||
for (const auto &bmeshNode: m_postProcessedResultContext->bmeshNodes) {
|
||||
for (size_t i = 0; i < sizeof(bmeshNode.material.textureImages) / sizeof(bmeshNode.material.textureImages[0]); ++i) {
|
||||
TextureType forWhat = (TextureType)(i + 1);
|
||||
const QImage *image = bmeshNode.material.textureImages[i];
|
||||
if (nullptr != image) {
|
||||
if (TextureType::BaseColor == forWhat)
|
||||
m_textureGenerator->addPartColorMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Normal == forWhat)
|
||||
m_textureGenerator->addPartNormalMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Metalness == forWhat)
|
||||
m_textureGenerator->addPartMetalnessMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Roughness == forWhat)
|
||||
m_textureGenerator->addPartRoughnessMap(bmeshNode.partId, image);
|
||||
else if (TextureType::AmbientOcclusion == forWhat)
|
||||
m_textureGenerator->addPartAmbientOcclusionMap(bmeshNode.partId, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_textureGenerator = new TextureGenerator(*m_postProcessedResultContext, snapshot);
|
||||
m_textureGenerator->moveToThread(thread);
|
||||
connect(thread, &QThread::started, m_textureGenerator, &TextureGenerator::process);
|
||||
connect(m_textureGenerator, &TextureGenerator::finished, this, &SkeletonDocument::textureReady);
|
||||
|
@ -2270,7 +2255,7 @@ void SkeletonDocument::setPartMaterialId(QUuid partId, QUuid materialId)
|
|||
part->second.materialId = materialId;
|
||||
part->second.dirty = true;
|
||||
emit partMaterialIdChanged(partId);
|
||||
emit skeletonChanged();
|
||||
emit textureChanged();
|
||||
}
|
||||
|
||||
void SkeletonDocument::setPartRoundState(QUuid partId, bool rounded)
|
||||
|
@ -2887,6 +2872,7 @@ void SkeletonDocument::setMaterialLayers(QUuid materialId, std::vector<SkeletonM
|
|||
findMaterialResult->second.layers = layers;
|
||||
findMaterialResult->second.dirty = true;
|
||||
emit materialLayersChanged(materialId);
|
||||
emit textureChanged();
|
||||
emit optionsChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -537,6 +537,7 @@ signals:
|
|||
void meshGenerating();
|
||||
void postProcessing();
|
||||
void textureGenerating();
|
||||
void textureChanged();
|
||||
public: // need initialize
|
||||
float originX;
|
||||
float originY;
|
||||
|
|
|
@ -815,6 +815,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
|||
// m_document->postProcess();
|
||||
// }
|
||||
//});
|
||||
connect(m_document, &SkeletonDocument::textureChanged, m_document, &SkeletonDocument::generateTexture);
|
||||
connect(m_document, &SkeletonDocument::resultMeshChanged, m_document, &SkeletonDocument::postProcess);
|
||||
connect(m_document, &SkeletonDocument::resultMeshChanged, m_document, &SkeletonDocument::generateRig);
|
||||
connect(m_document, &SkeletonDocument::rigChanged, m_document, &SkeletonDocument::generateRig);
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QRegion>
|
||||
#include <QPolygon>
|
||||
#include <QElapsedTimer>
|
||||
#include "texturegenerator.h"
|
||||
#include "theme.h"
|
||||
#include "dust3dutil.h"
|
||||
|
||||
int TextureGenerator::m_textureSize = 1024;
|
||||
|
||||
TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext) :
|
||||
TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext, SkeletonSnapshot *snapshot) :
|
||||
m_resultTextureGuideImage(nullptr),
|
||||
m_resultTextureImage(nullptr),
|
||||
m_resultTextureBorderImage(nullptr),
|
||||
|
@ -17,7 +19,8 @@ TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext) :
|
|||
m_resultTextureRoughnessImage(nullptr),
|
||||
m_resultTextureMetalnessImage(nullptr),
|
||||
m_resultTextureAmbientOcclusionImage(nullptr),
|
||||
m_resultMesh(nullptr)
|
||||
m_resultMesh(nullptr),
|
||||
m_snapshot(snapshot)
|
||||
{
|
||||
m_resultContext = new MeshResultContext();
|
||||
*m_resultContext = meshResultContext;
|
||||
|
@ -36,6 +39,7 @@ TextureGenerator::~TextureGenerator()
|
|||
delete m_resultTextureMetalnessImage;
|
||||
delete m_resultTextureAmbientOcclusionImage;
|
||||
delete m_resultMesh;
|
||||
delete m_snapshot;
|
||||
}
|
||||
|
||||
QImage *TextureGenerator::takeResultTextureGuideImage()
|
||||
|
@ -130,8 +134,53 @@ QPainterPath TextureGenerator::expandedPainterPath(const QPainterPath &painterPa
|
|||
return (stroker.createStroke(painterPath) + painterPath).simplified();
|
||||
}
|
||||
|
||||
void TextureGenerator::prepare()
|
||||
{
|
||||
if (nullptr == m_snapshot)
|
||||
return;
|
||||
|
||||
std::map<QUuid, QUuid> updatedMaterialIdMap;
|
||||
for (const auto &partIt: m_snapshot->parts) {
|
||||
auto materialIdIt = partIt.second.find("materialId");
|
||||
if (materialIdIt == partIt.second.end())
|
||||
continue;
|
||||
QUuid partId = QUuid(partIt.first);
|
||||
QUuid materialId = QUuid(materialIdIt->second);
|
||||
updatedMaterialIdMap.insert({partId, materialId});
|
||||
}
|
||||
for (const auto &bmeshNode: m_resultContext->bmeshNodes) {
|
||||
for (size_t i = 0; i < (int)TextureType::Count - 1; ++i) {
|
||||
TextureType forWhat = (TextureType)(i + 1);
|
||||
MaterialTextures materialTextures;
|
||||
QUuid materialId = bmeshNode.material.materialId;
|
||||
auto findUpdatedMaterialIdResult = updatedMaterialIdMap.find(bmeshNode.partId);
|
||||
if (findUpdatedMaterialIdResult != updatedMaterialIdMap.end())
|
||||
materialId = findUpdatedMaterialIdResult->second;
|
||||
initializeMaterialTexturesFromSnapshot(*m_snapshot, materialId, materialTextures);
|
||||
const QImage *image = materialTextures.textureImages[i];
|
||||
if (nullptr != image) {
|
||||
if (TextureType::BaseColor == forWhat)
|
||||
addPartColorMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Normal == forWhat)
|
||||
addPartNormalMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Metalness == forWhat)
|
||||
addPartMetalnessMap(bmeshNode.partId, image);
|
||||
else if (TextureType::Roughness == forWhat)
|
||||
addPartRoughnessMap(bmeshNode.partId, image);
|
||||
else if (TextureType::AmbientOcclusion == forWhat)
|
||||
addPartAmbientOcclusionMap(bmeshNode.partId, image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureGenerator::generate()
|
||||
{
|
||||
QElapsedTimer countTimeConsumed;
|
||||
countTimeConsumed.start();
|
||||
|
||||
prepare();
|
||||
|
||||
bool hasNormalMap = false;
|
||||
bool hasMetalnessMap = false;
|
||||
bool hasRoughnessMap = false;
|
||||
|
@ -350,6 +399,8 @@ void TextureGenerator::generate()
|
|||
m_resultMesh->setHasRoughnessInImage(hasRoughnessMap);
|
||||
m_resultMesh->setHasAmbientOcclusionInImage(hasAmbientOcclusionMap);
|
||||
}
|
||||
|
||||
qDebug() << "The texture[" << TextureGenerator::m_textureSize << "x" << TextureGenerator::m_textureSize << "] generation took" << countTimeConsumed.elapsed() << "milliseconds";
|
||||
}
|
||||
|
||||
void TextureGenerator::process()
|
||||
|
|
|
@ -10,7 +10,7 @@ class TextureGenerator : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TextureGenerator(const MeshResultContext &meshResultContext);
|
||||
TextureGenerator(const MeshResultContext &meshResultContext, SkeletonSnapshot *snapshot=nullptr);
|
||||
~TextureGenerator();
|
||||
QImage *takeResultTextureGuideImage();
|
||||
QImage *takeResultTextureImage();
|
||||
|
@ -32,6 +32,7 @@ public slots:
|
|||
public:
|
||||
static int m_textureSize;
|
||||
private:
|
||||
void prepare();
|
||||
QPainterPath expandedPainterPath(const QPainterPath &painterPath);
|
||||
private:
|
||||
MeshResultContext *m_resultContext;
|
||||
|
@ -50,6 +51,7 @@ private:
|
|||
std::map<QUuid, QImage> m_partMetalnessTextureMap;
|
||||
std::map<QUuid, QImage> m_partRoughnessTextureMap;
|
||||
std::map<QUuid, QImage> m_partAmbientOcclusionTextureMap;
|
||||
SkeletonSnapshot *m_snapshot;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue