From 327c2f4e3d8be6296cc454c7dc5f3b9dfffd2653 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Oct 2018 12:15:05 -0700 Subject: [PATCH 1/6] move blendshape buffers to render thread --- .../src/avatars-renderer/Avatar.cpp | 26 ++++++- .../src/avatars-renderer/Avatar.h | 4 +- .../src/RenderableModelEntityItem.h | 2 - .../render-utils/src/CauterizedModel.cpp | 4 +- .../render-utils/src/MeshPartPayload.cpp | 35 ++++----- libraries/render-utils/src/MeshPartPayload.h | 5 +- .../render-utils/src/MetaModelPayload.cpp | 55 ++++++++++++++ libraries/render-utils/src/MetaModelPayload.h | 30 ++++++++ libraries/render-utils/src/Model.cpp | 71 ++++++++----------- libraries/render-utils/src/Model.h | 29 +++----- .../render-utils/src/SoftAttachmentModel.cpp | 2 +- 11 files changed, 175 insertions(+), 88 deletions(-) create mode 100644 libraries/render-utils/src/MetaModelPayload.cpp create mode 100644 libraries/render-utils/src/MetaModelPayload.h diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f154746707..acbdf63945 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -713,7 +713,17 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc // INitialize the _render bound as we are creating the avatar render item _renderBound = getBounds(); transaction.resetItem(_renderItemID, avatarPayloadPointer); - _skeletonModel->addToScene(scene, transaction); + auto metaBlendshapeOperator = [this](int blendshapeNumber, QVector blendshapeOffsets, QVector blendedMeshSizes, render::ItemIDs subItemIDs) { + render::Transaction transaction; + transaction.updateItem(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs](AvatarData& avatar) { + auto avatarPtr = dynamic_cast(&avatar); + if (avatarPtr) { + avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs); + } + }); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + }; + _skeletonModel->addToScene(scene, transaction, metaBlendshapeOperator); _skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS); _skeletonModel->setGroupCulled(true); _skeletonModel->setCanCastShadow(true); @@ -792,7 +802,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) { avatarPtr->_renderBound = renderBound; } } - ); + ); } } @@ -936,7 +946,17 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { render::Transaction transaction; if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); - _skeletonModel->addToScene(scene, transaction); + auto metaBlendshapeOperator = [this](int blendshapeNumber, QVector blendshapeOffsets, QVector blendedMeshSizes, render::ItemIDs subItemIDs) { + render::Transaction transaction; + transaction.updateItem(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs](AvatarData& avatar) { + auto avatarPtr = dynamic_cast(&avatar); + if (avatarPtr) { + avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs); + } + }); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + }; + _skeletonModel->addToScene(scene, transaction, metaBlendshapeOperator); _skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS); _skeletonModel->setGroupCulled(true); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 1087f74c07..a5ff810b17 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -28,6 +28,8 @@ #include "Rig.h" #include +#include "MetaModelPayload.h" + namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar); template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar); @@ -108,7 +110,7 @@ private: float _scale { 1.0f }; }; -class Avatar : public AvatarData, public scriptable::ModelProvider { +class Avatar : public AvatarData, public scriptable::ModelProvider, public MetaModelPayload { Q_OBJECT // This property has JSDoc in MyAvatar.h. diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index b5f9d9f833..2d31549872 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -24,8 +24,6 @@ #include "RenderableEntityItem.h" - - class Model; class EntityTreeRenderer; diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 8ea4cdcd60..81a017a46d 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -96,7 +96,7 @@ void CauterizedModel::createRenderItemSet() { shapeID++; } } - _blendshapeBuffersInitialized = true; + _blendshapeOffsetsInitialized = true; } else { Model::createRenderItemSet(); } @@ -175,7 +175,7 @@ void CauterizedModel::updateClusterMatrices() { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (_blendshapeBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendshapeOffsetsInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index c5df2c3e01..9b015bc190 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -209,6 +209,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); + _meshNumVertices = modelMesh->getNumVertices(); const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); @@ -238,19 +239,12 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in initCache(model); - if (_isBlendShaped) { - auto buffer = model->_blendshapeBuffers.find(meshIndex); - if (buffer != model->_blendshapeBuffers.end()) { - _blendshapeBuffer = buffer->second; - } - } - #ifdef Q_OS_MAC - // On mac AMD, we specifically need to have a _blendshapeBuffer bound when using a deformed mesh pipeline + // On mac AMD, we specifically need to have a _meshBlendshapeBuffer bound when using a deformed mesh pipeline // it cannot be null otherwise we crash in the drawcall using a deformed pipeline with a skinned only (not blendshaped) mesh - if ((_isBlendShaped || _isSkinned) && !_blendshapeBuffer) { + if ((_isBlendShaped || _isSkinned)) { glm::vec4 data; - _blendshapeBuffer = std::make_shared(sizeof(glm::vec4), reinterpret_cast(&data)); + _meshBlendshapeBuffer = std::make_shared(sizeof(glm::vec4), reinterpret_cast(&data)); } #endif @@ -292,8 +286,7 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clu if (!_clusterBuffer) { _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) clusterMatrices.data()); - } - else { + } else { _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) clusterMatrices.data()); } @@ -313,8 +306,7 @@ void ModelMeshPartPayload::updateClusterBuffer(const std::vector(clusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), (const gpu::Byte*) clusterDualQuaternions.data()); - } - else { + } else { _clusterBuffer->setSubData(0, clusterDualQuaternions.size() * sizeof(Model::TransformDualQuaternion), (const gpu::Byte*) clusterDualQuaternions.data()); } @@ -403,8 +395,8 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setInputFormat((_drawMesh->getVertexFormat())); - if (_blendshapeBuffer) { - batch.setResourceBuffer(0, _blendshapeBuffer); + if (_meshBlendshapeBuffer) { + batch.setResourceBuffer(0, _meshBlendshapeBuffer); } batch.setInputStream(0, _drawMesh->getVertexStream()); } @@ -431,7 +423,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMesh(batch); // IF deformed pass the mesh key - auto drawcallInfo = (uint16_t) (((_isBlendShaped && args->_enableBlendshape) << 0) | ((_isSkinned && args->_enableSkinning) << 1)); + auto drawcallInfo = (uint16_t) (((_isBlendShaped && _meshBlendshapeBuffer && args->_enableBlendshape) << 0) | ((_isSkinned && args->_enableSkinning) << 1)); if (drawcallInfo) { batch.setDrawcallUniform(drawcallInfo); } @@ -483,3 +475,12 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& blendshapeBuffers, const QVector& blendedMeshSizes) { + if (_meshIndex < blendedMeshSizes.length() && blendedMeshSizes.at(_meshIndex) == _meshNumVertices) { + auto blendshapeBuffer = blendshapeBuffers.find(_meshIndex); + if (blendshapeBuffer != blendshapeBuffers.end()) { + _meshBlendshapeBuffer = blendshapeBuffer->second; + } + } +} \ No newline at end of file diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ceed4b330b..4d41d1d93e 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -134,10 +134,13 @@ public: bool _isBlendShaped { false }; bool _hasTangents { false }; + void setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes); + private: void initCache(const ModelPointer& model); - gpu::BufferPointer _blendshapeBuffer; + gpu::BufferPointer _meshBlendshapeBuffer; + int _meshNumVertices; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; }; diff --git a/libraries/render-utils/src/MetaModelPayload.cpp b/libraries/render-utils/src/MetaModelPayload.cpp new file mode 100644 index 0000000000..5c4cc169b7 --- /dev/null +++ b/libraries/render-utils/src/MetaModelPayload.cpp @@ -0,0 +1,55 @@ +// +// MetaModelPayload.cpp +// +// Created by Sam Gondelman on 10/9/18. +// Copyright 2018 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 "MetaModelPayload.h" + +#include "AbstractViewStateInterface.h" +#include "MeshPartPayload.h" + +void MetaModelPayload::setBlendedVertices(int blendNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, const render::ItemIDs& subRenderItems) { + PROFILE_RANGE(render, __FUNCTION__); + if (blendNumber < _appliedBlendNumber) { + return; + } + _appliedBlendNumber = blendNumber; + + // We have fewer meshes than before. Invalidate everything + if (blendedMeshSizes.length() < _blendshapeBuffers.size()) { + _blendshapeBuffers.clear(); + } + + int index = 0; + for (int i = 0; i < blendedMeshSizes.size(); i++) { + int numVertices = blendedMeshSizes.at(i); + + // This mesh isn't blendshaped + if (numVertices == 0) { + _blendshapeBuffers.erase(i); + continue; + } + + const auto& buffer = _blendshapeBuffers.find(i); + const auto blendShapeBufferSize = numVertices * sizeof(BlendshapeOffset); + if (buffer == _blendshapeBuffers.end()) { + _blendshapeBuffers[i] = std::make_shared(blendShapeBufferSize, (gpu::Byte*) blendshapeOffsets.constData() + index * sizeof(BlendshapeOffset), blendShapeBufferSize); + } else { + buffer->second->setData(blendShapeBufferSize, (gpu::Byte*) blendshapeOffsets.constData() + index * sizeof(BlendshapeOffset)); + } + + index += numVertices; + } + + render::Transaction transaction; + for (auto& id : subRenderItems) { + transaction.updateItem(id, [this, blendedMeshSizes](ModelMeshPartPayload& data) { + data.setBlendshapeBuffer(_blendshapeBuffers, blendedMeshSizes); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} \ No newline at end of file diff --git a/libraries/render-utils/src/MetaModelPayload.h b/libraries/render-utils/src/MetaModelPayload.h new file mode 100644 index 0000000000..83731f3039 --- /dev/null +++ b/libraries/render-utils/src/MetaModelPayload.h @@ -0,0 +1,30 @@ +// +// MetaModelPayload.h +// +// Created by Sam Gondelman on 10/9/18. +// Copyright 2018 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_MetaModelPayload_h +#define hifi_MetaModelPayload_h + +#include + +#include "Model.h" + +#include "gpu/Buffer.h" + +class MetaModelPayload { +public: + void setBlendedVertices(int blendNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, const render::ItemIDs& subRenderItems); + +private: + std::unordered_map _blendshapeBuffers; + int _appliedBlendNumber { 0 }; + +}; + +#endif \ No newline at end of file diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index a700c200f8..b0ad0f3ba3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -62,8 +62,6 @@ Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) : _snapModelToRegistrationPoint(false), _snappedToRegistrationPoint(false), _url(HTTP_INVALID_COM), - _blendNumber(0), - _appliedBlendNumber(0), _isWireframe(false), _renderItemKeyGlobalFlags(render::ItemKey::Builder().withVisible().withTagBits(render::hifi::TAG_ALL_VIEWS).build()) { @@ -311,7 +309,7 @@ bool Model::updateGeometry() { initializeBlendshapes(mesh, i); i++; } - _blendshapeBuffersInitialized = true; + _blendshapeOffsetsInitialized = true; needFullUpdate = true; emit rigReady(); } @@ -979,7 +977,8 @@ const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, - render::Item::Status::Getters& statusGetters) { + render::Item::Status::Getters& statusGetters, + std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { if (!_addedToScene && isLoaded()) { updateClusterMatrices(); if (_modelMeshRenderItems.empty()) { @@ -987,10 +986,11 @@ bool Model::addToScene(const render::ScenePointer& scene, } } + _modelBlendshapeOperator = modelBlendshapeOperator; + bool somethingAdded = false; if (_modelMeshRenderItemsMap.empty()) { - bool hasTransparent = false; size_t verticesCount = 0; foreach(auto renderItem, _modelMeshRenderItems) { @@ -1032,9 +1032,8 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); - _blendshapeBuffers.clear(); _blendshapeOffsets.clear(); - _blendshapeBuffersInitialized = false; + _blendshapeOffsetsInitialized = false; _addedToScene = false; @@ -1437,7 +1436,7 @@ void Model::updateClusterMatrices() { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (_blendshapeBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendshapeOffsetsInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } @@ -1445,9 +1444,8 @@ void Model::updateClusterMatrices() { void Model::deleteGeometry() { _deleteGeometryCounter++; - _blendshapeBuffers.clear(); _blendshapeOffsets.clear(); - _blendshapeBuffersInitialized = false; + _blendshapeOffsetsInitialized = false; _meshStates.clear(); _rig.destroyAnimGraph(); _blendedBlendshapeCoefficients.clear(); @@ -1525,7 +1523,7 @@ void Model::createRenderItemSet() { shapeID++; } } - _blendshapeBuffersInitialized = true; + _blendshapeOffsetsInitialized = true; } bool Model::isRenderable() const { @@ -1654,6 +1652,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe void Blender::run() { QVector blendshapeOffsets; + QVector blendedMeshSizes; if (_model && _model->isLoaded()) { DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); int offset = 0; @@ -1662,12 +1661,22 @@ void Blender::run() { foreach(const FBXMesh& mesh, meshes) { auto modelMeshBlendshapeOffsets = _model->_blendshapeOffsets.find(meshIndex++); if (mesh.blendshapes.isEmpty() || modelMeshBlendshapeOffsets == _model->_blendshapeOffsets.end()) { + // Not blendshaped or not initialized + blendedMeshSizes.push_back(0); + continue; + } + + if (mesh.vertices.size() != modelMeshBlendshapeOffsets->second.size()) { + // Mesh sizes don't match. Something has gone wrong + blendedMeshSizes.push_back(0); continue; } blendshapeOffsets += modelMeshBlendshapeOffsets->second; BlendshapeOffset* meshBlendshapeOffsets = blendshapeOffsets.data() + offset; - offset += modelMeshBlendshapeOffsets->second.size(); + int numVertices = modelMeshBlendshapeOffsets->second.size(); + blendedMeshSizes.push_back(numVertices); + offset += numVertices; std::vector unpackedBlendshapeOffsets(modelMeshBlendshapeOffsets->second.size()); const float NORMAL_COEFFICIENT_SCALE = 0.01f; @@ -1711,7 +1720,7 @@ void Blender::run() { } // post the result to the ModelBlender, which will dispatch to the model if still alive QMetaObject::invokeMethod(DependencyManager::get().data(), "setBlendedVertices", - Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber), Q_ARG(QVector, blendshapeOffsets)); + Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber), Q_ARG(QVector, blendshapeOffsets), Q_ARG(QVector, blendedMeshSizes)); } bool Model::maybeStartBlender() { @@ -1722,43 +1731,18 @@ bool Model::maybeStartBlender() { return false; } -void Model::setBlendedVertices(int blendNumber, const QVector& blendshapeOffsets) { - PROFILE_RANGE(render, __FUNCTION__); - if (!isLoaded() || blendNumber < _appliedBlendNumber || !_blendshapeBuffersInitialized) { - return; - } - _appliedBlendNumber = blendNumber; - const FBXGeometry& fbxGeometry = getFBXGeometry(); - int index = 0; - for (int i = 0; i < fbxGeometry.meshes.size(); i++) { - const FBXMesh& mesh = fbxGeometry.meshes.at(i); - auto meshBlendshapeOffsets = _blendshapeOffsets.find(i); - const auto& buffer = _blendshapeBuffers.find(i); - if (mesh.blendshapes.isEmpty() || meshBlendshapeOffsets == _blendshapeOffsets.end() || buffer == _blendshapeBuffers.end()) { - continue; - } - - const auto blendshapeOffsetSize = meshBlendshapeOffsets->second.size() * sizeof(BlendshapeOffset); - buffer->second->setSubData(0, blendshapeOffsetSize, (gpu::Byte*) blendshapeOffsets.constData() + index * sizeof(BlendshapeOffset)); - - index += meshBlendshapeOffsets->second.size(); - } -} - void Model::initializeBlendshapes(const FBXMesh& mesh, int index) { if (mesh.blendshapes.empty()) { // mesh doesn't have blendshape, did we allocate one though ? - if (_blendshapeBuffers.find(index) != _blendshapeBuffers.end()) { - qWarning() << "Mesh does not have Blendshape yet a blendshapeOffset buffer is allocated ?"; + if (_blendshapeOffsets.find(index) != _blendshapeOffsets.end()) { + qWarning() << "Mesh does not have Blendshape yet the blendshapeOffsets are allocated ?"; } return; } // Mesh has blendshape, let s allocate the local buffer if not done yet - if (_blendshapeBuffers.find(index) == _blendshapeBuffers.end()) { + if (_blendshapeOffsets.find(index) == _blendshapeOffsets.end()) { QVector blendshapeOffset; blendshapeOffset.fill(BlendshapeOffset(), mesh.vertices.size()); - const auto blendshapeOffsetsSize = blendshapeOffset.size() * sizeof(BlendshapeOffset); - _blendshapeBuffers[index] = std::make_shared(blendshapeOffsetsSize, (const gpu::Byte*) blendshapeOffset.constData(), blendshapeOffsetsSize); _blendshapeOffsets[index] = blendshapeOffset; } } @@ -1791,10 +1775,11 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) { } } -void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, QVector blendshapeOffsets) { +void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, QVector blendshapeOffsets, QVector blendedMeshSizes) { if (model) { - model->setBlendedVertices(blendNumber, blendshapeOffsets); + model->getModelBlendshapeOperator()(blendNumber, blendshapeOffsets, blendedMeshSizes, model->fetchRenderItemIDs()); } + { Lock lock(_mutex); _pendingBlenders--; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e42da4ecb1..fe1897bc1f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -135,13 +135,14 @@ public: bool needsReload() const { return _needsReload; } bool addToScene(const render::ScenePointer& scene, - render::Transaction& transaction) { - auto getters = render::Item::Status::Getters(0); - return addToScene(scene, transaction, getters); + render::Transaction& transaction, + std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { + return addToScene(scene, transaction, render::Item::Status::Getters(0), modelBlendshapeOperator); } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, - render::Item::Status::Getters& statusGetters); + render::Item::Status::Getters& statusGetters = render::Item::Status::Getters(0), + std::function, QVector, render::ItemIDs)> modelBlendshapeOperator = [](int, QVector, QVector, render::ItemIDs) {}); void removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction); bool isRenderable() const; @@ -155,9 +156,6 @@ public: bool maybeStartBlender(); - /// Sets blended vertices computed in a separate thread. - void setBlendedVertices(int blendNumber, const QVector& blendshapeOffsets); - bool isLoaded() const { return (bool)_renderGeometry && _renderGeometry->isGeometryLoaded(); } bool isAddedToScene() const { return _addedToScene; } @@ -339,6 +337,7 @@ public: uint32_t getGeometryCounter() const { return _deleteGeometryCounter; } const QMap& getRenderItems() const { return _modelMeshRenderItemsMap; } + std::function, QVector, render::ItemIDs)> getModelBlendshapeOperator() const { return _modelBlendshapeOperator; } void renderDebugMeshBoxes(gpu::Batch& batch); @@ -432,18 +431,13 @@ protected: virtual void deleteGeometry(); - QVector _blendshapeCoefficients; - QUrl _url; - std::unordered_map _blendshapeBuffers; - bool _blendshapeBuffersInitialized{ false }; - - QVector>> _dilatedTextures; - + std::function, QVector, render::ItemIDs)> _modelBlendshapeOperator { [](int, QVector, QVector, render::ItemIDs) {} }; + QVector _blendshapeCoefficients; QVector _blendedBlendshapeCoefficients; - int _blendNumber; - int _appliedBlendNumber; + int _blendNumber { 0 }; + bool _blendshapeOffsetsInitialized { false }; mutable QMutex _mutex{ QMutex::Recursive }; @@ -460,7 +454,6 @@ protected: // debug rendering support int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; - static AbstractViewStateInterface* _viewState; QVector> _modelMeshRenderItems; @@ -533,7 +526,7 @@ public: bool shouldComputeBlendshapes() { return _computeBlendshapes; } public slots: - void setBlendedVertices(ModelPointer model, int blendNumber, QVector blendshapeOffsets); + void setBlendedVertices(ModelPointer model, int blendNumber, QVector blendshapeOffsets, QVector blendedMeshSizes); void setComputeBlendshapes(bool computeBlendshapes) { _computeBlendshapes = computeBlendshapes; } private: diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 114ccab712..90015768d0 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -78,7 +78,7 @@ void SoftAttachmentModel::updateClusterMatrices() { // post the blender if we're not currently waiting for one to finish auto modelBlender = DependencyManager::get(); - if (_blendshapeBuffersInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { + if (_blendshapeOffsetsInitialized && modelBlender->shouldComputeBlendshapes() && geometry.hasBlendedMeshes() && _blendshapeCoefficients != _blendedBlendshapeCoefficients) { _blendedBlendshapeCoefficients = _blendshapeCoefficients; modelBlender->noteRequiresBlend(getThisPointer()); } From 296bd65c9b6f4638da9cbdb2dae51fc76cfe2d05 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 10 Oct 2018 16:05:14 -0700 Subject: [PATCH 2/6] fix build errors --- libraries/render-utils/src/Model.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index fe1897bc1f..afaccce12f 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -137,7 +137,8 @@ public: bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { - return addToScene(scene, transaction, render::Item::Status::Getters(0), modelBlendshapeOperator); + auto getters = render::Item::Status::Getters(0); + return addToScene(scene, transaction, getters, modelBlendshapeOperator); } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, From 6ed38ea33388555a1917927a6fc4e5b6d616d7f2 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 10 Oct 2018 16:16:56 -0700 Subject: [PATCH 3/6] fix build errors --- libraries/render-utils/src/Model.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index afaccce12f..c83acfdb53 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -134,6 +134,11 @@ public: bool needsFixupInScene() const; bool needsReload() const { return _needsReload; } + bool addToScene(const render::ScenePointer& scene, + render::Transaction& transaction) { + auto getters = render::Item::Status::Getters(0); + return addToScene(scene, transaction, getters); + } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { @@ -142,7 +147,7 @@ public: } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, - render::Item::Status::Getters& statusGetters = render::Item::Status::Getters(0), + render::Item::Status::Getters& statusGetters, std::function, QVector, render::ItemIDs)> modelBlendshapeOperator = [](int, QVector, QVector, render::ItemIDs) {}); void removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction); bool isRenderable() const; From 2421f9388c76ea943d16521878af045432f6e9fa Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 10 Oct 2018 17:09:35 -0700 Subject: [PATCH 4/6] FIX BUILD ERRORS? --- libraries/render-utils/src/MetaModelPayload.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/MetaModelPayload.cpp b/libraries/render-utils/src/MetaModelPayload.cpp index 5c4cc169b7..510972d86a 100644 --- a/libraries/render-utils/src/MetaModelPayload.cpp +++ b/libraries/render-utils/src/MetaModelPayload.cpp @@ -20,7 +20,7 @@ void MetaModelPayload::setBlendedVertices(int blendNumber, const QVectorgetMain3DScene()->enqueueTransaction(transaction); -} \ No newline at end of file +} From 39c828fad8b2183ea2af891088bea213fcd5b81a Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 10 Oct 2018 19:07:49 -0700 Subject: [PATCH 5/6] please --- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 9b015bc190..2fe0368db2 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -209,7 +209,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); - _meshNumVertices = modelMesh->getNumVertices(); + _meshNumVertices = (int)modelMesh->getNumVertices(); const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); @@ -483,4 +483,4 @@ void ModelMeshPartPayload::setBlendshapeBuffer(const std::unordered_mapsecond; } } -} \ No newline at end of file +} From 47c6825aea618603db1c70a5e7d811c543ac5b38 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 18 Oct 2018 11:08:53 -0700 Subject: [PATCH 6/6] CR --- .../src/avatars-renderer/Avatar.cpp | 39 ++++++++----------- .../src/avatars-renderer/Avatar.h | 3 ++ libraries/render-utils/src/Model.cpp | 7 +++- libraries/render-utils/src/Model.h | 9 +++-- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index acbdf63945..7037df4af5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -704,6 +704,19 @@ static TextRenderer3D* textRenderer(TextRendererType type) { return displayNameRenderer; } +void Avatar::metaBlendshapeOperator(int blendshapeNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, + const render::ItemIDs& subItemIDs) { + render::Transaction transaction; + transaction.updateItem(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes, + subItemIDs](AvatarData& avatar) { + auto avatarPtr = dynamic_cast(&avatar); + if (avatarPtr) { + avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs); + } + }); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& scene, render::Transaction& transaction) { auto avatarPayload = new render::Payload(self); auto avatarPayloadPointer = std::shared_ptr>(avatarPayload); @@ -713,17 +726,8 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc // INitialize the _render bound as we are creating the avatar render item _renderBound = getBounds(); transaction.resetItem(_renderItemID, avatarPayloadPointer); - auto metaBlendshapeOperator = [this](int blendshapeNumber, QVector blendshapeOffsets, QVector blendedMeshSizes, render::ItemIDs subItemIDs) { - render::Transaction transaction; - transaction.updateItem(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs](AvatarData& avatar) { - auto avatarPtr = dynamic_cast(&avatar); - if (avatarPtr) { - avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs); - } - }); - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); - }; - _skeletonModel->addToScene(scene, transaction, metaBlendshapeOperator); + using namespace std::placeholders; + _skeletonModel->addToScene(scene, transaction, std::bind(&Avatar::metaBlendshapeOperator, this, _1, _2, _3, _4)); _skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS); _skeletonModel->setGroupCulled(true); _skeletonModel->setCanCastShadow(true); @@ -946,17 +950,8 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { render::Transaction transaction; if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); - auto metaBlendshapeOperator = [this](int blendshapeNumber, QVector blendshapeOffsets, QVector blendedMeshSizes, render::ItemIDs subItemIDs) { - render::Transaction transaction; - transaction.updateItem(_renderItemID, [blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs](AvatarData& avatar) { - auto avatarPtr = dynamic_cast(&avatar); - if (avatarPtr) { - avatarPtr->setBlendedVertices(blendshapeNumber, blendshapeOffsets, blendedMeshSizes, subItemIDs); - } - }); - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); - }; - _skeletonModel->addToScene(scene, transaction, metaBlendshapeOperator); + using namespace std::placeholders; + _skeletonModel->addToScene(scene, transaction, std::bind(&Avatar::metaBlendshapeOperator, this, _1, _2, _3, _4)); _skeletonModel->setTagMask(render::hifi::TAG_ALL_VIEWS); _skeletonModel->setGroupCulled(true); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a5ff810b17..3f4cf7b8c2 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -622,6 +622,9 @@ protected: static const float ATTACHMENT_LOADING_PRIORITY; LoadingStatus _loadingStatus { LoadingStatus::NoModel }; + + void metaBlendshapeOperator(int blendshapeNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, + const render::ItemIDs& subItemIDs); }; #endif // hifi_Avatar_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b0ad0f3ba3..53009e8bfa 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -978,7 +978,7 @@ const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { bool Model::addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters, - std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { + BlendShapeOperator modelBlendshapeOperator) { if (!_addedToScene && isLoaded()) { updateClusterMatrices(); if (_modelMeshRenderItems.empty()) { @@ -1777,7 +1777,10 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) { void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, QVector blendshapeOffsets, QVector blendedMeshSizes) { if (model) { - model->getModelBlendshapeOperator()(blendNumber, blendshapeOffsets, blendedMeshSizes, model->fetchRenderItemIDs()); + auto blendshapeOperator = model->getModelBlendshapeOperator(); + if (blendshapeOperator) { + blendshapeOperator(blendNumber, blendshapeOffsets, blendedMeshSizes, model->fetchRenderItemIDs()); + } } { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c83acfdb53..71809821eb 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -86,6 +86,7 @@ struct BlendshapeOffsetUnpacked { }; using BlendshapeOffset = BlendshapeOffsetPacked; +using BlendShapeOperator = std::function&, const QVector&, const render::ItemIDs&)>; /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public std::enable_shared_from_this, public scriptable::ModelProvider { @@ -141,14 +142,14 @@ public: } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, - std::function, QVector, render::ItemIDs)> modelBlendshapeOperator) { + BlendShapeOperator modelBlendshapeOperator) { auto getters = render::Item::Status::Getters(0); return addToScene(scene, transaction, getters, modelBlendshapeOperator); } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, render::Item::Status::Getters& statusGetters, - std::function, QVector, render::ItemIDs)> modelBlendshapeOperator = [](int, QVector, QVector, render::ItemIDs) {}); + BlendShapeOperator modelBlendshapeOperator = nullptr); void removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction); bool isRenderable() const; @@ -343,7 +344,7 @@ public: uint32_t getGeometryCounter() const { return _deleteGeometryCounter; } const QMap& getRenderItems() const { return _modelMeshRenderItemsMap; } - std::function, QVector, render::ItemIDs)> getModelBlendshapeOperator() const { return _modelBlendshapeOperator; } + BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; } void renderDebugMeshBoxes(gpu::Batch& batch); @@ -439,7 +440,7 @@ protected: QUrl _url; - std::function, QVector, render::ItemIDs)> _modelBlendshapeOperator { [](int, QVector, QVector, render::ItemIDs) {} }; + BlendShapeOperator _modelBlendshapeOperator { nullptr }; QVector _blendshapeCoefficients; QVector _blendedBlendshapeCoefficients; int _blendNumber { 0 };