Add translation parameter for pose editor

master
Jeremy Hu 2018-11-02 13:43:01 +08:00
parent 0d45d65b98
commit e7249db089
8 changed files with 101 additions and 1 deletions

View File

@ -38,6 +38,19 @@ void GenericPoser::commit()
m_jointNodeTree.updateRotation(boneIndex, rotation);
continue;
}
auto findXResult = item.second.find("x");
auto findYResult = item.second.find("y");
auto findZResult = item.second.find("z");
if (findXResult != item.second.end() ||
findYResult != item.second.end() ||
findZResult != item.second.end()) {
float x = valueOfKeyInMapOrEmpty(item.second, "x").toFloat();
float y = valueOfKeyInMapOrEmpty(item.second, "y").toFloat();
float z = valueOfKeyInMapOrEmpty(item.second, "z").toFloat();
QVector3D translation = {x, y, z};
m_jointNodeTree.addTranslation(boneIndex, translation);
continue;
}
}
Poser::commit();

View File

@ -304,6 +304,9 @@ bool GenericRigger::rig()
bodyBone.index = m_resultBones.size() - 1;
bodyBone.name = "Body";
bodyBone.headPosition = QVector3D(0, 0, 0);
bodyBone.hasButton = true;
bodyBone.button = {spineNodes.size(), 0};
bodyBone.buttonParameterType = RiggerButtonParameterType::Translation;
boneIndexMap[bodyBone.name] = bodyBone.index;
auto remainingSpineVerticies = bodyVerticies;

View File

@ -11,6 +11,16 @@ void JointNodeTree::updateRotation(int index, QQuaternion rotation)
m_boneNodes[index].rotation = rotation;
}
void JointNodeTree::updateTranslation(int index, QVector3D translation)
{
m_boneNodes[index].translation = translation;
}
void JointNodeTree::addTranslation(int index, QVector3D translation)
{
m_boneNodes[index].translation += translation;
}
void JointNodeTree::reset()
{
for (auto &node: m_boneNodes) {
@ -80,6 +90,7 @@ JointNodeTree JointNodeTree::slerp(const JointNodeTree &first, const JointNodeTr
for (decltype(first.nodes().size()) i = 0; i < first.nodes().size() && i < second.nodes().size(); i++) {
slerpResult.updateRotation(i,
quaternionOvershootSlerp(first.nodes()[i].rotation, second.nodes()[i].rotation, t));
slerpResult.updateTranslation(i, (first.nodes()[i].translation * (1.0 - t) + second.nodes()[i].translation * t));
}
slerpResult.recalculateTransformMatrices();
return slerpResult;

View File

@ -23,6 +23,8 @@ public:
const std::vector<JointNode> &nodes() const;
JointNodeTree(const std::vector<RiggerBone> *resultRigBones);
void updateRotation(int index, QQuaternion rotation);
void updateTranslation(int index, QVector3D translation);
void addTranslation(int index, QVector3D translation);
void reset();
void recalculateTransformMatrices();
static JointNodeTree slerp(const JointNodeTree &first, const JointNodeTree &second, float t);

View File

@ -294,6 +294,60 @@ void PoseEditWidget::showPopupAngleDialog(QString boneName, PopupWidgetType popu
intersectionLayout->addWidget(intersectionEraser);
intersectionLayout->addWidget(intersectionWidget);
layout->addLayout(intersectionLayout);
} else if (PopupWidgetType::Translation == popupWidgetType) {
FloatNumberWidget *xWidget = new FloatNumberWidget;
xWidget->setItemName(tr("X"));
xWidget->setRange(-1, 1);
xWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "x").toFloat());
connect(xWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
m_parameters[boneName]["x"] = QString::number(value);
emit parametersAdjusted();
});
QPushButton *xEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeMiniButton(xEraser);
connect(xEraser, &QPushButton::clicked, this, [=]() {
xWidget->setValue(0.0);
});
QHBoxLayout *xLayout = new QHBoxLayout;
xLayout->addWidget(xEraser);
xLayout->addWidget(xWidget);
layout->addLayout(xLayout);
FloatNumberWidget *yWidget = new FloatNumberWidget;
yWidget->setItemName(tr("Y"));
yWidget->setRange(-1, 1);
yWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "y").toFloat());
connect(yWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
m_parameters[boneName]["y"] = QString::number(value);
emit parametersAdjusted();
});
QPushButton *yEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeMiniButton(yEraser);
connect(yEraser, &QPushButton::clicked, this, [=]() {
yWidget->setValue(0.0);
});
QHBoxLayout *yLayout = new QHBoxLayout;
yLayout->addWidget(yEraser);
yLayout->addWidget(yWidget);
layout->addLayout(yLayout);
FloatNumberWidget *zWidget = new FloatNumberWidget;
zWidget->setItemName(tr("Z"));
zWidget->setRange(-1, 1);
zWidget->setValue(valueOfKeyInMapOrEmpty(m_parameters[boneName], "z").toFloat());
connect(zWidget, &FloatNumberWidget::valueChanged, this, [=](float value) {
m_parameters[boneName]["z"] = QString::number(value);
emit parametersAdjusted();
});
QPushButton *zEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeMiniButton(zEraser);
connect(zEraser, &QPushButton::clicked, this, [=]() {
zWidget->setValue(0.0);
});
QHBoxLayout *zLayout = new QHBoxLayout;
zLayout->addWidget(zEraser);
zLayout->addWidget(zWidget);
layout->addLayout(zLayout);
}
popup->setLayout(layout);

View File

@ -15,7 +15,8 @@ enum class RiggerButtonParameterType
{
None = 0,
PitchYawRoll,
Intersection
Intersection,
Translation
};
class RiggerMark

View File

@ -65,6 +65,19 @@ void TetrapodPoser::commit()
}
continue;
}
auto findXResult = item.second.find("x");
auto findYResult = item.second.find("y");
auto findZResult = item.second.find("z");
if (findXResult != item.second.end() ||
findYResult != item.second.end() ||
findZResult != item.second.end()) {
float x = valueOfKeyInMapOrEmpty(item.second, "x").toFloat();
float y = valueOfKeyInMapOrEmpty(item.second, "y").toFloat();
float z = valueOfKeyInMapOrEmpty(item.second, "z").toFloat();
QVector3D translation = {x, y, z};
m_jointNodeTree.addTranslation(boneIndex, translation);
continue;
}
}
Poser::commit();

View File

@ -374,6 +374,9 @@ bool TetrapodRigger::rig()
bodyBone.name = "Body";
bodyBone.headPosition = QVector3D(0, 0, 0);
bodyBone.tailPosition = bonesOrigin;
bodyBone.hasButton = true;
bodyBone.button = {7, 1};
bodyBone.buttonParameterType = RiggerButtonParameterType::Translation;
boneIndexMap[bodyBone.name] = bodyBone.index;
m_resultBones.push_back(RiggerBone());