diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 93eaa6da33..6770cd7f96 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -703,6 +703,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); @@ -712,7 +725,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); - _skeletonModel->addToScene(scene, transaction); + 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); @@ -791,7 +805,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) { avatarPtr->_renderBound = renderBound; } } - ); + ); } } @@ -935,7 +949,8 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { render::Transaction transaction; if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); - _skeletonModel->addToScene(scene, transaction); + 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 1087f74c07..3f4cf7b8c2 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. @@ -620,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/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..2fe0368db2 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 = (int)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; + } + } +} 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..510972d86a --- /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() < (int)_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); +} 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..53009e8bfa 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, + BlendShapeOperator 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,14 @@ 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); + auto blendshapeOperator = model->getModelBlendshapeOperator(); + if (blendshapeOperator) { + blendshapeOperator(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..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,7 +142,14 @@ public: } bool addToScene(const render::ScenePointer& scene, render::Transaction& transaction, - render::Item::Status::Getters& statusGetters); + 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, + BlendShapeOperator modelBlendshapeOperator = nullptr); void removeFromScene(const render::ScenePointer& scene, render::Transaction& transaction); bool isRenderable() const; @@ -155,9 +163,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 +344,7 @@ public: uint32_t getGeometryCounter() const { return _deleteGeometryCounter; } const QMap& getRenderItems() const { return _modelMeshRenderItemsMap; } + BlendShapeOperator getModelBlendshapeOperator() const { return _modelBlendshapeOperator; } void renderDebugMeshBoxes(gpu::Batch& batch); @@ -432,18 +438,13 @@ protected: virtual void deleteGeometry(); - QVector _blendshapeCoefficients; - QUrl _url; - std::unordered_map _blendshapeBuffers; - bool _blendshapeBuffersInitialized{ false }; - - QVector>> _dilatedTextures; - + BlendShapeOperator _modelBlendshapeOperator { nullptr }; + QVector _blendshapeCoefficients; QVector _blendedBlendshapeCoefficients; - int _blendNumber; - int _appliedBlendNumber; + int _blendNumber { 0 }; + bool _blendshapeOffsetsInitialized { false }; mutable QMutex _mutex{ QMutex::Recursive }; @@ -460,7 +461,6 @@ protected: // debug rendering support int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID; - static AbstractViewStateInterface* _viewState; QVector> _modelMeshRenderItems; @@ -533,7 +533,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()); }