Add iteration setting for cloth simulation

master
Jeremy Hu 2020-01-18 12:34:31 +09:30
parent 21fd758c48
commit 2e047e3d26
10 changed files with 79 additions and 8 deletions

View File

@ -768,6 +768,10 @@ Tips:
<source>Offset</source> <source>Offset</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Iteration</source>
<translation></translation>
</message>
</context> </context>
<context> <context>
<name>PartWidget</name> <name>PartWidget</name>

View File

@ -22,7 +22,8 @@
#include "contourtopartconverter.h" #include "contourtopartconverter.h"
unsigned long Document::m_maxSnapshot = 1000; unsigned long Document::m_maxSnapshot = 1000;
const float Component::defaultStiffness = 0.5f; const float Component::defaultClothStiffness = 0.5f;
const size_t Component::defaultClothIteration = 350;
Document::Document() : Document::Document() :
SkeletonDocument(), SkeletonDocument(),
@ -1209,6 +1210,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
component["layer"] = ComponentLayerToString(componentIt.second.layer); component["layer"] = ComponentLayerToString(componentIt.second.layer);
if (componentIt.second.clothStiffnessAdjusted()) if (componentIt.second.clothStiffnessAdjusted())
component["clothStiffness"] = QString::number(componentIt.second.clothStiffness); component["clothStiffness"] = QString::number(componentIt.second.clothStiffness);
if (componentIt.second.clothIterationAdjusted())
component["clothIteration"] = QString::number(componentIt.second.clothIteration);
if (componentIt.second.clothForceAdjusted()) if (componentIt.second.clothForceAdjusted())
component["clothForce"] = ClothForceToString(componentIt.second.clothForce); component["clothForce"] = ClothForceToString(componentIt.second.clothForce);
if (componentIt.second.clothOffsetAdjusted()) if (componentIt.second.clothOffsetAdjusted())
@ -1724,6 +1727,9 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
auto findClothStiffness = componentKv.second.find("clothStiffness"); auto findClothStiffness = componentKv.second.find("clothStiffness");
if (findClothStiffness != componentKv.second.end()) if (findClothStiffness != componentKv.second.end())
component.clothStiffness = findClothStiffness->second.toFloat(); component.clothStiffness = findClothStiffness->second.toFloat();
auto findClothIteration = componentKv.second.find("clothIteration");
if (findClothIteration != componentKv.second.end())
component.clothIteration = findClothIteration->second.toUInt();
auto findClothForce = componentKv.second.find("clothForce"); auto findClothForce = componentKv.second.find("clothForce");
if (findClothForce != componentKv.second.end()) if (findClothForce != componentKv.second.end())
component.clothForce = ClothForceFromString(valueOfKeyInMapOrEmpty(componentKv.second, "clothForce").toUtf8().constData()); component.clothForce = ClothForceFromString(valueOfKeyInMapOrEmpty(componentKv.second, "clothForce").toUtf8().constData());
@ -2566,6 +2572,20 @@ void Document::setComponentClothStiffness(QUuid componentId, float stiffness)
emit skeletonChanged(); emit skeletonChanged();
} }
void Document::setComponentClothIteration(QUuid componentId, size_t iteration)
{
Component *component = (Component *)findComponent(componentId);
if (nullptr == component)
return;
if (component->clothIteration == iteration)
return;
component->clothIteration = iteration;
component->dirty = true;
emit componentClothIterationChanged(componentId);
emit skeletonChanged();
}
void Document::setComponentClothForce(QUuid componentId, ClothForce force) void Document::setComponentClothForce(QUuid componentId, ClothForce force)
{ {
Component *component = (Component *)findComponent(componentId); Component *component = (Component *)findComponent(componentId);

View File

@ -48,7 +48,8 @@ public:
class Component class Component
{ {
public: public:
static const float defaultStiffness; static const float defaultClothStiffness;
static const size_t defaultClothIteration;
Component() Component()
{ {
} }
@ -72,9 +73,10 @@ public:
float smoothSeam = 0.0; float smoothSeam = 0.0;
PolyCount polyCount = PolyCount::Original; PolyCount polyCount = PolyCount::Original;
ComponentLayer layer = ComponentLayer::Body; ComponentLayer layer = ComponentLayer::Body;
float clothStiffness = defaultStiffness; float clothStiffness = defaultClothStiffness;
ClothForce clothForce = ClothForce::Gravitational; ClothForce clothForce = ClothForce::Gravitational;
float clothOffset = 0.0f; float clothOffset = 0.0f;
size_t clothIteration = defaultClothIteration;
std::vector<QUuid> childrenIds; std::vector<QUuid> childrenIds;
QString linkData() const QString linkData() const
{ {
@ -196,7 +198,11 @@ public:
} }
bool clothStiffnessAdjusted() const bool clothStiffnessAdjusted() const
{ {
return fabs(clothStiffness - Component::defaultStiffness) >= 0.01; return fabs(clothStiffness - Component::defaultClothStiffness) >= 0.01;
}
bool clothIterationAdjusted() const
{
return clothIteration != defaultClothIteration;
} }
bool clothForceAdjusted() const bool clothForceAdjusted() const
{ {
@ -418,6 +424,7 @@ signals:
void componentPolyCountChanged(QUuid componentId); void componentPolyCountChanged(QUuid componentId);
void componentLayerChanged(QUuid componentId); void componentLayerChanged(QUuid componentId);
void componentClothStiffnessChanged(QUuid componentId); void componentClothStiffnessChanged(QUuid componentId);
void componentClothIterationChanged(QUuid componentId);
void componentClothForceChanged(QUuid componentId); void componentClothForceChanged(QUuid componentId);
void componentClothOffsetChanged(QUuid componentId); void componentClothOffsetChanged(QUuid componentId);
void nodeRemoved(QUuid nodeId); void nodeRemoved(QUuid nodeId);
@ -679,6 +686,7 @@ public slots:
void setComponentPolyCount(QUuid componentId, PolyCount count); void setComponentPolyCount(QUuid componentId, PolyCount count);
void setComponentLayer(QUuid componentId, ComponentLayer layer); void setComponentLayer(QUuid componentId, ComponentLayer layer);
void setComponentClothStiffness(QUuid componentId, float stiffness); void setComponentClothStiffness(QUuid componentId, float stiffness);
void setComponentClothIteration(QUuid componentId, size_t iteration);
void setComponentClothForce(QUuid componentId, ClothForce force); void setComponentClothForce(QUuid componentId, ClothForce force);
void setComponentClothOffset(QUuid componentId, float offset); void setComponentClothOffset(QUuid componentId, float offset);
void hideOtherComponents(QUuid componentId); void hideOtherComponents(QUuid componentId);

View File

@ -1044,6 +1044,7 @@ DocumentWindow::DocumentWindow() :
connect(partTreeWidget, &PartTreeWidget::setPartColorState, m_document, &Document::setPartColorState); connect(partTreeWidget, &PartTreeWidget::setPartColorState, m_document, &Document::setPartColorState);
connect(partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode); connect(partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode);
connect(partTreeWidget, &PartTreeWidget::setComponentClothStiffness, m_document, &Document::setComponentClothStiffness); connect(partTreeWidget, &PartTreeWidget::setComponentClothStiffness, m_document, &Document::setComponentClothStiffness);
connect(partTreeWidget, &PartTreeWidget::setComponentClothIteration, m_document, &Document::setComponentClothIteration);
connect(partTreeWidget, &PartTreeWidget::setComponentClothForce, m_document, &Document::setComponentClothForce); connect(partTreeWidget, &PartTreeWidget::setComponentClothForce, m_document, &Document::setComponentClothForce);
connect(partTreeWidget, &PartTreeWidget::setComponentClothOffset, m_document, &Document::setComponentClothOffset); connect(partTreeWidget, &PartTreeWidget::setComponentClothOffset, m_document, &Document::setComponentClothOffset);
connect(partTreeWidget, &PartTreeWidget::setPartTarget, m_document, &Document::setPartTarget); connect(partTreeWidget, &PartTreeWidget::setPartTarget, m_document, &Document::setPartTarget);

View File

@ -919,13 +919,23 @@ ComponentLayer MeshGenerator::componentLayer(const std::map<QString, QString> *c
float MeshGenerator::componentClothStiffness(const std::map<QString, QString> *component) float MeshGenerator::componentClothStiffness(const std::map<QString, QString> *component)
{ {
if (nullptr == component) if (nullptr == component)
return Component::defaultStiffness; return Component::defaultClothStiffness;
auto findClothStiffness = component->find("clothStiffness"); auto findClothStiffness = component->find("clothStiffness");
if (findClothStiffness == component->end()) if (findClothStiffness == component->end())
return Component::defaultStiffness; return Component::defaultClothStiffness;
return findClothStiffness->second.toFloat(); return findClothStiffness->second.toFloat();
} }
size_t MeshGenerator::componentClothIteration(const std::map<QString, QString> *component)
{
if (nullptr == component)
return Component::defaultClothIteration;
auto findClothIteration = component->find("clothIteration");
if (findClothIteration == component->end())
return Component::defaultClothIteration;
return findClothIteration->second.toUInt();
}
ClothForce MeshGenerator::componentClothForce(const std::map<QString, QString> *component) ClothForce MeshGenerator::componentClothForce(const std::map<QString, QString> *component)
{ {
if (nullptr == component) if (nullptr == component)
@ -1723,6 +1733,7 @@ void MeshGenerator::collectClothComponent(const QString &componentIdString)
clothMesh.clothForce = componentClothForce(component); clothMesh.clothForce = componentClothForce(component);
clothMesh.clothOffset = componentClothOffset(component); clothMesh.clothOffset = componentClothOffset(component);
clothMesh.clothStiffness = componentClothStiffness(component); clothMesh.clothStiffness = componentClothStiffness(component);
clothMesh.clothIteration = componentClothIteration(component);
clothMesh.outcomeNodeVertices = &componentCache.outcomeNodeVertices; clothMesh.outcomeNodeVertices = &componentCache.outcomeNodeVertices;
m_outcome->nodes.insert(m_outcome->nodes.end(), componentCache.outcomeNodes.begin(), componentCache.outcomeNodes.end()); m_outcome->nodes.insert(m_outcome->nodes.end(), componentCache.outcomeNodes.begin(), componentCache.outcomeNodes.end());
} }

View File

@ -133,6 +133,7 @@ private:
QString componentColorName(const std::map<QString, QString> *component); QString componentColorName(const std::map<QString, QString> *component);
ComponentLayer componentLayer(const std::map<QString, QString> *component); ComponentLayer componentLayer(const std::map<QString, QString> *component);
float componentClothStiffness(const std::map<QString, QString> *component); float componentClothStiffness(const std::map<QString, QString> *component);
size_t componentClothIteration(const std::map<QString, QString> *component);
ClothForce componentClothForce(const std::map<QString, QString> *component); ClothForce componentClothForce(const std::map<QString, QString> *component);
float componentClothOffset(const std::map<QString, QString> *component); float componentClothOffset(const std::map<QString, QString> *component);
void collectUncombinedComponent(const QString &componentIdString); void collectUncombinedComponent(const QString &componentIdString);

View File

@ -15,6 +15,7 @@
#include "partwidget.h" #include "partwidget.h"
#include "skeletongraphicswidget.h" #include "skeletongraphicswidget.h"
#include "floatnumberwidget.h" #include "floatnumberwidget.h"
#include "intnumberwidget.h"
PartTreeWidget::PartTreeWidget(const Document *document, QWidget *parent) : PartTreeWidget::PartTreeWidget(const Document *document, QWidget *parent) :
QTreeWidget(parent), QTreeWidget(parent),
@ -285,7 +286,7 @@ void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &compon
Theme::initAwesomeToolButton(clothStiffnessEraser); Theme::initAwesomeToolButton(clothStiffnessEraser);
connect(clothStiffnessEraser, &QPushButton::clicked, [=]() { connect(clothStiffnessEraser, &QPushButton::clicked, [=]() {
clothStiffnessWidget->setValue(Component::defaultStiffness); clothStiffnessWidget->setValue(Component::defaultClothStiffness);
emit groupOperationAdded(); emit groupOperationAdded();
}); });
@ -293,6 +294,28 @@ void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &compon
clothStiffnessLayout->addWidget(clothStiffnessEraser); clothStiffnessLayout->addWidget(clothStiffnessEraser);
clothStiffnessLayout->addWidget(clothStiffnessWidget); clothStiffnessLayout->addWidget(clothStiffnessWidget);
IntNumberWidget *clothIterationWidget = new IntNumberWidget;
clothIterationWidget->setItemName(tr("Iteration"));
clothIterationWidget->setRange(0, 1000);
clothIterationWidget->setValue(component->clothIteration);
connect(clothIterationWidget, &IntNumberWidget::valueChanged, [=](int value) {
//emit setComponentClothIteration(componentId, value);
//emit groupOperationAdded();
});
QPushButton *clothIterationEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(clothIterationEraser);
connect(clothIterationEraser, &QPushButton::clicked, [=]() {
clothIterationWidget->setValue(Component::defaultClothIteration);
emit groupOperationAdded();
});
QHBoxLayout *clothIterationLayout = new QHBoxLayout;
clothIterationLayout->addWidget(clothIterationEraser);
clothIterationLayout->addWidget(clothIterationWidget);
FloatNumberWidget *clothOffsetWidget = new FloatNumberWidget; FloatNumberWidget *clothOffsetWidget = new FloatNumberWidget;
clothOffsetWidget->setItemName(tr("Offset")); clothOffsetWidget->setItemName(tr("Offset"));
clothOffsetWidget->setRange(0.0f, 1.0f); clothOffsetWidget->setRange(0.0f, 1.0f);
@ -333,6 +356,7 @@ void PartTreeWidget::showClothSettingMenu(const QPoint &pos, const QUuid &compon
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(clothStiffnessLayout); mainLayout->addLayout(clothStiffnessLayout);
//mainLayout->addLayout(clothIterationLayout);
mainLayout->addLayout(clothOffsetLayout); mainLayout->addLayout(clothOffsetLayout);
mainLayout->addLayout(clothForceLayout); mainLayout->addLayout(clothForceLayout);

View File

@ -43,6 +43,7 @@ signals:
void setPartColorState(QUuid partId, bool hasColor, QColor color); void setPartColorState(QUuid partId, bool hasColor, QColor color);
void setComponentCombineMode(QUuid componentId, CombineMode combineMode); void setComponentCombineMode(QUuid componentId, CombineMode combineMode);
void setComponentClothStiffness(QUuid componentId, float clothStiffness); void setComponentClothStiffness(QUuid componentId, float clothStiffness);
void setComponentClothIteration(QUuid componentId, size_t iteration);
void setComponentClothForce(QUuid componentId, ClothForce force); void setComponentClothForce(QUuid componentId, ClothForce force);
void setComponentClothOffset(QUuid componentId, float offset); void setComponentClothOffset(QUuid componentId, float offset);
void hideDescendantComponents(QUuid componentId); void hideDescendantComponents(QUuid componentId);

View File

@ -58,7 +58,7 @@ public:
externalForces); externalForces);
clothSimulator.setStiffness(clothMesh->clothStiffness); clothSimulator.setStiffness(clothMesh->clothStiffness);
clothSimulator.create(); clothSimulator.create();
for (size_t i = 0; i < 350; ++i) for (size_t i = 0; i < clothMesh->clothIteration; ++i)
clothSimulator.step(); clothSimulator.step();
clothSimulator.getCurrentVertices(&filteredClothVertices); clothSimulator.getCurrentVertices(&filteredClothVertices);
for (size_t i = 0; i < filteredClothVertices.size(); ++i) { for (size_t i = 0; i < filteredClothVertices.size(); ++i) {

View File

@ -14,6 +14,7 @@ struct ClothMesh
ClothForce clothForce; ClothForce clothForce;
float clothOffset; float clothOffset;
float clothStiffness; float clothStiffness;
size_t clothIteration;
}; };
void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes, void simulateClothMeshes(std::vector<ClothMesh> *clothMeshes,