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
|
SOURCES += src/materialwidget.cpp
|
||||||
HEADERS += src/materialwidget.h
|
HEADERS += src/materialwidget.h
|
||||||
|
|
||||||
|
SOURCES += src/material.cpp
|
||||||
|
HEADERS += src/material.h
|
||||||
|
|
||||||
SOURCES += src/main.cpp
|
SOURCES += src/main.cpp
|
||||||
|
|
||||||
HEADERS += src/version.h
|
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 "meshquadify.h"
|
||||||
#include "meshweldseam.h"
|
#include "meshweldseam.h"
|
||||||
#include "imageforever.h"
|
#include "imageforever.h"
|
||||||
|
#include "material.h"
|
||||||
|
|
||||||
bool MeshGenerator::m_enableDebug = false;
|
bool MeshGenerator::m_enableDebug = false;
|
||||||
PositionMap<int> *MeshGenerator::m_forMakePositionKey = new PositionMap<int>;
|
PositionMap<int> *MeshGenerator::m_forMakePositionKey = new PositionMap<int>;
|
||||||
|
@ -257,27 +258,8 @@ void *MeshGenerator::combinePartMesh(QString partId)
|
||||||
materialId = QUuid(materialIdString);
|
materialId = QUuid(materialIdString);
|
||||||
|
|
||||||
Material partMaterial;
|
Material partMaterial;
|
||||||
for (const auto &material: m_snapshot->materials) {
|
partMaterial.color = partColor;
|
||||||
if (materialIdString != valueOfKeyInMapOrEmpty(material.first, "id"))
|
partMaterial.materialId = materialId;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString mirroredPartId;
|
QString mirroredPartId;
|
||||||
QUuid mirroredPartIdNotAsString;
|
QUuid mirroredPartIdNotAsString;
|
||||||
|
|
|
@ -8,15 +8,10 @@
|
||||||
#include "positionmap.h"
|
#include "positionmap.h"
|
||||||
#include "skeletonbonemark.h"
|
#include "skeletonbonemark.h"
|
||||||
#include "texturetype.h"
|
#include "texturetype.h"
|
||||||
|
#include "material.h"
|
||||||
|
|
||||||
#define MAX_WEIGHT_NUM 4
|
#define MAX_WEIGHT_NUM 4
|
||||||
|
|
||||||
struct Material
|
|
||||||
{
|
|
||||||
QColor color;
|
|
||||||
const QImage *textureImages[(int)TextureType::Count - 1] = {nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BmeshNode
|
struct BmeshNode
|
||||||
{
|
{
|
||||||
QUuid partId;
|
QUuid partId;
|
||||||
|
|
|
@ -1524,26 +1524,11 @@ void SkeletonDocument::generateTexture()
|
||||||
|
|
||||||
m_isTextureObsolete = false;
|
m_isTextureObsolete = false;
|
||||||
|
|
||||||
|
SkeletonSnapshot *snapshot = new SkeletonSnapshot;
|
||||||
|
toSnapshot(snapshot);
|
||||||
|
|
||||||
QThread *thread = new QThread;
|
QThread *thread = new QThread;
|
||||||
m_textureGenerator = new TextureGenerator(*m_postProcessedResultContext);
|
m_textureGenerator = new TextureGenerator(*m_postProcessedResultContext, snapshot);
|
||||||
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->moveToThread(thread);
|
m_textureGenerator->moveToThread(thread);
|
||||||
connect(thread, &QThread::started, m_textureGenerator, &TextureGenerator::process);
|
connect(thread, &QThread::started, m_textureGenerator, &TextureGenerator::process);
|
||||||
connect(m_textureGenerator, &TextureGenerator::finished, this, &SkeletonDocument::textureReady);
|
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.materialId = materialId;
|
||||||
part->second.dirty = true;
|
part->second.dirty = true;
|
||||||
emit partMaterialIdChanged(partId);
|
emit partMaterialIdChanged(partId);
|
||||||
emit skeletonChanged();
|
emit textureChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonDocument::setPartRoundState(QUuid partId, bool rounded)
|
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.layers = layers;
|
||||||
findMaterialResult->second.dirty = true;
|
findMaterialResult->second.dirty = true;
|
||||||
emit materialLayersChanged(materialId);
|
emit materialLayersChanged(materialId);
|
||||||
|
emit textureChanged();
|
||||||
emit optionsChanged();
|
emit optionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -537,6 +537,7 @@ signals:
|
||||||
void meshGenerating();
|
void meshGenerating();
|
||||||
void postProcessing();
|
void postProcessing();
|
||||||
void textureGenerating();
|
void textureGenerating();
|
||||||
|
void textureChanged();
|
||||||
public: // need initialize
|
public: // need initialize
|
||||||
float originX;
|
float originX;
|
||||||
float originY;
|
float originY;
|
||||||
|
|
|
@ -815,6 +815,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
||||||
// m_document->postProcess();
|
// 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::postProcess);
|
||||||
connect(m_document, &SkeletonDocument::resultMeshChanged, m_document, &SkeletonDocument::generateRig);
|
connect(m_document, &SkeletonDocument::resultMeshChanged, m_document, &SkeletonDocument::generateRig);
|
||||||
connect(m_document, &SkeletonDocument::rigChanged, m_document, &SkeletonDocument::generateRig);
|
connect(m_document, &SkeletonDocument::rigChanged, m_document, &SkeletonDocument::generateRig);
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QRegion>
|
#include <QRegion>
|
||||||
#include <QPolygon>
|
#include <QPolygon>
|
||||||
|
#include <QElapsedTimer>
|
||||||
#include "texturegenerator.h"
|
#include "texturegenerator.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
#include "dust3dutil.h"
|
||||||
|
|
||||||
int TextureGenerator::m_textureSize = 1024;
|
int TextureGenerator::m_textureSize = 1024;
|
||||||
|
|
||||||
TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext) :
|
TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext, SkeletonSnapshot *snapshot) :
|
||||||
m_resultTextureGuideImage(nullptr),
|
m_resultTextureGuideImage(nullptr),
|
||||||
m_resultTextureImage(nullptr),
|
m_resultTextureImage(nullptr),
|
||||||
m_resultTextureBorderImage(nullptr),
|
m_resultTextureBorderImage(nullptr),
|
||||||
|
@ -17,7 +19,8 @@ TextureGenerator::TextureGenerator(const MeshResultContext &meshResultContext) :
|
||||||
m_resultTextureRoughnessImage(nullptr),
|
m_resultTextureRoughnessImage(nullptr),
|
||||||
m_resultTextureMetalnessImage(nullptr),
|
m_resultTextureMetalnessImage(nullptr),
|
||||||
m_resultTextureAmbientOcclusionImage(nullptr),
|
m_resultTextureAmbientOcclusionImage(nullptr),
|
||||||
m_resultMesh(nullptr)
|
m_resultMesh(nullptr),
|
||||||
|
m_snapshot(snapshot)
|
||||||
{
|
{
|
||||||
m_resultContext = new MeshResultContext();
|
m_resultContext = new MeshResultContext();
|
||||||
*m_resultContext = meshResultContext;
|
*m_resultContext = meshResultContext;
|
||||||
|
@ -36,6 +39,7 @@ TextureGenerator::~TextureGenerator()
|
||||||
delete m_resultTextureMetalnessImage;
|
delete m_resultTextureMetalnessImage;
|
||||||
delete m_resultTextureAmbientOcclusionImage;
|
delete m_resultTextureAmbientOcclusionImage;
|
||||||
delete m_resultMesh;
|
delete m_resultMesh;
|
||||||
|
delete m_snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage *TextureGenerator::takeResultTextureGuideImage()
|
QImage *TextureGenerator::takeResultTextureGuideImage()
|
||||||
|
@ -130,8 +134,53 @@ QPainterPath TextureGenerator::expandedPainterPath(const QPainterPath &painterPa
|
||||||
return (stroker.createStroke(painterPath) + painterPath).simplified();
|
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()
|
void TextureGenerator::generate()
|
||||||
{
|
{
|
||||||
|
QElapsedTimer countTimeConsumed;
|
||||||
|
countTimeConsumed.start();
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
|
||||||
bool hasNormalMap = false;
|
bool hasNormalMap = false;
|
||||||
bool hasMetalnessMap = false;
|
bool hasMetalnessMap = false;
|
||||||
bool hasRoughnessMap = false;
|
bool hasRoughnessMap = false;
|
||||||
|
@ -350,6 +399,8 @@ void TextureGenerator::generate()
|
||||||
m_resultMesh->setHasRoughnessInImage(hasRoughnessMap);
|
m_resultMesh->setHasRoughnessInImage(hasRoughnessMap);
|
||||||
m_resultMesh->setHasAmbientOcclusionInImage(hasAmbientOcclusionMap);
|
m_resultMesh->setHasAmbientOcclusionInImage(hasAmbientOcclusionMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qDebug() << "The texture[" << TextureGenerator::m_textureSize << "x" << TextureGenerator::m_textureSize << "] generation took" << countTimeConsumed.elapsed() << "milliseconds";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureGenerator::process()
|
void TextureGenerator::process()
|
||||||
|
|
|
@ -10,7 +10,7 @@ class TextureGenerator : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TextureGenerator(const MeshResultContext &meshResultContext);
|
TextureGenerator(const MeshResultContext &meshResultContext, SkeletonSnapshot *snapshot=nullptr);
|
||||||
~TextureGenerator();
|
~TextureGenerator();
|
||||||
QImage *takeResultTextureGuideImage();
|
QImage *takeResultTextureGuideImage();
|
||||||
QImage *takeResultTextureImage();
|
QImage *takeResultTextureImage();
|
||||||
|
@ -32,6 +32,7 @@ public slots:
|
||||||
public:
|
public:
|
||||||
static int m_textureSize;
|
static int m_textureSize;
|
||||||
private:
|
private:
|
||||||
|
void prepare();
|
||||||
QPainterPath expandedPainterPath(const QPainterPath &painterPath);
|
QPainterPath expandedPainterPath(const QPainterPath &painterPath);
|
||||||
private:
|
private:
|
||||||
MeshResultContext *m_resultContext;
|
MeshResultContext *m_resultContext;
|
||||||
|
@ -50,6 +51,7 @@ private:
|
||||||
std::map<QUuid, QImage> m_partMetalnessTextureMap;
|
std::map<QUuid, QImage> m_partMetalnessTextureMap;
|
||||||
std::map<QUuid, QImage> m_partRoughnessTextureMap;
|
std::map<QUuid, QImage> m_partRoughnessTextureMap;
|
||||||
std::map<QUuid, QImage> m_partAmbientOcclusionTextureMap;
|
std::map<QUuid, QImage> m_partAmbientOcclusionTextureMap;
|
||||||
|
SkeletonSnapshot *m_snapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue