From bdbc6ddcc13eff1c8f28ee298d0f2afc807f9298 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 25 May 2017 10:50:41 -0700 Subject: [PATCH 01/21] change some code to look at head-controller position rather than hmd position --- interface/src/Application.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 55 ++++++++----------- interface/src/avatar/MyAvatar.h | 11 ++-- interface/src/avatar/MySkeletonModel.cpp | 2 +- .../src/scripting/HMDScriptingInterface.cpp | 2 +- libraries/controllers/src/controllers/Pose.h | 4 ++ 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ae490c05e7..7926905273 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3953,6 +3953,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtPosition.x = -lookAtPosition.x; } if (isHMD) { + // TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose(); glm::quat hmdRotation = glm::quat_cast(headPose); lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition); @@ -3995,7 +3996,8 @@ void Application::updateMyAvatarLookAtPosition() { } else { // I am not looking at anyone else, so just look forward if (isHMD) { - glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * + (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b4e418b6a2..4bb9a2ef5f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -401,7 +401,7 @@ void MyAvatar::update(float deltaTime) { // update moving average of HMD facing in xz plane. const float HMD_FACING_TIMESCALE = 4.0f; // very slow average float tau = deltaTime / HMD_FACING_TIMESCALE; - _hmdSensorFacingMovingAverage = lerp(_hmdSensorFacingMovingAverage, _hmdSensorFacing, tau); + _headControllerFacingMovingAverage = lerp(_headControllerFacingMovingAverage, _headControllerFacing, tau); if (_smoothOrientationTimer < SMOOTH_TIME_ORIENTATION) { _rotationChanged = usecTimestampNow(); @@ -409,16 +409,18 @@ void MyAvatar::update(float deltaTime) { } #ifdef DEBUG_DRAW_HMD_MOVING_AVERAGE - glm::vec3 p = transformPoint(getSensorToWorldMatrix(), _hmdSensorPosition + glm::vec3(_hmdSensorFacingMovingAverage.x, 0.0f, _hmdSensorFacingMovingAverage.y)); + glm::vec3 p = transformPoint(getSensorToWorldMatrix(), getHeadControllerPoseInAvatarFrame() + + glm::vec3(_headControllerFacingMovingAverage.x, 0.0f, _headControllerFacingMovingAverage.y)); DebugDraw::getInstance().addMarker("facing-avg", getOrientation(), p, glm::vec4(1.0f)); - p = transformPoint(getSensorToWorldMatrix(), _hmdSensorPosition + glm::vec3(_hmdSensorFacing.x, 0.0f, _hmdSensorFacing.y)); + p = transformPoint(getSensorToWorldMatrix(), getHMDSensorPosition() + + glm::vec3(_headControllerFacing.x, 0.0f, _headControllerFacing.y)); DebugDraw::getInstance().addMarker("facing", getOrientation(), p, glm::vec4(1.0f)); #endif if (_goToPending) { setPosition(_goToPosition); setOrientation(_goToOrientation); - _hmdSensorFacingMovingAverage = _hmdSensorFacing; // reset moving average + _headControllerFacingMovingAverage = _headControllerFacing; // reset moving average _goToPending = false; // updateFromHMDSensorMatrix (called from paintGL) expects that the sensorToWorldMatrix is updated for any position changes // that happen between render and Application::update (which calls updateSensorToWorldMatrix to do so). @@ -625,7 +627,7 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { _hmdSensorMatrix = hmdSensorMatrix; auto newHmdSensorPosition = extractTranslation(hmdSensorMatrix); - if (newHmdSensorPosition != _hmdSensorPosition && + if (newHmdSensorPosition != getHMDSensorPosition() && glm::length(newHmdSensorPosition) > MAX_HMD_ORIGIN_DISTANCE) { qWarning() << "Invalid HMD sensor position " << newHmdSensorPosition; // Ignore unreasonable HMD sensor data @@ -633,7 +635,7 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { } _hmdSensorPosition = newHmdSensorPosition; _hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix); - _hmdSensorFacing = getFacingDir2D(_hmdSensorOrientation); + _headControllerFacing = getFacingDir2D(_headControllerPoseInSensorFrameCache.get().rotation); } void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeValueCache& matrixCache) { @@ -671,7 +673,7 @@ void MyAvatar::updateSensorToWorldMatrix() { // Update avatar head rotation with sensor data void MyAvatar::updateFromTrackers(float deltaTime) { - glm::vec3 estimatedPosition, estimatedRotation; + glm::vec3 estimatedRotation; bool inHmd = qApp->isHMDMode(); bool playing = DependencyManager::get()->isPlaying(); @@ -682,11 +684,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { FaceTracker* tracker = qApp->getActiveFaceTracker(); bool inFacetracker = tracker && !FaceTracker::isMuted(); - if (inHmd) { - estimatedPosition = extractTranslation(getHMDSensorMatrix()); - estimatedPosition.x *= -1.0f; - } else if (inFacetracker) { - estimatedPosition = tracker->getHeadTranslation(); + if (inFacetracker) { estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); } @@ -1884,20 +1882,14 @@ void MyAvatar::updateOrientation(float deltaTime) { getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime); - if (qApp->isHMDMode()) { - glm::quat orientation = glm::quat_cast(getSensorToWorldMatrix()) * getHMDSensorOrientation(); - glm::quat bodyOrientation = getWorldBodyOrientation(); - glm::quat localOrientation = glm::inverse(bodyOrientation) * orientation; - - // these angles will be in radians - // ... so they need to be converted to degrees before we do math... - glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; - - Head* head = getHead(); - head->setBaseYaw(YAW(euler)); - head->setBasePitch(PITCH(euler)); - head->setBaseRoll(ROLL(euler)); - } + glm::quat localOrientation = getHeadControllerPoseInAvatarFrame(); + // these angles will be in radians + // ... so they need to be converted to degrees before we do math... + glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; + Head* head = getHead(); + head->setBaseYaw(YAW(euler)); + head->setBasePitch(PITCH(euler)); + head->setBaseRoll(ROLL(euler)); } void MyAvatar::updateActionMotor(float deltaTime) { @@ -2332,8 +2324,8 @@ glm::quat MyAvatar::getWorldBodyOrientation() const { glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // HMD is in sensor space. - const glm::vec3 hmdPosition = getHMDSensorPosition(); - const glm::quat hmdOrientation = getHMDSensorOrientation(); + const glm::vec3 hmdPosition = getHeadControllerPoseInSensorFrame(); + const glm::quat hmdOrientation = getHeadControllerPoseInSensorFrame(); const glm::quat hmdOrientationYawOnly = cancelOutRollAndPitch(hmdOrientation); const Rig& rig = _skeletonModel->getRig(); @@ -2478,7 +2470,7 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co } else { const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); - return glm::dot(myAvatar.getHMDSensorFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; + return glm::dot(myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; } } @@ -2625,9 +2617,10 @@ 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. + // 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(_hmdSensorMatrix); + glm::mat4 cameraSensorToWorldMatrix = cameraWorldMatrix * glm::inverse(getHMDSensorMatrix()); // Using the new cameraSensorToWorldMatrix, compute where the controller is in world space. glm::mat4 controllerWorldMatrix = cameraSensorToWorldMatrix * controllerSensorMatrix; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fde350a43e..05615a600d 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -185,7 +185,6 @@ public: const glm::mat4& getHMDSensorMatrix() const { return _hmdSensorMatrix; } const glm::vec3& getHMDSensorPosition() const { return _hmdSensorPosition; } const glm::quat& getHMDSensorOrientation() const { return _hmdSensorOrientation; } - const glm::vec2& getHMDSensorFacingMovingAverage() const { return _hmdSensorFacingMovingAverage; } Q_INVOKABLE void setOrientationVar(const QVariant& newOrientationVar); Q_INVOKABLE QVariant getOrientationVar() const; @@ -470,6 +469,8 @@ public: controller::Pose getHeadControllerPoseInSensorFrame() const; controller::Pose getHeadControllerPoseInWorldFrame() const; controller::Pose getHeadControllerPoseInAvatarFrame() const; + const glm::vec2& getHeadControllerFacingMovingAverage() const { return _headControllerFacingMovingAverage; } + bool hasDriveInput() const; @@ -664,13 +665,13 @@ private: // working copies -- 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. + // cache of the current HMD sensor position and orientation in sensor space. glm::mat4 _hmdSensorMatrix; glm::quat _hmdSensorOrientation; glm::vec3 _hmdSensorPosition; - glm::vec2 _hmdSensorFacing; // facing vector in xz plane - glm::vec2 _hmdSensorFacingMovingAverage { 0, 0 }; // facing vector in xz plane + // cache head controller pose in sensor space + glm::vec2 _headControllerFacing; // facing vector in xz plane + glm::vec2 _headControllerFacingMovingAverage { 0, 0 }; // facing vector in xz plane // cache of the current body position and orientation of the avatar's body, // in sensor space. diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 828a5f8a01..a98055ad35 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -59,7 +59,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } else { if (qApp->isHMDMode()) { // get HMD position from sensor space into world space, and back into rig space - glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation()); glm::mat4 worldToRig = glm::inverse(rigToWorld); glm::mat4 rigHMDMat = worldToRig * worldHMDMat; diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 95bf5eb028..d0e8e74d85 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -118,7 +118,7 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const { auto myAvatar = DependencyManager::get()->getMyAvatar(); - return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + return myAvatar->getSensorToWorldMatrix() * (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); } glm::vec3 HMDScriptingInterface::getPosition() const { diff --git a/libraries/controllers/src/controllers/Pose.h b/libraries/controllers/src/controllers/Pose.h index a6d1360f9f..10cb65a421 100644 --- a/libraries/controllers/src/controllers/Pose.h +++ b/libraries/controllers/src/controllers/Pose.h @@ -43,6 +43,10 @@ namespace controller { Pose transform(const glm::mat4& mat) const; Pose postTransform(const glm::mat4& mat) const; + operator glm::mat4() const { return createMatFromQuatAndPos(rotation, translation); } + operator glm::quat() const { return rotation; } + operator glm::vec3() const { return translation; } + static QScriptValue toScriptValue(QScriptEngine* engine, const Pose& event); static void fromScriptValue(const QScriptValue& object, Pose& event); }; From af5ba3a90af049f116bd0f2a07a6a94b610a69e2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 25 May 2017 15:14:10 -0700 Subject: [PATCH 02/21] ask display-plugins if they are head-controllers --- .../resources/controllers/oculus_touch.json | 2 ++ interface/src/Application.cpp | 15 +++++++++++++++ interface/src/Application.h | 1 + interface/src/avatar/MyAvatar.cpp | 18 ++++++++++-------- .../src/scripting/HMDScriptingInterface.cpp | 4 ++++ .../src/scripting/HMDScriptingInterface.h | 1 + .../impl/filters/LowVelocityFilter.h | 2 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 2 ++ .../hmd/DebugHmdDisplayPlugin.h | 1 + .../src/display-plugins/hmd/HmdDisplayPlugin.h | 1 + .../stereo/InterleavedStereoDisplayPlugin.h | 2 ++ .../stereo/SideBySideStereoDisplayPlugin.h | 2 ++ .../src/input-plugins/KeyboardMouseDevice.h | 1 + .../src/input-plugins/TouchscreenDevice.h | 1 + libraries/plugins/src/plugins/DisplayPlugin.h | 1 + libraries/plugins/src/plugins/InputPlugin.h | 1 + libraries/plugins/src/plugins/PluginUtils.cpp | 14 ++++++++++++++ libraries/plugins/src/plugins/PluginUtils.h | 1 + plugins/hifiKinect/src/KinectPlugin.cpp | 16 ++++++++++++++-- plugins/hifiKinect/src/KinectPlugin.h | 1 + plugins/hifiNeuron/src/NeuronPlugin.h | 1 + plugins/hifiSdl2/src/SDL2Manager.h | 1 + plugins/hifiSixense/src/SixenseManager.h | 1 + plugins/oculus/src/OculusControllerManager.h | 1 + plugins/oculus/src/OculusDisplayPlugin.h | 2 ++ plugins/openvr/src/OpenVrDisplayPlugin.h | 4 +++- plugins/openvr/src/ViveControllerManager.h | 1 + 27 files changed, 86 insertions(+), 12 deletions(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index aa574e36dd..544c8bd5b8 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -58,5 +58,7 @@ { "from": "OculusTouch.RightThumbUp", "to": "Standard.RightThumbUp" }, { "from": "OculusTouch.LeftIndexPoint", "to": "Standard.LeftIndexPoint" }, { "from": "OculusTouch.RightIndexPoint", "to": "Standard.RightIndexPoint" } + + { "from": "OculusTouch.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] } ] } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8761268147..6eb3aedef6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4851,6 +4851,21 @@ bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } +bool Application::isHeadControllerEnabled() const { + const InputPluginList& inputPlugins = PluginManager::getInstance()->getInputPlugins(); + for (auto& ip : inputPlugins) { + if (ip->isActive() && ip->isHeadController()) { + return true; + } + } + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + if (displayPlugin->isActive() && displayPlugin->isHeadController()) { + return true; + } + } + return false; +} + float Application::getTargetFrameRate() const { return getActiveDisplayPlugin()->getTargetFrameRate(); } QRect Application::getDesirableApplicationGeometry() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index e8507c39e8..aaf56ef0c2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -248,6 +248,7 @@ public: // rendering of several elements depend on that // TODO: carry that information on the Camera as a setting virtual bool isHMDMode() const override; + bool isHeadControllerEnabled() const; glm::mat4 getHMDSensorPose() const; glm::mat4 getEyeOffset(int eye) const; glm::mat4 getEyeProjection(int eye) const; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6cf6ef2fee..2f97cee0be 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1845,14 +1845,16 @@ void MyAvatar::updateOrientation(float deltaTime) { getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime); - glm::quat localOrientation = getHeadControllerPoseInAvatarFrame(); - // these angles will be in radians - // ... so they need to be converted to degrees before we do math... - glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; - Head* head = getHead(); - head->setBaseYaw(YAW(euler)); - head->setBasePitch(PITCH(euler)); - head->setBaseRoll(ROLL(euler)); + if (qApp->isHeadControllerEnabled()) { + glm::quat localOrientation = getHeadControllerPoseInAvatarFrame(); + // these angles will be in radians + // ... so they need to be converted to degrees before we do math... + glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; + Head* head = getHead(); + head->setBaseYaw(YAW(euler)); + head->setBasePitch(PITCH(euler)); + head->setBaseRoll(ROLL(euler)); + } } void MyAvatar::updateActionMotor(float deltaTime) { diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index d0e8e74d85..d347b72d7b 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -54,6 +54,10 @@ bool HMDScriptingInterface::isHMDAvailable(const QString& name) { return PluginUtils::isHMDAvailable(name); } +bool HMDScriptingInterface::isHeadControllerAvailable(const QString& name) { + return PluginUtils::isHeadControllerAvailable(name); +} + bool HMDScriptingInterface::isHandControllerAvailable(const QString& name) { return PluginUtils::isHandControllerAvailable(name); } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 7ecafdcbcb..4657e61d05 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -43,6 +43,7 @@ public: Q_INVOKABLE QString preferredAudioOutput() const; Q_INVOKABLE bool isHMDAvailable(const QString& name = ""); + Q_INVOKABLE bool isHeadControllerAvailable(const QString& name = ""); Q_INVOKABLE bool isHandControllerAvailable(const QString& name = ""); Q_INVOKABLE bool isSubdeviceContainingNameAvailable(const QString& name); diff --git a/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h b/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h index d870a5c551..feaf7685fd 100644 --- a/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h @@ -22,7 +22,7 @@ namespace controller { _translationConstant(translationConstant), _rotationConstant(rotationConstant) {} virtual float apply(float value) const override { return value; } - virtual Pose apply(Pose newPose) const; + virtual Pose apply(Pose newPose) const override; virtual bool parseParameters(const QJsonValue& parameters) override; private: diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index f3dd50602c..8dc1d83c1b 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -26,6 +26,8 @@ public: virtual bool isThrottled() const override; + virtual bool isHeadController() const override { return false; } + protected: mutable bool _isThrottled = false; diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h index 9bb82b1836..a971c25bf6 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h @@ -21,6 +21,7 @@ public: bool beginFrameRender(uint32_t frameIndex) override; float getTargetFrameRate() const override { return 90; } + virtual bool isHeadController() const override { return false; } protected: void updatePresentPose() override; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index aaa6e347e0..7dfd0fed1e 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -25,6 +25,7 @@ class HmdDisplayPlugin : public OpenGLDisplayPlugin { public: ~HmdDisplayPlugin(); bool isHmd() const override final { return true; } + bool isHeadController() const override = 0; 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]; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index debd340f24..4834e6c542 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -17,6 +17,8 @@ public: grouping getGrouping() const override { return ADVANCED; } glm::uvec2 getRecommendedRenderSize() const override; + virtual bool isHeadController() const override { return false; } + protected: // initialize OpenGL context settings needed by the plugin void customizeContext() override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h index 79bf2a9ecb..aa65fc37e3 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -19,6 +19,8 @@ public: virtual grouping getGrouping() const override { return ADVANCED; } virtual glm::uvec2 getRecommendedRenderSize() const override; + virtual bool isHeadController() const override { return false; } + private: static const QString NAME; }; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 3570ec7193..a0e216c904 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -71,6 +71,7 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return false; } + bool isHeadController() const override { return false; } void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h index 65e771e8f0..926f9dbdca 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h @@ -40,6 +40,7 @@ public: virtual const QString getName() const override { return NAME; } bool isHandController() const override { return false; } + bool isHeadController() const override { return false; } virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 754c919fd4..549387b6a4 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -135,6 +135,7 @@ public: virtual int getRequiredThreadCount() const { return 0; } virtual bool isHmd() const { return false; } + virtual bool isHeadController() const = 0; virtual int getHmdScreen() const { return -1; } /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } diff --git a/libraries/plugins/src/plugins/InputPlugin.h b/libraries/plugins/src/plugins/InputPlugin.h index 0db0b24420..0519ed776d 100644 --- a/libraries/plugins/src/plugins/InputPlugin.h +++ b/libraries/plugins/src/plugins/InputPlugin.h @@ -25,5 +25,6 @@ public: // If an input plugin is only a single device, it will only return it's primary name. virtual QStringList getSubdeviceNames() { return { getName() }; }; virtual bool isHandController() const = 0; + virtual bool isHeadController() const = 0; }; diff --git a/libraries/plugins/src/plugins/PluginUtils.cpp b/libraries/plugins/src/plugins/PluginUtils.cpp index 20dc011f25..4af77156e7 100644 --- a/libraries/plugins/src/plugins/PluginUtils.cpp +++ b/libraries/plugins/src/plugins/PluginUtils.cpp @@ -24,6 +24,20 @@ bool PluginUtils::isHMDAvailable(const QString& pluginName) { return false; } +bool PluginUtils::isHeadControllerAvailable(const QString& pluginName) { + for (auto& inputPlugin : PluginManager::getInstance()->getInputPlugins()) { + if (inputPlugin->isHeadController() && (pluginName.isEmpty() || inputPlugin->getName() == pluginName)) { + return true; + } + } + for (auto& displayPlugin : PluginManager::getInstance()->getDisplayPlugins()) { + if (displayPlugin->isHeadController() && (pluginName.isEmpty() || displayPlugin->getName() == pluginName)) { + return true; + } + } + return false; +}; + bool PluginUtils::isHandControllerAvailable(const QString& pluginName) { for (auto& inputPlugin : PluginManager::getInstance()->getInputPlugins()) { if (inputPlugin->isHandController() && (pluginName.isEmpty() || inputPlugin->getName() == pluginName)) { diff --git a/libraries/plugins/src/plugins/PluginUtils.h b/libraries/plugins/src/plugins/PluginUtils.h index 351c9e7e58..2b6206fe63 100644 --- a/libraries/plugins/src/plugins/PluginUtils.h +++ b/libraries/plugins/src/plugins/PluginUtils.h @@ -16,6 +16,7 @@ class PluginUtils { public: static bool isHMDAvailable(const QString& pluginName = ""); static bool isHandControllerAvailable(const QString& pluginName = ""); + static bool isHeadControllerAvailable(const QString& pluginName = ""); static bool isSubdeviceContainingNameAvailable(QString name); static bool isViveControllerAvailable(); static bool isOculusTouchControllerAvailable(); diff --git a/plugins/hifiKinect/src/KinectPlugin.cpp b/plugins/hifiKinect/src/KinectPlugin.cpp index 3a36be0982..834ee1ea2e 100644 --- a/plugins/hifiKinect/src/KinectPlugin.cpp +++ b/plugins/hifiKinect/src/KinectPlugin.cpp @@ -273,7 +273,19 @@ bool KinectPlugin::activate() { return false; } -bool KinectPlugin::isHandController() const { +bool KinectPlugin::isHandController() const { + bool sensorAvailable = false; +#ifdef HAVE_KINECT + if (_kinectSensor) { + BOOLEAN sensorIsAvailable = FALSE; + HRESULT hr = _kinectSensor->get_IsAvailable(&sensorIsAvailable); + sensorAvailable = SUCCEEDED(hr) && (sensorIsAvailable == TRUE); + } +#endif + return _enabled && _initialized && sensorAvailable; +} + +bool KinectPlugin::isHeadController() const { bool sensorAvailable = false; #ifdef HAVE_KINECT if (_kinectSensor) { @@ -654,4 +666,4 @@ void KinectPlugin::InputDevice::clearState() { int poseIndex = KinectJointIndexToPoseIndex((KinectJointIndex)i); _poseStateMap[poseIndex] = controller::Pose(); } -} \ No newline at end of file +} diff --git a/plugins/hifiKinect/src/KinectPlugin.h b/plugins/hifiKinect/src/KinectPlugin.h index 158e66ee62..e8f0745200 100644 --- a/plugins/hifiKinect/src/KinectPlugin.h +++ b/plugins/hifiKinect/src/KinectPlugin.h @@ -43,6 +43,7 @@ class KinectPlugin : public InputPlugin { Q_OBJECT public: bool isHandController() const override; + bool isHeadController() const override; // Plugin functions virtual void init() override; diff --git a/plugins/hifiNeuron/src/NeuronPlugin.h b/plugins/hifiNeuron/src/NeuronPlugin.h index 43b27d14dd..41c2322465 100644 --- a/plugins/hifiNeuron/src/NeuronPlugin.h +++ b/plugins/hifiNeuron/src/NeuronPlugin.h @@ -26,6 +26,7 @@ public: friend void FrameDataReceivedCallback(void* context, void* sender, _BvhDataHeaderEx* header, float* data); bool isHandController() const override { return false; } + bool isHeadController() const override { return false; } // Plugin functions virtual void init() override; diff --git a/plugins/hifiSdl2/src/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h index 4501d0792b..d2bbe8265e 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -28,6 +28,7 @@ public: QStringList getSubdeviceNames() override; bool isHandController() const override { return false; } + bool isHeadController() const override { return false; } void init() override; void deinit() override; diff --git a/plugins/hifiSixense/src/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h index 5237dba791..889f6c3bad 100644 --- a/plugins/hifiSixense/src/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -34,6 +34,7 @@ public: // Sixense always seems to initialize even if the hydras are not present. Is there // a way we can properly detect whether the hydras are present? bool isHandController() const override { return false; } + bool isHeadController() const override { return false; } virtual bool activate() override; virtual void deactivate() override; diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 11d699ca8e..77b40d3764 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -28,6 +28,7 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return _touch != nullptr; } + bool isHeadController() const override { return true; } QStringList getSubdeviceNames() override; bool activate() override; diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 9209fd373e..a4978a984e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,6 +24,8 @@ public: virtual QJsonObject getHardwareStats() const; + bool isHeadController() const override { return true; } + protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index a60c21a606..9856c27c50 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -56,7 +56,9 @@ public: bool isKeyboardVisible() override; // Possibly needs an additional thread for VR submission - int getRequiredThreadCount() const override; + int getRequiredThreadCount() const override; + + bool isHeadController() const override { return true; } protected: bool internalActivate() override; diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index fa2566da45..d147573d7c 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -39,6 +39,7 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return true; } + bool isHeadController() const override { return true; } bool activate() override; void deactivate() override; From e82e80e8e08cf68572049483b89992a3cd44ea9e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 30 May 2017 09:55:33 -0700 Subject: [PATCH 03/21] OculusDebugDisplayPlugin is head controller --- plugins/oculus/src/OculusDebugDisplayPlugin.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.h b/plugins/oculus/src/OculusDebugDisplayPlugin.h index ec05cd92e2..1cc6bd0f8e 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.h +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.h @@ -15,6 +15,8 @@ public: grouping getGrouping() const override { return DEVELOPER; } bool isSupported() const override; + bool isHeadController() const override { return false; } + protected: void hmdPresent() override {} bool isHmdMounted() const override { return true; } From 2ad85c158aafaa3477ed75edd6bfa53d53edbac5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 30 May 2017 17:11:56 -0700 Subject: [PATCH 04/21] more work on getting head routed through input system --- .../oculus/src/OculusControllerManager.cpp | 37 ++++++++++++++++--- plugins/oculus/src/OculusControllerManager.h | 9 ++++- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 6445c3c891..6042968ffc 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -230,14 +230,14 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control _lastControllerPose[controller] = tracking.HandPoses[hand]; return; } - + if (_lostTracking[controller]) { if (currentTime > _regainTrackingDeadline[controller]) { _poseStateMap.erase(controller); _poseStateMap[controller].valid = false; return; } - + } else { quint64 deadlineToRegainTracking = currentTime + LOST_TRACKING_DELAY; _regainTrackingDeadline[controller] = deadlineToRegainTracking; @@ -245,6 +245,10 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control } handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]); }); + + _poseStateMap.erase(controller::HEAD); + handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose); + using namespace controller; // Axes const auto& inputState = _parent._inputState; @@ -269,7 +273,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control if (inputState.Touches & pair.first) { _buttonPressedMap.insert(pair.second); } - } + } // Haptics { @@ -292,16 +296,36 @@ void OculusControllerManager::TouchDevice::focusOutEvent() { _buttonPressedMap.clear(); }; -void OculusControllerManager::TouchDevice::handlePose(float deltaTime, - const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, - const ovrPoseStatef& handPose) { +void OculusControllerManager::TouchDevice::handlePose(float deltaTime, + const controller::InputCalibrationData& inputCalibrationData, + ovrHandType hand, const ovrPoseStatef& handPose) { auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND; auto& pose = _poseStateMap[poseId]; pose = ovrControllerPoseToHandPose(hand, handPose); // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; pose = pose.transform(controllerToAvatar); +} +void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime, + const controller::InputCalibrationData& inputCalibrationData, + const ovrPoseStatef& headPose) { + auto poseId = controller::HEAD; + auto& pose = _poseStateMap[poseId]; + + pose.translation = toGlm(headPose.ThePose.Position); + pose.rotation = toGlm(headPose.ThePose.Orientation); + pose.angularVelocity = toGlm(headPose.AngularVelocity); + pose.velocity = toGlm(headPose.LinearVelocity); + pose.valid = true; + + qDebug() << "handleHeadPose" << pose.translation.x << pose.translation.y << pose.translation.z; + + // transform into avatar frame + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + pose = pose.transform(controllerToAvatar); + + qDebug() << "handleHeadPose after" << pose.translation.x << pose.translation.y << pose.translation.z; } void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, @@ -382,6 +406,7 @@ controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailabl makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), + makePair(HEAD, "Head"), makePair(LEFT_PRIMARY_THUMB_TOUCH, "LeftPrimaryThumbTouch"), makePair(LEFT_SECONDARY_THUMB_TOUCH, "LeftSecondaryThumbTouch"), diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 77b40d3764..61f2241f4d 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -76,8 +76,13 @@ private: private: void stopHapticPulse(bool leftHand); - void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); - void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); + void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, + ovrHandType hand, const ovrPoseStatef& handPose); + void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, + ovrHandType hand, const ovrPoseStatef& handPose); + void handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, + const ovrPoseStatef& headPose); + int _trackedControllers { 0 }; // perform an action when the TouchDevice mutex is acquired. From 7a47250aa7db257553711de94c7c2a7de1454246 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 31 May 2017 10:21:10 -0700 Subject: [PATCH 05/21] oops missed a comma --- interface/resources/controllers/oculus_touch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index 544c8bd5b8..03fc1cbefb 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -57,7 +57,7 @@ { "from": "OculusTouch.LeftThumbUp", "to": "Standard.LeftThumbUp" }, { "from": "OculusTouch.RightThumbUp", "to": "Standard.RightThumbUp" }, { "from": "OculusTouch.LeftIndexPoint", "to": "Standard.LeftIndexPoint" }, - { "from": "OculusTouch.RightIndexPoint", "to": "Standard.RightIndexPoint" } + { "from": "OculusTouch.RightIndexPoint", "to": "Standard.RightIndexPoint" }, { "from": "OculusTouch.Head", "to" : "Standard.Head", "when" : [ "Application.InHMD"] } ] From e37387f45c4e1f80ac431406dbd332fc0d8c7356 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 31 May 2017 14:01:09 -0700 Subject: [PATCH 06/21] sync --- interface/src/Application.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 18 +++++++++--------- interface/src/avatar/MySkeletonModel.cpp | 3 ++- .../src/scripting/HMDScriptingInterface.cpp | 3 ++- plugins/oculus/src/OculusControllerManager.cpp | 9 ++++----- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 17f9b03346..13c3605320 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3992,7 +3992,7 @@ void Application::updateMyAvatarLookAtPosition() { // I am not looking at anyone else, so just look forward if (isHMD) { glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * - (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); + (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame() * Matrices::Y_180; lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 11c8c5b186..e2aadbc365 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2328,9 +2328,9 @@ glm::quat MyAvatar::getWorldBodyOrientation() const { glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // HMD is in sensor space. - const glm::vec3 hmdPosition = getHeadControllerPoseInSensorFrame(); - const glm::quat hmdOrientation = getHeadControllerPoseInSensorFrame(); - const glm::quat hmdOrientationYawOnly = cancelOutRollAndPitch(hmdOrientation); + const glm::vec3 headPosition = getHeadControllerPoseInSensorFrame(); + const glm::quat headOrientation = (glm::quat)getHeadControllerPoseInSensorFrame() * Quaternions::Y_180; + const glm::quat headOrientationYawOnly = cancelOutRollAndPitch(headOrientation); const Rig& rig = _skeletonModel->getRig(); int rightEyeIndex = rig.indexOfJoint("RightEye"); @@ -2353,12 +2353,12 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // eyeToNeck offset is relative full HMD orientation. // while neckToRoot offset is only relative to HMDs yaw. - // Y_180 is necessary because rig is z forward and hmdOrientation is -z forward - glm::vec3 eyeToNeck = hmdOrientation * Quaternions::Y_180 * (localNeck - localEyes); - glm::vec3 neckToRoot = hmdOrientationYawOnly * Quaternions::Y_180 * -localNeck; - glm::vec3 bodyPos = hmdPosition + eyeToNeck + neckToRoot; + // Y_180 is necessary because rig is z forward and headOrientation is -z forward + glm::vec3 eyeToNeck = headOrientation * Quaternions::Y_180 * (localNeck - localEyes); + glm::vec3 neckToRoot = headOrientationYawOnly * Quaternions::Y_180 * -localNeck; + glm::vec3 bodyPos = headPosition + eyeToNeck + neckToRoot; - return createMatFromQuatAndPos(hmdOrientationYawOnly, bodyPos); + return createMatFromQuatAndPos(headOrientationYawOnly, bodyPos); } glm::vec3 MyAvatar::getPositionForAudio() { @@ -2474,7 +2474,7 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co } else { const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); - return glm::dot(myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; + return glm::dot(myAvatar.getHeadControllerFacingMovingAverage() * -1.0f, bodyFacing) < FOLLOW_ROTATION_THRESHOLD; } } diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 84e4a9ff83..20b9ee2850 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -59,7 +59,8 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } else { if (qApp->isHMDMode()) { // get HMD position from sensor space into world space, and back into rig space - glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); + // glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); + glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation()); glm::mat4 worldToRig = glm::inverse(rigToWorld); glm::mat4 rigHMDMat = worldToRig * worldHMDMat; diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index d347b72d7b..ecc207a519 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -122,7 +122,8 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const { auto myAvatar = DependencyManager::get()->getMyAvatar(); - return myAvatar->getSensorToWorldMatrix() * (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); + // return myAvatar->getSensorToWorldMatrix() * (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); + return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); } glm::vec3 HMDScriptingInterface::getPosition() const { diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 6042968ffc..0236ea1e62 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -19,6 +19,8 @@ #include #include +#include +#include #include @@ -313,19 +315,16 @@ void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime, auto poseId = controller::HEAD; auto& pose = _poseStateMap[poseId]; + static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y); pose.translation = toGlm(headPose.ThePose.Position); - pose.rotation = toGlm(headPose.ThePose.Orientation); + pose.rotation = toGlm(headPose.ThePose.Orientation) * yFlip; pose.angularVelocity = toGlm(headPose.AngularVelocity); pose.velocity = toGlm(headPose.LinearVelocity); pose.valid = true; - qDebug() << "handleHeadPose" << pose.translation.x << pose.translation.y << pose.translation.z; - // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; pose = pose.transform(controllerToAvatar); - - qDebug() << "handleHeadPose after" << pose.translation.x << pose.translation.y << pose.translation.z; } void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, From eca05d9c4281cc12187c77abb698f1332f7bf434 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 10:57:53 -0700 Subject: [PATCH 07/21] more use of head input --- interface/src/avatar/MySkeletonModel.cpp | 3 +-- interface/src/scripting/HMDScriptingInterface.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 20b9ee2850..84e4a9ff83 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -59,8 +59,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } else { if (qApp->isHMDMode()) { // get HMD position from sensor space into world space, and back into rig space - // glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); - glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation()); glm::mat4 worldToRig = glm::inverse(rigToWorld); glm::mat4 rigHMDMat = worldToRig * worldHMDMat; diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index ecc207a519..1227f46eb6 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -122,8 +122,8 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const { auto myAvatar = DependencyManager::get()->getMyAvatar(); - // return myAvatar->getSensorToWorldMatrix() * (glm::mat4)myAvatar->getHeadControllerPoseInSensorFrame(); - return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + // return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + return myAvatar->getSensorToWorldMatrix() * myAvatar->getHeadControllerPoseInSensorFrame().getMatrix() * Matrices::Y_180; } glm::vec3 HMDScriptingInterface::getPosition() const { From ac6135387cf3a520851e4acc9d709c3c4ad6175c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 13:37:16 -0700 Subject: [PATCH 08/21] display plugins are never head controllers --- interface/src/Application.cpp | 5 ----- interface/src/avatar/MySkeletonModel.cpp | 2 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 2 -- .../display-plugins/hmd/DebugHmdDisplayPlugin.h | 2 -- .../src/display-plugins/hmd/HmdDisplayPlugin.h | 1 - .../stereo/InterleavedStereoDisplayPlugin.h | 2 -- .../stereo/SideBySideStereoDisplayPlugin.h | 2 -- libraries/plugins/src/plugins/DisplayPlugin.h | 1 - libraries/plugins/src/plugins/PluginUtils.cpp | 5 ----- plugins/oculus/src/OculusControllerManager.cpp | 14 ++++++++++++-- plugins/oculus/src/OculusControllerManager.h | 2 +- plugins/oculus/src/OculusDebugDisplayPlugin.h | 2 -- plugins/oculus/src/OculusDisplayPlugin.h | 2 -- plugins/openvr/src/OpenVrDisplayPlugin.h | 2 -- 14 files changed, 14 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d34de2b0e..aee829b624 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4865,11 +4865,6 @@ bool Application::isHeadControllerEnabled() const { return true; } } - foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { - if (displayPlugin->isActive() && displayPlugin->isHeadController()) { - return true; - } - } return false; } diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 84e4a9ff83..3721eea569 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -59,7 +59,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } else { if (qApp->isHMDMode()) { // get HMD position from sensor space into world space, and back into rig space - glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame(); + glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame().getMatrix(); glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation()); glm::mat4 worldToRig = glm::inverse(rigToWorld); glm::mat4 rigHMDMat = worldToRig * worldHMDMat; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 8dc1d83c1b..f3dd50602c 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -26,8 +26,6 @@ public: virtual bool isThrottled() const override; - virtual bool isHeadController() const override { return false; } - protected: mutable bool _isThrottled = false; diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h index a971c25bf6..55746e65eb 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h @@ -21,8 +21,6 @@ public: bool beginFrameRender(uint32_t frameIndex) override; float getTargetFrameRate() const override { return 90; } - virtual bool isHeadController() const override { return false; } - protected: void updatePresentPose() override; void hmdPresent() override {} diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 7dfd0fed1e..aaa6e347e0 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -25,7 +25,6 @@ class HmdDisplayPlugin : public OpenGLDisplayPlugin { public: ~HmdDisplayPlugin(); bool isHmd() const override final { return true; } - bool isHeadController() const override = 0; 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]; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index 4834e6c542..debd340f24 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -17,8 +17,6 @@ public: grouping getGrouping() const override { return ADVANCED; } glm::uvec2 getRecommendedRenderSize() const override; - virtual bool isHeadController() const override { return false; } - protected: // initialize OpenGL context settings needed by the plugin void customizeContext() override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h index aa65fc37e3..79bf2a9ecb 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -19,8 +19,6 @@ public: virtual grouping getGrouping() const override { return ADVANCED; } virtual glm::uvec2 getRecommendedRenderSize() const override; - virtual bool isHeadController() const override { return false; } - private: static const QString NAME; }; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 549387b6a4..754c919fd4 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -135,7 +135,6 @@ public: virtual int getRequiredThreadCount() const { return 0; } virtual bool isHmd() const { return false; } - virtual bool isHeadController() const = 0; virtual int getHmdScreen() const { return -1; } /// By default, all HMDs are stereo virtual bool isStereo() const { return isHmd(); } diff --git a/libraries/plugins/src/plugins/PluginUtils.cpp b/libraries/plugins/src/plugins/PluginUtils.cpp index 4af77156e7..ce67f7c585 100644 --- a/libraries/plugins/src/plugins/PluginUtils.cpp +++ b/libraries/plugins/src/plugins/PluginUtils.cpp @@ -30,11 +30,6 @@ bool PluginUtils::isHeadControllerAvailable(const QString& pluginName) { return true; } } - for (auto& displayPlugin : PluginManager::getInstance()->getDisplayPlugins()) { - if (displayPlugin->isHeadController() && (pluginName.isEmpty() || displayPlugin->getName() == pluginName)) { - return true; - } - } return false; }; diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 0236ea1e62..60031a1179 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -210,10 +210,20 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { _buttonPressedMap.clear(); } +bool OculusControllerManager::isHeadController() const { + // this plugin is a head controller if the HMD is mounted. + ovrSessionStatus status; + + bool success = OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)); + if (!success) { + return false; + } + return status.HmdMounted == ovrTrue; +} + void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { _buttonPressedMap.clear(); - ovrSessionStatus status; - if (!OVR_SUCCESS(ovr_GetSessionStatus(_parent._session, &status)) || (ovrFalse == status.HmdMounted)) { + if (!_parent.isHeadController()) { // if the HMD isn't on someone's head, don't take input from the controllers return; } diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 61f2241f4d..54237645eb 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -28,7 +28,7 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return _touch != nullptr; } - bool isHeadController() const override { return true; } + bool isHeadController() const override; QStringList getSubdeviceNames() override; bool activate() override; diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.h b/plugins/oculus/src/OculusDebugDisplayPlugin.h index 1cc6bd0f8e..ec05cd92e2 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.h +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.h @@ -15,8 +15,6 @@ public: grouping getGrouping() const override { return DEVELOPER; } bool isSupported() const override; - bool isHeadController() const override { return false; } - protected: void hmdPresent() override {} bool isHmdMounted() const override { return true; } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index a4978a984e..9209fd373e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -24,8 +24,6 @@ public: virtual QJsonObject getHardwareStats() const; - bool isHeadController() const override { return true; } - protected: QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 9856c27c50..01e02c9892 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -58,8 +58,6 @@ public: // Possibly needs an additional thread for VR submission int getRequiredThreadCount() const override; - bool isHeadController() const override { return true; } - protected: bool internalActivate() override; void internalDeactivate() override; From 552b69bb1c6aefc0cf7303da62f70a14e99e2c4f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 13:47:19 -0700 Subject: [PATCH 09/21] cleanups --- interface/src/avatar/MyAvatar.cpp | 1 + interface/src/scripting/HMDScriptingInterface.cpp | 3 +-- .../src/display-plugins/hmd/DebugHmdDisplayPlugin.h | 1 + plugins/hifiKinect/src/KinectPlugin.cpp | 10 +--------- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5723751631..ef2e53cbb9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1889,6 +1889,7 @@ void MyAvatar::updateOrientation(float deltaTime) { // these angles will be in radians // ... so they need to be converted to degrees before we do math... glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; + Head* head = getHead(); head->setBaseYaw(YAW(euler)); head->setBasePitch(PITCH(euler)); diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 1227f46eb6..883a6e758e 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -122,8 +122,7 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const { glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const { auto myAvatar = DependencyManager::get()->getMyAvatar(); - // return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); - return myAvatar->getSensorToWorldMatrix() * myAvatar->getHeadControllerPoseInSensorFrame().getMatrix() * Matrices::Y_180; + return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); } glm::vec3 HMDScriptingInterface::getPosition() const { diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h index 55746e65eb..9bb82b1836 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h @@ -21,6 +21,7 @@ public: bool beginFrameRender(uint32_t frameIndex) override; float getTargetFrameRate() const override { return 90; } + protected: void updatePresentPose() override; void hmdPresent() override {} diff --git a/plugins/hifiKinect/src/KinectPlugin.cpp b/plugins/hifiKinect/src/KinectPlugin.cpp index 834ee1ea2e..92c578e9aa 100644 --- a/plugins/hifiKinect/src/KinectPlugin.cpp +++ b/plugins/hifiKinect/src/KinectPlugin.cpp @@ -286,15 +286,7 @@ bool KinectPlugin::isHandController() const { } bool KinectPlugin::isHeadController() const { - bool sensorAvailable = false; -#ifdef HAVE_KINECT - if (_kinectSensor) { - BOOLEAN sensorIsAvailable = FALSE; - HRESULT hr = _kinectSensor->get_IsAvailable(&sensorIsAvailable); - sensorAvailable = SUCCEEDED(hr) && (sensorIsAvailable == TRUE); - } -#endif - return _enabled && _initialized && sensorAvailable; + return isHandController(); } From f45db99149946bc61a97034e98af77c97da367ac Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 14:35:53 -0700 Subject: [PATCH 10/21] for the moment, vive input plugin isn't a head-controller unless the HMD is being worn --- plugins/openvr/src/ViveControllerManager.cpp | 5 +++++ plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 53500a3353..11d390fca4 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -138,6 +138,11 @@ void ViveControllerManager::deactivate() { _registeredWithInputMapper = false; } +bool ViveControllerManager::isHeadController() const { + vr::EDeviceActivityLevel activityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); + return activityLevel == vr::k_EDeviceActivityLevel_UserInteraction; +} + void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { if (!_system) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 6532540285..0fdd04fdfb 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -41,7 +41,7 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return true; } - bool isHeadController() const override { return true; } + bool isHeadController() const override; bool activate() override; void deactivate() override; From 7d21ab88b0add448700fe4cca4c5dacb2b5a19c8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 16:14:59 -0700 Subject: [PATCH 11/21] add some saftey checks. cleanups --- interface/src/Application.cpp | 12 +++++++++--- interface/src/avatar/MyAvatar.cpp | 5 ++--- plugins/oculus/src/OculusControllerManager.cpp | 6 ++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aee829b624..8d20cbe715 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4423,7 +4423,9 @@ void Application::update(float deltaTime) { myAvatar->setSpineControllerPosesInSensorFrame(hipsPose.transform(avatarToSensorMatrix), spine2Pose.transform(avatarToSensorMatrix)); controller::Pose headPose = userInputMapper->getPoseState(controller::Action::HEAD); - myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); + if (headPose.isValid()) { + myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); + } controller::Pose leftArmPose = userInputMapper->getPoseState(controller::Action::LEFT_ARM); controller::Pose rightArmPose = userInputMapper->getPoseState(controller::Action::RIGHT_ARM); @@ -4859,9 +4861,13 @@ bool Application::isHMDMode() const { } bool Application::isHeadControllerEnabled() const { - const InputPluginList& inputPlugins = PluginManager::getInstance()->getInputPlugins(); + auto pluginManager = PluginManager::getInstance(); + if (!pluginManager) { + return false; + } + const InputPluginList& inputPlugins = pluginManager->getInputPlugins(); for (auto& ip : inputPlugins) { - if (ip->isActive() && ip->isHeadController()) { + if (ip && ip->isActive() && ip->isHeadController()) { return true; } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ef2e53cbb9..c26cdf0b01 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2328,7 +2328,6 @@ glm::quat MyAvatar::getWorldBodyOrientation() const { // old school meat hook style glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { - // HMD is in sensor space. const glm::vec3 headPosition = getHeadControllerPoseInSensorFrame().translation; const glm::quat headOrientation = getHeadControllerPoseInSensorFrame().rotation * Quaternions::Y_180; const glm::quat headOrientationYawOnly = cancelOutRollAndPitch(headOrientation); @@ -2352,8 +2351,8 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // apply simplistic head/neck model // figure out where the avatar body should be by applying offsets from the avatar's neck & head joints. - // eyeToNeck offset is relative full HMD orientation. - // while neckToRoot offset is only relative to HMDs yaw. + // eyeToNeck offset is relative to head's full orientation, + // while neckToRoot offset is only relative to head's yaw. // Y_180 is necessary because rig is z forward and headOrientation is -z forward glm::vec3 eyeToNeck = headOrientation * Quaternions::Y_180 * (localNeck - localEyes); glm::vec3 neckToRoot = headOrientationYawOnly * Quaternions::Y_180 * -localNeck; diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 60031a1179..ff3e614077 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -221,8 +221,11 @@ bool OculusControllerManager::isHeadController() const { return status.HmdMounted == ovrTrue; } -void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { +void OculusControllerManager::TouchDevice::update(float deltaTime, + const controller::InputCalibrationData& inputCalibrationData) { _buttonPressedMap.clear(); + _poseStateMap.erase(controller::HEAD); + if (!_parent.isHeadController()) { // if the HMD isn't on someone's head, don't take input from the controllers return; @@ -258,7 +261,6 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]); }); - _poseStateMap.erase(controller::HEAD); handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose); using namespace controller; From 27664756de05b4b8ac96cc3fdb9d81e24450b6b1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Jun 2017 16:37:04 -0700 Subject: [PATCH 12/21] with vive head-puck, isHeadController is true, even when HMD isn't mounted --- plugins/openvr/src/ViveControllerManager.cpp | 3 +++ plugins/openvr/src/ViveControllerManager.h | 1 + 2 files changed, 4 insertions(+) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2f2278ae82..abff0770a7 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -165,6 +165,9 @@ void ViveControllerManager::deactivate() { } bool ViveControllerManager::isHeadController() const { + if (_inputDevice && _inputDevice->isHeadController()) { + return true; + } vr::EDeviceActivityLevel activityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); return activityLevel == vr::k_EDeviceActivityLevel_UserInteraction; } diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index b06ba5bf89..d03818ea34 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -55,6 +55,7 @@ private: class InputDevice : public controller::InputDevice { public: InputDevice(vr::IVRSystem*& system); + bool isHeadController() const { return _overrideHead; } private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; From 9088e288e09c02184eb60932398f83967d7677bd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Jun 2017 13:57:53 -0700 Subject: [PATCH 13/21] don't worry about head controller being enabled, just check to see if head pose is valid --- interface/src/Application.cpp | 18 +------------- interface/src/Application.h | 1 - interface/src/avatar/MyAvatar.cpp | 8 +++++-- interface/src/avatar/MySkeletonModel.cpp | 24 +++++++------------ .../oculus/src/OculusControllerManager.cpp | 20 +++++++++------- plugins/oculus/src/OculusControllerManager.h | 3 ++- plugins/openvr/src/ViveControllerManager.cpp | 4 ++-- plugins/openvr/src/ViveControllerManager.h | 5 ++-- 8 files changed, 33 insertions(+), 50 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 673813b0db..35a8f65c06 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4429,9 +4429,7 @@ void Application::update(float deltaTime) { myAvatar->setSpineControllerPosesInSensorFrame(hipsPose.transform(avatarToSensorMatrix), spine2Pose.transform(avatarToSensorMatrix)); controller::Pose headPose = userInputMapper->getPoseState(controller::Action::HEAD); - if (headPose.isValid()) { - myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); - } + myAvatar->setHeadControllerPoseInSensorFrame(headPose.transform(avatarToSensorMatrix)); controller::Pose leftArmPose = userInputMapper->getPoseState(controller::Action::LEFT_ARM); controller::Pose rightArmPose = userInputMapper->getPoseState(controller::Action::RIGHT_ARM); @@ -4867,20 +4865,6 @@ bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } -bool Application::isHeadControllerEnabled() const { - auto pluginManager = PluginManager::getInstance(); - if (!pluginManager) { - return false; - } - const InputPluginList& inputPlugins = pluginManager->getInputPlugins(); - for (auto& ip : inputPlugins) { - if (ip && ip->isActive() && ip->isHeadController()) { - return true; - } - } - return false; -} - float Application::getTargetFrameRate() const { return getActiveDisplayPlugin()->getTargetFrameRate(); } QRect Application::getDesirableApplicationGeometry() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index ec3792ea75..9cf03f1cef 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -248,7 +248,6 @@ public: // rendering of several elements depend on that // TODO: carry that information on the Camera as a setting virtual bool isHMDMode() const override; - bool isHeadControllerEnabled() const; glm::mat4 getHMDSensorPose() const; glm::mat4 getEyeOffset(int eye) const; glm::mat4 getEyeProjection(int eye) const; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c26cdf0b01..7e998b11c0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -641,9 +641,13 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { // Ignore unreasonable HMD sensor data return; } + _hmdSensorPosition = newHmdSensorPosition; _hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix); - _headControllerFacing = getFacingDir2D(_headControllerPoseInSensorFrameCache.get().rotation); + auto headPose = _headControllerPoseInSensorFrameCache.get(); + if (headPose.isValid()) { + _headControllerFacing = getFacingDir2D(headPose.rotation); + } } void MyAvatar::updateJointFromController(controller::Action poseKey, ThreadSafeValueCache& matrixCache) { @@ -1884,7 +1888,7 @@ void MyAvatar::updateOrientation(float deltaTime) { getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime); - if (qApp->isHeadControllerEnabled()) { + if (getHeadControllerPoseInAvatarFrame().isValid()) { glm::quat localOrientation = getHeadControllerPoseInAvatarFrame().rotation; // these angles will be in radians // ... so they need to be converted to degrees before we do math... diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 3721eea569..e74df4cf0f 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -52,26 +52,18 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { // input action is the highest priority source for head orientation. auto avatarHeadPose = myAvatar->getHeadControllerPoseInAvatarFrame(); if (avatarHeadPose.isValid()) { - glm::mat4 rigHeadMat = Matrices::Y_180 * createMatFromQuatAndPos(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation()); + glm::mat4 rigHeadMat = Matrices::Y_180 * + createMatFromQuatAndPos(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation()); headParams.rigHeadPosition = extractTranslation(rigHeadMat); headParams.rigHeadOrientation = glmExtractRotation(rigHeadMat); headParams.headEnabled = true; } else { - if (qApp->isHMDMode()) { - // get HMD position from sensor space into world space, and back into rig space - glm::mat4 worldHMDMat = myAvatar->getHeadControllerPoseInWorldFrame().getMatrix(); - glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation()); - glm::mat4 worldToRig = glm::inverse(rigToWorld); - glm::mat4 rigHMDMat = worldToRig * worldHMDMat; - _rig.computeHeadFromHMD(AnimPose(rigHMDMat), headParams.rigHeadPosition, headParams.rigHeadOrientation); - headParams.headEnabled = true; - } else { - // even though full head IK is disabled, the rig still needs the head orientation to rotate the head up and down in desktop mode. - // preMult 180 is necessary to convert from avatar to rig coordinates. - // postMult 180 is necessary to convert head from -z forward to z forward. - headParams.rigHeadOrientation = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180; - headParams.headEnabled = false; - } + // even though full head IK is disabled, the rig still needs the head orientation to rotate the head up and + // down in desktop mode. + // preMult 180 is necessary to convert from avatar to rig coordinates. + // postMult 180 is necessary to convert head from -z forward to z forward. + headParams.rigHeadOrientation = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180; + headParams.headEnabled = false; } auto avatarHipsPose = myAvatar->getHipsControllerPoseInAvatarFrame(); diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index ff3e614077..4b7873c86d 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -210,10 +210,8 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { _buttonPressedMap.clear(); } -bool OculusControllerManager::isHeadController() const { - // this plugin is a head controller if the HMD is mounted. +bool OculusControllerManager::isHeadControllerMounted() const { ovrSessionStatus status; - bool success = OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)); if (!success) { return false; @@ -224,12 +222,12 @@ bool OculusControllerManager::isHeadController() const { void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { _buttonPressedMap.clear(); - _poseStateMap.erase(controller::HEAD); + // _poseStateMap.erase(controller::HEAD); - if (!_parent.isHeadController()) { - // if the HMD isn't on someone's head, don't take input from the controllers - return; - } + // if (!_parent.isHeadControllerMounted()) { + // // if the HMD isn't on someone's head, don't take input from the controllers + // return; + // } int numTrackedControllers = 0; quint64 currentTime = usecTimestampNow(); @@ -261,7 +259,11 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]); }); - handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose); + if (_parent.isHeadControllerMounted()) { + handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose); + } else { + _poseStateMap[controller::HEAD].valid = false; + } using namespace controller; // Axes diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 54237645eb..69187f94a6 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -28,7 +28,8 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return _touch != nullptr; } - bool isHeadController() const override; + bool isHeadController() const override { return true; } + bool isHeadControllerMounted() const; QStringList getSubdeviceNames() override; bool activate() override; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index abff0770a7..b5fa7cadad 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -164,8 +164,8 @@ void ViveControllerManager::deactivate() { _registeredWithInputMapper = false; } -bool ViveControllerManager::isHeadController() const { - if (_inputDevice && _inputDevice->isHeadController()) { +bool ViveControllerManager::isHeadControllerMounted() const { + if (_inputDevice && _inputDevice->isHeadControllerMounted()) { return true; } vr::EDeviceActivityLevel activityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index d03818ea34..35ad2df359 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -41,7 +41,8 @@ public: const QString getName() const override { return NAME; } bool isHandController() const override { return true; } - bool isHeadController() const override; + bool isHeadController() const override { return true; } + bool isHeadControllerMounted() const; bool activate() override; void deactivate() override; @@ -55,7 +56,7 @@ private: class InputDevice : public controller::InputDevice { public: InputDevice(vr::IVRSystem*& system); - bool isHeadController() const { return _overrideHead; } + bool isHeadControllerMounted() const { return _overrideHead; } private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; From 3359a0a794f276efd12286c21ea67cdaca8ca593 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Jun 2017 15:29:20 -0700 Subject: [PATCH 14/21] work on fixing some head to eye offsets. MyHead::getHmdOrientation to MyHead::getHeadOrientation --- interface/src/Application.cpp | 8 +-- interface/src/avatar/MyAvatar.cpp | 50 ++++++++++--------- interface/src/avatar/MyHead.cpp | 17 ++++--- interface/src/avatar/MyHead.h | 2 +- .../oculus/src/OculusControllerManager.cpp | 27 ++++++---- 5 files changed, 57 insertions(+), 47 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9245c58760..55666d521e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2091,7 +2091,7 @@ void Application::paintGL() { _myCamera.setOrientation(glm::quat_cast(camMat)); } else { _myCamera.setPosition(myAvatar->getDefaultEyePosition()); - _myCamera.setOrientation(myAvatar->getMyHead()->getCameraOrientation()); + _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); } } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { if (isHMDMode()) { @@ -4047,9 +4047,9 @@ void Application::updateMyAvatarLookAtPosition() { } else { // I am not looking at anyone else, so just look forward if (isHMD) { - glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * - myAvatar->getHeadControllerPoseInSensorFrame().getMatrix() * Matrices::Y_180; - lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE)); + glm::mat4 worldHeadMat = myAvatar->getSensorToWorldMatrix() * + myAvatar->getHeadControllerPoseInSensorFrame().getMatrix(); + lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7e998b11c0..826a6a00ac 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -644,9 +644,12 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { _hmdSensorPosition = newHmdSensorPosition; _hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix); + // _headControllerFacing = getFacingDir2D(_hmdSensorOrientation); auto headPose = _headControllerPoseInSensorFrameCache.get(); if (headPose.isValid()) { _headControllerFacing = getFacingDir2D(headPose.rotation); + } else { + _headControllerFacing = glm::vec2(1.0f, 0.0f); } } @@ -1481,12 +1484,12 @@ void MyAvatar::updateMotors() { if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { if (_characterController.getState() == CharacterController::State::Hover || _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { - motorRotation = getMyHead()->getCameraOrientation(); + motorRotation = getMyHead()->getHeadOrientation(); } else { // non-hovering = walking: follow camera twist about vertical but not lift // so we decompose camera's rotation and store the twist part in motorRotation glm::quat liftRotation; - swingTwistDecomposition(getMyHead()->getCameraOrientation(), _worldUpDirection, liftRotation, motorRotation); + swingTwistDecomposition(getMyHead()->getHeadOrientation(), _worldUpDirection, liftRotation, motorRotation); } const float DEFAULT_MOTOR_TIMESCALE = 0.2f; const float INVALID_MOTOR_TIMESCALE = 1.0e6f; @@ -1500,7 +1503,7 @@ void MyAvatar::updateMotors() { } if (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) { if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) { - motorRotation = getMyHead()->getCameraOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); + motorRotation = getMyHead()->getHeadOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); } else if (_scriptedMotorFrame == SCRIPTED_MOTOR_AVATAR_FRAME) { motorRotation = getOrientation() * glm::angleAxis(PI, Vectors::UNIT_Y); } else { @@ -1849,7 +1852,7 @@ void MyAvatar::updateOrientation(float deltaTime) { if (getCharacterController()->getState() == CharacterController::State::Hover) { // This is the direction the user desires to fly in. - glm::vec3 desiredFacing = getMyHead()->getCameraOrientation() * Vectors::UNIT_Z; + 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. @@ -1888,8 +1891,9 @@ void MyAvatar::updateOrientation(float deltaTime) { getHead()->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime); - if (getHeadControllerPoseInAvatarFrame().isValid()) { - glm::quat localOrientation = getHeadControllerPoseInAvatarFrame().rotation; + auto headPose = getHeadControllerPoseInAvatarFrame(); + if (headPose.isValid()) { + glm::quat localOrientation = headPose.rotation; // these angles will be in radians // ... so they need to be converted to degrees before we do math... glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; @@ -2003,11 +2007,14 @@ void MyAvatar::updatePosition(float deltaTime) { } // 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)) { + 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()->getCameraOrientation() * Vectors::UNIT_Z); - } else if (_hoverReferenceCameraFacingIsCaptured && (fabs(getDriveKey(TRANSLATE_Z)) <= 0.1f && fabs(getDriveKey(TRANSLATE_X)) <= 0.1f)) { + _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; } } @@ -2332,35 +2339,32 @@ glm::quat MyAvatar::getWorldBodyOrientation() const { // old school meat hook style glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { + // HMD is in sensor space. const glm::vec3 headPosition = getHeadControllerPoseInSensorFrame().translation; const glm::quat headOrientation = getHeadControllerPoseInSensorFrame().rotation * Quaternions::Y_180; const glm::quat headOrientationYawOnly = cancelOutRollAndPitch(headOrientation); const Rig& rig = _skeletonModel->getRig(); - int rightEyeIndex = rig.indexOfJoint("RightEye"); - int leftEyeIndex = rig.indexOfJoint("LeftEye"); + int headIndex = rig.indexOfJoint("Head"); int neckIndex = rig.indexOfJoint("Neck"); int hipsIndex = rig.indexOfJoint("Hips"); - glm::vec3 rigMiddleEyePos = DEFAULT_AVATAR_MIDDLE_EYE_POS; - if (leftEyeIndex >= 0 && rightEyeIndex >= 0) { - rigMiddleEyePos = (rig.getAbsoluteDefaultPose(leftEyeIndex).trans() + rig.getAbsoluteDefaultPose(rightEyeIndex).trans()) / 2.0f; - } + glm::vec3 rigHeadPos = headIndex != -1 ? rig.getAbsoluteDefaultPose(headIndex).trans() : DEFAULT_AVATAR_HEAD_POS; glm::vec3 rigNeckPos = neckIndex != -1 ? rig.getAbsoluteDefaultPose(neckIndex).trans() : DEFAULT_AVATAR_NECK_POS; glm::vec3 rigHipsPos = hipsIndex != -1 ? rig.getAbsoluteDefaultPose(hipsIndex).trans() : DEFAULT_AVATAR_HIPS_POS; - glm::vec3 localEyes = (rigMiddleEyePos - rigHipsPos); + glm::vec3 localHead = (rigHeadPos - rigHipsPos); glm::vec3 localNeck = (rigNeckPos - rigHipsPos); // apply simplistic head/neck model // figure out where the avatar body should be by applying offsets from the avatar's neck & head joints. - // eyeToNeck offset is relative to head's full orientation, - // while neckToRoot offset is only relative to head's yaw. - // Y_180 is necessary because rig is z forward and headOrientation is -z forward - glm::vec3 eyeToNeck = headOrientation * Quaternions::Y_180 * (localNeck - localEyes); - glm::vec3 neckToRoot = headOrientationYawOnly * Quaternions::Y_180 * -localNeck; - glm::vec3 bodyPos = headPosition + eyeToNeck + neckToRoot; + // eyeToNeck offset is relative full HMD orientation. + // while neckToRoot offset is only relative to HMDs yaw. + // 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; return createMatFromQuatAndPos(headOrientationYawOnly, bodyPos); } @@ -2478,7 +2482,7 @@ bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, co } else { const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); - return glm::dot(myAvatar.getHeadControllerFacingMovingAverage() * -1.0f, bodyFacing) < FOLLOW_ROTATION_THRESHOLD; + return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; } } diff --git a/interface/src/avatar/MyHead.cpp b/interface/src/avatar/MyHead.cpp index f02aefec5b..9f2d080cd6 100644 --- a/interface/src/avatar/MyHead.cpp +++ b/interface/src/avatar/MyHead.cpp @@ -26,19 +26,20 @@ using namespace std; MyHead::MyHead(MyAvatar* owningAvatar) : Head(owningAvatar) { } -glm::quat MyHead::getCameraOrientation() const { - // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so +glm::quat MyHead::getHeadOrientation() const { + // NOTE: Head::getHeadOrientation() is not used for orienting the camera "view" while in Oculus mode, so // you may wonder why this code is here. This method will be called while in Oculus mode to determine how // to change the driving direction while in Oculus mode. It is used to support driving toward where you're // head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not // always the same. - if (qApp->isHMDMode()) { - MyAvatar* myAvatar = static_cast(_owningAvatar); - return glm::quat_cast(myAvatar->getSensorToWorldMatrix()) * myAvatar->getHMDSensorOrientation(); - } else { - Avatar* owningAvatar = static_cast(_owningAvatar); - return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f))); + + MyAvatar* myAvatar = static_cast(_owningAvatar); + auto headPose = myAvatar->getHeadControllerPoseInWorldFrame(); + if (headPose.isValid()) { + return headPose.rotation * Quaternions::Y_180; } + + return myAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f))); } void MyHead::simulate(float deltaTime) { diff --git a/interface/src/avatar/MyHead.h b/interface/src/avatar/MyHead.h index 097415153c..c999311b80 100644 --- a/interface/src/avatar/MyHead.h +++ b/interface/src/avatar/MyHead.h @@ -18,7 +18,7 @@ public: explicit MyHead(MyAvatar* owningAvatar); /// \return orientationBody * orientationBasePitch - glm::quat getCameraOrientation() const; + glm::quat getHeadOrientation() const; void simulate(float deltaTime) override; private: diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 4b7873c86d..dee9f1082e 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -326,19 +326,24 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const ovrPoseStatef& headPose) { - auto poseId = controller::HEAD; - auto& pose = _poseStateMap[poseId]; + glm::mat4 mat = createMatFromQuatAndPos(toGlm(headPose.ThePose.Orientation), + toGlm(headPose.ThePose.Position)); + + //perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z + glm::mat4 matYFlip = mat * Matrices::Y_180; + controller::Pose pose(extractTranslation(matYFlip), + glmExtractRotation(matYFlip), + toGlm(headPose.LinearVelocity), // XXX * matYFlip ? + toGlm(headPose.AngularVelocity)); + + glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) * + inputCalibrationData.defaultHeadMat; + + controller::Pose hmdHeadPose = pose.transform(sensorToAvatar); - static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y); - pose.translation = toGlm(headPose.ThePose.Position); - pose.rotation = toGlm(headPose.ThePose.Orientation) * yFlip; - pose.angularVelocity = toGlm(headPose.AngularVelocity); - pose.velocity = toGlm(headPose.LinearVelocity); pose.valid = true; - - // transform into avatar frame - glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; - pose = pose.transform(controllerToAvatar); + _poseStateMap[controller::HEAD] = hmdHeadPose.postTransform(defaultHeadOffset); } void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, From 9654e007a6833a6e0ef1bc74982fe41b5640385b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Jun 2017 16:31:08 -0700 Subject: [PATCH 15/21] most input plugins are not head or hand controllers --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.h | 3 --- libraries/input-plugins/src/input-plugins/TouchscreenDevice.h | 3 --- libraries/plugins/src/plugins/InputPlugin.h | 4 ++-- plugins/hifiNeuron/src/NeuronPlugin.h | 3 --- plugins/hifiSdl2/src/SDL2Manager.h | 2 -- plugins/hifiSixense/src/SixenseManager.h | 3 +-- 6 files changed, 3 insertions(+), 15 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index a0e216c904..b94acb8b71 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -70,9 +70,6 @@ public: bool isSupported() const override { return true; } const QString getName() const override { return NAME; } - bool isHandController() const override { return false; } - bool isHeadController() const override { return false; } - void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h index 926f9dbdca..02dcbe4664 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.h @@ -39,9 +39,6 @@ public: virtual bool isSupported() const override; virtual const QString getName() const override { return NAME; } - bool isHandController() const override { return false; } - bool isHeadController() const override { return false; } - virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; diff --git a/libraries/plugins/src/plugins/InputPlugin.h b/libraries/plugins/src/plugins/InputPlugin.h index 0519ed776d..2a4737b5a1 100644 --- a/libraries/plugins/src/plugins/InputPlugin.h +++ b/libraries/plugins/src/plugins/InputPlugin.h @@ -24,7 +24,7 @@ public: // Some input plugins are comprised of multiple subdevices (SDL2, for instance). // If an input plugin is only a single device, it will only return it's primary name. virtual QStringList getSubdeviceNames() { return { getName() }; }; - virtual bool isHandController() const = 0; - virtual bool isHeadController() const = 0; + virtual bool isHandController() const { return false; } + virtual bool isHeadController() const { return false; } }; diff --git a/plugins/hifiNeuron/src/NeuronPlugin.h b/plugins/hifiNeuron/src/NeuronPlugin.h index 41c2322465..34d084160f 100644 --- a/plugins/hifiNeuron/src/NeuronPlugin.h +++ b/plugins/hifiNeuron/src/NeuronPlugin.h @@ -25,9 +25,6 @@ class NeuronPlugin : public InputPlugin { public: friend void FrameDataReceivedCallback(void* context, void* sender, _BvhDataHeaderEx* header, float* data); - bool isHandController() const override { return false; } - bool isHeadController() const override { return false; } - // Plugin functions virtual void init() override; virtual bool isSupported() const override; diff --git a/plugins/hifiSdl2/src/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h index d2bbe8265e..9cb4d268c0 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -27,8 +27,6 @@ public: const QString getName() const override { return NAME; } QStringList getSubdeviceNames() override; - bool isHandController() const override { return false; } - bool isHeadController() const override { return false; } void init() override; void deinit() override; diff --git a/plugins/hifiSixense/src/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h index 889f6c3bad..5b2c140868 100644 --- a/plugins/hifiSixense/src/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -33,8 +33,7 @@ public: // Sixense always seems to initialize even if the hydras are not present. Is there // a way we can properly detect whether the hydras are present? - bool isHandController() const override { return false; } - bool isHeadController() const override { return false; } + // bool isHandController() const override { return true; } virtual bool activate() override; virtual void deactivate() override; From 27669d44a7458e270abb5209599e2fa126fb4391 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Jun 2017 08:58:40 -0700 Subject: [PATCH 16/21] in deriveBodyFromHMDSensor, avoid using invalid head pose --- interface/src/avatar/MyAvatar.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 826a6a00ac..64914a7ec1 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2338,10 +2338,13 @@ glm::quat MyAvatar::getWorldBodyOrientation() const { // old school meat hook style glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { - - // HMD is in sensor space. - const glm::vec3 headPosition = getHeadControllerPoseInSensorFrame().translation; - const glm::quat headOrientation = getHeadControllerPoseInSensorFrame().rotation * Quaternions::Y_180; + glm::vec3 headPosition; + glm::quat headOrientation; + auto headPose = getHeadControllerPoseInSensorFrame(); + if (headPose.isValid()) { + headPosition = getHeadControllerPoseInSensorFrame().translation; + headOrientation = getHeadControllerPoseInSensorFrame().rotation * Quaternions::Y_180; + } const glm::quat headOrientationYawOnly = cancelOutRollAndPitch(headOrientation); const Rig& rig = _skeletonModel->getRig(); From 3ab67cf27ed459cd7f19f38c24d53acee64784ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Jun 2017 11:44:27 -0700 Subject: [PATCH 17/21] fix forward gaze in HMD while not looking at anyone --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5b9e46f549..c83ca9b2ff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4060,7 +4060,7 @@ void Application::updateMyAvatarLookAtPosition() { if (isHMD) { glm::mat4 worldHeadMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHeadControllerPoseInSensorFrame().getMatrix(); - lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, TREE_SCALE)); + lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); From 9fcc1e15b8bcbd65c8fd80f42e9c65f1f25332c1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Jun 2017 15:52:47 -0700 Subject: [PATCH 18/21] remove some cruft --- .../avatars-renderer/src/avatars-renderer/Head.cpp | 12 ------------ .../avatars-renderer/src/avatars-renderer/Head.h | 3 --- libraries/avatars/src/HeadData.h | 3 --- 3 files changed, 18 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 96ecd86ff4..b8a559027b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -304,18 +304,6 @@ glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { return rotationBetween(orientation * IDENTITY_FORWARD, lookAtDelta + glm::length(lookAtDelta) * _saccade) * orientation; } -void Head::setFinalPitch(float finalPitch) { - _deltaPitch = glm::clamp(finalPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH) - _basePitch; -} - -void Head::setFinalYaw(float finalYaw) { - _deltaYaw = glm::clamp(finalYaw, MIN_HEAD_YAW, MAX_HEAD_YAW) - _baseYaw; -} - -void Head::setFinalRoll(float finalRoll) { - _deltaRoll = glm::clamp(finalRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL) - _baseRoll; -} - float Head::getFinalYaw() const { return glm::clamp(_baseYaw + _deltaYaw, MIN_HEAD_YAW, MAX_HEAD_YAW); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.h b/libraries/avatars-renderer/src/avatars-renderer/Head.h index c5902285b9..e3c8d7d2b5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.h @@ -71,9 +71,6 @@ public: void setDeltaRoll(float roll) { _deltaRoll = roll; } float getDeltaRoll() const { return _deltaRoll; } - virtual void setFinalYaw(float finalYaw) override; - virtual void setFinalPitch(float finalPitch) override; - virtual void setFinalRoll(float finalRoll) override; virtual float getFinalPitch() const override; virtual float getFinalYaw() const override; virtual float getFinalRoll() const override; diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 0bb38c1dad..c15714bd73 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -45,9 +45,6 @@ public: float getBaseRoll() const { return _baseRoll; } void setBaseRoll(float roll) { _baseRoll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } - virtual void setFinalYaw(float finalYaw) { _baseYaw = finalYaw; } - virtual void setFinalPitch(float finalPitch) { _basePitch = finalPitch; } - virtual void setFinalRoll(float finalRoll) { _baseRoll = finalRoll; } virtual float getFinalYaw() const { return _baseYaw; } virtual float getFinalPitch() const { return _basePitch; } virtual float getFinalRoll() const { return _baseRoll; } From 7a276f027fb7e2c957b8b3caf188cb5275606eb3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 5 Jun 2017 15:53:01 -0700 Subject: [PATCH 19/21] fix orientation used for 3d audio --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 64914a7ec1..158e55ab5c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1893,7 +1893,7 @@ void MyAvatar::updateOrientation(float deltaTime) { auto headPose = getHeadControllerPoseInAvatarFrame(); if (headPose.isValid()) { - glm::quat localOrientation = headPose.rotation; + glm::quat localOrientation = headPose.rotation * Quaternions::Y_180; // these angles will be in radians // ... so they need to be converted to degrees before we do math... glm::vec3 euler = glm::eulerAngles(localOrientation) * DEGREES_PER_RADIAN; From ad1ee973243fe55389044226a51dac32f9ac071f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 6 Jun 2017 09:50:40 -0700 Subject: [PATCH 20/21] remove cruft --- plugins/oculus/src/OculusControllerManager.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index dee9f1082e..6f7be26554 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -222,12 +222,6 @@ bool OculusControllerManager::isHeadControllerMounted() const { void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { _buttonPressedMap.clear(); - // _poseStateMap.erase(controller::HEAD); - - // if (!_parent.isHeadControllerMounted()) { - // // if the HMD isn't on someone's head, don't take input from the controllers - // return; - // } int numTrackedControllers = 0; quint64 currentTime = usecTimestampNow(); From 69520ff3db0f7b37bf34710f68b174e8d4f2fe23 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 7 Jun 2017 10:28:02 -0700 Subject: [PATCH 21/21] pull from upstream, code review --- interface/src/avatar/MyAvatar.cpp | 11 +---------- interface/src/avatar/MyAvatar.h | 4 ---- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 158e55ab5c..9e01d59f4f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -417,7 +417,7 @@ void MyAvatar::update(float deltaTime) { } #ifdef DEBUG_DRAW_HMD_MOVING_AVERAGE - glm::vec3 p = transformPoint(getSensorToWorldMatrix(), getHeadControllerPoseInAvatarFrame() + + glm::vec3 p = transformPoint(getSensorToWorldMatrix(), getHeadControllerPoseInAvatarFrame() * glm::vec3(_headControllerFacingMovingAverage.x, 0.0f, _headControllerFacingMovingAverage.y)); DebugDraw::getInstance().addMarker("facing-avg", getOrientation(), p, glm::vec4(1.0f)); p = transformPoint(getSensorToWorldMatrix(), getHMDSensorPosition() + @@ -644,7 +644,6 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) { _hmdSensorPosition = newHmdSensorPosition; _hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix); - // _headControllerFacing = getFacingDir2D(_hmdSensorOrientation); auto headPose = _headControllerPoseInSensorFrameCache.get(); if (headPose.isValid()) { _headControllerFacing = getFacingDir2D(headPose.rotation); @@ -2328,14 +2327,6 @@ bool MyAvatar::isDriveKeyDisabled(DriveKeys key) const { } } -glm::vec3 MyAvatar::getWorldBodyPosition() const { - return transformPoint(_sensorToWorldMatrix, extractTranslation(_bodySensorMatrix)); -} - -glm::quat MyAvatar::getWorldBodyOrientation() const { - return glm::quat_cast(_sensorToWorldMatrix * _bodySensorMatrix); -} - // old school meat hook style glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { glm::vec3 headPosition; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index babe47a2bc..f828a48636 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -564,10 +564,6 @@ signals: private: - glm::vec3 getWorldBodyPosition() const; - glm::quat getWorldBodyOrientation() const; - - virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail) override; void simulate(float deltaTime);