Rename vertebrata motion
parent
16fa029c63
commit
9309afd587
|
@ -121,9 +121,6 @@ after_test:
|
||||||
- dust3d.exe :/resources/model-bicycle.ds3 -o bicycle.obj
|
- 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.fbx
|
||||||
- dust3d.exe :/resources/model-bicycle.ds3 -o bicycle.glb
|
- 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.obj
|
||||||
- dust3d.exe :/resources/model-dog.ds3 -o dog.fbx
|
- dust3d.exe :/resources/model-dog.ds3 -o dog.fbx
|
||||||
- dust3d.exe :/resources/model-dog.ds3 -o dog.glb
|
- dust3d.exe :/resources/model-dog.ds3 -o dog.glb
|
||||||
|
|
14
dust3d.pro
14
dust3d.pro
|
@ -511,8 +511,8 @@ HEADERS += src/genericspineandpseudophysics.h
|
||||||
SOURCES += src/chainsimulator.cpp
|
SOURCES += src/chainsimulator.cpp
|
||||||
HEADERS += src/chainsimulator.h
|
HEADERS += src/chainsimulator.h
|
||||||
|
|
||||||
SOURCES += src/vertebratamotion.cpp
|
SOURCES += src/vertebratamovemotionbuilder.cpp
|
||||||
HEADERS += src/vertebratamotion.h
|
HEADERS += src/vertebratamovemotionbuilder.h
|
||||||
|
|
||||||
SOURCES += src/simplerendermeshgenerator.cpp
|
SOURCES += src/simplerendermeshgenerator.cpp
|
||||||
HEADERS += src/simplerendermeshgenerator.h
|
HEADERS += src/simplerendermeshgenerator.h
|
||||||
|
@ -520,8 +520,8 @@ HEADERS += src/simplerendermeshgenerator.h
|
||||||
SOURCES += src/motioneditwidget.cpp
|
SOURCES += src/motioneditwidget.cpp
|
||||||
HEADERS += src/motioneditwidget.h
|
HEADERS += src/motioneditwidget.h
|
||||||
|
|
||||||
SOURCES += src/vertebratamotionparameterswidget.cpp
|
SOURCES += src/vertebratamovemotionparameterswidget.cpp
|
||||||
HEADERS += src/vertebratamotionparameterswidget.h
|
HEADERS += src/vertebratamovemotionparameterswidget.h
|
||||||
|
|
||||||
SOURCES += src/objectxml.cpp
|
SOURCES += src/objectxml.cpp
|
||||||
HEADERS += src/objectxml.h
|
HEADERS += src/objectxml.h
|
||||||
|
@ -529,6 +529,12 @@ HEADERS += src/objectxml.h
|
||||||
SOURCES += src/rigxml.cpp
|
SOURCES += src/rigxml.cpp
|
||||||
HEADERS += src/rigxml.h
|
HEADERS += src/rigxml.h
|
||||||
|
|
||||||
|
SOURCES += src/ragdoll.cpp
|
||||||
|
HEADERS += src/ragdoll.h
|
||||||
|
|
||||||
|
SOURCES += src/motionbuilder.cpp
|
||||||
|
HEADERS += src/motionbuilder.h
|
||||||
|
|
||||||
SOURCES += src/main.cpp
|
SOURCES += src/main.cpp
|
||||||
|
|
||||||
HEADERS += src/version.h
|
HEADERS += src/version.h
|
||||||
|
|
|
@ -36,7 +36,7 @@ void ChainSimulator::start()
|
||||||
initializeVertexMotions();
|
initializeVertexMotions();
|
||||||
prepareChains();
|
prepareChains();
|
||||||
|
|
||||||
outputChainsForDebug("debug-chains.obj", m_chains);
|
//outputChainsForDebug("debug-chains.obj", m_chains);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChainSimulator::VertexMotion &ChainSimulator::getVertexMotion(size_t vertexIndex)
|
const ChainSimulator::VertexMotion &ChainSimulator::getVertexMotion(size_t vertexIndex)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "motionbuilder.h"
|
|
@ -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
|
|
@ -13,7 +13,7 @@
|
||||||
#include "motionsgenerator.h"
|
#include "motionsgenerator.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "vertebratamotionparameterswidget.h"
|
#include "vertebratamovemotionparameterswidget.h"
|
||||||
|
|
||||||
MotionEditWidget::~MotionEditWidget()
|
MotionEditWidget::~MotionEditWidget()
|
||||||
{
|
{
|
||||||
|
@ -94,8 +94,8 @@ MotionEditWidget::MotionEditWidget()
|
||||||
|
|
||||||
void MotionEditWidget::updateParametersArea()
|
void MotionEditWidget::updateParametersArea()
|
||||||
{
|
{
|
||||||
VertebrataMotionParametersWidget *widget = new VertebrataMotionParametersWidget(m_parameters);
|
VertebrataMoveMotionParametersWidget *widget = new VertebrataMoveMotionParametersWidget(m_parameters);
|
||||||
connect(widget, &VertebrataMotionParametersWidget::parametersChanged, this, [=]() {
|
connect(widget, &VertebrataMoveMotionParametersWidget::parametersChanged, this, [=]() {
|
||||||
this->m_parameters = widget->getParameters();
|
this->m_parameters = widget->getParameters();
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include "vertebratamotion.h"
|
|
||||||
#include "rig.h"
|
#include "rig.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QMatrix4x4>
|
#include <QMatrix4x4>
|
||||||
#include "motionsgenerator.h"
|
#include "motionsgenerator.h"
|
||||||
#include "vertebratamotion.h"
|
#include "vertebratamovemotionbuilder.h"
|
||||||
#include "blockmesh.h"
|
#include "blockmesh.h"
|
||||||
#include "vertebratamotionparameterswidget.h"
|
#include "vertebratamovemotionparameterswidget.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
MotionsGenerator::MotionsGenerator(RigType rigType,
|
MotionsGenerator::MotionsGenerator(RigType rigType,
|
||||||
|
@ -141,7 +141,7 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
|
|
||||||
double radiusScale = 0.5;
|
double radiusScale = 0.5;
|
||||||
|
|
||||||
std::vector<VertebrataMotion::Node> spineNodes;
|
std::vector<MotionBuilder::Node> spineNodes;
|
||||||
if (!spineBones.empty()) {
|
if (!spineBones.empty()) {
|
||||||
const auto &it = spineBones[0];
|
const auto &it = spineBones[0];
|
||||||
if (it.second) {
|
if (it.second) {
|
||||||
|
@ -175,14 +175,14 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VertebrataMotion *vertebrataMotion = new VertebrataMotion;
|
VertebrataMoveMotionBuilder *vertebrataMoveMotionBuilder = new VertebrataMoveMotionBuilder;
|
||||||
|
|
||||||
VertebrataMotion::Parameters parameters =
|
VertebrataMoveMotionBuilder::Parameters parameters =
|
||||||
VertebrataMotionParametersWidget::toVertebrataMotionParameters(m_motions[motionId]);
|
VertebrataMoveMotionParametersWidget::toVertebrataMoveMotionParameters(m_motions[motionId]);
|
||||||
if ("Vertical" == valueOfKeyInMapOrEmpty(m_bones[0].attributes, "spineDirection"))
|
if ("Vertical" == valueOfKeyInMapOrEmpty(m_bones[0].attributes, "spineDirection"))
|
||||||
parameters.biped = true;
|
parameters.biped = true;
|
||||||
vertebrataMotion->setParameters(parameters);
|
vertebrataMoveMotionBuilder->setParameters(parameters);
|
||||||
vertebrataMotion->setSpineNodes(spineNodes);
|
vertebrataMoveMotionBuilder->setSpineNodes(spineNodes);
|
||||||
|
|
||||||
double groundY = std::numeric_limits<double>::max();
|
double groundY = std::numeric_limits<double>::max();
|
||||||
for (const auto &it: spineNodes) {
|
for (const auto &it: spineNodes) {
|
||||||
|
@ -191,12 +191,12 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &chain: chains) {
|
for (const auto &chain: chains) {
|
||||||
std::vector<VertebrataMotion::Node> legNodes;
|
std::vector<MotionBuilder::Node> legNodes;
|
||||||
VertebrataMotion::Side side;
|
MotionBuilder::Side side;
|
||||||
if (chain.first.startsWith("LeftLimb")) {
|
if (chain.first.startsWith("LeftLimb")) {
|
||||||
side = VertebrataMotion::Side::Left;
|
side = MotionBuilder::Side::Left;
|
||||||
} else if (chain.first.startsWith("RightLimb")) {
|
} else if (chain.first.startsWith("RightLimb")) {
|
||||||
side = VertebrataMotion::Side::Right;
|
side = MotionBuilder::Side::Right;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -221,14 +221,14 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
it,
|
it,
|
||||||
true});
|
true});
|
||||||
}
|
}
|
||||||
vertebrataMotion->setLegNodes(findSpine->second, side, legNodes);
|
vertebrataMoveMotionBuilder->setLegNodes(findSpine->second, side, legNodes);
|
||||||
for (const auto &it: legNodes) {
|
for (const auto &it: legNodes) {
|
||||||
if (it.position.y() - it.radius < groundY)
|
if (it.position.y() - it.radius < groundY)
|
||||||
groundY = it.position.y() - it.radius;
|
groundY = it.position.y() - it.radius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vertebrataMotion->setGroundY(groundY);
|
vertebrataMoveMotionBuilder->setGroundY(groundY);
|
||||||
vertebrataMotion->generate();
|
vertebrataMoveMotionBuilder->generate();
|
||||||
|
|
||||||
std::vector<std::pair<float, JointNodeTree>> jointNodeTrees;
|
std::vector<std::pair<float, JointNodeTree>> jointNodeTrees;
|
||||||
std::vector<std::pair<float, SimpleShaderMesh *>> previewMeshes;
|
std::vector<std::pair<float, SimpleShaderMesh *>> previewMeshes;
|
||||||
|
@ -249,9 +249,9 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
bindTransforms[i] = parentMatrix * translationMatrix;
|
bindTransforms[i] = parentMatrix * translationMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &vertebrataMotionFrames = vertebrataMotion->frames();
|
const auto &vertebrataMoveMotionBuilderFrames = vertebrataMoveMotionBuilder->frames();
|
||||||
for (size_t frameIndex = 0; frameIndex < vertebrataMotionFrames.size(); ++frameIndex) {
|
for (size_t frameIndex = 0; frameIndex < vertebrataMoveMotionBuilderFrames.size(); ++frameIndex) {
|
||||||
const auto &frame = vertebrataMotionFrames[frameIndex];
|
const auto &frame = vertebrataMoveMotionBuilderFrames[frameIndex];
|
||||||
std::vector<RigBone> transformedBones = m_bones;
|
std::vector<RigBone> transformedBones = m_bones;
|
||||||
for (const auto &node: frame) {
|
for (const auto &node: frame) {
|
||||||
if (-1 == node.boneIndex)
|
if (-1 == node.boneIndex)
|
||||||
|
@ -356,7 +356,7 @@ void MotionsGenerator::generateMotion(const QUuid &motionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_snapshotMeshesEnabled) {
|
if (m_snapshotMeshesEnabled) {
|
||||||
if (frameIndex == vertebrataMotionFrames.size() / 2) {
|
if (frameIndex == vertebrataMoveMotionBuilderFrames.size() / 2) {
|
||||||
delete snapshotMesh;
|
delete snapshotMesh;
|
||||||
snapshotMesh = new Model(frameVertices, frameFaces, frameCornerNormals);
|
snapshotMesh = new Model(frameVertices, frameFaces, frameCornerNormals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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
|
|
@ -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> ¶meters=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> ¶meters);
|
|
||||||
private:
|
|
||||||
std::map<QString, QString> m_parameters;
|
|
||||||
VertebrataMotion::Parameters m_vertebrataMotionParameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,18 +1,18 @@
|
||||||
#include "vertebratamotion.h"
|
#include "vertebratamovemotionbuilder.h"
|
||||||
#include "genericspineandpseudophysics.h"
|
#include "genericspineandpseudophysics.h"
|
||||||
#include "hermitecurveinterpolation.h"
|
#include "hermitecurveinterpolation.h"
|
||||||
#include "chainsimulator.h"
|
#include "chainsimulator.h"
|
||||||
#include "ccdikresolver.h"
|
#include "ccdikresolver.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
void VertebrataMotion::prepareLegHeights()
|
void VertebrataMoveMotionBuilder::prepareLegHeights()
|
||||||
{
|
{
|
||||||
GenericSpineAndPseudoPhysics physics;
|
GenericSpineAndPseudoPhysics physics;
|
||||||
physics.calculateFootHeights(m_parameters.hipHeight,
|
physics.calculateFootHeights(m_parameters.hipHeight,
|
||||||
m_parameters.stanceTime, m_parameters.swingTime, &m_legHeights, &m_legMoveOffsets);
|
m_parameters.stanceTime, m_parameters.swingTime, &m_legHeights, &m_legMoveOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertebrataMotion::prepareLegs()
|
void VertebrataMoveMotionBuilder::prepareLegs()
|
||||||
{
|
{
|
||||||
m_legs.clear();
|
m_legs.clear();
|
||||||
for (size_t spineNodeIndex = 0;
|
for (size_t spineNodeIndex = 0;
|
||||||
|
@ -40,7 +40,7 @@ void VertebrataMotion::prepareLegs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertebrataMotion::prepareLegHeightIndices()
|
void VertebrataMoveMotionBuilder::prepareLegHeightIndices()
|
||||||
{
|
{
|
||||||
int balancedStart = 0;
|
int balancedStart = 0;
|
||||||
for (int side = 0; side < 3; ++side) {
|
for (int side = 0; side < 3; ++side) {
|
||||||
|
@ -60,7 +60,7 @@ void VertebrataMotion::prepareLegHeightIndices()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertebrataMotion::calculateSpineJoints()
|
void VertebrataMoveMotionBuilder::calculateSpineJoints()
|
||||||
{
|
{
|
||||||
HermiteCurveInterpolation spineInterpolation;
|
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) {
|
auto calculateLegTargetTop = [&](size_t legIndex) {
|
||||||
double sumTop = 0.0;
|
double sumTop = 0.0;
|
||||||
|
@ -240,7 +240,7 @@ void VertebrataMotion::calculateLegMoves(size_t heightIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertebrataMotion::generate()
|
void VertebrataMoveMotionBuilder::generate()
|
||||||
{
|
{
|
||||||
prepareLegHeights();
|
prepareLegHeights();
|
||||||
prepareLegs();
|
prepareLegs();
|
|
@ -1,11 +1,12 @@
|
||||||
#ifndef DUST3D_VERTEBRATA_MOTION_H
|
#ifndef DUST3D_VERTEBRATA_MOVE_MOTION_H
|
||||||
#define DUST3D_VERTEBRATA_MOTION_H
|
#define DUST3D_VERTEBRATA_MOVE_MOTION_H
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include "motionbuilder.h"
|
||||||
|
|
||||||
class VertebrataMotion
|
class VertebrataMoveMotionBuilder : public MotionBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Parameters
|
struct Parameters
|
||||||
|
@ -24,21 +25,6 @@ public:
|
||||||
bool biped = false;
|
bool biped = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Node
|
|
||||||
{
|
|
||||||
QVector3D position;
|
|
||||||
double radius;
|
|
||||||
int boneIndex = -1;
|
|
||||||
bool isTail = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Side
|
|
||||||
{
|
|
||||||
Middle = 0,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Leg
|
struct Leg
|
||||||
{
|
{
|
||||||
std::vector<std::vector<Node>> nodes;
|
std::vector<std::vector<Node>> nodes;
|
||||||
|
@ -49,7 +35,8 @@ public:
|
||||||
double move[3] = {0, 0, 0};
|
double move[3] = {0, 0, 0};
|
||||||
};
|
};
|
||||||
|
|
||||||
VertebrataMotion()
|
VertebrataMoveMotionBuilder() :
|
||||||
|
MotionBuilder()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include "vertebratamotionparameterswidget.h"
|
#include "vertebratamovemotionparameterswidget.h"
|
||||||
#include "util.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;
|
std::map<QString, QString> parameters;
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ std::map<QString, QString> VertebrataMotionParametersWidget::fromVertebrataMotio
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
VertebrataMotion::Parameters VertebrataMotionParametersWidget::toVertebrataMotionParameters(const std::map<QString, QString> ¶meters)
|
VertebrataMoveMotionBuilder::Parameters VertebrataMoveMotionParametersWidget::toVertebrataMoveMotionParameters(const std::map<QString, QString> ¶meters)
|
||||||
{
|
{
|
||||||
VertebrataMotion::Parameters vertebrataMotionParameters;
|
VertebrataMoveMotionBuilder::Parameters vertebrataMotionParameters;
|
||||||
|
|
||||||
if (parameters.end() != parameters.find("stanceTime"))
|
if (parameters.end() != parameters.find("stanceTime"))
|
||||||
vertebrataMotionParameters.stanceTime = valueOfKeyInMapOrEmpty(parameters, "stanceTime").toDouble();
|
vertebrataMotionParameters.stanceTime = valueOfKeyInMapOrEmpty(parameters, "stanceTime").toDouble();
|
||||||
|
@ -53,10 +53,10 @@ VertebrataMotion::Parameters VertebrataMotionParametersWidget::toVertebrataMotio
|
||||||
return vertebrataMotionParameters;
|
return vertebrataMotionParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::map<QString, QString> ¶meters) :
|
VertebrataMoveMotionParametersWidget::VertebrataMoveMotionParametersWidget(const std::map<QString, QString> ¶meters) :
|
||||||
m_parameters(parameters)
|
m_parameters(parameters)
|
||||||
{
|
{
|
||||||
m_vertebrataMotionParameters = toVertebrataMotionParameters(m_parameters);
|
m_vertebrataMotionParameters = toVertebrataMoveMotionParameters(m_parameters);
|
||||||
|
|
||||||
QFormLayout *parametersLayout = new QFormLayout;
|
QFormLayout *parametersLayout = new QFormLayout;
|
||||||
parametersLayout->setSpacing(0);
|
parametersLayout->setSpacing(0);
|
||||||
|
@ -67,7 +67,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Stance time: "), stanceTimeBox);
|
parametersLayout->addRow(tr("Stance time: "), stanceTimeBox);
|
||||||
connect(stanceTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(stanceTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.stanceTime = value;
|
m_vertebrataMotionParameters.stanceTime = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Swing time: "), swingTimeBox);
|
parametersLayout->addRow(tr("Swing time: "), swingTimeBox);
|
||||||
connect(swingTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(swingTimeBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.swingTime = value;
|
m_vertebrataMotionParameters.swingTime = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Hip height: "), hipHeightBox);
|
parametersLayout->addRow(tr("Hip height: "), hipHeightBox);
|
||||||
connect(hipHeightBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(hipHeightBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.hipHeight = value;
|
m_vertebrataMotionParameters.hipHeight = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Arm length: "), armLengthBox);
|
parametersLayout->addRow(tr("Arm length: "), armLengthBox);
|
||||||
connect(armLengthBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(armLengthBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.armLength = value;
|
m_vertebrataMotionParameters.armLength = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Leg side intval: "), legSideIntvalBox);
|
parametersLayout->addRow(tr("Leg side intval: "), legSideIntvalBox);
|
||||||
connect(legSideIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(legSideIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.legSideIntval = value;
|
m_vertebrataMotionParameters.legSideIntval = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Leg balance intval: "), legBalanceIntvalBox);
|
parametersLayout->addRow(tr("Leg balance intval: "), legBalanceIntvalBox);
|
||||||
connect(legBalanceIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(legBalanceIntvalBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.legBalanceIntval = value;
|
m_vertebrataMotionParameters.legBalanceIntval = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Spine stability: "), spineStabilityBox);
|
parametersLayout->addRow(tr("Spine stability: "), spineStabilityBox);
|
||||||
connect(spineStabilityBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(spineStabilityBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.spineStability = value;
|
m_vertebrataMotionParameters.spineStability = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Cycles: "), cyclesBox);
|
parametersLayout->addRow(tr("Cycles: "), cyclesBox);
|
||||||
connect(cyclesBox, QOverload<int>::of(&QSpinBox::valueChanged), [&](int value){
|
connect(cyclesBox, QOverload<int>::of(&QSpinBox::valueChanged), [&](int value){
|
||||||
m_vertebrataMotionParameters.cycles = value;
|
m_vertebrataMotionParameters.cycles = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Ground offset: "), groundOffsetBox);
|
parametersLayout->addRow(tr("Ground offset: "), groundOffsetBox);
|
||||||
connect(groundOffsetBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(groundOffsetBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.groundOffset = value;
|
m_vertebrataMotionParameters.groundOffset = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Tail lift force: "), tailLiftForceBox);
|
parametersLayout->addRow(tr("Tail lift force: "), tailLiftForceBox);
|
||||||
connect(tailLiftForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(tailLiftForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.tailLiftForce = value;
|
m_vertebrataMotionParameters.tailLiftForce = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ VertebrataMotionParametersWidget::VertebrataMotionParametersWidget(const std::ma
|
||||||
parametersLayout->addRow(tr("Tail drag force: "), tailDragForceBox);
|
parametersLayout->addRow(tr("Tail drag force: "), tailDragForceBox);
|
||||||
connect(tailDragForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
connect(tailDragForceBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), [&](double value){
|
||||||
m_vertebrataMotionParameters.tailDragForce = value;
|
m_vertebrataMotionParameters.tailDragForce = value;
|
||||||
m_parameters = fromVertebrataMotionParameters(m_vertebrataMotionParameters);
|
m_parameters = fromVertebrataMoveMotionParameters(m_vertebrataMotionParameters);
|
||||||
emit parametersChanged();
|
emit parametersChanged();
|
||||||
});
|
});
|
||||||
|
|
|
@ -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> ¶meters=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> ¶meters);
|
||||||
|
private:
|
||||||
|
std::map<QString, QString> m_parameters;
|
||||||
|
VertebrataMoveMotionBuilder::Parameters m_vertebrataMotionParameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue