From 0469eafbe46bf2df42f9f0ea6104d1ad9d98273a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 22 Feb 2018 18:35:16 -0800 Subject: [PATCH] Switch between dualQuats and matrix skinning based on model entity scale factor. --- .../src/RenderableModelEntityItem.cpp | 7 ++++++- .../render-utils/src/MeshPartPayload.cpp | 9 ++++++++- libraries/render-utils/src/MeshPartPayload.h | 2 ++ libraries/render-utils/src/Model.cpp | 20 ++++++++++++------- libraries/render-utils/src/Model.h | 1 + .../render-utils/src/RenderPipelines.cpp | 2 +- libraries/shared/src/DualQuaternion.h | 2 +- libraries/shared/src/GLMHelpers.cpp | 3 +++ libraries/shared/src/GLMHelpers.h | 2 ++ 9 files changed, 37 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 83ec675adf..d295e9e1fa 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -133,6 +133,9 @@ void RenderableModelEntityItem::doInitialModelSimulation() { model->setRotation(getWorldOrientation()); model->setTranslation(getWorldPosition()); + glm::vec3 scale = model->getScale(); + model->setUseDualQuaternionSkinning(!isNonUniformScale(scale)); + if (_needsInitialSimulation) { model->simulate(0.0f); _needsInitialSimulation = false; @@ -243,6 +246,8 @@ void RenderableModelEntityItem::updateModelBounds() { } if (updateRenderItems) { + glm::vec3 scale = model->getScale(); + model->setUseDualQuaternionSkinning(!isNonUniformScale(scale)); model->updateRenderItems(); } } @@ -1500,4 +1505,4 @@ void ModelEntityRenderer::processMaterials() { material.pop(); } } -} \ No newline at end of file +} diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4a0ea40f55..99048fe324 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -407,7 +407,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe if (isWireframe) { builder.withWireframe(); } - if (_useDualQuaternionSkinning) { + if (_useDualQuaternionSkinning && isSkinned) { builder.withDualQuatSkinned(); } @@ -497,3 +497,10 @@ void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterDualQuaternions); + void setUseDualQuaternionSkinning(bool value); + gpu::BufferPointer _clusterBuffer; int _meshIndex; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index da43e4fd8f..8318715732 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -288,6 +288,7 @@ void Model::updateRenderItems() { invalidatePayloadShapeKey, isWireframe, isVisible, viewTagBits, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) { + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); if (useDualQuaternionSkinning) { data.updateClusterBuffer(meshState.clusterDualQuaternions); } else { @@ -388,11 +389,8 @@ bool Model::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; - if (_useDualQuaternionSkinning) { - state.clusterDualQuaternions.resize(mesh.clusters.size()); - } else { - state.clusterMatrices.resize(mesh.clusters.size()); - } + 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 @@ -1248,6 +1246,10 @@ void Model::snapToRegistrationPoint() { _snappedToRegistrationPoint = true; } +void Model::setUseDualQuaternionSkinning(bool value) { + _useDualQuaternionSkinning = value; +} + void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) @@ -1583,11 +1585,13 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); data.setShapeKey(invalidatePayloadShapeKey, wireframe); }); } @@ -1608,11 +1612,13 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string bool wireframe = isWireframe(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.removeMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setUseDualQuaternionSkinning(useDualQuaternionSkinning); data.setShapeKey(invalidatePayloadShapeKey, wireframe); }); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 61e699f30a..aef6a84a24 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -314,6 +314,7 @@ public: void scaleToFit(); bool getUseDualQuaternionSkinning() const { return _useDualQuaternionSkinning; } + void setUseDualQuaternionSkinning(bool value); void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index cccc128b64..3fedae1778 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -447,7 +447,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular().withFade(), skinModelNormalMapFadeVertex, modelTranslucentNormalMapFadePixel, batchSetter, itemSetter); - // dual quatenion skinned + // dual quaternion skinned addPipeline( Key::Builder().withMaterial().withSkinned().withDualQuatSkinned(), skinModelDualQuatVertex, modelPixel, nullptr, nullptr); diff --git a/libraries/shared/src/DualQuaternion.h b/libraries/shared/src/DualQuaternion.h index 709c089fdc..af1011a6d8 100644 --- a/libraries/shared/src/DualQuaternion.h +++ b/libraries/shared/src/DualQuaternion.h @@ -55,7 +55,7 @@ protected: inline QDebug operator<<(QDebug debug, const DualQuaternion& dq) { - debug << "AnimPose, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")"; + debug << "DualQuaternion, real = (" << dq._real.x << dq._real.y << dq._real.z << dq._real.w << "), dual = (" << dq._dual.x << dq._dual.y << dq._dual.z << dq._dual.w << ")"; return debug; } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index ff1d29eed1..46e484cf2b 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -601,3 +601,6 @@ glm::vec3 randVector() { return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f; } +bool isNonUniformScale(const glm::vec3& scale) { + return fabsf(scale.x - scale.y) > EPSILON || fabsf(scale.y - scale.z) > EPSILON; +} diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 4f761a4aac..5c9a8b5ca1 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -260,6 +260,8 @@ glm::mat4 orthoInverse(const glm::mat4& m); // Return a random vector of average length 1 glm::vec3 randVector(); +bool isNonUniformScale(const glm::vec3& scale); + // // Safe replacement of glm_mat4_mul() for unaligned arguments instead of __m128 //