Fix deform

master
Jeremy Hu 2018-04-18 00:14:31 +08:00
parent ce41e654fb
commit f1b219333f
13 changed files with 139 additions and 47 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
moc_*
.DS_Store
*.o

View File

@ -125,9 +125,12 @@ void MeshGenerator::process()
int bmeshId = meshlite_bmesh_create(meshliteContext);
if (subdived)
meshlite_bmesh_set_cut_subdiv_count(meshliteContext, bmeshId, 1);
QString thicknessString = valueOfKeyInMapOrEmpty(part->second, "thickness");
QString thicknessString = valueOfKeyInMapOrEmpty(part->second, "deformThickness");
if (!thicknessString.isEmpty())
meshlite_bmesh_set_thickness(meshliteContext, bmeshId, thicknessString.toFloat());
meshlite_bmesh_set_deform_thickness(meshliteContext, bmeshId, thicknessString.toFloat());
QString widthString = valueOfKeyInMapOrEmpty(part->second, "deformWidth");
if (!widthString.isEmpty())
meshlite_bmesh_set_deform_width(meshliteContext, bmeshId, widthString.toFloat());
if (MeshGenerator::enableDebug)
meshlite_bmesh_enable_debug(meshliteContext, bmeshId, 1);
partBmeshMap[partIdIt] = bmeshId;

View File

@ -585,8 +585,10 @@ void SkeletonDocument::toSnapshot(SkeletonSnapshot *snapshot, const std::set<QUu
part["disabled"] = partIt.second.disabled ? "true" : "false";
part["xMirrored"] = partIt.second.xMirrored ? "true" : "false";
part["zMirrored"] = partIt.second.zMirrored ? "true" : "false";
if (partIt.second.thicknessAdjusted())
part["thickness"] = QString::number(partIt.second.thickness);
if (partIt.second.deformThicknessAdjusted())
part["deformThickness"] = QString::number(partIt.second.deformThickness);
if (partIt.second.deformWidthAdjusted())
part["deformWidth"] = QString::number(partIt.second.deformWidth);
if (!partIt.second.name.isEmpty())
part["name"] = partIt.second.name;
snapshot->parts[part["id"]] = part;
@ -657,9 +659,12 @@ void SkeletonDocument::addFromSnapshot(const SkeletonSnapshot &snapshot)
part.disabled = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "disabled"));
part.xMirrored = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "xMirrored"));
part.zMirrored = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "zMirrored"));
const auto &thicknessIt = partKv.second.find("thickness");
if (thicknessIt != partKv.second.end())
part.setThickness(thicknessIt->second.toFloat());
const auto &deformThicknessIt = partKv.second.find("deformThickness");
if (deformThicknessIt != partKv.second.end())
part.setDeformThickness(deformThicknessIt->second.toFloat());
const auto &deformWidthIt = partKv.second.find("deformWidth");
if (deformWidthIt != partKv.second.end())
part.setDeformWidth(deformWidthIt->second.toFloat());
partMap[part.id] = part;
}
for (const auto &nodeKv : snapshot.nodes) {
@ -929,15 +934,27 @@ void SkeletonDocument::setPartZmirrorState(QUuid partId, bool mirrored)
emit skeletonChanged();
}
void SkeletonDocument::setPartThickness(QUuid partId, float thickness)
void SkeletonDocument::setPartDeformThickness(QUuid partId, float thickness)
{
auto part = partMap.find(partId);
if (part == partMap.end()) {
qDebug() << "Part not found:" << partId;
return;
}
part->second.setThickness(thickness);
emit partThicknessChanged(partId);
part->second.setDeformThickness(thickness);
emit partDeformThicknessChanged(partId);
emit skeletonChanged();
}
void SkeletonDocument::setPartDeformWidth(QUuid partId, float width)
{
auto part = partMap.find(partId);
if (part == partMap.end()) {
qDebug() << "Part not found:" << partId;
return;
}
part->second.setDeformWidth(width);
emit partDeformWidthChanged(partId);
emit skeletonChanged();
}

View File

@ -71,7 +71,8 @@ public:
bool disabled;
bool xMirrored;
bool zMirrored;
float thickness;
float deformThickness;
float deformWidth;
QImage preview;
std::vector<QUuid> nodeIds;
SkeletonPart(const QUuid &withId=QUuid()) :
@ -81,21 +82,38 @@ public:
disabled(false),
xMirrored(false),
zMirrored(false),
thickness(1.0)
deformThickness(1.0),
deformWidth(1.0)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
void setThickness(float toThickness)
void setDeformThickness(float toThickness)
{
if (toThickness < 0)
toThickness = 0;
else if (toThickness > 2)
toThickness = 2;
thickness = toThickness;
deformThickness = toThickness;
}
bool thicknessAdjusted() const
void setDeformWidth(float toWidth)
{
return fabs(thickness - 1.0) >= 0.01;
if (toWidth < 0)
toWidth = 0;
else if (toWidth > 2)
toWidth = 2;
deformWidth = toWidth;
}
bool deformThicknessAdjusted() const
{
return fabs(deformThickness - 1.0) >= 0.01;
}
bool deformWidthAdjusted() const
{
return fabs(deformWidth - 1.0) >= 0.01;
}
bool deformAdjusted() const
{
return deformThicknessAdjusted() || deformWidthAdjusted();
}
bool isEditVisible() const
{
@ -109,7 +127,8 @@ public:
disabled = other.disabled;
xMirrored = other.xMirrored;
zMirrored = other.zMirrored;
thickness = other.thickness;
deformThickness = other.deformThickness;
deformWidth = other.deformWidth;
}
};
@ -161,7 +180,8 @@ signals:
void partDisableStateChanged(QUuid partId);
void partXmirrorStateChanged(QUuid partId);
void partZmirrorStateChanged(QUuid partId);
void partThicknessChanged(QUuid partId);
void partDeformThicknessChanged(QUuid partId);
void partDeformWidthChanged(QUuid partId);
void cleanup();
void originChanged();
void xlockStateChanged();
@ -220,7 +240,8 @@ public slots:
void setPartDisableState(QUuid partId, bool disabled);
void setPartXmirrorState(QUuid partId, bool mirrored);
void setPartZmirrorState(QUuid partId, bool mirrored);
void setPartThickness(QUuid partId, float thickness);
void setPartDeformThickness(QUuid partId, float thickness);
void setPartDeformWidth(QUuid partId, float width);
void saveSnapshot();
void undo();
void redo();

View File

@ -422,7 +422,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
connect(m_document, &SkeletonDocument::partSubdivStateChanged, partListWidget, &SkeletonPartListWidget::partSubdivStateChanged);
connect(m_document, &SkeletonDocument::partDisableStateChanged, partListWidget, &SkeletonPartListWidget::partDisableStateChanged);
connect(m_document, &SkeletonDocument::partXmirrorStateChanged, partListWidget, &SkeletonPartListWidget::partXmirrorStateChanged);
connect(m_document, &SkeletonDocument::partThicknessChanged, partListWidget, &SkeletonPartListWidget::partThicknessChanged);
connect(m_document, &SkeletonDocument::partDeformThicknessChanged, partListWidget, &SkeletonPartListWidget::partDeformChanged);
connect(m_document, &SkeletonDocument::partDeformWidthChanged, partListWidget, &SkeletonPartListWidget::partDeformChanged);
connect(m_document, &SkeletonDocument::cleanup, partListWidget, &SkeletonPartListWidget::partListChanged);
connect(m_document, &SkeletonDocument::skeletonChanged, m_document, &SkeletonDocument::generateMesh);

View File

@ -31,9 +31,9 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
initButton(m_xMirrorButton);
updateXmirrorButton();
m_thicknessButton = new QPushButton();
initButton(m_thicknessButton);
updateThicknessButton();
m_deformButton = new QPushButton();
initButton(m_deformButton);
updateDeformButton();
m_previewLabel = new QLabel;
@ -49,8 +49,8 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
miniBottomToolLayout->setSpacing(0);
miniBottomToolLayout->setContentsMargins(0, 0, 0, 0);
miniBottomToolLayout->addWidget(m_subdivButton);
miniBottomToolLayout->addWidget(m_deformButton);
miniBottomToolLayout->addWidget(m_xMirrorButton);
miniBottomToolLayout->addWidget(m_thicknessButton);
miniBottomToolLayout->addStretch();
QWidget *hrWidget = new QWidget;
@ -74,7 +74,8 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
connect(this, &SkeletonPartWidget::setPartSubdivState, m_document, &SkeletonDocument::setPartSubdivState);
connect(this, &SkeletonPartWidget::setPartDisableState, m_document, &SkeletonDocument::setPartDisableState);
connect(this, &SkeletonPartWidget::setPartXmirrorState, m_document, &SkeletonDocument::setPartXmirrorState);
connect(this, &SkeletonPartWidget::setPartThickness, m_document, &SkeletonDocument::setPartThickness);
connect(this, &SkeletonPartWidget::setPartDeformThickness, m_document, &SkeletonDocument::setPartDeformThickness);
connect(this, &SkeletonPartWidget::setPartDeformWidth, m_document, &SkeletonDocument::setPartDeformWidth);
connect(m_lockButton, &QPushButton::clicked, [=]() {
const SkeletonPart *part = m_document->findPart(m_partId);
@ -121,17 +122,25 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
emit setPartXmirrorState(m_partId, !part->xMirrored);
});
connect(m_thicknessButton, &QPushButton::clicked, [=]() {
connect(m_deformButton, &QPushButton::clicked, [=]() {
const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) {
qDebug() << "Part not found:" << m_partId;
return;
}
showThicknessSettingPopup(mapFromGlobal(QCursor::pos()));
showDeformSettingPopup(mapFromGlobal(QCursor::pos()));
});
}
void SkeletonPartWidget::showThicknessSettingPopup(const QPoint &pos)
void SkeletonPartWidget::initToolButton(QPushButton *button)
{
button->setFont(Theme::awesome()->font(Theme::toolIconFontSize / 2));
button->setFixedSize(Theme::toolIconSize / 2, Theme::toolIconSize / 2);
button->setStyleSheet("QPushButton {color: #f7d9c8}");
button->setFocusPolicy(Qt::NoFocus);
}
void SkeletonPartWidget::showDeformSettingPopup(const QPoint &pos)
{
QMenu popupMenu;
@ -141,14 +150,50 @@ void SkeletonPartWidget::showThicknessSettingPopup(const QPoint &pos)
return;
}
FloatNumberWidget *popup = new FloatNumberWidget;
popup->setRange(0, 2);
popup->setValue(part->thickness);
QWidget *popup = new QWidget;
connect(popup, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartThickness(m_partId, value);
FloatNumberWidget *thicknessWidget = new FloatNumberWidget;
thicknessWidget->setRange(0, 2);
thicknessWidget->setValue(part->deformThickness);
connect(thicknessWidget, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartDeformThickness(m_partId, value);
});
FloatNumberWidget *widthWidget = new FloatNumberWidget;
widthWidget->setRange(0, 2);
widthWidget->setValue(part->deformWidth);
connect(widthWidget, &FloatNumberWidget::valueChanged, [=](float value) {
emit setPartDeformWidth(m_partId, value);
});
QPushButton *thicknessEraser = new QPushButton(QChar(fa::eraser));
initToolButton(thicknessEraser);
connect(thicknessEraser, &QPushButton::clicked, [=]() {
thicknessWidget->setValue(1.0);
});
QPushButton *widthEraser = new QPushButton(QChar(fa::eraser));
initToolButton(widthEraser);
connect(widthEraser, &QPushButton::clicked, [=]() {
widthWidget->setValue(1.0);
});
QVBoxLayout *layout = new QVBoxLayout;
QHBoxLayout *thicknessLayout = new QHBoxLayout;
QHBoxLayout *widthLayout = new QHBoxLayout;
thicknessLayout->addWidget(thicknessEraser);
thicknessLayout->addWidget(thicknessWidget);
widthLayout->addWidget(widthEraser);
widthLayout->addWidget(widthWidget);
layout->addLayout(thicknessLayout);
layout->addLayout(widthLayout);
popup->setLayout(layout);
QWidgetAction *action = new QWidgetAction(this);
action->setDefaultWidget(popup);
@ -248,17 +293,17 @@ void SkeletonPartWidget::updateXmirrorButton()
updateButton(m_xMirrorButton, QChar(fa::balancescale), false);
}
void SkeletonPartWidget::updateThicknessButton()
void SkeletonPartWidget::updateDeformButton()
{
const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) {
qDebug() << "Part not found:" << m_partId;
return;
}
if (part->thicknessAdjusted())
updateButton(m_thicknessButton, QChar(fa::handlizardo), true);
if (part->deformAdjusted())
updateButton(m_deformButton, QChar(fa::handlizardo), true);
else
updateButton(m_thicknessButton, QChar(fa::handlizardo), false);
updateButton(m_deformButton, QChar(fa::handlizardo), false);
}
void SkeletonPartWidget::reload()
@ -269,7 +314,7 @@ void SkeletonPartWidget::reload()
updateSubdivButton();
updateDisableButton();
updateXmirrorButton();
updateThicknessButton();
updateDeformButton();
}
SkeletonPartListWidget::SkeletonPartListWidget(const SkeletonDocument *document) :
@ -376,7 +421,7 @@ void SkeletonPartListWidget::partXmirrorStateChanged(QUuid partId)
widget->updateXmirrorButton();
}
void SkeletonPartListWidget::partThicknessChanged(QUuid partId)
void SkeletonPartListWidget::partDeformChanged(QUuid partId)
{
auto item = m_itemMap.find(partId);
if (item == m_itemMap.end()) {
@ -384,5 +429,5 @@ void SkeletonPartListWidget::partThicknessChanged(QUuid partId)
return;
}
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
widget->updateThicknessButton();
widget->updateDeformButton();
}

View File

@ -16,7 +16,8 @@ signals:
void setPartDisableState(QUuid partId, bool disabled);
void setPartXmirrorState(QUuid partId, bool mirrored);
void setPartZmirrorState(QUuid partId, bool mirrored);
void setPartThickness(QUuid partId, float thickness);
void setPartDeformThickness(QUuid partId, float thickness);
void setPartDeformWidth(QUuid partId, float width);
public:
SkeletonPartWidget(const SkeletonDocument *document, QUuid partId);
void reload();
@ -27,9 +28,9 @@ public:
void updateDisableButton();
void updateXmirrorButton();
void updateZmirrorButton();
void updateThicknessButton();
void updateDeformButton();
public slots:
void showThicknessSettingPopup(const QPoint &pos);
void showDeformSettingPopup(const QPoint &pos);
private:
const SkeletonDocument *m_document;
QUuid m_partId;
@ -40,9 +41,10 @@ private:
QPushButton *m_disableButton;
QPushButton *m_xMirrorButton;
QPushButton *m_zMirrorButton;
QPushButton *m_thicknessButton;
QPushButton *m_deformButton;
QLabel *m_nameLabel;
private:
void initToolButton(QPushButton *button);
void initButton(QPushButton *button);
void updateButton(QPushButton *button, QChar icon, bool highlighted);
};
@ -61,7 +63,7 @@ public slots:
void partSubdivStateChanged(QUuid partId);
void partDisableStateChanged(QUuid partId);
void partXmirrorStateChanged(QUuid partId);
void partThicknessChanged(QUuid partId);
void partDeformChanged(QUuid partId);
private:
const SkeletonDocument *m_document;
std::map<QUuid, QListWidgetItem *> m_itemMap;

View File

@ -33,7 +33,8 @@ int meshlite_get_halfedge_normal_array(void *context, int mesh_id, float *buffer
int meshlite_build(void *context, float *vertex_position_buffer, int vertex_count, int *face_index_buffer, int face_index_buffer_len);
int meshlite_bmesh_create(void *context);
int meshlite_bmesh_set_cut_subdiv_count(void *context, int bmesh_id, int subdiv_count);
int meshlite_bmesh_set_thickness(void *context, int bmesh_id, float thickness);
int meshlite_bmesh_set_deform_thickness(void *context, int bmesh_id, float thickness);
int meshlite_bmesh_set_deform_width(void *context, int bmesh_id, float width);
int meshlite_bmesh_enable_debug(void *context, int bmesh_id, int enable);
int meshlite_bmesh_add_node(void *context, int bmesh_id, float x, float y, float z, float radius);
int meshlite_bmesh_add_edge(void *context, int bmesh_id, int first_node_id, int second_node_id);

View File

@ -33,7 +33,8 @@ int meshlite_get_halfedge_normal_array(void *context, int mesh_id, float *buffer
int meshlite_build(void *context, float *vertex_position_buffer, int vertex_count, int *face_index_buffer, int face_index_buffer_len);
int meshlite_bmesh_create(void *context);
int meshlite_bmesh_set_cut_subdiv_count(void *context, int bmesh_id, int subdiv_count);
int meshlite_bmesh_set_thickness(void *context, int bmesh_id, float thickness);
int meshlite_bmesh_set_deform_thickness(void *context, int bmesh_id, float thickness);
int meshlite_bmesh_set_deform_width(void *context, int bmesh_id, float width);
int meshlite_bmesh_enable_debug(void *context, int bmesh_id, int enable);
int meshlite_bmesh_add_node(void *context, int bmesh_id, float x, float y, float z, float radius);
int meshlite_bmesh_add_edge(void *context, int bmesh_id, int first_node_id, int second_node_id);