diff --git a/dust3d.pro b/dust3d.pro index 9484a5b7..212b4457 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -372,6 +372,9 @@ HEADERS += src/posedocument.h SOURCES += src/combinemode.cpp HEADERS += src/combinemode.h +SOURCES += src/polycount.cpp +HEADERS += src/polycount.h + SOURCES += src/cutdocument.cpp HEADERS += src/cutdocument.h diff --git a/languages/dust3d_zh_CN.ts b/languages/dust3d_zh_CN.ts index 67c2f2b2..3374a30b 100644 --- a/languages/dust3d_zh_CN.ts +++ b/languages/dust3d_zh_CN.ts @@ -738,7 +738,11 @@ Tips: Remeshed - 重新网格化 + 重新网格化 + + + Poly + 面数 @@ -1046,6 +1050,22 @@ Tips: Fall to Death 倒地死亡 + + Low Poly + 低面 + + + Original + 原样 + + + High Poly + 高面 + + + Extreme High Poly + 极高面 + RigWidget diff --git a/src/document.cpp b/src/document.cpp index d7d0dcdc..dd0e6ae5 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -36,7 +36,7 @@ Document::Document() : textureAmbientOcclusionImage(nullptr), rigType(RigType::None), weldEnabled(true), - remeshed(false), + polyCount(PolyCount::Original), // private m_isResultMeshObsolete(false), m_meshGenerator(nullptr), @@ -1199,8 +1199,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId component["smoothAll"] = QString::number(componentIt.second.smoothAll); if (componentIt.second.smoothSeamAdjusted()) component["smoothSeam"] = QString::number(componentIt.second.smoothSeam); - if (componentIt.second.remeshed) - component["remeshed"] = "true"; + if (componentIt.second.polyCount != PolyCount::Original) + component["polyCount"] = PolyCountToString(componentIt.second.polyCount); QStringList childIdList; for (const auto &childId: componentIt.second.childrenIds) { childIdList.append(childId.toString()); @@ -1315,8 +1315,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId canvas["originY"] = QString::number(getOriginY()); canvas["originZ"] = QString::number(getOriginZ()); canvas["rigType"] = RigTypeToString(rigType); - if (this->remeshed) - canvas["remeshed"] = "true"; + if (this->polyCount != PolyCount::Original) + canvas["polyCount"] = PolyCountToString(this->polyCount); snapshot->canvas = canvas; } } @@ -1474,7 +1474,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste) bool isOriginChanged = false; bool isRigTypeChanged = false; if (!fromPaste) { - this->remeshed = isTrueValueString(valueOfKeyInMapOrEmpty(snapshot.canvas, "remeshed")); + this->polyCount = PolyCountFromString(valueOfKeyInMapOrEmpty(snapshot.canvas, "polyCount").toUtf8().constData()); const auto &originXit = snapshot.canvas.find("originX"); const auto &originYit = snapshot.canvas.find("originY"); const auto &originZit = snapshot.canvas.find("originZ"); @@ -1707,7 +1707,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste) const auto &smoothSeamIt = componentKv.second.find("smoothSeam"); if (smoothSeamIt != componentKv.second.end()) component.setSmoothSeam(smoothSeamIt->second.toFloat()); - component.remeshed = isTrueValueString(valueOfKeyInMapOrEmpty(componentKv.second, "remeshed")); + component.polyCount = PolyCountFromString(valueOfKeyInMapOrEmpty(componentKv.second, "polyCount").toUtf8().constData()); //qDebug() << "Add component:" << component.id << " old:" << componentKv.first << "name:" << component.name; if ("partId" == linkDataType) { QUuid partId = oldNewIdMap[QUuid(linkData)]; @@ -2474,13 +2474,13 @@ void Document::setComponentExpandState(QUuid componentId, bool expanded) emit optionsChanged(); } -void Document::setComponentRemeshState(QUuid componentId, bool remeshed) +void Document::setComponentPolyCount(QUuid componentId, PolyCount count) { if (componentId.isNull()) { - if (this->remeshed == remeshed) + if (polyCount == count) return; - this->remeshed = remeshed; - emit componentRemeshStateChanged(componentId); + polyCount = count; + emit componentPolyCountChanged(componentId); emit skeletonChanged(); return; } @@ -2488,12 +2488,12 @@ void Document::setComponentRemeshState(QUuid componentId, bool remeshed) Component *component = (Component *)findComponent(componentId); if (nullptr == component) return; - if (component->remeshed == remeshed) + if (component->polyCount == count) return; - component->remeshed = remeshed; + component->polyCount = count; component->dirty = true; - emit componentRemeshStateChanged(componentId); + emit componentPolyCountChanged(componentId); emit skeletonChanged(); } diff --git a/src/document.h b/src/document.h index dfdcc413..9b4f62c6 100644 --- a/src/document.h +++ b/src/document.h @@ -26,6 +26,7 @@ #include "jointnodetree.h" #include "skeletondocument.h" #include "combinemode.h" +#include "polycount.h" #include "preferences.h" #include "paintmode.h" #include "proceduralanimation.h" @@ -65,7 +66,7 @@ public: bool dirty = true; float smoothAll = 0.0; float smoothSeam = 0.0; - bool remeshed = false; + PolyCount polyCount = PolyCount::Original; std::vector childrenIds; QString linkData() const { @@ -394,7 +395,7 @@ signals: void componentExpandStateChanged(QUuid componentId); void componentSmoothAllChanged(QUuid componentId); void componentSmoothSeamChanged(QUuid componentId); - void componentRemeshStateChanged(QUuid componentId); + void componentPolyCountChanged(QUuid componentId); void nodeRemoved(QUuid nodeId); void edgeRemoved(QUuid edgeId); void nodeRadiusChanged(QUuid nodeId); @@ -497,7 +498,7 @@ public: // need initialize QImage *textureAmbientOcclusionImage; RigType rigType; bool weldEnabled; - bool remeshed; + PolyCount polyCount; public: Document(); ~Document(); @@ -640,7 +641,7 @@ public slots: void setComponentExpandState(QUuid componentId, bool expanded); void setComponentSmoothAll(QUuid componentId, float toSmoothAll); void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam); - void setComponentRemeshState(QUuid componentId, bool remeshed); + void setComponentPolyCount(QUuid componentId, PolyCount count); void hideOtherComponents(QUuid componentId); void lockOtherComponents(QUuid componentId); void hideAllComponents(); diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 0defab76..1e752c1c 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -990,7 +990,7 @@ DocumentWindow::DocumentWindow() : connect(partTreeWidget, &PartTreeWidget::setComponentExpandState, m_document, &Document::setComponentExpandState); connect(partTreeWidget, &PartTreeWidget::setComponentSmoothAll, m_document, &Document::setComponentSmoothAll); connect(partTreeWidget, &PartTreeWidget::setComponentSmoothSeam, m_document, &Document::setComponentSmoothSeam); - connect(partTreeWidget, &PartTreeWidget::setComponentRemeshState, m_document, &Document::setComponentRemeshState); + connect(partTreeWidget, &PartTreeWidget::setComponentPolyCount, m_document, &Document::setComponentPolyCount); connect(partTreeWidget, &PartTreeWidget::moveComponent, m_document, &Document::moveComponent); connect(partTreeWidget, &PartTreeWidget::removeComponent, m_document, &Document::removeComponent); connect(partTreeWidget, &PartTreeWidget::hideOtherComponents, m_document, &Document::hideOtherComponents); diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index 894f0fd6..a4233a5e 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -17,6 +17,7 @@ #include "gridmeshbuilder.h" #include "triangulatefaces.h" #include "remesher.h" +#include "polycount.h" MeshGenerator::MeshGenerator(Snapshot *snapshot) : m_snapshot(snapshot) @@ -843,11 +844,14 @@ CombineMode MeshGenerator::componentCombineMode(const std::map return combineMode; } -bool MeshGenerator::componentRemeshed(const std::map *component) +bool MeshGenerator::componentRemeshed(const std::map *component, float *polyCountValue) { if (nullptr == component) return false; - return isTrueValueString(valueOfKeyInMapOrEmpty(*component, "remeshed")); + auto polyCount = PolyCountFromString(valueOfKeyInMapOrEmpty(*component, "polyCount").toUtf8().constData()); + if (nullptr != polyCountValue) + *polyCountValue = PolyCountToValue(polyCount); + return polyCount != PolyCount::Original; } QString MeshGenerator::componentColorName(const std::map *component) @@ -1032,7 +1036,8 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component } if (nullptr != mesh) { - bool remeshed = componentId.isNull() ? componentRemeshed(&m_snapshot->canvas) : componentRemeshed(component); + float polyCountValue = 1.0f; + bool remeshed = componentId.isNull() ? componentRemeshed(&m_snapshot->canvas, &polyCountValue) : componentRemeshed(component, &polyCountValue); if (remeshed) { std::vector combinedVertices; std::vector> combinedFaces; @@ -1043,6 +1048,7 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component remesh(componentCache.outcomeNodes, combinedVertices, combinedFaces, + polyCountValue, &newVertices, &newQuads, &newTriangles, @@ -1460,6 +1466,7 @@ void MeshGenerator::generate() void MeshGenerator::remesh(const std::vector &inputNodes, const std::vector &inputVertices, const std::vector> &inputFaces, + float targetVertexMultiplyFactor, std::vector *outputVertices, std::vector> *outputQuads, std::vector> *outputTriangles, @@ -1476,7 +1483,7 @@ void MeshGenerator::remesh(const std::vector &inputNodes, Remesher remesher; remesher.setMesh(inputVertices, inputFaces); remesher.setNodes(nodes, sourceIds); - remesher.remesh(); + remesher.remesh(targetVertexMultiplyFactor); *outputVertices = remesher.getRemeshedVertices(); const auto &remeshedFaces = remesher.getRemeshedFaces(); *outputQuads = remeshedFaces; diff --git a/src/meshgenerator.h b/src/meshgenerator.h index 05fb1906..8496980a 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -120,7 +120,7 @@ private: std::vector> *triangleVertexNormals); const std::map *findComponent(const QString &componentIdString); CombineMode componentCombineMode(const std::map *component); - bool componentRemeshed(const std::map *component); + bool componentRemeshed(const std::map *component, float *polyCountValue=nullptr); MeshCombiner::Mesh *combineComponentChildGroupMesh(const std::vector &componentIdStrings, GeneratedComponent &componentCache); MeshCombiner::Mesh *combineMultipleMeshes(const std::vector> &multipleMeshes, bool recombine=true); @@ -130,6 +130,7 @@ private: void remesh(const std::vector &inputNodes, const std::vector &inputVertices, const std::vector> &inputFaces, + float targetVertexMultiplyFactor, std::vector *outputVertices, std::vector> *outputQuads, std::vector> *outputTriangles, diff --git a/src/parttreewidget.cpp b/src/parttreewidget.cpp index ae431aaf..612574c6 100644 --- a/src/parttreewidget.cpp +++ b/src/parttreewidget.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include "parttreewidget.h" #include "partwidget.h" #include "skeletongraphicswidget.h" @@ -289,24 +288,30 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) } layout->addWidget(previewLabel); } - QCheckBox *remeshBox = nullptr; + QComboBox *polyCountSelectBox = nullptr; if (componentIds.size() <= 1) { - remeshBox = new QCheckBox(); - remeshBox->setText(tr("Remeshed")); + polyCountSelectBox = new QComboBox; if (nullptr == component) { - if (m_document->remeshed) - remeshBox->setChecked(true); - connect(remeshBox, &QCheckBox::stateChanged, this, [=]() { - emit setComponentRemeshState(QUuid(), remeshBox->isChecked()); + for (size_t i = 0; i < (size_t)PolyCount::Count; ++i) { + PolyCount count = (PolyCount)i; + polyCountSelectBox->addItem(PolyCountToDispName(count)); + } + polyCountSelectBox->setCurrentIndex((int)m_document->polyCount); + connect(polyCountSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { + emit setComponentPolyCount(QUuid(), (PolyCount)index); + emit groupOperationAdded(); }); } else { - if (component->remeshed) - remeshBox->setChecked(true); - connect(remeshBox, &QCheckBox::stateChanged, this, [=]() { - emit setComponentRemeshState(component->id, remeshBox->isChecked()); + for (size_t i = 0; i < (size_t)PolyCount::Count; ++i) { + PolyCount count = (PolyCount)i; + polyCountSelectBox->addItem(PolyCountToDispName(count)); + } + polyCountSelectBox->setCurrentIndex((int)component->polyCount); + connect(polyCountSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { + emit setComponentPolyCount(component->id, (PolyCount)index); + emit groupOperationAdded(); }); } - Theme::initCheckbox(remeshBox); } QWidget *widget = new QWidget; if (nullptr != component) { @@ -318,6 +323,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) combineModeSelectBox->setCurrentIndex((int)component->combineMode); connect(combineModeSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { emit setComponentCombineMode(component->id, (CombineMode)index); + emit groupOperationAdded(); }); QComboBox *partTargetSelectBox = nullptr; @@ -330,6 +336,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) partTargetSelectBox->setCurrentIndex((int)part->target); connect(partTargetSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { emit setPartTarget(part->id, (PartTarget)index); + emit groupOperationAdded(); }); } @@ -343,6 +350,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) partBaseSelectBox->setCurrentIndex((int)part->base); connect(partBaseSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { emit setPartBase(part->id, (PartBase)index); + emit groupOperationAdded(); }); } @@ -353,6 +361,8 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) //combineModeLayout->addWidget(combineModeSelectBox); QFormLayout *componentSettingsLayout = new QFormLayout; + if (nullptr != polyCountSelectBox) + componentSettingsLayout->addRow(tr("Poly"), polyCountSelectBox); if (nullptr != partBaseSelectBox) componentSettingsLayout->addRow(tr("Base"), partBaseSelectBox); if (nullptr != partTargetSelectBox) @@ -361,15 +371,16 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) QVBoxLayout *newLayout = new QVBoxLayout; newLayout->addLayout(layout); - if (nullptr != remeshBox) - newLayout->addWidget(remeshBox); newLayout->addLayout(componentSettingsLayout); widget->setLayout(newLayout); } else { + QFormLayout *componentSettingsLayout = new QFormLayout; + if (nullptr != polyCountSelectBox) + componentSettingsLayout->addRow(tr("Poly"), polyCountSelectBox); + QVBoxLayout *newLayout = new QVBoxLayout; newLayout->addLayout(layout); - if (nullptr != remeshBox) - newLayout->addWidget(remeshBox); + newLayout->addLayout(componentSettingsLayout); widget->setLayout(newLayout); } forDisplayPartImage.setDefaultWidget(widget); diff --git a/src/parttreewidget.h b/src/parttreewidget.h index da0e43aa..a8bb21c8 100644 --- a/src/parttreewidget.h +++ b/src/parttreewidget.h @@ -22,7 +22,7 @@ signals: void setComponentExpandState(QUuid componentId, bool expanded); void setComponentSmoothAll(QUuid componentId, float toSmoothAll); void setComponentSmoothSeam(QUuid componentId, float toSmoothSeam); - void setComponentRemeshState(QUuid componentId, bool remeshed); + void setComponentPolyCount(QUuid componentId, PolyCount count); void setPartTarget(QUuid partId, PartTarget target); void setPartBase(QUuid partId, PartBase base); void moveComponent(QUuid componentId, QUuid toParentId); diff --git a/src/polycount.cpp b/src/polycount.cpp new file mode 100644 index 00000000..76a475c8 --- /dev/null +++ b/src/polycount.cpp @@ -0,0 +1,7 @@ +#include +#include "polycount.h" + +IMPL_PolyCountToString +IMPL_PolyCountFromString +IMPL_PolyCountToDispName +IMPL_PolyCountToValue diff --git a/src/polycount.h b/src/polycount.h new file mode 100644 index 00000000..a667932b --- /dev/null +++ b/src/polycount.h @@ -0,0 +1,80 @@ +#ifndef DUST3D_POLY_COUNT_H +#define DUST3D_POLY_COUNT_H +#include + +enum class PolyCount +{ + LowPoly, + Original, + HighPoly, + ExtremeHighPoly, + Count +}; +PolyCount PolyCountFromString(const char *countString); +#define IMPL_PolyCountFromString \ +PolyCount PolyCountFromString(const char *countString) \ +{ \ + QString count = countString; \ + if (count == "LowPoly") \ + return PolyCount::LowPoly; \ + if (count == "Original") \ + return PolyCount::Original; \ + if (count == "HighPoly") \ + return PolyCount::HighPoly; \ + if (count == "ExtremeHighPoly") \ + return PolyCount::ExtremeHighPoly; \ + return PolyCount::Original; \ +} +const char *PolyCountToString(PolyCount count); +#define IMPL_PolyCountToString \ +const char *PolyCountToString(PolyCount count) \ +{ \ + switch (count) { \ + case PolyCount::LowPoly: \ + return "LowPoly"; \ + case PolyCount::Original: \ + return "Original"; \ + case PolyCount::HighPoly: \ + return "HighPoly"; \ + case PolyCount::ExtremeHighPoly: \ + return "ExtremeHighPoly"; \ + default: \ + return "Original"; \ + } \ +} +QString PolyCountToDispName(PolyCount count); +#define IMPL_PolyCountToDispName \ +QString PolyCountToDispName(PolyCount count) \ +{ \ + switch (count) { \ + case PolyCount::LowPoly: \ + return QObject::tr("Low Poly"); \ + case PolyCount::Original: \ + return QObject::tr("Original"); \ + case PolyCount::HighPoly: \ + return QObject::tr("High Poly"); \ + case PolyCount::ExtremeHighPoly: \ + return QObject::tr("Extreme High Poly"); \ + default: \ + return QObject::tr("Original"); \ + } \ +} +float PolyCountToValue(PolyCount count); +#define IMPL_PolyCountToValue \ +float PolyCountToValue(PolyCount count) \ +{ \ + switch (count) { \ + case PolyCount::LowPoly: \ + return 0.6f; \ + case PolyCount::Original: \ + return 1.0f; \ + case PolyCount::HighPoly: \ + return 1.2f; \ + case PolyCount::ExtremeHighPoly: \ + return 1.8f; \ + default: \ + return 1.0f; \ + } \ +} + +#endif diff --git a/src/remesher.cpp b/src/remesher.cpp index 2e97abf9..d2c214b3 100644 --- a/src/remesher.cpp +++ b/src/remesher.cpp @@ -32,7 +32,7 @@ const std::vector> &Remesher::getRemeshedVertexSources() return m_remeshedVertexSources; } -void Remesher::remesh() +void Remesher::remesh(float targetVertexMultiplyFactor) { std::vector inputVertices(m_vertices.size()); for (size_t i = 0; i < m_vertices.size(); ++i) { @@ -61,7 +61,7 @@ void Remesher::remesh() size_t nResultQuads = 0; Dust3D_instantMeshesRemesh(inputVertices.data(), inputVertices.size(), inputTriangles.data(), inputTriangles.size(), - (size_t)(inputVertices.size() * 1.0f), + (size_t)(inputVertices.size() * targetVertexMultiplyFactor), &resultVertices, &nResultVertices, &resultTriangles, diff --git a/src/remesher.h b/src/remesher.h index 7c1af71e..46810119 100644 --- a/src/remesher.h +++ b/src/remesher.h @@ -15,7 +15,7 @@ public: const std::vector> &triangles); void setNodes(const std::vector> &nodes, const std::vector> &sourceIds); - void remesh(); + void remesh(float targetVertexMultiplyFactor); const std::vector &getRemeshedVertices() const; const std::vector> &getRemeshedFaces() const; const std::vector> &getRemeshedVertexSources() const;