From 05ff99a1d2f2f0aa8387bd505d665de26bc58519 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 9 Aug 2018 18:39:19 -0700 Subject: [PATCH 1/2] working on blendshapes --- interface/src/avatar/AvatarManager.cpp | 4 +- .../render-utils/src/CauterizedModel.cpp | 5 ++ .../render-utils/src/MeshPartPayload.cpp | 5 +- libraries/render-utils/src/Model.cpp | 54 +++++-------------- libraries/render-utils/src/Model.h | 2 +- 5 files changed, 26 insertions(+), 44 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index dbafd06611..efd1c103d9 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -353,15 +353,14 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { QReadLocker locker(&_hashLock); QVector::iterator avatarItr = _avatarsToFade.begin(); const render::ScenePointer& scene = qApp->getMain3DScene(); + render::Transaction transaction; while (avatarItr != _avatarsToFade.end()) { auto avatar = std::static_pointer_cast(*avatarItr); avatar->updateFadingStatus(scene); if (!avatar->isFading()) { // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { - render::Transaction transaction; avatar->removeFromScene(*avatarItr, scene, transaction); - scene->enqueueTransaction(transaction); } avatarItr = _avatarsToFade.erase(avatarItr); } else { @@ -370,6 +369,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { ++avatarItr; } } + scene->enqueueTransaction(transaction); } AvatarSharedPointer AvatarManager::newSharedAvatar() { diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 80a9c5ccae..ba394b8b2f 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -75,6 +75,7 @@ void CauterizedModel::createRenderItemSet() { // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; + const FBXGeometry& fbxGeometry = getFBXGeometry(); uint32_t numMeshes = (uint32_t)meshes.size(); for (uint32_t i = 0; i < numMeshes; i++) { const auto& mesh = meshes.at(i); @@ -85,6 +86,10 @@ void CauterizedModel::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { + if (!fbxGeometry.meshes[i].blendshapes.empty()) { + _blendedVertexBuffers[i] = std::make_shared(); + _blendedVertexBuffers[i]->resize(fbxGeometry.meshes[i].vertices.size() * (sizeof(glm::vec3) + 2 * sizeof(NormalType))); + } auto ptr = std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); _modelMeshRenderItems << std::static_pointer_cast(ptr); auto material = getGeometry()->getShapeMaterial(shapeID); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index ca6e736a65..58f4f170a0 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -208,7 +208,10 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in bool useDualQuaternionSkinning = model->getUseDualQuaternionSkinning(); - _blendedVertexBuffer = model->_blendedVertexBuffers[_meshIndex]; + auto blendedVertexBuffer = model->_blendedVertexBuffers.find(_meshIndex); + if (blendedVertexBuffer != model->_blendedVertexBuffers.end()) { + _blendedVertexBuffer = blendedVertexBuffer->second; + } auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); const Model::MeshState& state = model->getMeshState(_meshIndex); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ba0d714f7a..f92a6809f3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -305,36 +305,6 @@ bool Model::updateGeometry() { state.clusterDualQuaternions.resize(mesh.clusters.size()); state.clusterMatrices.resize(mesh.clusters.size()); _meshStates.push_back(state); - - // Note: we add empty buffers for meshes that lack blendshapes so we can access the buffers by index - // later in ModelMeshPayload, however the vast majority of meshes will not have them. - // TODO? make _blendedVertexBuffers a map instead of vector and only add for meshes with blendshapes? - auto buffer = std::make_shared(); - if (!mesh.blendshapes.isEmpty()) { - std::vector normalsAndTangents; - normalsAndTangents.reserve(mesh.normals.size() + mesh.tangents.size()); - - for (auto normalIt = mesh.normals.begin(), tangentIt = mesh.tangents.begin(); - normalIt != mesh.normals.end(); - ++normalIt, ++tangentIt) { -#if FBX_PACK_NORMALS - glm::uint32 finalNormal; - glm::uint32 finalTangent; - buffer_helpers::packNormalAndTangent(*normalIt, *tangentIt, finalNormal, finalTangent); -#else - const auto finalNormal = *normalIt; - const auto finalTangent = *tangentIt; -#endif - normalsAndTangents.push_back(finalNormal); - normalsAndTangents.push_back(finalTangent); - } - - buffer->resize(mesh.vertices.size() * (sizeof(glm::vec3) + 2 * sizeof(NormalType))); - buffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (const gpu::Byte*) mesh.vertices.constData()); - buffer->setSubData(mesh.vertices.size() * sizeof(glm::vec3), - mesh.normals.size() * 2 * sizeof(NormalType), (const gpu::Byte*) normalsAndTangents.data()); - } - _blendedVertexBuffers.push_back(buffer); } needFullUpdate = true; emit rigReady(); @@ -1280,9 +1250,9 @@ void Blender::run() { } // post the result to the geometry cache, 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(const Geometry::WeakPointer&, _geometry), Q_ARG(const QVector&, vertices), - Q_ARG(const QVector&, normals), Q_ARG(const QVector&, tangents)); + Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber), + Q_ARG(const Geometry::WeakPointer&, _geometry), Q_ARG(const QVector&, vertices), + Q_ARG(const QVector&, normals), Q_ARG(const QVector&, tangents)); } void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions, bool forceRescale) { @@ -1463,7 +1433,7 @@ bool Model::maybeStartBlender() { void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geometry, const QVector& vertices, const QVector& normals, const QVector& tangents) { auto geometryRef = geometry.lock(); - if (!geometryRef || _renderGeometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) { + if (!geometryRef || _renderGeometry != geometryRef || blendNumber < _appliedBlendNumber) { return; } _appliedBlendNumber = blendNumber; @@ -1476,13 +1446,13 @@ void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geo continue; } - gpu::BufferPointer& buffer = _blendedVertexBuffers[i]; + gpu::BufferPointer buffer = _blendedVertexBuffers[i]; const auto vertexCount = mesh.vertices.size(); const auto verticesSize = vertexCount * sizeof(glm::vec3); const auto offset = index * sizeof(glm::vec3); normalsAndTangents.clear(); - normalsAndTangents.resize(normals.size()+tangents.size()); + normalsAndTangents.resize(normals.size() + tangents.size()); // assert(normalsAndTangents.size() == 2 * vertexCount); // Interleave normals and tangents @@ -1510,7 +1480,7 @@ void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geo } #else // Parallel version for performance - tbb::parallel_for(tbb::blocked_range(index, index+vertexCount), [&](const tbb::blocked_range& range) { + tbb::parallel_for(tbb::blocked_range(index, index + vertexCount), [&](const tbb::blocked_range& range) { auto normalsRange = std::make_pair(normals.begin() + range.begin(), normals.begin() + range.end()); auto tangentsRange = std::make_pair(tangents.begin() + range.begin(), tangents.begin() + range.end()); auto normalsAndTangentsIt = normalsAndTangents.begin() + (range.begin()-index)*2; @@ -1603,6 +1573,7 @@ void Model::createRenderItemSet() { // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; uint32_t numMeshes = (uint32_t)meshes.size(); + const FBXGeometry& fbxGeometry = getFBXGeometry(); for (uint32_t i = 0; i < numMeshes; i++) { const auto& mesh = meshes.at(i); if (!mesh) { @@ -1612,6 +1583,10 @@ void Model::createRenderItemSet() { // Create the render payloads int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { + if (!fbxGeometry.meshes[i].blendshapes.empty()) { + _blendedVertexBuffers[i] = std::make_shared(); + _blendedVertexBuffers[i]->resize(fbxGeometry.meshes[i].vertices.size() * (sizeof(glm::vec3) + 2 * sizeof(NormalType))); + } _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); auto material = getGeometry()->getShapeMaterial(shapeID); _modelMeshMaterialNames.push_back(material ? material->getName() : ""); @@ -1724,8 +1699,8 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) { } } -void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry, - const QVector& vertices, const QVector& normals, +void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry, + const QVector& vertices, const QVector& normals, const QVector& tangents) { if (model) { model->setBlendedVertices(blendNumber, geometry, vertices, normals, tangents); @@ -1744,4 +1719,3 @@ void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, const } } } - diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 627e5fddab..1d0570f087 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -413,7 +413,7 @@ protected: QUrl _url; - gpu::Buffers _blendedVertexBuffers; + std::unordered_map _blendedVertexBuffers; QVector > > _dilatedTextures; From ff6020e0ef2489f3cfbe5e883d1688b73a0b3971 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 24 Aug 2018 15:41:25 -0700 Subject: [PATCH 2/2] fix compile errors, maybe --- libraries/render-utils/src/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4fc8e265ab..71250c6483 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -319,7 +319,7 @@ bool Model::updateGeometry() { // Interleave normals and tangents // Parallel version for performance - tbb::parallel_for(tbb::blocked_range(0, mesh.normals.size()), [&](const tbb::blocked_range& range) { + tbb::parallel_for(tbb::blocked_range(0, mesh.normals.size()), [&](const tbb::blocked_range& range) { auto normalsRange = std::make_pair(mesh.normals.begin() + range.begin(), mesh.normals.begin() + range.end()); auto tangentsRange = std::make_pair(mesh.tangents.begin() + range.begin(), mesh.tangents.begin() + range.end()); auto normalsAndTangentsIt = normalsAndTangents.begin() + 2 * range.begin(); @@ -1281,7 +1281,7 @@ void Blender::run() { } float normalCoefficient = vertexCoefficient * NORMAL_COEFFICIENT_SCALE; const FBXBlendshape& blendshape = mesh.blendshapes.at(i); - tbb::parallel_for(tbb::blocked_range(0, blendshape.indices.size()), [&](const tbb::blocked_range& range) { + tbb::parallel_for(tbb::blocked_range(0, blendshape.indices.size()), [&](const tbb::blocked_range& range) { for (auto j = range.begin(); j < range.end(); j++) { int index = blendshape.indices.at(j); meshVertices[index] += blendshape.vertices.at(j) * vertexCoefficient;