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:
- 重新网格化
+ 重新网格化
+
+
+
+ 面数
@@ -1046,6 +1050,22 @@ Tips:
倒地死亡
+
+
+ 低面
+
+
+
+ 原样
+
+
+
+ 高面
+
+
+
+ 极高面
+
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;