From a8501a7ac627cc968fd2a1ff43949548011f6c4b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 15 Jun 2017 14:45:40 +1200 Subject: [PATCH 01/22] Remove old Leap Motion code --- interface/src/Application.cpp | 8 - interface/src/Menu.cpp | 3 - interface/src/Menu.h | 1 - interface/src/devices/Leapmotion.cpp | 246 -------- interface/src/devices/Leapmotion.h | 48 -- .../ControllerScriptingInterface.cpp | 81 --- .../scripting/ControllerScriptingInterface.h | 40 -- .../trackers/src/trackers/DeviceTracker.cpp | 93 ---- .../trackers/src/trackers/DeviceTracker.h | 115 ---- .../trackers/src/trackers/MotionTracker.cpp | 186 ------- .../trackers/src/trackers/MotionTracker.h | 116 ---- scripts/system/controllers/leapHands.js | 527 ------------------ 12 files changed, 1464 deletions(-) delete mode 100644 interface/src/devices/Leapmotion.cpp delete mode 100644 interface/src/devices/Leapmotion.h delete mode 100644 libraries/trackers/src/trackers/DeviceTracker.cpp delete mode 100644 libraries/trackers/src/trackers/DeviceTracker.h delete mode 100644 libraries/trackers/src/trackers/MotionTracker.cpp delete mode 100644 libraries/trackers/src/trackers/MotionTracker.h delete mode 100644 scripts/system/controllers/leapHands.js diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9ce6cc9b25..c67ba9c81f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -143,7 +143,6 @@ #include "avatar/MyHead.h" #include "CrashHandler.h" #include "devices/DdeFaceTracker.h" -#include "devices/Leapmotion.h" #include "DiscoverabilityManager.h" #include "GLCanvas.h" #include "InterfaceDynamicFactory.h" @@ -1809,8 +1808,6 @@ Application::~Application() { // remove the NodeList from the DependencyManager DependencyManager::destroy(); - Leapmotion::destroy(); - if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { steamClient->shutdown(); } @@ -3977,8 +3974,6 @@ void Application::init() { qCDebug(interfaceapp) << "Loaded settings"; - Leapmotion::init(); - // fire off an immediate domain-server check in now that settings are loaded DependencyManager::get()->sendDomainServerCheckIn(); @@ -4451,7 +4446,6 @@ void Application::update(float deltaTime) { { PerformanceTimer perfTimer("devices"); - DeviceTracker::updateAll(); FaceTracker* tracker = getSelectedFaceTracker(); if (tracker && Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking) != tracker->isMuted()) { @@ -4519,8 +4513,6 @@ void Application::update(float deltaTime) { keyboardMousePlugin->pluginUpdate(deltaTime, calibrationData); } - _controllerScriptingInterface->updateInputControllers(); - // Transfer the user inputs to the driveKeys // FIXME can we drop drive keys and just have the avatar read the action states directly? myAvatar->clearDriveKeys(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 463069430d..f8f66aded5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -547,9 +547,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false, avatar.get(), SLOT(setEnableDebugDrawHandControllers(bool))); - MenuWrapper* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); - addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); - // Developer > Entities >>> MenuWrapper* entitiesOptionsMenu = developerMenu->addMenu("Entities"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 41bf89a20a..0dce84e8a5 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -115,7 +115,6 @@ namespace MenuOption { const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IndependentMode = "Independent Mode"; const QString ActionMotorControl = "Enable Default Motor Control"; - const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; const QString LodTools = "LOD Tools"; diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp deleted file mode 100644 index c643042300..0000000000 --- a/interface/src/devices/Leapmotion.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// -// Created by Sam Cake on 6/2/2014 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Leapmotion.h" - -#include - -#include "Menu.h" - -const int PALMROOT_NUM_JOINTS = 3; -const int FINGER_NUM_JOINTS = 4; -const int HAND_NUM_JOINTS = FINGER_NUM_JOINTS*5+PALMROOT_NUM_JOINTS; - -const DeviceTracker::Name Leapmotion::NAME = "Leapmotion"; - -// find the index of a joint from -// the side: true = right -// the finger & the bone: -// finger in [0..4] : bone in [0..3] a finger phalange -// [-1] up the hand branch : bone in [0..2] <=> [ hand, forearm, arm] -MotionTracker::Index evalJointIndex(bool isRightSide, int finger, int bone) { - - MotionTracker::Index offset = 1 // start after root - + (int(isRightSide) * HAND_NUM_JOINTS) // then offset for side - + PALMROOT_NUM_JOINTS; // then add the arm/forearm/hand chain - if (finger >= 0) { - // from there go down in the correct finger and bone - return offset + (finger * FINGER_NUM_JOINTS) + bone; - } else { - // or go back up for the correct root bone - return offset - 1 - bone; - } -} - -// static -void Leapmotion::init() { - DeviceTracker* device = DeviceTracker::getDevice(NAME); - - if (!device) { - // create a new Leapmotion and register it - Leapmotion* leap = new Leapmotion(); - DeviceTracker::registerDevice(NAME, leap); - } -} - -// static -void Leapmotion::destroy() { - DeviceTracker::destroyDevice(NAME); -} - -// static -Leapmotion* Leapmotion::getInstance() { - DeviceTracker* device = DeviceTracker::getDevice(NAME); - if (!device) { - // create a new Leapmotion and register it - device = new Leapmotion(); - DeviceTracker::registerDevice(NAME, device); - } - return dynamic_cast< Leapmotion* > (device); -} - -Leapmotion::Leapmotion() : - MotionTracker(), - _active(false) -{ - // Create the Leapmotion joint hierarchy - std::vector< Semantic > sides; - sides.push_back("joint_L_"); - sides.push_back("joint_R_"); - - std::vector< Semantic > rootBones; - rootBones.push_back("elbow"); - rootBones.push_back("wrist"); - rootBones.push_back("hand"); - - std::vector< Semantic > fingers; - fingers.push_back("thumb"); - fingers.push_back("index"); - fingers.push_back("middle"); - fingers.push_back("ring"); - fingers.push_back("pinky"); - - std::vector< Semantic > fingerBones; - fingerBones.push_back("1"); - fingerBones.push_back("2"); - fingerBones.push_back("3"); - fingerBones.push_back("4"); - - std::vector< Index > palms; - for (unsigned int s = 0; s < sides.size(); s++) { - Index rootJoint = 0; - for (unsigned int rb = 0; rb < rootBones.size(); rb++) { - rootJoint = addJoint(sides[s] + rootBones[rb], rootJoint); - } - - // capture the hand index for debug - palms.push_back(rootJoint); - - for (unsigned int f = 0; f < fingers.size(); f++) { - for (unsigned int b = 0; b < fingerBones.size(); b++) { - rootJoint = addJoint(sides[s] + fingers[f] + fingerBones[b], rootJoint); - } - } - } - -#ifdef HAVE_LEAPMOTION - if (Menu::getInstance()->isOptionChecked(MenuOption::LeapMotionOnHMD)) { - _controller.setPolicyFlags(Leap::Controller::POLICY_OPTIMIZE_HMD); - } -#endif -} - -Leapmotion::~Leapmotion() { -} - -#ifdef HAVE_LEAPMOTION -glm::quat quatFromLeapBase(float sideSign, const Leap::Matrix& basis) { - - // fix the handness to right and always... - glm::vec3 xAxis = glm::normalize(sideSign * glm::vec3(basis.xBasis.x, basis.xBasis.y, basis.xBasis.z)); - glm::vec3 yAxis = glm::normalize(glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z)); - glm::vec3 zAxis = glm::normalize(glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z)); - - xAxis = glm::normalize(glm::cross(yAxis, zAxis)); - - glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); - return orientation; -} - -glm::vec3 vec3FromLeapVector(const Leap::Vector& vec) { - return glm::vec3(vec.x * METERS_PER_MILLIMETER, vec.y * METERS_PER_MILLIMETER, vec.z * METERS_PER_MILLIMETER); -} - -#endif - -void Leapmotion::update() { -#ifdef HAVE_LEAPMOTION - bool wasActive = _active; - _active = _controller.isConnected(); - - if (_active || wasActive) { - // Go through all the joints and increment their counter since last update. - // Increment all counters once after controller first becomes inactive so that each joint reports itself as inactive. - // TODO C++11 for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { - for (JointTracker::Vector::iterator jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { - (*jointIt).tickNewFrame(); - } - } - - if (!_active) { - return; - } - - // Get the most recent frame and report some basic information - const Leap::Frame frame = _controller.frame(); - static int64_t lastFrameID = -1; - int64_t newFrameID = frame.id(); - - // If too soon then exit - if (lastFrameID >= newFrameID) - return; - - glm::vec3 delta(0.0f); - glm::quat handOri; - if (!frame.hands().isEmpty()) { - for (int handNum = 0; handNum < frame.hands().count(); handNum++) { - - const Leap::Hand hand = frame.hands()[handNum]; - int side = (hand.isRight() ? 1 : -1); - - JointTracker* parentJointTracker = _jointsArray.data(); - - - int rootBranchIndex = -1; - - Leap::Arm arm = hand.arm(); - if (arm.isValid()) { - glm::quat ori = quatFromLeapBase(float(side), arm.basis()); - glm::vec3 pos = vec3FromLeapVector(arm.elbowPosition()); - JointTracker* elbow = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 2)); // 2 is the index of the elbow joint - elbow->editAbsFrame().setTranslation(pos); - elbow->editAbsFrame().setRotation(ori); - elbow->updateLocFromAbsTransform(parentJointTracker); - elbow->activeFrame(); - parentJointTracker = elbow; - - pos = vec3FromLeapVector(arm.wristPosition()); - JointTracker* wrist = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 1)); // 1 is the index of the wrist joint - wrist->editAbsFrame().setTranslation(pos); - wrist->editAbsFrame().setRotation(ori); - wrist->updateLocFromAbsTransform(parentJointTracker); - wrist->activeFrame(); - parentJointTracker = wrist; - } - - JointTracker* palmJoint = NULL; - { - glm::vec3 pos = vec3FromLeapVector(hand.palmPosition()); - glm::quat ori = quatFromLeapBase(float(side), hand.basis()); - - palmJoint = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 0)); // 0 is the index of the palm joint - palmJoint->editAbsFrame().setTranslation(pos); - palmJoint->editAbsFrame().setRotation(ori); - palmJoint->updateLocFromAbsTransform(parentJointTracker); - palmJoint->activeFrame(); - } - - // Check if the hand has any fingers - const Leap::FingerList fingers = hand.fingers(); - if (!fingers.isEmpty()) { - // For every fingers in the list - for (int i = 0; i < fingers.count(); ++i) { - // Reset the parent joint to the palmJoint for every finger traversal - parentJointTracker = palmJoint; - - // surprisingly, Leap::Finger::Type start at 0 for thumb a until 4 for the pinky - Index fingerIndex = evalJointIndex((side > 0), int(fingers[i].type()), 0); - - // let's update the finger's joints - for (int b = 0; b < FINGER_NUM_JOINTS; b++) { - Leap::Bone::Type type = Leap::Bone::Type(b + Leap::Bone::TYPE_METACARPAL); - Leap::Bone bone = fingers[i].bone(type); - JointTracker* ljointTracker = editJointTracker(fingerIndex + b); - if (bone.isValid()) { - Leap::Vector bp = bone.nextJoint(); - - ljointTracker->editAbsFrame().setTranslation(vec3FromLeapVector(bp)); - ljointTracker->editAbsFrame().setRotation(quatFromLeapBase(float(side), bone.basis())); - ljointTracker->updateLocFromAbsTransform(parentJointTracker); - ljointTracker->activeFrame(); - } - parentJointTracker = ljointTracker; - } - } - } - } - } - - lastFrameID = newFrameID; -#endif -} diff --git a/interface/src/devices/Leapmotion.h b/interface/src/devices/Leapmotion.h deleted file mode 100644 index a119821846..0000000000 --- a/interface/src/devices/Leapmotion.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by Sam Cake on 6/2/2014 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Leapmotion_h -#define hifi_Leapmotion_h - -#include - -#include - -#ifdef HAVE_LEAPMOTION -#include -#endif - -/// Handles interaction with the Leapmotion skeleton tracking suit. -class Leapmotion : public MotionTracker { -public: - static const Name NAME; - - static void init(); - static void destroy(); - - /// Leapmotion MotionTracker factory - static Leapmotion* getInstance(); - - bool isActive() const { return _active; } - - virtual void update() override; - -protected: - Leapmotion(); - virtual ~Leapmotion(); - -private: -#ifdef HAVE_LEAPMOTION - Leap::Listener _listener; - Leap::Controller _controller; -#endif - - bool _active; -}; - -#endif // hifi_Leapmotion_h diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index f3ec3cd79d..9fbd01817a 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -17,7 +17,6 @@ #include #include "Application.h" -#include void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { if (event->type() == HFActionEvent::startType()) { @@ -97,86 +96,6 @@ QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const { return qRectToVariant(rect); } -controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { - // This is where we retrieve the Device Tracker category and then the sub tracker within it - auto icIt = _inputControllers.find(0); - if (icIt != _inputControllers.end()) { - return (*icIt).second.get(); - } - - // Look for device - DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString()); - if (deviceID < 0) { - deviceID = 0; - } - // TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion) - // in the near future we need to change that to a real mapping between the devices and the deviceName - // ALso we need to expand the spec so we can fall back on the "default" controller per categories - - if (deviceID >= 0) { - // TODO here again the assumption it's the LeapMotion and so it's a MOtionTracker, this would need to be changed to support different types of devices - MotionTracker* motionTracker = dynamic_cast< MotionTracker* > (DeviceTracker::getDevice(deviceID)); - if (motionTracker) { - MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString()); - if (trackerID >= 0) { - controller::InputController::Pointer inputController = std::make_shared(deviceID, trackerID, this); - controller::InputController::Key key = inputController->getKey(); - _inputControllers.insert(InputControllerMap::value_type(key, inputController)); - return inputController.get(); - } - } - } - - return nullptr; -} - -void ControllerScriptingInterface::releaseInputController(controller::InputController* input) { - _inputControllers.erase(input->getKey()); -} - -void ControllerScriptingInterface::updateInputControllers() { - for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) { - (*it).second->update(); - } -} - -InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) : - _deviceTrackerId(deviceTrackerId), - _subTrackerId(subTrackerId), - _isActive(false) -{ -} - -void InputController::update() { - _isActive = false; - - // TODO for now the InputController is only supporting a JointTracker from a MotionTracker - MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId)); - if (motionTracker) { - if ((int)_subTrackerId < motionTracker->numJointTrackers()) { - const MotionTracker::JointTracker* joint = motionTracker->getJointTracker(_subTrackerId); - - if (joint->isActive()) { - joint->getAbsFrame().getTranslation(_eventCache.absTranslation); - joint->getAbsFrame().getRotation(_eventCache.absRotation); - joint->getLocFrame().getTranslation(_eventCache.locTranslation); - joint->getLocFrame().getRotation(_eventCache.locRotation); - - _isActive = true; - //emit spatialEvent(_eventCache); - } - } - } -} - -const unsigned int INPUTCONTROLLER_KEY_DEVICE_OFFSET = 16; -const unsigned int INPUTCONTROLLER_KEY_DEVICE_MASK = 16; - -InputController::Key InputController::getKey() const { - return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId); -} - - void ControllerScriptingInterface::emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } void ControllerScriptingInterface::emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 996ccabb20..6d197477bb 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -25,38 +25,6 @@ #include class ScriptEngine; -class PalmData; - -class InputController : public controller::InputController { - Q_OBJECT - -public: - InputController(int deviceTrackerId, int subTrackerId, QObject* parent = NULL); - - virtual void update() override; - virtual Key getKey() const override; - -public slots: - - virtual bool isActive() const override { return _isActive; } - virtual glm::vec3 getAbsTranslation() const override { return _eventCache.absTranslation; } - virtual glm::quat getAbsRotation() const override { return _eventCache.absRotation; } - virtual glm::vec3 getLocTranslation() const override { return _eventCache.locTranslation; } - virtual glm::quat getLocRotation() const override { return _eventCache.locRotation; } - -private: - - int _deviceTrackerId; - uint _subTrackerId; - - // cache for the spatial - SpatialEvent _eventCache; - bool _isActive; - -signals: -}; - - /// handles scripting of input controller commands from JS class ControllerScriptingInterface : public controller::ScriptingInterface { Q_OBJECT @@ -86,8 +54,6 @@ public: bool isJoystickCaptured(int joystickIndex) const; bool areEntityClicksCaptured() const; - void updateInputControllers(); - public slots: virtual void captureKeyEvents(const KeyEvent& event); @@ -102,10 +68,6 @@ public slots: virtual glm::vec2 getViewportDimensions() const; virtual QVariant getRecommendedOverlayRect() const; - /// Factory to create an InputController - virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker); - virtual void releaseInputController(controller::InputController* input); - signals: void keyPressEvent(const KeyEvent& event); void keyReleaseEvent(const KeyEvent& event); @@ -135,8 +97,6 @@ private: bool _captureEntityClicks; using InputKey = controller::InputController::Key; - using InputControllerMap = std::map; - InputControllerMap _inputControllers; }; const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip diff --git a/libraries/trackers/src/trackers/DeviceTracker.cpp b/libraries/trackers/src/trackers/DeviceTracker.cpp deleted file mode 100644 index 93aeb607bc..0000000000 --- a/libraries/trackers/src/trackers/DeviceTracker.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Created by Sam Cake on 6/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "DeviceTracker.h" - -DeviceTracker::SingletonData::~SingletonData() { - // Destroy all the device registered - //TODO C++11 for (auto device = _devicesVector.begin(); device != _devicesVector.end(); device++) { - for (Vector::iterator device = _devicesVector.begin(); device != _devicesVector.end(); device++) { - delete (*device); - } -} - -int DeviceTracker::getNumDevices() { - return (int)Singleton::get()->_devicesMap.size(); -} - -DeviceTracker::ID DeviceTracker::getDeviceID(const Name& name) { - //TODO C++11 auto deviceIt = Singleton::get()->_devicesMap.find(name); - Map::iterator deviceIt = Singleton::get()->_devicesMap.find(name); - if (deviceIt != Singleton::get()->_devicesMap.end()) { - return (*deviceIt).second; - } else { - return INVALID_DEVICE; - } -} - -DeviceTracker* DeviceTracker::getDevice(const Name& name) { - return getDevice(getDeviceID(name)); -} - -DeviceTracker* DeviceTracker::getDevice(DeviceTracker::ID deviceID) { - if ((deviceID >= 0) && (deviceID < (int)(Singleton::get()->_devicesVector.size()))) { - return Singleton::get()->_devicesVector[ deviceID ]; - } else { - return NULL; - } -} - -DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker* device) { - // Check that the device exists, if not exit - if (!device) { - return INVALID_DEVICE; - } - - // Look if the name is not already used - ID deviceID = getDeviceID(name); - if (deviceID >= 0) { - return INVALID_DEVICE_NAME; - } - - // Good to register the device - deviceID = (ID)Singleton::get()->_devicesVector.size(); - Singleton::get()->_devicesMap.insert(Map::value_type(name, deviceID)); - Singleton::get()->_devicesVector.push_back(device); - device->assignIDAndName(deviceID, name); - - return deviceID; -} - -void DeviceTracker::destroyDevice(const Name& name) { - DeviceTracker::ID deviceID = getDeviceID(name); - if (deviceID != INVALID_DEVICE) { - delete Singleton::get()->_devicesVector[getDeviceID(name)]; - Singleton::get()->_devicesVector[getDeviceID(name)] = nullptr; - } -} - -void DeviceTracker::updateAll() { - //TODO C++11 for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) { - for (Vector::iterator deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) { - if ((*deviceIt)) - (*deviceIt)->update(); - } -} - -// Core features of the Device Tracker -DeviceTracker::DeviceTracker() : - _ID(INVALID_DEVICE), - _name("Unkown") -{ -} - -DeviceTracker::~DeviceTracker() { -} - -void DeviceTracker::update() { -} diff --git a/libraries/trackers/src/trackers/DeviceTracker.h b/libraries/trackers/src/trackers/DeviceTracker.h deleted file mode 100644 index 8a7f509cb3..0000000000 --- a/libraries/trackers/src/trackers/DeviceTracker.h +++ /dev/null @@ -1,115 +0,0 @@ -// -// Created by Sam Cake on 6/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_DeviceTracker_h -#define hifi_DeviceTracker_h - -#include -#include -#include - -// Singleton template class -template < typename T > -class TemplateSingleton { -public: - - static T* get() { - if ( !_singleton._one ) { - _singleton._one = new T(); - } - return _singleton._one; - } - - TemplateSingleton() : - _one(0) - { - } - ~TemplateSingleton() { - if ( _one ) { - delete _one; - _one = 0; - } - } -private: - static TemplateSingleton< T > _singleton; - T* _one; -}; -template -TemplateSingleton TemplateSingleton::_singleton; - -/// Base class for device trackers. -class DeviceTracker { -public: - - // THe ID and Name types used to manage the pool of devices - typedef std::string Name; - typedef int ID; - static const ID INVALID_DEVICE = -1; - static const ID INVALID_DEVICE_NAME = -2; - - // Singleton interface to register and query the devices currently connected - static int getNumDevices(); - static ID getDeviceID(const Name& name); - static DeviceTracker* getDevice(ID deviceID); - static DeviceTracker* getDevice(const Name& name); - - /// Update all the devices calling for their update() function - /// This should be called every frame by the main loop to update all the devices that pull their state - static void updateAll(); - - /// Register a device tracker to the factory - /// Right after creating a new DeviceTracker, it should be registered - /// This is why, it's recommended to use a factory static call in the specialized class - /// to create a new input device - /// - /// \param name The Name under wich registering the device - /// \param parent The DeviceTracker - /// - /// \return The Index of the newly registered device. - /// Valid if everything went well. - /// INVALID_DEVICE if the device is not valid (NULL) - /// INVALID_DEVICE_NAME if the name is already taken - static ID registerDevice(const Name& name, DeviceTracker* tracker); - - static void destroyDevice(const Name& name); - - // DeviceTracker interface - - virtual void update(); - - /// Get the ID assigned to the Device when registered after creation, or INVALID_DEVICE if it hasn't been registered which should not happen. - ID getID() const { return _ID; } - - /// Get the name assigned to the Device when registered after creation, or "Unknown" if it hasn't been registered which should not happen. - const Name& getName() const { return _name; } - - typedef std::map< Name, ID > Map; - static const Map& getDevices() { return Singleton::get()->_devicesMap; } - -protected: - DeviceTracker(); - virtual ~DeviceTracker(); - -private: - ID _ID; - Name _name; - - // this call is used by the singleton when the device tracker is currently beeing registered and beeing assigned an ID - void assignIDAndName( const ID id, const Name& name ) { _ID = id; _name = name; } - - typedef std::vector< DeviceTracker* > Vector; - struct SingletonData { - Map _devicesMap; - Vector _devicesVector; - - ~SingletonData(); - }; - typedef TemplateSingleton< SingletonData > Singleton; -}; - -#endif // hifi_DeviceTracker_h diff --git a/libraries/trackers/src/trackers/MotionTracker.cpp b/libraries/trackers/src/trackers/MotionTracker.cpp deleted file mode 100644 index c6012c0422..0000000000 --- a/libraries/trackers/src/trackers/MotionTracker.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// Created by Sam Cake on 6/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "MotionTracker.h" - -// glm::mult(mat43, mat43) just the composition of the 2 matrices assuming they are in fact mat44 with the last raw = { 0, 0, 0, 1 } -namespace glm { - mat4x3 mult(const mat4& lhs, const mat4x3& rhs) { - vec3 lrx(lhs[0].x, lhs[1].x, lhs[2].x); - vec3 lry(lhs[0].y, lhs[1].y, lhs[2].y); - vec3 lrz(lhs[0].z, lhs[1].z, lhs[2].z); - return mat4x3( - dot(lrx, rhs[0]), - dot(lry, rhs[0]), - dot(lrz, rhs[0]), - - dot(lrx, rhs[1]), - dot(lry, rhs[1]), - dot(lrz, rhs[1]), - - dot(lrx, rhs[2]), - dot(lry, rhs[2]), - dot(lrz, rhs[2]), - - dot(lrx, rhs[3]) + lhs[3].x, - dot(lry, rhs[3]) + lhs[3].y, - dot(lrz, rhs[3]) + lhs[3].z - ); - } - mat4x3 mult(const mat4x3& lhs, const mat4x3& rhs) { - vec3 lrx(lhs[0].x, lhs[1].x, lhs[2].x); - vec3 lry(lhs[0].y, lhs[1].y, lhs[2].y); - vec3 lrz(lhs[0].z, lhs[1].z, lhs[2].z); - return mat4x3( - dot(lrx, rhs[0]), - dot(lry, rhs[0]), - dot(lrz, rhs[0]), - - dot(lrx, rhs[1]), - dot(lry, rhs[1]), - dot(lrz, rhs[1]), - - dot(lrx, rhs[2]), - dot(lry, rhs[2]), - dot(lrz, rhs[2]), - - dot(lrx, rhs[3]) + lhs[3].x, - dot(lry, rhs[3]) + lhs[3].y, - dot(lrz, rhs[3]) + lhs[3].z - ); - } -} - -// MotionTracker -MotionTracker::MotionTracker() : - DeviceTracker() -{ - _jointsArray.resize(1); - _jointsMap.insert(JointTracker::Map::value_type(Semantic("Root"), 0)); -} - -MotionTracker::~MotionTracker() -{ -} - -bool MotionTracker::isConnected() const { - return false; -} - -MotionTracker::Index MotionTracker::addJoint(const Semantic& semantic, Index parent) { - // Check the parent - if (int(parent) < 0) - return INVALID_PARENT; - - // Check that the semantic is not already in use - Index foundIndex = findJointIndex(semantic); - if (foundIndex >= 0) { - return INVALID_SEMANTIC; - } - - - // All good then allocate the joint - Index newIndex = (Index)_jointsArray.size(); - _jointsArray.push_back(JointTracker(semantic, parent)); - _jointsMap.insert(JointTracker::Map::value_type(semantic, newIndex)); - - return newIndex; -} - -MotionTracker::Index MotionTracker::findJointIndex(const Semantic& semantic) const { - // TODO C++11 auto jointIt = _jointsMap.find(semantic); - JointTracker::Map::const_iterator jointIt = _jointsMap.find(semantic); - if (jointIt != _jointsMap.end()) { - return (*jointIt).second; - } - - return INVALID_SEMANTIC; -} - -void MotionTracker::updateAllAbsTransform() { - _jointsArray[0].updateAbsFromLocTransform(0); - - // Because we know the hierarchy is stored from root down the branches let's just traverse and update - for (Index i = 1; i < (Index)(_jointsArray.size()); i++) { - JointTracker* joint = _jointsArray.data() + i; - joint->updateAbsFromLocTransform(_jointsArray.data() + joint->getParent()); - } -} - - -// MotionTracker::JointTracker -MotionTracker::JointTracker::JointTracker() : - _locFrame(), - _absFrame(), - _semantic(""), - _parent(INVALID_PARENT), - _lastUpdate(1) // Joint inactive -{ -} - -MotionTracker::JointTracker::JointTracker(const Semantic& semantic, Index parent) : - _semantic(semantic), - _parent(parent), - _lastUpdate(1) // Joint inactive -{ -} - -MotionTracker::JointTracker::JointTracker(const JointTracker& tracker) : - _locFrame(tracker._locFrame), - _absFrame(tracker._absFrame), - _semantic(tracker._semantic), - _parent(tracker._parent), - _lastUpdate(tracker._lastUpdate) -{ -} - -void MotionTracker::JointTracker::updateAbsFromLocTransform(const JointTracker* parentJoint) { - if (parentJoint) { - editAbsFrame()._transform = (parentJoint->getAbsFrame()._transform * getLocFrame()._transform); - } else { - editAbsFrame()._transform = getLocFrame()._transform; - } -} - -void MotionTracker::JointTracker::updateLocFromAbsTransform(const JointTracker* parentJoint) { - if (parentJoint) { - glm::mat4 ip = glm::inverse(parentJoint->getAbsFrame()._transform); - editLocFrame()._transform = (ip * getAbsFrame()._transform); - } else { - editLocFrame()._transform = getAbsFrame()._transform; - } -} - -//-------------------------------------------------------------------------------------- -// MotionTracker::Frame -//-------------------------------------------------------------------------------------- - -MotionTracker::Frame::Frame() : - _transform() -{ -} - -void MotionTracker::Frame::setRotation(const glm::quat& rotation) { - glm::mat3x3 rot = glm::mat3_cast(rotation); - _transform[0] = glm::vec4(rot[0], 0.0f); - _transform[1] = glm::vec4(rot[1], 0.0f); - _transform[2] = glm::vec4(rot[2], 0.0f); -} - -void MotionTracker::Frame::getRotation(glm::quat& rotation) const { - rotation = glm::quat_cast(_transform); -} - -void MotionTracker::Frame::setTranslation(const glm::vec3& translation) { - _transform[3] = glm::vec4(translation, 1.0f); -} - -void MotionTracker::Frame::getTranslation(glm::vec3& translation) const { - translation = extractTranslation(_transform); -} - diff --git a/libraries/trackers/src/trackers/MotionTracker.h b/libraries/trackers/src/trackers/MotionTracker.h deleted file mode 100644 index 26c8dcea2c..0000000000 --- a/libraries/trackers/src/trackers/MotionTracker.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// Created by Sam Cake on 6/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MotionTracker_h -#define hifi_MotionTracker_h - -#include "DeviceTracker.h" - -#include - -/// Base class for device trackers. -class MotionTracker : public DeviceTracker { -public: - - class Frame { - public: - Frame(); - - glm::mat4 _transform; - - void setRotation(const glm::quat& rotation); - void getRotation(glm::quat& rotatio) const; - - void setTranslation(const glm::vec3& translation); - void getTranslation(glm::vec3& translation) const; - }; - - // Semantic and Index types to retreive the JointTrackers of this MotionTracker - typedef std::string Semantic; - typedef int32_t Index; - static const Index INVALID_SEMANTIC = -1; - static const Index INVALID_PARENT = -2; - - class JointTracker { - public: - typedef std::vector< JointTracker > Vector; - typedef std::map< Semantic, Index > Map; - - JointTracker(); - JointTracker(const JointTracker& tracker); - JointTracker(const Semantic& semantic, Index parent); - - const Frame& getLocFrame() const { return _locFrame; } - Frame& editLocFrame() { return _locFrame; } - void setLocFrame(const Frame& frame) { editLocFrame() = frame; } - - const Frame& getAbsFrame() const { return _absFrame; } - Frame& editAbsFrame() { return _absFrame; } - void setAbsFrame(const Frame& frame) { editAbsFrame() = frame; } - - const Semantic& getSemantic() const { return _semantic; } - const Index& getParent() const { return _parent; } - - bool isActive() const { return (_lastUpdate <= 0); } - void tickNewFrame() { _lastUpdate++; } - void activeFrame() { _lastUpdate = 0; } - - /// Update the loc/abs transform for this joint from the current abs/loc value and the specified parent joint abs frame - void updateLocFromAbsTransform(const JointTracker* parentJoint); - void updateAbsFromLocTransform(const JointTracker* parentJoint); - - protected: - Frame _locFrame; - Frame _absFrame; - Semantic _semantic; - Index _parent; - int _lastUpdate; - }; - - virtual bool isConnected() const; - - Index numJointTrackers() const { return (Index)_jointsArray.size(); } - - /// Access a Joint from it's index. - /// Index 0 is always the "Root". - /// if the index is Invalid then returns NULL. - const JointTracker* getJointTracker(Index index) const { return ((index > 0) && (index < (Index)(_jointsArray.size())) ? _jointsArray.data() + index : NULL); } - JointTracker* editJointTracker(Index index) { return ((index > 0) && (index < (Index)(_jointsArray.size())) ? _jointsArray.data() + index : NULL); } - - /// From a semantic, find the Index of the Joint. - /// \return the index of the mapped Joint or INVALID_SEMANTIC if the semantic is not knowned. - Index findJointIndex(const Semantic& semantic) const; - -protected: - MotionTracker(); - virtual ~MotionTracker(); - - JointTracker::Vector _jointsArray; - JointTracker::Map _jointsMap; - - /// Adding joint is only done from the specialized Motion Tracker, hence this function is protected. - /// The hierarchy of joints must be created from the top down to the branches. - /// The "Root" node is at index 0 and exists at creation of the Motion Tracker. - /// - /// \param semantic A joint is defined by it's semantic, the unique name mapping to it - /// \param parent The parent's index, the parent must be valid and correspond to a Joint that has been previously created - /// - /// \return The Index of the newly created Joint. - /// Valid if everything went well. - /// INVALID_SEMANTIC if the semantic is already in use - /// INVALID_PARENT if the parent is not valid - Index addJoint(const Semantic& semantic, Index parent); - - /// Update the absolute transform stack traversing the hierarchy from the root down the branches - /// This is a generic way to update all the Joint's absFrame by combining the locFrame going down the hierarchy branch. - void updateAllAbsTransform(); -}; - - - -#endif // hifi_MotionTracker_h diff --git a/scripts/system/controllers/leapHands.js b/scripts/system/controllers/leapHands.js deleted file mode 100644 index 1be0b1e5f6..0000000000 --- a/scripts/system/controllers/leapHands.js +++ /dev/null @@ -1,527 +0,0 @@ -// -// leapHands.js -// examples -// -// Created by David Rowe on 8 Sep 2014. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example script that uses the Leap Motion to make the avatar's hands replicate the user's hand actions. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var leftTriggerValue = 0; -var rightTriggerValue = 0; - -var LEAP_TRIGGER_START_ANGLE = 15.0; -var LEAP_TRIGGER_END_ANGLE = 40.0; - -function getLeapMotionLeftTrigger() { - //print("left trigger = " + leftTriggerValue); - return leftTriggerValue; -} -function getLeapMotionRightTrigger() { - //print("right trigger = " + rightTriggerValue); - return rightTriggerValue; -} - -var leapHands = (function () { - - var isOnHMD, - LEAP_ON_HMD_MENU_ITEM = "Leap Motion on HMD", - LEAP_OFFSET = 0.019, // Thickness of Leap Motion plus HMD clip - HMD_OFFSET = 0.070, // Eyeballs to front surface of Oculus DK2 TODO: Confirm and make depend on device and eye relief - hasHandAndWristJoints, - handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position - HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle - handAnimationStateHandlers, - handAnimationStateFunctions, - handAnimationStateProperties, - hands, - wrists, - NUM_HANDS = 2, // 0 = left; 1 = right - fingers, - NUM_FINGERS = 5, // 0 = thumb; ...; 4 = pinky - THUMB = 0, - MIDDLE_FINGER = 2, - NUM_FINGER_JOINTS = 3, // 0 = metacarpal(hand)-proximal(finger) joint; ...; 2 = intermediate-distal joint - MAX_HAND_INACTIVE_COUNT = 20, - calibrationStatus, - UNCALIBRATED = 0, - CALIBRATING = 1, - CALIBRATED = 2, - CALIBRATION_TIME = 1000, // milliseconds - avatarScale, - avatarFaceModelURL, - avatarSkeletonModelURL, - settingsTimer, - HMD_CAMERA_TO_AVATAR_ROTATION = [ - Quat.angleAxis(180.0, { x: 0, y: 0, z: 1 }), - Quat.angleAxis(-180.0, { x: 0, y: 0, z: 1 }) - ], - DESKTOP_CAMERA_TO_AVATAR_ROTATION = - Quat.multiply(Quat.angleAxis(180.0, { x: 0, y: 1, z: 0 }), Quat.angleAxis(90.0, { x: 0, y: 0, z: 1 })), - LEAP_THUMB_ROOT_ADJUST = [Quat.fromPitchYawRollDegrees(0, 0, 20), Quat.fromPitchYawRollDegrees(0, 0, -20)]; - - function printSkeletonJointNames() { - var jointNames, - i; - - print(MyAvatar.skeletonModelURL); - - print("Skeleton joint names ..."); - jointNames = MyAvatar.getJointNames(); - for (i = 0; i < jointNames.length; i += 1) { - print(i + ": " + jointNames[i]); - } - print("... skeleton joint names"); - } - - function animateLeftHand() { - var ROTATION_AND_POSITION = 0; - - return { - leftHandType: ROTATION_AND_POSITION, - leftHandPosition: hands[0].position, - leftHandRotation: hands[0].rotation - }; - } - - function animateRightHand() { - var ROTATION_AND_POSITION = 0; - - return { - rightHandType: ROTATION_AND_POSITION, - rightHandPosition: hands[1].position, - rightHandRotation: hands[1].rotation - }; - } - - function finishCalibration() { - var avatarPosition, - handPosition, - middleFingerPosition, - leapHandHeight, - h; - - if (!isOnHMD) { - if (hands[0].controller.isActive() && hands[1].controller.isActive()) { - leapHandHeight = (hands[0].controller.getAbsTranslation().y + hands[1].controller.getAbsTranslation().y) / 2.0; - } else { - calibrationStatus = UNCALIBRATED; - return; - } - } - - avatarPosition = MyAvatar.position; - - for (h = 0; h < NUM_HANDS; h += 1) { - handPosition = MyAvatar.getJointPosition(hands[h].jointName); - if (!hasHandAndWristJoints) { - middleFingerPosition = MyAvatar.getJointPosition(fingers[h][MIDDLE_FINGER][0].jointName); - handToWristOffset[h] = Vec3.multiply(Vec3.subtract(handPosition, middleFingerPosition), 1.0 - HAND_OFFSET); - } - - if (isOnHMD) { - // Offset of Leap Motion origin from physical eye position - hands[h].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; - } else { - hands[h].zeroPosition = { - x: handPosition.x - avatarPosition.x, - y: handPosition.y - avatarPosition.y, - z: avatarPosition.z - handPosition.z - }; - hands[h].zeroPosition = Vec3.multiplyQbyV(MyAvatar.orientation, hands[h].zeroPosition); - hands[h].zeroPosition.y = hands[h].zeroPosition.y - leapHandHeight; - } - } - - MyAvatar.clearJointData("LeftHand"); - MyAvatar.clearJointData("LeftForeArm"); - MyAvatar.clearJointData("RightHand"); - MyAvatar.clearJointData("RightForeArm"); - - calibrationStatus = CALIBRATED; - print("Leap Motion: Calibrated"); - } - - function calibrate() { - var jointNames, - i; - - calibrationStatus = CALIBRATING; - - avatarScale = MyAvatar.scale; - avatarFaceModelURL = MyAvatar.faceModelURL; - avatarSkeletonModelURL = MyAvatar.skeletonModelURL; - - // Does this skeleton have both wrist and hand joints? - hasHandAndWristJoints = false; - jointNames = MyAvatar.getJointNames(); - for (i = 0; i < jointNames.length; i += 1) { - hasHandAndWristJoints = hasHandAndWristJoints || jointNames[i].toLowerCase() === "leftwrist"; - } - - // Set avatar arms vertical, forearms horizontal, as "zero" position for calibration - MyAvatar.setJointRotation("LeftForeArm", Quat.fromPitchYawRollDegrees(0.0, 0.0, 90.0)); - MyAvatar.setJointRotation("LeftHand", Quat.fromPitchYawRollDegrees(0.0, 90.0, 0.0)); - MyAvatar.setJointRotation("RightForeArm", Quat.fromPitchYawRollDegrees(0.0, 0.0, -90.0)); - MyAvatar.setJointRotation("RightHand", Quat.fromPitchYawRollDegrees(0.0, -90.0, 0.0)); - - // Wait for arms to assume their positions before calculating - Script.setTimeout(finishCalibration, CALIBRATION_TIME); - } - - function checkCalibration() { - - if (calibrationStatus === CALIBRATED) { - return true; - } - - if (calibrationStatus !== CALIBRATING) { - calibrate(); - } - - return false; - } - - function setIsOnHMD() { - isOnHMD = Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM); - print("Leap Motion: " + (isOnHMD ? "Is on HMD" : "Is on desk")); - } - - function checkSettings() { - if (calibrationStatus > UNCALIBRATED && (MyAvatar.scale !== avatarScale - || MyAvatar.faceModelURL !== avatarFaceModelURL - || MyAvatar.skeletonModelURL !== avatarSkeletonModelURL - || Menu.isOptionChecked(LEAP_ON_HMD_MENU_ITEM) !== isOnHMD)) { - print("Leap Motion: Recalibrate..."); - calibrationStatus = UNCALIBRATED; - - setIsOnHMD(); - } - } - - function setUp() { - - wrists = [ - { - jointName: "LeftWrist", - controller: Controller.createInputController("Spatial", "joint_L_wrist") - }, - { - jointName: "RightWrist", - controller: Controller.createInputController("Spatial", "joint_R_wrist") - } - ]; - - hands = [ - { - jointName: "LeftHand", - controller: Controller.createInputController("Spatial", "joint_L_hand"), - inactiveCount: 0 - }, - { - jointName: "RightHand", - controller: Controller.createInputController("Spatial", "joint_R_hand"), - inactiveCount: 0 - } - ]; - - // The Leap controller's first joint is the hand-metacarpal joint but this joint's data is not used because it's too - // dependent on the model skeleton exactly matching the Leap skeleton; using just the second and subsequent joints - // seems to work better over all. - fingers = [{}, {}]; - fingers[0] = [ - [ - { jointName: "LeftHandThumb1", controller: Controller.createInputController("Spatial", "joint_L_thumb2") }, - { jointName: "LeftHandThumb2", controller: Controller.createInputController("Spatial", "joint_L_thumb3") }, - { jointName: "LeftHandThumb3", controller: Controller.createInputController("Spatial", "joint_L_thumb4") } - ], - [ - { jointName: "LeftHandIndex1", controller: Controller.createInputController("Spatial", "joint_L_index2") }, - { jointName: "LeftHandIndex2", controller: Controller.createInputController("Spatial", "joint_L_index3") }, - { jointName: "LeftHandIndex3", controller: Controller.createInputController("Spatial", "joint_L_index4") } - ], - [ - { jointName: "LeftHandMiddle1", controller: Controller.createInputController("Spatial", "joint_L_middle2") }, - { jointName: "LeftHandMiddle2", controller: Controller.createInputController("Spatial", "joint_L_middle3") }, - { jointName: "LeftHandMiddle3", controller: Controller.createInputController("Spatial", "joint_L_middle4") } - ], - [ - { jointName: "LeftHandRing1", controller: Controller.createInputController("Spatial", "joint_L_ring2") }, - { jointName: "LeftHandRing2", controller: Controller.createInputController("Spatial", "joint_L_ring3") }, - { jointName: "LeftHandRing3", controller: Controller.createInputController("Spatial", "joint_L_ring4") } - ], - [ - { jointName: "LeftHandPinky1", controller: Controller.createInputController("Spatial", "joint_L_pinky2") }, - { jointName: "LeftHandPinky2", controller: Controller.createInputController("Spatial", "joint_L_pinky3") }, - { jointName: "LeftHandPinky3", controller: Controller.createInputController("Spatial", "joint_L_pinky4") } - ] - ]; - fingers[1] = [ - [ - { jointName: "RightHandThumb1", controller: Controller.createInputController("Spatial", "joint_R_thumb2") }, - { jointName: "RightHandThumb2", controller: Controller.createInputController("Spatial", "joint_R_thumb3") }, - { jointName: "RightHandThumb3", controller: Controller.createInputController("Spatial", "joint_R_thumb4") } - ], - [ - { jointName: "RightHandIndex1", controller: Controller.createInputController("Spatial", "joint_R_index2") }, - { jointName: "RightHandIndex2", controller: Controller.createInputController("Spatial", "joint_R_index3") }, - { jointName: "RightHandIndex3", controller: Controller.createInputController("Spatial", "joint_R_index4") } - ], - [ - { jointName: "RightHandMiddle1", controller: Controller.createInputController("Spatial", "joint_R_middle2") }, - { jointName: "RightHandMiddle2", controller: Controller.createInputController("Spatial", "joint_R_middle3") }, - { jointName: "RightHandMiddle3", controller: Controller.createInputController("Spatial", "joint_R_middle4") } - ], - [ - { jointName: "RightHandRing1", controller: Controller.createInputController("Spatial", "joint_R_ring2") }, - { jointName: "RightHandRing2", controller: Controller.createInputController("Spatial", "joint_R_ring3") }, - { jointName: "RightHandRing3", controller: Controller.createInputController("Spatial", "joint_R_ring4") } - ], - [ - { jointName: "RightHandPinky1", controller: Controller.createInputController("Spatial", "joint_R_pinky2") }, - { jointName: "RightHandPinky2", controller: Controller.createInputController("Spatial", "joint_R_pinky3") }, - { jointName: "RightHandPinky3", controller: Controller.createInputController("Spatial", "joint_R_pinky4") } - ] - ]; - - handAnimationStateHandlers = [null, null]; - handAnimationStateFunctions = [animateLeftHand, animateRightHand]; - handAnimationStateProperties = [ - ["leftHandType", "leftHandPosition", "leftHandRotation"], - ["rightHandType", "rightHandPosition", "rightHandPosition"] - ]; - - setIsOnHMD(); - - settingsTimer = Script.setInterval(checkSettings, 2000); - - calibrationStatus = UNCALIBRATED; - - { - var mapping = Controller.newMapping("LeapmotionTrigger"); - mapping.from(getLeapMotionLeftTrigger).to(Controller.Standard.LT); - mapping.from(getLeapMotionRightTrigger).to(Controller.Standard.RT); - mapping.enable(); - } - } - - function moveHands() { - var h, - i, - j, - side, - handOffset, - wristOffset, - handRotation, - locRotation, - cameraOrientation, - inverseAvatarOrientation; - - for (h = 0; h < NUM_HANDS; h += 1) { - side = h === 0 ? -1.0 : 1.0; - - if (hands[h].controller.isActive()) { - - // Calibrate if necessary. - if (!checkCalibration()) { - return; - } - - // Hand animation handlers ... - if (handAnimationStateHandlers[h] === null) { - handAnimationStateHandlers[h] = MyAvatar.addAnimationStateHandler(handAnimationStateFunctions[h], - handAnimationStateProperties[h]); - } - - // Hand position ... - handOffset = hands[h].controller.getAbsTranslation(); - handRotation = hands[h].controller.getAbsRotation(); - - if (isOnHMD) { - - // Adjust to control wrist position if "hand" joint is at wrist ... - if (!hasHandAndWristJoints) { - wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]); - handOffset = Vec3.sum(handOffset, wristOffset); - } - - // Hand offset in camera coordinates ... - handOffset = { - x: -handOffset.x, - y: -handOffset.z, - z: -handOffset.y - hands[h].zeroPosition.z - }; - - // Hand offset in world coordinates ... - cameraOrientation = Camera.getOrientation(); - handOffset = Vec3.sum(Camera.getPosition(), Vec3.multiplyQbyV(cameraOrientation, handOffset)); - - // Hand offset in avatar coordinates ... - inverseAvatarOrientation = Quat.inverse(MyAvatar.orientation); - handOffset = Vec3.subtract(handOffset, MyAvatar.position); - handOffset = Vec3.multiplyQbyV(inverseAvatarOrientation, handOffset); - handOffset.z = -handOffset.z; - handOffset.x = -handOffset.x; - - - // Hand rotation in camera coordinates ... - handRotation = { - x: -handRotation.y, - y: -handRotation.z, - z: -handRotation.x, - w: handRotation.w - }; - - // Hand rotation in avatar coordinates ... - handRotation = Quat.multiply(HMD_CAMERA_TO_AVATAR_ROTATION[h], handRotation); - cameraOrientation = { - x: cameraOrientation.z, - y: cameraOrientation.y, - z: cameraOrientation.x, - w: cameraOrientation.w - }; - cameraOrientation = Quat.multiply(cameraOrientation, Quat.inverse(MyAvatar.orientation)); - handRotation = Quat.multiply(handRotation, cameraOrientation); // Works!!! - - } else { - - // Adjust to control wrist position if "hand" joint is at wrist ... - if (!hasHandAndWristJoints) { - wristOffset = Vec3.multiplyQbyV(handRotation, handToWristOffset[h]); - handOffset = Vec3.sum(handOffset, wristOffset); - } - - // Hand offset in camera coordinates ... - handOffset = { - x: -handOffset.x, - y: hands[h].zeroPosition.y + handOffset.y, - z: hands[h].zeroPosition.z - handOffset.z - }; - - // Hand rotation in camera coordinates ... - handRotation = { - x: handRotation.z, - y: handRotation.y, - z: handRotation.x, - w: handRotation.w - }; - - // Hand rotation in avatar coordinates ... - handRotation = Quat.multiply(DESKTOP_CAMERA_TO_AVATAR_ROTATION, handRotation); - } - - // Set hand position and orientation for animation state handler ... - hands[h].position = handOffset; - hands[h].rotation = handRotation; - - // Set finger joints ... - var summed = 0; - var closeAngle = 0; - for (i = 0; i < NUM_FINGERS; i += 1) { - for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { - if (fingers[h][i][j].controller !== null) { - locRotation = fingers[h][i][j].controller.getLocRotation(); - var eulers = Quat.safeEulerAngles(locRotation); - closeAngle += eulers.x; - - summed++; - - if (i === THUMB) { - locRotation = { - x: side * locRotation.y, - y: side * -locRotation.z, - z: side * -locRotation.x, - w: locRotation.w - }; - if (j === 0) { - // Adjust avatar thumb root joint rotation to make avatar hands look better - locRotation = Quat.multiply(LEAP_THUMB_ROOT_ADJUST[h], locRotation); - } - } else { - locRotation = { - x: -locRotation.x, - y: -locRotation.z, - z: -locRotation.y, - w: locRotation.w - }; - } - MyAvatar.setJointRotation(fingers[h][i][j].jointName, locRotation); - } - } - } - - hands[h].inactiveCount = 0; - if (summed > 0) { - closeAngle /= summed; - } - - var triggerValue = (-closeAngle - LEAP_TRIGGER_START_ANGLE) / (LEAP_TRIGGER_END_ANGLE - LEAP_TRIGGER_START_ANGLE); - triggerValue = Math.max(0.0, Math.min(triggerValue, 1.0)); - - if (h == 0) { - leftTriggerValue = triggerValue; - } else { - rightTriggerValue = triggerValue; - - } - - } else { - - if (hands[h].inactiveCount < MAX_HAND_INACTIVE_COUNT) { - - hands[h].inactiveCount += 1; - - if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) { - if (handAnimationStateHandlers[h] !== null) { - MyAvatar.removeAnimationStateHandler(handAnimationStateHandlers[h]); - handAnimationStateHandlers[h] = null; - leftTriggerValue = 0.0; - rightTriggerValue = 0.0; - } - } - } - } - } - } - - function tearDown() { - var h, - i, - j; - - Script.clearInterval(settingsTimer); - - for (h = 0; h < NUM_HANDS; h += 1) { - Controller.releaseInputController(hands[h].controller); - Controller.releaseInputController(wrists[h].controller); - if (handAnimationStateHandlers[h] !== null) { - MyAvatar.removeAnimationStateHandler(handAnimationStateHandlers[h]); - } - for (i = 0; i < NUM_FINGERS; i += 1) { - for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { - if (fingers[h][i][j].controller !== null) { - Controller.releaseInputController(fingers[h][i][j].controller); - } - } - } - } - } - - return { - printSkeletonJointNames: printSkeletonJointNames, - setUp : setUp, - moveHands : moveHands, - tearDown : tearDown - }; -}()); - - -//leapHands.printSkeletonJointNames(); - -leapHands.setUp(); -Script.update.connect(leapHands.moveHands); -Script.scriptEnding.connect(leapHands.tearDown); From 9c431a11afd68bc9b506db62e106b8ed739d10ae Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 15 Jun 2017 17:50:07 +1200 Subject: [PATCH 02/22] Set up Leap Motion plugin container --- interface/external/leapmotion/readme.txt | 8 +-- plugins/CMakeLists.txt | 2 + plugins/hifiLeapMotion/CMakeLists.txt | 16 ++++++ .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 25 +++++++++ plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 42 +++++++++++++++ .../hifiLeapMotion/src/LeapMotionProvider.cpp | 51 +++++++++++++++++++ plugins/hifiLeapMotion/src/plugin.json | 1 + 7 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 plugins/hifiLeapMotion/CMakeLists.txt create mode 100644 plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp create mode 100644 plugins/hifiLeapMotion/src/LeapMotionPlugin.h create mode 100644 plugins/hifiLeapMotion/src/LeapMotionProvider.cpp create mode 100644 plugins/hifiLeapMotion/src/plugin.json diff --git a/interface/external/leapmotion/readme.txt b/interface/external/leapmotion/readme.txt index 51a65caf22..97502d694c 100644 --- a/interface/external/leapmotion/readme.txt +++ b/interface/external/leapmotion/readme.txt @@ -10,7 +10,7 @@ Interface has been tested with SDK versions: 1. Copy the LeapSDK folders from the LeapDeveloperKit installation directory (Lib, Include) into the interface/externals/leapmotion folder. This readme.txt should be there as well. - The files neeeded in the folders are: + The files needed in the folders are: include/ - Leap.h @@ -21,8 +21,8 @@ Interface has been tested with SDK versions: x86/ - Leap.dll - Leap.lib - - mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed) - - mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed) + - mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistributable installed) + - mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistributable installed) - lipLeap.dylib libc++/ -libLeap.dylib @@ -30,4 +30,4 @@ Interface has been tested with SDK versions: You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects). If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'leapmotion' that contains the 2 folders mentioned above (Include, Lib). -2. Clear your build directory, run cmake and build, and you should be all set. \ No newline at end of file +2. Clear your build directory, run cmake and build, and you should be all set. diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 82ca2a7d38..06cf929368 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -30,6 +30,8 @@ if (NOT SERVER_ONLY AND NOT ANDROID) add_subdirectory(${DIR}) set(DIR "steamClient") add_subdirectory(${DIR}) + set(DIR "hifiLeapMotion") + add_subdirectory(${DIR}) endif() # server-side plugins diff --git a/plugins/hifiLeapMotion/CMakeLists.txt b/plugins/hifiLeapMotion/CMakeLists.txt new file mode 100644 index 0000000000..ee2fb22f0e --- /dev/null +++ b/plugins/hifiLeapMotion/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Created by David Rowe on 15 Jun 2017. +# Copyright 2017 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html +# + +if (WIN32) + find_package(LEAPMOTION) + if (LEAPMOTION_FOUND) + set(TARGET_NAME hifiLeapMotion) + setup_hifi_plugin(Script Qml Widgets) + link_hifi_libraries(shared controllers ui plugins input-plugins) + endif() +endif() diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp new file mode 100644 index 0000000000..412ff492f9 --- /dev/null +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -0,0 +1,25 @@ +// +// LeapMotionPlugin.cpp +// +// Created by David Rowe on 15 Jun 2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "LeapMotionPlugin.h" + +const char* LeapMotionPlugin::NAME = "Leap Motion"; + +void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + // TODO +} + +controller::Input::NamedVector LeapMotionPlugin::InputDevice::getAvailableInputs() const { + static controller::Input::NamedVector availableInputs; + + // TODO + + return availableInputs; +} diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h new file mode 100644 index 0000000000..f8a4aae173 --- /dev/null +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -0,0 +1,42 @@ +// +// LeapMotionPlugin.h +// +// Created by David Rowe on 15 Jun 2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_LeapMotionPlugin_h +#define hifi_LeapMotionPlugin_h + +#include +#include + +class LeapMotionPlugin : public InputPlugin { + Q_OBJECT + +public: + virtual const QString getName() const override { return NAME; } + + virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + +protected: + static const char* NAME; + + class InputDevice : public controller::InputDevice { + public: + friend class LeapMotionPlugin; + + InputDevice() : controller::InputDevice("Leap Motion") {} + + // Device functions + virtual controller::Input::NamedVector getAvailableInputs() const override; + }; + + std::shared_ptr _inputDevice{ std::make_shared() }; +}; + +#endif // hifi_LeapMotionPlugin_h diff --git a/plugins/hifiLeapMotion/src/LeapMotionProvider.cpp b/plugins/hifiLeapMotion/src/LeapMotionProvider.cpp new file mode 100644 index 0000000000..62517439c3 --- /dev/null +++ b/plugins/hifiLeapMotion/src/LeapMotionProvider.cpp @@ -0,0 +1,51 @@ +// +// LeapMotionProvider.cpp +// +// Created by David Rowe on 15 Jun 2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include +#include + +#include +#include + +#include "LeapMotionPlugin.h" + +class LeapMotionProvider : public QObject, public InputProvider +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json") + Q_INTERFACES(InputProvider) + +public: + LeapMotionProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~LeapMotionProvider() {} + + virtual InputPluginList getInputPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + InputPluginPointer plugin(new LeapMotionPlugin()); + if (plugin->isSupported()) { + _inputPlugins.push_back(plugin); + } + }); + return _inputPlugins; + } + + virtual void destroyInputPlugins() override { + _inputPlugins.clear(); + } + +private: + InputPluginList _inputPlugins; +}; + +#include "LeapMotionProvider.moc" diff --git a/plugins/hifiLeapMotion/src/plugin.json b/plugins/hifiLeapMotion/src/plugin.json new file mode 100644 index 0000000000..2e867d96e4 --- /dev/null +++ b/plugins/hifiLeapMotion/src/plugin.json @@ -0,0 +1 @@ +{"name":"Leap Motion"} From 6b2fbbf5fe9dc646b671292e5949777650914b17 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 16 Jun 2017 10:05:33 +1200 Subject: [PATCH 03/22] Add logging category --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 412ff492f9..e910b8932a 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -10,6 +10,11 @@ #include "LeapMotionPlugin.h" +#include + +Q_DECLARE_LOGGING_CATEGORY(inputplugins) +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") + const char* LeapMotionPlugin::NAME = "Leap Motion"; void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { From 170cf8156f2f0bfe7a0a77eb4852e7ccadfb9e22 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 16 Jun 2017 10:11:08 +1200 Subject: [PATCH 04/22] Add plugin ID --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 1 + plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index e910b8932a..e75019d389 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -16,6 +16,7 @@ Q_DECLARE_LOGGING_CATEGORY(inputplugins) Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") const char* LeapMotionPlugin::NAME = "Leap Motion"; +const char* LeapMotionPlugin::LEAPMOTION_ID_STRING = "Leap Motion"; void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { // TODO diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index f8a4aae173..aae0561e39 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -18,13 +18,17 @@ class LeapMotionPlugin : public InputPlugin { Q_OBJECT public: - virtual const QString getName() const override { return NAME; } - + // InputPlugin methods virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + // Plugin methods + virtual const QString getName() const override { return NAME; } + const QString getID() const override { return LEAPMOTION_ID_STRING; } + protected: static const char* NAME; + static const char* LEAPMOTION_ID_STRING; class InputDevice : public controller::InputDevice { public: From febd0eaf985967b0065872c8db10bde531a1cc0a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 16 Jun 2017 10:58:11 +1200 Subject: [PATCH 05/22] Add Leap Motion settings --- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 72 +++++++++++++++++++ plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 10 +++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 44cae95696..cabc09e49b 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Leap Motion"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index fe043f6ac7..18e7898dd0 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration", "Leap Motion"] } } diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index e75019d389..f9cdf8a958 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -12,12 +12,21 @@ #include +#include +#include +#include + Q_DECLARE_LOGGING_CATEGORY(inputplugins) Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") const char* LeapMotionPlugin::NAME = "Leap Motion"; const char* LeapMotionPlugin::LEAPMOTION_ID_STRING = "Leap Motion"; +const bool DEFAULT_ENABLED = false; +const char* SENSOR_ON_DESKTOP = "Desktop"; +const char* SENSOR_ON_HMD = "HMD"; +const char* DEFAULT_SENSOR_LOCATION = SENSOR_ON_DESKTOP; + void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { // TODO } @@ -29,3 +38,66 @@ controller::Input::NamedVector LeapMotionPlugin::InputDevice::getAvailableInputs return availableInputs; } + +void LeapMotionPlugin::init() { + loadSettings(); + + auto preferences = DependencyManager::get(); + static const QString LEAPMOTION_PLUGIN { "Leap Motion" }; + { + auto getter = [this]()->bool { return _enabled; }; + auto setter = [this](bool value) { + _enabled = value; + saveSettings(); + if (!_enabled) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->withLock([&, this]() { + _inputDevice->clearState(); + }); + } + }; + auto preference = new CheckPreference(LEAPMOTION_PLUGIN, "Enabled", getter, setter); + preferences->addPreference(preference); + } + { + auto getter = [this]()->QString { return _sensorLocation; }; + auto setter = [this](QString value) { + _sensorLocation = value; + saveSettings(); + // TODO: Apply setting value. + }; + auto preference = new ComboBoxPreference(LEAPMOTION_PLUGIN, "Sensor location", getter, setter); + QStringList list = { SENSOR_ON_DESKTOP, SENSOR_ON_HMD }; + preference->setItems(list); + preferences->addPreference(preference); + } +} + +const char* SETTINGS_ENABLED_KEY = "enabled"; +const char* SETTINGS_SENSOR_LOCATION_KEY = "sensorLocation"; + +void LeapMotionPlugin::saveSettings() const { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + settings.setValue(QString(SETTINGS_ENABLED_KEY), _enabled); + settings.setValue(QString(SETTINGS_SENSOR_LOCATION_KEY), _sensorLocation); + } + settings.endGroup(); +} + +void LeapMotionPlugin::loadSettings() { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + _enabled = settings.value(SETTINGS_ENABLED_KEY, QVariant(DEFAULT_ENABLED)).toBool(); + _sensorLocation = settings.value(SETTINGS_SENSOR_LOCATION_KEY, QVariant(DEFAULT_SENSOR_LOCATION)).toString(); + } + settings.endGroup(); +} + +void LeapMotionPlugin::InputDevice::clearState() { + // TODO +} diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index aae0561e39..d6fe6d8a55 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -26,10 +26,18 @@ public: virtual const QString getName() const override { return NAME; } const QString getID() const override { return LEAPMOTION_ID_STRING; } + virtual void init() override; + + virtual void saveSettings() const override; + virtual void loadSettings() override; + protected: static const char* NAME; static const char* LEAPMOTION_ID_STRING; + bool _enabled { false }; + QString _sensorLocation; + class InputDevice : public controller::InputDevice { public: friend class LeapMotionPlugin; @@ -38,6 +46,8 @@ protected: // Device functions virtual controller::Input::NamedVector getAvailableInputs() const override; + + void clearState(); }; std::shared_ptr _inputDevice{ std::make_shared() }; From 2ca4283828183949f020202b315de789abb51264 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 17 Jun 2017 12:02:26 +1200 Subject: [PATCH 06/22] Fix Leap Motion SDK access --- cmake/macros/TargetLeapMotion.cmake | 12 ++++++++++++ plugins/hifiLeapMotion/CMakeLists.txt | 13 ++++++------- plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 3 +++ 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 cmake/macros/TargetLeapMotion.cmake diff --git a/cmake/macros/TargetLeapMotion.cmake b/cmake/macros/TargetLeapMotion.cmake new file mode 100644 index 0000000000..674ec8f62d --- /dev/null +++ b/cmake/macros/TargetLeapMotion.cmake @@ -0,0 +1,12 @@ +# +# Created by David Rowe on 16 Jun 2017. +# Copyright 2017 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html +# + +macro(TARGET_LEAPMOTION) + target_include_directories(${TARGET_NAME} PRIVATE ${LEAPMOTION_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${LEAPMOTION_LIBRARIES}) +endmacro() diff --git a/plugins/hifiLeapMotion/CMakeLists.txt b/plugins/hifiLeapMotion/CMakeLists.txt index ee2fb22f0e..14f9bbaa17 100644 --- a/plugins/hifiLeapMotion/CMakeLists.txt +++ b/plugins/hifiLeapMotion/CMakeLists.txt @@ -6,11 +6,10 @@ # See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html # -if (WIN32) - find_package(LEAPMOTION) - if (LEAPMOTION_FOUND) - set(TARGET_NAME hifiLeapMotion) - setup_hifi_plugin(Script Qml Widgets) - link_hifi_libraries(shared controllers ui plugins input-plugins) - endif() +find_package(LEAPMOTION) +if (LEAPMOTION_FOUND) + set(TARGET_NAME hifiLeapMotion) + setup_hifi_plugin(Script Qml Widgets) + link_hifi_libraries(shared controllers ui plugins input-plugins) + target_leapmotion() endif() diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index d6fe6d8a55..f42d4ccaf5 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -14,6 +14,9 @@ #include #include +// LeapMotion SDK +#include + class LeapMotionPlugin : public InputPlugin { Q_OBJECT From 5de585e3204776cfe20b2c064658fa83bafddfdc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 17 Jun 2017 13:56:44 +1200 Subject: [PATCH 07/22] Leap Motion activation --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 19 +++++++++++++++++++ plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index f9cdf8a958..4d2cc474bd 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -28,6 +28,10 @@ const char* SENSOR_ON_HMD = "HMD"; const char* DEFAULT_SENSOR_LOCATION = SENSOR_ON_DESKTOP; void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + if (!_enabled) { + return; + } + // TODO } @@ -73,6 +77,21 @@ void LeapMotionPlugin::init() { } } +bool LeapMotionPlugin::activate() { + InputPlugin::activate(); + + if (_enabled) { + // Nothing required to be done to start up Leap Motion. + return true; + } + + return false; +} + +void LeapMotionPlugin::deactivate() { + InputPlugin::deactivate(); +} + const char* SETTINGS_ENABLED_KEY = "enabled"; const char* SETTINGS_SENSOR_LOCATION_KEY = "sensorLocation"; diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index f42d4ccaf5..60b476a443 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -31,6 +31,9 @@ public: virtual void init() override; + virtual bool activate() override; + virtual void deactivate() override; + virtual void saveSettings() const override; virtual void loadSettings() override; @@ -54,6 +57,10 @@ protected: }; std::shared_ptr _inputDevice{ std::make_shared() }; + +private: + Leap::Controller _controller; + }; #endif // hifi_LeapMotionPlugin_h From 8d84e86d193d5c13c81693b5b2fa2bdf67f48b3e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 17 Jun 2017 13:57:43 +1200 Subject: [PATCH 08/22] Apply sensor location setting --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 11 ++++++++++- plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 4d2cc474bd..34913cb415 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -68,7 +68,7 @@ void LeapMotionPlugin::init() { auto setter = [this](QString value) { _sensorLocation = value; saveSettings(); - // TODO: Apply setting value. + applySensorLocation(); }; auto preference = new ComboBoxPreference(LEAPMOTION_PLUGIN, "Sensor location", getter, setter); QStringList list = { SENSOR_ON_DESKTOP, SENSOR_ON_HMD }; @@ -113,6 +113,7 @@ void LeapMotionPlugin::loadSettings() { { _enabled = settings.value(SETTINGS_ENABLED_KEY, QVariant(DEFAULT_ENABLED)).toBool(); _sensorLocation = settings.value(SETTINGS_SENSOR_LOCATION_KEY, QVariant(DEFAULT_SENSOR_LOCATION)).toString(); + applySensorLocation(); } settings.endGroup(); } @@ -120,3 +121,11 @@ void LeapMotionPlugin::loadSettings() { void LeapMotionPlugin::InputDevice::clearState() { // TODO } + +void LeapMotionPlugin::applySensorLocation() { + if (_sensorLocation == SENSOR_ON_HMD) { + _controller.setPolicyFlags(Leap::Controller::POLICY_OPTIMIZE_HMD); + } else { + _controller.setPolicyFlags(Leap::Controller::POLICY_DEFAULT); + } +} diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index 60b476a443..7db4f4d8d7 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -59,6 +59,8 @@ protected: std::shared_ptr _inputDevice{ std::make_shared() }; private: + void applySensorLocation(); + Leap::Controller _controller; }; From 0d986b8dc26073b3c2ddb12e30c7886ff4e3e4ba Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 17 Jun 2017 14:43:32 +1200 Subject: [PATCH 09/22] Signal when Leap Motion is connected --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 14 ++++++++++++++ plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 34913cb415..b60c2f69cf 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -32,7 +32,21 @@ void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCali return; } + const auto frame = _controller.frame(); + const auto frameID = frame.id(); + if (_lastFrameID >= frameID) { + // Leap Motion not connected or duplicate frame. + return; + } + + if (!_hasLeapMotionBeenConnected) { + emit deviceConnected(getName()); + _hasLeapMotionBeenConnected = true; + } + // TODO + + _lastFrameID = frameID; } controller::Input::NamedVector LeapMotionPlugin::InputDevice::getAvailableInputs() const { diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index 7db4f4d8d7..ed5a3c94fe 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -63,6 +63,8 @@ private: Leap::Controller _controller; + bool _hasLeapMotionBeenConnected { false }; + int64_t _lastFrameID { -1 }; }; #endif // hifi_LeapMotionPlugin_h From 5b6a5525b66cd4bb7dd8790beb8d0bfb69f45e42 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 18 Jun 2017 13:03:54 +1200 Subject: [PATCH 10/22] Initial control of avatar hand positions --- .../resources/controllers/leapmotion.json | 7 + .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 216 +++++++++++++++++- plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 23 +- 3 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 interface/resources/controllers/leapmotion.json diff --git a/interface/resources/controllers/leapmotion.json b/interface/resources/controllers/leapmotion.json new file mode 100644 index 0000000000..2ee4c98009 --- /dev/null +++ b/interface/resources/controllers/leapmotion.json @@ -0,0 +1,7 @@ +{ + "name": "Leap Motion to Standard", + "channels": [ + { "from": "LeapMotion.LeftHand", "to": "Standard.LeftHand" }, + { "from": "LeapMotion.RightHand", "to": "Standard.RightHand" } + ] +} diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index b60c2f69cf..435f3ed03b 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -13,6 +13,8 @@ #include #include +#include +#include #include #include @@ -27,6 +29,100 @@ const char* SENSOR_ON_DESKTOP = "Desktop"; const char* SENSOR_ON_HMD = "HMD"; const char* DEFAULT_SENSOR_LOCATION = SENSOR_ON_DESKTOP; +enum LeapMotionJointIndex { + LeftHand = 0, + RightHand, + Size +}; + +static controller::StandardPoseChannel LeapMotionJointIndexToPoseIndexMap[LeapMotionJointIndex::Size] = { + controller::LEFT_HAND, + controller::RIGHT_HAND +}; + +#define UNKNOWN_JOINT (controller::StandardPoseChannel)0 + +static controller::StandardPoseChannel LeapMotionJointIndexToPoseIndex(LeapMotionJointIndex i) { + assert(i >= 0 && i < LeapMotionJointIndex::Size); + if (i >= 0 && i < LeapMotionJointIndex::Size) { + return LeapMotionJointIndexToPoseIndexMap[i]; + } else { + return UNKNOWN_JOINT; + } +} + +QStringList controllerJointNames = { + "Hips", + "RightUpLeg", + "RightLeg", + "RightFoot", + "LeftUpLeg", + "LeftLeg", + "LeftFoot", + "Spine", + "Spine1", + "Spine2", + "Spine3", + "Neck", + "Head", + "RightShoulder", + "RightArm", + "RightForeArm", + "RightHand", + "RightHandThumb1", + "RightHandThumb2", + "RightHandThumb3", + "RightHandThumb4", + "RightHandIndex1", + "RightHandIndex2", + "RightHandIndex3", + "RightHandIndex4", + "RightHandMiddle1", + "RightHandMiddle2", + "RightHandMiddle3", + "RightHandMiddle4", + "RightHandRing1", + "RightHandRing2", + "RightHandRing3", + "RightHandRing4", + "RightHandPinky1", + "RightHandPinky2", + "RightHandPinky3", + "RightHandPinky4", + "LeftShoulder", + "LeftArm", + "LeftForeArm", + "LeftHand", + "LeftHandThumb1", + "LeftHandThumb2", + "LeftHandThumb3", + "LeftHandThumb4", + "LeftHandIndex1", + "LeftHandIndex2", + "LeftHandIndex3", + "LeftHandIndex4", + "LeftHandMiddle1", + "LeftHandMiddle2", + "LeftHandMiddle3", + "LeftHandMiddle4", + "LeftHandRing1", + "LeftHandRing2", + "LeftHandRing3", + "LeftHandRing4", + "LeftHandPinky1", + "LeftHandPinky2", + "LeftHandPinky3", + "LeftHandPinky4" +}; + +static const char* getControllerJointName(controller::StandardPoseChannel i) { + if (i >= 0 && i < controller::NUM_STANDARD_POSES) { + return qPrintable(controllerJointNames[i]); + } + return "unknown"; +} + + void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { if (!_enabled) { return; @@ -44,19 +140,68 @@ void LeapMotionPlugin::pluginUpdate(float deltaTime, const controller::InputCali _hasLeapMotionBeenConnected = true; } - // TODO + processFrame(frame); // Updates _joints. + + auto joints = _joints; + + auto userInputMapper = DependencyManager::get(); + userInputMapper->withLock([&, this]() { + _inputDevice->update(deltaTime, inputCalibrationData, joints, _prevJoints); + }); + + _prevJoints = joints; _lastFrameID = frameID; } controller::Input::NamedVector LeapMotionPlugin::InputDevice::getAvailableInputs() const { static controller::Input::NamedVector availableInputs; - - // TODO - + if (availableInputs.size() == 0) { + for (int i = 0; i < LeapMotionJointIndex::Size; i++) { + auto channel = LeapMotionJointIndexToPoseIndex(static_cast(i)); + availableInputs.push_back(makePair(channel, getControllerJointName(channel))); + } + }; return availableInputs; } +QString LeapMotionPlugin::InputDevice::getDefaultMappingConfig() const { + static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/leapmotion.json"; + return MAPPING_JSON; +} + +void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, + const std::vector& joints, + const std::vector& prevJoints) { + + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + glm::quat controllerToAvatarRotation = glmExtractRotation(controllerToAvatar); + + for (size_t i = 0; i < joints.size(); i++) { + int poseIndex = LeapMotionJointIndexToPoseIndex((LeapMotionJointIndex)i); + glm::vec3 linearVelocity, angularVelocity; + + // TODO: Adjust the position to be avatar relative for desktop or HMD-relative, and rotated to match avatar rotation. + const glm::vec3& pos = controllerToAvatarRotation * joints[i].position; + + if (pos == Vectors::ZERO) { + _poseStateMap[poseIndex] = controller::Pose(); + continue; + } + + glm::quat rot = controllerToAvatarRotation * joints[i].orientation; + + if (i < prevJoints.size()) { + linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s + // quat log imaginary part points along the axis of rotation, with length of one half the angle of rotation. + glm::quat d = glm::log(rot * glm::inverse(prevJoints[i].orientation)); + angularVelocity = glm::vec3(d.x, d.y, d.z) / (0.5f * deltaTime); // radians/s + } + + _poseStateMap[poseIndex] = controller::Pose(pos, rot, linearVelocity, angularVelocity); + } +} + void LeapMotionPlugin::init() { loadSettings(); @@ -96,6 +241,14 @@ bool LeapMotionPlugin::activate() { if (_enabled) { // Nothing required to be done to start up Leap Motion. + + auto userInputMapper = DependencyManager::get(); + userInputMapper->registerDevice(_inputDevice); + + if (_joints.size() != LeapMotionJointIndex::Size) { + _joints.resize(LeapMotionJointIndex::Size, { glm::vec3(), glm::quat() }); + } + return true; } @@ -103,6 +256,11 @@ bool LeapMotionPlugin::activate() { } void LeapMotionPlugin::deactivate() { + if (_inputDevice->_deviceID != controller::Input::INVALID_DEVICE) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->removeDevice(_inputDevice->_deviceID); + } + InputPlugin::deactivate(); } @@ -133,7 +291,10 @@ void LeapMotionPlugin::loadSettings() { } void LeapMotionPlugin::InputDevice::clearState() { - // TODO + for (size_t i = 0; i < LeapMotionJointIndex::Size; i++) { + int poseIndex = LeapMotionJointIndexToPoseIndex((LeapMotionJointIndex)i); + _poseStateMap[poseIndex] = controller::Pose(); + } } void LeapMotionPlugin::applySensorLocation() { @@ -143,3 +304,48 @@ void LeapMotionPlugin::applySensorLocation() { _controller.setPolicyFlags(Leap::Controller::POLICY_DEFAULT); } } + +glm::quat LeapBasisToQuat(float sideSign, const Leap::Matrix& basis) { + glm::vec3 xAxis = glm::normalize(sideSign * glm::vec3(basis.xBasis.x, basis.xBasis.y, basis.xBasis.z)); + glm::vec3 yAxis = glm::normalize(glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z)); + glm::vec3 zAxis = glm::normalize(glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z)); + xAxis = glm::normalize(glm::cross(yAxis, zAxis)); + glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); + return orientation; +} + +glm::vec3 LeapVectorToVec3(const Leap::Vector& vec) { + return glm::vec3(vec.x * METERS_PER_MILLIMETER, vec.y * METERS_PER_MILLIMETER, vec.z * METERS_PER_MILLIMETER); +} + +void LeapMotionPlugin::processFrame(const Leap::Frame& frame) { + + // TODO + + auto hands = frame.hands(); + if (hands.count() == 2) { + auto hand = hands[0]; + auto arm = hand.arm(); + /* + _joints[LeapMotionJointIndex::LeftElbow].position = LeapVectorToVec3(arm.elbowPosition()); + _joints[LeapMotionJointIndex::LeftElbow].orientation = LeapBasisToQuat(-1.f, arm.basis()); + _joints[LeapMotionJointIndex::LeftWrist].position = LeapVectorToVec3(arm.wristPosition()); + _joints[LeapMotionJointIndex::LeftWrist].orientation = LeapBasisToQuat(-1.f, arm.basis()); + */ + _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::LeftHand].orientation = LeapBasisToQuat(-1.0f, hand.basis()); + + hand = hands[1]; + arm = hand.arm(); + /* + _joints[LeapMotionJointIndex::RightElbow].position = LeapVectorToVec3(arm.elbowPosition()); + _joints[LeapMotionJointIndex::RightElbow].orientation = LeapBasisToQuat(1.f, arm.basis()); + _joints[LeapMotionJointIndex::RightWrist].position = LeapVectorToVec3(arm.wristPosition()); + _joints[LeapMotionJointIndex::RightWrist].orientation = LeapBasisToQuat(1.f, arm.basis()); + */ + _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::RightHand].orientation = LeapBasisToQuat(1.0f, hand.basis()); + } + +} + diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index ed5a3c94fe..5e9e0da42b 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -25,6 +25,8 @@ public: virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } virtual void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + bool isHandController() const override { return true; } + // Plugin methods virtual const QString getName() const override { return NAME; } const QString getID() const override { return LEAPMOTION_ID_STRING; } @@ -44,23 +46,40 @@ protected: bool _enabled { false }; QString _sensorLocation; + struct LeapMotionJoint { + glm::vec3 position; + glm::quat orientation; + }; + + std::vector _joints; + std::vector _prevJoints; + class InputDevice : public controller::InputDevice { public: friend class LeapMotionPlugin; - InputDevice() : controller::InputDevice("Leap Motion") {} + InputDevice() : controller::InputDevice("LeapMotion") {} // Device functions virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const override; + virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override {}; + virtual void focusOutEvent() override {}; + + void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, + const std::vector& joints, + const std::vector& prevJoints); void clearState(); }; - std::shared_ptr _inputDevice{ std::make_shared() }; + std::shared_ptr _inputDevice { std::make_shared() }; private: void applySensorLocation(); + void processFrame(const Leap::Frame& frame); + Leap::Controller _controller; bool _hasLeapMotionBeenConnected { false }; From 2d1cc12bc5f5bafdff45cf9058b976efef643a63 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 18 Jun 2017 16:40:55 +1200 Subject: [PATCH 11/22] Desktop hand positions and orientations --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 435f3ed03b..4a6ccb9b9b 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -177,20 +177,25 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; glm::quat controllerToAvatarRotation = glmExtractRotation(controllerToAvatar); + // Desktop "zero" position is some distance above the Leap Motion sensor and half the avatar's shoulder-to-hand length in + // front of avatar. + float halfShouldToHandLength = fabsf(extractTranslation(inputCalibrationData.defaultLeftHand).x + - extractTranslation(inputCalibrationData.defaultLeftArm).x) / 2.0f; + const float ZERO_HEIGHT_OFFSET = 0.2f; + glm::vec3 leapMotionOffset = glm::vec3(0.0f, ZERO_HEIGHT_OFFSET, halfShouldToHandLength); + for (size_t i = 0; i < joints.size(); i++) { int poseIndex = LeapMotionJointIndexToPoseIndex((LeapMotionJointIndex)i); - glm::vec3 linearVelocity, angularVelocity; - // TODO: Adjust the position to be avatar relative for desktop or HMD-relative, and rotated to match avatar rotation. - const glm::vec3& pos = controllerToAvatarRotation * joints[i].position; - - if (pos == Vectors::ZERO) { + if (joints[i].position == Vectors::ZERO) { _poseStateMap[poseIndex] = controller::Pose(); continue; } + const glm::vec3& pos = controllerToAvatarRotation * (joints[i].position - leapMotionOffset); glm::quat rot = controllerToAvatarRotation * joints[i].orientation; + glm::vec3 linearVelocity, angularVelocity; if (i < prevJoints.size()) { linearVelocity = (pos - (prevJoints[i].position * METERS_PER_CENTIMETER)) / deltaTime; // m/s // quat log imaginary part points along the axis of rotation, with length of one half the angle of rotation. @@ -305,13 +310,16 @@ void LeapMotionPlugin::applySensorLocation() { } } +const float LEFT_SIDE_SIGN = -1.0f; +const float RIGHT_SIDE_SIGN = 1.0f; + glm::quat LeapBasisToQuat(float sideSign, const Leap::Matrix& basis) { - glm::vec3 xAxis = glm::normalize(sideSign * glm::vec3(basis.xBasis.x, basis.xBasis.y, basis.xBasis.z)); - glm::vec3 yAxis = glm::normalize(glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z)); - glm::vec3 zAxis = glm::normalize(glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z)); - xAxis = glm::normalize(glm::cross(yAxis, zAxis)); + glm::vec3 xAxis = sideSign * glm::vec3(basis.xBasis.x, basis.xBasis.y, basis.xBasis.z); + glm::vec3 yAxis = glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z); + glm::vec3 zAxis = glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z); glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); - return orientation; + const glm::quat ZERO_HAND_ORIENTATION = glm::quat(glm::vec3(PI_OVER_TWO, PI, 0.0f)); + return orientation * ZERO_HAND_ORIENTATION; } glm::vec3 LeapVectorToVec3(const Leap::Vector& vec) { @@ -319,33 +327,23 @@ glm::vec3 LeapVectorToVec3(const Leap::Vector& vec) { } void LeapMotionPlugin::processFrame(const Leap::Frame& frame) { - - // TODO + // Default to uncontrolled. + _joints[LeapMotionJointIndex::LeftHand].position = glm::vec3(); + _joints[LeapMotionJointIndex::RightHand].position = glm::vec3(); auto hands = frame.hands(); - if (hands.count() == 2) { - auto hand = hands[0]; + + for (int i = 0; i < hands.count() && i < 2; i++) { + auto hand = hands[i]; auto arm = hand.arm(); - /* - _joints[LeapMotionJointIndex::LeftElbow].position = LeapVectorToVec3(arm.elbowPosition()); - _joints[LeapMotionJointIndex::LeftElbow].orientation = LeapBasisToQuat(-1.f, arm.basis()); - _joints[LeapMotionJointIndex::LeftWrist].position = LeapVectorToVec3(arm.wristPosition()); - _joints[LeapMotionJointIndex::LeftWrist].orientation = LeapBasisToQuat(-1.f, arm.basis()); - */ - _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.palmPosition()); - _joints[LeapMotionJointIndex::LeftHand].orientation = LeapBasisToQuat(-1.0f, hand.basis()); - hand = hands[1]; - arm = hand.arm(); - /* - _joints[LeapMotionJointIndex::RightElbow].position = LeapVectorToVec3(arm.elbowPosition()); - _joints[LeapMotionJointIndex::RightElbow].orientation = LeapBasisToQuat(1.f, arm.basis()); - _joints[LeapMotionJointIndex::RightWrist].position = LeapVectorToVec3(arm.wristPosition()); - _joints[LeapMotionJointIndex::RightWrist].orientation = LeapBasisToQuat(1.f, arm.basis()); - */ - _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.palmPosition()); - _joints[LeapMotionJointIndex::RightHand].orientation = LeapBasisToQuat(1.0f, hand.basis()); + if (hands[i].isLeft()) { + _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::LeftHand].orientation = LeapBasisToQuat(LEFT_SIDE_SIGN, hand.basis()); + } else { + _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::RightHand].orientation = LeapBasisToQuat(RIGHT_SIDE_SIGN, hand.basis()); + } } - } From deae33fd1e6198854b9464bd605a2aed13b4b5f6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 18 Jun 2017 17:43:52 +1200 Subject: [PATCH 12/22] Add setting for desktop "zero" height offset --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 30 +++++++++++++++++-- plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 8 +++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 4a6ccb9b9b..6fd94c0ed0 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -181,8 +181,7 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In // front of avatar. float halfShouldToHandLength = fabsf(extractTranslation(inputCalibrationData.defaultLeftHand).x - extractTranslation(inputCalibrationData.defaultLeftArm).x) / 2.0f; - const float ZERO_HEIGHT_OFFSET = 0.2f; - glm::vec3 leapMotionOffset = glm::vec3(0.0f, ZERO_HEIGHT_OFFSET, halfShouldToHandLength); + glm::vec3 leapMotionOffset = glm::vec3(0.0f, _desktopHeightOffset, halfShouldToHandLength); for (size_t i = 0; i < joints.size(); i++) { int poseIndex = LeapMotionJointIndexToPoseIndex((LeapMotionJointIndex)i); @@ -239,6 +238,24 @@ void LeapMotionPlugin::init() { preference->setItems(list); preferences->addPreference(preference); } + { + auto getter = [this]()->float { return _desktopHeightOffset; }; + auto setter = [this](float value) { + _desktopHeightOffset = value; + saveSettings(); + applyDesktopHeightOffset(); + }; + auto preference = new SpinnerPreference(LEAPMOTION_PLUGIN, "Desktop height offset", getter, setter); + float MIN_VALUE = 0.0f; + float MAX_VALUE = 1.0f; + float DECIMALS = 2.0f; + float STEP = 0.01f; + preference->setMin(MIN_VALUE); + preference->setMax(MAX_VALUE); + preference->setDecimals(DECIMALS); + preference->setStep(STEP); + preferences->addPreference(preference); + } } bool LeapMotionPlugin::activate() { @@ -271,6 +288,7 @@ void LeapMotionPlugin::deactivate() { const char* SETTINGS_ENABLED_KEY = "enabled"; const char* SETTINGS_SENSOR_LOCATION_KEY = "sensorLocation"; +const char* SETTINGS_DESKTOP_HEIGHT_OFFSET_KEY = "desktopHeightOffset"; void LeapMotionPlugin::saveSettings() const { Settings settings; @@ -279,6 +297,7 @@ void LeapMotionPlugin::saveSettings() const { { settings.setValue(QString(SETTINGS_ENABLED_KEY), _enabled); settings.setValue(QString(SETTINGS_SENSOR_LOCATION_KEY), _sensorLocation); + settings.setValue(QString(SETTINGS_DESKTOP_HEIGHT_OFFSET_KEY), _desktopHeightOffset); } settings.endGroup(); } @@ -290,7 +309,10 @@ void LeapMotionPlugin::loadSettings() { { _enabled = settings.value(SETTINGS_ENABLED_KEY, QVariant(DEFAULT_ENABLED)).toBool(); _sensorLocation = settings.value(SETTINGS_SENSOR_LOCATION_KEY, QVariant(DEFAULT_SENSOR_LOCATION)).toString(); + _desktopHeightOffset = + settings.value(SETTINGS_DESKTOP_HEIGHT_OFFSET_KEY, QVariant(DEFAULT_DESKTOP_HEIGHT_OFFSET)).toFloat(); applySensorLocation(); + applyDesktopHeightOffset(); } settings.endGroup(); } @@ -310,6 +332,10 @@ void LeapMotionPlugin::applySensorLocation() { } } +void LeapMotionPlugin::applyDesktopHeightOffset() { + _inputDevice->setDektopHeightOffset(_desktopHeightOffset); +} + const float LEFT_SIDE_SIGN = -1.0f; const float RIGHT_SIDE_SIGN = 1.0f; diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index 5e9e0da42b..a089bcf87d 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -42,9 +42,11 @@ public: protected: static const char* NAME; static const char* LEAPMOTION_ID_STRING; + const float DEFAULT_DESKTOP_HEIGHT_OFFSET = 0.2f; bool _enabled { false }; QString _sensorLocation; + float _desktopHeightOffset { DEFAULT_DESKTOP_HEIGHT_OFFSET }; struct LeapMotionJoint { glm::vec3 position; @@ -71,12 +73,18 @@ protected: const std::vector& prevJoints); void clearState(); + + void setDektopHeightOffset(float desktopHeightOffset) { _desktopHeightOffset = desktopHeightOffset; }; + + private: + float _desktopHeightOffset { 0.0f }; }; std::shared_ptr _inputDevice { std::make_shared() }; private: void applySensorLocation(); + void applyDesktopHeightOffset(); void processFrame(const Leap::Frame& frame); From cacc89e8b647e3f28b7d181d4f2c07fe71e69e0b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 19 Jun 2017 17:21:44 +1200 Subject: [PATCH 13/22] HMD hand positions and orientations --- .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 48 +++++++++++++------ plugins/hifiLeapMotion/src/LeapMotionPlugin.h | 2 + 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 6fd94c0ed0..cd406f2676 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -177,11 +177,19 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; glm::quat controllerToAvatarRotation = glmExtractRotation(controllerToAvatar); - // Desktop "zero" position is some distance above the Leap Motion sensor and half the avatar's shoulder-to-hand length in - // front of avatar. - float halfShouldToHandLength = fabsf(extractTranslation(inputCalibrationData.defaultLeftHand).x - - extractTranslation(inputCalibrationData.defaultLeftArm).x) / 2.0f; - glm::vec3 leapMotionOffset = glm::vec3(0.0f, _desktopHeightOffset, halfShouldToHandLength); + glm::vec3 hmdSensorPosition; // HMD + glm::quat hmdSensorOrientation; // HMD + glm::vec3 leapMotionOffset; // Desktop + if (_isLeapOnHMD) { + hmdSensorPosition = extractTranslation(inputCalibrationData.hmdSensorMat); + hmdSensorOrientation = extractRotation(inputCalibrationData.hmdSensorMat); + } else { + // Desktop "zero" position is some distance above the Leap Motion sensor and half the avatar's shoulder-to-hand length + // in front of avatar. + float halfShouldToHandLength = fabsf(extractTranslation(inputCalibrationData.defaultLeftHand).x + - extractTranslation(inputCalibrationData.defaultLeftArm).x) / 2.0f; + leapMotionOffset = glm::vec3(0.0f, _desktopHeightOffset, halfShouldToHandLength); + } for (size_t i = 0; i < joints.size(); i++) { int poseIndex = LeapMotionJointIndexToPoseIndex((LeapMotionJointIndex)i); @@ -191,8 +199,23 @@ void LeapMotionPlugin::InputDevice::update(float deltaTime, const controller::In continue; } - const glm::vec3& pos = controllerToAvatarRotation * (joints[i].position - leapMotionOffset); - glm::quat rot = controllerToAvatarRotation * joints[i].orientation; + glm::vec3 pos; + glm::quat rot; + if (_isLeapOnHMD) { + auto jointPosition = joints[i].position; + const glm::vec3 HMD_EYE_TO_LEAP_OFFSET = glm::vec3(0.0f, 0.0f, -0.09f); // Eyes to surface of Leap Motion. + jointPosition = glm::vec3(-jointPosition.x, -jointPosition.z, -jointPosition.y) + HMD_EYE_TO_LEAP_OFFSET; + jointPosition = hmdSensorPosition + hmdSensorOrientation * jointPosition; + pos = transformPoint(controllerToAvatar, jointPosition); + + glm::quat jointOrientation = joints[i].orientation; + jointOrientation = glm::quat(jointOrientation.w, -jointOrientation.x, -jointOrientation.z, -jointOrientation.y); + rot = controllerToAvatarRotation * hmdSensorOrientation * jointOrientation; + } else { + pos = controllerToAvatarRotation * (joints[i].position - leapMotionOffset); + const glm::quat ZERO_HAND_ORIENTATION = glm::quat(glm::vec3(PI_OVER_TWO, PI, 0.0f)); + rot = controllerToAvatarRotation * joints[i].orientation * ZERO_HAND_ORIENTATION; + } glm::vec3 linearVelocity, angularVelocity; if (i < prevJoints.size()) { @@ -325,11 +348,9 @@ void LeapMotionPlugin::InputDevice::clearState() { } void LeapMotionPlugin::applySensorLocation() { - if (_sensorLocation == SENSOR_ON_HMD) { - _controller.setPolicyFlags(Leap::Controller::POLICY_OPTIMIZE_HMD); - } else { - _controller.setPolicyFlags(Leap::Controller::POLICY_DEFAULT); - } + bool isLeapOnHMD = _sensorLocation == SENSOR_ON_HMD; + _controller.setPolicyFlags(isLeapOnHMD ? Leap::Controller::POLICY_OPTIMIZE_HMD : Leap::Controller::POLICY_DEFAULT); + _inputDevice->setIsLeapOnHMD(isLeapOnHMD); } void LeapMotionPlugin::applyDesktopHeightOffset() { @@ -344,8 +365,7 @@ glm::quat LeapBasisToQuat(float sideSign, const Leap::Matrix& basis) { glm::vec3 yAxis = glm::vec3(basis.yBasis.x, basis.yBasis.y, basis.yBasis.z); glm::vec3 zAxis = glm::vec3(basis.zBasis.x, basis.zBasis.y, basis.zBasis.z); glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); - const glm::quat ZERO_HAND_ORIENTATION = glm::quat(glm::vec3(PI_OVER_TWO, PI, 0.0f)); - return orientation * ZERO_HAND_ORIENTATION; + return orientation; } glm::vec3 LeapVectorToVec3(const Leap::Vector& vec) { diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h index a089bcf87d..391d569567 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.h +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.h @@ -75,9 +75,11 @@ protected: void clearState(); void setDektopHeightOffset(float desktopHeightOffset) { _desktopHeightOffset = desktopHeightOffset; }; + void setIsLeapOnHMD(bool isLeapOnHMD) { _isLeapOnHMD = isLeapOnHMD; }; private: float _desktopHeightOffset { 0.0f }; + bool _isLeapOnHMD { false }; }; std::shared_ptr _inputDevice { std::make_shared() }; From 61bb853cdd2e37a5afcd1018fead287d3e0831a2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 19 Jun 2017 17:26:55 +1200 Subject: [PATCH 14/22] Fix hand position --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index cd406f2676..35e2f8d8e0 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -384,10 +384,10 @@ void LeapMotionPlugin::processFrame(const Leap::Frame& frame) { auto arm = hand.arm(); if (hands[i].isLeft()) { - _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.wristPosition()); _joints[LeapMotionJointIndex::LeftHand].orientation = LeapBasisToQuat(LEFT_SIDE_SIGN, hand.basis()); } else { - _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.palmPosition()); + _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.wristPosition()); _joints[LeapMotionJointIndex::RightHand].orientation = LeapBasisToQuat(RIGHT_SIDE_SIGN, hand.basis()); } } From 3bdf267900f44f3c0cef2d24cf53279cba5738ac Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Jun 2017 23:32:06 +1200 Subject: [PATCH 15/22] Implement fingers control --- .../resources/controllers/leapmotion.json | 43 +++- interface/resources/controllers/standard.json | 41 ++++ interface/src/Application.cpp | 10 + interface/src/avatar/MyAvatar.cpp | 13 ++ interface/src/avatar/MyAvatar.h | 7 + interface/src/avatar/MySkeletonModel.cpp | 195 +++++++++++++++++- .../controllers/src/controllers/Actions.cpp | 42 ++++ .../controllers/src/controllers/Actions.h | 41 ++++ .../src/controllers/StandardController.cpp | 40 ++++ .../hifiLeapMotion/src/LeapMotionPlugin.cpp | 128 ++++++++++-- 10 files changed, 546 insertions(+), 14 deletions(-) diff --git a/interface/resources/controllers/leapmotion.json b/interface/resources/controllers/leapmotion.json index 2ee4c98009..25cb575946 100644 --- a/interface/resources/controllers/leapmotion.json +++ b/interface/resources/controllers/leapmotion.json @@ -2,6 +2,47 @@ "name": "Leap Motion to Standard", "channels": [ { "from": "LeapMotion.LeftHand", "to": "Standard.LeftHand" }, - { "from": "LeapMotion.RightHand", "to": "Standard.RightHand" } + { "from": "LeapMotion.LeftHandThumb1", "to": "Standard.LeftHandThumb1"}, + { "from": "LeapMotion.LeftHandThumb2", "to": "Standard.LeftHandThumb2"}, + { "from": "LeapMotion.LeftHandThumb3", "to": "Standard.LeftHandThumb3"}, + { "from": "LeapMotion.LeftHandThumb4", "to": "Standard.LeftHandThumb4"}, + { "from": "LeapMotion.LeftHandIndex1", "to": "Standard.LeftHandIndex1"}, + { "from": "LeapMotion.LeftHandIndex2", "to": "Standard.LeftHandIndex2"}, + { "from": "LeapMotion.LeftHandIndex3", "to": "Standard.LeftHandIndex3"}, + { "from": "LeapMotion.LeftHandIndex4", "to": "Standard.LeftHandIndex4"}, + { "from": "LeapMotion.LeftHandMiddle1", "to": "Standard.LeftHandMiddle1"}, + { "from": "LeapMotion.LeftHandMiddle2", "to": "Standard.LeftHandMiddle2"}, + { "from": "LeapMotion.LeftHandMiddle3", "to": "Standard.LeftHandMiddle3"}, + { "from": "LeapMotion.LeftHandMiddle4", "to": "Standard.LeftHandMiddle4"}, + { "from": "LeapMotion.LeftHandRing1", "to": "Standard.LeftHandRing1"}, + { "from": "LeapMotion.LeftHandRing2", "to": "Standard.LeftHandRing2"}, + { "from": "LeapMotion.LeftHandRing3", "to": "Standard.LeftHandRing3"}, + { "from": "LeapMotion.LeftHandRing4", "to": "Standard.LeftHandRing4"}, + { "from": "LeapMotion.LeftHandPinky1", "to": "Standard.LeftHandPinky1"}, + { "from": "LeapMotion.LeftHandPinky2", "to": "Standard.LeftHandPinky2"}, + { "from": "LeapMotion.LeftHandPinky3", "to": "Standard.LeftHandPinky3"}, + { "from": "LeapMotion.LeftHandPinky4", "to": "Standard.LeftHandPinky4"}, + + { "from": "LeapMotion.RightHand", "to": "Standard.RightHand" }, + { "from": "LeapMotion.RightHandThumb1", "to": "Standard.RightHandThumb1"}, + { "from": "LeapMotion.RightHandThumb2", "to": "Standard.RightHandThumb2"}, + { "from": "LeapMotion.RightHandThumb3", "to": "Standard.RightHandThumb3"}, + { "from": "LeapMotion.RightHandThumb4", "to": "Standard.RightHandThumb4"}, + { "from": "LeapMotion.RightHandIndex1", "to": "Standard.RightHandIndex1"}, + { "from": "LeapMotion.RightHandIndex2", "to": "Standard.RightHandIndex2"}, + { "from": "LeapMotion.RightHandIndex3", "to": "Standard.RightHandIndex3"}, + { "from": "LeapMotion.RightHandIndex4", "to": "Standard.RightHandIndex4"}, + { "from": "LeapMotion.RightHandMiddle1", "to": "Standard.RightHandMiddle1"}, + { "from": "LeapMotion.RightHandMiddle2", "to": "Standard.RightHandMiddle2"}, + { "from": "LeapMotion.RightHandMiddle3", "to": "Standard.RightHandMiddle3"}, + { "from": "LeapMotion.RightHandMiddle4", "to": "Standard.RightHandMiddle4"}, + { "from": "LeapMotion.RightHandRing1", "to": "Standard.RightHandRing1"}, + { "from": "LeapMotion.RightHandRing2", "to": "Standard.RightHandRing2"}, + { "from": "LeapMotion.RightHandRing3", "to": "Standard.RightHandRing3"}, + { "from": "LeapMotion.RightHandRing4", "to": "Standard.RightHandRing4"}, + { "from": "LeapMotion.RightHandPinky1", "to": "Standard.RightHandPinky1"}, + { "from": "LeapMotion.RightHandPinky2", "to": "Standard.RightHandPinky2"}, + { "from": "LeapMotion.RightHandPinky3", "to": "Standard.RightHandPinky3"}, + { "from": "LeapMotion.RightHandPinky4", "to": "Standard.RightHandPinky4"} ] } diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 75b4821118..166f1a6869 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -58,7 +58,48 @@ { "from": "Standard.RT", "to": "Actions.RightHandClick" }, { "from": "Standard.LeftHand", "to": "Actions.LeftHand" }, + { "from": "Standard.LeftHandThumb1", "to": "Actions.LeftHandThumb1"}, + { "from": "Standard.LeftHandThumb2", "to": "Actions.LeftHandThumb2"}, + { "from": "Standard.LeftHandThumb3", "to": "Actions.LeftHandThumb3"}, + { "from": "Standard.LeftHandThumb4", "to": "Actions.LeftHandThumb4"}, + { "from": "Standard.LeftHandIndex1", "to": "Actions.LeftHandIndex1"}, + { "from": "Standard.LeftHandIndex2", "to": "Actions.LeftHandIndex2"}, + { "from": "Standard.LeftHandIndex3", "to": "Actions.LeftHandIndex3"}, + { "from": "Standard.LeftHandIndex4", "to": "Actions.LeftHandIndex4"}, + { "from": "Standard.LeftHandMiddle1", "to": "Actions.LeftHandMiddle1"}, + { "from": "Standard.LeftHandMiddle2", "to": "Actions.LeftHandMiddle2"}, + { "from": "Standard.LeftHandMiddle3", "to": "Actions.LeftHandMiddle3"}, + { "from": "Standard.LeftHandMiddle4", "to": "Actions.LeftHandMiddle4"}, + { "from": "Standard.LeftHandRing1", "to": "Actions.LeftHandRing1"}, + { "from": "Standard.LeftHandRing2", "to": "Actions.LeftHandRing2"}, + { "from": "Standard.LeftHandRing3", "to": "Actions.LeftHandRing3"}, + { "from": "Standard.LeftHandRing4", "to": "Actions.LeftHandRing4"}, + { "from": "Standard.LeftHandPinky1", "to": "Actions.LeftHandPinky1"}, + { "from": "Standard.LeftHandPinky2", "to": "Actions.LeftHandPinky2"}, + { "from": "Standard.LeftHandPinky3", "to": "Actions.LeftHandPinky3"}, + { "from": "Standard.LeftHandPinky4", "to": "Actions.LeftHandPinky4"}, + { "from": "Standard.RightHand", "to": "Actions.RightHand" }, + { "from": "Standard.RightHandThumb1", "to": "Actions.RightHandThumb1"}, + { "from": "Standard.RightHandThumb2", "to": "Actions.RightHandThumb2"}, + { "from": "Standard.RightHandThumb3", "to": "Actions.RightHandThumb3"}, + { "from": "Standard.RightHandThumb4", "to": "Actions.RightHandThumb4"}, + { "from": "Standard.RightHandIndex1", "to": "Actions.RightHandIndex1"}, + { "from": "Standard.RightHandIndex2", "to": "Actions.RightHandIndex2"}, + { "from": "Standard.RightHandIndex3", "to": "Actions.RightHandIndex3"}, + { "from": "Standard.RightHandIndex4", "to": "Actions.RightHandIndex4"}, + { "from": "Standard.RightHandMiddle1", "to": "Actions.RightHandMiddle1"}, + { "from": "Standard.RightHandMiddle2", "to": "Actions.RightHandMiddle2"}, + { "from": "Standard.RightHandMiddle3", "to": "Actions.RightHandMiddle3"}, + { "from": "Standard.RightHandMiddle4", "to": "Actions.RightHandMiddle4"}, + { "from": "Standard.RightHandRing1", "to": "Actions.RightHandRing1"}, + { "from": "Standard.RightHandRing2", "to": "Actions.RightHandRing2"}, + { "from": "Standard.RightHandRing3", "to": "Actions.RightHandRing3"}, + { "from": "Standard.RightHandRing4", "to": "Actions.RightHandRing4"}, + { "from": "Standard.RightHandPinky1", "to": "Actions.RightHandPinky1"}, + { "from": "Standard.RightHandPinky2", "to": "Actions.RightHandPinky2"}, + { "from": "Standard.RightHandPinky3", "to": "Actions.RightHandPinky3"}, + { "from": "Standard.RightHandPinky4", "to": "Actions.RightHandPinky4"}, { "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" }, { "from": "Standard.RightFoot", "to": "Actions.RightFoot" }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c67ba9c81f..2fa16c4225 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4537,6 +4537,16 @@ void Application::update(float deltaTime) { auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix; myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix)); + MyAvatar::FingerPosesMap leftHandFingerPoses; + for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) { + leftHandFingerPoses[i] = userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix); + } + MyAvatar::FingerPosesMap rightHandFingerPoses; + for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) { + rightHandFingerPoses[i] = userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix); + } + myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses); + controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT); controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT); myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix)); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1adcfbd345..6194ff154b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1447,6 +1447,19 @@ controller::Pose MyAvatar::getRightHandControllerPoseInAvatarFrame() const { return getRightHandControllerPoseInWorldFrame().transform(invAvatarMatrix); } +void MyAvatar::setFingerControllerPosesInSensorFrame(const FingerPosesMap& left, const FingerPosesMap& right) { + _leftHandFingerPosesInSensorFramceCache.set(left); + _rightHandFingerPosesInSensorFramceCache.set(right); +} + +MyAvatar::FingerPosesMap MyAvatar::getLeftHandFingerControllerPosesInSensorFrame() const { + return _leftHandFingerPosesInSensorFramceCache.get(); +} + +MyAvatar::FingerPosesMap MyAvatar::getRightHandFingerControllerPosesInSensorFrame() const { + return _rightHandFingerPosesInSensorFramceCache.get(); +} + void MyAvatar::setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right) { _leftFootControllerPoseInSensorFrameCache.set(left); _rightFootControllerPoseInSensorFrameCache.set(right); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index f61f24fb11..4d42b17301 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -469,6 +469,11 @@ public: controller::Pose getLeftHandControllerPoseInAvatarFrame() const; controller::Pose getRightHandControllerPoseInAvatarFrame() const; + typedef std::map FingerPosesMap; + void setFingerControllerPosesInSensorFrame(const FingerPosesMap& left, const FingerPosesMap& right); + FingerPosesMap getLeftHandFingerControllerPosesInSensorFrame() const; + FingerPosesMap getRightHandFingerControllerPosesInSensorFrame() const; + void setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right); controller::Pose getLeftFootControllerPoseInSensorFrame() const; controller::Pose getRightFootControllerPoseInSensorFrame() const; @@ -783,6 +788,8 @@ private: ThreadSafeValueCache _headControllerPoseInSensorFrameCache{ controller::Pose() }; ThreadSafeValueCache _leftArmControllerPoseInSensorFrameCache{ controller::Pose() }; ThreadSafeValueCache _rightArmControllerPoseInSensorFrameCache{ controller::Pose() }; + ThreadSafeValueCache _leftHandFingerPosesInSensorFramceCache { }; + ThreadSafeValueCache _rightHandFingerPosesInSensorFramceCache { }; bool _hmdLeanRecenterEnabled = true; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index e74df4cf0f..25d8427ccd 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -171,5 +171,198 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig.updateFromEyeParameters(eyeParams); -} + auto fingerPoses = myAvatar->getLeftHandFingerControllerPosesInSensorFrame(); + if (leftHandPose.isValid() && fingerPoses.size() > 0) { + // Can just check the first finger pose because either all finger poses will be valid or none of them will. + if (fingerPoses[(int)controller::Action::LEFT_HAND_INDEX1].isValid()) { + glm::quat handJointRotation = myAvatar->getLeftHandControllerPoseInSensorFrame().getRotation(); + + glm::quat previousJointRotation; + glm::quat thisJointRotation; + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky4"), glm::inverse(previousJointRotation) * thisJointRotation); + } else { + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb1")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb2")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb3")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb4")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex1")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex2")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex3")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex4")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle1")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle2")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle3")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle4")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing1")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing2")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing3")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing4")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky1")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky2")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky3")); + myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky4")); + } + } + + fingerPoses = myAvatar->getRightHandFingerControllerPosesInSensorFrame(); + if (rightHandPose.isValid() && fingerPoses.size() > 0) { + // Can just check the first finger pose because either all finger poses will be valid or none of them will. + if (fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX1].isValid()) { + glm::quat handJointRotation = myAvatar->getRightHandControllerPoseInSensorFrame().getRotation(); + + glm::quat previousJointRotation; + glm::quat thisJointRotation; + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing4"), glm::inverse(previousJointRotation) * thisJointRotation); + + previousJointRotation = handJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY1].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky1"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY2].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky2"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY3].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky3"), glm::inverse(previousJointRotation) * thisJointRotation); + previousJointRotation = thisJointRotation; + thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY4].getRotation(); + myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky4"), glm::inverse(previousJointRotation) * thisJointRotation); + } else { + myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb1")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb2")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb3")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb4")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex1")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex2")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex3")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex4")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle1")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle2")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle3")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle4")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing1")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing2")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing3")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing4")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky1")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky2")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky3")); + myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky4")); + } + } +} diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 96e433bcc8..b3c0ed3f05 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -59,6 +59,48 @@ namespace controller { makePosePair(Action::SPINE2, "Spine2"), makePosePair(Action::HEAD, "Head"), + makePosePair(Action::LEFT_HAND_THUMB1, "LeftHandThumb1"), + makePosePair(Action::LEFT_HAND_THUMB2, "LeftHandThumb2"), + makePosePair(Action::LEFT_HAND_THUMB3, "LeftHandThumb3"), + makePosePair(Action::LEFT_HAND_THUMB4, "LeftHandThumb4"), + makePosePair(Action::LEFT_HAND_INDEX1, "LeftHandIndex1"), + makePosePair(Action::LEFT_HAND_INDEX2, "LeftHandIndex2"), + makePosePair(Action::LEFT_HAND_INDEX3, "LeftHandIndex3"), + makePosePair(Action::LEFT_HAND_INDEX4, "LeftHandIndex4"), + makePosePair(Action::LEFT_HAND_MIDDLE1, "LeftHandMiddle1"), + makePosePair(Action::LEFT_HAND_MIDDLE2, "LeftHandMiddle2"), + makePosePair(Action::LEFT_HAND_MIDDLE3, "LeftHandMiddle3"), + makePosePair(Action::LEFT_HAND_MIDDLE4, "LeftHandMiddle4"), + makePosePair(Action::LEFT_HAND_RING1, "LeftHandRing1"), + makePosePair(Action::LEFT_HAND_RING2, "LeftHandRing2"), + makePosePair(Action::LEFT_HAND_RING3, "LeftHandRing3"), + makePosePair(Action::LEFT_HAND_RING4, "LeftHandRing4"), + makePosePair(Action::LEFT_HAND_PINKY1, "LeftHandPinky1"), + makePosePair(Action::LEFT_HAND_PINKY2, "LeftHandPinky2"), + makePosePair(Action::LEFT_HAND_PINKY3, "LeftHandPinky3"), + makePosePair(Action::LEFT_HAND_PINKY4, "LeftHandPinky4"), + + makePosePair(Action::RIGHT_HAND_THUMB1, "RightHandThumb1"), + makePosePair(Action::RIGHT_HAND_THUMB2, "RightHandThumb2"), + makePosePair(Action::RIGHT_HAND_THUMB3, "RightHandThumb3"), + makePosePair(Action::RIGHT_HAND_THUMB4, "RightHandThumb4"), + makePosePair(Action::RIGHT_HAND_INDEX1, "RightHandIndex1"), + makePosePair(Action::RIGHT_HAND_INDEX2, "RightHandIndex2"), + makePosePair(Action::RIGHT_HAND_INDEX3, "RightHandIndex3"), + makePosePair(Action::RIGHT_HAND_INDEX4, "RightHandIndex4"), + makePosePair(Action::RIGHT_HAND_MIDDLE1, "RightHandMiddle1"), + makePosePair(Action::RIGHT_HAND_MIDDLE2, "RightHandMiddle2"), + makePosePair(Action::RIGHT_HAND_MIDDLE3, "RightHandMiddle3"), + makePosePair(Action::RIGHT_HAND_MIDDLE4, "RightHandMiddle4"), + makePosePair(Action::RIGHT_HAND_RING1, "RightHandRing1"), + makePosePair(Action::RIGHT_HAND_RING2, "RightHandRing2"), + makePosePair(Action::RIGHT_HAND_RING3, "RightHandRing3"), + makePosePair(Action::RIGHT_HAND_RING4, "RightHandRing4"), + makePosePair(Action::RIGHT_HAND_PINKY1, "RightHandPinky1"), + makePosePair(Action::RIGHT_HAND_PINKY2, "RightHandPinky2"), + makePosePair(Action::RIGHT_HAND_PINKY3, "RightHandPinky3"), + makePosePair(Action::RIGHT_HAND_PINKY4, "RightHandPinky4"), + makeButtonPair(Action::LEFT_HAND_CLICK, "LeftHandClick"), makeButtonPair(Action::RIGHT_HAND_CLICK, "RightHandClick"), diff --git a/libraries/controllers/src/controllers/Actions.h b/libraries/controllers/src/controllers/Actions.h index 2cb500c42a..ec4800c9aa 100644 --- a/libraries/controllers/src/controllers/Actions.h +++ b/libraries/controllers/src/controllers/Actions.h @@ -104,6 +104,47 @@ enum class Action { LEFT_ARM, RIGHT_ARM, + LEFT_HAND_THUMB1, + LEFT_HAND_THUMB2, + LEFT_HAND_THUMB3, + LEFT_HAND_THUMB4, + LEFT_HAND_INDEX1, + LEFT_HAND_INDEX2, + LEFT_HAND_INDEX3, + LEFT_HAND_INDEX4, + LEFT_HAND_MIDDLE1, + LEFT_HAND_MIDDLE2, + LEFT_HAND_MIDDLE3, + LEFT_HAND_MIDDLE4, + LEFT_HAND_RING1, + LEFT_HAND_RING2, + LEFT_HAND_RING3, + LEFT_HAND_RING4, + LEFT_HAND_PINKY1, + LEFT_HAND_PINKY2, + LEFT_HAND_PINKY3, + LEFT_HAND_PINKY4, + + RIGHT_HAND_THUMB1, + RIGHT_HAND_THUMB2, + RIGHT_HAND_THUMB3, + RIGHT_HAND_THUMB4, + RIGHT_HAND_INDEX1, + RIGHT_HAND_INDEX2, + RIGHT_HAND_INDEX3, + RIGHT_HAND_INDEX4, + RIGHT_HAND_MIDDLE1, + RIGHT_HAND_MIDDLE2, + RIGHT_HAND_MIDDLE3, + RIGHT_HAND_MIDDLE4, + RIGHT_HAND_RING1, + RIGHT_HAND_RING2, + RIGHT_HAND_RING3, + RIGHT_HAND_RING4, + RIGHT_HAND_PINKY1, + RIGHT_HAND_PINKY2, + RIGHT_HAND_PINKY3, + RIGHT_HAND_PINKY4, NUM_ACTIONS, }; diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 8e49bb0ebf..40b87bc6b2 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -101,7 +101,47 @@ Input::NamedVector StandardController::getAvailableInputs() const { // Poses makePair(LEFT_HAND, "LeftHand"), + makePair(LEFT_HAND_THUMB1, "LeftHandThumb1"), + makePair(LEFT_HAND_THUMB2, "LeftHandThumb2"), + makePair(LEFT_HAND_THUMB3, "LeftHandThumb3"), + makePair(LEFT_HAND_THUMB4, "LeftHandThumb4"), + makePair(LEFT_HAND_INDEX1, "LeftHandIndex1"), + makePair(LEFT_HAND_INDEX2, "LeftHandIndex2"), + makePair(LEFT_HAND_INDEX3, "LeftHandIndex3"), + makePair(LEFT_HAND_INDEX4, "LeftHandIndex4"), + makePair(LEFT_HAND_MIDDLE1, "LeftHandMiddle1"), + makePair(LEFT_HAND_MIDDLE2, "LeftHandMiddle2"), + makePair(LEFT_HAND_MIDDLE3, "LeftHandMiddle3"), + makePair(LEFT_HAND_MIDDLE4, "LeftHandMiddle4"), + makePair(LEFT_HAND_RING1, "LeftHandRing1"), + makePair(LEFT_HAND_RING2, "LeftHandRing2"), + makePair(LEFT_HAND_RING3, "LeftHandRing3"), + makePair(LEFT_HAND_RING4, "LeftHandRing4"), + makePair(LEFT_HAND_PINKY1, "LeftHandPinky1"), + makePair(LEFT_HAND_PINKY2, "LeftHandPinky2"), + makePair(LEFT_HAND_PINKY3, "LeftHandPinky3"), + makePair(LEFT_HAND_PINKY4, "LeftHandPinky4"), makePair(RIGHT_HAND, "RightHand"), + makePair(RIGHT_HAND_THUMB1, "RightHandThumb1"), + makePair(RIGHT_HAND_THUMB2, "RightHandThumb2"), + makePair(RIGHT_HAND_THUMB3, "RightHandThumb3"), + makePair(RIGHT_HAND_THUMB4, "RightHandThumb4"), + makePair(RIGHT_HAND_INDEX1, "RightHandIndex1"), + makePair(RIGHT_HAND_INDEX2, "RightHandIndex2"), + makePair(RIGHT_HAND_INDEX3, "RightHandIndex3"), + makePair(RIGHT_HAND_INDEX4, "RightHandIndex4"), + makePair(RIGHT_HAND_MIDDLE1, "RightHandMiddle1"), + makePair(RIGHT_HAND_MIDDLE2, "RightHandMiddle2"), + makePair(RIGHT_HAND_MIDDLE3, "RightHandMiddle3"), + makePair(RIGHT_HAND_MIDDLE4, "RightHandMiddle4"), + makePair(RIGHT_HAND_RING1, "RightHandRing1"), + makePair(RIGHT_HAND_RING2, "RightHandRing2"), + makePair(RIGHT_HAND_RING3, "RightHandRing3"), + makePair(RIGHT_HAND_RING4, "RightHandRing4"), + makePair(RIGHT_HAND_PINKY1, "RightHandPinky1"), + makePair(RIGHT_HAND_PINKY2, "RightHandPinky2"), + makePair(RIGHT_HAND_PINKY3, "RightHandPinky3"), + makePair(RIGHT_HAND_PINKY4, "RightHandPinky4"), makePair(LEFT_FOOT, "LeftFoot"), makePair(RIGHT_FOOT, "RightFoot"), makePair(RIGHT_ARM, "RightArm"), diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 35e2f8d8e0..bc9ff5745c 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -31,13 +31,94 @@ const char* DEFAULT_SENSOR_LOCATION = SENSOR_ON_DESKTOP; enum LeapMotionJointIndex { LeftHand = 0, + LeftHandThumb1, + LeftHandThumb2, + LeftHandThumb3, + LeftHandThumb4, + LeftHandIndex1, + LeftHandIndex2, + LeftHandIndex3, + LeftHandIndex4, + LeftHandMiddle1, + LeftHandMiddle2, + LeftHandMiddle3, + LeftHandMiddle4, + LeftHandRing1, + LeftHandRing2, + LeftHandRing3, + LeftHandRing4, + LeftHandPinky1, + LeftHandPinky2, + LeftHandPinky3, + LeftHandPinky4, RightHand, + RightHandThumb1, + RightHandThumb2, + RightHandThumb3, + RightHandThumb4, + RightHandIndex1, + RightHandIndex2, + RightHandIndex3, + RightHandIndex4, + RightHandMiddle1, + RightHandMiddle2, + RightHandMiddle3, + RightHandMiddle4, + RightHandRing1, + RightHandRing2, + RightHandRing3, + RightHandRing4, + RightHandPinky1, + RightHandPinky2, + RightHandPinky3, + RightHandPinky4, + Size }; static controller::StandardPoseChannel LeapMotionJointIndexToPoseIndexMap[LeapMotionJointIndex::Size] = { controller::LEFT_HAND, - controller::RIGHT_HAND + controller::LEFT_HAND_THUMB1, + controller::LEFT_HAND_THUMB2, + controller::LEFT_HAND_THUMB3, + controller::LEFT_HAND_THUMB4, + controller::LEFT_HAND_INDEX1, + controller::LEFT_HAND_INDEX2, + controller::LEFT_HAND_INDEX3, + controller::LEFT_HAND_INDEX4, + controller::LEFT_HAND_MIDDLE1, + controller::LEFT_HAND_MIDDLE2, + controller::LEFT_HAND_MIDDLE3, + controller::LEFT_HAND_MIDDLE4, + controller::LEFT_HAND_RING1, + controller::LEFT_HAND_RING2, + controller::LEFT_HAND_RING3, + controller::LEFT_HAND_RING4, + controller::LEFT_HAND_PINKY1, + controller::LEFT_HAND_PINKY2, + controller::LEFT_HAND_PINKY3, + controller::LEFT_HAND_PINKY4, + controller::RIGHT_HAND, + controller::RIGHT_HAND_THUMB1, + controller::RIGHT_HAND_THUMB2, + controller::RIGHT_HAND_THUMB3, + controller::RIGHT_HAND_THUMB4, + controller::RIGHT_HAND_INDEX1, + controller::RIGHT_HAND_INDEX2, + controller::RIGHT_HAND_INDEX3, + controller::RIGHT_HAND_INDEX4, + controller::RIGHT_HAND_MIDDLE1, + controller::RIGHT_HAND_MIDDLE2, + controller::RIGHT_HAND_MIDDLE3, + controller::RIGHT_HAND_MIDDLE4, + controller::RIGHT_HAND_RING1, + controller::RIGHT_HAND_RING2, + controller::RIGHT_HAND_RING3, + controller::RIGHT_HAND_RING4, + controller::RIGHT_HAND_PINKY1, + controller::RIGHT_HAND_PINKY2, + controller::RIGHT_HAND_PINKY3, + controller::RIGHT_HAND_PINKY4 }; #define UNKNOWN_JOINT (controller::StandardPoseChannel)0 @@ -374,21 +455,44 @@ glm::vec3 LeapVectorToVec3(const Leap::Vector& vec) { void LeapMotionPlugin::processFrame(const Leap::Frame& frame) { // Default to uncontrolled. - _joints[LeapMotionJointIndex::LeftHand].position = glm::vec3(); - _joints[LeapMotionJointIndex::RightHand].position = glm::vec3(); + for (int i = 0; i < _joints.size(); i++) { + _joints[i].position = glm::vec3(); + } auto hands = frame.hands(); - - for (int i = 0; i < hands.count() && i < 2; i++) { + const int MAX_NUMBER_OF_HANDS = 2; + for (int i = 0; i < hands.count() && i < MAX_NUMBER_OF_HANDS; i++) { auto hand = hands[i]; - auto arm = hand.arm(); - if (hands[i].isLeft()) { - _joints[LeapMotionJointIndex::LeftHand].position = LeapVectorToVec3(hand.wristPosition()); - _joints[LeapMotionJointIndex::LeftHand].orientation = LeapBasisToQuat(LEFT_SIDE_SIGN, hand.basis()); - } else { - _joints[LeapMotionJointIndex::RightHand].position = LeapVectorToVec3(hand.wristPosition()); - _joints[LeapMotionJointIndex::RightHand].orientation = LeapBasisToQuat(RIGHT_SIDE_SIGN, hand.basis()); + int sideSign = hand.isLeft() ? LEFT_SIDE_SIGN : RIGHT_SIDE_SIGN; + int jointIndex = hand.isLeft() ? LeapMotionJointIndex::LeftHand : LeapMotionJointIndex::RightHand; + + // Hand. + _joints[jointIndex].position = LeapVectorToVec3(hand.wristPosition()); + _joints[jointIndex].orientation = LeapBasisToQuat(sideSign, hand.basis()); + + // Fingers. + // Leap Motion SDK guarantees full set of fingers and finger joints so can straightforwardly process them all. + Leap::FingerList fingers = hand.fingers(); + for (int j = Leap::Finger::Type::TYPE_THUMB; j <= Leap::Finger::Type::TYPE_PINKY; j++) { + Leap::Finger finger; + finger = fingers[j]; + Leap::Bone bone; + bone = finger.bone(Leap::Bone::Type::TYPE_PROXIMAL); + jointIndex++; + _joints[jointIndex].position = LeapVectorToVec3(bone.prevJoint()); + _joints[jointIndex].orientation = LeapBasisToQuat(sideSign, bone.basis()); + bone = finger.bone(Leap::Bone::Type::TYPE_INTERMEDIATE); + jointIndex++; + _joints[jointIndex].position = LeapVectorToVec3(bone.prevJoint()); + _joints[jointIndex].orientation = LeapBasisToQuat(sideSign, bone.basis()); + bone = finger.bone(Leap::Bone::Type::TYPE_DISTAL); + jointIndex++; + _joints[jointIndex].position = LeapVectorToVec3(bone.prevJoint()); + _joints[jointIndex].orientation = LeapBasisToQuat(sideSign, bone.basis()); + jointIndex++; + _joints[jointIndex].position = LeapVectorToVec3(bone.nextJoint()); + _joints[jointIndex].orientation = LeapBasisToQuat(sideSign, bone.basis()); } } } From c54a5d85062de6639e629127dfcd60cde440f27e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Jun 2017 23:32:16 +1200 Subject: [PATCH 16/22] Tidying --- interface/src/avatar/MyAvatar.h | 14 +++++++------- interface/src/avatar/MySkeletonModel.cpp | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 4d42b17301..a709f1dc25 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -781,15 +781,15 @@ private: // These are stored in SENSOR frame ThreadSafeValueCache _leftHandControllerPoseInSensorFrameCache { controller::Pose() }; ThreadSafeValueCache _rightHandControllerPoseInSensorFrameCache { controller::Pose() }; - ThreadSafeValueCache _leftFootControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _rightFootControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _hipsControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _spine2ControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _headControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _leftArmControllerPoseInSensorFrameCache{ controller::Pose() }; - ThreadSafeValueCache _rightArmControllerPoseInSensorFrameCache{ controller::Pose() }; ThreadSafeValueCache _leftHandFingerPosesInSensorFramceCache { }; ThreadSafeValueCache _rightHandFingerPosesInSensorFramceCache { }; + ThreadSafeValueCache _leftFootControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _rightFootControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _hipsControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _spine2ControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _headControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _leftArmControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _rightArmControllerPoseInSensorFrameCache { controller::Pose() }; bool _hmdLeanRecenterEnabled = true; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 25d8427ccd..44e1624aea 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -110,20 +110,20 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::HandAndFeetParameters handAndFeetParams; - auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame(); - if (leftPose.isValid()) { + auto leftHandPose = myAvatar->getLeftHandControllerPoseInAvatarFrame(); + if (leftHandPose.isValid()) { handAndFeetParams.isLeftEnabled = true; - handAndFeetParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation(); - handAndFeetParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation(); + handAndFeetParams.leftPosition = Quaternions::Y_180 * leftHandPose.getTranslation(); + handAndFeetParams.leftOrientation = Quaternions::Y_180 * leftHandPose.getRotation(); } else { handAndFeetParams.isLeftEnabled = false; } - auto rightPose = myAvatar->getRightHandControllerPoseInAvatarFrame(); - if (rightPose.isValid()) { + auto rightHandPose = myAvatar->getRightHandControllerPoseInAvatarFrame(); + if (rightHandPose.isValid()) { handAndFeetParams.isRightEnabled = true; - handAndFeetParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation(); - handAndFeetParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation(); + handAndFeetParams.rightPosition = Quaternions::Y_180 * rightHandPose.getTranslation(); + handAndFeetParams.rightOrientation = Quaternions::Y_180 * rightHandPose.getRotation(); } else { handAndFeetParams.isRightEnabled = false; } From f633f074b358d78901040c8f4384970530f9dd76 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 23 Jun 2017 00:24:28 +1200 Subject: [PATCH 17/22] Post-merge fix --- plugins/hifiLeapMotion/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiLeapMotion/CMakeLists.txt b/plugins/hifiLeapMotion/CMakeLists.txt index 14f9bbaa17..119fe5516e 100644 --- a/plugins/hifiLeapMotion/CMakeLists.txt +++ b/plugins/hifiLeapMotion/CMakeLists.txt @@ -10,6 +10,6 @@ find_package(LEAPMOTION) if (LEAPMOTION_FOUND) set(TARGET_NAME hifiLeapMotion) setup_hifi_plugin(Script Qml Widgets) - link_hifi_libraries(shared controllers ui plugins input-plugins) + link_hifi_libraries(shared controllers ui plugins input-plugins display-plugins) target_leapmotion() endif() From 8682cee17ae68a36158cef40e38b0ec28561d41c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 23 Jun 2017 11:33:29 +1200 Subject: [PATCH 18/22] Refactoring --- interface/src/Application.cpp | 10 +- interface/src/avatar/MyAvatar.h | 2 +- interface/src/avatar/MySkeletonModel.cpp | 235 +++++------------------ interface/src/avatar/MySkeletonModel.h | 4 + 4 files changed, 58 insertions(+), 193 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 92447f0e62..ace38fcc1e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4564,11 +4564,17 @@ void Application::update(float deltaTime) { MyAvatar::FingerPosesMap leftHandFingerPoses; for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) { - leftHandFingerPoses[i] = userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix); + leftHandFingerPoses[i] = { + userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), + userInputMapper->getActionName((controller::Action)i) + }; } MyAvatar::FingerPosesMap rightHandFingerPoses; for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) { - rightHandFingerPoses[i] = userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix); + rightHandFingerPoses[i] = { + userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), + userInputMapper->getActionName((controller::Action)i) + }; } myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 5768a392dd..18e2499c43 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -474,7 +474,7 @@ public: controller::Pose getLeftHandControllerPoseInAvatarFrame() const; controller::Pose getRightHandControllerPoseInAvatarFrame() const; - typedef std::map FingerPosesMap; + typedef std::map> FingerPosesMap; void setFingerControllerPosesInSensorFrame(const FingerPosesMap& left, const FingerPosesMap& right); FingerPosesMap getLeftHandFingerControllerPosesInSensorFrame() const; FingerPosesMap getRightHandFingerControllerPosesInSensorFrame() const; diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 44e1624aea..54973dc5c5 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -172,197 +172,52 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig.updateFromEyeParameters(eyeParams); - auto fingerPoses = myAvatar->getLeftHandFingerControllerPosesInSensorFrame(); - if (leftHandPose.isValid() && fingerPoses.size() > 0) { - // Can just check the first finger pose because either all finger poses will be valid or none of them will. - if (fingerPoses[(int)controller::Action::LEFT_HAND_INDEX1].isValid()) { - glm::quat handJointRotation = myAvatar->getLeftHandControllerPoseInSensorFrame().getRotation(); - glm::quat previousJointRotation; - glm::quat thisJointRotation; - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_THUMB4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandThumb4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_INDEX4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandIndex4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_MIDDLE4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandMiddle4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_RING4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandRing4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::LEFT_HAND_PINKY4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("LeftHandPinky4"), glm::inverse(previousJointRotation) * thisJointRotation); - } else { - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb1")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb2")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb3")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandThumb4")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex1")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex2")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex3")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandIndex4")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle1")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle2")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle3")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandMiddle4")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing1")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing2")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing3")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandRing4")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky1")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky2")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky3")); - myAvatar->clearJointData(_rig.indexOfJoint("LeftHandPinky4")); - } + if (leftHandPose.isValid()) { + updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame()); } - - fingerPoses = myAvatar->getRightHandFingerControllerPosesInSensorFrame(); - if (rightHandPose.isValid() && fingerPoses.size() > 0) { - // Can just check the first finger pose because either all finger poses will be valid or none of them will. - if (fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX1].isValid()) { - glm::quat handJointRotation = myAvatar->getRightHandControllerPoseInSensorFrame().getRotation(); - - glm::quat previousJointRotation; - glm::quat thisJointRotation; - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_THUMB4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandThumb4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_INDEX4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandIndex4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_MIDDLE4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandMiddle4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_RING4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandRing4"), glm::inverse(previousJointRotation) * thisJointRotation); - - previousJointRotation = handJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY1].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky1"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY2].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky2"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY3].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky3"), glm::inverse(previousJointRotation) * thisJointRotation); - previousJointRotation = thisJointRotation; - thisJointRotation = fingerPoses[(int)controller::Action::RIGHT_HAND_PINKY4].getRotation(); - myAvatar->setJointRotation(_rig.indexOfJoint("RightHandPinky4"), glm::inverse(previousJointRotation) * thisJointRotation); - } else { - myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb1")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb2")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb3")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandThumb4")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex1")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex2")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex3")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandIndex4")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle1")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle2")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle3")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandMiddle4")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing1")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing2")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing3")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandRing4")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky1")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky2")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky3")); - myAvatar->clearJointData(_rig.indexOfJoint("RightHandPinky4")); - } + if (rightHandPose.isValid()) { + updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame()); + } +} + + +void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses) { + // Assumes that finger poses are kept in the poses map in order. + + if (fingerPoses.size() == 0) { + return; + } + + auto posesMapItr = fingerPoses.begin(); + + bool isLeftHand = posesMapItr->first < (int)controller::Action::RIGHT_HAND_THUMB1; + + MyAvatar* myAvatar = static_cast(_owningAvatar); + glm::quat handJointRotation = isLeftHand + ? myAvatar->getLeftHandControllerPoseInSensorFrame().getRotation() + : myAvatar->getRightHandControllerPoseInSensorFrame().getRotation(); + + bool isFingerValid = false; + glm::quat previousJointRotation; + + while (posesMapItr != fingerPoses.end()) { + auto jointName = posesMapItr->second.second; + if (jointName.right(1) == "1") { + isFingerValid = posesMapItr->second.first.isValid(); + previousJointRotation = handJointRotation; + } + + if (isFingerValid) { + auto thisJointRotation = posesMapItr->second.first.getRotation(); + const float CONTROLLER_PRIORITY = 2.0f; + _rig.setJointRotation(_rig.indexOfJoint(jointName), true, glm::inverse(previousJointRotation) * thisJointRotation, + CONTROLLER_PRIORITY); + previousJointRotation = thisJointRotation; + } else { + _rig.clearJointAnimationPriority(_rig.indexOfJoint(jointName)); + } + + posesMapItr++; } } diff --git a/interface/src/avatar/MySkeletonModel.h b/interface/src/avatar/MySkeletonModel.h index 12aba6b545..6867c596af 100644 --- a/interface/src/avatar/MySkeletonModel.h +++ b/interface/src/avatar/MySkeletonModel.h @@ -10,6 +10,7 @@ #define hifi_MySkeletonModel_h #include +#include "MyAvatar.h" /// A skeleton loaded from a model. class MySkeletonModel : public SkeletonModel { @@ -21,6 +22,9 @@ private: public: MySkeletonModel(Avatar* owningAvatar, QObject* parent = nullptr); void updateRig(float deltaTime, glm::mat4 parentTransform) override; + +private: + void updateFingers(const MyAvatar::FingerPosesMap& fingerPoses); }; #endif // hifi_MySkeletonModel_h From b26f5c5811f6e285ad15120bc132d6e2f1fba86c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 23 Jun 2017 16:15:40 +1200 Subject: [PATCH 19/22] Clear finger joints when finger poses no longer being updated --- interface/src/Application.cpp | 29 ++++++++++++++++-------- interface/src/avatar/MySkeletonModel.cpp | 23 ++++++++----------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ace38fcc1e..38ebfe609f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4562,19 +4562,28 @@ void Application::update(float deltaTime) { auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix; myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix)); + // If have previously done finger poses or there are new valid finger poses, update finger pose values. This so that if + // fingers are not being controlled, finger joints are not updated in MySkeletonModel. + // Assumption: Finger poses are either all present and valid or not present at all; thus can test just one joint. MyAvatar::FingerPosesMap leftHandFingerPoses; - for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) { - leftHandFingerPoses[i] = { - userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), - userInputMapper->getActionName((controller::Action)i) - }; + if (myAvatar->getLeftHandFingerControllerPosesInSensorFrame().size() > 0 + || userInputMapper->getPoseState(controller::Action::LEFT_HAND_THUMB1).isValid()) { + for (int i = (int)controller::Action::LEFT_HAND_THUMB1; i <= (int)controller::Action::LEFT_HAND_PINKY4; i++) { + leftHandFingerPoses[i] = { + userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), + userInputMapper->getActionName((controller::Action)i) + }; + } } MyAvatar::FingerPosesMap rightHandFingerPoses; - for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) { - rightHandFingerPoses[i] = { - userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), - userInputMapper->getActionName((controller::Action)i) - }; + if (myAvatar->getRightHandFingerControllerPosesInSensorFrame().size() > 0 + || userInputMapper->getPoseState(controller::Action::RIGHT_HAND_THUMB1).isValid()) { + for (int i = (int)controller::Action::RIGHT_HAND_THUMB1; i <= (int)controller::Action::RIGHT_HAND_PINKY4; i++) { + rightHandFingerPoses[i] = { + userInputMapper->getPoseState((controller::Action)i).transform(avatarToSensorMatrix), + userInputMapper->getActionName((controller::Action)i) + }; + } } myAvatar->setFingerControllerPosesInSensorFrame(leftHandFingerPoses, rightHandFingerPoses); diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 54973dc5c5..ee292725e0 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -172,18 +172,13 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig.updateFromEyeParameters(eyeParams); - - if (leftHandPose.isValid()) { - updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame()); - } - if (rightHandPose.isValid()) { - updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame()); - } + updateFingers(myAvatar->getLeftHandFingerControllerPosesInSensorFrame()); + updateFingers(myAvatar->getRightHandFingerControllerPosesInSensorFrame()); } void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses) { - // Assumes that finger poses are kept in the poses map in order. + // Assumes that finger poses are kept in order in the poses map. if (fingerPoses.size() == 0) { return; @@ -194,21 +189,23 @@ void MySkeletonModel::updateFingers(const MyAvatar::FingerPosesMap& fingerPoses) bool isLeftHand = posesMapItr->first < (int)controller::Action::RIGHT_HAND_THUMB1; MyAvatar* myAvatar = static_cast(_owningAvatar); - glm::quat handJointRotation = isLeftHand - ? myAvatar->getLeftHandControllerPoseInSensorFrame().getRotation() - : myAvatar->getRightHandControllerPoseInSensorFrame().getRotation(); + auto handPose = isLeftHand + ? myAvatar->getLeftHandControllerPoseInSensorFrame() + : myAvatar->getRightHandControllerPoseInSensorFrame(); + auto handJointRotation = handPose.getRotation(); + bool isHandValid = handPose.isValid(); bool isFingerValid = false; glm::quat previousJointRotation; while (posesMapItr != fingerPoses.end()) { auto jointName = posesMapItr->second.second; - if (jointName.right(1) == "1") { + if (isHandValid && jointName.right(1) == "1") { isFingerValid = posesMapItr->second.first.isValid(); previousJointRotation = handJointRotation; } - if (isFingerValid) { + if (isHandValid && isFingerValid) { auto thisJointRotation = posesMapItr->second.first.getRotation(); const float CONTROLLER_PRIORITY = 2.0f; _rig.setJointRotation(_rig.indexOfJoint(jointName), true, glm::inverse(previousJointRotation) * thisJointRotation, From e1dcf01706109a6197b4cbee661690871be24772 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 23 Jun 2017 17:33:02 +1200 Subject: [PATCH 20/22] Better settings text --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index bc9ff5745c..2139da6ce6 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -349,7 +349,7 @@ void LeapMotionPlugin::init() { saveSettings(); applyDesktopHeightOffset(); }; - auto preference = new SpinnerPreference(LEAPMOTION_PLUGIN, "Desktop height offset", getter, setter); + auto preference = new SpinnerPreference(LEAPMOTION_PLUGIN, "Desktop height for horizontal forearms", getter, setter); float MIN_VALUE = 0.0f; float MAX_VALUE = 1.0f; float DECIMALS = 2.0f; From 9f48a139cc695ccb3bac784e38fec586be0abda8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 23 Jun 2017 18:37:48 +1200 Subject: [PATCH 21/22] Fix crash when enable Leap Motion --- plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp index 2139da6ce6..174dd02426 100644 --- a/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp +++ b/plugins/hifiLeapMotion/src/LeapMotionPlugin.cpp @@ -365,20 +365,14 @@ void LeapMotionPlugin::init() { bool LeapMotionPlugin::activate() { InputPlugin::activate(); - if (_enabled) { - // Nothing required to be done to start up Leap Motion. + // Nothing required to be done to start up Leap Motion library. - auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(_inputDevice); + _joints.resize(LeapMotionJointIndex::Size, { glm::vec3(), glm::quat() }); - if (_joints.size() != LeapMotionJointIndex::Size) { - _joints.resize(LeapMotionJointIndex::Size, { glm::vec3(), glm::quat() }); - } + auto userInputMapper = DependencyManager::get(); + userInputMapper->registerDevice(_inputDevice); - return true; - } - - return false; + return true; } void LeapMotionPlugin::deactivate() { From 384e2cefdb098e557fd801ce5d83b259399ec826 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Jun 2017 09:53:58 +1200 Subject: [PATCH 22/22] Update make file per master changes --- plugins/hifiLeapMotion/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiLeapMotion/CMakeLists.txt b/plugins/hifiLeapMotion/CMakeLists.txt index 119fe5516e..14f9bbaa17 100644 --- a/plugins/hifiLeapMotion/CMakeLists.txt +++ b/plugins/hifiLeapMotion/CMakeLists.txt @@ -10,6 +10,6 @@ find_package(LEAPMOTION) if (LEAPMOTION_FOUND) set(TARGET_NAME hifiLeapMotion) setup_hifi_plugin(Script Qml Widgets) - link_hifi_libraries(shared controllers ui plugins input-plugins display-plugins) + link_hifi_libraries(shared controllers ui plugins input-plugins) target_leapmotion() endif()