From 86abd9120ebffdf1f1bd314549e55bd412572bef Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 1 Nov 2016 22:16:56 +0100 Subject: [PATCH 01/34] Fixed menu out of view with HMD and Xbox controller --- .../controllers/handControllerPointer.js | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index c2deaa2fac..26a8eb5ab8 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -203,14 +203,41 @@ function overlayFromWorldPoint(point) { return { x: horizontalPixels, y: verticalPixels }; } +function activeHudPoint2dGamePad() { + if(!HMD.active){ + return; + } + var headPosition = MyAvatar.getHeadPosition(); + var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); + + var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection); + + if (!hudPoint3d) { + if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here + print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong. + } + return; + } + var hudPoint2d = overlayFromWorldPoint(hudPoint3d); + + // We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if + // it's pointing at a QML tool (aka system overlay). + setReticlePosition(hudPoint2d); + + return hudPoint2d; +} + function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey. var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye) if (!controllerPose.valid) { + if(gamePad){ + return activeHudPoint2dGamePad(); + } return; // Controller is cradled. } var controllerPosition = controllerPose.position; var controllerDirection = Quat.getUp(controllerPose.rotation); - + var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here @@ -350,6 +377,7 @@ var leftTrigger = new Trigger('left'); var rightTrigger = new Trigger('right'); var activeTrigger = rightTrigger; var activeHand = Controller.Standard.RightHand; +var gamePad = Controller.findDevice("GamePad"); var LEFT_HUD_LASER = 1; var RIGHT_HUD_LASER = 2; var BOTH_HUD_LASERS = LEFT_HUD_LASER + RIGHT_HUD_LASER; @@ -405,7 +433,7 @@ clickMapping.from(rightTrigger.full).when(isPointingAtOverlayStartedNonFullTrigg clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick); // The following is essentially like Left and Right versions of // clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu); -// except that we first update the reticle position from the appropriate hand position, before invoking the ContextMenu. +// except that we first update the reticle position from the appropriate hand position, before invoking the . var wantsMenu = 0; clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu); clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) { @@ -420,6 +448,11 @@ clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (cl } wantsMenu = clicked; }); +clickMapping.from(Controller.Hardware.GamePad.Back).peek().to(function () { + Script.setTimeout(function () { + activeHudPoint2dGamePad(); + }, 0); +}); clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () { // Allow the reticle depth to be set correctly: // Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move @@ -472,13 +505,16 @@ function update() { expireMouseCursor(); clearSystemLaser(); } + //print("In updating HandControllerPointer"); updateSeeking(true); if (!handControllerLockOut.expired(now)) { return off(); // Let them use mouse in peace. } + //print("test2"); if (!Menu.isOptionChecked("First Person")) { return off(); // What to do? menus can be behind hand! } + //print("test3"); if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) { // In desktop it's pretty clear when another app is on top. In that case we bail, because // hand controllers might be sputtering "valid" data and that will keep someone from deliberately @@ -487,14 +523,18 @@ function update() { // other apps anyway. So in that case, we DO keep going even though we're not on top. (Fogbugz 1831.) return off(); // Don't mess with other apps or paused mouse activity } + leftTrigger.update(); rightTrigger.update(); if (!activeTrigger.state) { return off(); // No trigger } + if (getGrabCommunications()) { return off(); } + + var hudPoint2d = activeHudPoint2d(activeHand); if (!hudPoint2d) { return off(); From e9d10b609d3e50b02ab1089577b0887e6647113d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 2 Nov 2016 00:05:38 +0100 Subject: [PATCH 02/34] removed bad commit --- scripts/system/controllers/handControllerPointer.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 26a8eb5ab8..77cc7603e5 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -204,7 +204,7 @@ function overlayFromWorldPoint(point) { } function activeHudPoint2dGamePad() { - if(!HMD.active){ + if (!HMD.active) { return; } var headPosition = MyAvatar.getHeadPosition(); @@ -227,6 +227,7 @@ function activeHudPoint2dGamePad() { return hudPoint2d; } +var gamePad = Controller.findDevice("GamePad"); function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey. var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye) if (!controllerPose.valid) { @@ -377,7 +378,6 @@ var leftTrigger = new Trigger('left'); var rightTrigger = new Trigger('right'); var activeTrigger = rightTrigger; var activeHand = Controller.Standard.RightHand; -var gamePad = Controller.findDevice("GamePad"); var LEFT_HUD_LASER = 1; var RIGHT_HUD_LASER = 2; var BOTH_HUD_LASERS = LEFT_HUD_LASER + RIGHT_HUD_LASER; @@ -449,6 +449,8 @@ clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (cl wantsMenu = clicked; }); clickMapping.from(Controller.Hardware.GamePad.Back).peek().to(function () { + // Wait a tick an allow the reticle to be correctly set to the players look at position before invoking + // ContextMenu action Script.setTimeout(function () { activeHudPoint2dGamePad(); }, 0); @@ -505,16 +507,16 @@ function update() { expireMouseCursor(); clearSystemLaser(); } - //print("In updating HandControllerPointer"); + updateSeeking(true); if (!handControllerLockOut.expired(now)) { return off(); // Let them use mouse in peace. } - //print("test2"); + if (!Menu.isOptionChecked("First Person")) { return off(); // What to do? menus can be behind hand! } - //print("test3"); + if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) { // In desktop it's pretty clear when another app is on top. In that case we bail, because // hand controllers might be sputtering "valid" data and that will keep someone from deliberately From d29b1c34b1cc564a0670cbe2d6035f8aa962111b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 2 Nov 2016 00:07:58 +0100 Subject: [PATCH 03/34] fixed coding standard conflicts --- scripts/system/controllers/handControllerPointer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 77cc7603e5..0ad297ccd3 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -231,7 +231,7 @@ var gamePad = Controller.findDevice("GamePad"); function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey. var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye) if (!controllerPose.valid) { - if(gamePad){ + if (gamePad) { return activeHudPoint2dGamePad(); } return; // Controller is cradled. @@ -458,7 +458,7 @@ clickMapping.from(Controller.Hardware.GamePad.Back).peek().to(function () { clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () { // Allow the reticle depth to be set correctly: // Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move - // so that the system updates qml state (Reticle.pointingAtSystemOverlay) before it gives us a mouseMove. + // so that the system updates qml state (Reticle.pointingAtSystemverlay) before it gives us a mouseMove. // We don't want the system code to always do this for us, because, e.g., we do not want to get a mouseMove // after the Left/RightSecondaryThumb gives us a context menu. Only from the mouse. Script.setTimeout(function () { From 1a83cc2c3e0dc2c4691319ec2d36c561d87a6cf7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 2 Nov 2016 00:12:23 +0100 Subject: [PATCH 04/34] fixed deleted comment --- scripts/system/controllers/handControllerPointer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 0ad297ccd3..82344426cb 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -458,7 +458,7 @@ clickMapping.from(Controller.Hardware.GamePad.Back).peek().to(function () { clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () { // Allow the reticle depth to be set correctly: // Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move - // so that the system updates qml state (Reticle.pointingAtSystemverlay) before it gives us a mouseMove. + // so that the system updates qml state (Reticle.pointingAtSystemOverlay) before it gives us a mouseMove. // We don't want the system code to always do this for us, because, e.g., we do not want to get a mouseMove // after the Left/RightSecondaryThumb gives us a context menu. Only from the mouse. Script.setTimeout(function () { From 844cc03dcbbc7a8764f20cabbab13f4ce9736734 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 2 Nov 2016 10:24:01 -0700 Subject: [PATCH 05/34] fix names of model-entity joint setters --- .../src/RenderableModelEntityItem.cpp | 52 +++++++++---------- .../src/RenderableModelEntityItem.h | 4 +- libraries/entities/src/EntityItem.h | 5 +- .../entities/src/EntityScriptingInterface.cpp | 30 +++++------ .../entities/src/EntityScriptingInterface.h | 16 +++--- libraries/entities/src/ModelEntityItem.cpp | 38 +++++++------- libraries/entities/src/ModelEntityItem.h | 14 ++--- libraries/shared/src/SpatiallyNestable.h | 3 ++ 8 files changed, 80 insertions(+), 82 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 95d28f74f3..fe61b0e703 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -307,14 +307,14 @@ bool RenderableModelEntityItem::getAnimationFrame() { } glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform * rotationMat * fbxJoints[index].postTransform); - _absoluteJointTranslationsInObjectFrame[j] = extractTranslation(finalMat); - _absoluteJointTranslationsInObjectFrameSet[j] = true; - _absoluteJointTranslationsInObjectFrameDirty[j] = true; + _localJointTranslations[j] = extractTranslation(finalMat); + _localJointTranslationsSet[j] = true; + _localJointTranslationsDirty[j] = true; - _absoluteJointRotationsInObjectFrame[j] = glmExtractRotation(finalMat); + _localJointRotations[j] = glmExtractRotation(finalMat); - _absoluteJointRotationsInObjectFrameSet[j] = true; - _absoluteJointRotationsInObjectFrameDirty[j] = true; + _localJointRotationsSet[j] = true; + _localJointRotationsDirty[j] = true; } } } @@ -387,18 +387,18 @@ void RenderableModelEntityItem::render(RenderArgs* args) { getAnimationFrame(); // relay any inbound joint changes from scripts/animation/network to the model/rig - for (int index = 0; index < _absoluteJointRotationsInObjectFrame.size(); index++) { - if (_absoluteJointRotationsInObjectFrameDirty[index]) { - glm::quat rotation = _absoluteJointRotationsInObjectFrame[index]; + for (int index = 0; index < _localJointRotations.size(); index++) { + if (_localJointRotationsDirty[index]) { + glm::quat rotation = _localJointRotations[index]; _model->setJointRotation(index, true, rotation, 1.0f); - _absoluteJointRotationsInObjectFrameDirty[index] = false; + _localJointRotationsDirty[index] = false; } } - for (int index = 0; index < _absoluteJointTranslationsInObjectFrame.size(); index++) { - if (_absoluteJointTranslationsInObjectFrameDirty[index]) { - glm::vec3 translation = _absoluteJointTranslationsInObjectFrame[index]; + for (int index = 0; index < _localJointTranslations.size(); index++) { + if (_localJointTranslationsDirty[index]) { + glm::vec3 translation = _localJointTranslations[index]; _model->setJointTranslation(index, true, translation, 1.0f); - _absoluteJointTranslationsInObjectFrameDirty[index] = false; + _localJointTranslationsDirty[index] = false; } } }); @@ -1017,16 +1017,16 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in return glm::vec3(0.0f); } -bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { +bool RenderableModelEntityItem::setLocalJointRotation(int index, const glm::quat& rotation) { bool result = false; _jointDataLock.withWriteLock([&] { _jointRotationsExplicitlySet = true; resizeJointArrays(); - if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() && - _absoluteJointRotationsInObjectFrame[index] != rotation) { - _absoluteJointRotationsInObjectFrame[index] = rotation; - _absoluteJointRotationsInObjectFrameSet[index] = true; - _absoluteJointRotationsInObjectFrameDirty[index] = true; + if (index >= 0 && index < _localJointRotations.size() && + _localJointRotations[index] != rotation) { + _localJointRotations[index] = rotation; + _localJointRotationsSet[index] = true; + _localJointRotationsDirty[index] = true; result = true; _needsJointSimulation = true; } @@ -1034,16 +1034,16 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, return result; } -bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { +bool RenderableModelEntityItem::setLocalJointTranslation(int index, const glm::vec3& translation) { bool result = false; _jointDataLock.withWriteLock([&] { _jointTranslationsExplicitlySet = true; resizeJointArrays(); - if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() && - _absoluteJointTranslationsInObjectFrame[index] != translation) { - _absoluteJointTranslationsInObjectFrame[index] = translation; - _absoluteJointTranslationsInObjectFrameSet[index] = true; - _absoluteJointTranslationsInObjectFrameDirty[index] = true; + if (index >= 0 && index < _localJointTranslations.size() && + _localJointTranslations[index] != translation) { + _localJointTranslations[index] = translation; + _localJointTranslationsSet[index] = true; + _localJointTranslationsDirty[index] = true; result = true; _needsJointSimulation = true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index a52b0b0041..8ae7a5c873 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,8 +71,8 @@ public: // these are in the frame of this object (model space) virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override; - virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override; + virtual bool setLocalJointRotation(int index, const glm::quat& rotation) override; + virtual bool setLocalJointTranslation(int index, const glm::vec3& translation) override; virtual void setJointRotations(const QVector& rotations) override; virtual void setJointRotationsSet(const QVector& rotationsSet) override; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index a751d76b2a..d3c4cbfdfc 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -411,8 +411,9 @@ public: // these are in the frame of this object virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } - virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } - virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } + + virtual bool setLocalJointRotation(int index, const glm::quat& rotation) override { return false; } + virtual bool setLocalJointTranslation(int index, const glm::vec3& translation) override { return false; } virtual int getJointIndex(const QString& name) const { return -1; } virtual QStringList getJointNames() const { return QStringList(); } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 306477b10c..8a2bb5731a 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1110,12 +1110,11 @@ glm::quat EntityScriptingInterface::getAbsoluteJointRotationInObjectFrame(const } } -bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, - int jointIndex, glm::vec3 translation) { +bool EntityScriptingInterface::setLocalJointTranslation(const QUuid& entityID, int jointIndex, glm::vec3 translation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); - bool result = modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); + bool result = modelEntity->setLocalJointTranslation(jointIndex, translation); if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { @@ -1132,12 +1131,11 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QU return false; } -bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, - int jointIndex, glm::quat rotation) { +bool EntityScriptingInterface::setLocalJointRotation(const QUuid& entityID, int jointIndex, glm::quat rotation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); - bool result = modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); + bool result = modelEntity->setLocalJointRotation(jointIndex, rotation); if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { @@ -1156,15 +1154,14 @@ bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid -bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUuid& entityID, - const QVector& rotations) { +bool EntityScriptingInterface::setLocalJointRotations(const QUuid& entityID, const QVector& rotations) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); bool result = false; for (int index = 0; index < rotations.size(); index++) { - result |= modelEntity->setAbsoluteJointRotationInObjectFrame(index, rotations[index]); + result |= modelEntity->setLocalJointRotation(index, rotations[index]); } if (result) { EntityItemProperties properties; @@ -1184,15 +1181,14 @@ bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUui } -bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const QUuid& entityID, - const QVector& translations) { +bool EntityScriptingInterface::setLocalJointTranslations(const QUuid& entityID, const QVector& translations) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); bool result = false; for (int index = 0; index < translations.size(); index++) { - result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); + result |= modelEntity->setLocalJointTranslation(index, translations[index]); } if (result) { EntityItemProperties properties; @@ -1211,12 +1207,12 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const Q return false; } -bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, - const QVector& rotations, - const QVector& translations) { +bool EntityScriptingInterface::setLocalJointsData(const QUuid& entityID, + const QVector& rotations, + const QVector& translations) { // for a model with 80 joints, sending both these in one edit packet causes the packet to be too large. - return setAbsoluteJointRotationsInObjectFrame(entityID, rotations) || - setAbsoluteJointTranslationsInObjectFrame(entityID, translations); + return setLocalJointRotations(entityID, rotations) || + setLocalJointTranslations(entityID, translations); } int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString& name) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 3a24ff59fd..eaa328e74d 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -184,15 +184,13 @@ public slots: Q_INVOKABLE glm::vec3 getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex); Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); - Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); - Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); - Q_INVOKABLE bool setAbsoluteJointRotationsInObjectFrame(const QUuid& entityID, - const QVector& rotations); - Q_INVOKABLE bool setAbsoluteJointTranslationsInObjectFrame(const QUuid& entityID, - const QVector& translations); - Q_INVOKABLE bool setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, - const QVector& rotations, - const QVector& translations); + Q_INVOKABLE bool setLocalJointTranslation(const QUuid& entityID, int jointIndex, glm::vec3 translation); + Q_INVOKABLE bool setLocalJointRotation(const QUuid& entityID, int jointIndex, glm::quat rotation); + Q_INVOKABLE bool setLocalJointRotations(const QUuid& entityID, const QVector& rotations); + Q_INVOKABLE bool setLocalJointTranslations(const QUuid& entityID, const QVector& translations); + Q_INVOKABLE bool setLocalJointsData(const QUuid& entityID, + const QVector& rotations, + const QVector& translations); Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name); Q_INVOKABLE QStringList getJointNames(const QUuid& entityID); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b098247524..df568817ac 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -389,13 +389,13 @@ bool ModelEntityItem::shouldBePhysical() const { } void ModelEntityItem::resizeJointArrays(int newSize) { - if (newSize >= 0 && newSize > _absoluteJointRotationsInObjectFrame.size()) { - _absoluteJointRotationsInObjectFrame.resize(newSize); - _absoluteJointRotationsInObjectFrameSet.resize(newSize); - _absoluteJointRotationsInObjectFrameDirty.resize(newSize); - _absoluteJointTranslationsInObjectFrame.resize(newSize); - _absoluteJointTranslationsInObjectFrameSet.resize(newSize); - _absoluteJointTranslationsInObjectFrameDirty.resize(newSize); + if (newSize >= 0 && newSize > _localJointRotations.size()) { + _localJointRotations.resize(newSize); + _localJointRotationsSet.resize(newSize); + _localJointRotationsDirty.resize(newSize); + _localJointTranslations.resize(newSize); + _localJointTranslationsSet.resize(newSize); + _localJointTranslationsDirty.resize(newSize); } } @@ -404,9 +404,9 @@ void ModelEntityItem::setJointRotations(const QVector& rotations) { _jointRotationsExplicitlySet = rotations.size() > 0; resizeJointArrays(rotations.size()); for (int index = 0; index < rotations.size(); index++) { - if (_absoluteJointRotationsInObjectFrameSet[index]) { - _absoluteJointRotationsInObjectFrame[index] = rotations[index]; - _absoluteJointRotationsInObjectFrameDirty[index] = true; + if (_localJointRotationsSet[index]) { + _localJointRotations[index] = rotations[index]; + _localJointRotationsDirty[index] = true; } } }); @@ -417,7 +417,7 @@ void ModelEntityItem::setJointRotationsSet(const QVector& rotationsSet) { _jointRotationsExplicitlySet = rotationsSet.size() > 0; resizeJointArrays(rotationsSet.size()); for (int index = 0; index < rotationsSet.size(); index++) { - _absoluteJointRotationsInObjectFrameSet[index] = rotationsSet[index]; + _localJointRotationsSet[index] = rotationsSet[index]; } }); } @@ -427,9 +427,9 @@ void ModelEntityItem::setJointTranslations(const QVector& translation _jointTranslationsExplicitlySet = translations.size() > 0; resizeJointArrays(translations.size()); for (int index = 0; index < translations.size(); index++) { - if (_absoluteJointTranslationsInObjectFrameSet[index]) { - _absoluteJointTranslationsInObjectFrame[index] = translations[index]; - _absoluteJointTranslationsInObjectFrameSet[index] = true; + if (_localJointTranslationsSet[index]) { + _localJointTranslations[index] = translations[index]; + _localJointTranslationsSet[index] = true; } } }); @@ -440,7 +440,7 @@ void ModelEntityItem::setJointTranslationsSet(const QVector& translationsS _jointTranslationsExplicitlySet = translationsSet.size() > 0; resizeJointArrays(translationsSet.size()); for (int index = 0; index < translationsSet.size(); index++) { - _absoluteJointTranslationsInObjectFrameSet[index] = translationsSet[index]; + _localJointTranslationsSet[index] = translationsSet[index]; } }); } @@ -449,7 +449,7 @@ QVector ModelEntityItem::getJointRotations() const { QVector result; _jointDataLock.withReadLock([&] { if (_jointRotationsExplicitlySet) { - result = _absoluteJointRotationsInObjectFrame; + result = _localJointRotations; } }); return result; @@ -459,7 +459,7 @@ QVector ModelEntityItem::getJointRotationsSet() const { QVector result; _jointDataLock.withReadLock([&] { if (_jointRotationsExplicitlySet) { - result = _absoluteJointRotationsInObjectFrameSet; + result = _localJointRotationsSet; } }); @@ -470,7 +470,7 @@ QVector ModelEntityItem::getJointTranslations() const { QVector result; _jointDataLock.withReadLock([&] { if (_jointTranslationsExplicitlySet) { - result = _absoluteJointTranslationsInObjectFrame; + result = _localJointTranslations; } }); return result; @@ -480,7 +480,7 @@ QVector ModelEntityItem::getJointTranslationsSet() const { QVector result; _jointDataLock.withReadLock([&] { if (_jointTranslationsExplicitlySet) { - result = _absoluteJointTranslationsInObjectFrameSet; + result = _localJointTranslationsSet; } }); return result; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 6f2a0e1b31..c9f278bb3b 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -143,14 +143,14 @@ protected: ReadWriteLockable _jointDataLock; bool _jointRotationsExplicitlySet { false }; // were the joints set as a property or just side effect of animations - QVector _absoluteJointRotationsInObjectFrame; - QVector _absoluteJointRotationsInObjectFrameSet; // ever set? - QVector _absoluteJointRotationsInObjectFrameDirty; // needs a relay to model/rig? - + QVector _localJointRotations; + QVector _localJointRotationsSet; // ever set? + QVector _localJointRotationsDirty; // needs a relay to model/rig? + bool _jointTranslationsExplicitlySet { false }; // were the joints set as a property or just side effect of animations - QVector _absoluteJointTranslationsInObjectFrame; - QVector _absoluteJointTranslationsInObjectFrameSet; // ever set? - QVector _absoluteJointTranslationsInObjectFrameDirty; // needs a relay to model/rig? + QVector _localJointTranslations; + QVector _localJointTranslationsSet; // ever set? + QVector _localJointTranslationsDirty; // needs a relay to model/rig? int _lastKnownCurrentFrame; virtual void resizeJointArrays(int newSize = -1); diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 5605cc0031..ece10617cb 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -144,6 +144,9 @@ public: virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { return false; } virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) {return false; } + virtual bool setLocalJointRotation(int index, const glm::quat& rotation) { return false; } + virtual bool setLocalJointTranslation(int index, const glm::vec3& translation) { return false; } + SpatiallyNestablePointer getThisPointer() const; void markAncestorMissing(bool value) { _missingAncestor = value; } From 339d6a55cfec28d12dfd1fbbd75fb298455e2ba2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 3 Nov 2016 10:06:07 -0700 Subject: [PATCH 06/34] getLocalJointRotation getLocalJointTranslation, started on getLocalJointTranslation getLocalJointRotation --- .../src/RenderableModelEntityItem.cpp | 34 ++++++++++ .../src/RenderableModelEntityItem.h | 6 ++ .../entities/src/EntityScriptingInterface.cpp | 62 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 6 ++ libraries/entities/src/ModelEntityItem.h | 4 +- libraries/shared/src/SpatiallyNestable.h | 2 + 6 files changed, 112 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index fe61b0e703..976819a8f5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1017,6 +1017,40 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in return glm::vec3(0.0f); } +bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { + // TODO -- write this + assert(false); + abort(); + return false; +} + +bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { + // TODO -- write this + assert(false); + abort(); + return false; +} + +glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const { + if (_model) { + glm::quat result; + if (_model->getJointRotation(index, result)) { + return result; + } + } + return glm::quat(); +} + +glm::vec3 RenderableModelEntityItem::getLocalJointTranslation(int index) const { + if (_model) { + glm::vec3 result; + if (_model->getJointTranslation(index, result)) { + return result; + } + } + return glm::vec3(); +} + bool RenderableModelEntityItem::setLocalJointRotation(int index, const glm::quat& rotation) { bool result = false; _jointDataLock.withWriteLock([&] { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 8ae7a5c873..93d48c6085 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,6 +71,12 @@ public: // these are in the frame of this object (model space) virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override; + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override; + + + virtual glm::quat getLocalJointRotation(int index) const override; + virtual glm::vec3 getLocalJointTranslation(int index) const override; virtual bool setLocalJointRotation(int index, const glm::quat& rotation) override; virtual bool setLocalJointTranslation(int index, const glm::vec3& translation) override; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8a2bb5731a..ee4db74c64 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1110,6 +1110,68 @@ glm::quat EntityScriptingInterface::getAbsoluteJointRotationInObjectFrame(const } } +bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, + int jointIndex, glm::vec3 translation) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); + auto modelEntity = std::dynamic_pointer_cast(entity); + bool result = modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); + if (result) { + EntityItemProperties properties; + _entityTree->withWriteLock([&] { + properties = entity->getProperties(); + entity->setLastBroadcast(now); + }); + + properties.setJointTranslationsDirty(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } + } + return false; +} + +bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, + int jointIndex, glm::quat rotation) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); + auto modelEntity = std::dynamic_pointer_cast(entity); + bool result = modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); + if (result) { + EntityItemProperties properties; + _entityTree->withWriteLock([&] { + properties = entity->getProperties(); + entity->setLastBroadcast(now); + }); + + properties.setJointRotationsDirty(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } + } + return false; +} + +glm::vec3 EntityScriptingInterface::getLocalJointTranslation(const QUuid& entityID, int jointIndex) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto modelEntity = std::dynamic_pointer_cast(entity); + return modelEntity->getLocalJointTranslation(jointIndex); + } else { + return glm::vec3(0.0f); + } +} + +glm::quat EntityScriptingInterface::getLocalJointRotation(const QUuid& entityID, int jointIndex) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto modelEntity = std::dynamic_pointer_cast(entity); + return modelEntity->getLocalJointRotation(jointIndex); + } else { + return glm::quat(); + } +} + bool EntityScriptingInterface::setLocalJointTranslation(const QUuid& entityID, int jointIndex, glm::vec3 translation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index eaa328e74d..3d46113611 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -184,8 +184,14 @@ public slots: Q_INVOKABLE glm::vec3 getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex); Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); + Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); + Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); + + Q_INVOKABLE glm::vec3 getLocalJointTranslation(const QUuid& entityID, int jointIndex); + Q_INVOKABLE glm::quat getLocalJointRotation(const QUuid& entityID, int jointIndex); Q_INVOKABLE bool setLocalJointTranslation(const QUuid& entityID, int jointIndex, glm::vec3 translation); Q_INVOKABLE bool setLocalJointRotation(const QUuid& entityID, int jointIndex, glm::quat rotation); + Q_INVOKABLE bool setLocalJointRotations(const QUuid& entityID, const QVector& rotations); Q_INVOKABLE bool setLocalJointTranslations(const QUuid& entityID, const QVector& translations); Q_INVOKABLE bool setLocalJointsData(const QUuid& entityID, diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index c9f278bb3b..797474f784 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -117,8 +117,8 @@ public: virtual bool shouldBePhysical() const override; - virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); } - virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); } + // virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); } + // virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); } virtual void setJointRotations(const QVector& rotations); virtual void setJointRotationsSet(const QVector& rotationsSet); diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index ece10617cb..f58e2c906c 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -144,6 +144,8 @@ public: virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { return false; } virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) {return false; } + virtual glm::quat getLocalJointRotation(int index) const {return glm::quat(); } + virtual glm::vec3 getLocalJointTranslation(int index) const {return glm::vec3(); } virtual bool setLocalJointRotation(int index, const glm::quat& rotation) { return false; } virtual bool setLocalJointTranslation(int index, const glm::vec3& translation) { return false; } From e41fa94958279ef74098afe78ffe5e8197f5e13c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 4 Nov 2016 11:42:31 -0700 Subject: [PATCH 07/34] implement RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame and RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame --- libraries/animation/src/Rig.cpp | 17 +++++ libraries/animation/src/Rig.h | 3 + .../src/RenderableModelEntityItem.cpp | 62 ++++++++++++++++--- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 877c6c3e91..722fcc92aa 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -308,6 +308,13 @@ void Rig::clearIKJointLimitHistory() { } } +int Rig::getJointParentIndex(int childIndex) { + if (_animSkeleton && isIndexValid(childIndex)) { + return _animSkeleton->getParentIndex(childIndex); + } + return -1; +} + void Rig::setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority) { if (isIndexValid(index)) { if (valid) { @@ -414,6 +421,16 @@ bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& trans } } +bool Rig::getAbsoluteJointPoseInRigFrame(int jointIndex, AnimPose& returnPose) const { + QReadLocker readLock(&_externalPoseSetLock); + if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { + returnPose = _externalPoseSet._absolutePoses[jointIndex]; + return true; + } else { + return false; + } +} + bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const { // AJT: TODO: used by attachments ASSERT(false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 86b8dadd85..cc4992cb31 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -105,6 +105,8 @@ public: void clearIKJointLimitHistory(); + int getJointParentIndex(int childIndex); + // geometry space void setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority); @@ -133,6 +135,7 @@ public: // rig space (thread-safe) bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const; bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const; + bool getAbsoluteJointPoseInRigFrame(int jointIndex, AnimPose& returnPose) const; // legacy bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a6b3cb1d92..e58212e676 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1028,17 +1028,63 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { - // TODO -- write this - assert(false); - abort(); - return false; + if (!_model) { + return false; + } + RigPointer rig = _model->getRig(); + if (!rig) { + return false; + } + + int jointParentIndex = rig->getJointParentIndex(index); + + bool success; + AnimPose jointParentPose; + success = rig->getAbsoluteJointPoseInRigFrame(jointParentIndex, jointParentPose); + if (!success) { + return false; + } + AnimPose jointParentInversePose = jointParentPose.inverse(); + + AnimPose jointAbsolutePose; // in rig frame + success = rig->getAbsoluteJointPoseInRigFrame(index, jointAbsolutePose); + if (!success) { + return false; + } + jointAbsolutePose.rot = rotation; + + AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose; + return setLocalJointRotation(index, jointRelativePose.rot); } bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { - // TODO -- write this - assert(false); - abort(); - return false; + if (!_model) { + return false; + } + RigPointer rig = _model->getRig(); + if (!rig) { + return false; + } + + int jointParentIndex = rig->getJointParentIndex(index); + + bool success; + AnimPose jointParentPose; + success = rig->getAbsoluteJointPoseInRigFrame(jointParentIndex, jointParentPose); + if (!success) { + return false; + } + AnimPose jointParentInversePose = jointParentPose.inverse(); + + AnimPose jointAbsolutePose; // in rig frame + success = rig->getAbsoluteJointPoseInRigFrame(index, jointAbsolutePose); + if (!success) { + return false; + } + jointAbsolutePose.trans = translation; + + AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose; + return setLocalJointRotation(index, jointRelativePose.trans); } glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const { From 689fdfb35ff1242c6891bdc0b387b0755519c024 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 4 Nov 2016 11:44:42 -0700 Subject: [PATCH 08/34] implement RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame and RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e58212e676..dc5b6cd8d3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1037,6 +1037,9 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, } int jointParentIndex = rig->getJointParentIndex(index); + if (jointParentIndex == -1) { + return setLocalJointRotation(index, rotation); + } bool success; AnimPose jointParentPose; @@ -1067,6 +1070,9 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind } int jointParentIndex = rig->getJointParentIndex(index); + if (jointParentIndex == -1) { + return setLocalJointTranslation(index, translation); + } bool success; AnimPose jointParentPose; @@ -1084,7 +1090,7 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind jointAbsolutePose.trans = translation; AnimPose jointRelativePose = jointParentInversePose * jointAbsolutePose; - return setLocalJointRotation(index, jointRelativePose.trans); + return setLocalJointTranslation(index, jointRelativePose.trans); } glm::quat RenderableModelEntityItem::getLocalJointRotation(int index) const { From 51f6b5af78222d8d2632da7f4fb00370a09353ea Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 5 Nov 2016 10:35:21 -0700 Subject: [PATCH 09/34] code review --- libraries/animation/src/Rig.cpp | 2 +- libraries/animation/src/Rig.h | 2 +- libraries/entities/src/ModelEntityItem.h | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 722fcc92aa..45790524d1 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -308,7 +308,7 @@ void Rig::clearIKJointLimitHistory() { } } -int Rig::getJointParentIndex(int childIndex) { +int Rig::getJointParentIndex(int childIndex) const { if (_animSkeleton && isIndexValid(childIndex)) { return _animSkeleton->getParentIndex(childIndex); } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index cc4992cb31..151a7ae8e9 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -105,7 +105,7 @@ public: void clearIKJointLimitHistory(); - int getJointParentIndex(int childIndex); + int getJointParentIndex(int childIndex) const; // geometry space void setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 797474f784..58766906bb 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -117,9 +117,6 @@ public: virtual bool shouldBePhysical() const override; - // virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); } - // virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); } - virtual void setJointRotations(const QVector& rotations); virtual void setJointRotationsSet(const QVector& rotationsSet); virtual void setJointTranslations(const QVector& translations); From e22c36b4b7800eae88cf7b081be0d673f1931a7c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 7 Nov 2016 17:16:24 +0000 Subject: [PATCH 10/34] fixed menu pop up delay --- interface/resources/controllers/xbox.json | 30 +++++++++---------- .../controllers/handControllerPointer.js | 18 +++++------ 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/interface/resources/controllers/xbox.json b/interface/resources/controllers/xbox.json index b0e97b849f..36065b87a1 100644 --- a/interface/resources/controllers/xbox.json +++ b/interface/resources/controllers/xbox.json @@ -4,12 +4,12 @@ { "from": "GamePad.LY", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateZ" }, { "from": "GamePad.LX", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Actions.TranslateX" }, - { "from": "GamePad.LT", "to": "Standard.LTClick", + { "from": "GamePad.LT", "to": "Standard.LTClick", "peek": true, "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] }, - { "from": "GamePad.LT", "to": "Standard.LT" }, - { "from": "GamePad.LB", "to": "Standard.LB" }, + { "from": "GamePad.LT", "to": "Standard.LT" }, + { "from": "GamePad.LB", "to": "Standard.LB" }, { "from": "GamePad.LS", "to": "Standard.LS" }, @@ -27,34 +27,34 @@ { "from": "GamePad.RX", "to": "Actions.Yaw" }, - { "from": "GamePad.RY", - "to": "Actions.VERTICAL_UP", - "filters": + { "from": "GamePad.RY", + "to": "Actions.VERTICAL_UP", + "filters": [ { "type": "deadZone", "min": 0.95 }, "invert" ] - }, + }, - { "from": "GamePad.RT", "to": "Standard.RTClick", + { "from": "GamePad.RT", "to": "Standard.RTClick", "peek": true, "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] }, - { "from": "GamePad.RT", "to": "Standard.RT" }, - { "from": "GamePad.RB", "to": "Standard.RB" }, + { "from": "GamePad.RT", "to": "Standard.RT" }, + { "from": "GamePad.RB", "to": "Standard.RB" }, { "from": "GamePad.RS", "to": "Standard.RS" }, { "from": "GamePad.Start", "to": "Actions.CycleCamera" }, - { "from": "GamePad.Back", "to": "Actions.ContextMenu" }, + { "from": "GamePad.Back", "to": "Standard.Start" }, { "from": "GamePad.DU", "to": "Standard.DU" }, - { "from": "GamePad.DD", "to": "Standard.DD" }, + { "from": "GamePad.DD", "to": "Standard.DD" }, { "from": "GamePad.DL", "to": "Standard.DL" }, - { "from": "GamePad.DR", "to": "Standard.DR" }, + { "from": "GamePad.DR", "to": "Standard.DR" }, { "from": [ "GamePad.Y" ], "to": "Standard.RightPrimaryThumb", "peek": true }, - { "from": "GamePad.A", "to": "Standard.A" }, - { "from": "GamePad.B", "to": "Standard.B" }, + { "from": "GamePad.A", "to": "Standard.A" }, + { "from": "GamePad.B", "to": "Standard.B" }, { "from": "GamePad.X", "to": "Standard.X" }, { "from": "GamePad.Y", "to": "Standard.Y" } ] diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 82344426cb..ce9b8e403f 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -203,6 +203,7 @@ function overlayFromWorldPoint(point) { return { x: horizontalPixels, y: verticalPixels }; } +var gamePad = Controller.findDevice("GamePad"); function activeHudPoint2dGamePad() { if (!HMD.active) { return; @@ -227,13 +228,10 @@ function activeHudPoint2dGamePad() { return hudPoint2d; } -var gamePad = Controller.findDevice("GamePad"); + function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey. var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye) if (!controllerPose.valid) { - if (gamePad) { - return activeHudPoint2dGamePad(); - } return; // Controller is cradled. } var controllerPosition = controllerPose.position; @@ -448,12 +446,12 @@ clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (cl } wantsMenu = clicked; }); -clickMapping.from(Controller.Hardware.GamePad.Back).peek().to(function () { - // Wait a tick an allow the reticle to be correctly set to the players look at position before invoking - // ContextMenu action - Script.setTimeout(function () { - activeHudPoint2dGamePad(); - }, 0); +clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) { + if (clicked) { + activeHudPoint2dGamePad(); + } + + wantsMenu = clicked; }); clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () { // Allow the reticle depth to be set correctly: From 86a569651c501da4f4f3e7d70e809b8023b67135 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 7 Nov 2016 14:45:26 -0800 Subject: [PATCH 11/34] Add more precuation when extracting the opengl version in the openGLVersionChecker to avoid crashing --- libraries/gl/src/gl/OpenGLVersionChecker.cpp | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 6473b6bf2b..9a41ebfdca 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -75,15 +75,26 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) { // - major_number.minor_number // - major_number.minor_number.release_number // Reference: https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGetString.xml - const QString version { "version" }; - QString glVersion = glData[version].toString(); - QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); - int majorNumber = versionParts[0].toInt(); - int minorNumber = versionParts[1].toInt(); + int minimumMajorNumber = (MINIMUM_GL_VERSION >> 16); int minimumMinorNumber = (MINIMUM_GL_VERSION & 0xFF); - valid = (majorNumber > minimumMajorNumber - || (majorNumber == minimumMajorNumber && minorNumber >= minimumMinorNumber)); + int majorNumber = 0; + int minorNumber = 0; + const QString version { "version" }; + if (version.contains(version)) { + QString glVersion = glData[version].toString(); + QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); + if (versionParts.size() >= 2) { + majorNumber = versionParts[0].toInt(); + minorNumber = versionParts[1].toInt(); + valid = (majorNumber > minimumMajorNumber + || (majorNumber == minimumMajorNumber && minorNumber >= minimumMinorNumber)); + } else { + valid = false; + } + } else { + valid = false; + } // Prompt user if below minimum if (!valid) { From 284b458148dd9e0a1f32700bab7ee211d16301f6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Nov 2016 09:46:47 -0800 Subject: [PATCH 12/34] Increase margin at bottom of users.js --- scripts/system/users.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/system/users.js b/scripts/system/users.js index 1e4cf042f3..68501721b3 100644 --- a/scripts/system/users.js +++ b/scripts/system/users.js @@ -228,7 +228,7 @@ var usersWindow = (function () { var WINDOW_WIDTH = 260, WINDOW_MARGIN = 12, - WINDOW_BASE_MARGIN = 6, // A little less is needed in order look correct + WINDOW_BASE_MARGIN = 24, // A little less is needed in order look correct WINDOW_FONT = { size: 12 }, @@ -254,10 +254,11 @@ var usersWindow = (function () { windowHeading, // Window border is similar to that of edit.js. - WINDOW_BORDER_WIDTH = WINDOW_WIDTH + 2 * WINDOW_BASE_MARGIN, - WINDOW_BORDER_TOP_MARGIN = 2 * WINDOW_BASE_MARGIN, - WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_BASE_MARGIN, - WINDOW_BORDER_LEFT_MARGIN = WINDOW_BASE_MARGIN, + WINDOW_MARGIN_HALF = WINDOW_MARGIN / 2, + WINDOW_BORDER_WIDTH = WINDOW_WIDTH + 2 * WINDOW_MARGIN_HALF, + WINDOW_BORDER_TOP_MARGIN = 2 * WINDOW_MARGIN_HALF, + WINDOW_BORDER_BOTTOM_MARGIN = WINDOW_MARGIN_HALF, + WINDOW_BORDER_LEFT_MARGIN = WINDOW_MARGIN_HALF, WINDOW_BORDER_RADIUS = 4, WINDOW_BORDER_COLOR = { red: 255, green: 255, blue: 255 }, WINDOW_BORDER_ALPHA = 0.5, From 5dab2ac2a7b492b46d741f818bfdb3ccd4aaf412 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Nov 2016 09:47:09 -0800 Subject: [PATCH 13/34] Add margin to left and right side of users.js --- scripts/system/users.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/system/users.js b/scripts/system/users.js index 68501721b3..d03a5bb846 100644 --- a/scripts/system/users.js +++ b/scripts/system/users.js @@ -253,6 +253,11 @@ var usersWindow = (function () { windowPane, windowHeading, + // Margin on the left and right side of the window to keep + // it from getting too close to the edge of the screen which + // is unclickable. + WINDOW_MARGIN_X = 20, + // Window border is similar to that of edit.js. WINDOW_MARGIN_HALF = WINDOW_MARGIN / 2, WINDOW_BORDER_WIDTH = WINDOW_WIDTH + 2 * WINDOW_MARGIN_HALF, @@ -446,7 +451,7 @@ var usersWindow = (function () { } function saturateWindowPosition() { - windowPosition.x = Math.max(0, Math.min(viewport.x - WINDOW_WIDTH, windowPosition.x)); + windowPosition.x = Math.max(WINDOW_MARGIN_X, Math.min(viewport.x - WINDOW_WIDTH - WINDOW_MARGIN_X, windowPosition.x)); windowPosition.y = Math.max(windowMinimumHeight, Math.min(viewport.y, windowPosition.y)); } From a4e75b4dcf334bcbf9980d187a2cfabbaa730970 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 8 Nov 2016 14:51:48 -0800 Subject: [PATCH 14/34] FIx an obvious mistake, good catch MR Zappoman --- libraries/gl/src/gl/OpenGLVersionChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 9a41ebfdca..24b61e5128 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -81,7 +81,7 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) { int majorNumber = 0; int minorNumber = 0; const QString version { "version" }; - if (version.contains(version)) { + if (glData.contains(version)) { QString glVersion = glData[version].toString(); QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); if (versionParts.size() >= 2) { From b7381c30cb605ed7e23aa3f7c8d0d773905c5f25 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Nov 2016 10:38:44 -0800 Subject: [PATCH 15/34] Including the fix for the bad Major Version number from David K --- libraries/gl/src/gl/OpenGLVersionChecker.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 24b61e5128..428bf86c6f 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -21,6 +21,7 @@ #include "GLHelpers.h" +// Minimum gl version required is 4.1 #define MINIMUM_GL_VERSION 0x0401 OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : @@ -76,7 +77,7 @@ QJsonObject OpenGLVersionChecker::checkVersion(bool& valid, bool& override) { // - major_number.minor_number.release_number // Reference: https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGetString.xml - int minimumMajorNumber = (MINIMUM_GL_VERSION >> 16); + int minimumMajorNumber = (MINIMUM_GL_VERSION >> 8) & 0xFF; int minimumMinorNumber = (MINIMUM_GL_VERSION & 0xFF); int majorNumber = 0; int minorNumber = 0; From 941e5a57b18c532b683ccd66d729727688d63290 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Nov 2016 17:25:46 -0800 Subject: [PATCH 16/34] trying a test with 4.4 as the minimum gl context to be able to break on Intel integrated --- libraries/gl/src/gl/Context.cpp | 6 ++++-- libraries/gl/src/gl/OpenGLVersionChecker.cpp | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index ec1c284e99..fe48968981 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -217,8 +217,10 @@ void Context::create() { glewInit(); if (glewIsSupported("GL_VERSION_4_5")) { _version = 0x0405; - } else if (glewIsSupported("GL_VERSION_4_3")) { - _version = 0x0403; + // } else if (glewIsSupported("GL_VERSION_4_3")) { + } else if (glewIsSupported("GL_VERSION_4_4")) { +///_version = 0x0403; + _version = 0x0404; } glGetError(); wglMakeCurrent(0, 0); diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 428bf86c6f..273251581a 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -22,7 +22,8 @@ #include "GLHelpers.h" // Minimum gl version required is 4.1 -#define MINIMUM_GL_VERSION 0x0401 +//#define MINIMUM_GL_VERSION 0x0401 +#define MINIMUM_GL_VERSION 0x0404 OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : QApplication(argc, argv) From c01b39b54bdd0fe83fdfb8690a640ae98f1d2cef Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Nov 2016 18:16:51 -0800 Subject: [PATCH 17/34] And test that again --- libraries/gl/src/gl/Context.cpp | 6 +++--- libraries/gl/src/gl/OpenGLVersionChecker.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index fe48968981..221223d584 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -215,10 +215,10 @@ void Context::create() { } glewExperimental = true; glewInit(); - if (glewIsSupported("GL_VERSION_4_5")) { - _version = 0x0405; + // if (glewIsSupported("GL_VERSION_4_5")) { + // _version = 0x0405; // } else if (glewIsSupported("GL_VERSION_4_3")) { - } else if (glewIsSupported("GL_VERSION_4_4")) { + /* } else*/ if (glewIsSupported("GL_VERSION_4_8")) { ///_version = 0x0403; _version = 0x0404; } diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 273251581a..322a7bc484 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -23,7 +23,7 @@ // Minimum gl version required is 4.1 //#define MINIMUM_GL_VERSION 0x0401 -#define MINIMUM_GL_VERSION 0x0404 +#define MINIMUM_GL_VERSION 0x0408 OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : QApplication(argc, argv) From 0ab4a781f59513f598de3e4eaafb38a5a1e1c412 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Nov 2016 18:25:37 -0800 Subject: [PATCH 18/34] Back to the correct code --- libraries/gl/src/gl/Context.cpp | 10 ++++------ libraries/gl/src/gl/OpenGLVersionChecker.cpp | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/libraries/gl/src/gl/Context.cpp b/libraries/gl/src/gl/Context.cpp index 221223d584..ec1c284e99 100644 --- a/libraries/gl/src/gl/Context.cpp +++ b/libraries/gl/src/gl/Context.cpp @@ -215,12 +215,10 @@ void Context::create() { } glewExperimental = true; glewInit(); - // if (glewIsSupported("GL_VERSION_4_5")) { - // _version = 0x0405; - // } else if (glewIsSupported("GL_VERSION_4_3")) { - /* } else*/ if (glewIsSupported("GL_VERSION_4_8")) { -///_version = 0x0403; - _version = 0x0404; + if (glewIsSupported("GL_VERSION_4_5")) { + _version = 0x0405; + } else if (glewIsSupported("GL_VERSION_4_3")) { + _version = 0x0403; } glGetError(); wglMakeCurrent(0, 0); diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index 322a7bc484..428bf86c6f 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -22,8 +22,7 @@ #include "GLHelpers.h" // Minimum gl version required is 4.1 -//#define MINIMUM_GL_VERSION 0x0401 -#define MINIMUM_GL_VERSION 0x0408 +#define MINIMUM_GL_VERSION 0x0401 OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : QApplication(argc, argv) From db98a742b60f5075ec848c206a4e4dc00ae7b26b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 9 Nov 2016 12:22:57 -0800 Subject: [PATCH 19/34] Remove incremental transfers --- interface/src/Menu.cpp | 9 --- interface/src/Menu.h | 1 - libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 8 ++- .../src/gpu/gl45/GL45BackendTexture.cpp | 67 +++++++++++-------- libraries/gpu/src/gpu/Texture.cpp | 23 +------ libraries/gpu/src/gpu/Texture.h | 7 +- 6 files changed, 51 insertions(+), 64 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6207ecdb3c..dfa1a2f8b9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -396,15 +396,6 @@ Menu::Menu() { }); } - // Developer > Render > Enable Incremental Texture Transfer - { - auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::IncrementalTextureTransfer, 0, gpu::Texture::getEnableIncrementalTextureTransfers()); - connect(action, &QAction::triggered, [&](bool checked) { - qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked; - gpu::Texture::setEnableIncrementalTextureTransfers(checked); - }); - } - #else qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer and Dynamic Texture Management not supported on this platform."; #endif diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 87e0e678f1..e339da4d25 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -112,7 +112,6 @@ namespace MenuOption { const QString FrameTimer = "Show Timer"; const QString FullscreenMirror = "Mirror"; const QString Help = "Help..."; - const QString IncrementalTextureTransfer = "Enable Incremental Texture Transfer"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IndependentMode = "Independent Mode"; const QString ActionMotorControl = "Enable Default Motor Control"; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index 438b1e9454..291888e81b 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -14,6 +14,8 @@ #include "../gl/GLBackend.h" #include "../gl/GLTexture.h" +#define INCREMENTAL_TRANSFER 0 + namespace gpu { namespace gl45 { using namespace gpu::gl; @@ -56,6 +58,7 @@ public: GLint pageDimensionsIndex { 0 }; }; +#if INCREMENTAL_TRANSFER struct TransferState { TransferState(GL45Texture& texture); uvec3 currentPageSize() const; @@ -74,6 +77,10 @@ public: uvec3 mipOffset; const uint8_t* srcPointer { nullptr }; }; + protected: + TransferState _transferState; +#endif + protected: void updateMips() override; void stripToMip(uint16_t newMinMip); @@ -91,7 +98,6 @@ public: void derez(); SparseInfo _sparseInfo; - TransferState _transferState; uint32_t _allocatedPages { 0 }; uint32_t _lastMipAllocatedPages { 0 }; uint16_t _mipOffset { 0 }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index f97364f5c5..fca809186f 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -162,6 +162,8 @@ void GL45Backend::initTextureManagementStage() { } } +#if INCREMENTAL_TRANSFER + using TransferState = GL45Backend::GL45Texture::TransferState; TransferState::TransferState(GL45Texture& texture) : texture(texture) { @@ -246,6 +248,7 @@ void TransferState::populatePage(std::vector& buffer) { uvec3 TransferState::currentPageSize() const { return glm::clamp(mipDimensions - mipOffset, uvec3(1), texture._sparseInfo.pageDimensions); } +#endif GLuint GL45Texture::allocate(const Texture& texture) { GLuint result; @@ -258,11 +261,19 @@ GLuint GL45Backend::getTextureID(const TexturePointer& texture, bool transfer) { } GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& texture, GLuint externalId) - : GLTexture(backend, texture, externalId), _sparseInfo(*this), _transferState(*this) { + : GLTexture(backend, texture, externalId), _sparseInfo(*this) +#if INCREMENTAL_TRANSFER +, _transferState(*this) +#endif +{ } GL45Texture::GL45Texture(const std::weak_ptr& backend, const Texture& texture, bool transferrable) - : GLTexture(backend, texture, allocate(texture), transferrable), _sparseInfo(*this), _transferState(*this) { + : GLTexture(backend, texture, allocate(texture), transferrable), _sparseInfo(*this) +#if INCREMENTAL_TRANSFER +, _transferState(*this) +#endif + { auto theBackend = _backend.lock(); if (_transferrable && theBackend && theBackend->isTextureManagementSparseEnabled()) { @@ -375,39 +386,40 @@ void GL45Texture::updateSize() const { void GL45Texture::startTransfer() { Parent::startTransfer(); _sparseInfo.update(); +#if INCREMENTAL_TRANSFER _transferState.updateMip(); +#endif } bool GL45Texture::continueTransfer() { - if (!Texture::getEnableIncrementalTextureTransfers()) { - size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; - for (uint8_t face = 0; face < maxFace; ++face) { - for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { - auto size = _gpuObject.evalMipDimensions(mipLevel); - if (_sparseInfo.sparse && mipLevel <= _sparseInfo.maxSparseLevel) { - glTexturePageCommitmentEXT(_id, mipLevel, 0, 0, face, size.x, size.y, 1, GL_TRUE); - _allocatedPages += _sparseInfo.getPageCount(size); - } - if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) { - auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); - GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat()); - if (GL_TEXTURE_2D == _target) { - glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); - } else if (GL_TEXTURE_CUBE_MAP == _target) { - // DSA ARB does not work on AMD, so use EXT - // glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData()); - auto target = CUBE_FACE_LAYOUT[face]; - glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); - } else { - Q_ASSERT(false); - } - (void)CHECK_GL_ERROR(); +#if !INCREMENTAL_TRANSFER + size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; + for (uint8_t face = 0; face < maxFace; ++face) { + for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { + auto size = _gpuObject.evalMipDimensions(mipLevel); + if (_sparseInfo.sparse && mipLevel <= _sparseInfo.maxSparseLevel) { + glTexturePageCommitmentEXT(_id, mipLevel, 0, 0, face, size.x, size.y, 1, GL_TRUE); + _allocatedPages += _sparseInfo.getPageCount(size); + } + if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) { + auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); + GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat()); + if (GL_TEXTURE_2D == _target) { + glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else if (GL_TEXTURE_CUBE_MAP == _target) { + // DSA ARB does not work on AMD, so use EXT + // glTextureSubImage3D(_id, mipLevel, 0, 0, face, size.x, size.y, 1, texelFormat.format, texelFormat.type, mip->readData()); + auto target = CUBE_FACE_LAYOUT[face]; + glTextureSubImage2DEXT(_id, target, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); + } else { + Q_ASSERT(false); } + (void)CHECK_GL_ERROR(); } } - return false; } - + return false; +#else static std::vector buffer; if (buffer.empty()) { buffer.resize(DEFAULT_PAGE_BUFFER_SIZE); @@ -458,6 +470,7 @@ bool GL45Texture::continueTransfer() { _lastMipAllocatedPages = _allocatedPages; } return result; +#endif } void GL45Texture::finishTransfer() { diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 33786155db..45aff54b8f 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -35,18 +35,15 @@ std::atomic Texture::_allowedCPUMemoryUsage { 0 }; #define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 -bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); -bool recommendedSparseTextures = recommendedIncrementalTransfers; +bool recommendedSparseTextures = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); -std::atomic Texture::_enableSparseTextures { recommendedIncrementalTransfers }; -std::atomic Texture::_enableIncrementalTextureTransfers { recommendedSparseTextures }; +std::atomic Texture::_enableSparseTextures { recommendedSparseTextures }; struct ReportTextureState { ReportTextureState() { qDebug() << "[TEXTURE TRANSFER SUPPORT]" << "\n\tidealThreadCount:" << QThread::idealThreadCount() - << "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures - << "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers; + << "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures; } } report; @@ -59,16 +56,6 @@ void Texture::setEnableSparseTextures(bool enabled) { #endif } -void Texture::setEnableIncrementalTextureTransfers(bool enabled) { -#ifdef Q_OS_WIN - qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Incremental Texture Transfer:" << enabled; - _enableIncrementalTextureTransfers = enabled; -#else - qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer not supported on this platform."; -#endif -} - - void Texture::updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize) { if (prevObjectSize == newObjectSize) { return; @@ -84,10 +71,6 @@ bool Texture::getEnableSparseTextures() { return _enableSparseTextures.load(); } -bool Texture::getEnableIncrementalTextureTransfers() { - return _enableIncrementalTextureTransfers.load(); -} - uint32_t Texture::getTextureCPUCount() { return _textureCPUCount.load(); } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 2a93ec3066..856bd4983d 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -143,10 +143,8 @@ class Texture : public Resource { static std::atomic _textureCPUCount; static std::atomic _textureCPUMemoryUsage; static std::atomic _allowedCPUMemoryUsage; - static void updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize); - static std::atomic _enableSparseTextures; - static std::atomic _enableIncrementalTextureTransfers; + static void updateTextureCPUMemoryUsage(Size prevObjectSize, Size newObjectSize); public: static uint32_t getTextureCPUCount(); @@ -162,10 +160,7 @@ public: static void setAllowedGPUMemoryUsage(Size size); static bool getEnableSparseTextures(); - static bool getEnableIncrementalTextureTransfers(); - static void setEnableSparseTextures(bool enabled); - static void setEnableIncrementalTextureTransfers(bool enabled); using ExternalRecycler = std::function; using ExternalIdAndFence = std::pair; From 563322d08d2aeaea69c9ee886876230ace733fa9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 10:02:31 -0800 Subject: [PATCH 20/34] add min and max avatar scale to domain-server settings --- .../resources/describe-settings.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index e6663888b4..6c4ab9fd77 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -866,6 +866,28 @@ } ] }, + { + "name": "avatars", + "label": "Avatars", + "settings": [ + { + "name": "min_avatar_scale", + "type": "double", + "label": "Minimum Avatar Scale (meters)", + "help": "Limits the scale of avatars in your domain", + "placeholder": 0.01, + "default": 0.01 + }, + { + "name": "max_avatar_scale", + "type": "double", + "label": "Maximum Avatar Scale (meters)", + "help": "Limits the scale of avatars in your domain", + "placeholder": 4.0, + "default": 4.0 + } + ] + }, { "name": "audio_env", "label": "Audio Environment", From e2991c366529022c1a5fee098caeaf74db240b50 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 10 Nov 2016 10:35:05 -0800 Subject: [PATCH 21/34] Change minimum cores to 3 to enable OpenVR --- plugins/openvr/src/OpenVrHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 2803ca424e..0c3a2faed6 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -331,7 +331,7 @@ controller::Pose openVrControllerPoseToHandPose(bool isLeftHand, const mat4& mat #define FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME "Minimum specifications for SteamVR not met" #define FAILED_MIN_SPEC_UPDATE_INTERVAL_MS 10 #define FAILED_MIN_SPEC_AUTO_QUIT_INTERVAL_MS (MSECS_PER_SECOND * 30) -#define MIN_CORES_SPEC 5 +#define MIN_CORES_SPEC 3 void showMinSpecWarning() { auto vrSystem = acquireOpenVrSystem(); From 77ede81fc906adb51abe68a9ef77c37a36a60520 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 13:27:13 -0800 Subject: [PATCH 22/34] limit MyAvatar scale to limits from domain settings --- .../src/avatars/ScriptableAvatar.h | 4 +- .../resources/describe-settings.json | 12 +-- interface/src/avatar/MyAvatar.cpp | 78 +++++++++++++++++-- interface/src/avatar/MyAvatar.h | 3 + libraries/avatars/src/AvatarData.cpp | 8 +- libraries/avatars/src/AvatarData.h | 6 ++ 6 files changed, 92 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 56707de471..18d64f4ac5 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -17,7 +17,7 @@ #include #include -class ScriptableAvatar : public AvatarData, public Dependency{ +class ScriptableAvatar : public AvatarData, public Dependency { Q_OBJECT public: @@ -39,4 +39,4 @@ private: std::shared_ptr _animSkeleton; }; -#endif // hifi_ScriptableAvatar_h \ No newline at end of file +#endif // hifi_ScriptableAvatar_h diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 6c4ab9fd77..b5c612881f 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -874,17 +874,17 @@ "name": "min_avatar_scale", "type": "double", "label": "Minimum Avatar Scale (meters)", - "help": "Limits the scale of avatars in your domain", - "placeholder": 0.01, - "default": 0.01 + "help": "Limits the scale of avatars in your domain. Must be at least than 0.005.", + "placeholder": 0.25, + "default": 0.25 }, { "name": "max_avatar_scale", "type": "double", "label": "Maximum Avatar Scale (meters)", - "help": "Limits the scale of avatars in your domain", - "placeholder": 4.0, - "default": 4.0 + "help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.", + "placeholder": 3.0, + "default": 3.0 } ] }, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 735ba05810..e1f0bd3a68 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -130,6 +130,15 @@ MyAvatar::MyAvatar(RigPointer rig) : connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, this, static_cast(&MyAvatar::goToLocation)); + // handle scale constraints imposed on us by the domain-server + auto& domainHandler = DependencyManager::get()->getDomainHandler(); + + // when we connect to a domain and retrieve its settings, we restrict our max/min scale based on those settings + connect(&domainHandler, &DomainHandler::settingsReceived, this, &MyAvatar::restrictScaleFromDomainSettings); + + // when we leave a domain we lift whatever restrictions that domain may have placed on our scale + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::clearScaleRestriction); + _characterController.setEnabled(true); _bodySensorMatrix = deriveBodyFromHMDSensor(); @@ -1824,24 +1833,79 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float } void MyAvatar::increaseSize() { - if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { - _targetScale *= (1.0f + SCALING_RATIO); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + // clamp the target scale to the maximum allowable scale in the domain + + float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO); + + if (updatedTargetScale > _domainMaximumScale) { + qCDebug(interfaceapp, "Forced scale to %f since %f would be larger than allowed maximum", + _domainMaximumScale, updatedTargetScale); + + updatedTargetScale = _domainMaximumScale; } + + setTargetScale(updatedTargetScale); + qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } void MyAvatar::decreaseSize() { - if (MIN_AVATAR_SCALE < (1.0f - SCALING_RATIO) * _targetScale) { - _targetScale *= (1.0f - SCALING_RATIO); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + // clamp the target scale to the minimum allowable scale in the domain + float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO); + + if (updatedTargetScale < _domainMinimumScale) { + qCDebug(interfaceapp, "Forced scale to %f since %f would be smaller than allowed minimum", + _domainMinimumScale, updatedTargetScale); + + updatedTargetScale = _domainMinimumScale; } + + + setTargetScale(updatedTargetScale); + qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } void MyAvatar::resetSize() { - _targetScale = 1.0f; + // if the default + const float DEFAULT_AVATAR_SCALE = 1.0f; + + float allowedDefaultScale = glm::clamp(DEFAULT_AVATAR_SCALE, _domainMinimumScale, _domainMaximumScale); + + if (allowedDefaultScale != DEFAULT_AVATAR_SCALE) { + qCDebug(interfaceapp, "Forcing scale to %f since %f is not an allowed avatar scale by the domain", + allowedDefaultScale, DEFAULT_AVATAR_SCALE); + } + + setTargetScale(allowedDefaultScale); qCDebug(interfaceapp, "Reset scale to %f", (double)_targetScale); } +void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject) { + // pull out the minimum and maximum scale and set them to restrict our scale + + static const QString AVATAR_SETTINGS_KEY = "avatars"; + auto avatarsObject = domainSettingsObject[AVATAR_SETTINGS_KEY].toObject(); + + static const QString MIN_SCALE_OPTION = "min_avatar_scale"; + float settingMinScale = avatarsObject[MIN_SCALE_OPTION].toDouble(MIN_AVATAR_SCALE); + setDomainMinimumScale(settingMinScale); + + static const QString MAX_SCALE_OPTION = "max_avatar_scale"; + float settingMaxScale = avatarsObject[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); + setDomainMaximumScale(settingMaxScale); + + // debug to log if this avatar's scale in this domain will be clamped + auto clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); + + if (_targetScale != clampedScale) { + qCDebug(interfaceapp, "Avatar scale will be clamped to %f because %f is not allowed by current domain", + clampedScale, _targetScale); + } +} + +void MyAvatar::clearScaleRestriction() { + _domainMinimumScale = MIN_AVATAR_SCALE; + _domainMaximumScale = MAX_AVATAR_SCALE; +} void MyAvatar::goToLocation(const QVariant& propertiesVar) { qCDebug(interfaceapp, "MyAvatar QML goToLocation"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 71f185c6ed..d9c88621d2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -292,6 +292,9 @@ public slots: bool shouldFaceLocation = false); void goToLocation(const QVariant& properties); + void restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject); + void clearScaleRestriction(); + // Set/Get update the thrust that will move the avatar around void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; glm::vec3 getThrust() { return _thrust; }; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 9df23dad2c..2469d0df04 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -210,7 +210,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) { packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 0), bodyEulerAngles.y); packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 1), bodyEulerAngles.x); packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 2), bodyEulerAngles.z); - packFloatRatioToTwoByte((uint8_t*)(&header->scale), _targetScale); + packFloatRatioToTwoByte((uint8_t*)(&header->scale), getDomainLimitedScale()); header->lookAtPosition[0] = _headData->_lookAtPosition.x; header->lookAtPosition[1] = _headData->_lookAtPosition.y; header->lookAtPosition[2] = _headData->_lookAtPosition.z; @@ -516,7 +516,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } return buffer.size(); } - _targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, scale)); + setTargetScale(scale); glm::vec3 lookAt = glm::vec3(header->lookAtPosition[0], header->lookAtPosition[1], header->lookAtPosition[2]); if (isNaN(lookAt)) { @@ -1439,7 +1439,7 @@ QJsonObject AvatarData::toJson() const { if (!success) { qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform"; } - avatarTransform.setScale(getTargetScale()); + avatarTransform.setScale(getDomainLimitedScale()); if (recordingBasis) { root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis); // Find the relative transform @@ -1451,7 +1451,7 @@ QJsonObject AvatarData::toJson() const { root[JSON_AVATAR_RELATIVE] = Transform::toJson(avatarTransform); } - auto scale = getTargetScale(); + auto scale = getDomainLimitedScale(); if (scale != 1.0f) { root[JSON_AVATAR_SCALE] = scale; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index cb3ef0c40e..018833283a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -243,6 +243,10 @@ public: void setTargetScale(float targetScale); void setTargetScaleVerbose(float targetScale); + float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); } + void setDomainMinimumScale(float domainMinimumScale) { _domainMinimumScale = std::max(domainMinimumScale, MIN_AVATAR_SCALE); } + void setDomainMaximumScale(float domainMaximumScale) { _domainMaximumScale = std::min(domainMaximumScale, MAX_AVATAR_SCALE); } + // Hand State Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE char getHandState() const { return _handState; } @@ -377,6 +381,8 @@ protected: // Body scale float _targetScale; + float _domainMinimumScale { MIN_AVATAR_SCALE }; + float _domainMaximumScale { MAX_AVATAR_SCALE }; // Hand state (are we grabbing something or not) char _handState; From 64d9fa0f3907a9c03d1968a8903938bb9b7538e1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 14:19:32 -0800 Subject: [PATCH 23/34] clamp avatar scale to domain limit in avatar mixer --- assignment-client/src/avatars/AvatarMixer.cpp | 28 ++++++++++++++++--- assignment-client/src/avatars/AvatarMixer.h | 3 ++ libraries/avatars/src/AvatarData.h | 6 ++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index d87a5f1cc9..1896e3a43f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -512,12 +512,19 @@ void AvatarMixer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); nodeList->addNodeTypeToInterestSet(NodeType::Agent); - nodeList->linkedDataCreateCallback = [] (Node* node) { - node->setLinkedData(std::unique_ptr { new AvatarMixerClientData }); - }; - // parse the settings to pull out the values we need parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); + + float domainMinimumScale = _domainMinimumScale; + float domainMaximumScale = _domainMaximumScale; + + nodeList->linkedDataCreateCallback = [domainMinimumScale, domainMaximumScale] (Node* node) { + auto clientData = std::unique_ptr { new AvatarMixerClientData }; + clientData->getAvatar().setDomainMinimumScale(domainMinimumScale); + clientData->getAvatar().setDomainMaximumScale(domainMaximumScale); + + node->setLinkedData(std::move(clientData)); + }; // start the broadcastThread _broadcastThread.start(); @@ -549,4 +556,17 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { _maxKbpsPerNode = nodeBandwidthValue.toDouble(DEFAULT_NODE_SEND_BANDWIDTH) * KILO_PER_MEGA; qDebug() << "The maximum send bandwidth per node is" << _maxKbpsPerNode << "kbps."; + + const QString AVATARS_SETTINGS_KEY = "avatars"; + + static const QString MIN_SCALE_OPTION = "min_avatar_scale"; + float settingMinScale = domainSettings[AVATARS_SETTINGS_KEY].toObject()[MIN_SCALE_OPTION].toDouble(MIN_AVATAR_SCALE); + _domainMinimumScale = glm::clamp(settingMinScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + + static const QString MAX_SCALE_OPTION = "max_avatar_scale"; + float settingMaxScale = domainSettings[AVATARS_SETTINGS_KEY].toObject()[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); + _domainMaximumScale = glm::clamp(settingMaxScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + + qDebug() << "This domain requires a minimum avatar scale of" << _domainMinimumScale + << "and a maximum avatar scale of" << _domainMaximumScale; } diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 9286cd4691..6e1d722145 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -59,6 +59,9 @@ private: float _maxKbpsPerNode = 0.0f; + float _domainMinimumScale { MIN_AVATAR_SCALE }; + float _domainMaximumScale { MAX_AVATAR_SCALE }; + QTimer* _broadcastTimer = nullptr; }; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 018833283a..97879700ee 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -244,8 +244,10 @@ public: void setTargetScaleVerbose(float targetScale); float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); } - void setDomainMinimumScale(float domainMinimumScale) { _domainMinimumScale = std::max(domainMinimumScale, MIN_AVATAR_SCALE); } - void setDomainMaximumScale(float domainMaximumScale) { _domainMaximumScale = std::min(domainMaximumScale, MAX_AVATAR_SCALE); } + void setDomainMinimumScale(float domainMinimumScale) + { _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } + void setDomainMaximumScale(float domainMaximumScale) + { _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } // Hand State Q_INVOKABLE void setHandState(char s) { _handState = s; } From 6f442a74b1cbc7355717ce3cc6a52ede5b8689fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 14:43:15 -0800 Subject: [PATCH 24/34] request settings from agents and debug results --- .../resources/describe-settings.json | 1 + interface/src/avatar/MyAvatar.cpp | 3 ++ libraries/networking/src/DomainHandler.cpp | 32 +++++++------------ 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index b5c612881f..77a33b4d56 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -869,6 +869,7 @@ { "name": "avatars", "label": "Avatars", + "assignment-types": [1, 2], "settings": [ { "name": "min_avatar_scale", diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e1f0bd3a68..48b6e7c53c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1893,6 +1893,9 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings float settingMaxScale = avatarsObject[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); setDomainMaximumScale(settingMaxScale); + qCDebug(interfaceapp, "This domain requires a minimum avatar scale of %f and a maximum avatar scale of %f", + _domainMinimumScale, _domainMaximumScale); + // debug to log if this avatar's scale in this domain will be clamped auto clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index eecc1515f5..5d7340b2ce 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -272,27 +272,17 @@ void DomainHandler::setIsConnected(bool isConnected) { } void DomainHandler::requestDomainSettings() { - // TODO: the nodes basically lock if they don't get a response - add a timeout to this so that they at least restart - // if they can't get settings - - NodeType_t owningNodeType = DependencyManager::get()->getOwnerType(); - if (owningNodeType == NodeType::Agent) { - // for now the agent nodes don't need any domain settings - _settingsObject = QJsonObject(); - emit settingsReceived(_settingsObject); - } else { - qCDebug(networking) << "Requesting settings from domain server"; - - Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get()->getOwnerType()); - - auto packet = NLPacket::create(PacketType::DomainSettingsRequest, sizeof(assignmentType), true, false); - packet->writePrimitive(assignmentType); - - auto nodeList = DependencyManager::get(); - nodeList->sendPacket(std::move(packet), _sockAddr); - - _settingsTimer.start(); - } + qCDebug(networking) << "Requesting settings from domain server"; + + Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get()->getOwnerType()); + + auto packet = NLPacket::create(PacketType::DomainSettingsRequest, sizeof(assignmentType), true, false); + packet->writePrimitive(assignmentType); + + auto nodeList = DependencyManager::get(); + nodeList->sendPacket(std::move(packet), _sockAddr); + + _settingsTimer.start(); } void DomainHandler::processSettingsPacketList(QSharedPointer packetList) { From 9fdde49d141b4f70ef22d945115c0c5c96f578f4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 14:54:42 -0800 Subject: [PATCH 25/34] clamp target scale changes on both ends --- interface/src/avatar/MyAvatar.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 48b6e7c53c..3b2b89310b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1833,34 +1833,32 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float } void MyAvatar::increaseSize() { - // clamp the target scale to the maximum allowable scale in the domain - + // clamp the target scale to the allowable scale in the domain float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO); - if (updatedTargetScale > _domainMaximumScale) { - qCDebug(interfaceapp, "Forced scale to %f since %f would be larger than allowed maximum", - _domainMaximumScale, updatedTargetScale); + auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); - updatedTargetScale = _domainMaximumScale; + if (clampedTargetScale != updatedTargetScale) { + qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain", + clampedTargetScale, updatedTargetScale); } - setTargetScale(updatedTargetScale); + setTargetScale(clampedTargetScale); qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } void MyAvatar::decreaseSize() { - // clamp the target scale to the minimum allowable scale in the domain + // clamp the target scale to the allowable scale in the domain float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO); - if (updatedTargetScale < _domainMinimumScale) { - qCDebug(interfaceapp, "Forced scale to %f since %f would be smaller than allowed minimum", - _domainMinimumScale, updatedTargetScale); + auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); - updatedTargetScale = _domainMinimumScale; + if (clampedTargetScale != updatedTargetScale) { + qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain", + clampedTargetScale, updatedTargetScale); } - - setTargetScale(updatedTargetScale); + setTargetScale(clampedTargetScale); qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); } From 53769f4edf030c5a4ddb7aac3cc8ef1c4f551cc3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 14:58:04 -0800 Subject: [PATCH 26/34] change scale for avatar if domain limited scale changes --- interface/src/avatar/Avatar.cpp | 11 ++++++----- interface/src/avatar/AvatarActionHold.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 872d2af04e..46ee15de08 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -165,16 +165,17 @@ AABox Avatar::getBounds() const { void Avatar::animateScaleChanges(float deltaTime) { float currentScale = getUniformScale(); - if (currentScale != _targetScale) { - // use exponential decay toward _targetScale + auto desiredScale = getDomainLimitedScale(); + if (currentScale != desiredScale) { + // use exponential decay toward the domain limit clamped scale const float SCALE_ANIMATION_TIMESCALE = 0.5f; float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f); - float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale; + float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * desiredScale; // snap to the end when we get close enough const float MIN_RELATIVE_SCALE_ERROR = 0.03f; - if (fabsf(_targetScale - currentScale) / _targetScale < MIN_RELATIVE_SCALE_ERROR) { - animatedScale = _targetScale; + if (fabsf(desiredScale - currentScale) / desiredScale < MIN_RELATIVE_SCALE_ERROR) { + animatedScale = desiredScale; } setScale(glm::vec3(animatedScale)); // avatar scale is uniform diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 85ff485d7a..32a3586dba 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -152,7 +152,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm:: Transform avatarTransform; auto myAvatar = DependencyManager::get()->getMyAvatar(); avatarTransform = myAvatar->getTransform(); - palmPosition = avatarTransform.transform(pose.getTranslation() / myAvatar->getTargetScale()); + palmPosition = avatarTransform.transform(pose.getTranslation() / myAvatar->getDomainLimitedScale()); palmRotation = avatarTransform.getRotation() * pose.getRotation(); } else { glm::vec3 avatarRigidBodyPosition; From 4d18a3cc3d5a7b52930cfb904676b78688703c83 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 10 Nov 2016 15:01:06 -0800 Subject: [PATCH 27/34] expose menu enablement to javascript --- .../src/scripting/MenuScriptingInterface.cpp | 17 +++++++++++++++++ .../src/scripting/MenuScriptingInterface.h | 3 +++ libraries/ui/src/ui/Menu.cpp | 19 +++++++++++++++++++ libraries/ui/src/ui/Menu.h | 3 +++ 4 files changed, 42 insertions(+) diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index 2fa7470561..df75d331d6 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -126,6 +126,23 @@ void MenuScriptingInterface::setIsOptionChecked(const QString& menuOption, bool Q_ARG(bool, isChecked)); } +bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) { + if (QThread::currentThread() == qApp->thread()) { + return Menu::getInstance()->isOptionChecked(menuOption); + } + bool result; + QMetaObject::invokeMethod(Menu::getInstance(), "isMenuEnabled", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, result), + Q_ARG(const QString&, menuOption)); + return result; +} + +void MenuScriptingInterface::setMenuEnabled(const QString& menuOption, bool isChecked) { + QMetaObject::invokeMethod(Menu::getInstance(), "setMenuEnabled", + Q_ARG(const QString&, menuOption), + Q_ARG(bool, isChecked)); +} + void MenuScriptingInterface::triggerOption(const QString& menuOption) { QMetaObject::invokeMethod(Menu::getInstance(), "triggerOption", Q_ARG(const QString&, menuOption)); } diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 5b8a437529..855b1af13b 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -50,6 +50,9 @@ public slots: void setIsOptionChecked(const QString& menuOption, bool isChecked); void triggerOption(const QString& menuOption); + + bool isMenuEnabled(const QString& menuName); + void setMenuEnabled(const QString& menuName, bool isEnabled); signals: void menuItemEvent(const QString& menuItem); diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index aee8b40832..ba24adfc3f 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -428,6 +428,25 @@ bool Menu::menuExists(const QString& menuName) { return false; } +bool Menu::isMenuEnabled(const QString& menuName) { + QAction* action = getMenuAction(menuName); + + // only proceed if the menu actually exists + if (action) { + return action->isEnabled(); + } + return false; +} + +void Menu::setMenuEnabled(const QString& menuName, bool isEnabled) { + QAction* action = getMenuAction(menuName); + + // only proceed if the menu actually exists + if (action) { + action->setEnabled(isEnabled); + } +} + void Menu::addSeparator(const QString& menuName, const QString& separatorName, const QString& grouping) { MenuWrapper* menuObj = getMenu(menuName); if (menuObj) { diff --git a/libraries/ui/src/ui/Menu.h b/libraries/ui/src/ui/Menu.h index ee60a031c3..2711fc5921 100644 --- a/libraries/ui/src/ui/Menu.h +++ b/libraries/ui/src/ui/Menu.h @@ -106,6 +106,9 @@ public slots: bool isOptionChecked(const QString& menuOption) const; void setIsOptionChecked(const QString& menuOption, bool isChecked); + bool isMenuEnabled(const QString& menuName); + void setMenuEnabled(const QString& menuName, bool isEnabled); + bool getGroupingIsVisible(const QString& grouping); void setGroupingIsVisible(const QString& grouping, bool isVisible); /// NOTE: the "" grouping is always visible From d5722c1654dd55f1ab8235ec2f5a7c09afb5887b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 15:03:13 -0800 Subject: [PATCH 28/34] fix clamping of scale and DRY it up --- interface/src/avatar/MyAvatar.cpp | 44 +++++++++++-------------------- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3b2b89310b..0fd7192f2f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1832,49 +1832,37 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float return false; } +void MyAvatar::clampScaleChangeToDomainLimits(float desiredScale) { + auto clampedTargetScale = glm::clamp(desiredScale, _domainMinimumScale, _domainMaximumScale); + + if (clampedTargetScale != desiredScale) { + qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain", + clampedTargetScale, desiredScale); + } + + setTargetScale(clampedTargetScale); + qCDebug(interfaceapp, "Changed scale to %f", _targetScale); +} + void MyAvatar::increaseSize() { // clamp the target scale to the allowable scale in the domain float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO); - auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); - - if (clampedTargetScale != updatedTargetScale) { - qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain", - clampedTargetScale, updatedTargetScale); - } - - setTargetScale(clampedTargetScale); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + clampScaleChangeToDomainLimits(updatedTargetScale); } void MyAvatar::decreaseSize() { // clamp the target scale to the allowable scale in the domain float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO); - auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); - - if (clampedTargetScale != updatedTargetScale) { - qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain", - clampedTargetScale, updatedTargetScale); - } - - setTargetScale(clampedTargetScale); - qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale); + clampScaleChangeToDomainLimits(updatedTargetScale); } void MyAvatar::resetSize() { - // if the default + // attempt to reset avatar size to the default const float DEFAULT_AVATAR_SCALE = 1.0f; - float allowedDefaultScale = glm::clamp(DEFAULT_AVATAR_SCALE, _domainMinimumScale, _domainMaximumScale); - - if (allowedDefaultScale != DEFAULT_AVATAR_SCALE) { - qCDebug(interfaceapp, "Forcing scale to %f since %f is not an allowed avatar scale by the domain", - allowedDefaultScale, DEFAULT_AVATAR_SCALE); - } - - setTargetScale(allowedDefaultScale); - qCDebug(interfaceapp, "Reset scale to %f", (double)_targetScale); + clampScaleChangeToDomainLimits(DEFAULT_AVATAR_SCALE); } void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d9c88621d2..0b8db6a24d 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -372,6 +372,7 @@ private: virtual void updatePalms() override {} void lateUpdatePalms(); + void clampScaleChangeToDomainLimits(float desiredScale); float _driveKeys[MAX_DRIVE_KEYS]; bool _wasPushing; From 8299e23cc3e084f2be5823491963bf5606c4028c Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 10 Nov 2016 15:15:11 -0800 Subject: [PATCH 29/34] diable some viewpoint menu options when in hmd. --- scripts/system/hmd.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/system/hmd.js b/scripts/system/hmd.js index 84ff6b3c89..e1c846806f 100644 --- a/scripts/system/hmd.js +++ b/scripts/system/hmd.js @@ -24,10 +24,16 @@ var desktopMenuItemName = "Desktop"; var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var button; +// Independent and Entity mode make people sick. Third Person and Mirror have traps that we need to work through. +// Disable them in hmd. +var desktopOnlyViews = ['Third Person', 'Mirror', 'Independent Mode', 'Entity Mode']; function onHmdChanged(isHmd) { button.writeProperty('buttonState', isHmd ? 0 : 1); button.writeProperty('defaultState', isHmd ? 0 : 1); button.writeProperty('hoverState', isHmd ? 2 : 3); + desktopOnlyViews.forEach(function (view) { + Menu.setMenuEnabled("View>" + view, !isHmd); + }); } function onClicked(){ var isDesktop = Menu.isOptionChecked(desktopMenuItemName); From 272d0c845e48d58db7e1089fa04c8d22dacb59e5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 15:25:15 -0800 Subject: [PATCH 30/34] add clarifying comments about target scale changes --- interface/src/avatar/MyAvatar.cpp | 36 ++++++++++++++++++++++++++++--- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0fd7192f2f..cdde8a00a3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1832,6 +1832,28 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float return false; } +// There can be a separation between the _targetScale and the actual scale of the rendered avatar in a domain. +// When the avatar enters a domain where their target scale is not allowed according to the min/max +// we do not change their saved target scale. Instead, we use getDomainLimitedScale() to render the avatar +// at a domain appropriate size. When the avatar leaves the limiting domain, we'll return them to their previous target scale. +// While connected to a domain that limits avatar scale if the user manually changes their avatar scale, we change +// target scale to match the new scale they have chosen. When they leave the domain they will not return to the scale they were +// before they entered the limiting domain. + +void MyAvatar::clampTargetScaleToDomainLimits() { + // when we're about to change the target scale because the user has asked to increase or decrease their scale, + // we first make sure that we're starting from a target scale that is allowed by the current domain + + auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); + + if (clampedTargetScale != _targetScale) { + qCDebug(interfaceapp, "Clamped scale to %f since original target scale %f was not allowed by domain", + clampedTargetScale, _targetScale); + + setTargetScale(clampedTargetScale); + } +} + void MyAvatar::clampScaleChangeToDomainLimits(float desiredScale) { auto clampedTargetScale = glm::clamp(desiredScale, _domainMinimumScale, _domainMaximumScale); @@ -1845,21 +1867,29 @@ void MyAvatar::clampScaleChangeToDomainLimits(float desiredScale) { } void MyAvatar::increaseSize() { - // clamp the target scale to the allowable scale in the domain + // make sure we're starting from an allowable scale + clampTargetScaleToDomainLimits(); + + // calculate what our new scale should be float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO); + // attempt to change to desired scale (clamped to the domain limits) clampScaleChangeToDomainLimits(updatedTargetScale); } void MyAvatar::decreaseSize() { - // clamp the target scale to the allowable scale in the domain + // make sure we're starting from an allowable scale + clampTargetScaleToDomainLimits(); + + // calculate what our new scale should be float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO); + // attempt to change to desired scale (clamped to the domain limits) clampScaleChangeToDomainLimits(updatedTargetScale); } void MyAvatar::resetSize() { - // attempt to reset avatar size to the default + // attempt to reset avatar size to the default (clamped to domain limits) const float DEFAULT_AVATAR_SCALE = 1.0f; clampScaleChangeToDomainLimits(DEFAULT_AVATAR_SCALE); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0b8db6a24d..60049bea67 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -372,6 +372,7 @@ private: virtual void updatePalms() override {} void lateUpdatePalms(); + void clampTargetScaleToDomainLimits(); void clampScaleChangeToDomainLimits(float desiredScale); float _driveKeys[MAX_DRIVE_KEYS]; From f14037979a697d6c72b7e24c98a2dbb42833f81c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 15:31:23 -0800 Subject: [PATCH 31/34] fix a typo in help text for minimum scale --- domain-server/resources/describe-settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 77a33b4d56..8b3b21e066 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -875,7 +875,7 @@ "name": "min_avatar_scale", "type": "double", "label": "Minimum Avatar Scale (meters)", - "help": "Limits the scale of avatars in your domain. Must be at least than 0.005.", + "help": "Limits the scale of avatars in your domain. Must be at least 0.005.", "placeholder": 0.25, "default": 0.25 }, From 88c63332de1cda9058fec5f789d33a9a733cf619 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 16:21:48 -0800 Subject: [PATCH 32/34] protect flipped min/max scale in avatar mixer settings --- assignment-client/src/avatars/AvatarMixer.cpp | 3 +++ interface/src/avatar/MyAvatar.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 1896e3a43f..9700c544c1 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -567,6 +567,9 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { float settingMaxScale = domainSettings[AVATARS_SETTINGS_KEY].toObject()[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); _domainMaximumScale = glm::clamp(settingMaxScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + // make sure that the domain owner didn't flip min and max + _domainMinimumScale = std::min(_domainMinimumScale, _domainMaximumScale); + qDebug() << "This domain requires a minimum avatar scale of" << _domainMinimumScale << "and a maximum avatar scale of" << _domainMaximumScale; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cdde8a00a3..7ce0f92d72 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1909,6 +1909,9 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings float settingMaxScale = avatarsObject[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE); setDomainMaximumScale(settingMaxScale); + // make sure that the domain owner didn't flip min and max + _domainMinimumScale = std::min(_domainMinimumScale, _domainMaximumScale); + qCDebug(interfaceapp, "This domain requires a minimum avatar scale of %f and a maximum avatar scale of %f", _domainMinimumScale, _domainMaximumScale); From 020942c82602c98ea36bc475ffeddf492703e062 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 16:50:36 -0800 Subject: [PATCH 33/34] better handling for a flipped min/max scale --- assignment-client/src/avatars/AvatarMixer.cpp | 4 +++- interface/src/avatar/MyAvatar.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 9700c544c1..041449dc57 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -568,7 +568,9 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { _domainMaximumScale = glm::clamp(settingMaxScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); // make sure that the domain owner didn't flip min and max - _domainMinimumScale = std::min(_domainMinimumScale, _domainMaximumScale); + if (_domainMinimumScale > _domainMaximumScale) { + std::swap(_domainMinimumScale, _domainMaximumScale); + } qDebug() << "This domain requires a minimum avatar scale of" << _domainMinimumScale << "and a maximum avatar scale of" << _domainMaximumScale; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7ce0f92d72..155b059f68 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1910,7 +1910,9 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings setDomainMaximumScale(settingMaxScale); // make sure that the domain owner didn't flip min and max - _domainMinimumScale = std::min(_domainMinimumScale, _domainMaximumScale); + if (_domainMinimumScale > _domainMaximumScale) { + std::swap(_domainMinimumScale, _domainMaximumScale); + } qCDebug(interfaceapp, "This domain requires a minimum avatar scale of %f and a maximum avatar scale of %f", _domainMinimumScale, _domainMaximumScale); From 7f46714645d3a259b369d8f89488a17dcd948050 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 10 Nov 2016 16:53:56 -0800 Subject: [PATCH 34/34] drop the incorrect scale from domain settings --- domain-server/resources/describe-settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 8b3b21e066..675c39563b 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -874,7 +874,7 @@ { "name": "min_avatar_scale", "type": "double", - "label": "Minimum Avatar Scale (meters)", + "label": "Minimum Avatar Scale", "help": "Limits the scale of avatars in your domain. Must be at least 0.005.", "placeholder": 0.25, "default": 0.25 @@ -882,7 +882,7 @@ { "name": "max_avatar_scale", "type": "double", - "label": "Maximum Avatar Scale (meters)", + "label": "Maximum Avatar Scale", "help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.", "placeholder": 3.0, "default": 3.0