diff --git a/application/application.pro b/application/application.pro index 98a4716a..b576c7e7 100644 --- a/application/application.pro +++ b/application/application.pro @@ -145,20 +145,6 @@ SOURCES += sources/log_browser.cc HEADERS += sources/log_browser_dialog.h SOURCES += sources/log_browser_dialog.cc SOURCES += sources/main.cc -HEADERS += sources/material.h -SOURCES += sources/material.cc -HEADERS += sources/material_edit_widget.h -SOURCES += sources/material_edit_widget.cc -HEADERS += sources/material_layer.h -SOURCES += sources/material_layer.cc -HEADERS += sources/material_list_widget.h -SOURCES += sources/material_list_widget.cc -HEADERS += sources/material_manage_widget.h -SOURCES += sources/material_manage_widget.cc -HEADERS += sources/material_previews_generator.h -SOURCES += sources/material_previews_generator.cc -HEADERS += sources/material_widget.h -SOURCES += sources/material_widget.cc HEADERS += sources/mesh_generator.h SOURCES += sources/mesh_generator.cc HEADERS += sources/mesh_preview_images_generator.h @@ -195,8 +181,6 @@ HEADERS += sources/skeleton_ik_mover.h SOURCES += sources/skeleton_ik_mover.cc HEADERS += sources/spinnable_toolbar_icon.h SOURCES += sources/spinnable_toolbar_icon.cc -HEADERS += sources/texture_generator.h -SOURCES += sources/texture_generator.cc HEADERS += sources/theme.h SOURCES += sources/theme.cc HEADERS += sources/toolbar_button.h diff --git a/application/resources.qrc b/application/resources.qrc index 478d27cc..3b78ef15 100644 --- a/application/resources.qrc +++ b/application/resources.qrc @@ -25,7 +25,6 @@ resources/toolbar_z_disabled.svg resources/toolbar_radius.svg resources/toolbar_radius_disabled.svg - resources/material-demo-model.ds3 resources/model-addax.ds3 resources/model-banana.ds3 resources/model-bicycle.ds3 diff --git a/application/resources/material-demo-model.ds3 b/application/resources/material-demo-model.ds3 deleted file mode 100644 index 23a04e6d..00000000 Binary files a/application/resources/material-demo-model.ds3 and /dev/null differ diff --git a/application/sources/document.cc b/application/sources/document.cc index 656ed07e..5913b697 100644 --- a/application/sources/document.cc +++ b/application/sources/document.cc @@ -1,9 +1,8 @@ #include "document.h" #include "image_forever.h" -#include "material_previews_generator.h" #include "mesh_generator.h" #include "mesh_result_post_processor.h" -#include "texture_generator.h" +#include "uv_map_generator.h" #include #include #include @@ -1423,14 +1422,6 @@ bool Document::originSettled() const return !qFuzzyIsNull(getOriginX()) && !qFuzzyIsNull(getOriginY()) && !qFuzzyIsNull(getOriginZ()); } -const Material* Document::findMaterial(dust3d::Uuid materialId) const -{ - auto it = materialMap.find(materialId); - if (it == materialMap.end()) - return nullptr; - return &it->second; -} - void Document::setNodeCutRotation(dust3d::Uuid nodeId, float cutRotation) { auto node = nodeMap.find(nodeId); @@ -1571,8 +1562,7 @@ void Document::setEditMode(DocumentEditMode mode) } void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::set& limitNodeIds, - DocumentToSnapshotFor forWhat, - const std::set& limitMaterialIds) const + DocumentToSnapshotFor forWhat) const { if (DocumentToSnapshotFor::Document == forWhat || DocumentToSnapshotFor::Nodes == forWhat) { std::set limitPartIds; @@ -1640,8 +1630,6 @@ void Document::toSnapshot(dust3d::Snapshot* snapshot, const std::setrootComponent["children"] = children; } } - if (DocumentToSnapshotFor::Document == forWhat || DocumentToSnapshotFor::Materials == forWhat) { - for (const auto& materialId : materialIdList) { - if (!limitMaterialIds.empty() && limitMaterialIds.find(materialId) == limitMaterialIds.end()) - continue; - auto findMaterialResult = materialMap.find(materialId); - if (findMaterialResult == materialMap.end()) { - qDebug() << "Find material failed:" << materialId; - continue; - } - auto& materialIt = *findMaterialResult; - std::map material; - material["id"] = materialIt.second.id.toString(); - material["type"] = "MetalRoughness"; - if (!materialIt.second.name.isEmpty()) - material["name"] = materialIt.second.name.toUtf8().constData(); - std::vector, std::vector>>> layers; - for (const auto& layer : materialIt.second.layers) { - std::vector> maps; - for (const auto& mapItem : layer.maps) { - std::map textureMap; - textureMap["for"] = TextureTypeToString(mapItem.forWhat); - textureMap["linkDataType"] = "imageId"; - textureMap["linkData"] = mapItem.imageId.toString(); - maps.push_back(textureMap); - } - std::map layerAttributes; - if (!qFuzzyCompare((float)layer.tileScale, (float)1.0)) - layerAttributes["tileScale"] = std::to_string(layer.tileScale); - layers.push_back({ layerAttributes, maps }); - } - snapshot->materials.push_back(std::make_pair(material, layers)); - } - } if (DocumentToSnapshotFor::Document == forWhat) { std::map canvas; canvas["originX"] = std::to_string(getOriginX()); @@ -1787,49 +1742,6 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo std::set inversePartIds; std::map oldNewIdMap; - for (const auto& materialIt : snapshot.materials) { - const auto& materialAttributes = materialIt.first; - auto materialType = dust3d::String::valueOrEmpty(materialAttributes, "type"); - if ("MetalRoughness" != materialType) { - qDebug() << "Unsupported material type:" << materialType; - continue; - } - dust3d::Uuid oldMaterialId = dust3d::Uuid(dust3d::String::valueOrEmpty(materialAttributes, "id")); - dust3d::Uuid newMaterialId = SnapshotSource::Import == source ? oldMaterialId : dust3d::Uuid::createUuid(); - oldNewIdMap[oldMaterialId] = newMaterialId; - if (materialMap.end() == materialMap.find(newMaterialId)) { - auto& newMaterial = materialMap[newMaterialId]; - newMaterial.id = newMaterialId; - newMaterial.name = dust3d::String::valueOrEmpty(materialAttributes, "name").c_str(); - for (const auto& layerIt : materialIt.second) { - MaterialLayer layer; - auto findTileScale = layerIt.first.find("tileScale"); - if (findTileScale != layerIt.first.end()) - layer.tileScale = dust3d::String::toFloat(findTileScale->second); - for (const auto& mapItem : layerIt.second) { - auto textureTypeString = dust3d::String::valueOrEmpty(mapItem, "for"); - auto textureType = dust3d::TextureTypeFromString(textureTypeString.c_str()); - if (dust3d::TextureType::None == textureType) { - qDebug() << "Unsupported texture type:" << textureTypeString; - continue; - } - auto linkTypeString = dust3d::String::valueOrEmpty(mapItem, "linkDataType"); - if ("imageId" != linkTypeString) { - qDebug() << "Unsupported link data type:" << linkTypeString; - continue; - } - auto imageId = dust3d::Uuid(dust3d::String::valueOrEmpty(mapItem, "linkData")); - MaterialMap materialMap; - materialMap.imageId = imageId; - materialMap.forWhat = textureType; - layer.maps.push_back(materialMap); - } - newMaterial.layers.push_back(layer); - } - materialIdList.push_back(newMaterialId); - emit materialAdded(newMaterialId); - } - } std::map cutFaceLinkedIdModifyMap; for (const auto& partKv : snapshot.parts) { const auto newUuid = dust3d::Uuid::createUuid(); @@ -1895,9 +1807,6 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo const auto& hollowThicknessIt = partKv.second.find("hollowThickness"); if (hollowThicknessIt != partKv.second.end()) part.hollowThickness = dust3d::String::toFloat(hollowThicknessIt->second); - const auto& materialIdIt = partKv.second.find("materialId"); - if (materialIdIt != partKv.second.end()) - part.materialId = oldNewIdMap[dust3d::Uuid(materialIdIt->second)]; part.countershaded = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "countershaded")); part.smooth = dust3d::String::isTrue(dust3d::String::valueOrEmpty(partKv.second, "smooth")); newAddedPartIds.insert(part.id); @@ -2054,9 +1963,6 @@ void Document::addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSo for (const auto& edgeIt : newAddedEdgeIds) { emit checkEdge(edgeIt); } - - if (!snapshot.materials.empty()) - emit materialListChanged(); } void Document::silentReset() @@ -2068,8 +1974,6 @@ void Document::silentReset() edgeMap.clear(); partMap.clear(); componentMap.clear(); - materialMap.clear(); - materialIdList.clear(); rootComponent = SkeletonComponent(); } @@ -2244,29 +2148,31 @@ void Document::generateTexture() m_isTextureObsolete = false; - dust3d::Snapshot* snapshot = new dust3d::Snapshot; - toSnapshot(snapshot); + auto object = std::make_unique(*m_postProcessedObject); + + auto snapshot = std::make_unique(); + toSnapshot(snapshot.get()); QThread* thread = new QThread; - m_textureGenerator = new TextureGenerator(*m_postProcessedObject, snapshot); + m_textureGenerator = new UvMapGenerator(std::move(object), std::move(snapshot)); m_textureGenerator->moveToThread(thread); - connect(thread, &QThread::started, m_textureGenerator, &TextureGenerator::process); - connect(m_textureGenerator, &TextureGenerator::finished, this, &Document::textureReady); - connect(m_textureGenerator, &TextureGenerator::finished, thread, &QThread::quit); + connect(thread, &QThread::started, m_textureGenerator, &UvMapGenerator::process); + connect(m_textureGenerator, &UvMapGenerator::finished, this, &Document::textureReady); + connect(m_textureGenerator, &UvMapGenerator::finished, thread, &QThread::quit); connect(thread, &QThread::finished, thread, &QThread::deleteLater); thread->start(); } void Document::textureReady() { - updateTextureImage(m_textureGenerator->takeResultTextureColorImage()); - updateTextureNormalImage(m_textureGenerator->takeResultTextureNormalImage()); - updateTextureMetalnessImage(m_textureGenerator->takeResultTextureMetalnessImage()); - updateTextureRoughnessImage(m_textureGenerator->takeResultTextureRoughnessImage()); - updateTextureAmbientOcclusionImage(m_textureGenerator->takeResultTextureAmbientOcclusionImage()); + updateTextureImage(m_textureGenerator->takeResultTextureColorImage().release()); + updateTextureNormalImage(m_textureGenerator->takeResultTextureNormalImage().release()); + updateTextureMetalnessImage(m_textureGenerator->takeResultTextureMetalnessImage().release()); + updateTextureRoughnessImage(m_textureGenerator->takeResultTextureRoughnessImage().release()); + updateTextureAmbientOcclusionImage(m_textureGenerator->takeResultTextureAmbientOcclusionImage().release()); delete m_resultTextureMesh; - m_resultTextureMesh = m_textureGenerator->takeResultMesh(); + m_resultTextureMesh = m_textureGenerator->takeResultMesh().release(); m_postProcessedObject->alphaEnabled = m_textureGenerator->hasTransparencySettings(); @@ -2486,21 +2392,6 @@ void Document::setPartDeformUnified(dust3d::Uuid partId, bool unified) emit skeletonChanged(); } -void Document::setPartMaterialId(dust3d::Uuid partId, dust3d::Uuid materialId) -{ - auto part = partMap.find(partId); - if (part == partMap.end()) { - qDebug() << "Part not found:" << partId; - return; - } - if (part->second.materialId == materialId) - return; - part->second.materialId = materialId; - part->second.dirty = true; - emit partMaterialIdChanged(partId); - emit textureChanged(); -} - void Document::setPartRoundState(dust3d::Uuid partId, bool rounded) { auto part = partMap.find(partId); @@ -2758,17 +2649,6 @@ bool Document::hasPastableNodesInClipboard() const return false; } -bool Document::hasPastableMaterialsInClipboard() const -{ - const QClipboard* clipboard = QApplication::clipboard(); - const QMimeData* mimeData = clipboard->mimeData(); - if (mimeData->hasText()) { - if (-1 != mimeData->text().indexOf("= 2; @@ -2816,126 +2696,6 @@ void Document::checkExportReadyState() emit exportReady(); } -void Document::addMaterial(dust3d::Uuid materialId, QString name, std::vector layers) -{ - auto findMaterialResult = materialMap.find(materialId); - if (findMaterialResult != materialMap.end()) { - qDebug() << "Material already exist:" << materialId; - return; - } - - dust3d::Uuid newMaterialId = materialId; - auto& material = materialMap[newMaterialId]; - material.id = newMaterialId; - - material.name = name; - material.layers = layers; - material.dirty = true; - - materialIdList.push_back(newMaterialId); - - emit materialAdded(newMaterialId); - emit materialListChanged(); - emit optionsChanged(); -} - -void Document::removeMaterial(dust3d::Uuid materialId) -{ - auto findMaterialResult = materialMap.find(materialId); - if (findMaterialResult == materialMap.end()) { - qDebug() << "Remove a none exist material:" << materialId; - return; - } - materialIdList.erase(std::remove(materialIdList.begin(), materialIdList.end(), materialId), materialIdList.end()); - materialMap.erase(findMaterialResult); - - emit materialListChanged(); - emit materialRemoved(materialId); - emit optionsChanged(); -} - -void Document::setMaterialLayers(dust3d::Uuid materialId, std::vector layers) -{ - auto findMaterialResult = materialMap.find(materialId); - if (findMaterialResult == materialMap.end()) { - qDebug() << "Find material failed:" << materialId; - return; - } - findMaterialResult->second.layers = layers; - findMaterialResult->second.dirty = true; - emit materialLayersChanged(materialId); - emit textureChanged(); - emit optionsChanged(); -} - -void Document::renameMaterial(dust3d::Uuid materialId, QString name) -{ - auto findMaterialResult = materialMap.find(materialId); - if (findMaterialResult == materialMap.end()) { - qDebug() << "Find material failed:" << materialId; - return; - } - if (findMaterialResult->second.name == name) - return; - - findMaterialResult->second.name = name; - emit materialNameChanged(materialId); - emit materialListChanged(); - emit optionsChanged(); -} - -void Document::generateMaterialPreviews() -{ - if (nullptr != m_materialPreviewsGenerator) { - return; - } - - QThread* thread = new QThread; - m_materialPreviewsGenerator = new MaterialPreviewsGenerator(); - bool hasDirtyMaterial = false; - for (auto& materialIt : materialMap) { - if (!materialIt.second.dirty) - continue; - m_materialPreviewsGenerator->addMaterial(materialIt.first, materialIt.second.layers); - materialIt.second.dirty = false; - hasDirtyMaterial = true; - } - if (!hasDirtyMaterial) { - delete m_materialPreviewsGenerator; - m_materialPreviewsGenerator = nullptr; - delete thread; - return; - } - - qDebug() << "Material previews generating.."; - - m_materialPreviewsGenerator->moveToThread(thread); - connect(thread, &QThread::started, m_materialPreviewsGenerator, &MaterialPreviewsGenerator::process); - connect(m_materialPreviewsGenerator, &MaterialPreviewsGenerator::finished, this, &Document::materialPreviewsReady); - connect(m_materialPreviewsGenerator, &MaterialPreviewsGenerator::finished, thread, &QThread::quit); - connect(thread, &QThread::finished, thread, &QThread::deleteLater); - thread->start(); -} - -void Document::materialPreviewsReady() -{ - for (const auto& materialId : m_materialPreviewsGenerator->generatedPreviewMaterialIds()) { - auto material = materialMap.find(materialId); - if (material != materialMap.end()) { - ModelMesh* resultPartPreviewMesh = m_materialPreviewsGenerator->takePreview(materialId); - material->second.updatePreviewMesh(resultPartPreviewMesh); - emit materialPreviewChanged(materialId); - } - } - - delete m_materialPreviewsGenerator; - m_materialPreviewsGenerator = nullptr; - - qDebug() << "Material previews generation done"; - - generateMaterialPreviews(); -} - bool Document::isMeshGenerating() const { return nullptr != m_meshGenerator; diff --git a/application/sources/document.h b/application/sources/document.h index 0c5b8809..8a890491 100644 --- a/application/sources/document.h +++ b/application/sources/document.h @@ -2,7 +2,6 @@ #define DUST3D_APPLICATION_DOCUMENT_H_ #include "debug.h" -#include "material_layer.h" #include "model_mesh.h" #include "monochrome_mesh.h" #include "theme.h" @@ -165,7 +164,6 @@ public: float cutRotation; dust3d::CutFace cutFace; dust3d::Uuid cutFaceLinkedId; - dust3d::Uuid materialId; dust3d::PartTarget target; float colorSolubility; float metalness; @@ -338,10 +336,6 @@ public: { return cutRotationAdjusted() || cutFaceAdjusted() || hollowThicknessAdjusted(); } - bool materialAdjusted() const - { - return !materialId.isNull(); - } bool isEditVisible() const { return visible && !disabled; @@ -364,7 +358,6 @@ public: cutFaceLinkedId = other.cutFaceLinkedId; componentId = other.componentId; dirty = other.dirty; - materialId = other.materialId; target = other.target; colorSolubility = other.colorSolubility; countershaded = other.countershaded; @@ -551,8 +544,7 @@ private: std::set m_childrenIdSet; }; -class MaterialPreviewsGenerator; -class TextureGenerator; +class UvMapGenerator; class MeshGenerator; class MeshResultPostProcessor; @@ -561,40 +553,9 @@ public: dust3d::Snapshot snapshot; }; -class Material { -public: - Material() - { - } - ~Material() - { - delete m_previewMesh; - } - dust3d::Uuid id; - QString name; - bool dirty = true; - std::vector layers; - void updatePreviewMesh(ModelMesh* previewMesh) - { - delete m_previewMesh; - m_previewMesh = previewMesh; - } - ModelMesh* takePreviewMesh() const - { - if (nullptr == m_previewMesh) - return nullptr; - return new ModelMesh(*m_previewMesh); - } - -private: - Q_DISABLE_COPY(Material); - ModelMesh* m_previewMesh = nullptr; -}; - enum class DocumentToSnapshotFor { Document = 0, - Nodes, - Materials + Nodes }; class Document : public QObject { @@ -618,7 +579,6 @@ signals: void partColorStateChanged(dust3d::Uuid partId); void partCutRotationChanged(dust3d::Uuid partId); void partCutFaceChanged(dust3d::Uuid partId); - void partMaterialIdChanged(dust3d::Uuid partId); void partChamferStateChanged(dust3d::Uuid partId); void partTargetChanged(dust3d::Uuid partId); void partColorSolubilityChanged(dust3d::Uuid partId); @@ -638,12 +598,6 @@ signals: void uncheckAll(); void checkNode(dust3d::Uuid nodeId); void checkEdge(dust3d::Uuid edgeId); - void materialAdded(dust3d::Uuid materialId); - void materialRemoved(dust3d::Uuid materialId); - void materialListChanged(); - void materialNameChanged(dust3d::Uuid materialId); - void materialLayersChanged(dust3d::Uuid materialId); - void materialPreviewChanged(dust3d::Uuid materialId); void meshGenerating(); void postProcessing(); void textureGenerating(); @@ -706,9 +660,6 @@ public: // need initialize public: Document(); ~Document(); - std::map materialMap; - std::vector materialIdList; - bool undoable() const; bool redoable() const; bool hasPastableNodesInClipboard() const; @@ -717,8 +668,7 @@ public: bool isEdgeEditable(dust3d::Uuid edgeId) const; void copyNodes(std::set nodeIdSet) const; void toSnapshot(dust3d::Snapshot* snapshot, const std::set& limitNodeIds = std::set(), - DocumentToSnapshotFor forWhat = DocumentToSnapshotFor::Document, - const std::set& limitMaterialIds = std::set()) const; + DocumentToSnapshotFor forWhat = DocumentToSnapshotFor::Document) const; void fromSnapshot(const dust3d::Snapshot& snapshot); enum class SnapshotSource { Unknown, @@ -726,7 +676,6 @@ public: Import }; void addFromSnapshot(const dust3d::Snapshot& snapshot, enum SnapshotSource source = SnapshotSource::Paste); - const Material* findMaterial(dust3d::Uuid materialId) const; ModelMesh* takeResultMesh(); MonochromeMesh* takeWireframeMesh(); ModelMesh* takePaintedMesh(); @@ -740,7 +689,6 @@ public: void updateTextureMetalnessImage(QImage* image); void updateTextureRoughnessImage(QImage* image); void updateTextureAmbientOcclusionImage(QImage* image); - bool hasPastableMaterialsInClipboard() const; const dust3d::Object& currentPostProcessedObject() const; bool isExportReady() const; bool isPostProcessResultObsolete() const; @@ -822,8 +770,6 @@ public slots: void textureReady(); void postProcess(); void postProcessedMeshResultReady(); - void generateMaterialPreviews(); - void materialPreviewsReady(); void setPartSubdivState(dust3d::Uuid partId, bool subdived); void setPartXmirrorState(dust3d::Uuid partId, bool mirrored); void setPartDeformThickness(dust3d::Uuid partId, float thickness); @@ -834,7 +780,6 @@ public slots: void setPartCutRotation(dust3d::Uuid partId, float cutRotation); void setPartCutFace(dust3d::Uuid partId, dust3d::CutFace cutFace); void setPartCutFaceLinkedId(dust3d::Uuid partId, dust3d::Uuid linkedId); - void setPartMaterialId(dust3d::Uuid partId, dust3d::Uuid materialId); void setPartChamferState(dust3d::Uuid partId, bool chamfered); void setPartTarget(dust3d::Uuid partId, dust3d::PartTarget target); void setPartColorSolubility(dust3d::Uuid partId, float solubility); @@ -852,10 +797,6 @@ public slots: void silentReset(); void toggleSmoothNormal(); void enableWeld(bool enabled); - void addMaterial(dust3d::Uuid materialId, QString name, std::vector); - void removeMaterial(dust3d::Uuid materialId); - void setMaterialLayers(dust3d::Uuid materialId, std::vector layers); - void renameMaterial(dust3d::Uuid materialId, QString name); void removeNode(dust3d::Uuid nodeId); void removeEdge(dust3d::Uuid edgeId); void removePart(dust3d::Uuid partId); @@ -932,14 +873,13 @@ private: int m_batchChangeRefCount = 0; dust3d::Object* m_currentObject = nullptr; bool m_isTextureObsolete = false; - TextureGenerator* m_textureGenerator = nullptr; + UvMapGenerator* m_textureGenerator = nullptr; bool m_isPostProcessResultObsolete = false; MeshResultPostProcessor* m_postProcessor = nullptr; dust3d::Object* m_postProcessedObject = new dust3d::Object; ModelMesh* m_resultTextureMesh = nullptr; unsigned long long m_textureImageUpdateVersion = 0; bool m_smoothNormal = false; - MaterialPreviewsGenerator* m_materialPreviewsGenerator = nullptr; quint64 m_meshGenerationId = 0; quint64 m_nextMeshGenerationId = 0; void* m_generatedCacheContext = nullptr; diff --git a/application/sources/document_saver.cc b/application/sources/document_saver.cc index 1a7aebba..95f83bbc 100644 --- a/application/sources/document_saver.cc +++ b/application/sources/document_saver.cc @@ -39,17 +39,6 @@ void DocumentSaver::collectUsedResourceIds(const dust3d::Snapshot* snapshot, dust3d::Uuid imageId = dust3d::Uuid(findImageIdString->second); imageIds.insert(imageId); } - for (const auto& material : snapshot->materials) { - for (auto& layer : material.second) { - for (auto& mapItem : layer.second) { - auto findImageIdString = mapItem.find("linkData"); - if (findImageIdString == mapItem.end()) - continue; - dust3d::Uuid imageId = dust3d::Uuid(findImageIdString->second); - imageIds.insert(imageId); - } - } - } } bool DocumentSaver::save(const QString* filename, diff --git a/application/sources/document_window.cc b/application/sources/document_window.cc index 96613b4b..7bb1f310 100644 --- a/application/sources/document_window.cc +++ b/application/sources/document_window.cc @@ -10,14 +10,13 @@ #include "horizontal_line_widget.h" #include "image_forever.h" #include "log_browser.h" -#include "material_manage_widget.h" #include "part_manage_widget.h" #include "preferences.h" #include "skeleton_graphics_widget.h" #include "spinnable_toolbar_icon.h" -#include "texture_generator.h" #include "theme.h" #include "updates_check_widget.h" +#include "uv_map_generator.h" #include "version.h" #include #include @@ -270,21 +269,6 @@ DocumentWindow::DocumentWindow() partsDocker->setWidget(m_partManageWidget); addDockWidget(Qt::RightDockWidgetArea, partsDocker); - QDockWidget* materialDocker = new QDockWidget(tr("Materials"), this); - materialDocker->setAllowedAreas(Qt::RightDockWidgetArea); - MaterialManageWidget* materialManageWidget = new MaterialManageWidget(m_document, materialDocker); - materialDocker->setWidget(materialManageWidget); - connect(materialManageWidget, &MaterialManageWidget::registerDialog, this, &DocumentWindow::registerDialog); - connect(materialManageWidget, &MaterialManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog); - addDockWidget(Qt::RightDockWidgetArea, materialDocker); - connect(materialDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) { - Q_UNUSED(topLevel); - for (const auto& material : m_document->materialMap) - emit m_document->materialPreviewChanged(material.first); - }); - - tabifyDockWidget(partsDocker, materialDocker); - partsDocker->raise(); QWidget* titleBarWidget = new QWidget; @@ -431,13 +415,6 @@ DocumentWindow::DocumentWindow() }); m_windowMenu->addAction(m_showPartsListAction); - m_showMaterialsAction = new QAction(tr("Materials"), this); - connect(m_showMaterialsAction, &QAction::triggered, [=]() { - materialDocker->show(); - materialDocker->raise(); - }); - m_windowMenu->addAction(m_showMaterialsAction); - QMenu* dialogsMenu = m_windowMenu->addMenu(tr("Dialogs")); connect(dialogsMenu, &QMenu::aboutToShow, [=]() { dialogsMenu->clear(); @@ -667,15 +644,6 @@ DocumentWindow::DocumentWindow() connect(m_document, &Document::zlockStateChanged, this, &DocumentWindow::updateZlockButtonState); connect(m_document, &Document::radiusLockStateChanged, this, &DocumentWindow::updateRadiusLockButtonState); - connect(m_document, &Document::materialAdded, this, [=](dust3d::Uuid materialId) { - Q_UNUSED(materialId); - m_document->generateMaterialPreviews(); - }); - connect(m_document, &Document::materialLayersChanged, this, [=](dust3d::Uuid materialId) { - Q_UNUSED(materialId); - m_document->generateMaterialPreviews(); - }); - initializeShortcuts(); connect(this, &DocumentWindow::initialized, m_document, &Document::uiReady); @@ -1088,7 +1056,7 @@ void DocumentWindow::exportGlbToFilename(const QString& filename) } QApplication::setOverrideCursor(Qt::WaitCursor); dust3d::Object skeletonResult = m_document->currentPostProcessedObject(); - QImage* textureMetalnessRoughnessAmbientOcclusionImage = TextureGenerator::combineMetalnessRoughnessAmbientOcclusionImages(m_document->textureMetalnessImage, + QImage* textureMetalnessRoughnessAmbientOcclusionImage = UvMapGenerator::combineMetalnessRoughnessAmbientOcclusionImages(m_document->textureMetalnessImage, m_document->textureRoughnessImage, m_document->textureAmbientOcclusionImage); GlbFileWriter glbFileWriter(skeletonResult, filename, diff --git a/application/sources/document_window.h b/application/sources/document_window.h index f9140b96..dcbdc273 100644 --- a/application/sources/document_window.h +++ b/application/sources/document_window.h @@ -144,7 +144,6 @@ private: QMenu* m_windowMenu = nullptr; QAction* m_showPartsListAction = nullptr; QAction* m_showDebugDialogAction = nullptr; - QAction* m_showMaterialsAction = nullptr; QMenu* m_helpMenu = nullptr; QAction* m_gotoHomepageAction = nullptr; diff --git a/application/sources/material.cc b/application/sources/material.cc deleted file mode 100644 index c5c1026c..00000000 --- a/application/sources/material.cc +++ /dev/null @@ -1,34 +0,0 @@ -#include "material.h" -#include "image_forever.h" - -void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot& snapshot, - const dust3d::Uuid& materialId, - MaterialTextures& materialTextures, - float& tileScale) -{ - auto materialIdString = materialId.toString(); - for (const auto& materialItem : snapshot.materials) { - if (materialIdString != dust3d::String::valueOrEmpty(materialItem.first, "id")) - continue; - for (const auto& layer : materialItem.second) { - //FIXME: Only support one layer currently - auto findTileScale = layer.first.find("tileScale"); - if (findTileScale != layer.first.end()) - tileScale = dust3d::String::toFloat(findTileScale->second); - for (const auto& mapItem : layer.second) { - auto textureType = dust3d::TextureTypeFromString(dust3d::String::valueOrEmpty(mapItem, "for").c_str()); - if (textureType != dust3d::TextureType::None) { - int index = (int)textureType - 1; - if (index >= 0 && index < (int)dust3d::TextureType::Count - 1) { - if ("imageId" == dust3d::String::valueOrEmpty(mapItem, "linkDataType")) { - auto imageIdString = dust3d::String::valueOrEmpty(mapItem, "linkData"); - materialTextures.textureImages[index] = ImageForever::get(dust3d::Uuid(imageIdString)); - } - } - } - } - break; - } - break; - } -} diff --git a/application/sources/material.h b/application/sources/material.h deleted file mode 100644 index b69357b5..00000000 --- a/application/sources/material.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_H_ -#define DUST3D_APPLICATION_MATERIAL_H_ - -#include -#include -#include -#include - -struct MaterialTextures { - const QImage* textureImages[(int)dust3d::TextureType::Count - 1] = { nullptr }; -}; - -void initializeMaterialTexturesFromSnapshot(const dust3d::Snapshot& snapshot, - const dust3d::Uuid& materialId, - MaterialTextures& materialTextures, - float& tileScale); - -#endif diff --git a/application/sources/material_edit_widget.cc b/application/sources/material_edit_widget.cc deleted file mode 100644 index bcb7df51..00000000 --- a/application/sources/material_edit_widget.cc +++ /dev/null @@ -1,335 +0,0 @@ -#include "material_edit_widget.h" -#include "document.h" -#include "float_number_widget.h" -#include "horizontal_line_widget.h" -#include "image_forever.h" -#include "theme.h" -#include "version.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -ImagePreviewWidget* MaterialEditWidget::createMapButton() -{ - ImagePreviewWidget* mapButton = new ImagePreviewWidget; - mapButton->setFixedSize(Theme::partPreviewImageSize * 2, Theme::partPreviewImageSize * 2); - updateMapButtonBackground(mapButton, nullptr); - return mapButton; -} - -QImage* MaterialEditWidget::pickImage() -{ - QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(), - tr("Image Files (*.png *.jpg *.bmp)")) - .trimmed(); - if (fileName.isEmpty()) - return nullptr; - QImage* image = new QImage(); - if (!image->load(fileName)) - return nullptr; - return image; -} - -MaterialEditWidget::MaterialEditWidget(const Document* document, QWidget* parent) - : QDialog(parent) - , m_document(document) -{ - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - - m_layers.resize(1); - - m_previewWidget = new ModelWidget(this); - m_previewWidget->setMinimumSize(128, 128); - m_previewWidget->resize(512, 512); - m_previewWidget->move(-128, -128); - m_previewWidget->setNotGraphics(true); - - QFont nameFont; - nameFont.setWeight(QFont::Light); - nameFont.setBold(false); - - QGridLayout* mapLayout = new QGridLayout; - int row = 0; - int col = 0; - for (int i = 1; i < (int)dust3d::TextureType::Count; i++) { - QVBoxLayout* textureManageLayout = new QVBoxLayout; - - MaterialMap item; - item.forWhat = (dust3d::TextureType)i; - m_layers[0].maps.push_back(item); - - ImagePreviewWidget* imageButton = createMapButton(); - connect(imageButton, &ImagePreviewWidget::clicked, [=]() { - QImage* image = pickImage(); - if (nullptr == image) - return; - m_layers[0].maps[(int)i - 1].imageId = ImageForever::add(image); - updateMapButtonBackground(imageButton, image); - delete image; - emit layersAdjusted(); - }); - - QLabel* nameLabel = new QLabel(tr(dust3d::TextureTypeToDispName(item.forWhat).c_str())); - nameLabel->setFont(nameFont); - - QPushButton* eraser = new QPushButton(QChar(fa::eraser)); - Theme::initAwesomeToolButton(eraser); - - connect(eraser, &QPushButton::clicked, [=]() { - m_layers[0].maps[(int)i - 1].imageId = dust3d::Uuid(); - updateMapButtonBackground(imageButton, nullptr); - emit layersAdjusted(); - }); - - QHBoxLayout* textureTitleLayout = new QHBoxLayout; - textureTitleLayout->addWidget(eraser); - textureTitleLayout->addWidget(nameLabel); - textureTitleLayout->addStretch(); - - textureManageLayout->addWidget(imageButton); - textureManageLayout->addLayout(textureTitleLayout); - m_textureMapButtons[i - 1] = imageButton; - - mapLayout->addLayout(textureManageLayout, row, col++); - if (col == 2) { - col = 0; - row++; - } - } - - QVBoxLayout* rightLayout = new QVBoxLayout; - rightLayout->addStretch(); - rightLayout->addLayout(mapLayout); - rightLayout->addStretch(); - - QHBoxLayout* paramtersLayout = new QHBoxLayout; - paramtersLayout->setContentsMargins(256, 0, 0, 0); - paramtersLayout->addStretch(); - paramtersLayout->addLayout(rightLayout); - - m_nameEdit = new QLineEdit; - connect(m_nameEdit, &QLineEdit::textChanged, this, [=]() { - m_unsaved = true; - updateTitle(); - }); - QPushButton* saveButton = new QPushButton(tr("Save")); - connect(saveButton, &QPushButton::clicked, this, &MaterialEditWidget::save); - saveButton->setDefault(true); - - FloatNumberWidget* tileScaleWidget = new FloatNumberWidget; - tileScaleWidget->setItemName(tr("Tile Scale")); - tileScaleWidget->setRange(0.01, 1.0); - tileScaleWidget->setValue(m_layers[0].tileScale); - - m_tileScaleSlider = tileScaleWidget; - - connect(tileScaleWidget, &FloatNumberWidget::valueChanged, [=](float value) { - m_layers[0].tileScale = value; - emit layersAdjusted(); - }); - - QPushButton* tileScaleEraser = new QPushButton(QChar(fa::eraser)); - Theme::initAwesomeToolButton(tileScaleEraser); - - connect(tileScaleEraser, &QPushButton::clicked, [=]() { - tileScaleWidget->setValue(1.0); - }); - - QHBoxLayout* tileScaleLayout = new QHBoxLayout; - tileScaleLayout->addWidget(tileScaleEraser); - tileScaleLayout->addWidget(tileScaleWidget); - tileScaleLayout->addStretch(); - - QHBoxLayout* baseInfoLayout = new QHBoxLayout; - baseInfoLayout->addWidget(new QLabel(tr("Name"))); - baseInfoLayout->addWidget(m_nameEdit); - baseInfoLayout->addStretch(); - baseInfoLayout->addWidget(saveButton); - - QVBoxLayout* mainLayout = new QVBoxLayout; - mainLayout->addLayout(paramtersLayout); - mainLayout->addStretch(); - mainLayout->addWidget(new HorizontalLineWidget()); - mainLayout->addLayout(tileScaleLayout); - mainLayout->addLayout(baseInfoLayout); - - setLayout(mainLayout); - - connect(this, &MaterialEditWidget::layersAdjusted, this, &MaterialEditWidget::updatePreview); - connect(this, &MaterialEditWidget::layersAdjusted, [=]() { - m_unsaved = true; - updateTitle(); - }); - connect(this, &MaterialEditWidget::addMaterial, document, &Document::addMaterial); - connect(this, &MaterialEditWidget::renameMaterial, document, &Document::renameMaterial); - connect(this, &MaterialEditWidget::setMaterialLayers, document, &Document::setMaterialLayers); - - updatePreview(); - updateTitle(); -} - -void MaterialEditWidget::updateMapButtonBackground(ImagePreviewWidget* button, const QImage* image) -{ - if (nullptr == image) - button->updateImage(QImage()); - else - button->updateImage(*image); -} - -void MaterialEditWidget::reject() -{ - close(); -} - -void MaterialEditWidget::closeEvent(QCloseEvent* event) -{ - if (m_unsaved && !m_closed) { - QMessageBox::StandardButton answer = QMessageBox::question(this, - APP_NAME, - tr("Do you really want to close while there are unsaved changes?"), - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - if (answer != QMessageBox::Yes) { - event->ignore(); - return; - } - } - m_closed = true; - hide(); - if (nullptr != m_materialPreviewsGenerator) { - event->ignore(); - return; - } - event->accept(); -} - -QSize MaterialEditWidget::sizeHint() const -{ - return QSize(0, 200); -} - -MaterialEditWidget::~MaterialEditWidget() -{ - Q_ASSERT(nullptr == m_materialPreviewsGenerator); -} - -void MaterialEditWidget::updatePreview() -{ - if (m_closed) - return; - - if (nullptr != m_materialPreviewsGenerator) { - m_isPreviewDirty = true; - return; - } - - m_isPreviewDirty = false; - - qDebug() << "Material preview generating.."; - - QThread* thread = new QThread; - m_materialPreviewsGenerator = new MaterialPreviewsGenerator(); - m_materialPreviewsGenerator->addMaterial(dust3d::Uuid(), m_layers); - m_materialPreviewsGenerator->moveToThread(thread); - connect(thread, &QThread::started, m_materialPreviewsGenerator, &MaterialPreviewsGenerator::process); - connect(m_materialPreviewsGenerator, &MaterialPreviewsGenerator::finished, this, &MaterialEditWidget::previewReady); - connect(m_materialPreviewsGenerator, &MaterialPreviewsGenerator::finished, thread, &QThread::quit); - connect(thread, &QThread::finished, thread, &QThread::deleteLater); - thread->start(); -} - -void MaterialEditWidget::previewReady() -{ - m_previewWidget->updateMesh(m_materialPreviewsGenerator->takePreview(dust3d::Uuid())); - - delete m_materialPreviewsGenerator; - m_materialPreviewsGenerator = nullptr; - - qDebug() << "Material preview generation done"; - - if (m_closed) { - close(); - return; - } - - if (m_isPreviewDirty) - updatePreview(); -} - -void MaterialEditWidget::setEditMaterialId(dust3d::Uuid materialId) -{ - if (m_materialId == materialId) - return; - - m_materialId = materialId; - updateTitle(); -} - -void MaterialEditWidget::updateTitle() -{ - if (m_materialId.isNull()) { - setWindowTitle(applicationTitle(tr("New") + (m_unsaved ? "*" : ""))); - return; - } - const Material* material = m_document->findMaterial(m_materialId); - if (nullptr == material) { - qDebug() << "Find material failed:" << m_materialId; - return; - } - setWindowTitle(applicationTitle(material->name + (m_unsaved ? "*" : ""))); -} - -void MaterialEditWidget::setEditMaterialName(QString name) -{ - m_nameEdit->setText(name); - updateTitle(); -} - -void MaterialEditWidget::setEditMaterialLayers(std::vector layers) -{ - for (int i = 1; i < (int)dust3d::TextureType::Count; i++) { - m_layers[0].maps[i - 1].imageId = dust3d::Uuid(); - } - if (!layers.empty()) { - for (const auto& layer : layers) { - m_layers[0].tileScale = layer.tileScale; - for (const auto& mapItem : layer.maps) { - int index = (int)mapItem.forWhat - 1; - if (index >= 0 && index < (int)dust3d::TextureType::Count - 1) { - m_layers[0].maps[index].imageId = mapItem.imageId; - } - } - } - m_tileScaleSlider->setValue(m_layers[0].tileScale); - } - for (int i = 1; i < (int)dust3d::TextureType::Count; i++) { - updateMapButtonBackground(m_textureMapButtons[i - 1], ImageForever::get(m_layers[0].maps[i - 1].imageId)); - } - updatePreview(); -} - -void MaterialEditWidget::clearUnsaveState() -{ - m_unsaved = false; - updateTitle(); -} - -void MaterialEditWidget::save() -{ - if (m_materialId.isNull()) { - m_materialId = dust3d::Uuid::createUuid(); - emit addMaterial(m_materialId, m_nameEdit->text(), m_layers); - } else if (m_unsaved) { - emit renameMaterial(m_materialId, m_nameEdit->text()); - emit setMaterialLayers(m_materialId, m_layers); - } - clearUnsaveState(); -} diff --git a/application/sources/material_edit_widget.h b/application/sources/material_edit_widget.h deleted file mode 100644 index 63359f8a..00000000 --- a/application/sources/material_edit_widget.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_EDIT_WIDGET_H_ -#define DUST3D_APPLICATION_MATERIAL_EDIT_WIDGET_H_ - -#include "float_number_widget.h" -#include "image_preview_widget.h" -#include "material_layer.h" -#include "material_previews_generator.h" -#include "model_widget.h" -#include -#include -#include -#include - -class Document; - -enum class PopupWidgetType { - PitchYawRoll, - Intersection -}; - -class MaterialEditWidget : public QDialog { - Q_OBJECT -signals: - void addMaterial(dust3d::Uuid materialId, QString name, std::vector layers); - void removeMaterial(dust3d::Uuid materialId); - void setMaterialLayers(dust3d::Uuid materialId, std::vector layers); - void renameMaterial(dust3d::Uuid materialId, QString name); - void layersAdjusted(); - -public: - MaterialEditWidget(const Document* document, QWidget* parent = nullptr); - ~MaterialEditWidget(); -public slots: - void updatePreview(); - void setEditMaterialId(dust3d::Uuid materialId); - void setEditMaterialName(QString name); - void setEditMaterialLayers(std::vector layers); - void updateTitle(); - void save(); - void clearUnsaveState(); - void previewReady(); - -protected: - QSize sizeHint() const override; - void closeEvent(QCloseEvent* event) override; - void reject() override; - -private: - void updateMapButtonBackground(ImagePreviewWidget* button, const QImage* image); - ImagePreviewWidget* createMapButton(); - QImage* pickImage(); - const Document* m_document = nullptr; - MaterialPreviewsGenerator* m_materialPreviewsGenerator = nullptr; - ModelWidget* m_previewWidget = nullptr; - FloatNumberWidget* m_tileScaleSlider = nullptr; - bool m_isPreviewDirty = false; - bool m_closed = false; - dust3d::Uuid m_materialId; - bool m_unsaved = false; - QLineEdit* m_nameEdit = nullptr; - std::vector m_layers; - ImagePreviewWidget* m_textureMapButtons[(int)dust3d::TextureType::Count - 1] = { nullptr }; -}; - -#endif diff --git a/application/sources/material_layer.cc b/application/sources/material_layer.cc deleted file mode 100644 index 93debe1a..00000000 --- a/application/sources/material_layer.cc +++ /dev/null @@ -1 +0,0 @@ -#include "material_layer.h" diff --git a/application/sources/material_layer.h b/application/sources/material_layer.h deleted file mode 100644 index 9d7cacba..00000000 --- a/application/sources/material_layer.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_LAYER_H_ -#define DUST3D_APPLICATION_MATERIAL_LAYER_H_ - -#include -#include -#include - -class MaterialMap { -public: - dust3d::TextureType forWhat; - dust3d::Uuid imageId; -}; - -class MaterialLayer { -public: - std::vector maps; - float tileScale = 1.0; -}; - -#endif diff --git a/application/sources/material_list_widget.cc b/application/sources/material_list_widget.cc deleted file mode 100644 index 52045288..00000000 --- a/application/sources/material_list_widget.cc +++ /dev/null @@ -1,308 +0,0 @@ -#include "material_list_widget.h" -#include "document.h" -#include -#include -#include -#include -#include -#include - -MaterialListWidget::MaterialListWidget(const Document* document, QWidget* parent) - : QTreeWidget(parent) - , m_document(document) -{ - setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); - setFocusPolicy(Qt::NoFocus); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - setAutoScroll(false); - - setHeaderHidden(true); - - QPalette palette = this->palette(); - palette.setColor(QPalette::Window, Qt::transparent); - palette.setColor(QPalette::Base, Qt::transparent); - setPalette(palette); - - setStyleSheet("QTreeView {qproperty-indentation: 0;}"); - - setContentsMargins(0, 0, 0, 0); - - connect(document, &Document::materialListChanged, this, &MaterialListWidget::reload); - connect(document, &Document::cleanup, this, &MaterialListWidget::removeAllContent); - - connect(this, &MaterialListWidget::removeMaterial, document, &Document::removeMaterial); - - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, &QTreeWidget::customContextMenuRequested, this, &MaterialListWidget::showContextMenu); - - reload(); -} - -void MaterialListWidget::enableMultipleSelection(bool enabled) -{ - m_multipleSelectionEnabled = enabled; -} - -void MaterialListWidget::materialRemoved(dust3d::Uuid materialId) -{ - if (m_currentSelectedMaterialId == materialId) - m_currentSelectedMaterialId = dust3d::Uuid(); - m_selectedMaterialIds.erase(materialId); - m_itemMap.erase(materialId); -} - -void MaterialListWidget::updateMaterialSelectState(dust3d::Uuid materialId, bool selected) -{ - auto findItemResult = m_itemMap.find(materialId); - if (findItemResult == m_itemMap.end()) { - qDebug() << "Find material item failed:" << materialId; - return; - } - MaterialWidget* materialWidget = (MaterialWidget*)itemWidget(findItemResult->second.first, findItemResult->second.second); - materialWidget->updateCheckedState(selected); -} - -void MaterialListWidget::selectMaterial(dust3d::Uuid materialId, bool multiple) -{ - if (multiple) { - if (!m_currentSelectedMaterialId.isNull()) { - m_selectedMaterialIds.insert(m_currentSelectedMaterialId); - m_currentSelectedMaterialId = dust3d::Uuid(); - } - if (m_selectedMaterialIds.find(materialId) != m_selectedMaterialIds.end()) { - updateMaterialSelectState(materialId, false); - m_selectedMaterialIds.erase(materialId); - } else { - if (m_multipleSelectionEnabled || m_selectedMaterialIds.empty()) { - updateMaterialSelectState(materialId, true); - m_selectedMaterialIds.insert(materialId); - } - } - if (m_selectedMaterialIds.size() > 1) { - return; - } - if (m_selectedMaterialIds.size() == 1) - materialId = *m_selectedMaterialIds.begin(); - else { - materialId = dust3d::Uuid(); - emit currentSelectedMaterialChanged(materialId); - } - } - if (!m_selectedMaterialIds.empty()) { - for (const auto& id : m_selectedMaterialIds) { - updateMaterialSelectState(id, false); - } - m_selectedMaterialIds.clear(); - } - if (m_currentSelectedMaterialId != materialId) { - if (!m_currentSelectedMaterialId.isNull()) { - updateMaterialSelectState(m_currentSelectedMaterialId, false); - } - m_currentSelectedMaterialId = materialId; - if (!m_currentSelectedMaterialId.isNull()) { - updateMaterialSelectState(m_currentSelectedMaterialId, true); - } - emit currentSelectedMaterialChanged(m_currentSelectedMaterialId); - } -} - -void MaterialListWidget::mousePressEvent(QMouseEvent* event) -{ - QModelIndex itemIndex = indexAt(event->pos()); - QTreeView::mousePressEvent(event); - if (event->button() == Qt::LeftButton) { - bool multiple = QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier); - if (itemIndex.isValid()) { - QTreeWidgetItem* item = itemFromIndex(itemIndex); - auto materialId = dust3d::Uuid(item->data(itemIndex.column(), Qt::UserRole).toString().toUtf8().constData()); - if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) { - bool startAdd = false; - bool stopAdd = false; - std::vector waitQueue; - for (const auto& childId : m_document->materialIdList) { - if (m_shiftStartMaterialId == childId || materialId == childId) { - if (startAdd) { - stopAdd = true; - } else { - startAdd = true; - } - } - if (startAdd) - waitQueue.push_back(childId); - if (stopAdd) - break; - } - if (stopAdd && !waitQueue.empty()) { - if (!m_selectedMaterialIds.empty()) { - for (const auto& id : m_selectedMaterialIds) { - updateMaterialSelectState(id, false); - } - m_selectedMaterialIds.clear(); - } - if (!m_currentSelectedMaterialId.isNull()) { - m_currentSelectedMaterialId = dust3d::Uuid(); - } - for (const auto& waitId : waitQueue) { - selectMaterial(waitId, true); - } - } - return; - } else { - m_shiftStartMaterialId = materialId; - } - selectMaterial(materialId, multiple); - return; - } - if (!multiple) - selectMaterial(dust3d::Uuid()); - } -} - -bool MaterialListWidget::isMaterialSelected(dust3d::Uuid materialId) -{ - return (m_currentSelectedMaterialId == materialId || m_selectedMaterialIds.find(materialId) != m_selectedMaterialIds.end()); -} - -void MaterialListWidget::showContextMenu(const QPoint& pos) -{ - if (!m_hasContextMenu) - return; - - QMenu contextMenu(this); - - std::set unorderedMaterialIds = m_selectedMaterialIds; - if (!m_currentSelectedMaterialId.isNull()) - unorderedMaterialIds.insert(m_currentSelectedMaterialId); - - std::vector materialIds; - for (const auto& cand : m_document->materialIdList) { - if (unorderedMaterialIds.find(cand) != unorderedMaterialIds.end()) - materialIds.push_back(cand); - } - - QAction modifyAction(tr("Modify"), this); - if (materialIds.size() == 1) { - connect(&modifyAction, &QAction::triggered, this, [=]() { - emit modifyMaterial(*materialIds.begin()); - }); - contextMenu.addAction(&modifyAction); - } - - QAction copyAction(tr("Copy"), this); - if (!materialIds.empty()) { - connect(©Action, &QAction::triggered, this, &MaterialListWidget::copy); - contextMenu.addAction(©Action); - } - - QAction pasteAction(tr("Paste"), this); - if (m_document->hasPastableMaterialsInClipboard()) { - connect(&pasteAction, &QAction::triggered, m_document, &Document::paste); - contextMenu.addAction(&pasteAction); - } - - QAction deleteAction(tr("Delete"), this); - if (!materialIds.empty()) { - connect(&deleteAction, &QAction::triggered, [=]() { - for (const auto& materialId : materialIds) - emit removeMaterial(materialId); - }); - contextMenu.addAction(&deleteAction); - } - - contextMenu.exec(mapToGlobal(pos)); -} - -void MaterialListWidget::resizeEvent(QResizeEvent* event) -{ - QTreeWidget::resizeEvent(event); - if (calculateColumnCount() != columnCount()) - reload(); -} - -int MaterialListWidget::calculateColumnCount() -{ - if (nullptr == parentWidget()) - return 0; - - int columns = parentWidget()->width() / Theme::materialPreviewImageSize; - if (0 == columns) - columns = 1; - return columns; -} - -void MaterialListWidget::reload() -{ - removeAllContent(); - - int columns = calculateColumnCount(); - if (0 == columns) - return; - - int columnWidth = parentWidget()->width() / columns; - - //qDebug() << "parentWidth:" << parentWidget()->width() << "columnWidth:" << columnWidth << "columns:" << columns; - - setColumnCount(columns); - for (int i = 0; i < columns; i++) - setColumnWidth(i, columnWidth); - - std::vector orderedMaterialIdList = m_document->materialIdList; - std::sort(orderedMaterialIdList.begin(), orderedMaterialIdList.end(), [&](const dust3d::Uuid& firstMaterialId, const dust3d::Uuid& secondMaterialId) { - const auto* firstMaterial = m_document->findMaterial(firstMaterialId); - const auto* secondMaterial = m_document->findMaterial(secondMaterialId); - if (nullptr == firstMaterial || nullptr == secondMaterial) - return false; - return QString::compare(firstMaterial->name, secondMaterial->name, Qt::CaseInsensitive) < 0; - }); - - decltype(orderedMaterialIdList.size()) materialIndex = 0; - while (materialIndex < orderedMaterialIdList.size()) { - QTreeWidgetItem* item = new QTreeWidgetItem(this); - item->setFlags((item->flags() | Qt::ItemIsEnabled) & ~(Qt::ItemIsSelectable) & ~(Qt::ItemIsEditable)); - for (int col = 0; col < columns && materialIndex < orderedMaterialIdList.size(); col++, materialIndex++) { - const auto& materialId = orderedMaterialIdList[materialIndex]; - item->setSizeHint(col, QSize(columnWidth, MaterialWidget::preferredHeight() + 2)); - item->setData(col, Qt::UserRole, QString(materialId.toString().c_str())); - MaterialWidget* widget = new MaterialWidget(m_document, materialId); - connect(widget, &MaterialWidget::modifyMaterial, this, &MaterialListWidget::modifyMaterial); - setItemWidget(item, col, widget); - widget->reload(); - widget->updateCheckedState(isMaterialSelected(materialId)); - m_itemMap[materialId] = std::make_pair(item, col); - } - invisibleRootItem()->addChild(item); - } -} - -void MaterialListWidget::setHasContextMenu(bool hasContextMenu) -{ - m_hasContextMenu = hasContextMenu; -} - -void MaterialListWidget::removeAllContent() -{ - m_itemMap.clear(); - clear(); -} - -void MaterialListWidget::copy() -{ - if (m_selectedMaterialIds.empty() && m_currentSelectedMaterialId.isNull()) - return; - - std::set limitMaterialIds = m_selectedMaterialIds; - if (!m_currentSelectedMaterialId.isNull()) - limitMaterialIds.insert(m_currentSelectedMaterialId); - - std::set emptySet; - - dust3d::Snapshot snapshot; - m_document->toSnapshot(&snapshot, emptySet, DocumentToSnapshotFor::Materials, - limitMaterialIds); - - std::string snapshotXml; - dust3d::saveSnapshotToXmlString(snapshot, snapshotXml); - QClipboard* clipboard = QApplication::clipboard(); - clipboard->setText(snapshotXml.c_str()); -} diff --git a/application/sources/material_list_widget.h b/application/sources/material_list_widget.h deleted file mode 100644 index db8b4ad3..00000000 --- a/application/sources/material_list_widget.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_LIST_WIDGET_H_ -#define DUST3D_APPLICATION_MATERIAL_LIST_WIDGET_H_ - -#include "material_widget.h" -#include -#include -#include - -class Document; - -class MaterialListWidget : public QTreeWidget { - Q_OBJECT -signals: - void removeMaterial(dust3d::Uuid materialId); - void modifyMaterial(dust3d::Uuid materialId); - void cornerButtonClicked(dust3d::Uuid materialId); - void currentSelectedMaterialChanged(dust3d::Uuid materialId); - -public: - MaterialListWidget(const Document* document, QWidget* parent = nullptr); - bool isMaterialSelected(dust3d::Uuid materialId); - void enableMultipleSelection(bool enabled); -public slots: - void reload(); - void removeAllContent(); - void materialRemoved(dust3d::Uuid materialId); - void showContextMenu(const QPoint& pos); - void selectMaterial(dust3d::Uuid materialId, bool multiple = false); - void copy(); - void setHasContextMenu(bool hasContextMenu); - -protected: - void resizeEvent(QResizeEvent* event) override; - void mousePressEvent(QMouseEvent* event) override; - -private: - int calculateColumnCount(); - void updateMaterialSelectState(dust3d::Uuid materialId, bool selected); - const Document* m_document = nullptr; - std::map> m_itemMap; - std::set m_selectedMaterialIds; - dust3d::Uuid m_currentSelectedMaterialId; - dust3d::Uuid m_shiftStartMaterialId; - bool m_hasContextMenu = true; - bool m_multipleSelectionEnabled = true; -}; - -#endif diff --git a/application/sources/material_manage_widget.cc b/application/sources/material_manage_widget.cc deleted file mode 100644 index 8905cd8f..00000000 --- a/application/sources/material_manage_widget.cc +++ /dev/null @@ -1,64 +0,0 @@ -#include "material_manage_widget.h" -#include "document.h" -#include "info_label.h" -#include "material_edit_widget.h" -#include "theme.h" -#include -#include -#include - -MaterialManageWidget::MaterialManageWidget(const Document* document, QWidget* parent) - : QWidget(parent) - , m_document(document) -{ - QPushButton* addMaterialButton = new QPushButton(Theme::awesome()->icon(fa::plus), tr("Add Material...")); - - connect(addMaterialButton, &QPushButton::clicked, this, &MaterialManageWidget::showAddMaterialDialog); - - QHBoxLayout* toolsLayout = new QHBoxLayout; - toolsLayout->addWidget(addMaterialButton); - - m_materialListWidget = new MaterialListWidget(document); - connect(m_materialListWidget, &MaterialListWidget::modifyMaterial, this, &MaterialManageWidget::showMaterialDialog); - - QVBoxLayout* mainLayout = new QVBoxLayout; - mainLayout->addLayout(toolsLayout); - mainLayout->addWidget(m_materialListWidget); - - setLayout(mainLayout); -} - -MaterialListWidget* MaterialManageWidget::materialListWidget() -{ - return m_materialListWidget; -} - -QSize MaterialManageWidget::sizeHint() const -{ - return QSize(Theme::sidebarPreferredWidth, 0); -} - -void MaterialManageWidget::showAddMaterialDialog() -{ - showMaterialDialog(dust3d::Uuid()); -} - -void MaterialManageWidget::showMaterialDialog(dust3d::Uuid materialId) -{ - MaterialEditWidget* materialEditWidget = new MaterialEditWidget(m_document); - materialEditWidget->setAttribute(Qt::WA_DeleteOnClose); - if (!materialId.isNull()) { - const Material* material = m_document->findMaterial(materialId); - if (nullptr != material) { - materialEditWidget->setEditMaterialId(materialId); - materialEditWidget->setEditMaterialName(material->name); - materialEditWidget->setEditMaterialLayers(material->layers); - materialEditWidget->clearUnsaveState(); - } - } - materialEditWidget->show(); - connect(materialEditWidget, &QDialog::destroyed, [=]() { - emit unregisterDialog((QWidget*)materialEditWidget); - }); - emit registerDialog((QWidget*)materialEditWidget); -} diff --git a/application/sources/material_manage_widget.h b/application/sources/material_manage_widget.h deleted file mode 100644 index 9310e609..00000000 --- a/application/sources/material_manage_widget.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_MANAGE_WIDGET_H_ -#define DUST3D_APPLICATION_MATERIAL_MANAGE_WIDGET_H_ - -#include "material_list_widget.h" -#include - -class Document; - -class MaterialManageWidget : public QWidget { - Q_OBJECT -signals: - void registerDialog(QWidget* widget); - void unregisterDialog(QWidget* widget); - -public: - MaterialManageWidget(const Document* document, QWidget* parent = nullptr); - MaterialListWidget* materialListWidget(); - -protected: - virtual QSize sizeHint() const; -public slots: - void showAddMaterialDialog(); - void showMaterialDialog(dust3d::Uuid materialId); - -private: - const Document* m_document = nullptr; - MaterialListWidget* m_materialListWidget = nullptr; -}; - -#endif diff --git a/application/sources/material_previews_generator.cc b/application/sources/material_previews_generator.cc deleted file mode 100644 index a0857a05..00000000 --- a/application/sources/material_previews_generator.cc +++ /dev/null @@ -1,131 +0,0 @@ -#include "material_previews_generator.h" -#include "image_forever.h" -#include "mesh_generator.h" -#include "mesh_result_post_processor.h" -#include "texture_generator.h" -#include -#include -#include -#include -#include -#include - -MaterialPreviewsGenerator::MaterialPreviewsGenerator() -{ -} - -MaterialPreviewsGenerator::~MaterialPreviewsGenerator() -{ - for (auto& item : m_previews) { - delete item.second; - } -} - -void MaterialPreviewsGenerator::addMaterial(dust3d::Uuid materialId, const std::vector& layers) -{ - m_materials.push_back({ materialId, layers }); -} - -const std::set& MaterialPreviewsGenerator::generatedPreviewMaterialIds() -{ - return m_generatedMaterialIds; -} - -ModelMesh* MaterialPreviewsGenerator::takePreview(dust3d::Uuid materialId) -{ - ModelMesh* resultMesh = m_previews[materialId]; - m_previews[materialId] = nullptr; - return resultMesh; -} - -void MaterialPreviewsGenerator::generate() -{ - dust3d::Snapshot* snapshot = new dust3d::Snapshot; - - QFile file(":/resources/material-demo-model.ds3"); - file.open(QFile::ReadOnly); - QByteArray fileData = file.readAll(); - - std::vector partIds; - dust3d::Ds3FileReader ds3Reader((const std::uint8_t*)fileData.data(), fileData.size()); - for (int i = 0; i < (int)ds3Reader.items().size(); ++i) { - dust3d::Ds3ReaderItem item = ds3Reader.items().at(i); - if (item.type == "model") { - std::vector data; - ds3Reader.loadItem(item.name, &data); - std::string xmlString((char*)data.data(), data.size()); - dust3d::loadSnapshotFromXmlString(snapshot, (char*)xmlString.c_str()); - for (const auto& item : snapshot->parts) { - partIds.push_back(dust3d::Uuid(item.first)); - } - } - } - - dust3d::MeshGenerator::GeneratedCacheContext* cacheContext = new dust3d::MeshGenerator::GeneratedCacheContext(); - MeshGenerator* meshGenerator = new MeshGenerator(snapshot); - meshGenerator->setGeneratedCacheContext(cacheContext); - - meshGenerator->generate(); - for (const auto& mirror : cacheContext->partMirrorIdMap) { - partIds.push_back(dust3d::Uuid(mirror.first)); - } - - dust3d::Object* object = meshGenerator->takeObject(); - if (nullptr != object) { - MeshResultPostProcessor* poseProcessor = new MeshResultPostProcessor(*object); - poseProcessor->poseProcess(); - delete object; - object = poseProcessor->takePostProcessedObject(); - delete poseProcessor; - } - - if (nullptr != object) { - for (const auto& material : m_materials) { - TextureGenerator* textureGenerator = new TextureGenerator(*object); - for (const auto& layer : material.second) { - for (const auto& mapItem : layer.maps) { - const QImage* image = ImageForever::get(mapItem.imageId); - if (nullptr == image) - continue; - for (const auto& partId : partIds) { - if (dust3d::TextureType::BaseColor == mapItem.forWhat) - textureGenerator->addPartColorMap(partId, image, layer.tileScale); - else if (dust3d::TextureType::Normal == mapItem.forWhat) - textureGenerator->addPartNormalMap(partId, image, layer.tileScale); - else if (dust3d::TextureType::Metallic == mapItem.forWhat) - textureGenerator->addPartMetalnessMap(partId, image, layer.tileScale); - else if (dust3d::TextureType::Roughness == mapItem.forWhat) - textureGenerator->addPartRoughnessMap(partId, image, layer.tileScale); - else if (dust3d::TextureType::AmbientOcclusion == mapItem.forWhat) - textureGenerator->addPartAmbientOcclusionMap(partId, image, layer.tileScale); - } - } - } - textureGenerator->generate(); - ModelMesh* texturedResultMesh = textureGenerator->takeResultMesh(); - if (nullptr != texturedResultMesh) { - m_previews[material.first] = new ModelMesh(*texturedResultMesh); - m_generatedMaterialIds.insert(material.first); - delete texturedResultMesh; - } - delete textureGenerator; - } - } - - delete object; - - delete meshGenerator; - delete cacheContext; -} - -void MaterialPreviewsGenerator::process() -{ - QElapsedTimer countTimeConsumed; - countTimeConsumed.start(); - - generate(); - - qDebug() << "The material previews generation took" << countTimeConsumed.elapsed() << "milliseconds"; - - emit finished(); -} diff --git a/application/sources/material_previews_generator.h b/application/sources/material_previews_generator.h deleted file mode 100644 index 6f1fa2b6..00000000 --- a/application/sources/material_previews_generator.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_PREVIEWS_GENERATOR_H_ -#define DUST3D_APPLICATION_MATERIAL_PREVIEWS_GENERATOR_H_ - -#include "material_layer.h" -#include "model_mesh.h" -#include -#include -#include - -class MaterialPreviewsGenerator : public QObject { - Q_OBJECT -public: - MaterialPreviewsGenerator(); - ~MaterialPreviewsGenerator(); - void addMaterial(dust3d::Uuid materialId, const std::vector& layers); - const std::set& generatedPreviewMaterialIds(); - ModelMesh* takePreview(dust3d::Uuid materialId); - void generate(); -signals: - void finished(); -public slots: - void process(); - -private: - std::vector>> m_materials; - std::map m_previews; - std::set m_generatedMaterialIds; -}; - -#endif diff --git a/application/sources/material_widget.cc b/application/sources/material_widget.cc deleted file mode 100644 index 768e64d1..00000000 --- a/application/sources/material_widget.cc +++ /dev/null @@ -1,98 +0,0 @@ -#include "material_widget.h" -#include "document.h" -#include - -MaterialWidget::MaterialWidget(const Document* document, dust3d::Uuid materialId) - : m_materialId(materialId) - , m_document(document) -{ - setObjectName("MaterialFrame"); - - m_previewWidget = new ModelWidget(this); - m_previewWidget->setAttribute(Qt::WA_TransparentForMouseEvents); - m_previewWidget->setFixedSize(Theme::materialPreviewImageSize, Theme::materialPreviewImageSize); - m_previewWidget->enableMove(false); - m_previewWidget->enableZoom(false); - - m_nameLabel = new QLabel; - m_nameLabel->setAlignment(Qt::AlignCenter); - m_nameLabel->setStyleSheet("background: qlineargradient(x1:0.5 y1:-15.5, x2:0.5 y2:1, stop:0 " + Theme::white.name() + ", stop:1 #252525);"); - - QFont nameFont; - nameFont.setWeight(QFont::Light); - nameFont.setBold(false); - m_nameLabel->setFont(nameFont); - - QVBoxLayout* mainLayout = new QVBoxLayout; - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addStretch(); - mainLayout->addWidget(m_nameLabel); - - setLayout(mainLayout); - - setFixedSize(Theme::materialPreviewImageSize, MaterialWidget::preferredHeight()); - - connect(document, &Document::materialNameChanged, this, &MaterialWidget::updateName); - connect(document, &Document::materialPreviewChanged, this, &MaterialWidget::updatePreview); -} - -void MaterialWidget::resizeEvent(QResizeEvent* event) -{ - QWidget::resizeEvent(event); - m_previewWidget->move((width() - Theme::materialPreviewImageSize) / 2, 0); -} - -int MaterialWidget::preferredHeight() -{ - return Theme::materialPreviewImageSize; -} - -void MaterialWidget::reload() -{ - updatePreview(m_materialId); - updateName(m_materialId); -} - -void MaterialWidget::updatePreview(dust3d::Uuid materialId) -{ - if (materialId != m_materialId) - return; - const Material* material = m_document->findMaterial(m_materialId); - if (!material) { - qDebug() << "Material not found:" << m_materialId; - return; - } - ModelMesh* previewMesh = material->takePreviewMesh(); - m_previewWidget->updateMesh(previewMesh); -} - -void MaterialWidget::updateName(dust3d::Uuid materialId) -{ - if (materialId != m_materialId) - return; - const Material* material = m_document->findMaterial(m_materialId); - if (!material) { - qDebug() << "Material not found:" << m_materialId; - return; - } - m_nameLabel->setText(material->name); -} - -void MaterialWidget::updateCheckedState(bool checked) -{ - if (checked) - setStyleSheet("#MaterialFrame {border: 1px solid " + Theme::red.name() + ";}"); - else - setStyleSheet("#MaterialFrame {border: 1px solid transparent;}"); -} - -ModelWidget* MaterialWidget::previewWidget() -{ - return m_previewWidget; -} - -void MaterialWidget::mouseDoubleClickEvent(QMouseEvent* event) -{ - QFrame::mouseDoubleClickEvent(event); - emit modifyMaterial(m_materialId); -} diff --git a/application/sources/material_widget.h b/application/sources/material_widget.h deleted file mode 100644 index 4734ae58..00000000 --- a/application/sources/material_widget.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DUST3D_APPLICATION_MATERIAL_WIDGET_H_ -#define DUST3D_APPLICATION_MATERIAL_WIDGET_H_ - -#include "model_widget.h" -#include -#include -#include -#include - -class Document; - -class MaterialWidget : public QFrame { - Q_OBJECT -signals: - void modifyMaterial(dust3d::Uuid materialId); - -public: - MaterialWidget(const Document* document, dust3d::Uuid materialId); - static int preferredHeight(); - ModelWidget* previewWidget(); - -protected: - void mouseDoubleClickEvent(QMouseEvent* event) override; - void resizeEvent(QResizeEvent* event) override; -public slots: - void reload(); - void updatePreview(dust3d::Uuid materialId); - void updateName(dust3d::Uuid materialId); - void updateCheckedState(bool checked); - -private: - dust3d::Uuid m_materialId; - const Document* m_document = nullptr; - ModelWidget* m_previewWidget = nullptr; - QLabel* m_nameLabel = nullptr; -}; - -#endif diff --git a/application/sources/texture_generator.cc b/application/sources/texture_generator.cc deleted file mode 100644 index 6790fa5f..00000000 --- a/application/sources/texture_generator.cc +++ /dev/null @@ -1,702 +0,0 @@ -#include "texture_generator.h" -#include "debug.h" -#include "material.h" -#include "theme.h" -#include -#include -#include -#include -#include -#include -#include - -QColor TextureGenerator::m_defaultTextureColor = Qt::transparent; - -TextureGenerator::TextureGenerator(const dust3d::Object& object, dust3d::Snapshot* snapshot) - : m_snapshot(snapshot) -{ - m_object = new dust3d::Object(); - *m_object = object; -} - -TextureGenerator::~TextureGenerator() -{ - delete m_object; - delete m_resultTextureColorImage; - delete m_resultTextureNormalImage; - delete m_resultTextureRoughnessImage; - delete m_resultTextureMetalnessImage; - delete m_resultTextureAmbientOcclusionImage; - delete m_resultMesh; - delete m_snapshot; -} - -QImage* TextureGenerator::takeResultTextureColorImage() -{ - QImage* resultTextureColorImage = m_resultTextureColorImage; - m_resultTextureColorImage = nullptr; - return resultTextureColorImage; -} - -QImage* TextureGenerator::takeResultTextureNormalImage() -{ - QImage* resultTextureNormalImage = m_resultTextureNormalImage; - m_resultTextureNormalImage = nullptr; - return resultTextureNormalImage; -} - -QImage* TextureGenerator::takeResultTextureRoughnessImage() -{ - QImage* resultTextureRoughnessImage = m_resultTextureRoughnessImage; - m_resultTextureRoughnessImage = nullptr; - return resultTextureRoughnessImage; -} - -QImage* TextureGenerator::takeResultTextureMetalnessImage() -{ - QImage* resultTextureMetalnessImage = m_resultTextureMetalnessImage; - m_resultTextureMetalnessImage = nullptr; - return resultTextureMetalnessImage; -} - -QImage* TextureGenerator::takeResultTextureAmbientOcclusionImage() -{ - QImage* resultTextureAmbientOcclusionImage = m_resultTextureAmbientOcclusionImage; - m_resultTextureAmbientOcclusionImage = nullptr; - return resultTextureAmbientOcclusionImage; -} - -dust3d::Object* TextureGenerator::takeObject() -{ - dust3d::Object* object = m_object; - m_object = nullptr; - return object; -} - -ModelMesh* TextureGenerator::takeResultMesh() -{ - ModelMesh* resultMesh = m_resultMesh; - m_resultMesh = nullptr; - return resultMesh; -} - -void TextureGenerator::addPartColorMap(dust3d::Uuid partId, const QImage* image, float tileScale) -{ - if (nullptr == image) - return; - m_partColorTextureMap[partId] = std::make_pair(*image, tileScale); -} - -void TextureGenerator::addPartNormalMap(dust3d::Uuid partId, const QImage* image, float tileScale) -{ - if (nullptr == image) - return; - m_partNormalTextureMap[partId] = std::make_pair(*image, tileScale); -} - -void TextureGenerator::addPartMetalnessMap(dust3d::Uuid partId, const QImage* image, float tileScale) -{ - if (nullptr == image) - return; - m_partMetalnessTextureMap[partId] = std::make_pair(*image, tileScale); -} - -void TextureGenerator::addPartRoughnessMap(dust3d::Uuid partId, const QImage* image, float tileScale) -{ - if (nullptr == image) - return; - m_partRoughnessTextureMap[partId] = std::make_pair(*image, tileScale); -} - -void TextureGenerator::addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage* image, float tileScale) -{ - if (nullptr == image) - return; - m_partAmbientOcclusionTextureMap[partId] = std::make_pair(*image, tileScale); -} - -void TextureGenerator::prepare() -{ - if (nullptr == m_snapshot) - return; - - std::map updatedMaterialIdMap; - std::map updatedCountershadedMap; - for (const auto& partIt : m_snapshot->parts) { - dust3d::Uuid materialId; - auto materialIdIt = partIt.second.find("materialId"); - if (materialIdIt != partIt.second.end()) - materialId = dust3d::Uuid(materialIdIt->second); - dust3d::Uuid partId = dust3d::Uuid(partIt.first); - updatedMaterialIdMap.insert({ partId, materialId }); - updatedCountershadedMap.insert({ partId, - dust3d::String::isTrue(dust3d::String::valueOrEmpty(partIt.second, "countershaded")) }); - } - for (const auto& bmeshNode : m_object->nodes) { - - bool countershaded = bmeshNode.countershaded; - auto findUpdatedCountershadedMap = updatedCountershadedMap.find(bmeshNode.mirrorFromPartId.isNull() ? bmeshNode.partId : bmeshNode.mirrorFromPartId); - if (findUpdatedCountershadedMap != updatedCountershadedMap.end()) - countershaded = findUpdatedCountershadedMap->second; - if (countershaded) - m_countershadedPartIds.insert(bmeshNode.partId); - - for (size_t i = 0; i < (int)dust3d::TextureType::Count - 1; ++i) { - dust3d::TextureType forWhat = (dust3d::TextureType)(i + 1); - MaterialTextures materialTextures; - dust3d::Uuid materialId = bmeshNode.materialId; - auto findUpdatedMaterialIdResult = updatedMaterialIdMap.find(bmeshNode.mirrorFromPartId.isNull() ? bmeshNode.partId : bmeshNode.mirrorFromPartId); - if (findUpdatedMaterialIdResult != updatedMaterialIdMap.end()) - materialId = findUpdatedMaterialIdResult->second; - float tileScale = 1.0; - initializeMaterialTexturesFromSnapshot(*m_snapshot, materialId, materialTextures, tileScale); - const QImage* image = materialTextures.textureImages[i]; - if (nullptr != image) { - if (dust3d::TextureType::BaseColor == forWhat) - addPartColorMap(bmeshNode.partId, image, tileScale); - else if (dust3d::TextureType::Normal == forWhat) - addPartNormalMap(bmeshNode.partId, image, tileScale); - else if (dust3d::TextureType::Metallic == forWhat) - addPartMetalnessMap(bmeshNode.partId, image, tileScale); - else if (dust3d::TextureType::Roughness == forWhat) - addPartRoughnessMap(bmeshNode.partId, image, tileScale); - else if (dust3d::TextureType::AmbientOcclusion == forWhat) - addPartAmbientOcclusionMap(bmeshNode.partId, image, tileScale); - } - } - } -} - -bool TextureGenerator::hasTransparencySettings() -{ - return m_hasTransparencySettings; -} - -void TextureGenerator::generate() -{ - m_resultMesh = new ModelMesh(*m_object); - - if (nullptr == m_object->triangleVertexUvs()) - return; - if (nullptr == m_object->triangleSourceNodes()) - return; - if (nullptr == m_object->partUvRects()) - return; - - QElapsedTimer countTimeConsumed; - countTimeConsumed.start(); - - prepare(); - - bool hasNormalMap = false; - bool hasMetalnessMap = false; - bool hasRoughnessMap = false; - bool hasAmbientOcclusionMap = false; - - const auto& triangleVertexUvs = *m_object->triangleVertexUvs(); - const auto& triangleSourceNodes = *m_object->triangleSourceNodes(); - const auto& partUvRects = *m_object->partUvRects(); - const auto& triangleNormals = m_object->triangleNormals; - - std::map partColorMap; - std::map, const dust3d::ObjectNode*> nodeMap; - std::map partColorSolubilityMap; - std::map partMetalnessMap; - std::map partRoughnessMap; - for (const auto& item : m_object->nodes) { - if (!m_hasTransparencySettings) { - if (!qFuzzyCompare(1.0, item.color.alpha())) - m_hasTransparencySettings = true; - } - nodeMap.insert({ { item.partId, item.nodeId }, &item }); - partColorMap.insert({ item.partId, QColor(item.color.toString().c_str()) }); - partColorSolubilityMap.insert({ item.partId, item.colorSolubility }); - partMetalnessMap.insert({ item.partId, item.metalness }); - partRoughnessMap.insert({ item.partId, item.roughness }); - } - - m_resultTextureColorImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32); - m_resultTextureColorImage->fill(m_hasTransparencySettings ? m_defaultTextureColor : Qt::white); - - m_resultTextureNormalImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32); - m_resultTextureNormalImage->fill(QColor(128, 128, 255)); - - m_resultTextureMetalnessImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32); - m_resultTextureMetalnessImage->fill(Qt::black); - - m_resultTextureRoughnessImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32); - m_resultTextureRoughnessImage->fill(Qt::white); - - m_resultTextureAmbientOcclusionImage = new QImage(TextureGenerator::m_textureSize, TextureGenerator::m_textureSize, QImage::Format_ARGB32); - m_resultTextureAmbientOcclusionImage->fill(Qt::white); - - QColor borderColor = Qt::darkGray; - QPen pen(borderColor); - - QPainter texturePainter; - texturePainter.begin(m_resultTextureColorImage); - texturePainter.setRenderHint(QPainter::Antialiasing); - texturePainter.setRenderHint(QPainter::HighQualityAntialiasing); - - QPainter textureNormalPainter; - textureNormalPainter.begin(m_resultTextureNormalImage); - textureNormalPainter.setRenderHint(QPainter::Antialiasing); - textureNormalPainter.setRenderHint(QPainter::HighQualityAntialiasing); - - QPainter textureMetalnessPainter; - textureMetalnessPainter.begin(m_resultTextureMetalnessImage); - textureMetalnessPainter.setRenderHint(QPainter::Antialiasing); - textureMetalnessPainter.setRenderHint(QPainter::HighQualityAntialiasing); - - QPainter textureRoughnessPainter; - textureRoughnessPainter.begin(m_resultTextureRoughnessImage); - textureRoughnessPainter.setRenderHint(QPainter::Antialiasing); - textureRoughnessPainter.setRenderHint(QPainter::HighQualityAntialiasing); - - QPainter textureAmbientOcclusionPainter; - textureAmbientOcclusionPainter.begin(m_resultTextureAmbientOcclusionImage); - textureAmbientOcclusionPainter.setRenderHint(QPainter::Antialiasing); - textureAmbientOcclusionPainter.setRenderHint(QPainter::HighQualityAntialiasing); - - texturePainter.setPen(Qt::NoPen); - - for (const auto& it : partUvRects) { - const auto& partId = it.first; - const auto& rects = it.second; - auto findSourceColorResult = partColorMap.find(partId); - if (findSourceColorResult != partColorMap.end()) { - const auto& color = findSourceColorResult->second; - QBrush brush(color); - float fillExpandSize = 2; - for (const auto& rect : rects) { - QRectF translatedRect = { - rect.left() * TextureGenerator::m_textureSize - fillExpandSize, - rect.top() * TextureGenerator::m_textureSize - fillExpandSize, - rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2, - rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2 - }; - texturePainter.fillRect(translatedRect, brush); - } - } - } - - for (const auto& it : partUvRects) { - const auto& partId = it.first; - const auto& rects = it.second; - auto findMetalnessResult = partMetalnessMap.find(partId); - if (findMetalnessResult != partMetalnessMap.end()) { - if (qFuzzyCompare(findMetalnessResult->second, (float)0.0)) - continue; - const auto& color = QColor(findMetalnessResult->second * 255, - findMetalnessResult->second * 255, - findMetalnessResult->second * 255); - QBrush brush(color); - float fillExpandSize = 2; - for (const auto& rect : rects) { - QRectF translatedRect = { - rect.left() * TextureGenerator::m_textureSize - fillExpandSize, - rect.top() * TextureGenerator::m_textureSize - fillExpandSize, - rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2, - rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2 - }; - textureMetalnessPainter.fillRect(translatedRect, brush); - hasMetalnessMap = true; - } - } - } - - for (const auto& it : partUvRects) { - const auto& partId = it.first; - const auto& rects = it.second; - auto findRoughnessResult = partRoughnessMap.find(partId); - if (findRoughnessResult != partRoughnessMap.end()) { - if (qFuzzyCompare(findRoughnessResult->second, (float)1.0)) - continue; - const auto& color = QColor(findRoughnessResult->second * 255, - findRoughnessResult->second * 255, - findRoughnessResult->second * 255); - QBrush brush(color); - float fillExpandSize = 2; - for (const auto& rect : rects) { - QRectF translatedRect = { - rect.left() * TextureGenerator::m_textureSize - fillExpandSize, - rect.top() * TextureGenerator::m_textureSize - fillExpandSize, - rect.width() * TextureGenerator::m_textureSize + fillExpandSize * 2, - rect.height() * TextureGenerator::m_textureSize + fillExpandSize * 2 - }; - textureRoughnessPainter.fillRect(translatedRect, brush); - hasRoughnessMap = true; - } - } - } - - auto drawTexture = [&](const std::map>& 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, QPointF(rect.top(), rect.left())); - } else { - painter.drawTiledPixmap(translatedRect, pixmap, QPointF(rect.left(), rect.top())); - } - } - painter.setOpacity(1.0); - } - } - }; - - auto convertTextureImageToPixmap = [&](const std::map>& sourceMap, - std::map>& 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).mirrored(true, false); - targetMap[it.first] = std::make_pair(QPixmap::fromImage(scaledImage), - QPixmap::fromImage(rotatedImage)); - } - }; - - std::map> partColorTexturePixmaps; - std::map> partNormalTexturePixmaps; - std::map> partMetalnessTexturePixmaps; - std::map> partRoughnessTexturePixmaps; - std::map> 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 drawBySolubility = [&](const dust3d::Uuid& partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex, - const dust3d::Uuid& neighborPartId) { - const std::vector& uv = triangleVertexUvs[triangleIndex]; - const auto& allRects = partUvRects.find(partId); - if (allRects == partUvRects.end()) { - qDebug() << "Found part uv rects failed"; - return; - } - const auto& firstPoint = uv[firstVertexIndex]; - const auto& secondPoint = uv[secondVertexIndex]; - auto edgeLength = (firstPoint - secondPoint).length(); - 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; - if (qFuzzyIsNull(findNeighborColorSolubility->second)) - return; - const auto& findNeighborColor = partColorMap.find(neighborPartId); - if (findNeighborColor == partColorMap.end()) - return; - for (const auto& it : allRects->second) { - if (it.contains(firstPoint.x(), firstPoint.y()) || it.contains(secondPoint.x(), secondPoint.y())) { - float finalRadius = (it.width() + it.height()) * 0.5 * findNeighborColorSolubility->second; - if (finalRadius < edgeLength) - finalRadius = edgeLength; - dust3d::Rectangle fillTarget((middlePoint.x() - finalRadius), - (middlePoint.y() - finalRadius), - (finalRadius + finalRadius), - (finalRadius + finalRadius)); - auto clippedRect = it.intersected(fillTarget); - QRectF translatedRect = { - clippedRect.left() * TextureGenerator::m_textureSize, - clippedRect.top() * TextureGenerator::m_textureSize, - clippedRect.width() * TextureGenerator::m_textureSize, - 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; - - QImage tmpImage(translatedRect.width(), translatedRect.height(), QImage::Format_ARGB32); - QPixmap tmpPixmap = QPixmap::fromImage(tmpImage); - QPainter tmpPainter; - QRectF tmpImageFrame = QRectF(0, 0, translatedRect.width(), translatedRect.height()); - - // Fill tiled texture - tmpPainter.begin(&tmpPixmap); - tmpPainter.setOpacity(alpha); - if (it.width() < it.height()) { - tmpPainter.drawTiledPixmap(tmpImageFrame, rotatedPixmap, QPointF(translatedRect.top(), translatedRect.left())); - } else { - tmpPainter.drawTiledPixmap(tmpImageFrame, pixmap, translatedRect.topLeft()); - } - tmpPainter.setOpacity(1.0); - tmpPainter.end(); - - // Apply gradient - QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize - translatedRect.left(), - middlePoint.y() * TextureGenerator::m_textureSize - translatedRect.top()), - finalRadius * TextureGenerator::m_textureSize); - gradient.setColorAt(0.0, findNeighborColor->second); - gradient.setColorAt(1.0, Qt::transparent); - - tmpPainter.begin(&tmpPixmap); - tmpPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - tmpPainter.fillRect(tmpImageFrame, gradient); - tmpPainter.end(); - - texturePainter.drawPixmap(translatedRect, tmpPixmap, tmpImageFrame); - } else { - QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize, - middlePoint.y() * TextureGenerator::m_textureSize), - finalRadius * TextureGenerator::m_textureSize); - gradient.setColorAt(0.0, findNeighborColor->second); - gradient.setColorAt(1.0, Qt::transparent); - texturePainter.fillRect(translatedRect, gradient); - } - texturePainter.setOpacity(1.0); - break; - } - } - }; - - std::map, std::tuple> halfEdgeToTriangleMap; - for (size_t i = 0; i < m_object->triangles.size(); ++i) { - const auto& triangleIndices = m_object->triangles[i]; - if (triangleIndices.size() != 3) { - qDebug() << "Found invalid triangle indices"; - continue; - } - for (size_t j = 0; j < triangleIndices.size(); ++j) { - size_t k = (j + 1) % triangleIndices.size(); - halfEdgeToTriangleMap.insert(std::make_pair(std::make_pair(triangleIndices[j], triangleIndices[k]), - std::make_tuple(i, j, k))); - } - } - for (const auto& it : halfEdgeToTriangleMap) { - auto oppositeHalfEdge = std::make_pair(it.first.second, it.first.first); - const auto& opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge); - if (opposite == halfEdgeToTriangleMap.end()) - continue; - const std::pair& source = triangleSourceNodes[std::get<0>(it.second)]; - const std::pair& oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)]; - if (source.first == oppositeSource.first) - continue; - drawBySolubility(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first); - drawBySolubility(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first); - } - - // Draw belly white - texturePainter.setCompositionMode(QPainter::CompositionMode_SoftLight); - for (size_t triangleIndex = 0; triangleIndex < m_object->triangles.size(); ++triangleIndex) { - const auto& normal = triangleNormals[triangleIndex]; - const std::pair& source = triangleSourceNodes[triangleIndex]; - const auto& partId = source.first; - if (m_countershadedPartIds.find(partId) == m_countershadedPartIds.end()) - continue; - - const auto& allRects = partUvRects.find(partId); - if (allRects == partUvRects.end()) { - qDebug() << "Found part uv rects failed"; - continue; - } - - const auto& findObjectNode = nodeMap.find(source); - if (findObjectNode == nodeMap.end()) - continue; - const dust3d::ObjectNode* objectNode = findObjectNode->second; - if (qAbs(dust3d::Vector3::dotProduct(objectNode->direction, dust3d::Vector3(0, 1, 0))) >= 0.707) { - if (dust3d::Vector3::dotProduct(normal, dust3d::Vector3(0, 0, 1)) <= 0.0) - continue; - } else { - if (dust3d::Vector3::dotProduct(normal, dust3d::Vector3(0, -1, 0)) <= 0.0) - continue; - } - - const auto& triangleIndices = m_object->triangles[triangleIndex]; - if (triangleIndices.size() != 3) { - qDebug() << "Found invalid triangle indices"; - continue; - } - - const std::vector& uv = triangleVertexUvs[triangleIndex]; - dust3d::Vector2 middlePoint = (uv[0] + uv[1] + uv[2]) / 3.0; - float finalRadius = ((uv[0] - uv[1]).length() + (uv[1] - uv[2]).length() + (uv[2] - uv[0]).length()) / 3.0; - QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize, - middlePoint.y() * TextureGenerator::m_textureSize), - finalRadius * TextureGenerator::m_textureSize); - gradient.setColorAt(0.0, Qt::white); - gradient.setColorAt(1.0, Qt::transparent); - for (const auto& it : allRects->second) { - if (it.contains(middlePoint.x(), middlePoint.y())) { - dust3d::Rectangle fillTarget((middlePoint.x() - finalRadius), - (middlePoint.y() - finalRadius), - (finalRadius + finalRadius), - (finalRadius + finalRadius)); - auto clippedRect = it.intersected(fillTarget); - QRectF translatedRect = { - clippedRect.left() * TextureGenerator::m_textureSize, - clippedRect.top() * TextureGenerator::m_textureSize, - clippedRect.width() * TextureGenerator::m_textureSize, - clippedRect.height() * TextureGenerator::m_textureSize - }; - texturePainter.fillRect(translatedRect, gradient); - } - } - - // Fill the neighbor halfedges - for (int i = 0; i < 3; ++i) { - int j = (i + 1) % 3; - auto oppositeHalfEdge = std::make_pair(triangleIndices[j], triangleIndices[i]); - const auto& opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge); - if (opposite == halfEdgeToTriangleMap.end()) - continue; - auto oppositeTriangleIndex = std::get<0>(opposite->second); - const std::pair& oppositeSource = triangleSourceNodes[oppositeTriangleIndex]; - if (partId == oppositeSource.first) - continue; - const auto& oppositeAllRects = partUvRects.find(oppositeSource.first); - if (oppositeAllRects == partUvRects.end()) { - qDebug() << "Found part uv rects failed"; - continue; - } - const std::vector& oppositeUv = triangleVertexUvs[oppositeTriangleIndex]; - dust3d::Vector2 oppositeMiddlePoint = (oppositeUv[std::get<1>(opposite->second)] + oppositeUv[std::get<2>(opposite->second)]) * 0.5; - QRadialGradient oppositeGradient(QPointF(oppositeMiddlePoint.x() * TextureGenerator::m_textureSize, - oppositeMiddlePoint.y() * TextureGenerator::m_textureSize), - finalRadius * TextureGenerator::m_textureSize); - oppositeGradient.setColorAt(0.0, Qt::white); - oppositeGradient.setColorAt(1.0, Qt::transparent); - for (const auto& it : oppositeAllRects->second) { - if (it.contains(oppositeMiddlePoint.x(), oppositeMiddlePoint.y())) { - dust3d::Rectangle fillTarget((oppositeMiddlePoint.x() - finalRadius), - (oppositeMiddlePoint.y() - finalRadius), - (finalRadius + finalRadius), - (finalRadius + finalRadius)); - auto clippedRect = it.intersected(fillTarget); - QRectF translatedRect = { - clippedRect.left() * TextureGenerator::m_textureSize, - clippedRect.top() * TextureGenerator::m_textureSize, - clippedRect.width() * TextureGenerator::m_textureSize, - clippedRect.height() * TextureGenerator::m_textureSize - }; - texturePainter.fillRect(translatedRect, oppositeGradient); - } - } - } - } - - hasNormalMap = !m_partNormalTextureMap.empty(); - if (!m_partMetalnessTextureMap.empty()) - hasMetalnessMap = true; - if (!m_partRoughnessTextureMap.empty()) - hasRoughnessMap = true; - hasAmbientOcclusionMap = !m_partAmbientOcclusionTextureMap.empty(); - - texturePainter.end(); - textureNormalPainter.end(); - textureMetalnessPainter.end(); - textureRoughnessPainter.end(); - textureAmbientOcclusionPainter.end(); - - if (!hasNormalMap) { - delete m_resultTextureNormalImage; - m_resultTextureNormalImage = nullptr; - } - - if (!hasMetalnessMap && !hasRoughnessMap && !hasAmbientOcclusionMap) { - delete m_resultTextureMetalnessImage; - m_resultTextureMetalnessImage = nullptr; - - delete m_resultTextureRoughnessImage; - m_resultTextureRoughnessImage = nullptr; - - delete m_resultTextureAmbientOcclusionImage; - m_resultTextureAmbientOcclusionImage = nullptr; - } - - m_resultMesh->setTextureImage(new QImage(*m_resultTextureColorImage)); - if (nullptr != m_resultTextureNormalImage) - m_resultMesh->setNormalMapImage(new QImage(*m_resultTextureNormalImage)); - if (hasMetalnessMap || hasRoughnessMap || hasAmbientOcclusionMap) { - m_resultMesh->setMetalnessRoughnessAmbientOcclusionMapImage(combineMetalnessRoughnessAmbientOcclusionImages( - m_resultTextureMetalnessImage, - m_resultTextureRoughnessImage, - m_resultTextureAmbientOcclusionImage)); - m_resultMesh->setHasMetalnessInImage(hasMetalnessMap); - m_resultMesh->setHasRoughnessInImage(hasRoughnessMap); - m_resultMesh->setHasAmbientOcclusionInImage(hasAmbientOcclusionMap); - } - - qDebug() << "The texture[" << TextureGenerator::m_textureSize << "x" << TextureGenerator::m_textureSize << "] generation took" << countTimeConsumed.elapsed() << "milliseconds"; -} - -QImage* TextureGenerator::combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage, - QImage* roughnessImage, - QImage* ambientOcclusionImage) -{ - QImage* textureMetalnessRoughnessAmbientOcclusionImage = nullptr; - if (nullptr != metalnessImage || nullptr != roughnessImage || nullptr != ambientOcclusionImage) { - int textureSize = 0; - if (nullptr != metalnessImage) - textureSize = metalnessImage->height(); - if (nullptr != roughnessImage) - textureSize = roughnessImage->height(); - if (nullptr != ambientOcclusionImage) - textureSize = ambientOcclusionImage->height(); - if (textureSize > 0) { - textureMetalnessRoughnessAmbientOcclusionImage = new QImage(textureSize, textureSize, QImage::Format_ARGB32); - textureMetalnessRoughnessAmbientOcclusionImage->fill(QColor(255, 255, 0)); - for (int row = 0; row < textureMetalnessRoughnessAmbientOcclusionImage->height(); ++row) { - for (int col = 0; col < textureMetalnessRoughnessAmbientOcclusionImage->width(); ++col) { - QColor color(255, 255, 0); - if (nullptr != metalnessImage) - color.setBlue(qGray(metalnessImage->pixel(col, row))); - if (nullptr != roughnessImage) - color.setGreen(qGray(roughnessImage->pixel(col, row))); - if (nullptr != ambientOcclusionImage) - color.setRed(qGray(ambientOcclusionImage->pixel(col, row))); - textureMetalnessRoughnessAmbientOcclusionImage->setPixelColor(col, row, color); - } - } - } - } - return textureMetalnessRoughnessAmbientOcclusionImage; -} - -void TextureGenerator::process() -{ - generate(); - - emit finished(); -} diff --git a/application/sources/texture_generator.h b/application/sources/texture_generator.h deleted file mode 100644 index 30984ad1..00000000 --- a/application/sources/texture_generator.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef DUST3D_APPLICATION_TEXTURE_GENERATOR_H_ -#define DUST3D_APPLICATION_TEXTURE_GENERATOR_H_ - -#include "model_mesh.h" -#include -#include -#include -#include -#include -#include -#include - -class TextureGenerator : public QObject { - Q_OBJECT -public: - TextureGenerator(const dust3d::Object& object, dust3d::Snapshot* snapshot = nullptr); - ~TextureGenerator(); - QImage* takeResultTextureColorImage(); - QImage* takeResultTextureNormalImage(); - QImage* takeResultTextureRoughnessImage(); - QImage* takeResultTextureMetalnessImage(); - QImage* takeResultTextureAmbientOcclusionImage(); - dust3d::Object* takeObject(); - ModelMesh* takeResultMesh(); - bool hasTransparencySettings(); - void addPartColorMap(dust3d::Uuid partId, const QImage* image, float tileScale); - void addPartNormalMap(dust3d::Uuid partId, const QImage* image, float tileScale); - void addPartMetalnessMap(dust3d::Uuid partId, const QImage* image, float tileScale); - void addPartRoughnessMap(dust3d::Uuid partId, const QImage* image, float tileScale); - void addPartAmbientOcclusionMap(dust3d::Uuid partId, const QImage* image, float tileScale); - void generate(); - static QImage* combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage, - QImage* roughnessImage, - QImage* ambientOcclusionImage); -signals: - void finished(); -public slots: - void process(); - -public: - static QColor m_defaultTextureColor; - -private: - void prepare(); - -private: - dust3d::Object* m_object = nullptr; - QImage* m_resultTextureColorImage = nullptr; - QImage* m_resultTextureNormalImage = nullptr; - QImage* m_resultTextureRoughnessImage = nullptr; - QImage* m_resultTextureMetalnessImage = nullptr; - QImage* m_resultTextureAmbientOcclusionImage = nullptr; - ModelMesh* m_resultMesh = nullptr; - std::map> m_partColorTextureMap; - std::map> m_partNormalTextureMap; - std::map> m_partMetalnessTextureMap; - std::map> m_partRoughnessTextureMap; - std::map> m_partAmbientOcclusionTextureMap; - std::set m_countershadedPartIds; - dust3d::Snapshot* m_snapshot = nullptr; - bool m_hasTransparencySettings = false; - int m_textureSize = 1024; -}; - -#endif diff --git a/application/sources/theme.cc b/application/sources/theme.cc index 22304c1f..92d19142 100644 --- a/application/sources/theme.cc +++ b/application/sources/theme.cc @@ -20,7 +20,6 @@ int Theme::toolIconSize = 0; int Theme::miniIconFontSize = 0; int Theme::miniIconSize = 0; int Theme::partPreviewImageSize = 0; -int Theme::materialPreviewImageSize = 0; int Theme::sidebarPreferredWidth = 0; int Theme::previewIconBorderSize = 0; int Theme::previewIconMargin = 0; @@ -57,7 +56,6 @@ void Theme::initialize() Theme::miniIconSize = (int)(Theme::miniIconFontSize * 1.67); Theme::partPreviewImageSize = (Theme::miniIconSize * 2.3); Theme::sidebarPreferredWidth = Theme::partPreviewImageSize * 4.5; - Theme::materialPreviewImageSize = Theme::sidebarPreferredWidth * 0.4; Theme::previewIconBorderSize = std::max(1, Theme::partPreviewImageSize / 20); Theme::previewIconMargin = std::max(1, Theme::previewIconBorderSize / 2); Theme::previewIconBorderRadius = std::max(3, Theme::partPreviewImageSize / 10); diff --git a/application/sources/theme.h b/application/sources/theme.h index ca21d8c0..124d0046 100644 --- a/application/sources/theme.h +++ b/application/sources/theme.h @@ -25,7 +25,6 @@ public: static int miniIconFontSize; static int miniIconSize; static int partPreviewImageSize; - static int materialPreviewImageSize; static int sidebarPreferredWidth; static int previewIconBorderSize; static int previewIconMargin; diff --git a/application/sources/uv_map_generator.cc b/application/sources/uv_map_generator.cc index 45e59a74..532c32e0 100644 --- a/application/sources/uv_map_generator.cc +++ b/application/sources/uv_map_generator.cc @@ -1,7 +1,11 @@ #include "uv_map_generator.h" #include "image_forever.h" +#include +#include #include +size_t UvMapGenerator::m_textureSize = 1024; + UvMapGenerator::UvMapGenerator(std::unique_ptr object, std::unique_ptr snapshot) : m_object(std::move(object)) , m_snapshot(std::move(snapshot)) @@ -14,16 +18,53 @@ void UvMapGenerator::process() emit finished(); } +std::unique_ptr UvMapGenerator::takeResultTextureColorImage() +{ + return std::move(m_textureColorImage); +} + +std::unique_ptr UvMapGenerator::takeResultTextureNormalImage() +{ + return std::move(m_textureNormalImage); +} + +std::unique_ptr UvMapGenerator::takeResultTextureRoughnessImage() +{ + return std::move(m_textureRoughnessImage); +} + +std::unique_ptr UvMapGenerator::takeResultTextureMetalnessImage() +{ + return std::move(m_textureMetalnessImage); +} + +std::unique_ptr UvMapGenerator::takeResultTextureAmbientOcclusionImage() +{ + return std::move(m_textureAmbientOcclusionImage); +} + +std::unique_ptr UvMapGenerator::takeResultMesh() +{ + return std::move(m_mesh); +} + std::unique_ptr UvMapGenerator::takeObject() { return std::move(m_object); } +bool UvMapGenerator::hasTransparencySettings() const +{ + return m_hasTransparencySettings; +} + void UvMapGenerator::generate() { if (nullptr == m_object) return; + m_mesh = std::make_unique(*m_object); + if (nullptr == m_snapshot) return; @@ -50,5 +91,78 @@ void UvMapGenerator::generate() m_mapPacker->pack(); - // TODO: + m_textureColorImage = std::make_unique(UvMapGenerator::m_textureSize, UvMapGenerator::m_textureSize, QImage::Format_ARGB32); + m_textureColorImage->fill(Qt::white); + + QPainter colorTexturePainter; + colorTexturePainter.begin(m_textureColorImage.get()); + colorTexturePainter.setRenderHint(QPainter::Antialiasing); + colorTexturePainter.setRenderHint(QPainter::HighQualityAntialiasing); + colorTexturePainter.setPen(Qt::NoPen); + + for (const auto& layout : m_mapPacker->packedLayouts()) { + auto findPart = m_snapshot->parts.find(layout.id.toString()); + if (findPart == m_snapshot->parts.end()) + continue; + const auto& colorImageIdIt = findPart->second.find("colorImageId"); + if (colorImageIdIt == findPart->second.end()) + continue; + auto imageId = dust3d::Uuid(colorImageIdIt->second); + const QImage* image = ImageForever::get(imageId); + if (nullptr == image) + continue; + QPixmap brushPixmap; + if (layout.flipped) { + auto scaledImage = image->scaled(QSize(layout.height * UvMapGenerator::m_textureSize, + layout.width * UvMapGenerator::m_textureSize)); + QPoint center = scaledImage.rect().center(); + QMatrix matrix; + matrix.translate(center.x(), center.y()); + matrix.rotate(90); + auto rotatedImage = scaledImage.transformed(matrix).mirrored(true, false); + brushPixmap = QPixmap::fromImage(rotatedImage); + } else { + auto scaledImage = image->scaled(QSize(layout.width * UvMapGenerator::m_textureSize, + layout.height * UvMapGenerator::m_textureSize)); + brushPixmap = QPixmap::fromImage(scaledImage); + } + colorTexturePainter.drawPixmap(layout.left * UvMapGenerator::m_textureSize, + layout.top * UvMapGenerator::m_textureSize, + brushPixmap); + } + + colorTexturePainter.end(); +} + +QImage* UvMapGenerator::combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage, + QImage* roughnessImage, + QImage* ambientOcclusionImage) +{ + QImage* textureMetalnessRoughnessAmbientOcclusionImage = nullptr; + if (nullptr != metalnessImage || nullptr != roughnessImage || nullptr != ambientOcclusionImage) { + int textureSize = 0; + if (nullptr != metalnessImage) + textureSize = metalnessImage->height(); + if (nullptr != roughnessImage) + textureSize = roughnessImage->height(); + if (nullptr != ambientOcclusionImage) + textureSize = ambientOcclusionImage->height(); + if (textureSize > 0) { + textureMetalnessRoughnessAmbientOcclusionImage = new QImage(textureSize, textureSize, QImage::Format_ARGB32); + textureMetalnessRoughnessAmbientOcclusionImage->fill(QColor(255, 255, 0)); + for (int row = 0; row < textureMetalnessRoughnessAmbientOcclusionImage->height(); ++row) { + for (int col = 0; col < textureMetalnessRoughnessAmbientOcclusionImage->width(); ++col) { + QColor color(255, 255, 0); + if (nullptr != metalnessImage) + color.setBlue(qGray(metalnessImage->pixel(col, row))); + if (nullptr != roughnessImage) + color.setGreen(qGray(roughnessImage->pixel(col, row))); + if (nullptr != ambientOcclusionImage) + color.setRed(qGray(ambientOcclusionImage->pixel(col, row))); + textureMetalnessRoughnessAmbientOcclusionImage->setPixelColor(col, row, color); + } + } + } + } + return textureMetalnessRoughnessAmbientOcclusionImage; } diff --git a/application/sources/uv_map_generator.h b/application/sources/uv_map_generator.h index 6afceeff..0fbba0ab 100644 --- a/application/sources/uv_map_generator.h +++ b/application/sources/uv_map_generator.h @@ -1,6 +1,8 @@ #ifndef DUST3D_APPLICATION_UV_MAP_GENERATOR_H_ #define DUST3D_APPLICATION_UV_MAP_GENERATOR_H_ +#include "model_mesh.h" +#include #include #include #include @@ -12,7 +14,17 @@ class UvMapGenerator : public QObject { public: UvMapGenerator(std::unique_ptr object, std::unique_ptr snapshot); void generate(); + std::unique_ptr takeResultTextureColorImage(); + std::unique_ptr takeResultTextureNormalImage(); + std::unique_ptr takeResultTextureRoughnessImage(); + std::unique_ptr takeResultTextureMetalnessImage(); + std::unique_ptr takeResultTextureAmbientOcclusionImage(); + std::unique_ptr takeResultMesh(); std::unique_ptr takeObject(); + bool hasTransparencySettings() const; + static QImage* combineMetalnessRoughnessAmbientOcclusionImages(QImage* metalnessImage, + QImage* roughnessImage, + QImage* ambientOcclusionImage); signals: void finished(); public slots: @@ -22,6 +34,14 @@ private: std::unique_ptr m_object; std::unique_ptr m_snapshot; std::unique_ptr m_mapPacker; + std::unique_ptr m_textureColorImage; + std::unique_ptr m_textureNormalImage; + std::unique_ptr m_textureRoughnessImage; + std::unique_ptr m_textureMetalnessImage; + std::unique_ptr m_textureAmbientOcclusionImage; + std::unique_ptr m_mesh; + bool m_hasTransparencySettings = false; + static size_t m_textureSize; }; #endif diff --git a/dust3d/uv/uv_map_packer.cc b/dust3d/uv/uv_map_packer.cc index 5ce035d8..1e187fee 100644 --- a/dust3d/uv/uv_map_packer.cc +++ b/dust3d/uv/uv_map_packer.cc @@ -61,15 +61,15 @@ void UvMapPacker::pack() layout.id = part.id; layout.flipped = flipped; if (flipped) { - layout.left = left; - layout.top = top; - layout.width = height; - layout.height = width; + layout.left = left / m_packedTextureSize; + layout.top = top / m_packedTextureSize; + layout.width = height / m_packedTextureSize; + layout.height = width / m_packedTextureSize; } else { - layout.left = left; - layout.top = top; - layout.width = width; - layout.height = height; + layout.left = left / m_packedTextureSize; + layout.top = top / m_packedTextureSize; + layout.width = width / m_packedTextureSize; + layout.height = height / m_packedTextureSize; } if (flipped) { for (auto& it : part.localUv) {