Rename vertebrata motion

master
huxingyi 2020-12-09 22:22:07 +09:30
parent 16fa029c63
commit 9309afd587
15 changed files with 346 additions and 103 deletions

View File

@ -121,9 +121,6 @@ after_test:
- dust3d.exe :/resources/model-bicycle.ds3 -o bicycle.obj
- dust3d.exe :/resources/model-bicycle.ds3 -o bicycle.fbx
- dust3d.exe :/resources/model-bicycle.ds3 -o bicycle.glb
- dust3d.exe :/resources/model-bob.ds3 -o bob.obj
- dust3d.exe :/resources/model-bob.ds3 -o bob.fbx
- dust3d.exe :/resources/model-bob.ds3 -o bob.glb
- dust3d.exe :/resources/model-dog.ds3 -o dog.obj
- dust3d.exe :/resources/model-dog.ds3 -o dog.fbx
- dust3d.exe :/resources/model-dog.ds3 -o dog.glb

View File

@ -511,8 +511,8 @@ HEADERS += src/genericspineandpseudophysics.h
SOURCES += src/chainsimulator.cpp
HEADERS += src/chainsimulator.h
SOURCES += src/vertebratamotion.cpp
HEADERS += src/vertebratamotion.h
SOURCES += src/vertebratamovemotionbuilder.cpp
HEADERS += src/vertebratamovemotionbuilder.h
SOURCES += src/simplerendermeshgenerator.cpp
HEADERS += src/simplerendermeshgenerator.h
@ -520,8 +520,8 @@ HEADERS += src/simplerendermeshgenerator.h
SOURCES += src/motioneditwidget.cpp
HEADERS += src/motioneditwidget.h
SOURCES += src/vertebratamotionparameterswidget.cpp
HEADERS += src/vertebratamotionparameterswidget.h
SOURCES += src/vertebratamovemotionparameterswidget.cpp
HEADERS += src/vertebratamovemotionparameterswidget.h
SOURCES += src/objectxml.cpp
HEADERS += src/objectxml.h
@ -529,6 +529,12 @@ HEADERS += src/objectxml.h
SOURCES += src/rigxml.cpp
HEADERS += src/rigxml.h
SOURCES += src/ragdoll.cpp
HEADERS += src/ragdoll.h
SOURCES += src/motionbuilder.cpp
HEADERS += src/motionbuilder.h
SOURCES += src/main.cpp
HEADERS += src/version.h

View File

@ -36,7 +36,7 @@ void ChainSimulator::start()
initializeVertexMotions();
prepareChains();
outputChainsForDebug("debug-chains.obj", m_chains);
//outputChainsForDebug("debug-chains.obj", m_chains);
}
const ChainSimulator::VertexMotion &ChainSimulator::getVertexMotion(size_t vertexIndex)

1
src/motionbuilder.cpp Normal file
View File

@ -0,0 +1 @@
#include "motionbuilder.h"

24
src/motionbuilder.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef MOTION_BUILDER_H
#define MOTION_BUILDER_H
#include <QVector3D>
class MotionBuilder
{
public:
struct Node
{
QVector3D position;
double radius;
int boneIndex = -1;
bool isTail = false;
};
enum class Side
{
Middle = 0,
Left,
Right,
};
};
#endif

View File

@ -13,7 +13,7 @@
#include "motionsgenerator.h"
#include "util.h"
#include "version.h"
#include "vertebratamotionparameterswidget.h"
#include "vertebratamovemotionparameterswidget.h"
MotionEditWidget::~MotionEditWidget()
{
@ -94,8 +94,8 @@ MotionEditWidget::MotionEditWidget()
void MotionEditWidget::updateParametersArea()
{
VertebrataMotionParametersWidget *widget = new VertebrataMotionParametersWidget(m_parameters);
connect(widget, &VertebrataMotionParametersWidget::parametersChanged, this, [=]() {
VertebrataMoveMotionParametersWidget *widget = new VertebrataMoveMotionParametersWidget(m_parameters);
connect(widget, &VertebrataMoveMotionParametersWidget::parametersChanged, this, [=]() {
this->m_parameters = widget->getParameters();
emit parametersChanged();
});

View File

@ -5,7 +5,6 @@
#include <queue>
#include <QLineEdit>
#include <QUuid>
#include "vertebratamotion.h"
#include "rig.h"
#include "object.h"

View File

@ -4,9 +4,9 @@
#include <QRegularExpression>
#include <QMatrix4x4>
#include "motionsgenerator.h"
#include "vertebratamotion.h"
#include "vertebratamovemotionbuilder.h"
#include "blockmesh.h"
#include "vertebratamotionparameterswidget.h"
#include "vertebratamovemotionparameterswidget.h"
#include "util.h"
MotionsGenerator::MotionsGenerator(RigType rigType,
@ -141,7 +141,7 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
double radiusScale = 0.5;
std::vector<VertebrataMotion::Node> spineNodes;
std::vector<MotionBuilder::Node> spineNodes;
if (!spineBones.empty()) {
const auto &it = spineBones[0];
if (it.second) {
@ -175,14 +175,14 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
}
}
VertebrataMotion *vertebrataMotion = new VertebrataMotion;
VertebrataMoveMotionBuilder *vertebrataMoveMotionBuilder = new VertebrataMoveMotionBuilder;
VertebrataMotion::Parameters parameters =
VertebrataMotionParametersWidget::toVertebrataMotionParameters(m_motions[motionId]);
VertebrataMoveMotionBuilder::Parameters parameters =
VertebrataMoveMotionParametersWidget::toVertebrataMoveMotionParameters(m_motions[motionId]);
if ("Vertical" == valueOfKeyInMapOrEmpty(m_bones[0].attributes, "spineDirection"))
parameters.biped = true;
vertebrataMotion->setParameters(parameters);
vertebrataMotion->setSpineNodes(spineNodes);
vertebrataMoveMotionBuilder->setParameters(parameters);
vertebrataMoveMotionBuilder->setSpineNodes(spineNodes);
double groundY = std::numeric_limits<double>::max();
for (const auto &it: spineNodes) {
@ -191,12 +191,12 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
}
for (const auto &chain: chains) {
std::vector<VertebrataMotion::Node> legNodes;
VertebrataMotion::Side side;
std::vector<MotionBuilder::Node> legNodes;
MotionBuilder::Side side;
if (chain.first.startsWith("LeftLimb")) {
side = VertebrataMotion::Side::Left;
side = MotionBuilder::Side::Left;
} else if (chain.first.startsWith("RightLimb")) {
side = VertebrataMotion::Side::Right;
side = MotionBuilder::Side::Right;
} else {
continue;
}
@ -221,14 +221,14 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
it,
true});
}
vertebrataMotion->setLegNodes(findSpine->second, side, legNodes);
vertebrataMoveMotionBuilder->setLegNodes(findSpine->second, side, legNodes);
for (const auto &it: legNodes) {
if (it.position.y() - it.radius < groundY)
groundY = it.position.y() - it.radius;
}
}
vertebrataMotion->setGroundY(groundY);
vertebrataMotion->generate();
vertebrataMoveMotionBuilder->setGroundY(groundY);
vertebrataMoveMotionBuilder->generate();
std::vector<std::pair<float, JointNodeTree>> jointNodeTrees;
std::vector<std::pair<float, SimpleShaderMesh *>> previewMeshes;
@ -249,9 +249,9 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
bindTransforms[i] = parentMatrix * translationMatrix;
}
const auto &vertebrataMotionFrames = vertebrataMotion->frames();
for (size_t frameIndex = 0; frameIndex < vertebrataMotionFrames.size(); ++frameIndex) {
const auto &frame = vertebrataMotionFrames[frameIndex];
const auto &vertebrataMoveMotionBuilderFrames = vertebrataMoveMotionBuilder->frames();
for (size_t frameIndex = 0; frameIndex < vertebrataMoveMotionBuilderFrames.size(); ++frameIndex) {
const auto &frame = vertebrataMoveMotionBuilderFrames[frameIndex];
std::vector<RigBone> transformedBones = m_bones;
for (const auto &node: frame) {
if (-1 == node.boneIndex)
@ -356,7 +356,7 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
}
if (m_snapshotMeshesEnabled) {
if (frameIndex == vertebrataMotionFrames.size() / 2) {
if (frameIndex == vertebrataMoveMotionBuilderFrames.size() / 2) {
delete snapshotMesh;
snapshotMesh = new Model(frameVertices, frameFaces, frameCornerNormals);
}

138
src/ragdoll.cpp Normal file
View File

@ -0,0 +1,138 @@
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <QDebug>
#include "ragdoll.h"
#include "util.h"
void Ragdoll::prepareChains()
{
for (const auto &it: *m_links) {
m_chains.push_back({it.first, it.second,
((*m_vertices)[it.first] - (*m_vertices)[it.second]).length()});
}
}
void Ragdoll::initializeVertexMotions()
{
for (size_t i = 0; i < m_vertices->size(); ++i)
m_vertexMotions[i].position = m_vertexMotions[i].lastPosition = (*m_vertices)[i];
}
void Ragdoll::outputChainsForDebug(const char *filename, const std::vector<Chain> &springs)
{
FILE *fp = fopen(filename, "wb");
for (const auto &it: *m_vertices) {
fprintf(fp, "v %f %f %f\n", it[0], it[1], it[2]);
}
for (const auto &it: springs) {
fprintf(fp, "l %zu %zu\n", it.from + 1, it.to + 1);
}
fclose(fp);
}
void Ragdoll::start()
{
initializeVertexMotions();
prepareChains();
//outputChainsForDebug("debug-chains.obj", m_chains);
}
const Ragdoll::VertexMotion &Ragdoll::getVertexMotion(size_t vertexIndex)
{
return m_vertexMotions[vertexIndex];
}
void Ragdoll::updateVertexForces()
{
for (auto &it: m_vertexMotions)
it.second.force = QVector3D();
QVector3D combinedForce = QVector3D(0.0, -9.80665, 0.0) + m_externalForce;
for (auto &it: m_vertexMotions) {
it.second.force += combinedForce;
}
}
void Ragdoll::doVerletIntegration(double stepSize)
{
for (auto &it: m_vertexMotions) {
if (it.second.fixed)
continue;
QVector3D &x = it.second.position;
QVector3D temp = x;
QVector3D &oldX = it.second.lastPosition;
QVector3D a = it.second.force;
x += x - oldX + a * stepSize * stepSize;
oldX = temp;
applyBoundingConstraints(&it.second);
}
}
void Ragdoll::applyBoundingConstraints(VertexMotion *vertexMotion)
{
if (vertexMotion->position.y() < m_groundY + vertexMotion->radius)
vertexMotion->position.setY(m_groundY + vertexMotion->radius);
}
void Ragdoll::applyConstraints()
{
for (size_t iteration = 0; iteration < m_parameters.iterations; ++iteration) {
for (auto &it: m_chains) {
auto &from = m_vertexMotions[it.from];
auto &to = m_vertexMotions[it.to];
auto delta = from.position - to.position;
auto deltaLength = delta.length();
if (qFuzzyCompare(deltaLength, 0.0f))
continue;
auto diff = (it.restLength - deltaLength) / deltaLength;
auto offset = delta * 0.5 * diff;
if (!from.fixed) {
from.position += offset;
applyBoundingConstraints(&from);
}
if (!to.fixed) {
to.position += -offset;
applyBoundingConstraints(&to);
}
}
for (const auto &it: m_jointConstraints) {
auto &from = m_vertexMotions[it.first];
auto &to = m_vertexMotions[it.second];
auto &joint = m_vertexMotions[it.joint];
double degrees = degreesBetweenVectors(from.position - joint.position,
to.position - joint.position);
if (degrees < it.minDegrees) {
QVector3D straightPosition = (from.position + to.position) * 0.5;
joint.position += (it.minDegrees - degrees) * (straightPosition - joint.position) / (180 - degrees);
applyBoundingConstraints(&joint);
} else if (degrees > it.maxDegrees) {
// TODO:
}
}
}
}
void Ragdoll::updateVertexPosition(size_t vertexIndex, const QVector3D &position)
{
m_vertexMotions[vertexIndex].position = position;
}
void Ragdoll::fixVertexPosition(size_t vertexIndex)
{
m_vertexMotions[vertexIndex].fixed = true;
}
void Ragdoll::updateVertexRadius(size_t vertexIndex, double radius)
{
m_vertexMotions[vertexIndex].radius = radius;
}
void Ragdoll::simulate(double stepSize)
{
updateVertexForces();
doVerletIntegration(stepSize);
applyConstraints();
}

91
src/ragdoll.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef DUST3D_RAGDOLL_H
#define DUST3D_RAGDOLL_H
#include <vector>
#include <QVector3D>
#include <unordered_map>
class Ragdoll
{
public:
struct Parameters
{
size_t iterations = 1;
};
struct Chain
{
size_t from;
size_t to;
double restLength;
};
struct VertexMotion
{
QVector3D position;
QVector3D lastPosition;
QVector3D force;
bool fixed = false;
double radius = 0.0;
};
struct JointConstraint
{
size_t joint;
size_t first;
size_t second;
double minDegrees;
double maxDegrees;
};
Ragdoll(const std::vector<QVector3D> *vertices,
const std::vector<std::pair<size_t, size_t>> *links) :
m_vertices(vertices),
m_links(links)
{
}
void addJointConstraint(size_t joint,
size_t first,
size_t second,
double minDegrees,
double maxDegrees)
{
JointConstraint jointConstraint = {
joint, first, second, minDegrees, maxDegrees
};
m_jointConstraints.push_back(jointConstraint);
}
void setExternalForce(const QVector3D &externalForce)
{
m_externalForce = externalForce;
}
void start();
void simulate(double stepSize);
const VertexMotion &getVertexMotion(size_t vertexIndex);
void updateVertexPosition(size_t vertexIndex, const QVector3D &position);
void updateVertexRadius(size_t vertexIndex, double radius);
void fixVertexPosition(size_t vertexIndex);
private:
Parameters m_parameters;
std::vector<Chain> m_chains;
const std::vector<QVector3D> *m_vertices = nullptr;
const std::vector<std::pair<size_t, size_t>> *m_links = nullptr;
std::vector<JointConstraint> m_jointConstraints;
std::unordered_map<size_t, VertexMotion> m_vertexMotions;
QVector3D m_externalForce;
double m_groundY = 0.0;
void initializeVertexMotions();
void prepareChains();
void updateVertexForces();
void applyConstraints();
void doVerletIntegration(double stepSize);
void applyBoundingConstraints(VertexMotion *vertexMotion);
void outputChainsForDebug(const char *filename, const std::vector<Chain> &springs);
};
#endif

View File

@ -1,28 +0,0 @@
#ifndef DUST3D_VERTEBRATA_MOTION_PARAMETERS_WIDGET_H
#define DUST3D_VERTEBRATA_MOTION_PARAMETERS_WIDGET_H
#include <QWidget>
#include <map>
#include <QString>
#include "vertebratamotion.h"
class VertebrataMotionParametersWidget : public QWidget
{
Q_OBJECT
signals:
void parametersChanged();
public:
VertebrataMotionParametersWidget(const std::map<QString, QString> &parameters=std::map<QString, QString>());
const std::map<QString, QString> &getParameters() const
{
return m_parameters;
}
static std::map<QString, QString> fromVertebrataMotionParameters(const VertebrataMotion::Parameters &from);
static VertebrataMotion::Parameters toVertebrataMotionParameters(const std::map<QString, QString> &parameters);
private:
std::map<QString, QString> m_parameters;
VertebrataMotion::Parameters m_vertebrataMotionParameters;
};
#endif

View File

@ -1,18 +1,18 @@
#include "vertebratamotion.h"
#include "vertebratamovemotionbuilder.h"
#include "genericspineandpseudophysics.h"
#include "hermitecurveinterpolation.h"
#include "chainsimulator.h"
#include "ccdikresolver.h"
#include <QDebug>
void VertebrataMotion::prepareLegHeights()
void VertebrataMoveMotionBuilder::prepareLegHeights()
{
GenericSpineAndPseudoPhysics physics;
physics.calculateFootHeights(m_parameters.hipHeight,
m_parameters.stanceTime, m_parameters.swingTime, &m_legHeights, &m_legMoveOffsets);
}
void VertebrataMotion::prepareLegs()
void VertebrataMoveMotionBuilder::prepareLegs()
{
m_legs.clear();
for (size_t spineNodeIndex = 0;
@ -40,7 +40,7 @@ void VertebrataMotion::prepareLegs()
}
}
void VertebrataMotion::prepareLegHeightIndices()
void VertebrataMoveMotionBuilder::prepareLegHeightIndices()
{
int balancedStart = 0;
for (int side = 0; side < 3; ++side) {
@ -60,7 +60,7 @@ void VertebrataMotion::prepareLegHeightIndices()
}
}
void VertebrataMotion::calculateSpineJoints()
void VertebrataMoveMotionBuilder::calculateSpineJoints()
{
HermiteCurveInterpolation spineInterpolation;
@ -112,7 +112,7 @@ void VertebrataMotion::calculateSpineJoints()
}
}
void VertebrataMotion::calculateLegMoves(size_t heightIndex)
void VertebrataMoveMotionBuilder::calculateLegMoves(size_t heightIndex)
{
auto calculateLegTargetTop = [&](size_t legIndex) {
double sumTop = 0.0;
@ -240,7 +240,7 @@ void VertebrataMotion::calculateLegMoves(size_t heightIndex)
}
}
void VertebrataMotion::generate()
void VertebrataMoveMotionBuilder::generate()
{
prepareLegHeights();
prepareLegs();

View File

@ -1,11 +1,12 @@
#ifndef DUST3D_VERTEBRATA_MOTION_H
#define DUST3D_VERTEBRATA_MOTION_H
#ifndef DUST3D_VERTEBRATA_MOVE_MOTION_H
#define DUST3D_VERTEBRATA_MOVE_MOTION_H
#include <QVector3D>
#include <vector>
#include <map>
#include <unordered_map>
#include "motionbuilder.h"
class VertebrataMotion
class VertebrataMoveMotionBuilder : public MotionBuilder
{
public:
struct Parameters
@ -23,22 +24,7 @@ public:
double tailDragForce = 4.0;
bool biped = false;
};
struct Node
{
QVector3D position;
double radius;
int boneIndex = -1;
bool isTail = false;
};
enum class Side
{
Middle = 0,
Left,
Right,
};
struct Leg
{
std::vector<std::vector<Node>> nodes;
@ -49,7 +35,8 @@ public:
double move[3] = {0, 0, 0};
};
VertebrataMotion()
VertebrataMoveMotionBuilder() :
MotionBuilder()
{
}

View File

@ -1,10 +1,10 @@
#include <QFormLayout>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include "vertebratamotionparameterswidget.h"
#include "vertebratamovemotionparameterswidget.h"
#include "util.h"
std::map<QString, QString> VertebrataMotionParametersWidget::fromVertebrataMotionParameters(const VertebrataMotion::Parameters &from)
std::map<QString, QString> VertebrataMoveMotionParametersWidget::fromVertebrataMoveMotionParameters(const VertebrataMoveMotionBuilder::Parameters &from)
{
std::map<QString, QString> parameters;
@ -23,9 +23,9 @@ std::map<QString, QString> VertebrataMotionParametersWidget::fromVertebrataMotio
return parameters;
}
VertebrataMotion::Parameters VertebrataMotionParametersWidget::toVertebrataMotionParameters(const std::map<QString, QString> &parameters)
VertebrataMoveMotionBuilder::Parameters VertebrataMoveMotionParametersWidget::toVertebrataMoveMotionParameters(const std::map<QString, QString> &parameters)
{
VertebrataMotion::Parameters vertebrataMotionParameters;
VertebrataMoveMotionBuilder::Parameters vertebrataMotionParameters;
if (parameters.end() != parameters.find("stanceTime"))
vertebrataMotionParameters.stanceTime = valueOfKeyInMapOrEmpty(parameters, "stanceTime").toDouble();
@ -53,10 +53,10 @@ VertebrataMotion::Parameters VertebrataMotionParametersWidget::toVertebrataMotio
return vertebrataMotionParameters;
}
VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::map<QString, QString> &parameters) :
VertebrataMoveMotionParametersWidget::VertebrataMoveMotionParametersWidget(const std::map<QString, QString> &parameters) :
m_parameters(parameters)
{
m_vertebrataMotionParameters = toVertebrataMotionParameters(m_parameters);
m_vertebrataMotionParameters = toVertebrataMoveMotionParameters(m_parameters);
QFormLayout *parametersLayout = new QFormLayout;
parametersLayout->setSpacing(0);
@ -67,7 +67,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Stance time: "), stanceTimeBox);
connect(stanceTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.stanceTime = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -77,7 +77,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Swing time: "), swingTimeBox);
connect(swingTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.swingTime = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -86,7 +86,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Hip height: "), hipHeightBox);
connect(hipHeightBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.hipHeight = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -95,7 +95,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Arm length: "), armLengthBox);
connect(armLengthBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.armLength = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -104,7 +104,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Leg side intval: "), legSideIntvalBox);
connect(legSideIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.legSideIntval = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -113,7 +113,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Leg balance intval: "), legBalanceIntvalBox);
connect(legBalanceIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.legBalanceIntval = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -122,7 +122,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Spine stability: "), spineStabilityBox);
connect(spineStabilityBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.spineStability = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -131,7 +131,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Cycles: "), cyclesBox);
connect(cyclesBox, QOverload<int>::of(&QSpinBox::valueChanged), [&](int value){
m_vertebrataMotionParameters.cycles = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -141,7 +141,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Ground offset: "), groundOffsetBox);
connect(groundOffsetBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.groundOffset = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -152,7 +152,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Tail lift force: "), tailLiftForceBox);
connect(tailLiftForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.tailLiftForce = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});
@ -162,7 +162,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
parametersLayout->addRow(tr("Tail drag force: "), tailDragForceBox);
connect(tailDragForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
m_vertebrataMotionParameters.tailDragForce = value;
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
emit parametersChanged();
});

View File

@ -0,0 +1,28 @@
#ifndef DUST3D_VERTEBRATA_MOVE_MOTION_PARAMETERS_WIDGET_H
#define DUST3D_VERTEBRATA_MOVE_MOTION_PARAMETERS_WIDGET_H
#include <QWidget>
#include <map>
#include <QString>
#include "vertebratamovemotionbuilder.h"
class VertebrataMoveMotionParametersWidget : public QWidget
{
Q_OBJECT
signals:
void parametersChanged();
public:
VertebrataMoveMotionParametersWidget(const std::map<QString, QString> &parameters=std::map<QString, QString>());
const std::map<QString, QString> &getParameters() const
{
return m_parameters;
}
static std::map<QString, QString> fromVertebrataMoveMotionParameters(const VertebrataMoveMotionBuilder::Parameters &from);
static VertebrataMoveMotionBuilder::Parameters toVertebrataMoveMotionParameters(const std::map<QString, QString> &parameters);
private:
std::map<QString, QString> m_parameters;
VertebrataMoveMotionBuilder::Parameters m_vertebrataMotionParameters;
};
#endif