From a0d72f08ac08fe70d902ee041dd46d7d838078c7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 16 Aug 2017 14:38:11 -0700 Subject: [PATCH 01/58] Fix for incorrectly scaled avatar collision on startup --- interface/src/avatar/MyAvatar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 30c6a85470..ce5445d512 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2251,6 +2251,7 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings } setScale(glm::vec3(_targetScale)); + rebuildCollisionShape(); settings.endGroup(); } From d1967439869c3805dc9b75fadbdb2d7054865546 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 16 Aug 2017 14:40:14 -0700 Subject: [PATCH 02/58] Added Avatar::getHeight() method --- interface/src/avatar/MyAvatar.cpp | 24 +---------- .../src/avatars-renderer/Avatar.cpp | 38 ++++++++++++++++ .../src/avatars-renderer/Avatar.h | 4 +- libraries/shared/src/AvatarConstants.h | 43 +++++++++++++++++++ 4 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 libraries/shared/src/AvatarConstants.h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ce5445d512..9f2b1bca33 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -87,29 +88,6 @@ const float MyAvatar::ZOOM_MIN = 0.5f; const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_DEFAULT = 1.5f; -// default values, used when avatar is missing joints... (avatar space) -static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; -static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; -static const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; -static const glm::quat DEFAULT_AVATAR_RIGHTARM_ROT { -0.536241f, 0.536241f, -0.460918f, -0.460918f }; -static const glm::vec3 DEFAULT_AVATAR_LEFTARM_POS { 0.134795f, 0.396349f, -0.0515881f }; -static const glm::quat DEFAULT_AVATAR_LEFTARM_ROT { 0.536257f, 0.536258f, -0.460899f, 0.4609f }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTHAND_POS { -0.72768f, 0.396349f, -0.0515779f }; -static const glm::quat DEFAULT_AVATAR_RIGHTHAND_ROT { 0.479184f, -0.520013f, 0.522537f, 0.476365f}; -static const glm::vec3 DEFAULT_AVATAR_LEFTHAND_POS { 0.727588f, 0.39635f, -0.0515878f }; -static const glm::quat DEFAULT_AVATAR_LEFTHAND_ROT { -0.479181f, -0.52001f, 0.52254f, -0.476369f }; -static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f }; -static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f }; -static const glm::quat DEFAULT_AVATAR_SPINE2_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f }; -static const glm::quat DEFAULT_AVATAR_HIPS_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.08f, -0.96f, 0.029f}; -static const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.9154590368270874f, -0.005437685176730156f, -0.023744143545627594f }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f }; -static const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f }; - MyAvatar::MyAvatar(QThread* thread) : Avatar(thread), _yawSpeed(YAW_SPEED_DEFAULT), diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index c619656cd9..97f83a3053 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -1548,3 +1549,40 @@ void Avatar::ensureInScene(AvatarSharedPointer self, const render::ScenePointer& addToScene(self, scene); } } + +// returns the avatar height, in meters, includes avatar scale factor. +float Avatar::getHeight() const { + // AJT: TODO: I don't know what scale is to use here... getDomainLimitedScale? + float avatarScale = getTargetScale(); + if (_skeletonModel) { + auto& rig = _skeletonModel->getRig(); + int headTopJoint = rig.indexOfJoint("HeadTop_End"); + int headJoint = rig.indexOfJoint("Head"); + int eyeJoint = rig.indexOfJoint("LeftEye") != -1 ? rig.indexOfJoint("LeftEye") : rig.indexOfJoint("RightEye"); + int toeJoint = rig.indexOfJoint("LeftToeBase") != -1 ? rig.indexOfJoint("LeftToeBase") : rig.indexOfJoint("RightToeBase"); + if (headTopJoint >= 0 && toeJoint >= 0) { + // measure toe to top of head. Note: default poses already include avatar scale factor + float height = rig.getAbsoluteDefaultPose(headTopJoint).trans().y - rig.getAbsoluteDefaultPose(toeJoint).trans().y; + return height; + } else if (eyeJoint >= 0 && toeJoint >= 0) { + // measure from eyes to toes + the average eye to top of head distance. + const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y - rig.getAbsoluteDefaultPose(toeJoint).trans().y; + return eyeHeight + eyeHeight * ratio; + } else if (headTopJoint >= 0) { + return rig.getAbsoluteDefaultPose(headTopJoint).trans().y; + } else if (eyeJoint >= 0) { + const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y; + return eyeHeight + eyeHeight * ratio; + } else if (headJoint >= 0) { + const float ratio = DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float neckHeight = rig.getAbsoluteDefaultPose(headJoint).trans().y; + return neckHeight + neckHeight * ratio; + } else { + return avatarScale * DEFAULT_AVATAR_HEIGHT; + } + } else { + return avatarScale * DEFAULT_AVATAR_HEIGHT; + } +} diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 5b64d79484..6ef935ad3d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -251,6 +251,9 @@ public: bool isFading() const { return _isFading; } void updateFadingStatus(render::ScenePointer scene); + // returns the avatar height, in meters, includes avatar scale factor. + Q_INVOKABLE float getHeight() const; + public slots: // FIXME - these should be migrated to use Pose data instead @@ -362,7 +365,6 @@ private: float _displayNameTargetAlpha { 1.0f }; float _displayNameAlpha { 1.0f }; - }; #endif // hifi_Avatar_h diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h new file mode 100644 index 0000000000..b1ff1872e7 --- /dev/null +++ b/libraries/shared/src/AvatarConstants.h @@ -0,0 +1,43 @@ +// +// AvatarConstants.h +// libraries/shared/src +// +// Created by Anthony J. Thibault on Aug 16th 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarConstants_h +#define hifi_AvatarConstants_h + +// 50th Percentile Man +const float DEFAULT_AVATAR_HEIGHT = 1.755f; // meters +const float DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD = 0.11f; // meters +const float DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD = 0.185f; // meters + +// Used when avatar is missing joints... (avatar space) +static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; +static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; +static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; +static const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 }; +static const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; +static const glm::quat DEFAULT_AVATAR_RIGHTARM_ROT { -0.536241f, 0.536241f, -0.460918f, -0.460918f }; +static const glm::vec3 DEFAULT_AVATAR_LEFTARM_POS { 0.134795f, 0.396349f, -0.0515881f }; +static const glm::quat DEFAULT_AVATAR_LEFTARM_ROT { 0.536257f, 0.536258f, -0.460899f, 0.4609f }; +static const glm::vec3 DEFAULT_AVATAR_RIGHTHAND_POS { -0.72768f, 0.396349f, -0.0515779f }; +static const glm::quat DEFAULT_AVATAR_RIGHTHAND_ROT { 0.479184f, -0.520013f, 0.522537f, 0.476365f}; +static const glm::vec3 DEFAULT_AVATAR_LEFTHAND_POS { 0.727588f, 0.39635f, -0.0515878f }; +static const glm::quat DEFAULT_AVATAR_LEFTHAND_ROT { -0.479181f, -0.52001f, 0.52254f, -0.476369f }; +static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f }; +static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f }; +static const glm::quat DEFAULT_AVATAR_SPINE2_ROT { Quaternions::Y_180 }; +static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f }; +static const glm::quat DEFAULT_AVATAR_HIPS_ROT { Quaternions::Y_180 }; +static const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.08f, -0.96f, 0.029f}; +static const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.9154590368270874f, -0.005437685176730156f, -0.023744143545627594f }; +static const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f }; +static const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f }; + +#endif // hifi_AvatarConstants_h From 80b660b2588260d4a3fe06ff565010696df2ff80 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 16 Aug 2017 17:52:01 -0700 Subject: [PATCH 03/58] Added userHeight accessors and preference Also made Avatar::getHeight thread-safe --- interface/src/avatar/MyAvatar.cpp | 11 ++++++++++- interface/src/avatar/MyAvatar.h | 10 ++++++++++ interface/src/ui/PreferencesDialog.cpp | 10 ++++++++++ .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 8 ++++++++ .../avatars-renderer/src/avatars-renderer/Avatar.h | 6 +++++- 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9f2b1bca33..e574cb78ec 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -976,6 +975,7 @@ void MyAvatar::saveData() { settings.setValue("collisionSoundURL", _collisionSoundURL); settings.setValue("useSnapTurn", _useSnapTurn); settings.setValue("clearOverlayWhenMoving", _clearOverlayWhenMoving); + settings.setValue("userHeight", getUserHeight()); settings.endGroup(); } @@ -1113,6 +1113,7 @@ void MyAvatar::loadData() { setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); setClearOverlayWhenMoving(settings.value("clearOverlayWhenMoving", _clearOverlayWhenMoving).toBool()); setDominantHand(settings.value("dominantHand", _dominantHand).toString().toLower()); + setUserHeight(settings.value("userHeight", DEFAULT_AVATAR_HEIGHT).toDouble()); settings.endGroup(); setEnableMeshVisible(Menu::getInstance()->isOptionChecked(MenuOption::MeshVisible)); @@ -2619,6 +2620,14 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { return createMatFromQuatAndPos(headOrientationYawOnly, bodyPos); } +float MyAvatar::getUserHeight() const { + return _userHeight.get(); +} + +void MyAvatar::setUserHeight(float value) { + _userHeight.set(value); +} + glm::vec3 MyAvatar::getPositionForAudio() { switch (_audioListenerMode) { case AudioListenerMode::FROM_HEAD: diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c7fe309894..70385cbaf2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "AtRestDetector.h" #include "MyCharacterController.h" @@ -101,6 +102,7 @@ class MyAvatar : public Avatar { * @property collisionsEnabled {bool} This can be used to disable collisions between the avatar and the world. * @property useAdvancedMovementControls {bool} Stores the user preference only, does not change user mappings, this is done in the defaultScript * "scripts/system/controllers/toggleAdvancedMovementForHandControllers.js". + * @property userHeight {number} The height of the user in sensor space. (meters). */ // FIXME: `glm::vec3 position` is not accessible from QML, so this exposes position in a QML-native type @@ -142,6 +144,8 @@ class MyAvatar : public Avatar { Q_PROPERTY(float hmdRollControlDeadZone READ getHMDRollControlDeadZone WRITE setHMDRollControlDeadZone) Q_PROPERTY(float hmdRollControlRate READ getHMDRollControlRate WRITE setHMDRollControlRate) + Q_PROPERTY(float userHeight READ getUserHeight WRITE setUserHeight) + const QString DOMINANT_LEFT_HAND = "left"; const QString DOMINANT_RIGHT_HAND = "right"; @@ -521,6 +525,9 @@ public: Q_INVOKABLE bool isUp(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) > 0.0f; }; // true iff direction points up wrt avatar's definition of up. Q_INVOKABLE bool isDown(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) < 0.0f; }; + float getUserHeight() const; + void setUserHeight(float value); + public slots: void increaseSize(); void decreaseSize(); @@ -794,6 +801,9 @@ private: void setAway(bool value); std::vector _pinnedJoints; + + // height of user in sensor space, when standing erect. + ThreadSafeValueCache _userHeight { DEFAULT_AVATAR_HEIGHT }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 1c3df3210c..8f59d46cc8 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -205,6 +205,16 @@ void setupPreferences() { // which can't be changed across domain switches. Having these values loaded up when you load the Dialog each time // is a way around this, therefore they're not specified here but in the QML. } + { + auto getter = [=]()->float { return myAvatar->getUserHeight(); }; + auto setter = [=](float value) { myAvatar->setUserHeight(value); }; + auto preference = new SpinnerPreference(AVATAR_TUNING, "User height (meters)", getter, setter); + preference->setMin(1.0f); + preference->setMax(2.2f); + preference->setDecimals(3); + preference->setStep(0.001f); + preferences->addPreference(preference); + } { auto getter = []()->float { return DependencyManager::get()->getEyeClosingThreshold(); }; auto setter = [](float value) { DependencyManager::get()->setEyeClosingThreshold(value); }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 97f83a3053..7d577a1687 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1552,6 +1552,14 @@ void Avatar::ensureInScene(AvatarSharedPointer self, const render::ScenePointer& // returns the avatar height, in meters, includes avatar scale factor. float Avatar::getHeight() const { + + if (QThread::currentThread() != thread()) { + float result = DEFAULT_AVATAR_HEIGHT; + BLOCKING_INVOKE_METHOD(const_cast(this), "getHeight", Q_RETURN_ARG(float, result)); + return result; + } + + // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. // AJT: TODO: I don't know what scale is to use here... getDomainLimitedScale? float avatarScale = getTargetScale(); if (_skeletonModel) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 6ef935ad3d..e070b82e00 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -251,7 +251,11 @@ public: bool isFading() const { return _isFading; } void updateFadingStatus(render::ScenePointer scene); - // returns the avatar height, in meters, includes avatar scale factor. + /**jsdoc + * Provides read only access to the current height of the avatar in world space. + * @function Avatar.getHeight + * @returns {number} height of avatar in meters + */ Q_INVOKABLE float getHeight() const; public slots: From 963ddce7bcf45abe53522b63b70554e0376891f7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 17 Aug 2017 11:08:14 -0700 Subject: [PATCH 04/58] Use eye-height to match user and avatar scales, follow fixes Fix postPhysicsUpdate to properly transform follow displacement into sensor frame. --- interface/src/Application.cpp | 8 +++- interface/src/avatar/MyAvatar.cpp | 33 +++++++++++---- interface/src/avatar/MyAvatar.h | 1 + .../src/scripting/HMDScriptingInterface.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 41 ++++++++++--------- .../src/avatars-renderer/Avatar.h | 8 ++-- libraries/shared/src/AvatarConstants.h | 2 + 7 files changed, 59 insertions(+), 36 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 398b2dbdb4..c07bf81785 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2385,7 +2385,7 @@ void Application::paintGL() { if (isHMDMode()) { mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); _myCamera.setPosition(extractTranslation(camMat)); - _myCamera.setOrientation(glm::quat_cast(camMat)); + _myCamera.setOrientation(glmExtractRotation(camMat)); } else { _myCamera.setPosition(myAvatar->getDefaultEyePosition()); _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); @@ -2393,7 +2393,7 @@ void Application::paintGL() { } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { if (isHMDMode()) { auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); - _myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat))); + _myCamera.setOrientation(glm::normalize(glmExtractRotation(hmdWorldMat))); _myCamera.setPosition(extractTranslation(hmdWorldMat) + myAvatar->getOrientation() * boomOffset); } else { @@ -2501,6 +2501,10 @@ void Application::paintGL() { auto hmdInterface = DependencyManager::get(); float IPDScale = hmdInterface->getIPDScale(); + // scale IPD by height ratio, to make the world seem larger or smaller accordingly. + float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight(); + IPDScale *= heightRatio; + // FIXME we probably don't need to set the projection matrix every frame, // only when the display plugin changes (or in non-HMD modes when the user // changes the FOV manually, which right now I don't think they can. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e574cb78ec..dc9c55243b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -321,7 +321,7 @@ void MyAvatar::centerBody() { // transform this body into world space auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; auto worldBodyPos = extractTranslation(worldBodyMatrix); - auto worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix)); + auto worldBodyRot = glmExtractRotation(worldBodyMatrix); if (_characterController.getState() == CharacterController::State::Ground) { // the avatar's physical aspect thinks it is standing on something @@ -374,7 +374,7 @@ void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) { // transform this body into world space auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; auto worldBodyPos = extractTranslation(worldBodyMatrix); - auto worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix)); + auto worldBodyRot = glmExtractRotation(worldBodyMatrix); // this will become our new position. setPosition(worldBodyPos); @@ -640,7 +640,7 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { } _hmdSensorPosition = newHmdSensorPosition; - _hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix); + _hmdSensorOrientation = glmExtractRotation(hmdSensorMatrix); auto headPose = getControllerPoseInSensorFrame(controller::Action::HEAD); if (headPose.isValid()) { _headControllerFacing = getFacingDir2D(headPose.rotation); @@ -664,9 +664,11 @@ void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeV // update sensor to world matrix from current body position and hmd sensor. // This is so the correct camera can be used for rendering. void MyAvatar::updateSensorToWorldMatrix() { + // update the sensor mat so that the body position will end up in the desired // position when driven from the head. - glm::mat4 desiredMat = createMatFromQuatAndPos(getOrientation(), getPosition()); + float heightRatio = getEyeHeight() / getUserEyeHeight(); + glm::mat4 desiredMat = createMatFromScaleQuatAndPos(glm::vec3(heightRatio), getOrientation(), getPosition()); _sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix); lateUpdatePalms(); @@ -2615,7 +2617,9 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // Y_180 is necessary because rig is z forward and hmdOrientation is -z forward glm::vec3 headToNeck = headOrientation * Quaternions::Y_180 * (localNeck - localHead); glm::vec3 neckToRoot = headOrientationYawOnly * Quaternions::Y_180 * -localNeck; - glm::vec3 bodyPos = headPosition + headToNeck + neckToRoot; + + float invHeightRatio = getUserEyeHeight() / getEyeHeight(); + glm::vec3 bodyPos = headPosition + invHeightRatio * (headToNeck + neckToRoot); return createMatFromQuatAndPos(headOrientationYawOnly, bodyPos); } @@ -2628,6 +2632,12 @@ void MyAvatar::setUserHeight(float value) { _userHeight.set(value); } +float MyAvatar::getUserEyeHeight() const { + float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float userHeight = _userHeight.get(); + return userHeight - userHeight * ratio; +} + glm::vec3 MyAvatar::getPositionForAudio() { switch (_audioListenerMode) { case AudioListenerMode::FROM_HEAD: @@ -2798,6 +2808,10 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix; AnimPose followWorldPose(currentWorldMatrix); + + // remove scale present from sensorToWorldMatrix + followWorldPose.scale() = glm::vec3(1.0f); + if (isActive(Rotation)) { followWorldPose.rot() = glmExtractRotation(desiredWorldMatrix); } @@ -2822,11 +2836,12 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co // apply follow displacement to the body matrix. glm::vec3 worldLinearDisplacement = myAvatar.getCharacterController()->getFollowLinearDisplacement(); glm::quat worldAngularDisplacement = myAvatar.getCharacterController()->getFollowAngularDisplacement(); - glm::quat sensorToWorld = glmExtractRotation(myAvatar.getSensorToWorldMatrix()); - glm::quat worldToSensor = glm::inverse(sensorToWorld); - glm::vec3 sensorLinearDisplacement = worldToSensor * worldLinearDisplacement; - glm::quat sensorAngularDisplacement = worldToSensor * worldAngularDisplacement * sensorToWorld; + glm::mat4 sensorToWorldMatrix = myAvatar.getSensorToWorldMatrix(); + glm::mat4 worldToSensorMatrix = glm::inverse(sensorToWorldMatrix); + + glm::vec3 sensorLinearDisplacement = transformVectorFast(worldToSensorMatrix, worldLinearDisplacement); + glm::quat sensorAngularDisplacement = glmExtractRotation(worldToSensorMatrix) * worldAngularDisplacement * glmExtractRotation(sensorToWorldMatrix); glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix), sensorLinearDisplacement + extractTranslation(currentBodyMatrix)); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 70385cbaf2..3b87980018 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -527,6 +527,7 @@ public: float getUserHeight() const; void setUserHeight(float value); + float getUserEyeHeight() const; public slots: void increaseSize(); diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 93c3a7652e..39d3164f1f 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -151,7 +151,7 @@ glm::vec3 HMDScriptingInterface::getPosition() const { glm::quat HMDScriptingInterface::getOrientation() const { if (qApp->getActiveDisplayPlugin()->isHmd()) { - return glm::normalize(glm::quat_cast(getWorldHMDMatrix())); + return glmExtractRotation(getWorldHMDMatrix()); } return glm::quat(); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 7d577a1687..17e3cd82bb 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1550,47 +1550,48 @@ void Avatar::ensureInScene(AvatarSharedPointer self, const render::ScenePointer& } } -// returns the avatar height, in meters, includes avatar scale factor. -float Avatar::getHeight() const { +float Avatar::getEyeHeight() const { if (QThread::currentThread() != thread()) { - float result = DEFAULT_AVATAR_HEIGHT; + float result = DEFAULT_AVATAR_EYE_HEIGHT; BLOCKING_INVOKE_METHOD(const_cast(this), "getHeight", Q_RETURN_ARG(float, result)); return result; } // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. - // AJT: TODO: I don't know what scale is to use here... getDomainLimitedScale? - float avatarScale = getTargetScale(); + float avatarScale = getUniformScale(); if (_skeletonModel) { auto& rig = _skeletonModel->getRig(); int headTopJoint = rig.indexOfJoint("HeadTop_End"); int headJoint = rig.indexOfJoint("Head"); int eyeJoint = rig.indexOfJoint("LeftEye") != -1 ? rig.indexOfJoint("LeftEye") : rig.indexOfJoint("RightEye"); int toeJoint = rig.indexOfJoint("LeftToeBase") != -1 ? rig.indexOfJoint("LeftToeBase") : rig.indexOfJoint("RightToeBase"); - if (headTopJoint >= 0 && toeJoint >= 0) { - // measure toe to top of head. Note: default poses already include avatar scale factor - float height = rig.getAbsoluteDefaultPose(headTopJoint).trans().y - rig.getAbsoluteDefaultPose(toeJoint).trans().y; - return height; - } else if (eyeJoint >= 0 && toeJoint >= 0) { - // measure from eyes to toes + the average eye to top of head distance. - const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + if (eyeJoint >= 0 && toeJoint >= 0) { + // measure from eyes to toes. float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y - rig.getAbsoluteDefaultPose(toeJoint).trans().y; - return eyeHeight + eyeHeight * ratio; - } else if (headTopJoint >= 0) { - return rig.getAbsoluteDefaultPose(headTopJoint).trans().y; + return eyeHeight; } else if (eyeJoint >= 0) { - const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + // measure eyes to y = 0 plane. float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y; - return eyeHeight + eyeHeight * ratio; + return eyeHeight; + } else if (headTopJoint >= 0 && toeJoint >= 0) { + // measure toe to top of head. Note: default poses already include avatar scale factor + const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float height = rig.getAbsoluteDefaultPose(headTopJoint).trans().y - rig.getAbsoluteDefaultPose(toeJoint).trans().y; + return height - height * ratio; + } else if (headTopJoint >= 0) { + const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + float height = rig.getAbsoluteDefaultPose(headTopJoint).trans().y; + return height - height * ratio; } else if (headJoint >= 0) { - const float ratio = DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; + const float DEFAULT_AVATAR_NECK_TO_EYE = DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; + const float ratio = DEFAULT_AVATAR_NECK_TO_EYE / DEFAULT_AVATAR_NECK_HEIGHT; float neckHeight = rig.getAbsoluteDefaultPose(headJoint).trans().y; return neckHeight + neckHeight * ratio; } else { - return avatarScale * DEFAULT_AVATAR_HEIGHT; + return avatarScale * DEFAULT_AVATAR_EYE_HEIGHT; } } else { - return avatarScale * DEFAULT_AVATAR_HEIGHT; + return avatarScale * DEFAULT_AVATAR_EYE_HEIGHT; } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index e070b82e00..a7e3076f10 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -252,11 +252,11 @@ public: void updateFadingStatus(render::ScenePointer scene); /**jsdoc - * Provides read only access to the current height of the avatar in world space. - * @function Avatar.getHeight - * @returns {number} height of avatar in meters + * Provides read only access to the current eye height of the avatar. + * @function Avatar.getEyeHeight + * @returns {number} eye height of avatar in meters */ - Q_INVOKABLE float getHeight() const; + Q_INVOKABLE float getEyeHeight() const; public slots: diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index b1ff1872e7..5849897dde 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -16,6 +16,8 @@ const float DEFAULT_AVATAR_HEIGHT = 1.755f; // meters const float DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD = 0.11f; // meters const float DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD = 0.185f; // meters +const float DEFAULT_AVATAR_NECK_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD; +const float DEFAULT_AVATAR_EYE_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; // Used when avatar is missing joints... (avatar space) static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; From 8e56404c40f7ef78e59ac761221c74e7285e7c77 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 18 Aug 2017 16:26:50 -0700 Subject: [PATCH 05/58] Fixes for flying and rotation re-centering in wikiplanet --- interface/src/Application.cpp | 9 ++- interface/src/avatar/MyAvatar.cpp | 59 ++++--------------- interface/src/avatar/MyAvatar.h | 2 - libraries/physics/src/CharacterController.cpp | 10 +--- 4 files changed, 23 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c07bf81785..560cb8c00d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2497,7 +2497,8 @@ void Application::paintGL() { _myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection())); renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; - auto baseProjection = renderArgs.getViewFrustum().getProjection(); + mat4 eyeProjections[2]; + auto hmdInterface = DependencyManager::get(); float IPDScale = hmdInterface->getIPDScale(); @@ -2505,6 +2506,12 @@ void Application::paintGL() { float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight(); IPDScale *= heightRatio; + // adjust near clip plane by heightRatio + auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), + renderArgs.getViewFrustum().getAspectRatio(), + renderArgs.getViewFrustum().getNearClip() * heightRatio, + renderArgs.getViewFrustum().getFarClip()); + // FIXME we probably don't need to set the projection matrix every frame, // only when the display plugin changes (or in non-HMD modes when the user // changes the FOV manually, which right now I don't think they can. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dc9c55243b..11af475ab4 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1884,38 +1884,8 @@ void MyAvatar::updateOrientation(float deltaTime) { snapTurn = true; } - // use head/HMD orientation to turn while flying - if (getCharacterController()->getState() == CharacterController::State::Hover) { - - // This is the direction the user desires to fly in. - glm::vec3 desiredFacing = getMyHead()->getHeadOrientation() * Vectors::UNIT_Z; - desiredFacing.y = 0.0f; - - // This is our reference frame, it is captured when the user begins to move. - glm::vec3 referenceFacing = transformVectorFast(_sensorToWorldMatrix, _hoverReferenceCameraFacing); - referenceFacing.y = 0.0f; - referenceFacing = glm::normalize(referenceFacing); - glm::vec3 referenceRight(referenceFacing.z, 0.0f, -referenceFacing.x); - const float HOVER_FLY_ROTATION_PERIOD = 0.5f; - float tau = glm::clamp(deltaTime / HOVER_FLY_ROTATION_PERIOD, 0.0f, 1.0f); - - // new facing is a linear interpolation between the desired and reference vectors. - glm::vec3 newFacing = glm::normalize((1.0f - tau) * referenceFacing + tau * desiredFacing); - - // calcualte the signed delta yaw angle to apply so that we match our newFacing. - float sign = copysignf(1.0f, glm::dot(desiredFacing, referenceRight)); - float deltaAngle = sign * acosf(glm::clamp(glm::dot(referenceFacing, newFacing), -1.0f, 1.0f)); - - // speedFactor is 0 when we are at rest adn 1.0 when we are at max flying speed. - const float MAX_FLYING_SPEED = 30.0f; - float speedFactor = glm::min(glm::length(getVelocity()) / MAX_FLYING_SPEED, 1.0f); - - // apply our delta, but scale it by the speed factor, so we turn faster when we are flying faster. - totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI)); - } - - // Use head/HMD roll to turn while walking or flying, but not when standing still - if (qApp->isHMDMode() && _hmdRollControlEnabled && hasDriveInput()) { + // Use head/HMD roll to turn while flying, but not when standing still. + if (qApp->isHMDMode() && getCharacterController()->getState() == CharacterController::State::Hover && _hmdRollControlEnabled && hasDriveInput()) { // Turn with head roll. const float MIN_CONTROL_SPEED = 0.01f; float speed = glm::length(getVelocity()); @@ -2067,18 +2037,6 @@ void MyAvatar::updatePosition(float deltaTime) { _characterController.setStepUpEnabled(result.walkable); } } - - // capture the head rotation, in sensor space, when the user first indicates they would like to move/fly. - if (!_hoverReferenceCameraFacingIsCaptured && - (fabs(getDriveKey(TRANSLATE_Z)) > 0.1f || fabs(getDriveKey(TRANSLATE_X)) > 0.1f)) { - _hoverReferenceCameraFacingIsCaptured = true; - // transform the camera facing vector into sensor space. - _hoverReferenceCameraFacing = transformVectorFast(glm::inverse(_sensorToWorldMatrix), - getMyHead()->getHeadOrientation() * Vectors::UNIT_Z); - } else if (_hoverReferenceCameraFacingIsCaptured && - (fabs(getDriveKey(TRANSLATE_Z)) <= 0.1f && fabs(getDriveKey(TRANSLATE_X)) <= 0.1f)) { - _hoverReferenceCameraFacingIsCaptured = false; - } } void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) { @@ -2756,7 +2714,6 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co } bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - // -z axis of currentBodyMatrix in world space. glm::vec3 forward = glm::normalize(glm::vec3(-currentBodyMatrix[0][2], -currentBodyMatrix[1][2], -currentBodyMatrix[2][2])); // x axis of currentBodyMatrix in world space. @@ -2780,7 +2737,6 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, } bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - const float CYLINDER_TOP = 0.1f; const float CYLINDER_BOTTOM = -1.5f; @@ -2807,6 +2763,16 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * desiredBodyMatrix; glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix; + glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f); + glm::vec4 GREEN(0.0f, 1.0f, 0.0f, 1.0f); + glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); + glm::vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); + glm::vec4 desiredColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(desiredBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? RED : GREEN; + glm::vec4 currentColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(currentBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? BLUE : WHITE; + + DebugDraw::getInstance().addMarker("desiredBody", glmExtractRotation(desiredWorldMatrix), extractTranslation(desiredWorldMatrix), desiredColor); + DebugDraw::getInstance().addMarker("currentBody", glmExtractRotation(currentWorldMatrix), extractTranslation(currentWorldMatrix), currentColor); + AnimPose followWorldPose(currentWorldMatrix); // remove scale present from sensorToWorldMatrix @@ -2846,7 +2812,6 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(const MyAvatar& myAvatar, co glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix), sensorLinearDisplacement + extractTranslation(currentBodyMatrix)); return newBodyMat; - } else { return currentBodyMatrix; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3b87980018..3d335d0a19 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -774,8 +774,6 @@ private: AtRestDetector _hmdAtRestDetector; bool _lastIsMoving { false }; - bool _hoverReferenceCameraFacingIsCaptured { false }; - glm::vec3 _hoverReferenceCameraFacing { 0.0f, 0.0f, -1.0f }; // hmd sensor space // all poses are in sensor-frame std::map _controllerPoseMap; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 9a7abc4e98..becc6c10bf 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -265,13 +265,9 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar btVector3 endPos = startPos + linearDisplacement; btQuaternion startRot = bodyTransform.getRotation(); - glm::vec2 currentFacing = getFacingDir2D(bulletToGLM(startRot)); - glm::vec2 currentRight(currentFacing.y, -currentFacing.x); - glm::vec2 desiredFacing = getFacingDir2D(bulletToGLM(_followDesiredBodyTransform.getRotation())); - float deltaAngle = acosf(glm::clamp(glm::dot(currentFacing, desiredFacing), -1.0f, 1.0f)); - float angularSpeed = deltaAngle / _followTimeRemaining; - float sign = copysignf(1.0f, glm::dot(desiredFacing, currentRight)); - btQuaternion angularDisplacement = btQuaternion(btVector3(0.0f, 1.0f, 0.0f), sign * angularSpeed * dt); + btQuaternion deltaRot = _followDesiredBodyTransform.getRotation() * startRot.inverse(); + float angularSpeed = deltaRot.getAngle() / _followTimeRemaining; + btQuaternion angularDisplacement = btQuaternion(deltaRot.getAxis(), angularSpeed * dt); btQuaternion endRot = angularDisplacement * startRot; // in order to accumulate displacement of avatar position, we need to take _shapeLocalOffset into account. From cd6d2173cce0b8935c29291164294f084e16c91b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 21 Aug 2017 18:09:58 -0700 Subject: [PATCH 06/58] Bug fix for follow rotation of CharacterController --- libraries/physics/src/CharacterController.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index becc6c10bf..c48df4bf8d 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -265,7 +265,11 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar btVector3 endPos = startPos + linearDisplacement; btQuaternion startRot = bodyTransform.getRotation(); - btQuaternion deltaRot = _followDesiredBodyTransform.getRotation() * startRot.inverse(); + btQuaternion desiredRot = _followDesiredBodyTransform.getRotation(); + if (desiredRot.dot(startRot) < 0.0f) { + desiredRot = -desiredRot; + } + btQuaternion deltaRot = desiredRot * startRot.inverse(); float angularSpeed = deltaRot.getAngle() / _followTimeRemaining; btQuaternion angularDisplacement = btQuaternion(deltaRot.getAxis(), angularSpeed * dt); btQuaternion endRot = angularDisplacement * startRot; From de2262968eb74e4cc60983b1d2a2201b355fa7af Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 22 Aug 2017 09:44:32 -0700 Subject: [PATCH 07/58] Fix for CAMERA_RELATIVE controllers with sensor scale --- interface/src/avatar/MyAvatar.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 11af475ab4..d13fa1cc24 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2869,15 +2869,16 @@ glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& c cameraWorldMatrix *= createMatFromScaleQuatAndPos(vec3(-1.0f, 1.0f, 1.0f), glm::quat(), glm::vec3()); } - // compute a NEW sensorToWorldMatrix for the camera. - // The equation is cameraWorldMatrix = cameraSensorToWorldMatrix * _hmdSensorMatrix. - // here we solve for the unknown cameraSensorToWorldMatrix. - glm::mat4 cameraSensorToWorldMatrix = cameraWorldMatrix * glm::inverse(getHMDSensorMatrix()); + // move the camera into sensor space. + glm::mat4 cameraSensorMatrix = glm::inverse(getSensorToWorldMatrix()) * cameraWorldMatrix; - // Using the new cameraSensorToWorldMatrix, compute where the controller is in world space. - glm::mat4 controllerWorldMatrix = cameraSensorToWorldMatrix * controllerSensorMatrix; + // measure the offset from the hmd and the camera, in sensor space + glm::mat4 delta = cameraSensorMatrix * glm::inverse(getHMDSensorMatrix()); - // move it into avatar space + // apply the delta offset to the controller, in sensor space, then transform it into world space. + glm::mat4 controllerWorldMatrix = getSensorToWorldMatrix() * delta * controllerSensorMatrix; + + // transform controller into avatar space glm::mat4 avatarMatrix = createMatFromQuatAndPos(getOrientation(), getPosition()); return glm::inverse(avatarMatrix) * controllerWorldMatrix; } From ffdb10681e28c2f78ae70773215832bbfa198f4d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 22 Aug 2017 11:07:04 -0700 Subject: [PATCH 08/58] Fix for laser rendering and positioning with sensor scale --- interface/src/Application.cpp | 24 +++++++++++++++--------- interface/src/avatar/MyAvatar.cpp | 9 +++++++-- interface/src/avatar/MyAvatar.h | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 560cb8c00d..93aa5791d0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2475,6 +2475,13 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } + auto hmdInterface = DependencyManager::get(); + float ipdScale = hmdInterface->getIPDScale(); + + // scale IPD by height ratio, to make the world seem larger or smaller accordingly. + float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight(); + ipdScale *= heightRatio; + mat4 eyeProjections[2]; { PROFILE_RANGE(render, "/mainRender"); @@ -2499,13 +2506,6 @@ void Application::paintGL() { mat4 eyeOffsets[2]; mat4 eyeProjections[2]; - auto hmdInterface = DependencyManager::get(); - float IPDScale = hmdInterface->getIPDScale(); - - // scale IPD by height ratio, to make the world seem larger or smaller accordingly. - float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight(); - IPDScale *= heightRatio; - // adjust near clip plane by heightRatio auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), renderArgs.getViewFrustum().getAspectRatio(), @@ -2524,7 +2524,7 @@ void Application::paintGL() { // Grab the translation vec3 eyeOffset = glm::vec3(eyeToHead[3]); // Apply IPD scaling - mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale); + mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale); eyeOffsets[eye] = eyeOffsetTransform; eyeProjections[eye] = displayPlugin->getEyeProjection(eye, baseProjection); }); @@ -2544,8 +2544,14 @@ void Application::paintGL() { PerformanceTimer perfTimer("postComposite"); renderArgs._batch = &postCompositeBatch; renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height())); - renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView()); for_each_eye([&](Eye eye) { + + // apply eye offset and IPD scale to the view matrix + mat4 eyeToHead = displayPlugin->getEyeToHeadTransform(eye); + vec3 eyeOffset = glm::vec3(eyeToHead[3]); + mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale); + renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView() * eyeOffsetTransform); + renderArgs._batch->setProjectionTransform(eyeProjections[eye]); _overlays.render3DHUDOverlays(&renderArgs); }); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index d13fa1cc24..4c79554a69 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -667,8 +667,8 @@ void MyAvatar::updateSensorToWorldMatrix() { // update the sensor mat so that the body position will end up in the desired // position when driven from the head. - float heightRatio = getEyeHeight() / getUserEyeHeight(); - glm::mat4 desiredMat = createMatFromScaleQuatAndPos(glm::vec3(heightRatio), getOrientation(), getPosition()); + float sensorToWorldScale = getEyeHeight() / getUserEyeHeight(); + glm::mat4 desiredMat = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), getOrientation(), getPosition()); _sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix); lateUpdatePalms(); @@ -679,6 +679,7 @@ void MyAvatar::updateSensorToWorldMatrix() { } _sensorToWorldMatrixCache.set(_sensorToWorldMatrix); + _sensorToWorldScaleCache.set(sensorToWorldScale); updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache); updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache); @@ -2872,6 +2873,10 @@ glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& c // move the camera into sensor space. glm::mat4 cameraSensorMatrix = glm::inverse(getSensorToWorldMatrix()) * cameraWorldMatrix; + // cancel out scale + glm::vec3 scale = extractScale(cameraSensorMatrix); + cameraSensorMatrix = glm::scale(cameraSensorMatrix, 1.0f / scale); + // measure the offset from the hmd and the camera, in sensor space glm::mat4 delta = cameraSensorMatrix * glm::inverse(getHMDSensorMatrix()); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3d335d0a19..ecd7be2b7b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -708,7 +708,7 @@ private: float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT }; float _lastDrivenSpeed { 0.0f }; - // working copies -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access + // working copy -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access glm::mat4 _sensorToWorldMatrix { glm::mat4() }; // cache of the current HMD sensor position and orientation in sensor space. From d62a0ea8ff7e1c0e63586ec104ed37570fc5b587 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 22 Aug 2017 11:43:39 -0700 Subject: [PATCH 09/58] Correct controller offsets with sensor scaling --- interface/src/Application.cpp | 8 ++++---- interface/src/avatar/MyAvatar.cpp | 5 ++--- libraries/avatars/src/AvatarData.cpp | 5 +++++ libraries/avatars/src/AvatarData.h | 3 +++ scripts/system/libraries/controllers.js | 17 +++++++++-------- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 93aa5791d0..e73afddd3a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2478,9 +2478,9 @@ void Application::paintGL() { auto hmdInterface = DependencyManager::get(); float ipdScale = hmdInterface->getIPDScale(); - // scale IPD by height ratio, to make the world seem larger or smaller accordingly. - float heightRatio = getMyAvatar()->getEyeHeight() / getMyAvatar()->getUserEyeHeight(); - ipdScale *= heightRatio; + // scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly. + float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); + ipdScale *= sensorToWorldScale; mat4 eyeProjections[2]; { @@ -2509,7 +2509,7 @@ void Application::paintGL() { // adjust near clip plane by heightRatio auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), renderArgs.getViewFrustum().getAspectRatio(), - renderArgs.getViewFrustum().getNearClip() * heightRatio, + renderArgs.getViewFrustum().getNearClip() * sensorToWorldScale, renderArgs.getViewFrustum().getFarClip()); // FIXME we probably don't need to set the projection matrix every frame, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4c79554a69..a7f60594a8 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -679,7 +679,6 @@ void MyAvatar::updateSensorToWorldMatrix() { } _sensorToWorldMatrixCache.set(_sensorToWorldMatrix); - _sensorToWorldScaleCache.set(sensorToWorldScale); updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache); updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache); @@ -2577,8 +2576,8 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { glm::vec3 headToNeck = headOrientation * Quaternions::Y_180 * (localNeck - localHead); glm::vec3 neckToRoot = headOrientationYawOnly * Quaternions::Y_180 * -localNeck; - float invHeightRatio = getUserEyeHeight() / getEyeHeight(); - glm::vec3 bodyPos = headPosition + invHeightRatio * (headToNeck + neckToRoot); + float invSensorToWorldScale = getUserEyeHeight() / getEyeHeight(); + glm::vec3 bodyPos = headPosition + invSensorToWorldScale * (headToNeck + neckToRoot); return createMatFromQuatAndPos(headOrientationYawOnly, bodyPos); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 9570056353..7fcae47f67 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2401,6 +2401,11 @@ glm::mat4 AvatarData::getSensorToWorldMatrix() const { return _sensorToWorldMatrixCache.get(); } +// thread-safe +float AvatarData::getSensorToWorldScale() const { + return extractUniformScale(_sensorToWorldMatrixCache.get()); +} + // thread-safe glm::mat4 AvatarData::getControllerLeftHandMatrix() const { return _controllerLeftHandMatrixCache.get(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 322dbe9be5..9eb1c37a15 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -385,6 +385,8 @@ class AvatarData : public QObject, public SpatiallyNestable { Q_PROPERTY(glm::mat4 controllerLeftHandMatrix READ getControllerLeftHandMatrix) Q_PROPERTY(glm::mat4 controllerRightHandMatrix READ getControllerRightHandMatrix) + Q_PROPERTY(float sensorToWorldScale READ getSensorToWorldScale) + public: virtual QString getName() const override { return QString("Avatar:") + _displayName; } @@ -617,6 +619,7 @@ public: // thread safe Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const; + Q_INVOKABLE float getSensorToWorldScale() const; Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const; Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const; diff --git a/scripts/system/libraries/controllers.js b/scripts/system/libraries/controllers.js index 75bca34ed6..dd73aa7f8d 100644 --- a/scripts/system/libraries/controllers.js +++ b/scripts/system/libraries/controllers.js @@ -19,14 +19,15 @@ getGrabCommunications = function getFarGrabCommunications() { var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral getGrabPointSphereOffset = function(handController) { - if (handController === Controller.Standard.RightHand) { - return GRAB_POINT_SPHERE_OFFSET; + var offset = GRAB_POINT_SPHERE_OFFSET; + if (handController === Controller.Standard.LeftHand) { + offset = { + x: -GRAB_POINT_SPHERE_OFFSET.x, + y: GRAB_POINT_SPHERE_OFFSET.y, + z: GRAB_POINT_SPHERE_OFFSET.z + }; } - return { - x: GRAB_POINT_SPHERE_OFFSET.x * -1, - y: GRAB_POINT_SPHERE_OFFSET.y, - z: GRAB_POINT_SPHERE_OFFSET.z - }; + return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); }; // controllerWorldLocation is where the controller would be, in-world, with an added offset @@ -53,7 +54,7 @@ getControllerWorldLocation = function (handController, doOffset) { } else if (!HMD.isHandControllerAvailable()) { // NOTE: keep this offset in sync with scripts/system/controllers/handControllerPointer.js:493 - var VERTICAL_HEAD_LASER_OFFSET = 0.1; + var VERTICAL_HEAD_LASER_OFFSET = 0.1 * MyAvatar.sensorToWorldScale; position = Vec3.sum(Camera.position, Vec3.multiplyQbyV(Camera.orientation, {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0})); orientation = Quat.multiply(Camera.orientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })); valid = true; From 5042b900520874bad449529a1b67e801af9054e6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 24 Aug 2017 10:47:48 -0700 Subject: [PATCH 10/58] Rig: Fix for debug mode assert --- libraries/animation/src/Rig.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1b91737364..6ae83b3433 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1129,7 +1129,6 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh glm::vec3 localPoint = shapePose.inverse().xformPoint(point); // Only works for 14-dop shape infos. - assert(shapeInfo.dots.size() == DOP14_COUNT); if (shapeInfo.dots.size() != DOP14_COUNT) { return false; } From 246097b65ebb2b10aef3d657a559f34858b27570 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 24 Aug 2017 11:18:38 -0700 Subject: [PATCH 11/58] WIP support for scale within SpatiallyNestable class. currently disabled by the SPATIALLY_NESTABLE_SCALE_SUPPORT pre-processor symbol. --- .../src/avatars-renderer/Avatar.cpp | 28 ++++++++++++++++--- .../src/avatars-renderer/Avatar.h | 3 ++ libraries/shared/src/SpatiallyNestable.cpp | 19 ++++++++++++- libraries/shared/src/SpatiallyNestable.h | 3 ++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 17e3cd82bb..0222a4c604 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -987,14 +987,15 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const { index += numeric_limits::max() + 1; // 65536 } - switch(index) { + switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); bool success; Transform avatarTransform; Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - return glmExtractRotation(invAvatarMat * sensorToWorldMatrix); + glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + return glmExtractRotation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix()); @@ -1027,14 +1028,15 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { index += numeric_limits::max() + 1; // 65536 } - switch(index) { + switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); bool success; Transform avatarTransform; Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - return extractTranslation(invAvatarMat * sensorToWorldMatrix); + glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + return extractTranslation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix()); @@ -1062,6 +1064,24 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } } +#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT +glm::vec3 Avatar::getAbsoluteJointScaleInObjectFrame(int index) const { + if (index < 0) { + index += numeric_limits::max() + 1; // 65536 + } + + // only sensor to world matrix has non identity scale. + switch (index) { + case SENSOR_TO_WORLD_MATRIX_INDEX: { + glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); + return extractScale(sensorToWorldMatrix); + } + default: + return AvatarData::getAbsoluteJointScaleInObjectFrame(index); + } +} +#endif + void Avatar::invalidateJointIndicesCache() const { QWriteLocker writeLock(&_modelJointIndicesCacheLock); _modelJointsCached = false; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a7e3076f10..d5f427c561 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -149,6 +149,9 @@ public: */ Q_INVOKABLE virtual glm::vec3 getAbsoluteDefaultJointTranslationInObjectFrame(int index) const; +#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT + virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; +#endif 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 { return false; } diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index fc189c5e3e..43275fa122 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -13,6 +13,7 @@ #include "DependencyManager.h" #include "SharedUtil.h" +#include "StreamUtils.h" #include "SharedLogging.h" #include "SpatiallyNestable.h" @@ -82,8 +83,12 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const return result; } if (parent) { +#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT + result = parent->getTransform(_parentJointIndex, success, depth + 1); +#else Transform parentTransform = parent->getTransform(_parentJointIndex, success, depth + 1); result = parentTransform.setScale(1.0f); // TODO: scaling +#endif } return result; } @@ -179,7 +184,9 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } +#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT parentTransform.setScale(1.0f); // TODO: scale +#endif } success = true; @@ -219,7 +226,9 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, if (!success) { return glm::quat(); } +#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT parentTransform.setScale(1.0f); // TODO: scale +#endif } success = true; @@ -291,7 +300,9 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } +#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT parentTransform.setScale(1.0f); // TODO: scale +#endif } success = true; @@ -633,7 +644,9 @@ const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, i } Transform worldTransform = getTransform(success, depth); - worldTransform.setScale(1.0f); // TODO -- scale; +#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT + worldTransform.setScale(1.0f); // TODO: scale +#endif if (!success) { return jointInWorldFrame; } @@ -904,6 +917,10 @@ const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jo Transform jointTransformInObjectFrame; glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex); glm::quat orientation = getAbsoluteJointRotationInObjectFrame(jointIndex); +#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT + glm::vec3 scale = getAbsoluteJointScaleInObjectFrame(jointIndex); + jointTransformInObjectFrame.setScale(scale); +#endif jointTransformInObjectFrame.setRotation(orientation); jointTransformInObjectFrame.setTranslation(position); return jointTransformInObjectFrame; diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 78a014d7c1..b58c1d346c 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -146,6 +146,9 @@ public: // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; +#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT + virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const { return glm::vec3(1.0f); } +#endif virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { return glm::vec3(); } virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { return false; } From dd9ee28b18ab93e326987bc592dc2fc605fb96d8 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 25 Aug 2017 10:10:23 -0700 Subject: [PATCH 12/58] Adjust avatar walking and flying speed based on sensor scale factor --- interface/src/avatar/MyAvatar.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a7f60594a8..c965b2108f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1979,17 +1979,17 @@ void MyAvatar::updateActionMotor(float deltaTime) { if (state == CharacterController::State::Hover) { // we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed float motorSpeed = glm::length(_actionMotorVelocity); - float finalMaxMotorSpeed = getUniformScale() * MAX_ACTION_MOTOR_SPEED; + float finalMaxMotorSpeed = getSensorToWorldScale() * MAX_ACTION_MOTOR_SPEED; float speedGrowthTimescale = 2.0f; float speedIncreaseFactor = 1.8f; motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f) * speedIncreaseFactor; - const float maxBoostSpeed = getUniformScale() * MAX_BOOST_SPEED; + const float maxBoostSpeed = getSensorToWorldScale() * MAX_BOOST_SPEED; if (_isPushing) { if (motorSpeed < maxBoostSpeed) { // an active action motor should never be slower than this float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed; - motorSpeed += MIN_AVATAR_SPEED * boostCoefficient; + motorSpeed += getSensorToWorldScale() * MIN_AVATAR_SPEED * boostCoefficient; } else if (motorSpeed > finalMaxMotorSpeed) { motorSpeed = finalMaxMotorSpeed; } @@ -1997,7 +1997,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { _actionMotorVelocity = motorSpeed * direction; } else { // we're interacting with a floor --> simple horizontal speed and exponential decay - _actionMotorVelocity = MAX_WALKING_SPEED * direction; + _actionMotorVelocity = getSensorToWorldScale() * MAX_WALKING_SPEED * direction; } float boomChange = getDriveKey(ZOOM); @@ -2011,22 +2011,24 @@ void MyAvatar::updatePosition(float deltaTime) { } vec3 velocity = getVelocity(); + float sensorToWorldScale = getSensorToWorldScale(); + float sensorToWorldScale2 = sensorToWorldScale * sensorToWorldScale; const float MOVING_SPEED_THRESHOLD_SQUARED = 0.0001f; // 0.01 m/s if (!_characterController.isEnabledAndReady()) { // _characterController is not in physics simulation but it can still compute its target velocity updateMotors(); _characterController.computeNewVelocity(deltaTime, velocity); - float speed2 = glm::length2(velocity); - if (speed2 > MIN_AVATAR_SPEED_SQUARED) { + float speed2 = glm::length(velocity); + if (speed2 > sensorToWorldScale2 * MIN_AVATAR_SPEED_SQUARED) { // update position ourselves applyPositionDelta(deltaTime * velocity); } measureMotionDerivatives(deltaTime); - _moving = speed2 > MOVING_SPEED_THRESHOLD_SQUARED; + _moving = speed2 > sensorToWorldScale2 * MOVING_SPEED_THRESHOLD_SQUARED; } else { float speed2 = glm::length2(velocity); - _moving = speed2 > MOVING_SPEED_THRESHOLD_SQUARED; + _moving = speed2 > sensorToWorldScale2 * MOVING_SPEED_THRESHOLD_SQUARED; if (_moving) { // scan for walkability From e0ff7f5f403a9d18178c6718574215fb0fc9596f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 25 Aug 2017 10:47:54 -0700 Subject: [PATCH 13/58] Moved speed constants into AvatarConstants.h --- interface/src/avatar/MyAvatar.cpp | 17 ++++------ libraries/shared/src/AvatarConstants.h | 45 ++++++++++++++------------ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c965b2108f..9e82351f72 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -64,18 +64,13 @@ using namespace std; const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; -const float MAX_WALKING_SPEED = 2.6f; // human walking speed -const float MAX_BOOST_SPEED = 0.5f * MAX_WALKING_SPEED; // action motor gets additive boost below this speed -const float MIN_AVATAR_SPEED = 0.05f; -const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // speed is set to zero below this - const float YAW_SPEED_DEFAULT = 100.0f; // degrees/sec const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec -// TODO: normalize avatar speed for standard avatar size, then scale all motion logic -// to properly follow avatar size. -float MAX_AVATAR_SPEED = 30.0f; -float MAX_ACTION_MOTOR_SPEED = MAX_AVATAR_SPEED; +const float MAX_BOOST_SPEED = 0.5f * DEFAULT_AVATAR_MAX_WALKING_SPEED; // action motor gets additive boost below this speed +const float MIN_AVATAR_SPEED = 0.05f; +const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // speed is set to zero below this + float MIN_SCRIPTED_MOTOR_TIMESCALE = 0.005f; float DEFAULT_SCRIPTED_MOTOR_TIMESCALE = 1.0e6f; const int SCRIPTED_MOTOR_CAMERA_FRAME = 0; @@ -1979,7 +1974,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { if (state == CharacterController::State::Hover) { // we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed float motorSpeed = glm::length(_actionMotorVelocity); - float finalMaxMotorSpeed = getSensorToWorldScale() * MAX_ACTION_MOTOR_SPEED; + float finalMaxMotorSpeed = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_FLYING_SPEED; float speedGrowthTimescale = 2.0f; float speedIncreaseFactor = 1.8f; motorSpeed *= 1.0f + glm::clamp(deltaTime / speedGrowthTimescale, 0.0f, 1.0f) * speedIncreaseFactor; @@ -1997,7 +1992,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { _actionMotorVelocity = motorSpeed * direction; } else { // we're interacting with a floor --> simple horizontal speed and exponential decay - _actionMotorVelocity = getSensorToWorldScale() * MAX_WALKING_SPEED * direction; + _actionMotorVelocity = getSensorToWorldScale() * DEFAULT_AVATAR_MAX_WALKING_SPEED * direction; } float boomChange = getDriveKey(ZOOM); diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 5849897dde..3d1424c029 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -20,26 +20,29 @@ const float DEFAULT_AVATAR_NECK_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_ const float DEFAULT_AVATAR_EYE_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; // Used when avatar is missing joints... (avatar space) -static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; -static const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; -static const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; -static const glm::quat DEFAULT_AVATAR_RIGHTARM_ROT { -0.536241f, 0.536241f, -0.460918f, -0.460918f }; -static const glm::vec3 DEFAULT_AVATAR_LEFTARM_POS { 0.134795f, 0.396349f, -0.0515881f }; -static const glm::quat DEFAULT_AVATAR_LEFTARM_ROT { 0.536257f, 0.536258f, -0.460899f, 0.4609f }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTHAND_POS { -0.72768f, 0.396349f, -0.0515779f }; -static const glm::quat DEFAULT_AVATAR_RIGHTHAND_ROT { 0.479184f, -0.520013f, 0.522537f, 0.476365f}; -static const glm::vec3 DEFAULT_AVATAR_LEFTHAND_POS { 0.727588f, 0.39635f, -0.0515878f }; -static const glm::quat DEFAULT_AVATAR_LEFTHAND_ROT { -0.479181f, -0.52001f, 0.52254f, -0.476369f }; -static const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f }; -static const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f }; -static const glm::quat DEFAULT_AVATAR_SPINE2_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f }; -static const glm::quat DEFAULT_AVATAR_HIPS_ROT { Quaternions::Y_180 }; -static const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.08f, -0.96f, 0.029f}; -static const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.9154590368270874f, -0.005437685176730156f, -0.023744143545627594f }; -static const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f }; -static const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f }; +const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; +const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; +const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; +const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 }; +const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; +const glm::quat DEFAULT_AVATAR_RIGHTARM_ROT { -0.536241f, 0.536241f, -0.460918f, -0.460918f }; +const glm::vec3 DEFAULT_AVATAR_LEFTARM_POS { 0.134795f, 0.396349f, -0.0515881f }; +const glm::quat DEFAULT_AVATAR_LEFTARM_ROT { 0.536257f, 0.536258f, -0.460899f, 0.4609f }; +const glm::vec3 DEFAULT_AVATAR_RIGHTHAND_POS { -0.72768f, 0.396349f, -0.0515779f }; +const glm::quat DEFAULT_AVATAR_RIGHTHAND_ROT { 0.479184f, -0.520013f, 0.522537f, 0.476365f}; +const glm::vec3 DEFAULT_AVATAR_LEFTHAND_POS { 0.727588f, 0.39635f, -0.0515878f }; +const glm::quat DEFAULT_AVATAR_LEFTHAND_ROT { -0.479181f, -0.52001f, 0.52254f, -0.476369f }; +const glm::vec3 DEFAULT_AVATAR_NECK_POS { 0.0f, 0.445f, 0.025f }; +const glm::vec3 DEFAULT_AVATAR_SPINE2_POS { 0.0f, 0.32f, 0.02f }; +const glm::quat DEFAULT_AVATAR_SPINE2_ROT { Quaternions::Y_180 }; +const glm::vec3 DEFAULT_AVATAR_HIPS_POS { 0.0f, 0.0f, 0.0f }; +const glm::quat DEFAULT_AVATAR_HIPS_ROT { Quaternions::Y_180 }; +const glm::vec3 DEFAULT_AVATAR_LEFTFOOT_POS { -0.08f, -0.96f, 0.029f}; +const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.9154590368270874f, -0.005437685176730156f, -0.023744143545627594f }; +const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f }; +const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f }; + +const float DEFAULT_AVATAR_MAX_WALKING_SPEED = 2.6f; // m/s +const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // m/s #endif // hifi_AvatarConstants_h From 4f830cf1dc61d19c39df23fd35265d91fa05832c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 25 Aug 2017 15:34:51 -0700 Subject: [PATCH 14/58] Calculate jump speed based on canonical jump height. --- interface/src/avatar/MyAvatar.cpp | 1 + libraries/physics/src/CharacterController.cpp | 19 ++++++++++--------- libraries/physics/src/CharacterController.h | 4 +++- libraries/shared/src/AvatarConstants.h | 12 ++++++++++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9e82351f72..a91f56ff7d 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1507,6 +1507,7 @@ void MyAvatar::prepareForPhysicsSimulation() { } _characterController.handleChangedCollisionGroup(); _characterController.setParentVelocity(parentVelocity); + _characterController.setScaleFactor(getSensorToWorldScale()); _characterController.setPositionAndOrientation(getPosition(), getOrientation()); auto headPose = getControllerPoseInAvatarFrame(controller::Action::HEAD); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index c48df4bf8d..d2da521768 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -12,14 +12,13 @@ #include "CharacterController.h" #include +#include #include "ObjectMotionState.h" #include "PhysicsHelpers.h" #include "PhysicsLogging.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); -const float JUMP_SPEED = 3.5f; -const float MAX_FALL_HEIGHT = 20.0f; #ifdef DEBUG_STATE_CHANGE #define SET_STATE(desiredState, reason) setState(desiredState, reason) @@ -62,12 +61,11 @@ CharacterController::CharacterMotor::CharacterMotor(const glm::vec3& vel, const } CharacterController::CharacterController() { - _floorDistance = MAX_FALL_HEIGHT; + _floorDistance = _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT; _targetVelocity.setValue(0.0f, 0.0f, 0.0f); _followDesiredBodyTransform.setIdentity(); _followTimeRemaining = 0.0f; - _jumpSpeed = JUMP_SPEED; _state = State::Hover; _isPushingUp = false; _rayHitStartTime = 0; @@ -376,8 +374,7 @@ void CharacterController::updateGravity() { if (_state == State::Hover || collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS) { _gravity = 0.0f; } else { - const float DEFAULT_CHARACTER_GRAVITY = -5.0f; - _gravity = DEFAULT_CHARACTER_GRAVITY; + _gravity = DEFAULT_AVATAR_GRAVITY; } if (_rigidBody) { _rigidBody->setGravity(_gravity * _currentUp); @@ -653,7 +650,7 @@ void CharacterController::updateState() { const btScalar FLY_TO_GROUND_THRESHOLD = 0.1f * _radius; const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight; const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND; - const btScalar MIN_HOVER_HEIGHT = 2.5f; + const btScalar MIN_HOVER_HEIGHT = _scaleFactor * DEFAULT_AVATAR_MIN_HOVER_HEIGHT; const quint64 JUMP_TO_HOVER_PERIOD = 1100 * MSECS_PER_SECOND; // scan for distant floor @@ -663,7 +660,7 @@ void CharacterController::updateState() { btScalar rayLength = _radius; int16_t collisionGroup = computeCollisionGroup(); if (collisionGroup == BULLET_COLLISION_GROUP_MY_AVATAR) { - rayLength += MAX_FALL_HEIGHT; + rayLength += _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT; } else { rayLength += MIN_HOVER_HEIGHT; } @@ -717,11 +714,15 @@ void CharacterController::updateState() { SET_STATE(State::Hover, "no ground"); } else if ((now - _takeoffToInAirStartTime) > TAKE_OFF_TO_IN_AIR_PERIOD) { SET_STATE(State::InAir, "takeoff done"); - velocity += _jumpSpeed * _currentUp; + + // compute jumpSpeed based on the scaled jump height for the default avatar in default gravity. + float jumpSpeed = sqrtf(2.0f * DEFAULT_AVATAR_GRAVITY * _scaleFactor * DEFAULT_AVATAR_JUMP_HEIGHT); + velocity += jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); } break; case State::InAir: { + const float JUMP_SPEED = _scaleFactor * DEFAULT_AVATAR_JUMP_SPEED; if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) { SET_STATE(State::Ground, "hit ground"); } else { diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index bf84d318d4..585eb7d3ed 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -73,6 +73,7 @@ public: void setStepUpEnabled(bool enabled) { _stepUpEnabled = enabled; } void computeNewVelocity(btScalar dt, btVector3& velocity); void computeNewVelocity(btScalar dt, glm::vec3& velocity); + void setScaleFactor(btScalar scaleFactor) { _scaleFactor = scaleFactor; } // HACK for legacy 'thrust' feature void setLinearAcceleration(const glm::vec3& acceleration) { _linearAcceleration = glmToBullet(acceleration); } @@ -185,7 +186,6 @@ protected: btScalar _gravity { 0.0f }; - btScalar _jumpSpeed; btScalar _followTime; btVector3 _followLinearDisplacement; btQuaternion _followAngularDisplacement; @@ -203,6 +203,8 @@ protected: bool _flyingAllowed { true }; bool _collisionlessAllowed { true }; bool _collisionless { false }; + + btScalar _scaleFactor { 1.0f }; }; #endif // hifi_CharacterController_h diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 3d1424c029..a7a80471be 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -42,7 +42,15 @@ const glm::quat DEFAULT_AVATAR_LEFTFOOT_ROT { -0.40167322754859924f, 0.915459036 const glm::vec3 DEFAULT_AVATAR_RIGHTFOOT_POS { 0.08f, -0.96f, 0.029f }; const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.9154615998268127f, 0.0053307069465518f, 0.023696165531873703f }; -const float DEFAULT_AVATAR_MAX_WALKING_SPEED = 2.6f; // m/s -const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // m/s +const float DEFAULT_AVATAR_MAX_WALKING_SPEED = 2.6f; // meters / second +const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second + +const float DEFAULT_AVATAR_GRAVITY = -5.0f; // meters / second^2 +const float DEFAULT_AVATAR_JUMP_SPEED = 3.5f; // meters / second +const float DEFAULT_AVATAR_JUMP_HEIGHT = (DEFAULT_AVATAR_JUMP_SPEED * DEFAULT_AVATAR_JUMP_SPEED) / (2.0f * DEFAULT_AVATAR_GRAVITY); // meters + +const float DEFAULT_AVATAR_FALL_HEIGHT = 20.0f; // meters +const float DEFAULT_AVATAR_MIN_HOVER_HEIGHT = 2.5f; // meters + #endif // hifi_AvatarConstants_h From 3ac09b7716f2da9dc80031df14e3a24376be0977 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 25 Aug 2017 15:48:53 -0700 Subject: [PATCH 15/58] Fix run blends and removed debug draws --- interface/src/avatar/MyAvatar.cpp | 3 --- interface/src/avatar/MySkeletonModel.cpp | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a91f56ff7d..103f0f3348 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2768,9 +2768,6 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat glm::vec4 desiredColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(desiredBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? RED : GREEN; glm::vec4 currentColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(currentBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? BLUE : WHITE; - DebugDraw::getInstance().addMarker("desiredBody", glmExtractRotation(desiredWorldMatrix), extractTranslation(desiredWorldMatrix), desiredColor); - DebugDraw::getInstance().addMarker("currentBody", glmExtractRotation(currentWorldMatrix), extractTranslation(currentWorldMatrix), currentColor); - AnimPose followWorldPose(currentWorldMatrix); // remove scale present from sensorToWorldMatrix diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 89e4368515..a707031167 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -148,7 +148,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::CharacterControllerState ccState = convertCharacterControllerState(myAvatar->getCharacterController()->getState()); - auto velocity = myAvatar->getLocalVelocity(); + auto velocity = myAvatar->getLocalVelocity() / myAvatar->getSensorToWorldScale(); auto position = myAvatar->getLocalPosition(); auto orientation = myAvatar->getLocalOrientation(); _rig.computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState); From 937f4005342a82b08b0536b79757784d03897057 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 25 Aug 2017 18:23:19 -0700 Subject: [PATCH 16/58] Bug fixes for Avatar::getEyeHeight() when no feet joints are present --- interface/src/avatar/MyAvatar.h | 4 +++- .../src/avatars-renderer/Avatar.cpp | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ecd7be2b7b..f33a16f0b8 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -103,6 +103,7 @@ class MyAvatar : public Avatar { * @property useAdvancedMovementControls {bool} Stores the user preference only, does not change user mappings, this is done in the defaultScript * "scripts/system/controllers/toggleAdvancedMovementForHandControllers.js". * @property userHeight {number} The height of the user in sensor space. (meters). + * @property userEyeHeight {number} Estimated height of the users eyes in sensor space. (meters) */ // FIXME: `glm::vec3 position` is not accessible from QML, so this exposes position in a QML-native type @@ -145,6 +146,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(float hmdRollControlRate READ getHMDRollControlRate WRITE setHMDRollControlRate) Q_PROPERTY(float userHeight READ getUserHeight WRITE setUserHeight) + Q_PROPERTY(float userEyeHeight READ getUserEyeHeight) const QString DOMINANT_LEFT_HAND = "left"; const QString DOMINANT_RIGHT_HAND = "right"; @@ -525,8 +527,8 @@ public: Q_INVOKABLE bool isUp(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) > 0.0f; }; // true iff direction points up wrt avatar's definition of up. Q_INVOKABLE bool isDown(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) < 0.0f; }; - float getUserHeight() const; void setUserHeight(float value); + float getUserHeight() const; float getUserEyeHeight() const; public slots: diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 0222a4c604..614c16228e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1579,6 +1579,8 @@ float Avatar::getEyeHeight() const { } // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. + // Makes assumption that the y = 0 plane in geometry is the ground plane. + // We also make that assumption in Rig::computeAvatarBoundingCapsule() float avatarScale = getUniformScale(); if (_skeletonModel) { auto& rig = _skeletonModel->getRig(); @@ -1592,7 +1594,8 @@ float Avatar::getEyeHeight() const { return eyeHeight; } else if (eyeJoint >= 0) { // measure eyes to y = 0 plane. - float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y; + float groundHeight = transformPoint(rig.getGeometryToRigTransform(), glm::vec3(0.0f)).y; + float eyeHeight = rig.getAbsoluteDefaultPose(eyeJoint).trans().y - groundHeight; return eyeHeight; } else if (headTopJoint >= 0 && toeJoint >= 0) { // measure toe to top of head. Note: default poses already include avatar scale factor @@ -1601,12 +1604,14 @@ float Avatar::getEyeHeight() const { return height - height * ratio; } else if (headTopJoint >= 0) { const float ratio = DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD / DEFAULT_AVATAR_HEIGHT; - float height = rig.getAbsoluteDefaultPose(headTopJoint).trans().y; - return height - height * ratio; + float groundHeight = transformPoint(rig.getGeometryToRigTransform(), glm::vec3(0.0f)).y; + float headHeight = rig.getAbsoluteDefaultPose(headTopJoint).trans().y - groundHeight; + return headHeight - headHeight * ratio; } else if (headJoint >= 0) { + float groundHeight = transformPoint(rig.getGeometryToRigTransform(), glm::vec3(0.0f)).y; const float DEFAULT_AVATAR_NECK_TO_EYE = DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; const float ratio = DEFAULT_AVATAR_NECK_TO_EYE / DEFAULT_AVATAR_NECK_HEIGHT; - float neckHeight = rig.getAbsoluteDefaultPose(headJoint).trans().y; + float neckHeight = rig.getAbsoluteDefaultPose(headJoint).trans().y - groundHeight; return neckHeight + neckHeight * ratio; } else { return avatarScale * DEFAULT_AVATAR_EYE_HEIGHT; From 5230b03f4f73ad7846fd27b0a59630cf44aa1946 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 28 Aug 2017 10:35:03 -0700 Subject: [PATCH 17/58] clang warning fixes --- interface/src/avatar/MyAvatar.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 203d6bf055..4b0186d583 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2806,13 +2806,6 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * desiredBodyMatrix; glm::mat4 currentWorldMatrix = myAvatar.getSensorToWorldMatrix() * currentBodyMatrix; - glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f); - glm::vec4 GREEN(0.0f, 1.0f, 0.0f, 1.0f); - glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); - glm::vec4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); - glm::vec4 desiredColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(desiredBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? RED : GREEN; - glm::vec4 currentColor = glm::dot(Vectors::UNIT_Y, transformVectorFast(currentBodyMatrix, Vectors::UNIT_Y)) < 0.9912f ? BLUE : WHITE; - AnimPose followWorldPose(currentWorldMatrix); // remove scale present from sensorToWorldMatrix From c9cdaadeb51490e3f4e892413234913d9302e524 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 30 Aug 2017 15:46:36 -0700 Subject: [PATCH 18/58] Better scale support in SpatiallyNestable class. Previously avatar used SpatiallyNestable scale to keep track of model rendering scale. It now uses a new member variable _modelScale instead. This is important because the notion of "Avatar" space does NOT include scale, so this is now reflected correctly in the SpatiallyNestable class. Similarly, EntityItems no longer stuff dimensions into the SpatiallyNestable scale field. a new _dimensions member variable is used instead. The SpatiallyNestable scale field for entities should always be one. Parent joints can now have scale if getAbsoluteJointScaleInObjectFrame() returns a non-zero scale. This is used in the case of the faux SENSOR_TO_WORLD_MATRIX_INDEX joint. Overlays now ignore the SpatiallyNestable scale, and render using only orientation, position and dimensions. Added qDebug stream support for Transform class. --- interface/src/Application.cpp | 6 +- interface/src/avatar/MyAvatar.cpp | 34 ++++- interface/src/avatar/MyAvatar.h | 1 + interface/src/ui/PreferencesDialog.cpp | 4 +- interface/src/ui/overlays/ModelOverlay.cpp | 18 +-- interface/src/ui/overlays/OverlaysPayload.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 11 +- .../src/avatars-renderer/Avatar.cpp | 42 +++--- .../src/avatars-renderer/Avatar.h | 7 +- .../src/avatars-renderer/SkeletonModel.cpp | 6 +- libraries/entities/src/EntityItem.cpp | 9 +- libraries/entities/src/EntityItem.h | 3 +- libraries/entities/src/PolyLineEntityItem.cpp | 2 +- libraries/entities/src/PolyLineEntityItem.h | 2 - libraries/shared/src/SpatiallyNestable.cpp | 124 +++++++----------- libraries/shared/src/SpatiallyNestable.h | 17 +-- libraries/shared/src/Transform.cpp | 7 + libraries/shared/src/Transform.h | 4 +- 18 files changed, 146 insertions(+), 153 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d9cbdd9b06..901b300277 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2463,7 +2463,7 @@ void Application::paintGL() { PerformanceTimer perfTimer("CameraUpdates"); auto myAvatar = getMyAvatar(); - boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; + boomOffset = myAvatar->getModelScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; // The render mode is default or mirror if the camera is in mirror mode, assigned further below renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; @@ -2516,14 +2516,14 @@ void Application::paintGL() { hmdOffset.x = -hmdOffset.x; _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + mirrorBodyOrientation * hmdOffset); } else { _myCamera.setOrientation(myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 91af85a108..eca61d95c8 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -558,7 +558,7 @@ void MyAvatar::simulate(float deltaTime) { headPosition = getPosition(); } head->setPosition(headPosition); - head->setScale(getUniformScale()); + head->setScale(getModelScale()); head->simulate(deltaTime); } @@ -1223,7 +1223,7 @@ void MyAvatar::updateLookAtTargetAvatar() { float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); avatar->setIsLookAtTarget(false); if (!avatar->isMyAvatar() && avatar->isInitialized() && - (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getUniformScale())) { + (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) { float radius = glm::length(avatar->getHead()->getEyePosition() - avatar->getHead()->getRightEyePosition()); float angleTo = coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius); if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { @@ -1465,7 +1465,7 @@ glm::vec3 MyAvatar::getSkeletonPosition() const { void MyAvatar::rebuildCollisionShape() { // compute localAABox - float scale = getUniformScale(); + float scale = getModelScale(); float radius = scale * _skeletonModel->getBoundingCapsuleRadius(); float height = scale * _skeletonModel->getBoundingCapsuleHeight() + 2.0f * radius; glm::vec3 corner(-radius, -0.5f * height, -radius); @@ -1896,7 +1896,7 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) { const float RENDER_HEAD_CUTOFF_DISTANCE = 0.3f; bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const { - return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); + return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getModelScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { @@ -2251,7 +2251,7 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings _targetScale = clampedScale; } - setScale(glm::vec3(_targetScale)); + setModelScale(_targetScale); rebuildCollisionShape(); settings.endGroup(); } @@ -2940,6 +2940,30 @@ glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& c return glm::inverse(avatarMatrix) * controllerWorldMatrix; } +glm::vec3 MyAvatar::getAbsoluteJointScaleInObjectFrame(int index) const { + if (index < 0) { + index += numeric_limits::max() + 1; // 65536 + } + + // only sensor to world matrix has non identity scale. + switch (index) { + case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractScale(result); + } + case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractScale(result); + } + default: + return Avatar::getAbsoluteJointScaleInObjectFrame(index); + } +} + glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 1c7cd559a6..07ad61b271 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -513,6 +513,7 @@ public: Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated Q_INVOKABLE bool getCharacterControllerEnabled(); // deprecated + virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8f59d46cc8..fb451f6b0e 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -193,8 +193,8 @@ void setupPreferences() { preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter)); } { - auto getter = [=]()->float { return myAvatar->getUniformScale(); }; - auto setter = [=](float value) { myAvatar->setTargetScale(value); }; + auto getter = [=]()->float { return myAvatar->getModelScale(); }; + auto setter = [=](float value) { myAvatar->setModelScale(value); }; auto preference = new SpinnerSliderPreference(AVATAR_TUNING, "Avatar Scale", getter, setter); preference->setStep(0.05f); preference->setDecimals(2); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 0bed07891e..c0d352bcae 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -46,13 +46,15 @@ void ModelOverlay::update(float deltatime) { if (_updateModel) { _updateModel = false; _model->setSnapModelToCenter(true); + Transform transform = getTransform(); + transform.setScale(1.0f); // disable inherited scale if (_scaleToFit) { - _model->setScaleToFit(true, getScale() * getDimensions()); + _model->setScaleToFit(true, transform.getScale() * getDimensions()); } else { - _model->setScale(getScale()); + _model->setScale(transform.getScale()); } - _model->setRotation(getRotation()); - _model->setTranslation(getPosition()); + _model->setRotation(transform.getRotation()); + _model->setTranslation(transform.getTranslation()); _model->setURL(_url); _model->simulate(deltatime, true); } else { @@ -93,13 +95,13 @@ void ModelOverlay::setProperties(const QVariantMap& properties) { auto origPosition = getPosition(); auto origRotation = getRotation(); auto origDimensions = getDimensions(); - auto origScale = getScale(); + auto origScale = getSNScale(); Base3DOverlay::setProperties(properties); auto scale = properties["scale"]; if (scale.isValid()) { - setScale(vec3FromVariant(scale)); + setSNScale(vec3FromVariant(scale)); } auto dimensions = properties["dimensions"]; @@ -112,7 +114,7 @@ void ModelOverlay::setProperties(const QVariantMap& properties) { _scaleToFit = false; } - if (origPosition != getPosition() || origRotation != getRotation() || origDimensions != getDimensions() || origScale != getScale()) { + if (origPosition != getPosition() || origRotation != getRotation() || origDimensions != getDimensions() || origScale != getSNScale()) { _updateModel = true; } @@ -194,7 +196,7 @@ QVariant ModelOverlay::getProperty(const QString& property) { return vec3toVariant(getDimensions()); } if (property == "scale") { - return vec3toVariant(getScale()); + return vec3toVariant(getSNScale()); } if (property == "textures") { if (_modelTextures.size() > 0) { diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index f2684a4368..887bf7ff8e 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -74,7 +74,7 @@ namespace render { glm::vec3 myAvatarPosition = avatar->getPosition(); float angle = glm::degrees(glm::angle(myAvatarRotation)); glm::vec3 axis = glm::axis(myAvatarRotation); - float myAvatarScale = avatar->getUniformScale(); + float myAvatarScale = avatar->getModelScale(); Transform transform = Transform(); transform.setTranslation(myAvatarPosition); transform.setRotation(glm::angleAxis(angle, axis)); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 104082dee4..d56a90e8fe 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -199,7 +199,6 @@ QString Web3DOverlay::pickURL() { } } - void Web3DOverlay::loadSourceURL() { if (!_webSurface) { return; @@ -302,19 +301,11 @@ void Web3DOverlay::render(RenderArgs* args) { emit resizeWebSurface(); } - vec2 halfSize = getSize() / 2.0f; vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); - - // FIXME: applyTransformTo causes tablet overlay to detach from tablet entity. - // Perhaps rather than deleting the following code it should be run only if isFacingAvatar() is true? - /* - applyTransformTo(transform, true); - setTransform(transform); - */ - + transform.setScale(1.0f); // ignore inherited scale factor from parents if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fc0ee1df7b..4e8f2ad572 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -107,7 +107,7 @@ Avatar::Avatar(QThread* thread) : // we may have been created in the network thread, but we live in the main thread moveToThread(thread); - setScale(glm::vec3(1.0f)); // avatar scale is uniform + setModelScale(1.0f); // avatar scale is uniform auto geometryCache = DependencyManager::get(); _nameRectGeometryID = geometryCache->allocateID(); @@ -156,14 +156,14 @@ glm::vec3 Avatar::getNeckPosition() const { AABox Avatar::getBounds() const { if (!_skeletonModel->isRenderable() || _skeletonModel->needsFixupInScene()) { // approximately 2m tall, scaled to user request. - return AABox(getPosition() - glm::vec3(getUniformScale()), getUniformScale() * 2.0f); + return AABox(getPosition() - glm::vec3(getModelScale()), getModelScale() * 2.0f); } return _skeletonModel->getRenderableMeshBound(); } void Avatar::animateScaleChanges(float deltaTime) { if (_isAnimatingScale) { - float currentScale = getUniformScale(); + float currentScale = getModelScale(); float desiredScale = getDomainLimitedScale(); // use exponential decay toward the domain limit clamped scale @@ -178,7 +178,7 @@ void Avatar::animateScaleChanges(float deltaTime) { animatedScale = desiredScale; _isAnimatingScale = false; } - setScale(glm::vec3(animatedScale)); // avatar scale is uniform + setModelScale(animatedScale); // avatar scale is uniform // flag the joints as having changed for force update to RenderItem _hasNewJointData = true; @@ -365,7 +365,7 @@ void Avatar::simulate(float deltaTime, bool inView) { } head->setPosition(headPosition); } - head->setScale(getUniformScale()); + head->setScale(getModelScale()); head->simulate(deltaTime); } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. @@ -423,7 +423,7 @@ bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const { glm::vec3 theirLookAt = dynamic_pointer_cast(avatar)->getHead()->getLookAtPosition(); glm::vec3 myEyePosition = getHead()->getEyePosition(); - return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getUniformScale()); + return glm::distance(theirLookAt, myEyePosition) <= (HEAD_SPHERE_RADIUS * getModelScale()); } void Avatar::slamPosition(const glm::vec3& newPosition) { @@ -654,7 +654,7 @@ void Avatar::render(RenderArgs* renderArgs) { if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; - _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); + _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getModelScale(), BOUNDING_SHAPE_ALPHA); } if (showReceiveStats || showNamesAboveHeads) { @@ -727,9 +727,9 @@ void Avatar::simulateAttachments(float deltaTime) { } else { if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) && _skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) { - model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale()); + model->setTranslation(jointPosition + jointRotation * attachment.translation * getModelScale()); model->setRotation(jointRotation * attachment.rotation); - float scale = getUniformScale() * attachment.scale; + float scale = getModelScale() * attachment.scale; model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale model->setSnapModelToCenter(false); // hack to force resnap model->setSnapModelToCenter(true); @@ -889,7 +889,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const } void Avatar::setSkeletonOffset(const glm::vec3& offset) { - const float MAX_OFFSET_LENGTH = getUniformScale() * 0.5f; + const float MAX_OFFSET_LENGTH = getModelScale() * 0.5f; float offsetLength = glm::length(offset); if (offsetLength > MAX_OFFSET_LENGTH) { _skeletonOffset = (MAX_OFFSET_LENGTH / offsetLength) * offset; @@ -990,11 +990,8 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const { switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + glm::mat4 avatarMatrix = getLocalTransform().getMatrix(); + glm::mat4 finalMat = glm::inverse(avatarMatrix) * sensorToWorldMatrix; return glmExtractRotation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { @@ -1031,11 +1028,8 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { switch (index) { case SENSOR_TO_WORLD_MATRIX_INDEX: { glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix(); - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - glm::mat4 finalMat = invAvatarMat * sensorToWorldMatrix; + glm::mat4 avatarMatrix = getLocalTransform().getMatrix(); + glm::mat4 finalMat = glm::inverse(avatarMatrix) * sensorToWorldMatrix; return extractTranslation(finalMat); } case CONTROLLER_LEFTHAND_INDEX: { @@ -1064,7 +1058,6 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } } -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT glm::vec3 Avatar::getAbsoluteJointScaleInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 @@ -1080,7 +1073,6 @@ glm::vec3 Avatar::getAbsoluteJointScaleInObjectFrame(int index) const { return AvatarData::getAbsoluteJointScaleInObjectFrame(index); } } -#endif void Avatar::invalidateJointIndicesCache() const { QWriteLocker writeLock(&_modelJointIndicesCacheLock); @@ -1170,7 +1162,7 @@ glm::vec3 Avatar::getJointPosition(const QString& name) const { void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { //Scale a world space vector as if it was relative to the position - positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition()); + positionToScale = getPosition() + getModelScale() * (positionToScale - getPosition()); } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { @@ -1372,7 +1364,7 @@ void Avatar::updateDisplayNameAlpha(bool showDisplayName) { // virtual void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) { - float uniformScale = getUniformScale(); + float uniformScale = getModelScale(); shapeInfo.setCapsuleY(uniformScale * _skeletonModel->getBoundingCapsuleRadius(), 0.5f * uniformScale * _skeletonModel->getBoundingCapsuleHeight()); shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset()); @@ -1581,7 +1573,7 @@ float Avatar::getEyeHeight() const { // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. // Makes assumption that the y = 0 plane in geometry is the ground plane. // We also make that assumption in Rig::computeAvatarBoundingCapsule() - float avatarScale = getUniformScale(); + float avatarScale = getModelScale(); if (_skeletonModel) { auto& rig = _skeletonModel->getRig(); int headTopJoint = rig.indexOfJoint("HeadTop_End"); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 7b0819655a..75d9afeb90 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -108,7 +108,6 @@ public: SkeletonModelPointer getSkeletonModel() { return _skeletonModel; } const SkeletonModelPointer getSkeletonModel() const { return _skeletonModel; } glm::vec3 getChestPosition() const; - float getUniformScale() const { return getScale().y; } const Head* getHead() const { return static_cast(_headData); } Head* getHead() { return static_cast(_headData); } @@ -151,9 +150,7 @@ public: */ Q_INVOKABLE virtual glm::vec3 getAbsoluteDefaultJointTranslationInObjectFrame(int index) const; -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; -#endif 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 { return false; } @@ -263,6 +260,9 @@ public: */ Q_INVOKABLE float getEyeHeight() const; + float getModelScale() const { return _modelScale; } + void setModelScale(float scale) { _modelScale = scale; } + public slots: // FIXME - these should be migrated to use Pose data instead @@ -365,6 +365,7 @@ private: bool _isAnimatingScale { false }; bool _mustFadeIn { false }; bool _isFading { false }; + float _modelScale { 1.0f }; static int _jointConesID; diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index c0d5fc07d7..eaa62ecb0a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -121,7 +121,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { void SkeletonModel::updateAttitude(const glm::quat& orientation) { setTranslation(_owningAvatar->getSkeletonPosition()); setRotation(orientation * Quaternions::Y_180); - setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale()); + setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getModelScale()); } // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), @@ -294,7 +294,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { - return _owningAvatar->getScale() * _defaultEyeModelPosition; + return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } float DENSITY_OF_WATER = 1000.0f; // kg/m^3 @@ -316,7 +316,7 @@ void SkeletonModel::computeBoundingShape() { float radius, height; glm::vec3 offset; _rig.computeAvatarBoundingCapsule(geometry, radius, height, offset); - float invScale = 1.0f / _owningAvatar->getUniformScale(); + float invScale = 1.0f / _owningAvatar->getModelScale(); _boundingCapsuleRadius = invScale * radius; _boundingCapsuleHeight = invScale * height; _boundingCapsuleLocalOffset = invScale * offset; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0c120d586c..6b57c79713 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -42,7 +42,8 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : setLocalVelocity(ENTITY_ITEM_DEFAULT_VELOCITY); setLocalAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); // explicitly set transform parts to set dirty flags used by batch rendering - setScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); + locationChanged(); + dimensionsChanged(); quint64 now = usecTimestampNow(); _lastSimulated = now; _lastUpdated = now; @@ -1382,7 +1383,11 @@ void EntityItem::setDimensions(const glm::vec3& value) { if (value.x <= 0.0f || value.y <= 0.0f || value.z <= 0.0f) { return; } - setScale(value); + if (_dimensions != value) { + _dimensions = value; + locationChanged(); + dimensionsChanged(); + } } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 84742587e9..a95f7ba316 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -179,7 +179,7 @@ public: void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) - inline const glm::vec3 getDimensions() const { return getScale(); } + inline const glm::vec3 getDimensions() const { return _dimensions; } virtual void setDimensions(const glm::vec3& value); float getLocalRenderAlpha() const; @@ -470,6 +470,7 @@ protected: virtual void dimensionsChanged() override; + glm::vec3 _dimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; EntityTypes::EntityType _type { EntityTypes::Unknown }; quint64 _lastSimulated { 0 }; // last time this entity called simulate(), this includes velocity, angular velocity, // and physics changes diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 23a5c88900..ad9686bdf2 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -176,7 +176,7 @@ void PolyLineEntityItem::calculateScaleAndRegistrationPoint() { } // if Polyline has only one or fewer points, use default dimension settings - SpatiallyNestable::setScale(newScale); + setDimensions(newScale); EntityItem::setRegistrationPoint(newRegistrationPoint); } diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 4860e3d4a4..9fbc6c60a1 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -91,8 +91,6 @@ class PolyLineEntityItem : public EntityItem { // disable these external interfaces as PolyLineEntities caculate their own dimensions based on the points they contain virtual void setRegistrationPoint(const glm::vec3& value) override {}; - virtual void setScale(const glm::vec3& scale) override {}; - virtual void setScale(float value) override {}; virtual void debugDump() const override; static const float DEFAULT_LINE_WIDTH; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 0bf7a8b95d..c20ce90cd6 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -84,12 +84,7 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const return result; } if (parent) { -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT result = parent->getTransform(_parentJointIndex, success, depth + 1); -#else - Transform parentTransform = parent->getTransform(_parentJointIndex, success, depth + 1); - result = parentTransform.setScale(1.0f); // TODO: scaling -#endif } return result; } @@ -161,7 +156,6 @@ void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success) { - Transform result; QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -185,25 +179,17 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; - Transform positionTransform; - positionTransform.setTranslation(position); - Transform myWorldTransform; - Transform::mult(myWorldTransform, parentTransform, positionTransform); - myWorldTransform.setTranslation(position); - Transform::inverseMult(result, parentTransform, myWorldTransform); - return result.getTranslation(); + Transform invParentTransform; + parentTransform.evalInverse(invParentTransform); + return invParentTransform.transform(position); } glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success) { - Transform result; QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -227,19 +213,11 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, if (!success) { return glm::quat(); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; - Transform orientationTransform; - orientationTransform.setRotation(orientation); - Transform myWorldTransform; - Transform::mult(myWorldTransform, parentTransform, orientationTransform); - myWorldTransform.setRotation(orientation); - Transform::inverseMult(result, parentTransform, myWorldTransform); - return result.getRotation(); + glm::quat invParentOrientation = glm::inverse(parentTransform.getRotation()); + return invParentOrientation * orientation; } glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, @@ -301,9 +279,6 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - parentTransform.setScale(1.0f); // TODO: scale -#endif } success = true; @@ -645,9 +620,6 @@ const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, i } Transform worldTransform = getTransform(success, depth); -#ifndef SPATIALLY_NESTABLE_SCALE_SUPPORT - worldTransform.setScale(1.0f); // TODO: scale -#endif if (!success) { return jointInWorldFrame; } @@ -686,61 +658,51 @@ bool SpatiallyNestable::setTransform(const Transform& transform) { return success; } -glm::vec3 SpatiallyNestable::getScale() const { - // TODO: scale - glm::vec3 result; - _transformLock.withReadLock([&] { - result = _transform.getScale(); - }); +glm::vec3 SpatiallyNestable::getSNScale() const { + bool success; + auto result = getSNScale(success); + #ifdef WANT_DEBUG + if (!success) { + qCDebug(shared) << "Warning -- getScale failed" << getID(); + } + #endif return result; } -glm::vec3 SpatiallyNestable::getScale(int jointIndex) const { - // TODO: scale - return getScale(); +glm::vec3 SpatiallyNestable::getSNScale(bool& success) const { + return getTransform(success).getScale(); } -void SpatiallyNestable::setScale(const glm::vec3& scale) { +glm::vec3 SpatiallyNestable::getSNScale(int jointIndex, bool& success) const { + return getTransform(jointIndex, success).getScale(); +} + +void SpatiallyNestable::setSNScale(const glm::vec3& scale) { + bool success; + setSNScale(scale, success); +} + +void SpatiallyNestable::setSNScale(const glm::vec3& scale, bool& success) { // guard against introducing NaN into the transform if (isNaN(scale)) { - qCDebug(shared) << "SpatiallyNestable::setScale -- scale contains NaN"; + success = false; return; } bool changed = false; - // TODO: scale + Transform parentTransform = getParentTransform(success); + Transform myWorldTransform; _transformLock.withWriteLock([&] { - if (_transform.getScale() != scale) { - _transform.setScale(scale); + Transform::mult(myWorldTransform, parentTransform, _transform); + if (myWorldTransform.getScale() != scale) { changed = true; + myWorldTransform.setScale(scale); + Transform::inverseMult(_transform, parentTransform, myWorldTransform); _scaleChanged = usecTimestampNow(); } }); - if (changed) { - dimensionsChanged(); - } -} - -void SpatiallyNestable::setScale(float value) { - // guard against introducing NaN into the transform - if (value <= 0.0f) { - qCDebug(shared) << "SpatiallyNestable::setScale -- scale is zero or negative value"; - return; - } - - bool changed = false; - // TODO: scale - _transformLock.withWriteLock([&] { - glm::vec3 beforeScale = _transform.getScale(); - _transform.setScale(value); - if (_transform.getScale() != beforeScale) { - changed = true; - _scaleChanged = usecTimestampNow(); - } - }); - - if (changed) { - dimensionsChanged(); + if (success && changed) { + locationChanged(); } } @@ -857,8 +819,7 @@ void SpatiallyNestable::setLocalAngularVelocity(const glm::vec3& angularVelocity }); } -glm::vec3 SpatiallyNestable::getLocalScale() const { - // TODO: scale +glm::vec3 SpatiallyNestable::getLocalSNScale() const { glm::vec3 result; _transformLock.withReadLock([&] { result = _transform.getScale(); @@ -866,7 +827,7 @@ glm::vec3 SpatiallyNestable::getLocalScale() const { return result; } -void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { +void SpatiallyNestable::setLocalSNScale(const glm::vec3& scale) { // guard against introducing NaN into the transform if (isNaN(scale)) { qCDebug(shared) << "SpatiallyNestable::setLocalScale -- scale contains NaN"; @@ -874,7 +835,6 @@ void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { } bool changed = false; - // TODO: scale _transformLock.withWriteLock([&] { if (_transform.getScale() != scale) { _transform.setScale(scale); @@ -918,10 +878,8 @@ const Transform SpatiallyNestable::getAbsoluteJointTransformInObjectFrame(int jo Transform jointTransformInObjectFrame; glm::vec3 position = getAbsoluteJointTranslationInObjectFrame(jointIndex); glm::quat orientation = getAbsoluteJointRotationInObjectFrame(jointIndex); -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT glm::vec3 scale = getAbsoluteJointScaleInObjectFrame(jointIndex); jointTransformInObjectFrame.setScale(scale); -#endif jointTransformInObjectFrame.setRotation(orientation); jointTransformInObjectFrame.setTranslation(position); return jointTransformInObjectFrame; @@ -1214,3 +1172,13 @@ QString SpatiallyNestable::nestableTypeToString(NestableType nestableType) { return "unknown"; } } + +void SpatiallyNestable::dump(const QString& prefix) const { + qDebug().noquote() << prefix << "id = " << getID(); + qDebug().noquote() << prefix << "transform = " << _transform; + bool success; + SpatiallyNestablePointer parent = getParentPointer(success); + if (success && parent) { + parent->dump(prefix + " "); + } +} diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index cb3dba754a..4195efc553 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -111,14 +111,15 @@ public: virtual AACube getQueryAACube(bool& success) const; virtual AACube getQueryAACube() const; - virtual glm::vec3 getScale() const; - virtual void setScale(const glm::vec3& scale); - virtual void setScale(float value); + virtual glm::vec3 getSNScale() const; + virtual glm::vec3 getSNScale(bool& success) const; + virtual void setSNScale(const glm::vec3& scale); + virtual void setSNScale(const glm::vec3& scale, bool& success); // get world-frame values for a specific joint virtual const Transform getTransform(int jointIndex, bool& success, int depth = 0) const; virtual glm::vec3 getPosition(int jointIndex, bool& success) const; - virtual glm::vec3 getScale(int jointIndex) const; + virtual glm::vec3 getSNScale(int jointIndex, bool& success) const; // object's parent's frame virtual const Transform getLocalTransform() const; @@ -136,8 +137,8 @@ public: virtual glm::vec3 getLocalAngularVelocity() const; virtual void setLocalAngularVelocity(const glm::vec3& angularVelocity); - virtual glm::vec3 getLocalScale() const; - virtual void setLocalScale(const glm::vec3& scale); + virtual glm::vec3 getLocalSNScale() const; + virtual void setLocalSNScale(const glm::vec3& scale); QList getChildren() const; bool hasChildren() const; @@ -146,9 +147,7 @@ public: // this object's frame virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; -#ifdef SPATIALLY_NESTABLE_SCALE_SUPPORT virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const { return glm::vec3(1.0f); } -#endif virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { return glm::vec3(); } virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { return false; } @@ -193,6 +192,8 @@ public: bool tranlationChangedSince(quint64 time) const { return _translationChanged > time; } bool rotationChangedSince(quint64 time) const { return _rotationChanged > time; } + void dump(const QString& prefix = "") const; + protected: const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; diff --git a/libraries/shared/src/Transform.cpp b/libraries/shared/src/Transform.cpp index c51b3dae4b..3e29c38add 100644 --- a/libraries/shared/src/Transform.cpp +++ b/libraries/shared/src/Transform.cpp @@ -150,3 +150,10 @@ QJsonObject Transform::toJson(const Transform& transform) { } return result; } + +QDebug& operator<<(QDebug& debug, const Transform& transform) { + debug << "Transform, trans = (" << transform._translation.x << transform._translation.y << transform._translation.z << "), rot = (" + << transform._rotation.x << transform._rotation.y << transform._rotation.z << transform._rotation.w << "), scale = (" + << transform._scale.x << transform._scale.y << transform._scale.z << ")"; + return debug; +} diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 38d47695f7..316fcb2f04 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -38,6 +38,7 @@ inline bool isValidScale(float scale) { class Transform { public: + friend QDebug& operator<<(QDebug& debug, const Transform& transform); using Pointer = std::shared_ptr; typedef glm::mat4 Mat4; typedef glm::mat3 Mat3; @@ -170,7 +171,6 @@ protected: }; typedef std::bitset Flags; - // TRS Quat _rotation; Vec3 _scale; @@ -202,6 +202,8 @@ protected: Mat4& getCachedMatrix(Mat4& result) const; }; +QDebug& operator<<(QDebug& debug, const Transform& transform); + inline Transform& Transform::setIdentity() { _translation = Vec3(0.0f); _rotation = Quat(1.0f, 0.0f, 0.0f, 0.0f); From 6e6687c3a62fe5490e5f09476d14535ce921fc16 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 30 Aug 2017 18:21:25 -0700 Subject: [PATCH 19/58] Change tablet dimensions as sensorToWorldScale changes --- interface/src/ui/overlays/Base3DOverlay.h | 3 +++ interface/src/ui/overlays/ModelOverlay.cpp | 2 ++ interface/src/ui/overlays/Sphere3DOverlay.cpp | 3 +++ interface/src/ui/overlays/Volume3DOverlay.cpp | 6 +++++- interface/src/ui/overlays/Web3DOverlay.cpp | 2 ++ scripts/system/libraries/WebTablet.js | 21 +++++++++++-------- scripts/system/tablet-ui/tabletUI.js | 16 +++++++++++--- 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 6377b46d7d..cc46fecfa5 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -16,6 +16,9 @@ #include "Overlay.h" +// AJT: keep or remove this. +// #define USE_SN_SCALE + class Base3DOverlay : public Overlay, public SpatiallyNestable { Q_OBJECT diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index c0d352bcae..891623edbc 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -47,7 +47,9 @@ void ModelOverlay::update(float deltatime) { _updateModel = false; _model->setSnapModelToCenter(true); Transform transform = getTransform(); +#ifndef USE_SN_SCALE transform.setScale(1.0f); // disable inherited scale +#endif if (_scaleToFit) { _model->setScaleToFit(true, transform.getScale() * getDimensions()); } else { diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 9309316d6e..94c92c029d 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -40,6 +40,9 @@ void Sphere3DOverlay::render(RenderArgs* args) { if (batch) { Transform transform = getTransform(); +#ifndef USE_SN_SCALE + transform.setScale(1.0f); // ignore inherited scale from SpatiallyNestable +#endif transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE); batch->setModelTransform(transform); diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index ad61e28bc7..5e3e4ccee7 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -56,7 +56,11 @@ bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve float& distance, BoxFace& face, glm::vec3& surfaceNormal) { // extents is the entity relative, scaled, centered extents of the entity glm::mat4 worldToEntityMatrix; - getTransform().getInverseMatrix(worldToEntityMatrix); + Transform transform = getTransform(); +#ifndef USE_SN_SCALE + transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable +#endif + transform.getInverseMatrix(worldToEntityMatrix); glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index d56a90e8fe..32f97507bd 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -305,7 +305,9 @@ void Web3DOverlay::render(RenderArgs* args) { vec4 color(toGlm(getColor()), getAlpha()); Transform transform = getTransform(); +#ifndef USE_SN_SCALE transform.setScale(1.0f); // ignore inherited scale factor from parents +#endif if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 3dc62c9e34..243b8bbc79 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -106,8 +106,10 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { var _this = this; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + // scale factor of natural tablet dimensions. - this.width = width || DEFAULT_WIDTH; + this.width = (width || DEFAULT_WIDTH) * sensorScaleFactor; var tabletScaleFactor = this.width / TABLET_NATURAL_DIMENSIONS.x; this.height = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; this.depth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; @@ -152,8 +154,8 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { Overlays.deleteOverlay(this.webOverlayID); } - var WEB_ENTITY_Z_OFFSET = (this.depth / 2); - var WEB_ENTITY_Y_OFFSET = 0.004; + var WEB_ENTITY_Z_OFFSET = (this.depth / 2) * (1 / sensorScaleFactor); + var WEB_ENTITY_Y_OFFSET = 0.004 * (1 / sensorScaleFactor); this.webOverlayID = Overlays.addOverlay("web3d", { name: "WebTablet Web", @@ -170,13 +172,13 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { visible: visible }); - var HOME_BUTTON_Y_OFFSET = (this.height / 2) - (this.height / 20); + var HOME_BUTTON_Y_OFFSET = ((this.height / 2) - (this.height / 20)) * (1 / sensorScaleFactor); this.homeButtonID = Overlays.addOverlay("sphere", { name: "homeButton", localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, localRotation: {x: 0, y: 1, z: 0, w: 0}, dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor}, - alpha: 0.0, + alpha: 1.0, visible: visible, drawInFront: false, parentID: this.tabletEntityID, @@ -301,9 +303,10 @@ WebTablet.prototype.getOverlayObject = function () { }; WebTablet.prototype.setWidth = function (width) { + var sensorScaleFactor = MyAvatar.sensorToWorldScale; // scale factor of natural tablet dimensions. - this.width = width || DEFAULT_WIDTH; + this.width = (width || DEFAULT_WIDTH) * sensorScaleFactor; var tabletScaleFactor = this.width / TABLET_NATURAL_DIMENSIONS.x; this.height = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; this.depth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; @@ -313,15 +316,15 @@ WebTablet.prototype.setWidth = function (width) { Overlays.editOverlay(this.tabletEntityID, { dimensions: this.getDimensions() }); // update webOverlay - var WEB_ENTITY_Z_OFFSET = (this.depth / 2); - var WEB_ENTITY_Y_OFFSET = 0.004; + var WEB_ENTITY_Z_OFFSET = (this.depth / 2) * (1 / sensorScaleFactor); + var WEB_ENTITY_Y_OFFSET = 0.004 * (1 / sensorScaleFactor); Overlays.editOverlay(this.webOverlayID, { localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET }, dpi: this.dpi }); // update homeButton - var HOME_BUTTON_Y_OFFSET = (this.height / 2) - (this.height / 20); + var HOME_BUTTON_Y_OFFSET = ((this.height / 2) - (this.height / 20)) * (1 / sensorScaleFactor); Overlays.editOverlay(this.homeButtonID, { localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor} diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 257a56bf09..4a77740d9b 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -28,6 +28,7 @@ var MSECS_PER_SEC = 1000.0; var MUTE_MICROPHONE_MENU_ITEM = "Mute Microphone"; var gTablet = null; + var avatarSensorScale = MyAvatar.sensorToWorldScale; Script.include("../libraries/WebTablet.js"); @@ -71,9 +72,9 @@ return tabletScalePercentage; } - function updateTabletWidthFromSettings() { + function updateTabletWidthFromSettings(force) { var newTabletScalePercentage = getTabletScalePercentageFromSettings(); - if (newTabletScalePercentage !== tabletScalePercentage && UIWebTablet) { + if ((force || newTabletScalePercentage !== tabletScalePercentage) && UIWebTablet) { tabletScalePercentage = newTabletScalePercentage; UIWebTablet.setWidth(DEFAULT_WIDTH * (tabletScalePercentage / 100)); } @@ -121,6 +122,7 @@ Overlays.editOverlay(HMD.homeButtonID, { visible: true }); Overlays.editOverlay(HMD.tabletScreenID, { visible: true }); Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 }); + updateTabletWidthFromSettings(true); } gTablet.tabletShown = true; } @@ -185,7 +187,15 @@ if (now - validCheckTime > MSECS_PER_SEC) { validCheckTime = now; - updateTabletWidthFromSettings(); + + // force tablet to resize if sensorToWorldScale changes + var force = false; + if (avatarSensorScale !== MyAvatar.sensorToWorldScale) { + force = true; + avatarSensorScale = MyAvatar.sensorToWorldScale; + } + updateTabletWidthFromSettings(force); + if (UIWebTablet) { UIWebTablet.setLandscape(landscape); } From 9c6b8a6826d11f1c7287d9bd764596beb5702233 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 31 Aug 2017 11:28:05 -0700 Subject: [PATCH 20/58] Fixes for scaling tablet --- .../system/controllers/handControllerGrab.js | 12 ++++ scripts/system/libraries/WebTablet.js | 28 +-------- scripts/system/libraries/utils.js | 62 +++++++++++++++++++ 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index f6eec7ab76..8ee9128210 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3029,6 +3029,12 @@ function MyController(hand) { if (this.grabbedIsOverlay) { Overlays.editOverlay(this.grabbedThingID, reparentProps); + // AJT: resize tablet to allow it to counter scale. + if (this.grabbedThingID === HMD.tabletID) { + var DEFAULT_TABLET_WIDTH = 0.4375; + var tabletScalePercentage = getTabletScalePercentageFromSettings(); + resizeTablet(DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100)); + } } else { if (grabbedProperties.userData.length > 0) { try{ @@ -3805,6 +3811,12 @@ function MyController(hand) { parentID: this.previousParentID[this.grabbedThingID], parentJointIndex: this.previousParentJointIndex[this.grabbedThingID], }); + // AJT: resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix + if (this.grabbedThingID === HMD.tabletID) { + var DEFAULT_TABLET_WIDTH = 0.4375; + var tabletScalePercentage = getTabletScalePercentageFromSettings(); + resizeTablet(DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100)); + } } else { // we're putting this back as a child of some other parent, so zero its velocity Entities.editEntity(this.grabbedThingID, { diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 243b8bbc79..e28b9be4e4 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -303,32 +303,8 @@ WebTablet.prototype.getOverlayObject = function () { }; WebTablet.prototype.setWidth = function (width) { - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - - // scale factor of natural tablet dimensions. - this.width = (width || DEFAULT_WIDTH) * sensorScaleFactor; - var tabletScaleFactor = this.width / TABLET_NATURAL_DIMENSIONS.x; - this.height = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; - this.depth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; - this.dpi = DEFAULT_DPI * (DEFAULT_WIDTH / this.width); - - // update tablet model dimensions - Overlays.editOverlay(this.tabletEntityID, { dimensions: this.getDimensions() }); - - // update webOverlay - var WEB_ENTITY_Z_OFFSET = (this.depth / 2) * (1 / sensorScaleFactor); - var WEB_ENTITY_Y_OFFSET = 0.004 * (1 / sensorScaleFactor); - Overlays.editOverlay(this.webOverlayID, { - localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET }, - dpi: this.dpi - }); - - // update homeButton - var HOME_BUTTON_Y_OFFSET = ((this.height / 2) - (this.height / 20)) * (1 / sensorScaleFactor); - Overlays.editOverlay(this.homeButtonID, { - localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, - dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor} - }); + // imported from libraries/utils.js + resizeTablet(width); }; WebTablet.prototype.destroy = function () { diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index a5e97d8949..b0437820d9 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -351,3 +351,65 @@ clamp = function(val, min, max){ flatten = function(array) { return [].concat.apply([], array); } + +getTabletScalePercentageFromSettings = function () { + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var toolbarMode = tablet.toolbarMode; + var DEFAULT_TABLET_SCALE = 100; + var tabletScalePercentage = DEFAULT_TABLET_SCALE; + if (!toolbarMode) { + if (HMD.active) { + tabletScalePercentage = Settings.getValue("hmdTabletScale") || DEFAULT_TABLET_SCALE; + } else { + tabletScalePercentage = Settings.getValue("desktopTabletScale") || DEFAULT_TABLET_SCALE; + } + } + return tabletScalePercentage; +}; + +resizeTablet = function (width, newParentJointID) { + + if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) { + return; + } + + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var sensorScaleOffsetOverride = 1; + var SENSOR_TO_ROOM_MATRIX = 65534; + var parentJointIndex = Overlays.getProperty(HMD.tabletID, "parentJointIndex"); + if (parentJointIndex === SENSOR_TO_ROOM_MATRIX) { + sensorScaleOffsetOverride = 1 / sensorScaleFactor; + } + + // will need to be recaclulated if dimensions of fbx model change. + var TABLET_NATURAL_DIMENSIONS = {x: 33.797, y: 50.129, z: 2.269}; + var DEFAULT_DPI = 34; + var DEFAULT_WIDTH = 0.4375; + + // scale factor of natural tablet dimensions. + var tabletWidth = (width || DEFAULT_WIDTH) * sensorScaleFactor; + var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x; + var tabletHeight = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; + var tabletDepth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; + var tabletDpi = DEFAULT_DPI * (DEFAULT_WIDTH / tabletWidth); + + // update tablet model dimensions + Overlays.editOverlay(HMD.tabletID, { + dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth } + }); + + // update webOverlay + var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2) * sensorScaleOffsetOverride; + var WEB_ENTITY_Y_OFFSET = 0.004 * sensorScaleOffsetOverride; + Overlays.editOverlay(HMD.tabletScreenID, { + localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET }, + dpi: tabletDpi + }); + + // update homeButton + var HOME_BUTTON_Y_OFFSET = ((tabletHeight / 2) - (tabletHeight / 20)) * sensorScaleOffsetOverride; + Overlays.editOverlay(HMD.homeButtonID, { + localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, + dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor} + }); +}; From 1a01209020d78919c0cf04ed34ee9c16e2b3b351 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 31 Aug 2017 13:02:31 -0700 Subject: [PATCH 21/58] Fixes for scaling tablet at high frame rates --- scripts/system/controllers/handControllerGrab.js | 8 ++------ scripts/system/libraries/WebTablet.js | 2 +- scripts/system/libraries/utils.js | 9 +++++---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 8ee9128210..56b52eb1a7 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3031,9 +3031,7 @@ function MyController(hand) { Overlays.editOverlay(this.grabbedThingID, reparentProps); // AJT: resize tablet to allow it to counter scale. if (this.grabbedThingID === HMD.tabletID) { - var DEFAULT_TABLET_WIDTH = 0.4375; - var tabletScalePercentage = getTabletScalePercentageFromSettings(); - resizeTablet(DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100)); + resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex); } } else { if (grabbedProperties.userData.length > 0) { @@ -3813,9 +3811,7 @@ function MyController(hand) { }); // AJT: resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix if (this.grabbedThingID === HMD.tabletID) { - var DEFAULT_TABLET_WIDTH = 0.4375; - var tabletScalePercentage = getTabletScalePercentageFromSettings(); - resizeTablet(DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100)); + resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]); } } else { // we're putting this back as a child of some other parent, so zero its velocity diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index e28b9be4e4..56dc06cf78 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -178,7 +178,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, localRotation: {x: 0, y: 1, z: 0, w: 0}, dimensions: { x: 4 * tabletScaleFactor, y: 4 * tabletScaleFactor, z: 4 * tabletScaleFactor}, - alpha: 1.0, + alpha: 0.0, visible: visible, drawInFront: false, parentID: this.tabletEntityID, diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index b0437820d9..b79ff03550 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -352,7 +352,8 @@ flatten = function(array) { return [].concat.apply([], array); } -getTabletScalePercentageFromSettings = function () { +getTabletWidthFromSettings = function () { + var DEFAULT_TABLET_WIDTH = 0.4375; var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var toolbarMode = tablet.toolbarMode; var DEFAULT_TABLET_SCALE = 100; @@ -364,10 +365,10 @@ getTabletScalePercentageFromSettings = function () { tabletScalePercentage = Settings.getValue("desktopTabletScale") || DEFAULT_TABLET_SCALE; } } - return tabletScalePercentage; + return DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100); }; -resizeTablet = function (width, newParentJointID) { +resizeTablet = function (width, newParentJointIndex) { if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) { return; @@ -376,7 +377,7 @@ resizeTablet = function (width, newParentJointID) { var sensorScaleFactor = MyAvatar.sensorToWorldScale; var sensorScaleOffsetOverride = 1; var SENSOR_TO_ROOM_MATRIX = 65534; - var parentJointIndex = Overlays.getProperty(HMD.tabletID, "parentJointIndex"); + var parentJointIndex = newParentJointIndex || Overlays.getProperty(HMD.tabletID, "parentJointIndex"); if (parentJointIndex === SENSOR_TO_ROOM_MATRIX) { sensorScaleOffsetOverride = 1 / sensorScaleFactor; } From a0eb8152a6636e5d4a78aad9493f40f2d87a21ef Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 31 Aug 2017 13:15:46 -0700 Subject: [PATCH 22/58] fix for tablet spawn position --- scripts/system/libraries/WebTablet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 56dc06cf78..aaaca70464 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -76,7 +76,8 @@ function calcSpawnInfo(hand, tabletHeight, landscape) { var TABLET_RAKE_ANGLE = 30; rotation = Quat.multiply(Quat.angleAxis(TABLET_RAKE_ANGLE, Vec3.multiplyQbyV(lookAt, Vec3.UNIT_X)), lookAt); - var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6, z: 0.1 }; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6 * sensorScaleFactor, z: 0.1 * sensorScaleFactor }; position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, Vec3.multiply(tabletHeight, RELATIVE_SPAWN_OFFSET))); return { From 98c89cbe782c9d01d0be4e05b4216fd2f71d3c99 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 31 Aug 2017 14:45:59 -0700 Subject: [PATCH 23/58] Fixes for stylus size and offset --- scripts/system/controllers/handControllerGrab.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 56b52eb1a7..e1c12604fe 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1248,7 +1248,7 @@ function MyController(hand) { this.stylusTip = getControllerWorldLocation(this.handToController(), true); // translate tip forward according to constant. - var TIP_OFFSET = {x: 0, y: WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, z: 0}; + var TIP_OFFSET = Vec3.multiply(MyAvatar.sensorToWorldScale, {x: 0, y: WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, z: 0}); this.stylusTip.position = Vec3.sum(this.stylusTip.position, Vec3.multiplyQbyV(this.stylusTip.orientation, TIP_OFFSET)); } @@ -1390,16 +1390,16 @@ function MyController(hand) { return; } + var X_ROT_NEG_90 = { x: -0.70710678, y: 0, z: 0, w: 0.70710678 }; + var modelOrientation = Quat.multiply(this.stylusTip.orientation, X_ROT_NEG_90); + var modelPositionOffset = Vec3.multiplyQbyV(modelOrientation, { x: 0, y: 0, z: MyAvatar.sensorToWorldScale * -WEB_STYLUS_LENGTH / 2 }); var stylusProperties = { name: "stylus", url: Script.resourcesPath() + "meshes/tablet-stylus-fat.fbx", loadPriority: 10.0, - localPosition: Vec3.sum({ x: 0.0, - y: WEB_TOUCH_Y_OFFSET, - z: 0.0 }, - getGrabPointSphereOffset(this.handToController())), - localRotation: Quat.fromVec3Degrees({ x: -90, y: 0, z: 0 }), - dimensions: { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }, + position: Vec3.sum(this.stylusTip.position, modelPositionOffset), + rotation: modelOrientation, + dimensions: Vec3.multiply(MyAvatar.sensorToWorldScale, { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }), solid: true, visible: true, ignoreRayIntersection: true, From a1b94fd9d269b3bc215099296f24ef1c0585d0bc Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 31 Aug 2017 17:26:00 -0700 Subject: [PATCH 24/58] Bug fixes for laser offset and avatar hold action --- interface/src/avatar/AvatarActionHold.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 24 ------------------- interface/src/avatar/MyAvatar.h | 1 - interface/src/raypick/JointRayPick.cpp | 2 +- .../system/controllers/handControllerGrab.js | 2 +- scripts/system/libraries/controllers.js | 8 +++++-- 6 files changed, 9 insertions(+), 30 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index fe5355ff2e..a47bbbad1b 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -165,7 +165,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm:: Transform avatarTransform; avatarTransform = myAvatar->getTransform(); - palmPosition = avatarTransform.transform(camRelPos / myAvatar->getDomainLimitedScale()); + palmPosition = avatarTransform.transform(camRelPos); palmRotation = avatarTransform.getRotation() * camRelRot; } else { glm::vec3 avatarRigidBodyPosition; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index eca61d95c8..9654f989a0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2940,30 +2940,6 @@ glm::mat4 MyAvatar::computeCameraRelativeHandControllerMatrix(const glm::mat4& c return glm::inverse(avatarMatrix) * controllerWorldMatrix; } -glm::vec3 MyAvatar::getAbsoluteJointScaleInObjectFrame(int index) const { - if (index < 0) { - index += numeric_limits::max() + 1; // 65536 - } - - // only sensor to world matrix has non identity scale. - switch (index) { - case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return extractScale(result); - } - case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return extractScale(result); - } - default: - return Avatar::getAbsoluteJointScaleInObjectFrame(index); - } -} - glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 07ad61b271..1c7cd559a6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -513,7 +513,6 @@ public: Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated Q_INVOKABLE bool getCharacterControllerEnabled(); // deprecated - virtual glm::vec3 getAbsoluteJointScaleInObjectFrame(int index) const override; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index 48ab908201..b4f0dde687 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -36,7 +36,7 @@ const PickRay JointRayPick::getPickRay(bool& valid) const { glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot; // Apply offset - pos = pos + (rot * _posOffset); + pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset)); glm::vec3 dir = rot * glm::normalize(_dirOffset); valid = true; diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index e1c12604fe..dacacae5b3 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1184,7 +1184,7 @@ function MyController(hand) { joint: (hand == RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS | RayPick.PICK_INCLUDE_NONCOLLIDABLE, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates diff --git a/scripts/system/libraries/controllers.js b/scripts/system/libraries/controllers.js index dd73aa7f8d..d99fd0db48 100644 --- a/scripts/system/libraries/controllers.js +++ b/scripts/system/libraries/controllers.js @@ -18,7 +18,7 @@ getGrabCommunications = function getFarGrabCommunications() { // this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral -getGrabPointSphereOffset = function(handController) { +getGrabPointSphereOffset = function(handController, ignoreSensorToWorldScale) { var offset = GRAB_POINT_SPHERE_OFFSET; if (handController === Controller.Standard.LeftHand) { offset = { @@ -27,7 +27,11 @@ getGrabPointSphereOffset = function(handController) { z: GRAB_POINT_SPHERE_OFFSET.z }; } - return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); + if (ignoreSensorToWorldScale) { + return offset; + } else { + return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); + } }; // controllerWorldLocation is where the controller would be, in-world, with an added offset From 26e9e6e580fb7497c013ae75cc784f9a4763deb4 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 1 Sep 2017 11:19:51 -0700 Subject: [PATCH 25/58] Fixes for stylus ranges and grab radii --- .../system/controllers/handControllerGrab.js | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index dacacae5b3..d5e1726332 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1651,8 +1651,11 @@ function MyController(hand) { hysteresisOffset = 0.05; } - this.isNearStylusTarget = isNearStylusTarget(stylusTargets, EDGE_BORDER + hysteresisOffset, - TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset, WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset); + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + this.isNearStylusTarget = isNearStylusTarget(stylusTargets, + (EDGE_BORDER + hysteresisOffset) * sensorScaleFactor, + (TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset) * sensorScaleFactor, + (WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset) * sensorScaleFactor); if (this.isNearStylusTarget) { if (!this.useFingerInsteadOfStylus) { @@ -1742,9 +1745,10 @@ function MyController(hand) { } // when the grab-point enters a grabable entity, give a haptic pulse - candidateEntities = Entities.findEntities(worldHandPosition, NEAR_GRAB_RADIUS); + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + candidateEntities = Entities.findEntities(worldHandPosition, NEAR_GRAB_RADIUS * sensorScaleFactor); var grabbableEntities = candidateEntities.filter(function(entity) { - return _this.entityIsNearGrabbable(entity, worldHandPosition, NEAR_GRAB_MAX_DISTANCE); + return _this.entityIsNearGrabbable(entity, worldHandPosition, NEAR_GRAB_MAX_DISTANCE * sensorScaleFactor); }); if (grabbableEntities.length > 0) { if (!this.grabPointIntersectsEntity) { @@ -2242,12 +2246,13 @@ function MyController(hand) { } } - var candidateEntities = Entities.findEntities(handPosition, NEAR_GRAB_RADIUS); + var sensorScaleFactor = MyAvatar.sensorToWorldMatrix + var candidateEntities = Entities.findEntities(handPosition, NEAR_GRAB_RADIUS * sensorScaleFactor); var grabbableEntities = candidateEntities.filter(function(entity) { - return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE); + return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE * sensorScaleFactor); }); - var candidateOverlays = Overlays.findOverlays(handPosition, NEAR_GRAB_RADIUS); + var candidateOverlays = Overlays.findOverlays(handPosition, NEAR_GRAB_RADIUS * sensorScaleFactor); var grabbableOverlays = candidateOverlays.filter(function(overlayID) { return Overlays.getProperty(overlayID, "grabbable"); }); @@ -2756,9 +2761,10 @@ function MyController(hand) { } var rayPositionOnEntity = Vec3.subtract(grabbedProperties.position, this.offsetPosition); //Far to Near Grab: If object is draw by user inside FAR_TO_NEAR_GRAB_MAX_DISTANCE, grab it + var sensorScaleFactor = MyAvatar.sensorToWorldScale; if (this.entityIsFarToNearGrabbable(rayPositionOnEntity, controllerLocation.position, - FAR_TO_NEAR_GRAB_MAX_DISTANCE)) { + FAR_TO_NEAR_GRAB_MAX_DISTANCE * sensorScaleFactor)) { this.farToNearGrab = true; Entities.deleteAction(this.grabbedThingID, this.actionID); From f0912987a384dc33c289c4f00718b5c7b4816513 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 5 Sep 2017 10:03:19 -0700 Subject: [PATCH 26/58] Fix ray picks against HUD sphere at different sensor scale factors --- interface/src/Application.cpp | 2 +- .../src/raypick/RayPickScriptingInterface.cpp | 2 +- .../src/display-plugins/CompositorHelper.cpp | 25 ++++++++++++------- .../src/display-plugins/CompositorHelper.h | 6 ++++- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 458026c6a8..79885cc6b6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2551,7 +2551,7 @@ void Application::paintGL() { { PROFILE_RANGE(render, "/updateCompositor"); - getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform()); + getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform(), getMyAvatar()->getSensorToWorldMatrix()); } gpu::FramebufferPointer finalFramebuffer; diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index 015f8fd7d1..cb2b3e4471 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -108,4 +108,4 @@ void RayPickScriptingInterface::setIgnoreAvatars(QUuid uid, const QScriptValue& void RayPickScriptingInterface::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { qApp->getRayPickManager().setIncludeAvatars(uid, includeAvatars); -} \ No newline at end of file +} diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index f09b3d7109..2f57cc29d0 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -339,23 +340,29 @@ void CompositorHelper::computeHmdPickRay(const glm::vec2& cursorPos, glm::vec3& glm::mat4 CompositorHelper::getUiTransform() const { glm::mat4 modelMat; _modelTransform.getMatrix(modelMat); - return _currentCamera * glm::inverse(_currentDisplayPlugin->getHeadPose()) * modelMat; + return _sensorToWorldMatrix * modelMat; } //Finds the collision point of a world space ray bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const { - auto UITransform = getUiTransform(); - auto relativePosition4 = glm::inverse(UITransform) * vec4(position, 1); - auto relativePosition = vec3(relativePosition4) / relativePosition4.w; - auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction; + glm::mat4 uiToWorld = getUiTransform(); + glm::mat4 worldToUi = glm::inverse(uiToWorld); + glm::vec3 localPosition = transformPoint(worldToUi, position); + glm::vec3 localDirection = glm::normalize(transformVectorFast(worldToUi, direction)); - const float UI_RADIUS = 1.0f; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale + const float UI_RADIUS = 1.0f; float instersectionDistance; - if (raySphereIntersect(relativeDirection, relativePosition, UI_RADIUS, &instersectionDistance)){ - result = position + glm::normalize(direction) * instersectionDistance; + if (raySphereIntersect(localDirection, localPosition, UI_RADIUS, &instersectionDistance)) { + result = transformPoint(uiToWorld, localPosition + localDirection * instersectionDistance); +#ifdef WANT_DEBUG + DebugDraw::getInstance().drawRay(position, result, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f)); +#endif return true; + } else { +#ifdef WANT_DEBUG + DebugDraw::getInstance().drawRay(position, position + (direction * 1000.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); +#endif } - return false; } diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 946229fc9b..b1d2815f65 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -109,7 +109,10 @@ public: void setReticleOverDesktop(bool value) { _isOverDesktop = value; } void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; } - void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; } + void setFrameInfo(uint32_t frame, const glm::mat4& camera, const glm::mat4& sensorToWorldMatrix) { + _currentCamera = camera; + _sensorToWorldMatrix = sensorToWorldMatrix; + } signals: void allowMouseCaptureChanged(); @@ -124,6 +127,7 @@ private: DisplayPluginPointer _currentDisplayPlugin; glm::mat4 _currentCamera; + glm::mat4 _sensorToWorldMatrix; QWidget* _renderingWidget{ nullptr }; //// Support for hovering and tooltips From 23ff1b9eade583752416300186616ccc4fd8383c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 5 Sep 2017 15:03:41 -0700 Subject: [PATCH 27/58] Fixes for scaling controller display Adds MyAvatar.sensorToWorldScaleChanged signal. --- interface/src/avatar/MyAvatar.cpp | 12 ++++ interface/src/avatar/MyAvatar.h | 3 + .../src/avatars-renderer/Avatar.h | 4 +- .../system/controllers/controllerDisplay.js | 56 +++++++++++++++---- .../controllers/controllerDisplayManager.js | 12 +++- .../system/controllers/handControllerGrab.js | 4 +- .../viveControllerConfiguration.js | 46 ++++++++++----- scripts/system/libraries/utils.js | 4 +- scripts/system/tablet-ui/tabletUI.js | 17 +++--- tools/dimensions.mel | 30 ++++++++++ 10 files changed, 146 insertions(+), 42 deletions(-) create mode 100644 tools/dimensions.mel diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9654f989a0..96688da587 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2651,6 +2651,9 @@ float MyAvatar::getUserHeight() const { void MyAvatar::setUserHeight(float value) { _userHeight.set(value); + + float sensorToWorldScale = getEyeHeight() / getUserEyeHeight(); + emit sensorToWorldScaleChanged(sensorToWorldScale); } float MyAvatar::getUserEyeHeight() const { @@ -3207,3 +3210,12 @@ void MyAvatar::updateHoldActions(const AnimPose& prePhysicsPose, const AnimPose& const MyHead* MyAvatar::getMyHead() const { return static_cast(getHead()); } + +void MyAvatar::setModelScale(float scale) { + bool changed = (scale != getModelScale()); + Avatar::setModelScale(scale); + if (changed) { + float sensorToWorldScale = getEyeHeight() / getUserEyeHeight(); + emit sensorToWorldScaleChanged(sensorToWorldScale); + } +} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 1c7cd559a6..f8617bd309 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -590,6 +590,8 @@ public slots: glm::vec3 getPositionForAudio(); glm::quat getOrientationForAudio(); + virtual void setModelScale(float scale) override; + signals: void audioListenerModeChanged(); void transformChanged(); @@ -602,6 +604,7 @@ signals: void wentActive(); void skeletonChanged(); void dominantHandChanged(const QString& hand); + void sensorToWorldScaleChanged(float sensorToWorldScale); private: diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index e4eb02b817..0f9a03d3de 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -261,8 +261,8 @@ public: */ Q_INVOKABLE float getEyeHeight() const; - float getModelScale() const { return _modelScale; } - void setModelScale(float scale) { _modelScale = scale; } + virtual float getModelScale() const { return _modelScale; } + virtual void setModelScale(float scale) { _modelScale = scale; } public slots: diff --git a/scripts/system/controllers/controllerDisplay.js b/scripts/system/controllers/controllerDisplay.js index 980829e0a3..af8cfa74f4 100644 --- a/scripts/system/controllers/controllerDisplay.js +++ b/scripts/system/controllers/controllerDisplay.js @@ -59,7 +59,8 @@ createControllerDisplay = function(config) { }, setPartVisible: function(partName, visible) { - return; + // Disabled + /* if (partName in this.partOverlays) { for (var i = 0; i < this.partOverlays[partName].length; ++i) { Overlays.editOverlay(this.partOverlays[partName][i], { @@ -67,6 +68,7 @@ createControllerDisplay = function(config) { }); } } + */ }, setLayerForPart: function(partName, layerName) { @@ -85,12 +87,45 @@ createControllerDisplay = function(config) { } } } + }, + + resize: function(sensorScaleFactor) { + if (this.overlays.length >= 0) { + var controller = config.controllers[0]; + var position = controller.position; + + // first overlay is main body. + var overlayID = this.overlays[0]; + var localPosition = Vec3.multiply(sensorScaleFactor, Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position)); + var dimensions = Vec3.multiply(sensorScaleFactor, controller.dimensions); + + Overlays.editOverlay(overlayID, { + dimensions: dimensions, + localPosition: localPosition + }); + + if (controller.parts) { + var i = 1; + for (var partName in controller.parts) { + overlayID = this.overlays[i++]; + var part = controller.parts[partName]; + var partPosition = Vec3.multiply(sensorScaleFactor, Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, part.naturalPosition))); + var partDimensions = Vec3.multiply(sensorScaleFactor, part.naturalDimensions); + Overlays.editOverlay(overlayID, { + dimensions: partDimensions, + localPosition: partPosition + }); + } + } + } } }; + var mapping = Controller.newMapping(controllerDisplay.mappingName); for (var i = 0; i < config.controllers.length; ++i) { var controller = config.controllers[i]; var position = controller.position; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; if (controller.naturalPosition) { position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position); @@ -98,9 +133,9 @@ createControllerDisplay = function(config) { var overlayID = Overlays.addOverlay("model", { url: controller.modelURL, - dimensions: controller.dimensions, + dimensions: Vec3.multiply(sensorScaleFactor, controller.dimensions), localRotation: controller.rotation, - localPosition: position, + localPosition: Vec3.multiply(sensorScaleFactor, position), parentID: PARENT_ID, parentJointIndex: controller.jointIndex, ignoreRayIntersection: true @@ -176,8 +211,8 @@ createControllerDisplay = function(config) { }); } else if (part.type === "joystick") { (function(controller, overlayID, part) { - const xInput = resolveHardware(part.xInput); - const yInput = resolveHardware(part.yInput); + var xInput = resolveHardware(part.xInput); + var yInput = resolveHardware(part.yInput); var xvalue = 0; var yvalue = 0; @@ -190,21 +225,20 @@ createControllerDisplay = function(config) { offset = Vec3.multiplyQbyV(rotation, part.originOffset); offset = Vec3.subtract(part.originOffset, offset); } - + var partPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, Vec3.sum(offset, part.naturalPosition))); - var partRotation = Quat.multiply(controller.rotation, rotation) + var partRotation = Quat.multiply(controller.rotation, rotation); return { position: partPosition, rotation: partRotation - } + }; } mapping.from([xInput]).peek().to(function(value) { xvalue = value; - //print(overlayID, xvalue.toFixed(3), yvalue.toFixed(3)); var posRot = calculatePositionAndRotation(xvalue, yvalue); Overlays.editOverlay(overlayID, { localPosition: posRot.position, @@ -224,10 +258,9 @@ createControllerDisplay = function(config) { } else if (part.type === "linear") { (function(controller, overlayID, part) { - const input = resolveHardware(part.input); + var input = resolveHardware(part.input); mapping.from([input]).peek().to(function(value) { - //print(value); var axis = Vec3.multiplyQbyV(controller.rotation, part.axis); var offset = Vec3.multiply(part.maxTranslation * value, axis); @@ -256,6 +289,7 @@ createControllerDisplay = function(config) { } } Controller.enableMapping(controllerDisplay.mappingName); + controllerDisplay.resize(MyAvatar.sensorToWorldScale); return controllerDisplay; }; diff --git a/scripts/system/controllers/controllerDisplayManager.js b/scripts/system/controllers/controllerDisplayManager.js index 56becfc453..e3fd74e05b 100644 --- a/scripts/system/controllers/controllerDisplayManager.js +++ b/scripts/system/controllers/controllerDisplayManager.js @@ -56,7 +56,6 @@ ControllerDisplayManager = function() { } if (leftConfig !== null && rightConfig !== null) { - print("Loading controllers"); if (controllerLeft === null) { controllerLeft = createControllerDisplay(leftConfig); controllerLeft.setVisible(true); @@ -70,6 +69,7 @@ ControllerDisplayManager = function() { Script.clearInterval(controllerCheckerIntervalID); controllerCheckerIntervalID = null; } + } else { self.deleteControllerDisplays(); if (!controllerCheckerIntervalID) { @@ -86,6 +86,15 @@ ControllerDisplayManager = function() { } } + function resizeControllers(sensorScaleFactor) { + if (controllerLeft) { + controllerLeft.resize(sensorScaleFactor); + } + if (controllerRight) { + controllerRight.resize(sensorScaleFactor); + } + }; + var handleMessages = function(channel, message, sender) { var i, data, name, visible; if (!controllerLeft && !controllerRight) { @@ -171,6 +180,7 @@ ControllerDisplayManager = function() { HMD.displayModeChanged.connect(updateControllers); HMD.shouldShowHandControllersChanged.connect(updateControllers); + MyAvatar.sensorToWorldScaleChanged.connect(resizeControllers); updateControllers(); }; diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d5e1726332..f66a8f976d 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3035,7 +3035,7 @@ function MyController(hand) { if (this.grabbedIsOverlay) { Overlays.editOverlay(this.grabbedThingID, reparentProps); - // AJT: resize tablet to allow it to counter scale. + // resize tablet to allow it to counter scale. if (this.grabbedThingID === HMD.tabletID) { resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex); } @@ -3815,7 +3815,7 @@ function MyController(hand) { parentID: this.previousParentID[this.grabbedThingID], parentJointIndex: this.previousParentJointIndex[this.grabbedThingID], }); - // AJT: resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix + // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix if (this.grabbedThingID === HMD.tabletID) { resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]); } diff --git a/scripts/system/controllers/viveControllerConfiguration.js b/scripts/system/controllers/viveControllerConfiguration.js index 51cbb69473..dc4a5b6bb3 100644 --- a/scripts/system/controllers/viveControllerConfiguration.js +++ b/scripts/system/controllers/viveControllerConfiguration.js @@ -62,7 +62,7 @@ var TIP_TEXTURE_BASE_URL = BASE_URL + "meshes/controller/vive_tips.fbm/"; var viveModelURL = BASE_URL + "meshes/controller/vive_body.fbx"; var viveTipsModelURL = BASE_URL + "meshes/controller/vive_tips.fbx"; -var viveTriggerModelURL = "meshes/controller/vive_trigger.fbx" +var viveTriggerModelURL = "meshes/controller/vive_trigger.fbx"; VIVE_CONTROLLER_CONFIGURATION_LEFT = { name: "Vive", @@ -81,6 +81,7 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { type: "static", modelURL: viveTipsModelURL, naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, + naturalDimensions: {x: 0.191437, y: 0.094095, z: 0.085656}, textureName: "Tex.Blank", defaultTextureLayer: "blank", @@ -112,6 +113,7 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { xInput: "Vive.LX", yInput: "Vive.LY", naturalPosition: {"x":0,"y":0.000979491975158453,"z":0.04872849956154823}, + naturalDimensions: {x: 0.042824, y: 0.012537, z: 0.043115}, minValue: 0.0, maxValue: 1.0, minPosition: { x: -0.035, y: 0.004, z: -0.005 }, @@ -137,6 +139,7 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx", input: Controller.Standard.LT, naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763}, + naturalDimensions: {x: 0.019105, y: 0.022189, z: 0.01909}, origin: { x: 0, y: -0.015, z: -0.00 }, minValue: 0.0, maxValue: 1.0, @@ -147,10 +150,10 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { defaultTextureLayer: "normal", textureLayers: { normal: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg", + defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg" }, highlight: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg", + defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg" } } }, @@ -158,30 +161,35 @@ VIVE_CONTROLLER_CONFIGURATION_LEFT = { l_grip: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx", - naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226} + naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, + naturalDimensions: {x: 0.010094, y: 0.015064, z: 0.029552} }, r_grip: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx", - naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226} + naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, + naturalDimensions: {x: 0.010083, y: 0.015064, z: 0.029552} }, sys_button: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx", - naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311} + naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}, + naturalDimensions: {x: 0.009986, y: 0.004282, z: 0.010264} }, button: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564} + naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, + naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} }, button2: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564} + naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, + naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} } } } @@ -211,6 +219,7 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { type: "static", modelURL: viveTipsModelURL, naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323}, + naturalDimensions: {x: 0.191437, y: 0.094095, z: 0.085656}, textureName: "Tex.Blank", @@ -243,6 +252,7 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { xInput: "Vive.RX", yInput: "Vive.RY", naturalPosition: { x: 0, y: 0.000979491975158453, z: 0.04872849956154823 }, + naturalDimensions: {x: 0.042824, y: 0.012537, z: 0.043115}, minValue: 0.0, maxValue: 1.0, minPosition: { x: -0.035, y: 0.004, z: -0.005 }, @@ -268,6 +278,7 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx", input: Controller.Standard.RT, naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763}, + naturalDimensions: {x: 0.019105, y: 0.022189, z: 0.01909}, origin: { x: 0, y: -0.015, z: -0.00 }, minValue: 0.0, maxValue: 1.0, @@ -278,10 +289,10 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { defaultTextureLayer: "normal", textureLayers: { normal: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg", + defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/black.jpg" }, highlight: { - defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg", + defaultTextureURL: BASE_URL + viveTriggerModelURL + "/Trigger.fbm/yellow.jpg" } } }, @@ -289,30 +300,35 @@ VIVE_CONTROLLER_CONFIGURATION_RIGHT = { l_grip: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx", - naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226} + naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, + naturalDimensions: {x: 0.010094, y: 0.015064, z: 0.029552} }, r_grip: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx", - naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226} + naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}, + naturalDimensions: {x: 0.010083, y: 0.015064, z: 0.029552} }, sys_button: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx", - naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311} + naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}, + naturalDimensions: {x: 0.009986, y: 0.004282, z: 0.010264} }, button: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564} + naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, + naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} }, button2: { type: "static", modelURL: BASE_URL + "meshes/controller/vive_button.fbx", - naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564} + naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}, + naturalDimensions: {x: 0.009986, y: 0.004496, z: 0.010121} } } } diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index b79ff03550..162edcaea0 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -368,13 +368,13 @@ getTabletWidthFromSettings = function () { return DEFAULT_TABLET_WIDTH * (tabletScalePercentage / 100); }; -resizeTablet = function (width, newParentJointIndex) { +resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) { if (!HMD.tabletID || !HMD.tabletScreenID || !HMD.homeButtonID) { return; } - var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var sensorScaleFactor = sensorToWorldScaleOverride || MyAvatar.sensorToWorldScale; var sensorScaleOffsetOverride = 1; var SENSOR_TO_ROOM_MATRIX = 65534; var parentJointIndex = newParentJointIndex || Overlays.getProperty(HMD.tabletID, "parentJointIndex"); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 4a77740d9b..e52d0b530b 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -28,7 +28,6 @@ var MSECS_PER_SEC = 1000.0; var MUTE_MICROPHONE_MENU_ITEM = "Mute Microphone"; var gTablet = null; - var avatarSensorScale = MyAvatar.sensorToWorldScale; Script.include("../libraries/WebTablet.js"); @@ -74,7 +73,7 @@ function updateTabletWidthFromSettings(force) { var newTabletScalePercentage = getTabletScalePercentageFromSettings(); - if ((force || newTabletScalePercentage !== tabletScalePercentage) && UIWebTablet) { + if ((force || (newTabletScalePercentage !== tabletScalePercentage)) && UIWebTablet) { tabletScalePercentage = newTabletScalePercentage; UIWebTablet.setWidth(DEFAULT_WIDTH * (tabletScalePercentage / 100)); } @@ -84,6 +83,11 @@ updateTabletWidthFromSettings(); } + function onSensorToWorldScaleChanged(sensorScaleFactor) { + var newTabletScalePercentage = getTabletScalePercentageFromSettings(); + resizeTablet(DEFAULT_WIDTH * (newTabletScalePercentage / 100), undefined, sensorScaleFactor); + } + function rezTablet() { if (debugTablet) { print("TABLET rezzing"); @@ -99,6 +103,7 @@ HMD.homeButtonID = UIWebTablet.homeButtonID; HMD.tabletScreenID = UIWebTablet.webOverlayID; HMD.displayModeChanged.connect(onHmdChanged); + MyAvatar.sensorToWorldScaleChanged.connect(onSensorToWorldScaleChanged); tabletRezzed = true; } @@ -188,13 +193,7 @@ if (now - validCheckTime > MSECS_PER_SEC) { validCheckTime = now; - // force tablet to resize if sensorToWorldScale changes - var force = false; - if (avatarSensorScale !== MyAvatar.sensorToWorldScale) { - force = true; - avatarSensorScale = MyAvatar.sensorToWorldScale; - } - updateTabletWidthFromSettings(force); + updateTabletWidthFromSettings(); if (UIWebTablet) { UIWebTablet.setLandscape(landscape); diff --git a/tools/dimensions.mel b/tools/dimensions.mel new file mode 100644 index 0000000000..c477fd04e8 --- /dev/null +++ b/tools/dimensions.mel @@ -0,0 +1,30 @@ +// +// dimensions.mel +// +// Created by Anthony J. Thibault on September 5th, 2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Maya Mel script to determine the High Fidelity "naturalDimensions" of a model. + +// get a list of all mesh objects +string $meshes[] = `ls -type mesh`; + +// compute the bounding box +float $boundingBox[] = `polyEvaluate -boundingBox $meshes`; + +// copy values into variables for readability +float $xmin = $boundingBox[0]; +float $xmax = $boundingBox[1]; +float $ymin = $boundingBox[2]; +float $ymax = $boundingBox[3]; +float $zmin = $boundingBox[4]; +float $zmax = $boundingBox[5]; + +// compute dimensions, and convert from cm to meters +vector $dim = <<($xmax - $xmin) / 100.0, ($ymax - $ymin) / 100.0, ($zmax - $zmin) / 100.0>>; + +// print result +print $dim; From 3d3bb2853ac98fdf0aedc8ad59f65e61d42705b6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 5 Sep 2017 15:39:35 -0700 Subject: [PATCH 28/58] Updated naturalDimensiosn for touch controller config Totally untested! I don't have an oculus. I'm sure it will work tho. ;) --- .../controllers/touchControllerConfiguration.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/system/controllers/touchControllerConfiguration.js b/scripts/system/controllers/touchControllerConfiguration.js index a4622fd5e6..9df8f9e97d 100644 --- a/scripts/system/controllers/touchControllerConfiguration.js +++ b/scripts/system/controllers/touchControllerConfiguration.js @@ -55,6 +55,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "static", modelURL: BASE_URL + "Oculus-Labels-L.fbx", naturalPosition: { x: -0.022335469722747803, y: 0.00022516027092933655, z: 0.020340695977211 }, + naturalDimensions: { x: 0.132063, y: 0.0856, z: 0.130282 }, textureName: "blank", defaultTextureLayer: "blank", @@ -84,6 +85,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "rotational", modelURL: BASE_URL + "touch_l_trigger.fbx", naturalPosition: { x: 0.0008544912561774254, y: -0.019867943599820137, z: 0.018800459802150726 }, + naturalDimensions: { x: 0.027509, y: 0.025211, z: 0.018443 }, // rotational input: Controller.Standard.LT, @@ -109,6 +111,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "linear", modelURL: BASE_URL + "touch_l_bumper.fbx", naturalPosition: { x: 0.00008066371083259583, y: -0.02715788595378399, z: -0.02448512241244316 }, + naturalDimensions: { x: 0.017444, y: 0.020297, z: 0.026003 }, // linear properties // Offset from origin = 0.36470, 0.11048, 0.11066 @@ -132,6 +135,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "joystick", modelURL: BASE_URL + "touch_l_joystick.fbx", naturalPosition: { x: 0.0075613949447870255, y: -0.008225866593420506, z: 0.004792703315615654 }, + naturalDimensions: { x: 0.027386, y: 0.033254, z: 0.027272 }, // joystick xInput: "OculusTouch.LX", @@ -156,6 +160,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "linear", modelURL: BASE_URL + "touch_l_button_x.fbx", naturalPosition: { x: -0.009307309985160828, y: -0.00005015172064304352, z: -0.012594521045684814 }, + naturalDimensions: { x: 0.009861, y: 0.004345, z: 0.00982 }, input: "OculusTouch.X", axis: { x: 0, y: -1, z: 0 }, @@ -177,6 +182,7 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = { type: "linear", modelURL: BASE_URL + "touch_l_button_y.fbx", naturalPosition: { x: -0.01616849936544895, y: -0.000050364527851343155, z: 0.0017703399062156677 }, + naturalDimensions: { x: 0.010014, y: 0.004412, z: 0.009972 }, input: "OculusTouch.Y", axis: { x: 0, y: -1, z: 0 }, @@ -214,6 +220,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "static", modelURL: BASE_URL + "Oculus-Labels-R.fbx", naturalPosition: { x: 0.009739525616168976, y: -0.0017818436026573181, z: 0.016794726252555847 }, + naturalDimensions: { x: 0.129049, y: 0.078297, z: 0.139492 }, textureName: "blank", defaultTextureLayer: "blank", @@ -243,6 +250,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "rotational", modelURL: BASE_URL + "touch_r_trigger.fbx", naturalPosition: { x: -0.0008544912561774254, y: -0.019867943599820137, z: 0.018800459802150726 }, + naturalDimensions: { x: 0.027384, y: 0.025201, z: 0.018425 }, // rotational input: "OculusTouch.RT", @@ -268,6 +276,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "linear", modelURL: BASE_URL + "touch_r_bumper.fbx", naturalPosition: { x: -0.0000806618481874466, y: -0.027157839387655258, z: -0.024485092610120773 }, + naturalDimensions: { x: 0.017268, y: 0.020366, z: 0.02599 }, // linear properties // Offset from origin = 0.36470, 0.11048, 0.11066 @@ -292,6 +301,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "joystick", modelURL: BASE_URL + "touch_r_joystick.fbx", naturalPosition: { x: -0.007561382371932268, y: -0.008225853554904461, z: 0.00479268841445446 }, + naturalDimensions: { x: 0.027272, y: 0.033254, z: 0.027272 }, // joystick xInput: "OculusTouch.RX", @@ -316,6 +326,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "linear", modelURL: BASE_URL + "touch_r_button_a.fbx", naturalPosition: { x: 0.009307296946644783, y: -0.00005015172064304352, z: -0.012594504281878471 }, + naturalDimensions: { x: 0.00982, y: 0.004345, z: 0.00982 }, input: "OculusTouch.A", axis: { x: 0, y: -1, z: 0 }, @@ -337,6 +348,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = { type: "linear", modelURL: BASE_URL + "touch_r_button_b.fbx", naturalPosition: { x: 0.01616847701370716, y: -0.000050364527851343155, z: 0.0017703361809253693 }, + naturalDimensions: { x: 0.009972, y: 0.004412, z: 0.009972 }, input: "OculusTouch.B", axis: { x: 0, y: -1, z: 0 }, From a34dae4aade95e99383bb30a6d5c530e1c98cd7f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 5 Sep 2017 17:12:40 -0700 Subject: [PATCH 29/58] adding scale to notifications --- scripts/system/notifications.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index b34630f3f8..111ebd4506 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -207,7 +207,7 @@ notificationOrientation, notificationPosition, buttonPosition; - + var sensorScaleFactor = MyAvatar.sensorToWorldScale; // Notification plane positions noticeY = -y * NOTIFICATION_3D_SCALE - noticeHeight / 2; notificationPosition = { x: 0, y: noticeY, z: 0 }; @@ -221,8 +221,8 @@ // Translate plane originOffset = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, NOTIFICATIONS_3D_DIRECTION, 0), - { x: 0, y: 0, z: -NOTIFICATIONS_3D_DISTANCE }); - originOffset.y += NOTIFICATIONS_3D_ELEVATION; + { x: 0, y: 0, z: -NOTIFICATIONS_3D_DISTANCE * sensorScaleFactor}); + originOffset.y += NOTIFICATIONS_3D_ELEVATION * sensorScaleFactor; notificationPosition = Vec3.sum(originOffset, notificationPosition); buttonPosition = Vec3.sum(originOffset, buttonPosition); @@ -242,14 +242,14 @@ noticeHeight, positions, last; - + var sensorScaleFactor = MyAvatar.sensorToWorldScale; if (isOnHMD) { // Calculate 3D values from 2D overlay properties. noticeWidth = notice.width * NOTIFICATION_3D_SCALE + NOTIFICATION_3D_BUTTON_WIDTH; noticeHeight = notice.height * NOTIFICATION_3D_SCALE; - notice.size = { x: noticeWidth, y: noticeHeight }; + notice.size = { x: noticeWidth, y: noticeHeight}; positions = calculate3DOverlayPositions(noticeWidth, noticeHeight, notice.y); @@ -261,7 +261,7 @@ notice.leftMargin = 2 * notice.leftMargin * NOTIFICATION_3D_SCALE; notice.bottomMargin = 0; notice.rightMargin = 0; - notice.lineHeight = 10.0 * (fontSize / 12.0) * NOTIFICATION_3D_SCALE; + notice.lineHeight = 10.0 * (fontSize * sensorScaleFactor / 12.0) * NOTIFICATION_3D_SCALE; notice.isFacingAvatar = false; notificationText = Overlays.addOverlay("text3d", notice); @@ -366,6 +366,7 @@ buttonProperties, i; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; if (text.length >= breakPoint) { breaks = count; } @@ -387,7 +388,7 @@ alpha: backgroundAlpha, topMargin: topMargin, leftMargin: leftMargin, - font: {size: fontSize}, + font: {size: fontSize * sensorScaleFactor}, text: text }; From af8b147321169c6617f8933e7cc43d7f6f01b8d5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 5 Sep 2017 17:34:35 -0700 Subject: [PATCH 30/58] away.js - works better with sensor scale. --- scripts/system/away.js | 64 +++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/scripts/system/away.js b/scripts/system/away.js index f98408376d..18eb5fa946 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -14,6 +14,8 @@ // Goes into "paused" when the '.' key (and automatically when started in HMD), and normal when pressing any key. // See MAIN CONTROL, below, for what "paused" actually does. +/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ + (function() { // BEGIN LOCAL_SCOPE var BASIC_TIMER_INTERVAL = 50; // 50ms = 20hz @@ -28,18 +30,22 @@ var OVERLAY_DATA = { }; var AVATAR_MOVE_FOR_ACTIVE_DISTANCE = 0.8; // meters -- no longer away if avatar moves this far while away -var lastOverlayPosition = { x: 0, y: 0, z: 0}; +var AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}"; +var CAMERA_MATRIX = -7; + var OVERLAY_DATA_HMD = { - position: lastOverlayPosition, + localPosition: {x: 0, y: 0, z: -1 * MyAvatar.sensorToWorldScale}, + localRotation: {x: 0, y: 0, z: 0, w: 1}, width: OVERLAY_WIDTH, height: OVERLAY_HEIGHT, url: "http://hifi-content.s3.amazonaws.com/alan/production/images/images/Overlay-Viz-blank.png", color: {red: 255, green: 255, blue: 255}, alpha: 1, - scale: 2, + scale: 2 * MyAvatar.sensorToWorldScale, emissive: true, - isFacingAvatar: true, - drawInFront: true + drawInFront: true, + parentID: AVATAR_SELF_ID, + parentJointIndex: CAMERA_MATRIX }; var AWAY_INTRO = { @@ -83,25 +89,11 @@ function stopAwayAnimation() { var overlay = Overlays.addOverlay("image", OVERLAY_DATA); var overlayHMD = Overlays.addOverlay("image3d", OVERLAY_DATA_HMD); -function moveCloserToCamera(positionAtHUD) { - // we don't actually want to render at the slerped look at... instead, we want to render - // slightly closer to the camera than that. - var MOVE_CLOSER_TO_CAMERA_BY = -0.25; - var cameraForward = Quat.getForward(Camera.orientation); - var closerToCamera = Vec3.multiply(cameraForward, MOVE_CLOSER_TO_CAMERA_BY); // slightly closer to camera - var slightlyCloserPosition = Vec3.sum(positionAtHUD, closerToCamera); - - return slightlyCloserPosition; -} - function showOverlay() { if (HMD.active) { // make sure desktop version is hidden Overlays.editOverlay(overlay, { visible: false }); - - lastOverlayPosition = HMD.getHUDLookAtPosition3D(); - var actualOverlayPositon = moveCloserToCamera(lastOverlayPosition); - Overlays.editOverlay(overlayHMD, { visible: true, position: actualOverlayPositon }); + Overlays.editOverlay(overlayHMD, { visible: true }); } else { // make sure HMD is hidden Overlays.editOverlay(overlayHMD, { visible: false }); @@ -110,9 +102,11 @@ function showOverlay() { var screen = Controller.getViewportDimensions(); // keep the overlay it's natural size and always center it... - Overlays.editOverlay(overlay, { visible: true, - x: ((screen.x - OVERLAY_WIDTH) / 2), - y: ((screen.y - OVERLAY_HEIGHT) / 2) }); + Overlays.editOverlay(overlay, { + visible: true, + x: ((screen.x - OVERLAY_WIDTH) / 2), + y: ((screen.y - OVERLAY_HEIGHT) / 2) + }); } } @@ -132,16 +126,10 @@ function maybeMoveOverlay() { } if (HMD.active) { - // Note: instead of moving it directly to the lookAt, we will move it slightly toward the - // new look at. This will result in a more subtle slerp toward the look at and reduce jerkiness - var EASE_BY_RATIO = 0.1; - var lookAt = HMD.getHUDLookAtPosition3D(); - var lookAtChange = Vec3.subtract(lookAt, lastOverlayPosition); - var halfWayBetweenOldAndLookAt = Vec3.multiply(lookAtChange, EASE_BY_RATIO); - var newOverlayPosition = Vec3.sum(lastOverlayPosition, halfWayBetweenOldAndLookAt); - lastOverlayPosition = newOverlayPosition; - var actualOverlayPositon = moveCloserToCamera(lastOverlayPosition); - Overlays.editOverlay(overlayHMD, { visible: true, position: actualOverlayPositon }); + + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var localPosition = {x: 0, y: 0, z: -1 * sensorScaleFactor}; + Overlays.editOverlay(overlayHMD, { visible: true, localPosition: localPosition, scale: 2 * sensorScaleFactor }); // make sure desktop version is hidden Overlays.editOverlay(overlay, { visible: false }); @@ -191,8 +179,8 @@ function goActive() { MyAvatar.isAway = false; } -MyAvatar.wentAway.connect(setAwayProperties) -MyAvatar.wentActive.connect(setActiveProperties) +MyAvatar.wentAway.connect(setAwayProperties); +MyAvatar.wentActive.connect(setActiveProperties); function setAwayProperties() { isAway = true; @@ -254,7 +242,7 @@ function maybeGoActive(event) { if (event.isAutoRepeat) { // isAutoRepeat is true when held down (or when Windows feels like it) return; } - if (!isAway && (event.text == 'ESC')) { + if (!isAway && (event.text === 'ESC')) { goAway(); } else { goActive(); @@ -286,7 +274,7 @@ function maybeGoAway() { } // If you've removed your HMD from your head, and we can detect it, we will also go away... - if (HMD.mounted != wasHmdMounted) { + if (HMD.mounted !== wasHmdMounted) { wasHmdMounted = HMD.mounted; print("HMD mounted changed..."); @@ -317,7 +305,7 @@ var handleMessage = function(channel, message, sender) { print("away.js | Got message on Hifi-Away-Enable: ", message); setEnabled(message === 'enable'); } -} +}; Messages.subscribe(CHANNEL_AWAY_ENABLE); Messages.messageReceived.connect(handleMessage); From a5553d5e1c4182344abff421b1404c37e406c2aa Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 6 Sep 2017 09:26:48 -0700 Subject: [PATCH 31/58] fixed text scale for notifications --- scripts/system/notifications.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 111ebd4506..53cffa18d8 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -449,7 +449,23 @@ return finishedLines.join('\n'); } + function updateNotificationsTexts() { + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + for (var i = 0; i < notifications.length; i++) { + var overlayType = Overlays.getOverlayType(notifications[i]); + + if (overlayType === "text3d") { + var props = { + font: {size: fontSize * sensorScaleFactor}, + lineHeight: 10.0 * (fontSize * sensorScaleFactor / 12.0) * NOTIFICATION_3D_SCALE + }; + Overlays.editOverlay(notifications[i], props); + } + } + } + function update() { + updateNotificationsTexts(); var noticeOut, buttonOut, arraysOut, From 2f850826f2b36395f98ed1b3765e8607f096ec44 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 6 Sep 2017 11:02:44 -0700 Subject: [PATCH 32/58] Allow override of near/far clip planes in Oculus and OpenVR plugins --- interface/src/Application.cpp | 2 +- .../src/display-plugins/hmd/HmdDisplayPlugin.h | 2 +- plugins/oculus/src/OculusBaseDisplayPlugin.cpp | 16 ++++++++++++++++ plugins/oculus/src/OculusBaseDisplayPlugin.h | 2 ++ plugins/openvr/src/OpenVrDisplayPlugin.cpp | 13 +++++++++++++ plugins/openvr/src/OpenVrDisplayPlugin.h | 2 ++ 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d85b87d46f..a1cd79e9c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2596,7 +2596,7 @@ void Application::paintGL() { mat4 eyeOffsets[2]; mat4 eyeProjections[2]; - // adjust near clip plane by heightRatio + // adjust near clip plane by sensorToWorldScale auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), renderArgs.getViewFrustum().getAspectRatio(), renderArgs.getViewFrustum().getNearClip() * sensorToWorldScale, diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 0827d04922..23e0893644 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -27,7 +27,7 @@ public: bool isHmd() const override final { return true; } float getIPD() const override final { return _ipd; } glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } - glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override final { return _eyeProjections[eye]; } + glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override { return _eyeProjections[eye]; } glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override final { return _cullingProjection; } glm::uvec2 getRecommendedUiSize() const override final; glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 69ad8a5710..aa39353b94 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -60,6 +60,22 @@ bool OculusBaseDisplayPlugin::isSupported() const { return oculusAvailable(); } +glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const { + if (_session) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + ovrEyeType ovrEye = (eye == Left) ? ovrEye_Left : ovrEye_Right; + ovrFovPort fovPort = _hmdDesc.DefaultEyeFov[eye]; + ovrEyeRenderDesc& erd = ovr_GetRenderDesc(_session, ovrEye, fovPort); + ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL); + return toGlm(ovrPerspectiveProjection); + } else { + return baseProjection; + } +} + // DLL based display plugins MUST initialize GLEW inside the DLL code. void OculusBaseDisplayPlugin::customizeContext() { glewExperimental = true; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 5230b11681..4d14223618 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -19,6 +19,8 @@ public: ~OculusBaseDisplayPlugin(); bool isSupported() const override; + glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + bool hasAsyncReprojection() const override { return true; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 771ba8a3d8..25c85737fe 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -357,6 +357,19 @@ bool OpenVrDisplayPlugin::isSupported() const { return openVrSupported(); } +glm::mat4 OpenVrDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const { + if (_system) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + vr::EVREye openVrEye = (eye == Left) ? vr::Eye_Left : vr::Eye_Right; + return toGlm(_system->GetProjectionMatrix(openVrEye, baseNearClip, baseFarClip)); + } else { + return baseProjection; + } +} + float OpenVrDisplayPlugin::getTargetFrameRate() const { if (forceInterleavedReprojection && !_asyncReprojectionActive) { return TARGET_RATE_OpenVr / 2.0f; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index a1bbed8754..062345943a 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -38,6 +38,8 @@ public: bool isSupported() const override; const QString getName() const override { return NAME; } + glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + void init() override; float getTargetFrameRate() const override; From 0ac7e006126c0e2fe65824b990aa57dbae4ca366 Mon Sep 17 00:00:00 2001 From: Daniela Date: Wed, 6 Sep 2017 19:45:03 +0100 Subject: [PATCH 33/58] Add Avatar resize compatible teleport.js pad scale --- scripts/system/controllers/teleport.js | 38 +++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 17ca2f91c5..2f3c9783bb 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -245,13 +245,49 @@ function Teleporter() { Script.clearTimeout(coolInTimeout); } + + // DAANTJE + // pad scale with avatar size + var AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENTIONS = Vec3.multiply(MyAvatar.sensorToWorldScale, TARGET_MODEL_DIMENSIONS); + + if (!Vec3.equal(AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENTIONS, cancelEnd.dimensions)) { + cancelEnd.dimensions = AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENTIONS; + teleportEnd.dimensions = AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENTIONS; + seatEnd.dimensions = AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENTIONS; + + teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd}, + {name: "teleport", path: teleportPath, end: teleportEnd}, + {name: "seat", path: seatPath, end: seatEnd}]; + + LaserPointers.editRenderState(this.teleportRayLeftVisible, "cancel", teleportRenderStates[0]); + LaserPointers.editRenderState(this.teleportRayLeftInvisible, "cancel", teleportRenderStates[0]); + LaserPointers.editRenderState(this.teleportRayRightVisible, "cancel", teleportRenderStates[0]); + LaserPointers.editRenderState(this.teleportRayRightInvisible, "cancel", teleportRenderStates[0]); + LaserPointers.editRenderState(this.teleportRayHeadVisible, "cancel", teleportRenderStates[0]); + LaserPointers.editRenderState(this.teleportRayHeadInvisible, "cancel", teleportRenderStates[0]); + + LaserPointers.editRenderState(this.teleportRayLeftVisible, "teleport", teleportRenderStates[1]); + LaserPointers.editRenderState(this.teleportRayLeftInvisible, "teleport", teleportRenderStates[1]); + LaserPointers.editRenderState(this.teleportRayRightVisible, "teleport", teleportRenderStates[1]); + LaserPointers.editRenderState(this.teleportRayRightInvisible, "teleport", teleportRenderStates[1]); + LaserPointers.editRenderState(this.teleportRayHeadVisible, "teleport", teleportRenderStates[1]); + LaserPointers.editRenderState(this.teleportRayHeadInvisible, "teleport", teleportRenderStates[1]); + + LaserPointers.editRenderState(this.teleportRayLeftVisible, "seat", teleportRenderStates[2]); + LaserPointers.editRenderState(this.teleportRayLeftInvisible, "seat", teleportRenderStates[2]); + LaserPointers.editRenderState(this.teleportRayRightVisible, "seat", teleportRenderStates[2]); + LaserPointers.editRenderState(this.teleportRayRightInvisible, "seat", teleportRenderStates[2]); + LaserPointers.editRenderState(this.teleportRayHeadVisible, "seat", teleportRenderStates[2]); + LaserPointers.editRenderState(this.teleportRayHeadInvisible, "seat", teleportRenderStates[2]); + } + this.state = TELEPORTER_STATES.COOL_IN; coolInTimeout = Script.setTimeout(function() { if (_this.state === TELEPORTER_STATES.COOL_IN) { _this.state = TELEPORTER_STATES.TARGETTING; } }, COOL_IN_DURATION); - + this.activeHand = hand; this.enableMappings(); Script.update.connect(this, this.update); From 37f959d74975f29dd62ab7d0f81c30e1f2c50a77 Mon Sep 17 00:00:00 2001 From: Daniela Date: Wed, 6 Sep 2017 19:45:58 +0100 Subject: [PATCH 34/58] Add Avatar resize compatible teleport pad alignment --- interface/src/raypick/LaserPointer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index f4adcc736d..696bed1066 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -150,7 +150,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); } if (_faceAvatar) { - glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), Vectors::UP))); + glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), DependencyManager::get()->getMyAvatar()->getOrientation()*Vectors::UP))); endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(0, glm::degrees(safeEulerAngles(rotation)).y, 0))))); } endProps.insert("visible", true); From 3ff707f27eada1487e62bc19dd8e070083011bd0 Mon Sep 17 00:00:00 2001 From: Daniela Date: Thu, 7 Sep 2017 13:31:41 +0100 Subject: [PATCH 35/58] Add Avatar resize compatible teleport pad alignment --- interface/src/raypick/LaserPointer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 696bed1066..4beb2bab10 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -151,7 +151,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } if (_faceAvatar) { glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), DependencyManager::get()->getMyAvatar()->getOrientation()*Vectors::UP))); - endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(0, glm::degrees(safeEulerAngles(rotation)).y, 0))))); + endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(glm::degrees(safeEulerAngles(rotation)).x, glm::degrees(safeEulerAngles(rotation)).y, glm::degrees(safeEulerAngles(rotation)).z))))); } endProps.insert("visible", true); endProps.insert("ignoreRayIntersection", renderState.doesEndIgnoreRays()); From 4c302b899de3081fb76b12703a370517984f3e87 Mon Sep 17 00:00:00 2001 From: Daniela Date: Thu, 7 Sep 2017 17:52:09 +0100 Subject: [PATCH 36/58] Fix teleport pad alignment --- interface/src/raypick/LaserPointer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 4beb2bab10..da0de7e9d5 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -151,7 +151,8 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } if (_faceAvatar) { glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), DependencyManager::get()->getMyAvatar()->getOrientation()*Vectors::UP))); - endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(glm::degrees(safeEulerAngles(rotation)).x, glm::degrees(safeEulerAngles(rotation)).y, glm::degrees(safeEulerAngles(rotation)).z))))); + //endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(glm::degrees(safeEulerAngles(rotation)).x, glm::degrees(safeEulerAngles(rotation)).y, glm::degrees(safeEulerAngles(rotation)).z))))); + endProps.insert("rotation", quatToVariant(DependencyManager::get()->getMyAvatar()->getOrientation())); } endProps.insert("visible", true); endProps.insert("ignoreRayIntersection", renderState.doesEndIgnoreRays()); From 94e26a554d85e4d5fb82bcba67db3b711ca86f30 Mon Sep 17 00:00:00 2001 From: Daniela Date: Thu, 7 Sep 2017 18:48:20 +0100 Subject: [PATCH 37/58] Add 180 degrees rotation so that pad faces the avatar --- interface/src/raypick/LaserPointer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index da0de7e9d5..aef48d864d 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -152,7 +152,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter if (_faceAvatar) { glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), DependencyManager::get()->getMyAvatar()->getOrientation()*Vectors::UP))); //endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(glm::degrees(safeEulerAngles(rotation)).x, glm::degrees(safeEulerAngles(rotation)).y, glm::degrees(safeEulerAngles(rotation)).z))))); - endProps.insert("rotation", quatToVariant(DependencyManager::get()->getMyAvatar()->getOrientation())); + endProps.insert("rotation", quatToVariant(DependencyManager::get()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))))); } endProps.insert("visible", true); endProps.insert("ignoreRayIntersection", renderState.doesEndIgnoreRays()); From d11a749365e28453d5e8dafaa5e82d3b60e68107 Mon Sep 17 00:00:00 2001 From: Daniela Date: Thu, 7 Sep 2017 19:28:36 +0100 Subject: [PATCH 38/58] Refactor 1 line. Pad alignment is correct. --- interface/src/raypick/LaserPointer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index aef48d864d..530821532e 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -150,8 +150,6 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); } if (_faceAvatar) { - glm::quat rotation = glm::inverse(glm::quat_cast(glm::lookAt(endVec, DependencyManager::get()->getMyAvatar()->getPosition(), DependencyManager::get()->getMyAvatar()->getOrientation()*Vectors::UP))); - //endProps.insert("rotation", quatToVariant(glm::quat(glm::radians(glm::vec3(glm::degrees(safeEulerAngles(rotation)).x, glm::degrees(safeEulerAngles(rotation)).y, glm::degrees(safeEulerAngles(rotation)).z))))); endProps.insert("rotation", quatToVariant(DependencyManager::get()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))))); } endProps.insert("visible", true); From d0f9a20a012ed578ae1846c71614c75b87d1a0b1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 7 Sep 2017 15:10:15 -0700 Subject: [PATCH 39/58] Fix for tablet grabbing at small scales --- interface/src/ui/overlays/Overlays.cpp | 1 + scripts/system/controllers/handControllerGrab.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d6e0b61e7d..c93d225718 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -1045,6 +1045,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { AABox overlayFrameBox(low, dimensions); Transform overlayToWorldMatrix = overlay->getTransform(); + overlayToWorldMatrix.setScale(1.0f); // ignore inherited scale factor from parents glm::mat4 worldToOverlayMatrix = glm::inverse(overlayToWorldMatrix.getMatrix()); glm::vec3 overlayFrameSearchPosition = glm::vec3(worldToOverlayMatrix * glm::vec4(center, 1.0f)); glm::vec3 penetration; diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index f66a8f976d..3bd503b5e7 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2246,7 +2246,7 @@ function MyController(hand) { } } - var sensorScaleFactor = MyAvatar.sensorToWorldMatrix + var sensorScaleFactor = MyAvatar.sensorToWorldScale; var candidateEntities = Entities.findEntities(handPosition, NEAR_GRAB_RADIUS * sensorScaleFactor); var grabbableEntities = candidateEntities.filter(function(entity) { return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE * sensorScaleFactor); From f4f9c29bffacb6e02961b06bae60046a32b04e7d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 7 Sep 2017 15:30:16 -0700 Subject: [PATCH 40/58] Fix for avatar scale preferences --- interface/src/ui/PreferencesDialog.cpp | 4 ++-- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index fb451f6b0e..b8d4a38905 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -193,8 +193,8 @@ void setupPreferences() { preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter)); } { - auto getter = [=]()->float { return myAvatar->getModelScale(); }; - auto setter = [=](float value) { myAvatar->setModelScale(value); }; + auto getter = [=]()->float { return myAvatar->getTargetScale(); }; + auto setter = [=](float value) { myAvatar->setTargetScale(value); }; auto preference = new SpinnerSliderPreference(AVATAR_TUNING, "Avatar Scale", getter, setter); preference->setStep(0.05f); preference->setDecimals(2); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 0f9a03d3de..c969de980f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -232,6 +232,7 @@ public: void animateScaleChanges(float deltaTime); void setTargetScale(float targetScale) override; + float getTargetScale() const { return _targetScale; } Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const; From 7ca498dc7f818de00c5875755856460aaa579d92 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 7 Sep 2017 16:28:08 -0700 Subject: [PATCH 41/58] Entities created from Google Blocks zip files now are positioned/scaled relative to the avatar. --- interface/src/Application.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a1cd79e9c1..d2a7014164 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6669,7 +6669,9 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar. properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. - properties.setPosition(getMyAvatar()->getPosition() + getMyAvatar()->getOrientation() * glm::vec3(0.0f, 0.0f, -2.0f)); + glm::vec3 positionOffset = getMyAvatar()->getOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); + properties.setPosition(getMyAvatar()->getPosition() + positionOffset); + properties.setRotation(getMyAvatar()->getOrientation()); properties.setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); auto entityID = DependencyManager::get()->addEntity(properties); @@ -6716,7 +6718,7 @@ void Application::addAssetToWorldCheckModelSize() { if (dimensions != DEFAULT_DIMENSIONS) { // Scale model so that its maximum is exactly specific size. - const float MAXIMUM_DIMENSION = 1.0f; + const float MAXIMUM_DIMENSION = 1.0f * getMyAvatar()->getSensorToWorldScale(); auto previousDimensions = dimensions; auto scale = std::min(MAXIMUM_DIMENSION / dimensions.x, std::min(MAXIMUM_DIMENSION / dimensions.y, MAXIMUM_DIMENSION / dimensions.z)); From 9eb429b25af075e31c6990636a9d26a314125371 Mon Sep 17 00:00:00 2001 From: Daniela Date: Fri, 8 Sep 2017 11:23:19 +0100 Subject: [PATCH 42/58] Fix offset for teleport pad. --- interface/src/raypick/LaserPointer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 530821532e..bfd91e5c84 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -143,14 +143,17 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } if (!renderState.getEndID().isNull()) { QVariantMap endProps; + glm::quat faceAvatarRotation = DependencyManager::get()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))); if (_centerEndY) { endProps.insert("position", end); } else { glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); - endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); + //endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); + glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP; + endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.x, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.z))); } if (_faceAvatar) { - endProps.insert("rotation", quatToVariant(DependencyManager::get()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))))); + endProps.insert("rotation", quatToVariant(faceAvatarRotation)); } endProps.insert("visible", true); endProps.insert("ignoreRayIntersection", renderState.doesEndIgnoreRays()); From 10e29d1cf0802fa9a502f25e4fbe43e0f487ddd9 Mon Sep 17 00:00:00 2001 From: Daniela Date: Fri, 8 Sep 2017 12:45:29 +0100 Subject: [PATCH 43/58] Decrease offset for teleport pad. Add Bubble orientation and scale correction. --- interface/src/raypick/LaserPointer.cpp | 3 +- scripts/system/bubble.js | 39 ++++++++++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index bfd91e5c84..d9475a8d9b 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -148,9 +148,8 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter endProps.insert("position", end); } else { glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); - //endProps.insert("position", vec3toVariant(endVec + glm::vec3(0, 0.5f * dim.y, 0))); glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP; - endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.x, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.z))); + endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.25f * dim.x, currentUpVector.y * 0.25f * dim.y, currentUpVector.z * 0.25f * dim.z))); } if (_faceAvatar) { endProps.insert("rotation", quatToVariant(faceAvatarRotation)); diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index c2a2f7af40..afb9328a52 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -27,8 +27,9 @@ url: Script.resolvePath("assets/models/Bubble-v14.fbx"), // If you'd like to change the model, modify this line (and the dimensions below) dimensions: { x: 1.0, y: 0.75, z: 1.0 }, position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { x: 2, y: MyAvatar.scale * 0.5 + 0.5, z: 2 }, + //rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), + rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), + scale: { x: 2*MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.5*MyAvatar.sensorToWorldScale, z: 2*MyAvatar.sensorToWorldScale }, visible: false, ignoreRayIntersection: true }); @@ -62,9 +63,17 @@ } Overlays.editOverlay(bubbleOverlay, { - position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { x: 2, y: MyAvatar.scale * 0.5 + 0.5, z: 2 }, + position: { + x: MyAvatar.position.x, + y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, + z: MyAvatar.position.z + }, + rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), + scale: { + x: 2 * MyAvatar.sensorToWorldScale, + y: MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale, + z: 2 * MyAvatar.sensorToWorldScale + }, visible: true }); bubbleOverlayTimestamp = Date.now(); @@ -105,11 +114,11 @@ y: (-((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { - x: 2, - y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.5), - z: 2 + rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), + scale: { + x: 2 * MyAvatar.sensorToWorldScale, + y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale), + z: 2 * MyAvatar.sensorToWorldScale } }); } else { @@ -120,11 +129,11 @@ y: MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - scale: { - x: 2, - y: MyAvatar.scale * 0.5 + 0.5, - z: 2 + rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), + scale: { + x: 2 * MyAvatar.sensorToWorldScale, + y: MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale, + z: 2 * MyAvatar.sensorToWorldScale } }); } From 758f049f306b9f56e522077032733ba89289b881 Mon Sep 17 00:00:00 2001 From: Daniela Date: Fri, 8 Sep 2017 14:02:26 +0100 Subject: [PATCH 44/58] Correct offset for teleport pad. --- interface/src/raypick/LaserPointer.cpp | 2 +- scripts/system/bubble.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index d9475a8d9b..9d64bcc476 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -149,7 +149,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } else { glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP; - endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.25f * dim.x, currentUpVector.y * 0.25f * dim.y, currentUpVector.z * 0.25f * dim.z))); + endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.y, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.y))); } if (_faceAvatar) { endProps.insert("rotation", quatToVariant(faceAvatarRotation)); diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index afb9328a52..7772a52187 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -29,7 +29,7 @@ position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, //rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { x: 2*MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.5*MyAvatar.sensorToWorldScale, z: 2*MyAvatar.sensorToWorldScale }, + scale: { x: 2 * MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale }, visible: false, ignoreRayIntersection: true }); @@ -71,7 +71,7 @@ rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { x: 2 * MyAvatar.sensorToWorldScale, - y: MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale, + y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale }, visible: true @@ -117,7 +117,7 @@ rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { x: 2 * MyAvatar.sensorToWorldScale, - y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale), + y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale), z: 2 * MyAvatar.sensorToWorldScale } }); @@ -132,7 +132,7 @@ rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { x: 2 * MyAvatar.sensorToWorldScale, - y: MyAvatar.scale * 0.5 + 0.5 * MyAvatar.sensorToWorldScale, + y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale } }); From 08688dc9ed791a72dfe7b60da558b66e5daa0de5 Mon Sep 17 00:00:00 2001 From: Daniela Date: Fri, 8 Sep 2017 17:56:11 +0100 Subject: [PATCH 45/58] Refactoring. --- scripts/system/bubble.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 7772a52187..6c5714ee07 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -28,7 +28,7 @@ dimensions: { x: 1.0, y: 0.75, z: 1.0 }, position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, //rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), - rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), + rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { x: 2 * MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale }, visible: false, ignoreRayIntersection: true @@ -64,16 +64,16 @@ Overlays.editOverlay(bubbleOverlay, { position: { - x: MyAvatar.position.x, - y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, - z: MyAvatar.position.z - }, + x: MyAvatar.position.x, + y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, + z: MyAvatar.position.z + }, rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { - x: 2 * MyAvatar.sensorToWorldScale, - y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, - z: 2 * MyAvatar.sensorToWorldScale - }, + x: 2 * MyAvatar.sensorToWorldScale, + y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, + z: 2 * MyAvatar.sensorToWorldScale + }, visible: true }); bubbleOverlayTimestamp = Date.now(); @@ -115,7 +115,7 @@ z: MyAvatar.position.z }, rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { + scale: { x: 2 * MyAvatar.sensorToWorldScale, y: ((1 - ((BUBBLE_RAISE_ANIMATION_DURATION_MS - delay) / BUBBLE_RAISE_ANIMATION_DURATION_MS)) * MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale), z: 2 * MyAvatar.sensorToWorldScale @@ -130,7 +130,7 @@ z: MyAvatar.position.z }, rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), - scale: { + scale: { x: 2 * MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale From e453bf8d559fdf59dee32f9ddf5a22547f25c1c4 Mon Sep 17 00:00:00 2001 From: Daniela Date: Fri, 8 Sep 2017 17:58:16 +0100 Subject: [PATCH 46/58] Refactoring. --- scripts/system/bubble.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/bubble.js b/scripts/system/bubble.js index 6c5714ee07..c3d240f9a5 100644 --- a/scripts/system/bubble.js +++ b/scripts/system/bubble.js @@ -27,7 +27,6 @@ url: Script.resolvePath("assets/models/Bubble-v14.fbx"), // If you'd like to change the model, modify this line (and the dimensions below) dimensions: { x: 1.0, y: 0.75, z: 1.0 }, position: { x: MyAvatar.position.x, y: -MyAvatar.scale * 2 + MyAvatar.position.y + MyAvatar.scale * BUBBLE_HEIGHT_SCALE, z: MyAvatar.position.z }, - //rotation: Quat.fromPitchYawRollDegrees(MyAvatar.bodyPitch, 0, MyAvatar.bodyRoll), rotation: Quat.multiply(MyAvatar.orientation, Quat.fromVec3Degrees({x: 0.0, y: 180.0, z: 0.0})), scale: { x: 2 * MyAvatar.sensorToWorldScale, y: MyAvatar.scale * 0.5 + 0.2 * MyAvatar.sensorToWorldScale, z: 2 * MyAvatar.sensorToWorldScale }, visible: false, From bb5e808051ce3e44f9d579bf1f49d2d483afada1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 11 Sep 2017 18:59:52 -0700 Subject: [PATCH 47/58] Fix for some of tablet size issues, on switching domains. --- scripts/system/libraries/WebTablet.js | 59 ++++++++++----------------- scripts/system/tablet-ui/tabletUI.js | 2 +- 2 files changed, 22 insertions(+), 39 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index aaaca70464..71d3a14845 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // /* global getControllerWorldLocation, Tablet, WebTablet:true, HMD, Settings, Script, - Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform, clamp, Controller, Mat4 */ + Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform, clamp, Controller, Mat4, resizeTablet */ Script.include(Script.resolvePath("../libraries/utils.js")); Script.include(Script.resolvePath("../libraries/controllers.js")); @@ -42,7 +42,7 @@ var LOCAL_TABLET_MODEL_PATH = Script.resourcesPath() + "meshes/tablet-with-home- // returns object with two fields: // * position - position in front of the user // * rotation - rotation of entity so it faces the user. -function calcSpawnInfo(hand, tabletHeight, landscape) { +function calcSpawnInfo(hand, height, landscape) { var finalPosition; var headPos = (HMD.active && Camera.mode === "first person") ? HMD.position : Camera.position; @@ -76,9 +76,8 @@ function calcSpawnInfo(hand, tabletHeight, landscape) { var TABLET_RAKE_ANGLE = 30; rotation = Quat.multiply(Quat.angleAxis(TABLET_RAKE_ANGLE, Vec3.multiplyQbyV(lookAt, Vec3.UNIT_X)), lookAt); - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6 * sensorScaleFactor, z: 0.1 * sensorScaleFactor }; - position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, Vec3.multiply(tabletHeight, RELATIVE_SPAWN_OFFSET))); + var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6 * height, z: 0.1 * height }; + position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RELATIVE_SPAWN_OFFSET)); return { position: position, @@ -110,18 +109,19 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { var sensorScaleFactor = MyAvatar.sensorToWorldScale; // scale factor of natural tablet dimensions. - this.width = (width || DEFAULT_WIDTH) * sensorScaleFactor; - var tabletScaleFactor = this.width / TABLET_NATURAL_DIMENSIONS.x; - this.height = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; - this.depth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; + var tabletWidth = (width || DEFAULT_WIDTH) * sensorScaleFactor; + var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x; + var tabletHeight = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; + var tabletDepth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; this.landscape = false; visible = visible === true; + var tabletDpi; if (dpi) { - this.dpi = dpi; + tabletDpi = dpi; } else { - this.dpi = DEFAULT_DPI * (DEFAULT_WIDTH / this.width); + tabletDpi = DEFAULT_DPI * (DEFAULT_WIDTH / tabletWidth); } var modelURL = LOCAL_TABLET_MODEL_PATH; @@ -135,7 +135,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { userData: JSON.stringify({ "grabbableKey": {"grabbable": true} }), - dimensions: this.getDimensions(), + dimensions: { x: tabletWidth, y: tabletHeight, z: tabletDepth }, parentID: AVATAR_SELF_ID, visible: visible }; @@ -155,7 +155,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { Overlays.deleteOverlay(this.webOverlayID); } - var WEB_ENTITY_Z_OFFSET = (this.depth / 2) * (1 / sensorScaleFactor); + var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2) * (1 / sensorScaleFactor); var WEB_ENTITY_Y_OFFSET = 0.004 * (1 / sensorScaleFactor); this.webOverlayID = Overlays.addOverlay("web3d", { @@ -164,7 +164,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { localPosition: { x: 0, y: WEB_ENTITY_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET }, localRotation: Quat.angleAxis(180, Y_AXIS), resolution: this.getTabletTextureResolution(), - dpi: this.dpi, + dpi: tabletDpi, color: { red: 255, green: 255, blue: 255 }, alpha: 1.0, parentID: this.tabletEntityID, @@ -173,7 +173,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { visible: visible }); - var HOME_BUTTON_Y_OFFSET = ((this.height / 2) - (this.height / 20)) * (1 / sensorScaleFactor); + var HOME_BUTTON_Y_OFFSET = ((tabletHeight / 2) - (tabletHeight / 20)) * (1 / sensorScaleFactor); this.homeButtonID = Overlays.addOverlay("sphere", { name: "homeButton", localPosition: {x: -0.001, y: -HOME_BUTTON_Y_OFFSET, z: 0.0}, @@ -250,10 +250,6 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { Camera.modeUpdated.connect(this.myCameraModeChanged); }; -WebTablet.prototype.getDimensions = function() { - return { x: this.width, y: this.height, z: this.depth }; -}; - WebTablet.prototype.getTabletTextureResolution = function() { if (this.landscape) { return { x: TABLET_TEXTURE_RESOLUTION.y , y: TABLET_TEXTURE_RESOLUTION.x }; @@ -324,12 +320,10 @@ WebTablet.prototype.destroy = function () { WebTablet.prototype.geometryChanged = function (geometry) { if (!HMD.active) { - var tabletProperties = {}; - + var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); - // TODO -- is this still needed? - // Entities.editEntity(this.tabletEntityID, tabletProperties); + Overlays.editOverlay(HMD.tabletID, tabletProperties); } }; @@ -403,7 +397,7 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou tabletProperties.parentJointIndex = SENSOR_TO_ROOM_MATRIX; // compute the appropriate position of the tablet, near the hand controller that was used to spawn it. - var spawnInfo = calcSpawnInfo(hand, this.height, this.landscape); + var spawnInfo = calcSpawnInfo(hand, tabletProperties.dimensions.y, this.landscape); tabletProperties.position = spawnInfo.position; tabletProperties.rotation = spawnInfo.rotation; } else { @@ -426,12 +420,10 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou }; WebTablet.prototype.onHmdChanged = function () { - - var tabletProperties = {}; + var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); - // TODO -- is this still needed? - // Entities.editEntity(this.tabletEntityID, tabletProperties); + Overlays.editOverlay(HMD.tabletID, tabletProperties); }; WebTablet.prototype.pickle = function () { @@ -511,16 +503,7 @@ WebTablet.prototype.mousePressEvent = function (event) { }; WebTablet.prototype.cameraModeChanged = function (newMode) { - // reposition the tablet. - // This allows HMD.position to reflect the new camera mode. - if (HMD.active) { - var self = this; - var tabletProperties = {}; - // compute position, rotation & parentJointIndex of the tablet - self.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); - // TODO -- is this still needed? - // Entities.editEntity(self.tabletEntityID, tabletProperties); - } + ; }; function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) { diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index e52d0b530b..4fedd4354c 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -120,7 +120,7 @@ if (debugTablet) { print("TABLET in showTabletUI, already rezzed"); } - var tabletProperties = {}; + var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties); tabletProperties.visible = true; Overlays.editOverlay(HMD.tabletID, tabletProperties); From c88c70aa6fe8df220c9a373523228b25ae3aa5dc Mon Sep 17 00:00:00 2001 From: Daniela Date: Tue, 12 Sep 2017 18:11:45 +0100 Subject: [PATCH 48/58] Add SensorToWorldScale factor to the bounding box dimensions. --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 34feafbd4d..0ca1795f9f 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -170,9 +170,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData); // Define the minimum bubble size - static const glm::vec3 minBubbleSize = glm::vec3(0.3f, 1.3f, 0.3f); + static const glm::vec3 minBubbleSize = avatar.getSensorToWorldScale() * glm::vec3(0.3f, 1.3f, 0.3f); // Define the scale of the box for the current node - glm::vec3 nodeBoxScale = (nodeData->getPosition() - nodeData->getGlobalBoundingBoxCorner()) * 2.0f; + glm::vec3 nodeBoxScale = (nodeData->getPosition() - nodeData->getGlobalBoundingBoxCorner()) * 2.0f * avatar.getSensorToWorldScale(); // Set up the bounding box for the current node AABox nodeBox(nodeData->getGlobalBoundingBoxCorner(), nodeBoxScale); // Clamp the size of the bounding box to a minimum scale @@ -209,7 +209,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) assert(avatarNode); // we can't have gotten here without the avatarData being a valid key in the map return nodeData->getLastBroadcastTime(avatarNode->getUUID()); }, [&](AvatarSharedPointer avatar)->float{ - glm::vec3 nodeBoxHalfScale = (avatar->getPosition() - avatar->getGlobalBoundingBoxCorner()); + glm::vec3 nodeBoxHalfScale = (avatar->getPosition() - avatar->getGlobalBoundingBoxCorner() * avatar->getSensorToWorldScale); return glm::max(nodeBoxHalfScale.x, glm::max(nodeBoxHalfScale.y, nodeBoxHalfScale.z)); }, [&](AvatarSharedPointer avatar)->bool { if (avatar == thisAvatar) { @@ -244,9 +244,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) // Check to see if the space bubble is enabled // Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored if (node->isIgnoreRadiusEnabled() || (avatarNode->isIgnoreRadiusEnabled() && !getsAnyIgnored)) { - + float sensorToWorldScale = avatarNodeData->getAvatarSharedPointer()->getSensorToWorldScale(); // Define the scale of the box for the current other node - glm::vec3 otherNodeBoxScale = (avatarNodeData->getPosition() - avatarNodeData->getGlobalBoundingBoxCorner()) * 2.0f; + glm::vec3 otherNodeBoxScale = (avatarNodeData->getPosition() - avatarNodeData->getGlobalBoundingBoxCorner()) * 2.0f * sensorToWorldScale; // Set up the bounding box for the current other node AABox otherNodeBox(avatarNodeData->getGlobalBoundingBoxCorner(), otherNodeBoxScale); // Clamp the size of the bounding box to a minimum scale From 5a918a3033bfd63291609f3ebf250752e43239f0 Mon Sep 17 00:00:00 2001 From: Daniela Date: Tue, 12 Sep 2017 19:00:57 +0100 Subject: [PATCH 49/58] Add SensorToWorldScale factor to the bounding box dimensions. --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 0ca1795f9f..5db0630191 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -209,7 +209,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) assert(avatarNode); // we can't have gotten here without the avatarData being a valid key in the map return nodeData->getLastBroadcastTime(avatarNode->getUUID()); }, [&](AvatarSharedPointer avatar)->float{ - glm::vec3 nodeBoxHalfScale = (avatar->getPosition() - avatar->getGlobalBoundingBoxCorner() * avatar->getSensorToWorldScale); + glm::vec3 nodeBoxHalfScale = (avatar->getPosition() - avatar->getGlobalBoundingBoxCorner() * avatar->getSensorToWorldScale()); return glm::max(nodeBoxHalfScale.x, glm::max(nodeBoxHalfScale.y, nodeBoxHalfScale.z)); }, [&](AvatarSharedPointer avatar)->bool { if (avatar == thisAvatar) { From 6941a10639eb09a7eb03a5f608d978a37fe0f219 Mon Sep 17 00:00:00 2001 From: Daniela Date: Tue, 12 Sep 2017 21:10:19 +0100 Subject: [PATCH 50/58] Add SensorToWorldScale factor to the bounding box dimensions in AvatarMixerSlave. --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 5db0630191..5d36a6d261 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -334,8 +334,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) glm::vec3 otherPosition = otherAvatar->getClientGlobalPosition(); + // determine if avatar is in view, to determine how much data to include... - glm::vec3 otherNodeBoxScale = (otherPosition - otherNodeData->getGlobalBoundingBoxCorner()) * 2.0f; + glm::vec3 otherNodeBoxScale = (otherPosition - otherNodeData->getGlobalBoundingBoxCorner()) * 2.0f * otherAvatar->getSensorToWorldScale(); AABox otherNodeBox(otherNodeData->getGlobalBoundingBoxCorner(), otherNodeBoxScale); bool isInView = nodeData->otherAvatarInView(otherNodeBox); From 9a1fa9b2f29e7a6e514c1f6d4f686dd202ab8d39 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 13 Sep 2017 09:50:48 -0700 Subject: [PATCH 51/58] Fix for stylus intersection with tablet and home button for scaled tablets --- scripts/system/controllers/handControllerGrab.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 3bd503b5e7..1418b8fbbc 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1670,8 +1670,11 @@ function MyController(hand) { var nearestStylusTarget = calculateNearestStylusTarget(stylusTargets); - if (nearestStylusTarget && nearestStylusTarget.distance > TABLET_MIN_TOUCH_DISTANCE && - nearestStylusTarget.distance < TABLET_MAX_HOVER_DISTANCE) { + var SCALED_TABLET_MIN_TOUCH_DISTANCE = TABLET_MIN_TOUCH_DISTANCE * sensorScaleFactor; + var SCALED_TABLET_MAX_TOUCH_DISTANCE = TABLET_MAX_TOUCH_DISTANCE * sensorScaleFactor; + var SCALED_TABLET_MAX_HOVER_DISTANCE = TABLET_MAX_HOVER_DISTANCE * sensorScaleFactor; + if (nearestStylusTarget && nearestStylusTarget.distance > SCALED_TABLET_MIN_TOUCH_DISTANCE && + nearestStylusTarget.distance < SCALED_TABLET_MAX_HOVER_DISTANCE) { this.requestTouchFocus(nearestStylusTarget); @@ -1685,8 +1688,8 @@ function MyController(hand) { // filter out presses when tip is moving away from tablet. // ensure that stylus is within bounding box by checking normalizedPosition - if (nearestStylusTarget.valid && nearestStylusTarget.distance > TABLET_MIN_TOUCH_DISTANCE && - nearestStylusTarget.distance < TABLET_MAX_TOUCH_DISTANCE && Vec3.dot(this.stylusTip.velocity, nearestStylusTarget.normal) < 0 && + if (nearestStylusTarget.valid && nearestStylusTarget.distance > SCALED_TABLET_MIN_TOUCH_DISTANCE && + nearestStylusTarget.distance < SCALED_TABLET_MAX_TOUCH_DISTANCE && Vec3.dot(this.stylusTip.velocity, nearestStylusTarget.normal) < 0 && nearestStylusTarget.normalizedPosition.x >= 0 && nearestStylusTarget.normalizedPosition.x <= 1 && nearestStylusTarget.normalizedPosition.y >= 0 && nearestStylusTarget.normalizedPosition.y <= 1) { From de5f0ad987acaecbe1c34429394f751e6193d201 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 13 Sep 2017 12:01:41 -0700 Subject: [PATCH 52/58] WebTablet.js: calcSpawnInfo works more consistently. --- scripts/system/libraries/WebTablet.js | 13 +++++++++---- scripts/system/tablet-ui/tabletUI.js | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 71d3a14845..bbc8d1268f 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -42,7 +42,7 @@ var LOCAL_TABLET_MODEL_PATH = Script.resourcesPath() + "meshes/tablet-with-home- // returns object with two fields: // * position - position in front of the user // * rotation - rotation of entity so it faces the user. -function calcSpawnInfo(hand, height, landscape) { +function calcSpawnInfo(hand, landscape) { var finalPosition; var headPos = (HMD.active && Camera.mode === "first person") ? HMD.position : Camera.position; @@ -76,7 +76,12 @@ function calcSpawnInfo(hand, height, landscape) { var TABLET_RAKE_ANGLE = 30; rotation = Quat.multiply(Quat.angleAxis(TABLET_RAKE_ANGLE, Vec3.multiplyQbyV(lookAt, Vec3.UNIT_X)), lookAt); + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var tabletWidth = getTabletWidthFromSettings() * sensorScaleFactor; + var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x; + var height = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6 * height, z: 0.1 * height }; + position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RELATIVE_SPAWN_OFFSET)); return { @@ -320,7 +325,7 @@ WebTablet.prototype.destroy = function () { WebTablet.prototype.geometryChanged = function (geometry) { if (!HMD.active) { - var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; + var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); Overlays.editOverlay(HMD.tabletID, tabletProperties); @@ -397,7 +402,7 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou tabletProperties.parentJointIndex = SENSOR_TO_ROOM_MATRIX; // compute the appropriate position of the tablet, near the hand controller that was used to spawn it. - var spawnInfo = calcSpawnInfo(hand, tabletProperties.dimensions.y, this.landscape); + var spawnInfo = calcSpawnInfo(hand, this.landscape); tabletProperties.position = spawnInfo.position; tabletProperties.rotation = spawnInfo.rotation; } else { @@ -420,7 +425,7 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou }; WebTablet.prototype.onHmdChanged = function () { - var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; + var tabletProperties = {}; // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties); Overlays.editOverlay(HMD.tabletID, tabletProperties); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 4fedd4354c..e52d0b530b 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -120,7 +120,7 @@ if (debugTablet) { print("TABLET in showTabletUI, already rezzed"); } - var tabletProperties = { dimensions: Overlays.getProperty(HMD.tabletID, "dimensions") }; + var tabletProperties = {}; UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties); tabletProperties.visible = true; Overlays.editOverlay(HMD.tabletID, tabletProperties); From ae2d0e89b4867be5db485df5660905e9fa50ec7b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 13 Sep 2017 14:18:00 -0700 Subject: [PATCH 53/58] Fixes for desktop tablet --- scripts/system/libraries/WebTablet.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index bbc8d1268f..0a2a9d05ef 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -359,10 +359,19 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos windowPos.y = clamp(windowPos.y, Y_CLAMP, Window.innerHeight - Y_CLAMP); var fov = (Settings.getValue('fieldOfView') || DEFAULT_VERTICAL_FIELD_OF_VIEW) * (Math.PI / 180); + + // scale factor of natural tablet dimensions. + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var tabletWidth = getTabletWidthFromSettings() * sensorScaleFactor; + var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x; + var tabletHeight = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; + var tabletDepth = TABLET_NATURAL_DIMENSIONS.z * tabletScaleFactor; + var tabletDpi = DEFAULT_DPI * (DEFAULT_WIDTH / tabletWidth); + var MAX_PADDING_FACTOR = 2.2; var PADDING_FACTOR = Math.min(Window.innerHeight / this.getTabletTextureResolution().y, MAX_PADDING_FACTOR); - var TABLET_HEIGHT = (this.getTabletTextureResolution().y / this.dpi) * INCHES_TO_METERS; - var WEB_ENTITY_Z_OFFSET = (this.depth / 2); + var TABLET_HEIGHT = (this.getTabletTextureResolution().y / tabletDpi) * INCHES_TO_METERS; + var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2); // calcualte distance from camera var dist = (PADDING_FACTOR * TABLET_HEIGHT) / (2 * Math.tan(fov / 2) * (DESKTOP_TABLET_SCALE / 100)) - WEB_ENTITY_Z_OFFSET; From a505a16232430fc0a158d2b0e74b5b699c525c7d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 13 Sep 2017 14:22:49 -0700 Subject: [PATCH 54/58] Don't rescale tablet, in desktop mode, when sensorToWorldScale changes. --- scripts/system/tablet-ui/tabletUI.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index e52d0b530b..63c1cc51aa 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -84,8 +84,10 @@ } function onSensorToWorldScaleChanged(sensorScaleFactor) { - var newTabletScalePercentage = getTabletScalePercentageFromSettings(); - resizeTablet(DEFAULT_WIDTH * (newTabletScalePercentage / 100), undefined, sensorScaleFactor); + if (HMD.active) { + var newTabletScalePercentage = getTabletScalePercentageFromSettings(); + resizeTablet(DEFAULT_WIDTH * (newTabletScalePercentage / 100), undefined, sensorScaleFactor); + } } function rezTablet() { From 9a9f4a0d24e218418718103e89774a8957f98a76 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 13 Sep 2017 18:23:54 -0700 Subject: [PATCH 55/58] Fix controllerModules with appropriate IPD scale changes --- .../controllerModules/farActionGrabEntity.js | 2 +- .../controllerModules/farTrigger.js | 2 +- .../controllerModules/inEditMode.js | 2 +- .../nearParentGrabOverlay.js | 10 ++++++ .../controllerModules/overlayLaserInput.js | 2 +- .../controllerModules/tabletStylusInput.js | 36 +++++++++++-------- .../controllerModules/webEntityLaserInput.js | 2 +- 7 files changed, 36 insertions(+), 20 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 80718bc68d..b46203c338 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -555,7 +555,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index 38152aac91..76fc87e607 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -202,7 +202,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 916487277a..4301ddcaa7 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -239,7 +239,7 @@ Script.include("/~/system/libraries/utils.js"); joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index 54257ea6af..643ef0d482 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -120,6 +120,11 @@ var GRAB_RADIUS = 0.35; } Overlays.editOverlay(this.grabbedThingID, reparentProps); + // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix + if (this.grabbedThingID === HMD.tabletID) { + resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex); + } + Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'grab', grabbedEntity: this.grabbedThingID, @@ -140,6 +145,11 @@ var GRAB_RADIUS = 0.35; parentID: this.previousParentID[this.grabbedThingID], parentJointIndex: this.previousParentJointIndex[this.grabbedThingID] }); + + // resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix + if (this.grabbedThingID === HMD.tabletID) { + resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]); + } } this.grabbedThingID = null; diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 2c950fd4df..f955029cae 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -528,7 +528,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", filter: RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 0d4f4ff78a..99c4a68b35 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -356,7 +356,7 @@ Script.include("/~/system/libraries/controllers.js"); this.stylusTip = getControllerWorldLocation(this.handToController(), true); // translate tip forward according to constant. - var TIP_OFFSET = {x: 0, y: WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, z: 0}; + var TIP_OFFSET = Vec3.multiply(MyAvatar.sensorToWorldScale, {x: 0, y: WEB_STYLUS_LENGTH - WEB_TOUCH_Y_OFFSET, z: 0}); this.stylusTip.position = Vec3.sum(this.stylusTip.position, Vec3.multiplyQbyV(this.stylusTip.orientation, TIP_OFFSET)); } @@ -380,17 +380,17 @@ Script.include("/~/system/libraries/controllers.js"); return; } + var X_ROT_NEG_90 = { x: -0.70710678, y: 0, z: 0, w: 0.70710678 }; + var modelOrientation = Quat.multiply(this.stylusTip.orientation, X_ROT_NEG_90); + var modelPositionOffset = Vec3.multiplyQbyV(modelOrientation, { x: 0, y: 0, z: MyAvatar.sensorToWorldScale * -WEB_STYLUS_LENGTH / 2 }); + var stylusProperties = { name: "stylus", url: Script.resourcesPath() + "meshes/tablet-stylus-fat.fbx", loadPriority: 10.0, - localPosition: Vec3.sum({ - x: 0.0, - y: WEB_TOUCH_Y_OFFSET, - z: 0.0 - }, getGrabPointSphereOffset(this.handToController())), - localRotation: Quat.fromVec3Degrees({ x: -90, y: 0, z: 0 }), - dimensions: { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }, + position: Vec3.sum(this.stylusTip.position, modelPositionOffset), + rotation: modelOrientation, + dimensions: Vec3.multiply(MyAvatar.sensorToWorldScale, { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }), solid: true, visible: true, ignoreRayIntersection: true, @@ -527,9 +527,11 @@ Script.include("/~/system/libraries/controllers.js"); hysteresisOffset = 0.05; } - this.isNearStylusTarget = isNearStylusTarget(stylusTargets, EDGE_BORDER + hysteresisOffset, - TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset, - WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset); + var sensorScaleFactor = MyAvatar.sensorToWorldScale; + this.isNearStylusTarget = isNearStylusTarget(stylusTargets, + (EDGE_BORDER + hysteresisOffset) * sensorScaleFactor, + (TABLET_MIN_TOUCH_DISTANCE - hysteresisOffset) * sensorScaleFactor, + (WEB_DISPLAY_STYLUS_DISTANCE + hysteresisOffset) * sensorScaleFactor); if (this.isNearStylusTarget) { if (!this.useFingerInsteadOfStylus) { @@ -544,8 +546,12 @@ Script.include("/~/system/libraries/controllers.js"); var nearestStylusTarget = calculateNearestStylusTarget(stylusTargets); - if (nearestStylusTarget && nearestStylusTarget.distance > TABLET_MIN_TOUCH_DISTANCE && - nearestStylusTarget.distance < TABLET_MAX_HOVER_DISTANCE) { + var SCALED_TABLET_MIN_TOUCH_DISTANCE = TABLET_MIN_TOUCH_DISTANCE * sensorScaleFactor; + var SCALED_TABLET_MAX_TOUCH_DISTANCE = TABLET_MAX_TOUCH_DISTANCE * sensorScaleFactor; + var SCALED_TABLET_MAX_HOVER_DISTANCE = TABLET_MAX_HOVER_DISTANCE * sensorScaleFactor; + + if (nearestStylusTarget && nearestStylusTarget.distance > SCALED_TABLET_MIN_TOUCH_DISTANCE && + nearestStylusTarget.distance < SCALED_TABLET_MAX_HOVER_DISTANCE) { this.requestTouchFocus(nearestStylusTarget); @@ -559,8 +565,8 @@ Script.include("/~/system/libraries/controllers.js"); // filter out presses when tip is moving away from tablet. // ensure that stylus is within bounding box by checking normalizedPosition - if (nearestStylusTarget.valid && nearestStylusTarget.distance > TABLET_MIN_TOUCH_DISTANCE && - nearestStylusTarget.distance < TABLET_MAX_TOUCH_DISTANCE && + if (nearestStylusTarget.valid && nearestStylusTarget.distance > SCALED_TABLET_MIN_TOUCH_DISTANCE && + nearestStylusTarget.distance < SCALED_TABLET_MAX_TOUCH_DISTANCE && Vec3.dot(this.stylusTip.velocity, nearestStylusTarget.normal) < 0 && nearestStylusTarget.normalizedPosition.x >= 0 && nearestStylusTarget.normalizedPosition.x <= 1 && nearestStylusTarget.normalizedPosition.y >= 0 && nearestStylusTarget.normalizedPosition.y <= 1) { diff --git a/scripts/system/controllers/controllerModules/webEntityLaserInput.js b/scripts/system/controllers/controllerModules/webEntityLaserInput.js index 1e954d5917..75ad3a60cb 100644 --- a/scripts/system/controllers/controllerModules/webEntityLaserInput.js +++ b/scripts/system/controllers/controllerModules/webEntityLaserInput.js @@ -459,7 +459,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES, maxDistance: PICK_MAX_DISTANCE, - posOffset: getGrabPointSphereOffset(this.handToController()), + posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, defaultRenderStates: defaultRenderStates From 7c725756f1ee87f99c051f518d55dbe9a340edb6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 14 Sep 2017 10:36:05 -0700 Subject: [PATCH 56/58] IPD Fixes for controllerDispatcher and controllerModules --- scripts/system/controllers/controllerDispatcher.js | 7 ++++--- .../controllerModules/nearActionGrabEntity.js | 3 ++- .../controllerModules/nearParentGrabEntity.js | 3 ++- .../controllerModules/nearParentGrabOverlay.js | 10 ++++++---- .../controllers/controllerModules/nearTrigger.js | 3 ++- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 990f156ba8..43e59242de 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -150,6 +150,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); if (PROFILE) { Script.beginProfileRange("dispatch.pre"); } + var sensorScaleFactor = MyAvatar.sensorToWorldScale; var deltaTime = _this.updateTimings(); _this.setIgnoreTablet(); @@ -196,7 +197,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var h; for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { if (controllerLocations[h].valid) { - var nearbyOverlays = Overlays.findOverlays(controllerLocations[h].position, NEAR_MAX_RADIUS); + var nearbyOverlays = Overlays.findOverlays(controllerLocations[h].position, NEAR_MAX_RADIUS * sensorScaleFactor); nearbyOverlays.sort(function (a, b) { var aPosition = Overlays.getProperty(a, "position"); var aDistance = Vec3.distance(aPosition, controllerLocations[h].position); @@ -216,7 +217,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { if (controllerLocations[h].valid) { var controllerPosition = controllerLocations[h].position; - var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MAX_RADIUS); + var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MAX_RADIUS * sensorScaleFactor); for (var j = 0; j < nearbyEntityIDs.length; j++) { var entityID = nearbyEntityIDs[j]; var props = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); @@ -249,7 +250,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); if (rayPicks[h].type === RayPick.INTERSECTED_ENTITY) { // XXX check to make sure this one isn't already in nearbyEntityProperties? - if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS) { + if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS * sensorScaleFactor) { var nearEntityID = rayPicks[h].objectID; var nearbyProps = Entities.getEntityProperties(nearEntityID, DISPATCHER_PROPERTIES); nearbyProps.id = nearEntityID; diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 399388d614..3cef3219a3 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -147,10 +147,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.getTargetProps = function (controllerData) { // nearbyEntityProperties is already sorted by distance from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var handPosition = controllerData.controllerLocations[this.hand].position; - if (props.distance > NEAR_GRAB_RADIUS) { + if (props.distance > NEAR_GRAB_RADIUS * sensorScaleFactor) { break; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 6cd52fef07..33f4936e48 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -147,11 +147,12 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.getTargetProps = function (controllerData) { // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var handPosition = controllerData.controllerLocations[this.hand].position; var distance = Vec3.distance(props.position, handPosition); - if (distance > NEAR_GRAB_RADIUS) { + if (distance > NEAR_GRAB_RADIUS * sensorScaleFactor) { continue; } if (entityIsGrabbable(props)) { diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index 643ef0d482..b3f982eb1e 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -8,12 +8,13 @@ /* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID, getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, - Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, - makeDispatcherModuleParameters, Overlays, makeRunningValues + Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, NEAR_GRAB_RADIUS + makeDispatcherModuleParameters, Overlays, makeRunningValues, resizeTablet, + getTabletWidthFromSettings */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); -var GRAB_RADIUS = 0.35; +Script.include("/~/system/libraries/utils.js"); (function() { @@ -156,11 +157,12 @@ var GRAB_RADIUS = 0.35; }; this.getTargetID = function(overlays, controllerData) { + var sensorScaleFactor = MyAvatar.sensorToWorldScale; for (var i = 0; i < overlays.length; i++) { var overlayPosition = Overlays.getProperty(overlays[i], "position"); var handPosition = controllerData.controllerLocations[this.hand].position; var distance = Vec3.distance(overlayPosition, handPosition); - if (distance <= GRAB_RADIUS) { + if (distance <= NEAR_GRAB_RADIUS * sensorScaleFactor) { return overlays[i]; } } diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js index 03fc7f8f64..9f34eb702f 100644 --- a/scripts/system/controllers/controllerModules/nearTrigger.js +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -37,11 +37,12 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.getTargetProps = function (controllerData) { // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; + var sensorScaleFactor = MyAvatar.sensorToWorldScale; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var handPosition = controllerData.controllerLocations[this.hand].position; var distance = Vec3.distance(props.position, handPosition); - if (distance > NEAR_GRAB_RADIUS) { + if (distance > NEAR_GRAB_RADIUS * sensorScaleFactor) { continue; } if (entityWantsNearTrigger(props)) { From f534ee5ad935d6b513de03068d4932b98d805d04 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 14 Sep 2017 16:37:45 -0700 Subject: [PATCH 57/58] laser offset fix --- scripts/system/controllers/controllerDispatcher.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 43e59242de..63657e9b6f 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -369,28 +369,28 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) + posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true) }); this.leftControllerHudRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_LEFTHAND", filter: RayPick.PICK_HUD, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) + posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true) }); this.rightControllerRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_RIGHTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) + posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true) }); this.rightControllerHudRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_RIGHTHAND", filter: RayPick.PICK_HUD, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) + posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true) }); this.handleHandMessage = function(channel, message, sender) { From 7e2b2960ed26cfc84da2a2051f7a444300d8e2da Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 15 Sep 2017 16:17:41 -0700 Subject: [PATCH 58/58] Fix for lighting as IPD scale changes. (cherry picked from commit a260aaaae898df5453ac7465e53af741cad46215) --- interface/src/Application.cpp | 18 ++++++++++-------- interface/src/ui/overlays/Base3DOverlay.h | 3 --- interface/src/ui/overlays/Planar3DOverlay.cpp | 3 ++- interface/src/ui/overlays/Web3DOverlay.cpp | 9 --------- interface/src/ui/overlays/Web3DOverlay.h | 1 - .../src/display-plugins/hmd/HmdDisplayPlugin.h | 2 +- plugins/oculus/src/OculusBaseDisplayPlugin.cpp | 14 ++++++++++++++ plugins/oculus/src/OculusBaseDisplayPlugin.h | 1 + plugins/openvr/src/OpenVrDisplayPlugin.cpp | 13 +++++++++++++ plugins/openvr/src/OpenVrDisplayPlugin.h | 1 + 10 files changed, 42 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9de0154f1c..03621fc24a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2413,10 +2413,18 @@ void Application::paintGL() { auto lodManager = DependencyManager::get(); RenderArgs renderArgs; + + float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); { PROFILE_RANGE(render, "/buildFrustrumAndArgs"); { QMutexLocker viewLocker(&_viewMutex); + // adjust near clip plane to account for sensor scaling. + auto adjustedProjection = glm::perspective(_viewFrustum.getFieldOfView(), + _viewFrustum.getAspectRatio(), + DEFAULT_NEAR_CLIP * sensorToWorldScale, + _viewFrustum.getFarClip()); + _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), @@ -2570,7 +2578,6 @@ void Application::paintGL() { float ipdScale = hmdInterface->getIPDScale(); // scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly. - float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); ipdScale *= sensorToWorldScale; mat4 eyeProjections[2]; @@ -2582,6 +2589,7 @@ void Application::paintGL() { // in the overlay render? // Viewport is assigned to the size of the framebuffer renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()); + auto baseProjection = renderArgs.getViewFrustum().getProjection(); if (displayPlugin->isStereo()) { // Stereo modes will typically have a larger projection matrix overall, // so we ask for the 'mono' projection matrix, which for stereo and HMD @@ -2592,17 +2600,11 @@ void Application::paintGL() { // just relying on the left FOV in each case and hoping that the // overall culling margin of error doesn't cause popping in the // right eye. There are FIXMEs in the relevant plugins - _myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection())); + _myCamera.setProjection(displayPlugin->getCullingProjection(baseProjection)); renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; mat4 eyeProjections[2]; - // adjust near clip plane by sensorToWorldScale - auto baseProjection = glm::perspective(renderArgs.getViewFrustum().getFieldOfView(), - renderArgs.getViewFrustum().getAspectRatio(), - renderArgs.getViewFrustum().getNearClip() * sensorToWorldScale, - renderArgs.getViewFrustum().getFarClip()); - // FIXME we probably don't need to set the projection matrix every frame, // only when the display plugin changes (or in non-HMD modes when the user // changes the FOV manually, which right now I don't think they can. diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 7f72c80d55..55b55ed16f 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -16,9 +16,6 @@ #include "Overlay.h" -// AJT: keep or remove this. -// #define USE_SN_SCALE - class Base3DOverlay : public Overlay, public SpatiallyNestable { Q_OBJECT diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index e2877e1e07..e865714e58 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -69,8 +69,9 @@ bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::ve Transform Planar3DOverlay::evalRenderTransform() const { auto transform = getTransform(); + transform.setScale(1.0f); // ignore inherited scale factor from parents if (glm::length2(getDimensions()) != 1.0f) { transform.postScale(vec3(getDimensions(), 1.0f)); } return transform; -} \ No newline at end of file +} diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index b8249d6c75..0807d1c117 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -187,15 +187,6 @@ void Web3DOverlay::update(float deltatime) { Parent::update(deltatime); } -Transform Web3DOverlay::evalRenderTransform() const { - Transform transform = getTransform(); - transform.setScale(1.0f); // ignore inherited scale factor from parents - if (glm::length2(getDimensions()) != 1.0f) { - transform.postScale(vec3(getDimensions(), 1.0f)); - } - return transform; -} - QString Web3DOverlay::pickURL() { QUrl sourceUrl(_url); if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 7031a3f2c9..6bd540d120 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -38,7 +38,6 @@ public: virtual const render::ShapeKey getShapeKey() override; virtual void update(float deltatime) override; - virtual Transform Web3DOverlay::evalRenderTransform() const override; QObject* getEventHandler(); void setProxyWindow(QWindow* proxyWindow); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index bcf2b16ac6..db4e0ff7a1 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -28,7 +28,7 @@ public: float getIPD() const override final { return _ipd; } glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override { return _eyeProjections[eye]; } - glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override final { return _cullingProjection; } + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override { return _cullingProjection; } glm::uvec2 getRecommendedUiSize() const override final; glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } bool isDisplayVisible() const override { return isHmdMounted(); } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index aa39353b94..ea0af0d5f5 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -76,6 +76,20 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& ba } } +glm::mat4 OculusBaseDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const { + if (_session) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + auto combinedFov = _eyeFovs[0]; + combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan); + return toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL)); + } else { + return baseProjection; + } +} + // DLL based display plugins MUST initialize GLEW inside the DLL code. void OculusBaseDisplayPlugin::customizeContext() { glewExperimental = true; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 4d14223618..b3b99c0ad1 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -20,6 +20,7 @@ public: bool isSupported() const override; glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override; bool hasAsyncReprojection() const override { return true; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 25c85737fe..96ad19f46b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -370,6 +370,19 @@ glm::mat4 OpenVrDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& basePr } } +glm::mat4 OpenVrDisplayPlugin::getCullingProjection(const glm::mat4& baseProjection) const { + if (_system) { + ViewFrustum baseFrustum; + baseFrustum.setProjection(baseProjection); + float baseNearClip = baseFrustum.getNearClip(); + float baseFarClip = baseFrustum.getFarClip(); + // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes + return toGlm(_system->GetProjectionMatrix((vr::EVREye)0, baseNearClip, baseFarClip)); + } else { + return baseProjection; + } +} + float OpenVrDisplayPlugin::getTargetFrameRate() const { if (forceInterleavedReprojection && !_asyncReprojectionActive) { return TARGET_RATE_OpenVr / 2.0f; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 062345943a..6aea6ef575 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -39,6 +39,7 @@ public: const QString getName() const override { return NAME; } glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; + glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override; void init() override;