From 01c740f415f08049bd58b60862c716f0574d78a5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 17 Jul 2015 17:19:49 -0700 Subject: [PATCH] cleaning up plugin architecture, fixed hand controllers --- interface/src/Application.cpp | 77 +++-- interface/src/Application.h | 2 +- interface/src/InputPlugins.h | 2 + interface/src/Menu.cpp | 13 +- interface/src/ui/PreferencesDialog.cpp | 3 +- .../src/input-plugins/InputDevice.cpp | 2 + .../src/input-plugins/InputDevice.h | 9 +- .../src/input-plugins/InputPlugin.h | 2 +- .../src/input-plugins/Joystick.cpp | 2 +- .../src/input-plugins/Joystick.h | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 2 +- .../src/input-plugins/KeyboardMouseDevice.h | 4 +- .../src/input-plugins/SDL2Manager.cpp | 4 +- .../src/input-plugins/SDL2Manager.h | 2 +- .../src/input-plugins/SixenseManager.cpp | 304 ++++++------------ .../src/input-plugins/SixenseManager.h | 19 +- .../src/input-plugins/UserInputMapper.cpp | 4 +- .../input-plugins/ViveControllerManager.cpp | 9 +- .../src/input-plugins/ViveControllerManager.h | 4 +- .../plugins/src/plugins/PluginContainer.h | 1 + 20 files changed, 197 insertions(+), 270 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e97b0c7585..e040833e01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -76,7 +76,6 @@ #include #include #include // this should probably be removed -#include // this definitely should be removed #include #include #include @@ -2130,7 +2129,7 @@ void Application::setEnableVRMode(bool enableVRMode) { #endif void Application::setLowVelocityFilter(bool lowVelocityFilter) { - SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter); + InputDevice::setLowVelocityFilter(lowVelocityFilter); } bool Application::mouseOnScreen() const { @@ -2364,18 +2363,7 @@ void Application::init() { DependencyManager::get()->loadSettings(addressLookupString); qCDebug(interfaceapp) << "Loaded settings"; - -#ifdef __APPLE__ - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) { - // on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash - // if hydra support is temporarily not required - SixenseManager::getInstance().toggleSixense(true); - } -#else - // setup sixense - SixenseManager::getInstance().toggleSixense(true); -#endif - + Leapmotion::init(); RealSense::init(); @@ -2683,12 +2671,17 @@ void Application::update(float deltaTime) { userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix()); userInputMapper->update(deltaTime); + // This needs to go after userInputMapper->update() because of the keyboard + bool jointsCaptured = false; auto inputPlugins = getInputPlugins(); foreach(auto inputPlugin, inputPlugins) { QString name = inputPlugin->getName(); QAction* action = Menu::getInstance()->getActionForOption(name); if (action->isChecked()) { - inputPlugin->pluginUpdate(deltaTime); // add flag to prevent multiple devices from modifying joints + inputPlugin->pluginUpdate(deltaTime, jointsCaptured); + if (inputPlugin->isJointController()) { + jointsCaptured = true; + } } } @@ -2716,8 +2709,8 @@ void Application::update(float deltaTime) { UserInputMapper::PoseValue leftHand = userInputMapper->getPoseState(UserInputMapper::LEFT_HAND); UserInputMapper::PoseValue rightHand = userInputMapper->getPoseState(UserInputMapper::RIGHT_HAND); Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); - setPalmData(hand, leftHand, LEFT_HAND_INDEX); - setPalmData(hand, rightHand, RIGHT_HAND_INDEX); + setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX); + setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX); if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput)) { emulateMouse(hand, userInputMapper->getActionState(UserInputMapper::LEFT_HAND_CLICK), userInputMapper->getActionState(UserInputMapper::SHIFT), LEFT_HAND_INDEX); @@ -2869,7 +2862,7 @@ void Application::update(float deltaTime) { _myAvatar->updateSensorToWorldMatrix(); } -void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int index) { +void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) { PalmData* palm; bool foundHand = false; for (size_t j = 0; j < hand->getNumPalms(); j++) { @@ -2887,12 +2880,54 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int i } palm->setActive(pose.isValid()); + + glm::vec3 position = pose.getTranslation(); + glm::quat rotation = pose.getRotation(); + + // TODO: velocity and tip position information should be converted to model space + // Compute current velocity from position change + glm::vec3 rawVelocity; + if (deltaTime > 0.0f) { + rawVelocity = (position - palm->getRawPosition()) / deltaTime; + } else { + rawVelocity = glm::vec3(0.0f); + } + palm->setRawVelocity(rawVelocity); // meters/sec - // TODO: velocity filters, tip velocities, etc. - // see SixenseManager + // Angular Velocity of Palm + glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); + glm::vec3 angularVelocity(0.0f); + float rotationAngle = glm::angle(deltaRotation); + if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { + angularVelocity = glm::normalize(glm::axis(deltaRotation)); + angularVelocity *= (rotationAngle / deltaTime); + palm->setRawAngularVelocity(angularVelocity); + } else { + palm->setRawAngularVelocity(glm::vec3(0.0f)); + } + + if (InputDevice::getLowVelocityFilter()) { + // Use a velocity sensitive filter to damp small motions and preserve large ones with + // no latency. + float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); + position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); + rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); + } + + // Store the one fingertip in the palm structure so we can track velocity + const float FINGER_LENGTH = 0.3f; // meters + const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); + const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; + glm::vec3 oldTipPosition = palm->getTipRawPosition(); + if (deltaTime > 0.0f) { + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); + } else { + palm->setTipVelocity(glm::vec3(0.0f)); + } + palm->setTipPosition(newTipPosition); // transform from sensor space, to world space, to avatar model space. - glm::mat4 poseMat = createMatFromQuatAndPos(pose.getRotation(), pose.getTranslation()); + glm::mat4 poseMat = createMatFromQuatAndPos(rotation, position); glm::mat4 sensorToWorldMat = _myAvatar->getSensorToWorldMatrix(); glm::mat4 modelMat = createMatFromQuatAndPos(_myAvatar->getOrientation(), _myAvatar->getPosition()); glm::mat4 objectPose = glm::inverse(modelMat) * sensorToWorldMat * poseMat; diff --git a/interface/src/Application.h b/interface/src/Application.h index 1ff56b37ed..46d1ecf39e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -475,7 +475,7 @@ private: void update(float deltaTime); - void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int index); + void setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index); void emulateMouse(Hand* hand, float click, float shift, int index); // Various helper functions called during update() diff --git a/interface/src/InputPlugins.h b/interface/src/InputPlugins.h index 14ed808df4..ce1beeb708 100644 --- a/interface/src/InputPlugins.h +++ b/interface/src/InputPlugins.h @@ -7,6 +7,8 @@ // #pragma once +#include + class InputPlugin; #include diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index bb1f6e6528..9c89db4353 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -464,26 +464,17 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandMouseInput, 0, true); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandLasers, 0, false); + addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true, + qApp, SLOT(setLowVelocityFilter(bool))); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false); MenuWrapper* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense"); - addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, - MenuOption::SixenseEnabled, - 0, false, - &SixenseManager::getInstance(), - SLOT(toggleSixense(bool))); addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::FilterSixense, 0, true, &SixenseManager::getInstance(), SLOT(setFilter(bool))); - addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, - MenuOption::LowVelocityFilter, - 0, - true, - qApp, - SLOT(setLowVelocityFilter(bool))); MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8cafc152f4..a1c0a0a512 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -181,8 +181,9 @@ void PreferencesDialog::loadPreferences() { ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationCompositor().getHmdUIAngularSize()); #endif - SixenseManager& sixense = SixenseManager::getInstance(); ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed()); + + SixenseManager& sixense = SixenseManager::getInstance(); ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); // LOD items diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.cpp b/libraries/input-plugins/src/input-plugins/InputDevice.cpp index 8f0f2449ca..057fb7ddf1 100644 --- a/libraries/input-plugins/src/input-plugins/InputDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/InputDevice.cpp @@ -7,6 +7,8 @@ // #include "InputDevice.h" +bool InputDevice::_lowVelocityFilter = false; + const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.h b/libraries/input-plugins/src/input-plugins/InputDevice.h index 4776766312..17f28c1bd8 100644 --- a/libraries/input-plugins/src/input-plugins/InputDevice.h +++ b/libraries/input-plugins/src/input-plugins/InputDevice.h @@ -34,7 +34,7 @@ public: // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas - virtual void update(float deltaTime) = 0; + virtual void update(float deltaTime, bool jointsCaptured) = 0; virtual void focusOutEvent() = 0; @@ -44,6 +44,11 @@ public: static float getReticleMoveSpeed() { return reticleMoveSpeed; } static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; } + static bool getLowVelocityFilter() { return _lowVelocityFilter; }; + +public slots: + static void setLowVelocityFilter(bool newLowVelocityFilter) { _lowVelocityFilter = newLowVelocityFilter; }; + protected: int _deviceID = 0; @@ -53,6 +58,8 @@ protected: AxisStateMap _axisStateMap; PoseStateMap _poseStateMap; + static bool _lowVelocityFilter; + private: static float reticleMoveSpeed; }; \ No newline at end of file diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.h b/libraries/input-plugins/src/input-plugins/InputPlugin.h index 776ece8b8a..d12ba4652f 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.h +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.h @@ -15,6 +15,6 @@ public: virtual void pluginFocusOutEvent() = 0; - virtual void pluginUpdate(float deltaTime) = 0; + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) = 0; }; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index a652bee227..a29b74ac40 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -41,7 +41,7 @@ void Joystick::closeJoystick() { #endif } -void Joystick::update(float deltaTime) { +void Joystick::update(float deltaTime, bool jointsCaptured) { for (auto axisState : _axisStateMap) { if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { _axisStateMap[axisState.first] = 0.0f; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index f8f98ca661..d78aef34d6 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -49,7 +49,7 @@ public: // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime) override; + virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; Joystick() : InputDevice("Joystick") {} diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 66751cc542..a6edfc392d 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -13,7 +13,7 @@ const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse"; -void KeyboardMouseDevice::update(float deltaTime) { +void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) { _axisStateMap.clear(); // For touch event, we need to check that the last event is not too long ago diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 727920630b..85f9c3679e 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -65,12 +65,12 @@ public: virtual void deactivate() override {}; virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime) override; + virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; void keyPressEvent(QKeyEvent* event); diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp index c5e56457b3..e8cae6be54 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp @@ -89,12 +89,12 @@ void SDL2Manager::pluginFocusOutEvent() { #endif } -void SDL2Manager::pluginUpdate(float deltaTime) { +void SDL2Manager::pluginUpdate(float deltaTime, bool jointsCaptured) { #ifdef HAVE_SDL2 if (_isInitialized) { auto userInputMapper = DependencyManager::get(); for (auto joystick : _openJoysticks) { - joystick->update(deltaTime); + joystick->update(deltaTime, jointsCaptured); } PerformanceTimer perfTimer("SDL2Manager::update"); diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/libraries/input-plugins/src/input-plugins/SDL2Manager.h index 123f8dc910..62b3f60d47 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.h @@ -38,7 +38,7 @@ public: virtual void deactivate() override {}; virtual void pluginFocusOutEvent() override; - virtual void pluginUpdate(float deltaTime) override; + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override; signals: void joystickAdded(Joystick* joystick); diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index d762d06558..8a535d636f 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -61,8 +61,6 @@ SixenseManager::SixenseManager() : #if defined(HAVE_SIXENSE) && defined(__APPLE__) _sixenseLibrary(NULL), #endif - _isInitialized(false), - _isEnabled(true), _hydrasConnected(false) { @@ -76,59 +74,50 @@ bool SixenseManager::isSupported() const { #endif } -void SixenseManager::init() { +void SixenseManager::activate(PluginContainer* container) { #ifdef HAVE_SIXENSE - - if (!_isInitialized) { - _lowVelocityFilter = false; - _calibrationState = CALIBRATION_STATE_IDLE; - // By default we assume the _neckBase (in orb frame) is as high above the orb - // as the "torso" is below it. - _neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z); + _calibrationState = CALIBRATION_STATE_IDLE; + // By default we assume the _neckBase (in orb frame) is as high above the orb + // as the "torso" is below it. + _neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z); #ifdef __APPLE__ - if (!_sixenseLibrary) { + if (!_sixenseLibrary) { #ifdef SIXENSE_LIB_FILENAME - _sixenseLibrary = new QLibrary(SIXENSE_LIB_FILENAME); + _sixenseLibrary = new QLibrary(SIXENSE_LIB_FILENAME); #else - const QString SIXENSE_LIBRARY_NAME = "libsixense_x64"; - QString frameworkSixenseLibrary = QCoreApplication::applicationDirPath() + "/../Frameworks/" - + SIXENSE_LIBRARY_NAME; + const QString SIXENSE_LIBRARY_NAME = "libsixense_x64"; + QString frameworkSixenseLibrary = QCoreApplication::applicationDirPath() + "/../Frameworks/" + + SIXENSE_LIBRARY_NAME; - _sixenseLibrary = new QLibrary(frameworkSixenseLibrary); + _sixenseLibrary = new QLibrary(frameworkSixenseLibrary); #endif - } - - if (_sixenseLibrary->load()){ - qCDebug(interfaceapp) << "Loaded sixense library for hydra support -" << _sixenseLibrary->fileName(); - } else { - qCDebug(interfaceapp) << "Sixense library at" << _sixenseLibrary->fileName() << "failed to load." - << "Continuing without hydra support."; - return; - } - - SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); -#endif - sixenseInit(); - - _isInitialized = true; } + if (_sixenseLibrary->load()){ + qCDebug(interfaceapp) << "Loaded sixense library for hydra support -" << _sixenseLibrary->fileName(); + } else { + qCDebug(interfaceapp) << "Sixense library at" << _sixenseLibrary->fileName() << "failed to load." + << "Continuing without hydra support."; + return; + } + + SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); +#endif + sixenseInit(); #endif } void SixenseManager::deinit() { #ifdef HAVE_SIXENSE_ - if (_isInitialized) { #ifdef __APPLE__ - SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit"); + SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit"); #endif - sixenseExit(); - } + sixenseExit(); #ifdef __APPLE__ delete _sixenseLibrary; @@ -139,141 +128,101 @@ void SixenseManager::deinit() { void SixenseManager::setFilter(bool filter) { #ifdef HAVE_SIXENSE - - if (_isInitialized) { #ifdef __APPLE__ - SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled"); + SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled"); #endif - - if (filter) { - sixenseSetFilterEnabled(1); - } else { - sixenseSetFilterEnabled(0); - } - } - + int newFilter = filter ? 1 : 0; + sixenseSetFilterEnabled(newFilter); #endif } -void SixenseManager::update(float deltaTime) { +void SixenseManager::update(float deltaTime, bool jointsCaptured) { #ifdef HAVE_SIXENSE - //Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); - if (_isInitialized && _isEnabled) { - _buttonPressedMap.clear(); + _buttonPressedMap.clear(); #ifdef __APPLE__ - SixenseBaseFunction sixenseGetNumActiveControllers = - (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers"); + SixenseBaseFunction sixenseGetNumActiveControllers = + (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers"); #endif - auto userInputMapper = DependencyManager::get(); + auto userInputMapper = DependencyManager::get(); - if (sixenseGetNumActiveControllers() == 0) { - _hydrasConnected = false; - if (_deviceID != 0) { - userInputMapper->removeDevice(_deviceID); - _deviceID = 0; + if (sixenseGetNumActiveControllers() == 0) { + _hydrasConnected = false; + if (_deviceID != 0) { + userInputMapper->removeDevice(_deviceID); + _deviceID = 0; + _poseStateMap.clear(); + } + return; + } + + PerformanceTimer perfTimer("sixense"); + if (!_hydrasConnected) { + _hydrasConnected = true; + registerToUserInputMapper(*userInputMapper); + assignDefaultInputMapping(*userInputMapper); + UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); + } + +#ifdef __APPLE__ + SixenseBaseFunction sixenseGetMaxControllers = + (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers"); +#endif + + int maxControllers = sixenseGetMaxControllers(); + + // we only support two controllers + sixenseControllerData controllers[2]; + +#ifdef __APPLE__ + SixenseTakeIntFunction sixenseIsControllerEnabled = + (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled"); + + SixenseTakeIntAndSixenseControllerData sixenseGetNewestData = + (SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData"); +#endif + + int numActiveControllers = 0; + for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { + if (!sixenseIsControllerEnabled(i)) { + continue; + } + sixenseControllerData* data = controllers + numActiveControllers; + ++numActiveControllers; + sixenseGetNewestData(i, data); + + // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. + glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); + position *= METERS_PER_MILLIMETER; + + // Check to see if this hand/controller is on the base + const float CONTROLLER_AT_BASE_DISTANCE = 0.075f; + if (glm::length(position) >= CONTROLLER_AT_BASE_DISTANCE) { + handleButtonEvent(data->buttons, numActiveControllers - 1); + handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1); + + // Rotation of Palm + glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); + rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation; + + if (!jointsCaptured) { + handlePoseEvent(position, rotation, numActiveControllers - 1); + } else { _poseStateMap.clear(); } - return; + } else { + _poseStateMap[(numActiveControllers - 1) == 0 ? LEFT_HAND : RIGHT_HAND] = UserInputMapper::PoseValue(); } - - PerformanceTimer perfTimer("sixense"); - if (!_hydrasConnected) { - _hydrasConnected = true; - registerToUserInputMapper(*userInputMapper); - getInstance().assignDefaultInputMapping(*userInputMapper); - UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); - } - -#ifdef __APPLE__ - SixenseBaseFunction sixenseGetMaxControllers = - (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers"); -#endif - - int maxControllers = sixenseGetMaxControllers(); - - // we only support two controllers - sixenseControllerData controllers[2]; - -#ifdef __APPLE__ - SixenseTakeIntFunction sixenseIsControllerEnabled = - (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled"); - - SixenseTakeIntAndSixenseControllerData sixenseGetNewestData = - (SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData"); -#endif - int numControllersAtBase = 0; - int numActiveControllers = 0; - for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { - if (!sixenseIsControllerEnabled(i)) { - continue; - } - sixenseControllerData* data = controllers + numActiveControllers; - ++numActiveControllers; - sixenseGetNewestData(i, data); - - // Set palm position and normal based on Hydra position/orientation - -// // Either find a palm matching the sixense controller, or make a new one -// PalmData* palm; -// bool foundHand = false; -// for (size_t j = 0; j < hand->getNumPalms(); j++) { -// if (hand->getPalms()[j].getSixenseID() == data->controller_index) { -// palm = &(hand->getPalms()[j]); -// _prevPalms[numActiveControllers - 1] = palm; -// foundHand = true; -// } -// } -// if (!foundHand) { -// PalmData newPalm(hand); -// hand->getPalms().push_back(newPalm); -// palm = &(hand->getPalms()[hand->getNumPalms() - 1]); -// palm->setSixenseID(data->controller_index); -// _prevPalms[numActiveControllers - 1] = palm; -// qCDebug(interfaceapp, "Found new Sixense controller, ID %i", data->controller_index); -// } - // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. - glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); - position *= METERS_PER_MILLIMETER; - // Check to see if this hand/controller is on the base - const float CONTROLLER_AT_BASE_DISTANCE = 0.075f; - if (glm::length(position) >= CONTROLLER_AT_BASE_DISTANCE) { - handleButtonEvent(data->buttons, numActiveControllers - 1); - handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1); - - // Rotation of Palm - glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); - rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation; - - handlePoseEvent(position, rotation, numActiveControllers - 1); - } - -// // Disable the hands (and return to default pose) if both controllers are at base station -// if (foundHand) { -// palm->setActive(!_controllersAtBase); -// } else { -// palm->setActive(false); // if this isn't a Sixsense ID palm, always make it inactive -// } - // // Read controller buttons and joystick into the hand // palm->setControllerButtons(data->buttons); // palm->setTrigger(data->trigger); // palm->setJoystick(data->joystick_x, data->joystick_y); + } - //handleButtonEvent(data->buttons, numActiveControllers - 1); - //handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1); - -// // Emulate the mouse so we can use scripts -// if (Menu::getInstance()->isOptionChecked(MenuOption::HandMouseInput) && !_controllersAtBase) { -// emulateMouse(palm, numActiveControllers - 1); -// } - } - - if (numActiveControllers == 2) { - updateCalibration(controllers); - } + if (numActiveControllers == 2) { + updateCalibration(controllers); } for (auto axisState : _axisStateMap) { @@ -284,15 +233,6 @@ void SixenseManager::update(float deltaTime) { #endif // HAVE_SIXENSE } -void SixenseManager::toggleSixense(bool shouldEnable) { - if (shouldEnable && !isInitialized()) { - init(); - //setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); - //setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter)); - } - setIsEnabled(shouldEnable); -} - #ifdef HAVE_SIXENSE // the calibration sequence is: @@ -483,56 +423,10 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int neck.y = 0.0f; position = _orbRotation * (position - neck); -// // Compute current velocity from position change -// glm::vec3 rawVelocity; -// if (deltaTime > 0.0f) { -// rawVelocity = (position - palm->getRawPosition()) / deltaTime; -// } else { -// rawVelocity = glm::vec3(0.0f); -// } -// palm->setRawVelocity(rawVelocity); // meters/sec - // adjustment for hydra controllers fit into hands float sign = (index == 0) ? -1.0f : 1.0f; rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); -// // Angular Velocity of Palm -// glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); -// glm::vec3 angularVelocity(0.0f); -// float rotationAngle = glm::angle(deltaRotation); -// if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { -// angularVelocity = glm::normalize(glm::axis(deltaRotation)); -// angularVelocity *= (rotationAngle / deltaTime); -// palm->setRawAngularVelocity(angularVelocity); -// } else { -// palm->setRawAngularVelocity(glm::vec3(0.0f)); -// } - -// if (_lowVelocityFilter) { -// // Use a velocity sensitive filter to damp small motions and preserve large ones with -// // no latency. -// float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); -// position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); -// rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); -// palm->setRawPosition(position); -// palm->setRawRotation(rotation); -// } else { -// palm->setRawPosition(position); -// palm->setRawRotation(rotation); -// } - -// // Store the one fingertip in the palm structure so we can track velocity -// const float FINGER_LENGTH = 0.3f; // meters -// const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); -// const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; -// glm::vec3 oldTipPosition = palm->getTipRawPosition(); -// if (deltaTime > 0.0f) { -// palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); -// } else { -// palm->setTipVelocity(glm::vec3(0.0f)); -// } -// palm->setTipPosition(newTipPosition); - _poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation); #endif // HAVE_SIXENSE } diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index fd18b77148..37b0acd51e 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -62,24 +62,19 @@ public: virtual bool isJointController() const override { return true; } const QString& getName() const { return NAME; } - virtual void init() override; virtual void deinit() override; - virtual void activate(PluginContainer * container) override {}; - virtual void deactivate() override { _poseStateMap.clear(); }; + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override { _poseStateMap.clear(); } virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime) override; + virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; - bool isInitialized() const { return _isInitialized; } - - void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; } - bool getInvertButtons() const { return _invertButtons; } void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; } @@ -88,9 +83,7 @@ public: UserInputMapper::Input makeInput(JointChannel joint); public slots: - void toggleSixense(bool shouldEnable); void setFilter(bool filter); - void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; }; private: void handleButtonEvent(unsigned int buttons, int index); @@ -122,11 +115,7 @@ private: #endif #endif - bool _isInitialized; - bool _isEnabled; bool _hydrasConnected; - - bool _lowVelocityFilter; bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS; diff --git a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp b/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp index b8aa52a508..fc959650ba 100755 --- a/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp +++ b/libraries/input-plugins/src/input-plugins/UserInputMapper.cpp @@ -192,7 +192,9 @@ void UserInputMapper::update(float deltaTime) { break; } case ChannelType::POSE: { - _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); + if (!_poseStates[channelInput.first].isValid()) { + _poseStates[channelInput.first] = deviceProxy->getPose(inputID, currentTimestamp); + } break; } default: { diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index f81e058b1e..825eb96789 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -186,7 +186,8 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); } -void ViveControllerManager::update(float deltaTime) { +void ViveControllerManager::update(float deltaTime, bool jointsCaptured) { + _poseStateMap.clear(); // TODO: This shouldn't be necessary if (!_hmd) { return; @@ -216,8 +217,10 @@ void ViveControllerManager::update(float deltaTime) { numTrackedControllers++; const mat4& mat = _trackedDevicePoseMat4[device]; - - handlePoseEvent(mat, numTrackedControllers - 1); + + if (!jointsCaptured) { + handlePoseEvent(mat, numTrackedControllers - 1); + } // handle inputs vr::VRControllerState_t controllerState = vr::VRControllerState_t(); diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index 81f8d0d729..9ba90a5ca8 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -59,12 +59,12 @@ public: virtual void deactivate() override; virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; - virtual void update(float deltaTime) override; + virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index 937c4e99e4..a72e5d1c8d 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -1,6 +1,7 @@ #pragma once #include +#include class GlWindow;