diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca56301c8e..08a4e96da6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2202,7 +2202,7 @@ void Application::updateLeap(float deltaTime) { LeapManager::enableFakeFingers(Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand)); _myAvatar.getHand().setRaveGloveActive(Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove)); - LeapManager::nextFrame(_myAvatar); + LeapManager::nextFrame(); } void Application::updateSixense() { @@ -4100,6 +4100,7 @@ void Application::resetSensors() { } _webcam.reset(); _faceshift.reset(); + LeapManager::reset(); QCursor::setPos(_headMouseX, _headMouseY); _myAvatar.reset(); _myTransmitter.resetLevels(); diff --git a/interface/src/devices/LeapManager.cpp b/interface/src/devices/LeapManager.cpp index c3dd993c16..adb14d41a0 100644 --- a/interface/src/devices/LeapManager.cpp +++ b/interface/src/devices/LeapManager.cpp @@ -6,12 +6,16 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#include "LeapManager.h" -#include "avatar/Avatar.h" -#include #include // needed for RTLD_LAZY + #include +#include + +#include "Application.h" +#include "LeapManager.h" +#include "Menu.h" + // Uncomment the next line to use Leap-smoothed stabilized (slower) data. //#define USE_STABILIZED_DATA @@ -19,6 +23,7 @@ bool LeapManager::_libraryExists = false; bool LeapManager::_doFakeFingers = false; Leap::Controller* LeapManager::_controller = NULL; HifiLeapListener* LeapManager::_listener = NULL; +glm::vec3 LeapManager::_baseDrivePosition; class HifiLeapListener : public Leap::Listener { public: @@ -44,6 +49,25 @@ void LeapManager::initialize() { #endif } +static PalmData* getRightmostPalm() { + PalmData* rightmostPalm = NULL; + Hand& hand = Application::getInstance()->getAvatar()->getHand(); + for (int i = 0; i < hand.getNumPalms(); i++) { + PalmData* palm = &hand.getPalms()[i]; + if (palm->isActive() && (rightmostPalm == NULL || palm->getRawPosition().x > rightmostPalm->getRawPosition().x)) { + rightmostPalm = palm; + } + } + return rightmostPalm; +} + +void LeapManager::reset() { + PalmData* rightmostPalm = getRightmostPalm(); + if (rightmostPalm != NULL) { + _baseDrivePosition = rightmostPalm->getRawPosition(); + } +} + void LeapManager::terminate() { delete _listener; delete _controller; @@ -51,9 +75,10 @@ void LeapManager::terminate() { _controller = NULL; } -void LeapManager::nextFrame(Avatar& avatar) { +void LeapManager::nextFrame() { // Apply the frame data directly to the avatar. - Hand& hand = avatar.getHand(); + MyAvatar* avatar = Application::getInstance()->getAvatar(); + Hand& hand = avatar->getHand(); // If we actually get valid Leap data, this will be set to true; bool gotRealData = false; @@ -244,6 +269,55 @@ void LeapManager::nextFrame(Avatar& avatar) { } } hand.updateFingerTrails(); + + // if Leap drive is enabled, drive avatar based on Leap input + if (!Menu::getInstance()->isOptionChecked(MenuOption::LeapDrive)) { + return; + } + glm::vec3 relativePosition; + glm::vec3 eulerAngles; + PalmData* rightmostPalm = getRightmostPalm(); + if (rightmostPalm != NULL) { + relativePosition = rightmostPalm->getRawPosition() - _baseDrivePosition; + + glm::vec3 directionSum; + int activeFingerCount = 0; + for (int i = 0; i < rightmostPalm->getNumFingers(); i++) { + FingerData& finger = rightmostPalm->getFingers()[i]; + glm::vec3 fingerVector = finger.getTipRawPosition() - rightmostPalm->getRawPosition(); + if (finger.isActive() && glm::length(fingerVector) > EPSILON) { + directionSum += glm::normalize(fingerVector); + activeFingerCount++; + } + } + const int MIN_DIRECTION_FINGER_COUNT = 3; + glm::vec3 right; + if (activeFingerCount >= MIN_DIRECTION_FINGER_COUNT) { + right = glm::normalize(glm::cross(glm::normalize(directionSum), -rightmostPalm->getRawNormal())); + + } else { + right = glm::normalize(glm::cross(IDENTITY_FRONT, -rightmostPalm->getRawNormal())); + } + eulerAngles = safeEulerAngles(glm::quat_cast(glm::mat3(right, -rightmostPalm->getRawNormal(), + glm::cross(right, -rightmostPalm->getRawNormal())))); + } + const float LINEAR_DRIVE_SCALE = 0.1f; + const float LINEAR_DEAD_ZONE = 0.3f; + avatar->setDriveKeys(FWD, glm::clamp(-relativePosition.z * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(BACK, glm::clamp(relativePosition.z * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(LEFT, glm::clamp(-relativePosition.x * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(RIGHT, glm::clamp(relativePosition.x * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(UP, glm::clamp(relativePosition.y * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(DOWN, glm::clamp(-relativePosition.y * LINEAR_DRIVE_SCALE - LINEAR_DEAD_ZONE, 0.0f, 1.0f)); + + const float ANGULAR_DRIVE_SCALE = 0.1f; + const float ANGULAR_DEAD_ZONE = 0.3f; + avatar->setDriveKeys(ROT_LEFT, glm::clamp(glm::max(eulerAngles.y, eulerAngles.z) * ANGULAR_DRIVE_SCALE - + ANGULAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(ROT_RIGHT, glm::clamp(glm::max(-eulerAngles.y, -eulerAngles.z) * ANGULAR_DRIVE_SCALE - + ANGULAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(ROT_UP, glm::clamp(eulerAngles.x * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f)); + avatar->setDriveKeys(ROT_DOWN, glm::clamp(-eulerAngles.x * ANGULAR_DRIVE_SCALE - ANGULAR_DEAD_ZONE, 0.0f, 1.0f)); } void LeapManager::enableFakeFingers(bool enable) { diff --git a/interface/src/devices/LeapManager.h b/interface/src/devices/LeapManager.h index 11dbefe849..4544d5afcf 100755 --- a/interface/src/devices/LeapManager.h +++ b/interface/src/devices/LeapManager.h @@ -21,7 +21,7 @@ namespace Leap { class LeapManager { public: - static void nextFrame(Avatar& avatar); // called once per frame to get new Leap data + static void nextFrame(); // called once per frame to get new Leap data static bool controllersExist(); // Returns true if there's at least one active Leap plugged in static void enableFakeFingers(bool enable); // put fake data in if there's no Leap plugged in static const std::vector& getFingerTips(); @@ -30,6 +30,7 @@ public: static const std::vector& getHandNormals(); static std::string statusString(); static void initialize(); + static void reset(); static void terminate(); private: @@ -37,6 +38,7 @@ private: static bool _doFakeFingers; static Leap::Controller* _controller; static HifiLeapListener* _listener; + static glm::vec3 _baseDrivePosition; }; #endif /* defined(__hifi__LeapManager__) */