From 18113d824c3f8c8340c6affc67c8bbf997728452 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 19 Dec 2017 15:57:06 -0800 Subject: [PATCH] Created Model::TransformComponents class --- .../src/CauterizedMeshPartPayload.cpp | 30 +++- .../src/CauterizedMeshPartPayload.h | 7 +- .../render-utils/src/CauterizedModel.cpp | 139 ++++------------- .../render-utils/src/MeshPartPayload.cpp | 83 ++++++----- libraries/render-utils/src/MeshPartPayload.h | 10 +- libraries/render-utils/src/Model.cpp | 53 ++----- libraries/render-utils/src/Model.h | 45 +++++- libraries/render-utils/src/Skinning.slh | 140 ++++++++---------- .../render-utils/src/SoftAttachmentModel.cpp | 34 +---- 9 files changed, 237 insertions(+), 304 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 396cd13508..c64c98b271 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -20,19 +20,35 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} -void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices) { - ModelMeshPartPayload::updateClusterBuffer(clusterMatrices); +#ifdef SKIN_COMP +void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms) { + ModelMeshPartPayload::updateClusterBuffer(clusterTransforms); - if (cauterizedClusterMatrices.size() > 1) { + if (cauterizedClusterTransforms.size() > 1) { if (!_cauterizedClusterBuffer) { - _cauterizedClusterBuffer = std::make_shared(cauterizedClusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) cauterizedClusterMatrices.data()); + _cauterizedClusterBuffer = std::make_shared(cauterizedClusterTransforms.size() * sizeof(Model::TransformComponents), + (const gpu::Byte*) cauterizedClusterTransforms.data()); } else { - _cauterizedClusterBuffer->setSubData(0, cauterizedClusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) cauterizedClusterMatrices.data()); + _cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(Model::TransformComponents), + (const gpu::Byte*) cauterizedClusterTransforms.data()); } } } +#else +void CauterizedMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms) { + ModelMeshPartPayload::updateClusterBuffer(clusterTransforms); + + if (cauterizedClusterTransforms.size() > 1) { + if (!_cauterizedClusterBuffer) { + _cauterizedClusterBuffer = std::make_shared(cauterizedClusterTransforms.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterTransforms.data()); + } else { + _cauterizedClusterBuffer->setSubData(0, cauterizedClusterTransforms.size() * sizeof(glm::mat4), + (const gpu::Byte*) cauterizedClusterTransforms.data()); + } + } +} +#endif void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform& renderTransform) { _cauterizedTransform = renderTransform; diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 44eddc6e31..1ee77c300f 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -14,8 +14,11 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: CauterizedMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); - - void updateClusterBuffer(const std::vector& clusterMatrices, const std::vector& cauterizedClusterMatrices); +#ifdef SKIN_COMP + void updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms); +#else + void updateClusterBuffer(const std::vector& clusterTransforms, const std::vector& cauterizedClusterTransforms); +#endif void updateTransformForCauterizedMesh(const Transform& renderTransform); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 282aedf180..606e1f0351 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -35,7 +35,7 @@ bool CauterizedModel::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { Model::MeshState state; - state.clusterMatrices.resize(mesh.clusters.size()); + state.clusterTransforms.resize(mesh.clusters.size()); _cauterizeMeshStates.append(state); } } @@ -116,47 +116,14 @@ void CauterizedModel::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - /* AJT: TODO REMOVE */ -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); -#endif #ifdef SKIN_COMP - - if (debug) { - qDebug() << "AJT: _meshState[" << i << "], cluster[" << j << "]"; - } - - AnimPose jointPose = _rig.getJointPose(cluster.jointIndex); - AnimPose result = jointPose * AnimPose(cluster.inverseBindMatrix); - result.rot() = glm::normalize(result.rot()); - - // pack scale rotation and translation into a mat4. - state.clusterMatrices[j][0].x = result.scale().x; - state.clusterMatrices[j][0].y = result.scale().y; - state.clusterMatrices[j][0].z = result.scale().z; - - state.clusterMatrices[j][1].x = result.rot().x; - state.clusterMatrices[j][1].y = result.rot().y; - state.clusterMatrices[j][1].z = result.rot().z; - state.clusterMatrices[j][1].w = result.rot().w; - - state.clusterMatrices[j][2].x = result.trans().x; - state.clusterMatrices[j][2].y = result.trans().y; - state.clusterMatrices[j][2].z = result.trans().z; - - // AJT REMOVE - if (debug) { - glm::mat4 jointMatrix = _rig.getJointTransform(cluster.jointIndex); - glm::mat4 m; - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); - qDebug() << "AJT: m =" << m; - qDebug() << "AJT: (AnimPose)m =" << AnimPose(m); - qDebug() << "AJT: result =" << result; - qDebug() << "AJT: (mat4)result =" << (glm::mat4)result; - SKIN_ASSERT(result.fuzzyEqual(AnimPose(m))); - } + // AJT: TODO: optimize + glm::mat4 m; + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); + state.clusterTransforms[j] = Model::TransformComponents(m); +#else + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); #endif } } @@ -177,60 +144,18 @@ void CauterizedModel::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - // AJT: TODO REMOVE: auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { jointMatrix = cauterizeMatrix; } - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); -#endif + #ifdef SKIN_COMP - - if (debug) { - qDebug() << "AJT: CAUTERIZED _meshState[" << i << "], cluster[" << j << "]"; - } - - auto jointPose = _rig.getJointPose(cluster.jointIndex); - /* - if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { - jointPose = cauterizePose; - } - */ - AnimPose result = jointPose * AnimPose(cluster.inverseBindMatrix); - result.rot() = glm::normalize(result.rot()); - - // pack scale rotation and translation into a mat4. - state.clusterMatrices[j][0].x = result.scale().x; - state.clusterMatrices[j][0].y = result.scale().y; - state.clusterMatrices[j][0].z = result.scale().z; - - state.clusterMatrices[j][1].x = result.rot().x; - state.clusterMatrices[j][1].y = result.rot().y; - state.clusterMatrices[j][1].z = result.rot().z; - state.clusterMatrices[j][1].w = result.rot().w; - - state.clusterMatrices[j][2].x = result.trans().x; - state.clusterMatrices[j][2].y = result.trans().y; - state.clusterMatrices[j][2].z = result.trans().z; - - // AJT REMOVE - auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); - /* - if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { - jointMatrix = cauterizeMatrix; - } - */ - if (debug) { - glm::mat4 m; - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); - qDebug() << "AJT: m =" << m; - qDebug() << "AJT: (AnimPose)m =" << AnimPose(m); - qDebug() << "AJT: result =" << result; - qDebug() << "AJT: (mat4)result =" << (glm::mat4)result; - SKIN_ASSERT(result.fuzzyEqual(AnimPose(m))); - } + // AJT: TODO: optimize + glm::mat4 m; + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); + state.clusterTransforms[j] = Model::TransformComponents(m); +#else + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); #endif } } @@ -288,43 +213,31 @@ void CauterizedModel::updateRenderItems() { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; - auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); - auto clusterMatricesCauterized(self->getCauterizeMeshState(meshIndex).clusterMatrices); + auto clusterTransforms(self->getMeshState(meshIndex).clusterTransforms); + auto clusterTransformsCauterized(self->getCauterizeMeshState(meshIndex).clusterTransforms); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized, invalidatePayloadShapeKey, + transaction.updateItem(itemID, [modelTransform, clusterTransforms, clusterTransformsCauterized, invalidatePayloadShapeKey, isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) { - data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); + data.updateClusterBuffer(clusterTransforms, clusterTransformsCauterized); Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); -#endif + if (clusterTransforms.size() == 1) { #ifdef SKIN_COMP - glm::vec3 scale(clusterMatrices[0][0]); - glm::quat rot(clusterMatrices[0][1].w, clusterMatrices[0][1].x, clusterMatrices[0][1].y, clusterMatrices[0][1].z); - glm::vec3 trans(clusterMatrices[0][2]); - glm::mat4 m = createMatFromScaleQuatAndPos(scale, rot, trans); - renderTransform = modelTransform.worldTransform(Transform(m)); + renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix())); +#else + renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); #endif } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); renderTransform = modelTransform; - if (clusterMatricesCauterized.size() == 1) { -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); -#endif + if (clusterTransformsCauterized.size() == 1) { #ifdef SKIN_COMP - glm::vec3 scale(clusterMatricesCauterized[0][0]); - glm::quat rot(clusterMatricesCauterized[0][1].w, clusterMatricesCauterized[0][1].x, clusterMatricesCauterized[0][1].y, clusterMatricesCauterized[0][1].z); - glm::vec3 trans(clusterMatricesCauterized[0][2]); - glm::mat4 m = createMatFromScaleQuatAndPos(scale, rot, trans); - renderTransform = modelTransform.worldTransform(Transform(m)); + renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0].getMatrix())); +#else + renderTransform = modelTransform.worldTransform(Transform(clusterTransformsCauterized[0])); #endif } data.updateTransformForCauterizedMesh(renderTransform); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index fcf6a61fb5..3056dbc728 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -326,22 +326,17 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in const Model::MeshState& state = model->getMeshState(_meshIndex); updateMeshPart(modelMesh, partIndex); - computeAdjustedLocalBound(state.clusterMatrices); + computeAdjustedLocalBound(state.clusterTransforms); updateTransform(transform, offsetTransform); Transform renderTransform = transform; - if (state.clusterMatrices.size() == 1) { -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - renderTransform = transform.worldTransform(Transform(state.clusterMatrices[0])); -#endif + if (state.clusterTransforms.size() == 1) { #ifdef SKIN_COMP - glm::vec3 scale(state.clusterMatrices[0][0]); - glm::quat rot(state.clusterMatrices[0][1].w, state.clusterMatrices[0][1].x, state.clusterMatrices[0][1].y, state.clusterMatrices[0][1].z); - glm::vec3 trans(state.clusterMatrices[0][2]); - glm::mat4 m = createMatFromScaleQuatAndPos(scale, rot, trans); - renderTransform = transform.worldTransform(Transform(m)); + renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0].getMatrix())); +#else + renderTransform = transform.worldTransform(Transform(state.clusterTransforms[0])); #endif + } updateTransformForSkinnedMesh(renderTransform, transform); @@ -371,20 +366,36 @@ void ModelMeshPartPayload::notifyLocationChanged() { } - -void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterMatrices) { +#ifdef SKIN_COMP +void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms) { // Once computed the cluster matrices, update the buffer(s) - if (clusterMatrices.size() > 1) { + if (clusterTransforms.size() > 1) { if (!_clusterBuffer) { - _clusterBuffer = std::make_shared(clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.data()); + _clusterBuffer = std::make_shared(clusterTransforms.size() * sizeof(Model::TransformComponents), + (const gpu::Byte*) clusterTransforms.data()); } else { - _clusterBuffer->setSubData(0, clusterMatrices.size() * sizeof(glm::mat4), - (const gpu::Byte*) clusterMatrices.data()); + _clusterBuffer->setSubData(0, clusterTransforms.size() * sizeof(Model::TransformComponents), + (const gpu::Byte*) clusterTransforms.data()); } } } +#else +void ModelMeshPartPayload::updateClusterBuffer(const std::vector& clusterTransforms) { + // Once computed the cluster matrices, update the buffer(s) + if (clusterTransforms.size() > 1) { + if (!_clusterBuffer) { + _clusterBuffer = std::make_shared(clusterTransforms.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterTransforms.data()); + } + else { + _clusterBuffer->setSubData(0, clusterTransforms.size() * sizeof(glm::mat4), + (const gpu::Byte*) clusterTransforms.data()); + } + } +} +#endif + void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform) { _transform = renderTransform; @@ -550,23 +561,27 @@ void ModelMeshPartPayload::render(RenderArgs* args) { args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } -void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterMatrices) { - _adjustedLocalBound = _localBound; - if (clusterMatrices.size() > 0) { - _adjustedLocalBound.transform(clusterMatrices[0]); - for (int i = 1; i < (int)clusterMatrices.size(); ++i) { - AABox clusterBound = _localBound; -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - clusterBound.transform(clusterMatrices[i]); -#endif #ifdef SKIN_COMP - // AJT: FIXME: TODO: SLOW AS SHIT - glm::vec3 scale(clusterMatrices[i][0]); - glm::quat rot(clusterMatrices[i][1].w, clusterMatrices[i][1].x, clusterMatrices[i][1].y, clusterMatrices[i][1].z); - glm::vec3 trans(clusterMatrices[i][2]); - glm::mat4 m = createMatFromScaleQuatAndPos(scale, rot, trans); - clusterBound.transform(m); +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterTransforms) { +#else +void ModelMeshPartPayload::computeAdjustedLocalBound(const std::vector& clusterTransforms) { +#endif + _adjustedLocalBound = _localBound; + if (clusterTransforms.size() > 0) { +#ifdef SKIN_COMP + // AJT: TODO: optimize + _adjustedLocalBound.transform(clusterTransforms[0].getMatrix()); +#else + _adjustedLocalBound.transform(clusterTransforms[0]); +#endif + + for (int i = 1; i < (int)clusterTransforms.size(); ++i) { + AABox clusterBound = _localBound; +#ifdef SKIN_COMP + // AJT: TODO: optimize + clusterBound.transform(clusterTransforms[i].getMatrix()); +#else + clusterBound.transform(clusterTransforms[i]); #endif _adjustedLocalBound += clusterBound; } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index fb55883101..989a653b2f 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -87,7 +87,11 @@ public: typedef Payload::DataPointer Pointer; void notifyLocationChanged() override; - void updateClusterBuffer(const std::vector& clusterMatrices); +#ifdef SKIN_COMP + void updateClusterBuffer(const std::vector& clusterTransforms); +#else + void updateClusterBuffer(const std::vector& clusterTransforms); +#endif void updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform); // Render Item interface @@ -104,7 +108,11 @@ public: void bindMesh(gpu::Batch& batch) override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; +#ifdef SKIN_COMP + void computeAdjustedLocalBound(const std::vector& clusterTransforms); +#else void computeAdjustedLocalBound(const std::vector& clusterMatrices); +#endif gpu::BufferPointer _clusterBuffer; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 36d26dea7b..0f014032a3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -266,25 +266,20 @@ void Model::updateRenderItems() { auto itemID = self->_modelMeshRenderItemIDs[i]; auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; - auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); + auto clusterTransforms(self->getMeshState(meshIndex).clusterTransforms); bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [modelTransform, clusterMatrices, invalidatePayloadShapeKey, + transaction.updateItem(itemID, [modelTransform, clusterTransforms, invalidatePayloadShapeKey, isWireframe, isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { - data.updateClusterBuffer(clusterMatrices); + data.updateClusterBuffer(clusterTransforms); + Transform renderTransform = modelTransform; - if (clusterMatrices.size() == 1) { -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); - renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); -#endif + if (clusterTransforms.size() == 1) { #ifdef SKIN_COMP - glm::vec3 scale(clusterMatrices[0][0]); - glm::quat rot(clusterMatrices[0][1].w, clusterMatrices[0][1].x, clusterMatrices[0][1].y, clusterMatrices[0][1].z); - glm::vec3 trans(clusterMatrices[0][2]); - glm::mat4 m = createMatFromScaleQuatAndPos(scale, rot, trans); - renderTransform = modelTransform.worldTransform(Transform(m)); + renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0].getMatrix())); +#else + renderTransform = modelTransform.worldTransform(Transform(clusterTransforms[0])); #endif } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); @@ -338,7 +333,7 @@ bool Model::updateGeometry() { const FBXGeometry& fbxGeometry = getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; - state.clusterMatrices.resize(mesh.clusters.size()); + state.clusterTransforms.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 @@ -1169,7 +1164,7 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) { void Model::computeMeshPartLocalBounds() { for (auto& part : _modelMeshRenderItems) { const Model::MeshState& state = _meshStates.at(part->_meshIndex); - part->computeAdjustedLocalBound(state.clusterMatrices); + part->computeAdjustedLocalBound(state.clusterTransforms); } } @@ -1187,30 +1182,14 @@ void Model::updateClusterMatrices() { const FBXMesh& mesh = geometry.meshes.at(i); for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); - - // AJT: TODO FIXME -#ifdef SKIN_MATRIX - SKIN_ASSERT(false); auto jointMatrix = _rig.getJointTransform(cluster.jointIndex); - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); -#endif #ifdef SKIN_COMP - AnimPose jointPose = _rig.getJointPose(cluster.jointIndex); - AnimPose result = jointPose * AnimPose(cluster.inverseBindMatrix); - - // pack scale rotation and translation into a mat4. - state.clusterMatrices[j][0].x = result.scale().x; - state.clusterMatrices[j][0].y = result.scale().y; - state.clusterMatrices[j][0].z = result.scale().z; - - state.clusterMatrices[j][1].x = result.rot().x; - state.clusterMatrices[j][1].y = result.rot().y; - state.clusterMatrices[j][1].z = result.rot().z; - state.clusterMatrices[j][1].w = result.rot().w; - - state.clusterMatrices[j][2].x = result.trans().x; - state.clusterMatrices[j][2].y = result.trans().y; - state.clusterMatrices[j][2].z = result.trans().z; + // AJT: TODO: optimize + glm::mat4 mat; + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, mat); + state.clusterTransforms[j] = TransformComponents(mat); +#else + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); #endif } } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b798d77ab9..e8f11a421b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -43,8 +43,6 @@ } \ } while(false) -//#define SKIN_MATRIX -//#define SKIN_DUAL_QUAT #define SKIN_COMP class AbstractViewStateInterface; @@ -257,9 +255,50 @@ public: int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; } bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; } + class TransformComponents { + public: + TransformComponents() {} + TransformComponents(const glm::mat4& m) { + AnimPose p(m); + _scale.x = p.scale().x; + _scale.y = p.scale().y; + _scale.z = p.scale().z; + _rot = p.rot(); + _trans.x = p.trans().x; + _trans.y = p.trans().y; + _trans.z = p.trans().z; + } + + TransformComponents(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) { + _scale.x = scale.x; + _scale.y = scale.y; + _scale.z = scale.z; + _rot = rot; + _trans.x = trans.x; + _trans.y = trans.y; + _trans.z = trans.z; + } + + glm::vec3 getScale() const { return glm::vec3(_scale); } + glm::quat getRot() const { return _rot; } + glm::vec3 getTrans() const { return glm::vec3(_trans); } + glm::mat4 getMatrix() const { return createMatFromScaleQuatAndPos(getScale(), getRot(), getTrans()); }; + + protected: + glm::vec4 _scale { 1.0f, 1.0f, 1.0f, 0.0f }; + glm::quat _rot { 1.0f, 0.0f, 0.0f, 0.0f }; + glm::vec4 _trans { 0.0f, 0.0f, 0.0f, 0.0f }; + glm::vec4 _padding { 0.0f, 0.0f, 0.0f, 0.0f }; + }; + class MeshState { public: - std::vector clusterMatrices; +#ifdef SKIN_COMP + std::vector clusterTransforms; +#else + std::vector clusterTransforms; +#endif + }; const MeshState& getMeshState(int index) { return _meshStates.at(index); } diff --git a/libraries/render-utils/src/Skinning.slh b/libraries/render-utils/src/Skinning.slh index 371efef145..63bb6ba46e 100644 --- a/libraries/render-utils/src/Skinning.slh +++ b/libraries/render-utils/src/Skinning.slh @@ -38,60 +38,11 @@ void dqMul(vec4 lhsReal, vec4 lhsImag, vec4 rhsReal, vec4 rhsImag, out vec4 real imagOut = quatMul(lhsReal, rhsImag) + quatMul(lhsImag, rhsReal); } -// dual quat blend -void blendClusters_dual_quat(ivec4 skinClusterIndex, vec4 skinClusterWeight, out vec3 scaleOut, out vec4 rotOut, out vec3 posOut) { - vec3 scale = vec3(0.0, 0.0, 0.0); - vec4 dqReal = vec4(0.0, 0.0, 0.0, 0.0); - vec4 dqImag = vec4(0.0, 0.0, 0.0, 0.0); - for (int i = 0; i < INDICES_PER_VERTEX; i++) { - mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; - float clusterWeight = skinClusterWeight[i]; +void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { + vec3 sAccum = vec3(0.0, 0.0, 0.0); + vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0); + vec3 tAccum = vec3(0.0, 0.0, 0.0); - vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); - vec4 dqr = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); - vec4 dqi = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]); - - scale += s * clusterWeight; - dqReal += dqr * clusterWeight; - dqImag += dqi * clusterWeight; - } - - scaleOut = scale; - - float dqLen = length(dqReal); - dqReal *= 1.0 / dqLen; - dqImag *= 1.0 / dqLen; - - rotOut = dqReal; - - vec4 invReal = quatConj(dqReal); - posOut.xyz = 2.0 * quatMul(dqImag, invReal).xyz; -} - -// rigid dual quat blend -void blendClusters_rigid_dual_quat(ivec4 skinClusterIndex, vec4 skinClusterWeight, out vec3 scaleOut, out vec4 rotOut, out vec3 posOut) { - float maxWeight = 0.0; - for (int i = 0; i < INDICES_PER_VERTEX; i++) { - mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; - float clusterWeight = skinClusterWeight[i]; - - vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); - vec4 dqr = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); - vec4 dqi = vec4(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2], clusterMatrix[2][3]); - - if (clusterWeight > maxWeight) { - maxWeight = clusterWeight; - scaleOut = s; - rotOut = dqr; - vec4 invReal = quatConj(dqr); - posOut = 2.0 * quatMul(dqi, invReal).xyz; - } - } -} - -// rigid componentwise blend -void blendClusters(ivec4 skinClusterIndex, vec4 skinClusterWeight, out vec3 scaleOut, out vec4 rotOut, out vec3 posOut) { - float maxWeight = 0.0; for (int i = 0; i < INDICES_PER_VERTEX; i++) { mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; float clusterWeight = skinClusterWeight[i]; @@ -100,51 +51,83 @@ void blendClusters(ivec4 skinClusterIndex, vec4 skinClusterWeight, out vec3 scal vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]); - if (clusterWeight > maxWeight) { - maxWeight = clusterWeight; - scaleOut = s; - rotOut = r; - posOut = t; + if (dot(r, rAccum) < 0) { + r = -r; } + + sAccum += s * clusterWeight; + rAccum += r * clusterWeight; + tAccum += t * clusterWeight; } -} -void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { + rAccum = normalize(rAccum); - vec3 scale, pos; - vec4 rot; - blendClusters(skinClusterIndex, skinClusterWeight, scale, rot, pos); - - skinnedPosition.xyz = rotateByQuat(rot, (vec3(inPosition) * scale)) + pos; - skinnedPosition.w = 1; + skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1); } void skinPositionNormal(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, out vec4 skinnedPosition, out vec3 skinnedNormal) { - vec3 scale, pos; - vec4 rot; - blendClusters(skinClusterIndex, skinClusterWeight, scale, rot, pos); + vec3 sAccum = vec3(0.0, 0.0, 0.0); + vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0); + vec3 tAccum = vec3(0.0, 0.0, 0.0); - skinnedNormal.xyz = rotateByQuat(rot, inNormal * scale); + for (int i = 0; i < INDICES_PER_VERTEX; i++) { + mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; + float clusterWeight = skinClusterWeight[i]; + + vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); + vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); + vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]); + + if (dot(r, rAccum) < 0) { + r = -r; + } + + sAccum += s * clusterWeight; + rAccum += r * clusterWeight; + tAccum += t * clusterWeight; + } + + rAccum = normalize(rAccum); + + skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1); + skinnedNormal = rotateByQuat(rAccum, inNormal); } void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, vec3 inNormal, vec3 inTangent, out vec4 skinnedPosition, out vec3 skinnedNormal, out vec3 skinnedTangent) { - vec3 scale, pos; - vec4 rot; - blendClusters(skinClusterIndex, skinClusterWeight, scale, rot, pos); + vec3 sAccum = vec3(0.0, 0.0, 0.0); + vec4 rAccum = vec4(0.0, 0.0, 0.0, 0.0); + vec3 tAccum = vec3(0.0, 0.0, 0.0); - skinnedPosition.xyz = rotateByQuat(rot, (vec3(inPosition) * scale)) + pos; - skinnedPosition.w = 1; + for (int i = 0; i < INDICES_PER_VERTEX; i++) { + mat4 clusterMatrix = clusterMatrices[(skinClusterIndex[i])]; + float clusterWeight = skinClusterWeight[i]; - skinnedNormal = rotateByQuat(rot, inNormal * scale); - skinnedTangent = rotateByQuat(rot, inTangent * scale); + vec3 s = vec3(clusterMatrix[0][0], clusterMatrix[0][1], clusterMatrix[0][2]); + vec4 r = vec4(clusterMatrix[1][0], clusterMatrix[1][1], clusterMatrix[1][2], clusterMatrix[1][3]); + vec3 t = vec3(clusterMatrix[2][0], clusterMatrix[2][1], clusterMatrix[2][2]); + + if (dot(r, rAccum) < 0) { + r = -r; + } + + sAccum += s * clusterWeight; + rAccum += r * clusterWeight; + tAccum += t * clusterWeight; + } + + rAccum = normalize(rAccum); + + skinnedPosition = vec4(rotateByQuat(rAccum, (vec3(inPosition) * sAccum)) + tAccum, 1); + skinnedNormal = rotateByQuat(rAccum, inNormal); + skinnedTangent = rotateByQuat(rAccum, inTangent); } -// ORIGINAL /* +// ORIGINAL void skinPosition(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPosition, out vec4 skinnedPosition) { vec4 newPosition = vec4(0.0, 0.0, 0.0, 0.0); @@ -193,5 +176,4 @@ void skinPositionNormalTangent(ivec4 skinClusterIndex, vec4 skinClusterWeight, v } */ - <@endif@> diff --git a/libraries/render-utils/src/SoftAttachmentModel.cpp b/libraries/render-utils/src/SoftAttachmentModel.cpp index 7d49a8cda1..8fa609b241 100644 --- a/libraries/render-utils/src/SoftAttachmentModel.cpp +++ b/libraries/render-utils/src/SoftAttachmentModel.cpp @@ -50,7 +50,6 @@ void SoftAttachmentModel::updateClusterMatrices() { for (int j = 0; j < mesh.clusters.size(); j++) { const FBXCluster& cluster = mesh.clusters.at(j); -#ifdef SKIN_MATRIX // TODO: cache these look-ups as an optimization int jointIndexOverride = getJointIndexOverride(cluster.jointIndex); glm::mat4 jointMatrix; @@ -59,35 +58,14 @@ void SoftAttachmentModel::updateClusterMatrices() { } else { jointMatrix = _rig.getJointTransform(cluster.jointIndex); } - SKIN_ASSERT(false); - glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterMatrices[j]); -#endif #ifdef SKIN_COMP - // TODO: cache these look-ups as an optimization - int jointIndexOverride = getJointIndexOverride(cluster.jointIndex); - AnimPose jointPose; - if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) { - jointPose = _rigOverride.getJointPose(jointIndexOverride); - } else { - jointPose = _rig.getJointPose(cluster.jointIndex); - } - AnimPose result = jointPose * AnimPose(cluster.inverseBindMatrix); - - // pack scale rotation and translation into a mat4. - state.clusterMatrices[j][0].x = result.scale().x; - state.clusterMatrices[j][0].y = result.scale().y; - state.clusterMatrices[j][0].z = result.scale().z; - - state.clusterMatrices[j][1].x = result.rot().x; - state.clusterMatrices[j][1].y = result.rot().y; - state.clusterMatrices[j][1].z = result.rot().z; - state.clusterMatrices[j][1].w = result.rot().w; - - state.clusterMatrices[j][2].x = result.trans().x; - state.clusterMatrices[j][2].y = result.trans().y; - state.clusterMatrices[j][2].z = result.trans().z; + // AJT: TODO: Optimize + glm::mat4 m; + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, m); + state.clusterTransforms[j] = Model::TransformComponents(m); +#else + glm_mat4u_mul(jointMatrix, cluster.inverseBindMatrix, state.clusterTransforms[j]); #endif - } }