Add iteration setting for cloth simulation
parent
21fd758c48
commit
2e047e3d26
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue