diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index b1c9f7262e..15ff09d13d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -33,6 +33,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : { // SkeletonModels, and by extention Avatars, use Dual Quaternion skinning. _useDualQuaternionSkinning = true; + _forceOffset = true; // Avatars all cast shadow setCanCastShadow(true); @@ -152,11 +153,11 @@ void SkeletonModel::updateAttitude(const glm::quat& orientation) { // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), // but just before head has been simulated. -void SkeletonModel::simulate(float deltaTime, bool fullUpdate, bool skeleton) { +void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { updateAttitude(_owningAvatar->getWorldOrientation()); setBlendshapeCoefficients(_owningAvatar->getHead()->getSummedBlendshapeCoefficients()); - Parent::simulate(deltaTime, fullUpdate, true); + Parent::simulate(deltaTime, fullUpdate); if (fullUpdate) { // let rig compute the model offset glm::vec3 registrationPoint; diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h index b21c414c37..e24d969461 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h @@ -36,7 +36,7 @@ public: void initJointStates() override; - void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false) override; + void simulate(float deltaTime, bool fullUpdate = true) override; glm::vec3 avoidCrossedEyes(const glm::vec3& lookAt); void updateRig(float deltaTime, glm::mat4 parentTransform) override; void updateAttitude(const glm::quat& orientation); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f58df45a31..7efc988bb4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -152,8 +152,9 @@ void RenderableModelEntityItem::updateModelBounds() { bool needsSimulate = false; if (!overridingModelTransform && (model->getScaleToFitDimensions() != scaledDimensions || - model->getRegistrationPoint() != registrationPoint || - !model->getIsScaledToFit() || _useOriginalPivot == model->getSnapModelToRegistrationPoint())) { + model->getRegistrationPoint() != registrationPoint || + !model->getIsScaledToFit() || _needsToRescaleModel || + _useOriginalPivot == model->getSnapModelToRegistrationPoint())) { // The machinery for updateModelBounds will give existing models the opportunity to fix their // translation/rotation/scale/registration. The first two are straightforward, but the latter two // have guards to make sure they don't happen after they've already been set. Here we reset those guards. diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0194b838cc..a58bfd6f5b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -344,7 +344,8 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 transRot = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 modelToWorldMatrix = transRot; if (!_snapModelToRegistrationPoint) { modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); } @@ -362,9 +363,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // we can use the AABox's intersection by mapping our origin and direction into the model frame // and testing intersection there. if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, 1.0f / modelFrameDirection, distance, face, surfaceNormal)) { - if (getURL().toString().toLower().contains("sink")) { - qDebug() << "boop" << modelFrameBox; - } QMutexLocker locker(&_mutex); float bestDistance = FLT_MAX; @@ -382,7 +380,14 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g calculateTriangleSets(hfmModel); } - glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); + glm::mat4 meshToWorldMatrix = transRot; + if (_snapModelToRegistrationPoint || _forceOffset) { + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); + } else { + Extents unscaledExtents = getUnscaledMeshExtents(); + glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -504,7 +509,8 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co } // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 transRot = createMatFromQuatAndPos(_rotation, _translation); + glm::mat4 modelToWorldMatrix = transRot; if (!_snapModelToRegistrationPoint) { modelToWorldMatrix = modelToWorldMatrix * glm::translate(getOriginalOffset()); } @@ -540,7 +546,14 @@ bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, co calculateTriangleSets(hfmModel); } - glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * (glm::scale(_scale) * glm::translate(_offset)); + glm::mat4 meshToWorldMatrix = transRot; + if (_snapModelToRegistrationPoint || _forceOffset) { + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(_offset)); + } else { + Extents unscaledExtents = getUnscaledMeshExtents(); + glm::vec3 unscaledDimensions = unscaledExtents.maximum - unscaledExtents.minimum; + meshToWorldMatrix = meshToWorldMatrix * (glm::scale(_scale) * glm::translate(unscaledDimensions * (0.5f - _registrationPoint))); + } glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); @@ -1420,7 +1433,7 @@ void Model::snapToRegistrationPoint() { glm::vec3 Model::getOriginalOffset() const { Extents modelMeshExtents = getUnscaledMeshExtents(); glm::vec3 dimensions = (modelMeshExtents.maximum - modelMeshExtents.minimum); - glm::vec3 offset = modelMeshExtents.minimum + (dimensions * _registrationPoint); + glm::vec3 offset = modelMeshExtents.minimum + (0.5f * dimensions); glm::mat4 transform = glm::scale(_scale) * glm::translate(offset); return transform[3]; } @@ -1430,7 +1443,7 @@ void Model::setUseDualQuaternionSkinning(bool value) { _useDualQuaternionSkinning = value; } -void Model::simulate(float deltaTime, bool fullUpdate, bool skeleton) { +void Model::simulate(float deltaTime, bool fullUpdate) { DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint) || _needsTransformUpdate; @@ -1446,7 +1459,7 @@ void Model::simulate(float deltaTime, bool fullUpdate, bool skeleton) { snapToRegistrationPoint(); } // update the world space transforms for all joints - glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || skeleton) ? + glm::mat4 parentTransform = glm::scale(_scale) * ((_snapModelToRegistrationPoint || _forceOffset) ? glm::translate(_offset) : glm::translate(getNaturalDimensions() * (0.5f - _registrationPoint))); updateRig(deltaTime, parentTransform); _needsTransformUpdate = false; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 800bfc7e15..aa5df1a3dd 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -169,7 +169,7 @@ public: bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } bool getSnappedToRegistrationPoint() { return _snappedToRegistrationPoint; } - virtual void simulate(float deltaTime, bool fullUpdate = true, bool skeleton = false); + virtual void simulate(float deltaTime, bool fullUpdate = true); virtual void updateClusterMatrices(); virtual void updateBlendshapes(); @@ -414,6 +414,7 @@ protected: bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint { glm::vec3(0.5f) }; /// the point in model space our center is snapped to bool _needsTransformUpdate { false }; + bool _forceOffset { false }; std::vector _meshStates; diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index fc3d4fc10f..96dbf4637d 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -737,6 +737,7 @@ var toolBar = (function () { grabbable: result.grabbable }, dynamic: dynamic, + useOriginalPivot: result.useOriginalPivot }); } } diff --git a/scripts/system/create/qml/NewModelDialog.qml b/scripts/system/create/qml/NewModelDialog.qml index 758706a79b..807ab1cd56 100644 --- a/scripts/system/create/qml/NewModelDialog.qml +++ b/scripts/system/create/qml/NewModelDialog.qml @@ -120,6 +120,11 @@ Rectangle { height: 600 spacing: 10 + CheckBox { + id: useOriginalPivot + text: qsTr("Use Original Pivot") + } + CheckBox { id: grabbable text: qsTr("Grabbable") @@ -219,7 +224,8 @@ Rectangle { url: modelURL.text, dynamic: dynamic.checked, collisionShapeIndex: collisionType.currentIndex, - grabbable: grabbable.checked + grabbable: grabbable.checked, + useOriginalPivot: useOriginalPivot.checked } }); }