From 76609197e2387f2b5643f43afbb1416e9340f0be Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 5 Mar 2019 18:50:53 -0700 Subject: [PATCH 1/3] Read flow data from the fst file --- interface/src/avatar/MyAvatar.cpp | 32 +++++++++++++++++++ interface/src/avatar/MyAvatar.h | 1 + libraries/hfm/src/hfm/HFM.h | 9 ++++++ .../model-baker/src/model-baker/Baker.cpp | 9 ++++-- .../src/model-baker/ParseFlowDataTask.cpp | 26 +++++++++++++++ .../src/model-baker/ParseFlowDataTask.h | 24 ++++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp create mode 100644 libraries/model-baker/src/model-baker/ParseFlowDataTask.h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index af261f490b..ecc51132b9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2337,6 +2337,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModel->setCauterizeBoneSet(_headBoneSet); _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); initAnimGraph(); + initFlow(); _skeletonModelLoaded = true; } QObject::disconnect(*skeletonConnection); @@ -5383,6 +5384,37 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys } } +void MyAvatar::initFlow() { + auto &flowData = _skeletonModel->getHFMModel().flowData; + if (flowData._physicsData.size() > 0) { + QVariantMap physicsConfig; + QVariantMap collisionsConfig; + for (auto &data : flowData._physicsData) { + QJsonObject map = QJsonDocument::fromJson(data).object(); + if (!map.isEmpty() && map.keys().size() == 1) { + QString group = map.keys()[0]; + if (map[group].isObject()) { + physicsConfig.insert(group, map[group].toObject().toVariantMap()); + } + } + } + for (auto &data : flowData._collisionsData) { + QJsonObject map = QJsonDocument::fromJson(data).object(); + if (!map.isEmpty() && map.keys().size() == 1) { + QString jointName = map.keys()[0]; + if (map[jointName].isObject()) { + collisionsConfig.insert(jointName, map[jointName].toObject().toVariantMap()); + } + } + } + if (collisionsConfig.size() > 0) { + useFlow(true, true, physicsConfig, collisionsConfig); + } else { + useFlow(true, false, physicsConfig); + } + } +} + void MyAvatar::sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const { auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2c8dedd430..c80412c949 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1751,6 +1751,7 @@ private: void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void initHeadBones(); void initAnimGraph(); + void initFlow(); // Avatar Preferences QUrl _fullAvatarURLFromPreferences; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 9f3de3302c..c2d8b14ba1 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -273,6 +273,13 @@ public: {} }; +class FlowData { +public: + FlowData() {}; + std::vector _physicsData; + std::vector _collisionsData; +}; + /// The runtime model format. class Model { public: @@ -319,6 +326,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; + FlowData flowData; }; }; @@ -343,6 +351,7 @@ typedef hfm::Mesh HFMMesh; typedef hfm::AnimationFrame HFMAnimationFrame; typedef hfm::Light HFMLight; typedef hfm::Model HFMModel; +typedef hfm::FlowData FlowData; Q_DECLARE_METATYPE(HFMAnimationFrame) Q_DECLARE_METATYPE(QVector) diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index dfb18eef86..595f2ae0f7 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -20,6 +20,7 @@ #include "CalculateBlendshapeNormalsTask.h" #include "CalculateBlendshapeTangentsTask.h" #include "PrepareJointsTask.h" +#include "ParseFlowDataTask.h" namespace baker { @@ -101,7 +102,7 @@ namespace baker { class BuildModelTask { public: - using Input = VaryingSet5, std::vector, QMap, QHash>; + using Input = VaryingSet6, std::vector, QMap, QHash, FlowData>; using Output = hfm::Model::Pointer; using JobModel = Job::ModelIO; @@ -111,6 +112,7 @@ namespace baker { hfmModelOut->joints = QVector::fromStdVector(input.get2()); hfmModelOut->jointRotationOffsets = input.get3(); hfmModelOut->jointIndices = input.get4(); + hfmModelOut->flowData = input.get5(); output = hfmModelOut; } }; @@ -157,12 +159,15 @@ namespace baker { // Parse material mapping const auto materialMapping = model.addJob("ParseMaterialMapping", mapping); + // Parse flow data + const auto flowData = model.addJob("ParseFlowData", mapping); + // Combine the outputs into a new hfm::Model const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying(); const auto blendshapesPerMeshOut = model.addJob("BuildBlendshapes", buildBlendshapesInputs); const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying(); const auto meshesOut = model.addJob("BuildMeshes", buildMeshesInputs); - const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices).asVarying(); + const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData).asVarying(); const auto hfmModelOut = model.addJob("BuildModel", buildModelInputs); output = Output(hfmModelOut, materialMapping); diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp new file mode 100644 index 0000000000..1a298b3d4b --- /dev/null +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp @@ -0,0 +1,26 @@ +// +// Created by Luis Cuenca on 5/3/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ParseFlowDataTask.h" + +void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) { + FlowData flowData; + static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData"; + static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData"; + for (auto &mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { + if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) { + QByteArray flowDataValue = mappingIter.value().toByteArray(); + if (mappingIter.key() == FLOW_PHYSICS_FIELD) { + flowData._physicsData.push_back(flowDataValue); + } else { + flowData._collisionsData.push_back(flowDataValue); + } + } + } + output = flowData; +} diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h new file mode 100644 index 0000000000..3c85430165 --- /dev/null +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h @@ -0,0 +1,24 @@ +// +// Created by Luis Cuenca on 3/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ParseFlowDataTask_h +#define hifi_ParseFlowDataTask_h + +#include +#include "Engine.h" + +class ParseFlowDataTask { +public: + using Input = QVariantHash; + using Output = FlowData; + using JobModel = baker::Job::ModelIO; + + void run(const baker::BakeContextPointer& context, const Input& input, Output& output); +}; + +#endif // hifi_ParseFlowDataTask_h From beeeb74f17ea740b4bf573a66c86b7e7ddee76d9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 5 Mar 2019 18:56:02 -0700 Subject: [PATCH 2/3] Fix creation date --- libraries/model-baker/src/model-baker/ParseFlowDataTask.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h index 3c85430165..7e1bc9fba1 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.h +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.h @@ -1,5 +1,5 @@ // -// Created by Luis Cuenca on 3/7/2019 +// Created by Luis Cuenca on 5/3/2019 // Copyright 2019 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. From dfb434ea09d3eb479117023355551daa6b8cb6ca Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 6 Mar 2019 09:25:49 -0700 Subject: [PATCH 3/3] Fix warning and refactoring --- interface/src/avatar/MyAvatar.cpp | 65 +++++++------------ interface/src/avatar/MyAvatar.h | 2 +- libraries/hfm/src/hfm/HFM.h | 6 +- .../src/model-baker/ParseFlowDataTask.cpp | 19 ++++-- 4 files changed, 40 insertions(+), 52 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ecc51132b9..578c1915fd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2323,24 +2323,25 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { - if (skeletonModelChangeCount == _skeletonModelChangeCount) { + if (skeletonModelChangeCount == _skeletonModelChangeCount) { - if (_fullAvatarModelName.isEmpty()) { - // Store the FST file name into preferences - const auto& mapping = _skeletonModel->getGeometry()->getMapping(); - if (mapping.value("name").isValid()) { - _fullAvatarModelName = mapping.value("name").toString(); - } - } + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } - initHeadBones(); - _skeletonModel->setCauterizeBoneSet(_headBoneSet); - _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); - initAnimGraph(); - initFlow(); - _skeletonModelLoaded = true; - } - QObject::disconnect(*skeletonConnection); + initHeadBones(); + _skeletonModel->setCauterizeBoneSet(_headBoneSet); + _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); + initAnimGraph(); + initFlowFromFST(); + + _skeletonModelLoaded = true; + } + QObject::disconnect(*skeletonConnection); }); saveAvatarUrl(); @@ -5384,33 +5385,11 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys } } -void MyAvatar::initFlow() { - auto &flowData = _skeletonModel->getHFMModel().flowData; - if (flowData._physicsData.size() > 0) { - QVariantMap physicsConfig; - QVariantMap collisionsConfig; - for (auto &data : flowData._physicsData) { - QJsonObject map = QJsonDocument::fromJson(data).object(); - if (!map.isEmpty() && map.keys().size() == 1) { - QString group = map.keys()[0]; - if (map[group].isObject()) { - physicsConfig.insert(group, map[group].toObject().toVariantMap()); - } - } - } - for (auto &data : flowData._collisionsData) { - QJsonObject map = QJsonDocument::fromJson(data).object(); - if (!map.isEmpty() && map.keys().size() == 1) { - QString jointName = map.keys()[0]; - if (map[jointName].isObject()) { - collisionsConfig.insert(jointName, map[jointName].toObject().toVariantMap()); - } - } - } - if (collisionsConfig.size() > 0) { - useFlow(true, true, physicsConfig, collisionsConfig); - } else { - useFlow(true, false, physicsConfig); +void MyAvatar::initFlowFromFST() { + if (_skeletonModel->isLoaded()) { + auto &flowData = _skeletonModel->getHFMModel().flowData; + if (flowData.shouldInitFlow()) { + useFlow(true, flowData.shouldInitCollisions(), flowData._physicsConfig, flowData._collisionsConfig); } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c80412c949..46189c4a11 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1751,7 +1751,7 @@ private: void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); void initHeadBones(); void initAnimGraph(); - void initFlow(); + void initFlowFromFST(); // Avatar Preferences QUrl _fullAvatarURLFromPreferences; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index c2d8b14ba1..4f44595eaa 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -276,8 +276,10 @@ public: class FlowData { public: FlowData() {}; - std::vector _physicsData; - std::vector _collisionsData; + QVariantMap _physicsConfig; + QVariantMap _collisionsConfig; + bool shouldInitFlow() const { return _physicsConfig.size() > 0; } + bool shouldInitCollisions() const { return _collisionsConfig.size() > 0; } }; /// The runtime model format. diff --git a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp index 1a298b3d4b..6dff4f8c55 100644 --- a/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp @@ -12,13 +12,20 @@ void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Inpu FlowData flowData; static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData"; static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData"; - for (auto &mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { + for (auto mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) { if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) { - QByteArray flowDataValue = mappingIter.value().toByteArray(); - if (mappingIter.key() == FLOW_PHYSICS_FIELD) { - flowData._physicsData.push_back(flowDataValue); - } else { - flowData._collisionsData.push_back(flowDataValue); + QByteArray data = mappingIter.value().toByteArray(); + QJsonObject dataObject = QJsonDocument::fromJson(data).object(); + if (!dataObject.isEmpty() && dataObject.keys().size() == 1) { + QString key = dataObject.keys()[0]; + if (dataObject[key].isObject()) { + QVariantMap dataMap = dataObject[key].toObject().toVariantMap(); + if (mappingIter.key() == FLOW_PHYSICS_FIELD) { + flowData._physicsConfig.insert(key, dataMap); + } else { + flowData._collisionsConfig.insert(key, dataMap); + } + } } } }