From c6e308bc876e6a7daca2341bc22795bc63289f78 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 9 Jul 2014 15:52:57 -0700 Subject: [PATCH] fixes after first review - lots of cleaning of the syntax to respect the coding standard - Fixed the device tracker singleton for clean destruction - introduced the Factory for the Leapmotion itstead of a naked constructor --- interface/src/Application.cpp | 4 +- interface/src/avatar/MyAvatar.cpp | 29 -- interface/src/devices/DeviceTracker.cpp | 82 ++-- interface/src/devices/DeviceTracker.h | 59 ++- interface/src/devices/Leapmotion.cpp | 455 ++++-------------- interface/src/devices/Leapmotion.h | 48 +- interface/src/devices/MotionTracker.cpp | 162 +++---- interface/src/devices/MotionTracker.h | 39 +- .../ControllerScriptingInterface.cpp | 74 +-- .../scripting/ControllerScriptingInterface.h | 6 +- 10 files changed, 333 insertions(+), 625 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 48c5da3080..0eb108e982 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1709,9 +1709,7 @@ void Application::init() { _faceplus.init(); _visage.init(); - Leapmotion* leap = new Leapmotion(); - int index = DeviceTracker::registerDevice( "Leapmotion", leap ); - // _leapmotion.init(); + Leapmotion* leap = Leapmotion::create(); // fire off an immediate domain-server check in now that settings are loaded NodeList::getInstance()->sendDomainServerCheckIn(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3d1b7beb9b..6cb6ba6840 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -312,35 +312,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) { -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); - - // Hand Tracker ? - { -/* HandTracker* tracker = Application::getInstance()->getActiveHandTracker(); - if (tracker) { - Hand* hand = getHand(); - if ( hand ) { - int numPalms = hand->getNumPalms(); - numPalms = (numPalms < 2 ? numPalms: 2 ); // stick to 2 palms for now - for ( int palmNum = 0; palmNum < numPalms; palmNum++ ) { - PalmData* palmData = &(hand->getPalms()[ palmNum ]); - - int handSide = HandTracker::SIDE_LEFT + palmNum; - - if ( tracker->isPalmActive( HandTracker::Side( handSide ) ) ) { - palmData->setRawPosition( tracker->getPalmTranslation( HandTracker::Side( handSide ) ) ); - palmData->setRawRotation( tracker->getPalmRotation( HandTracker::Side( handSide ) ) ); - palmData->setActive( true ); - - palmData->setSixenseID( ( (handSide == HandTracker::SIDE_LEFT) ? LEFT_HAND_INDEX : RIGHT_HAND_INDEX ) ); - } else { - palmData->setActive( false ); - palmData->setSixenseID( -1 ); - } - } - } - } - */ - } } void MyAvatar::moveWithLean() { diff --git a/interface/src/devices/DeviceTracker.cpp b/interface/src/devices/DeviceTracker.cpp index d6c54dc435..54e86dfc4c 100644 --- a/interface/src/devices/DeviceTracker.cpp +++ b/interface/src/devices/DeviceTracker.cpp @@ -11,72 +11,74 @@ #include "DeviceTracker.h" -// The singleton managing the connected devices -//template <> DeviceTracker::Singleton DeviceTracker::Singleton::_singleton; -//TemplateSingleton::_singleton; - -int DeviceTracker::init() { - return Singleton::get()->_devicesMap.size(); +DeviceTracker::SingletonData::~SingletonData() { + // Destroy all the device registered + for (auto device = _devicesVector.begin(); device != _devicesVector.end(); device++) { + delete (*device); + } } + int DeviceTracker::getNumDevices() { return Singleton::get()->_devicesMap.size(); } -int DeviceTracker::getDeviceIndex( const Name& name ) { - auto deviceIt = Singleton::get()->_devicesMap.find( name ); - if ( deviceIt != Singleton::get()->_devicesMap.end() ) +DeviceTracker::ID DeviceTracker::getDeviceID(const Name& name) { + auto deviceIt = Singleton::get()->_devicesMap.find(name); + if (deviceIt != Singleton::get()->_devicesMap.end()) { return (*deviceIt).second; - else - return -1; + } else { + return INVALID_DEVICE; + } } -DeviceTracker* DeviceTracker::getDevice( const Name& name ) { - return getDevice( getDeviceIndex( name ) ); +DeviceTracker* DeviceTracker::getDevice(const Name& name) { + return getDevice(getDeviceID(name)); } -DeviceTracker* DeviceTracker::getDevice( int deviceNum ) { - if ( (deviceNum >= 0) && ( deviceNum < Singleton::get()->_devicesVector.size() ) ) { - return Singleton::get()->_devicesVector[ deviceNum ]; +DeviceTracker* DeviceTracker::getDevice(DeviceTracker::ID deviceID) { + if ((deviceID >= 0) && deviceID < Singleton::get()->_devicesVector.size()) { + return Singleton::get()->_devicesVector[ deviceID ]; } else { return NULL; } } -int DeviceTracker::registerDevice( const Name& name, DeviceTracker* device ) { - if ( !device ) - return -1; - int index = getDeviceIndex( name ); - if ( index >= 0 ) { - // early exit because device name already taken - return -2; - } else { - index = Singleton::get()->_devicesVector.size(); - Singleton::get()->_devicesMap.insert( SingletonData::Map::value_type( name, index ) ); - Singleton::get()->_devicesVector.push_back( device ); - return index; +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 = Singleton::get()->_devicesVector.size(); + Singleton::get()->_devicesMap.insert(SingletonData::Map::value_type(name, deviceID)); + Singleton::get()->_devicesVector.push_back(device); + device->assignIDAndName(deviceID, name); + + return deviceID; } -void DeviceTracker::updateAll() -{ - for ( auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++ ) { - if ( (*deviceIt) ) +void DeviceTracker::updateAll() { + for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) { + if ((*deviceIt)) (*deviceIt)->update(); } } // Core features of the Device Tracker - -DeviceTracker::DeviceTracker() +DeviceTracker::DeviceTracker() : + _ID(INVALID_DEVICE), + _name("Unkown") { } -DeviceTracker::~DeviceTracker() -{ -} - -bool DeviceTracker::isConnected() const { - return false; +DeviceTracker::~DeviceTracker() { } void DeviceTracker::update() { diff --git a/interface/src/devices/DeviceTracker.h b/interface/src/devices/DeviceTracker.h index 8a02246cd3..2f2fd33d48 100644 --- a/interface/src/devices/DeviceTracker.h +++ b/interface/src/devices/DeviceTracker.h @@ -12,12 +12,11 @@ #ifndef hifi_DeviceTracker_h #define hifi_DeviceTracker_h -#include -#include +#include +#include +#include -//-------------------------------------------------------------------------------------- // Singleton template class -//-------------------------------------------------------------------------------------- template < typename T > class TemplateSingleton { public: @@ -47,41 +46,67 @@ template TemplateSingleton TemplateSingleton::_singleton; /// Base class for device trackers. -class DeviceTracker : public QObject { - Q_OBJECT +class DeviceTracker { public: + // THe ID and Name types used to manage the pool of devices typedef std::string Name; - typedef qint64 Stamp; + 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 init(); + // Singleton interface to register and query the devices currently connected static int getNumDevices(); - static int getDeviceIndex( const Name& name ); - static DeviceTracker* getDevice( int deviceNum ); - static DeviceTracker* getDevice( const Name& name ); - + 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(); - static int registerDevice( const Name& name, DeviceTracker* tracker ); + /// 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); // DeviceTracker interface - virtual bool isConnected() const; + 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; } + 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; } struct SingletonData { - typedef std::map< Name, int > Map; + typedef std::map< Name, ID > Map; typedef std::vector< DeviceTracker* > Vector; Map _devicesMap; Vector _devicesVector; + + ~SingletonData(); }; typedef TemplateSingleton< SingletonData > Singleton; }; diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp index 9c25d239bd..94df8c804d 100644 --- a/interface/src/devices/Leapmotion.cpp +++ b/interface/src/devices/Leapmotion.cpp @@ -8,191 +8,26 @@ // 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 "Application.h" +#include "SharedUtil.h" #include "Leapmotion.h" -#include "ui/TextRenderer.h" - - -#ifdef HAVE_LEAPMOTION - - -Leapmotion::SampleListener::SampleListener() : ::Leap::Listener() -{ -// std::cout << __FUNCTION__ << std::endl; -} - -Leapmotion::SampleListener::~SampleListener() -{ -// std::cout << __FUNCTION__ << std::endl; -} - -void Leapmotion::SampleListener::onConnect(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onDisconnect(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onExit(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onFocusGained(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onFocusLost(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onFrame(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onInit(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onServiceConnect(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} -void Leapmotion::SampleListener::onServiceDisconnect(const ::Leap::Controller &) -{ -// std::cout << __FUNCTION__ << std::endl; -} - -/*const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, - 0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; -const unsigned char AXIS_LIST[] = { 9, 43, 37, 37, 37, 13, 13, 13, 52, 52, 28, 28 }; -const int LIST_LENGTH = sizeof(SERIAL_LIST) / sizeof(SERIAL_LIST[0]); - -const char* JOINT_NAMES[] = { "Neck", "Spine", "LeftArm", "LeftForeArm", "LeftHand", "RightArm", - "RightForeArm", "RightHand", "LeftUpLeg", "LeftLeg", "RightUpLeg", "RightLeg" }; - -static int indexOfHumanIKJoint(const char* jointName) { - for (int i = 0;; i++) { - QByteArray humanIKJoint = HUMANIK_JOINTS[i]; - if (humanIKJoint.isEmpty()) { - return -1; - } - if (humanIKJoint == jointName) { - return i; - } - } -} - -static void setPalm(float deltaTime, int index) { - MyAvatar* avatar = Application::getInstance()->getAvatar(); - Hand* hand = avatar->getHand(); - PalmData* palm; - bool foundHand = false; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == index) { - palm = &(hand->getPalms()[j]); - foundHand = true; - } - } - if (!foundHand) { - PalmData newPalm(hand); - hand->getPalms().push_back(newPalm); - palm = &(hand->getPalms()[hand->getNumPalms() - 1]); - palm->setSixenseID(index); - } - - palm->setActive(true); - - // Read controller buttons and joystick into the hand - if (!Application::getInstance()->getJoystickManager()->getJoystickStates().isEmpty()) { - const JoystickState& state = Application::getInstance()->getJoystickManager()->getJoystickStates().at(0); - if (state.axes.size() >= 4 && state.buttons.size() >= 4) { - if (index == LEFT_HAND_INDEX) { - palm->setControllerButtons(state.buttons.at(1) ? BUTTON_FWD : 0); - palm->setTrigger(state.buttons.at(0) ? 1.0f : 0.0f); - palm->setJoystick(state.axes.at(0), -state.axes.at(1)); - - } else { - palm->setControllerButtons(state.buttons.at(3) ? BUTTON_FWD : 0); - palm->setTrigger(state.buttons.at(2) ? 1.0f : 0.0f); - palm->setJoystick(state.axes.at(2), -state.axes.at(3)); - } - } - } - - glm::vec3 position; - glm::quat rotation; - - SkeletonModel* skeletonModel = &Application::getInstance()->getAvatar()->getSkeletonModel(); - int jointIndex; - glm::quat inverseRotation = glm::inverse(Application::getInstance()->getAvatar()->getOrientation()); - if (index == LEFT_HAND_INDEX) { - jointIndex = skeletonModel->getLeftHandJointIndex(); - skeletonModel->getJointRotation(jointIndex, rotation, true); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); - - } else { - jointIndex = skeletonModel->getRightHandJointIndex(); - skeletonModel->getJointRotation(jointIndex, rotation, true); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); - } - skeletonModel->getJointPosition(jointIndex, position); - position = inverseRotation * (position - skeletonModel->getTranslation()); - - palm->setRawRotation(rotation); - - // Compute current velocity from position change - glm::vec3 rawVelocity; - if (deltaTime > 0.f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; - } else { - rawVelocity = glm::vec3(0.0f); - } - palm->setRawVelocity(rawVelocity); - palm->setRawPosition(position); - - // Store the one fingertip in the palm structure so we can track velocity - const float FINGER_LENGTH = 0.3f; // meters - const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); - const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; - glm::vec3 oldTipPosition = palm->getTipRawPosition(); - if (deltaTime > 0.f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); - } else { - palm->setTipVelocity(glm::vec3(0.f)); - } - palm->setTipPosition(newTipPosition); -} -*/ - -// default (expected) location of neck in sixense space -const float LEAP_X = 0.25f; // meters -const float LEAP_Y = 0.3f; // meters -const float LEAP_Z = 0.3f; // meters -#endif 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] -// the bone: -MotionTracker::Index evalJointIndex( bool isRightSide, int finger, int bone ) { +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 ) { + if (finger >= 0) { // from there go down in the correct finger and bone return offset + (finger * FINGER_NUM_JOINTS) + bone; } else { @@ -201,157 +36,148 @@ MotionTracker::Index evalJointIndex( bool isRightSide, int finger, int bone ) { } } +Leapmotion* Leapmotion::create() { + // check that the Leapmotion hasn't been created yet + DeviceTracker* device = DeviceTracker::getDevice(NAME); + if (!device) { + // create a new Leapmotion + Leapmotion* leap = new Leapmotion(); + + // register it + DeviceTracker::registerDevice(NAME, leap); + + return leap; + } + else + { + Leapmotion* leap = dynamic_cast< Leapmotion* > (device); + if (leap) { + return leap; + } + + return NULL; + } +} + Leapmotion::Leapmotion() : MotionTracker(), - _enabled(false), _active(false) { -#ifdef HAVE_LEAPMOTION - - // Have the sample listener receive events from the controller - _controller.addListener(_listener); - - reset(); - -#endif - // Create the Leapmotion joint hierarchy - { - std::vector< Semantic > sides; - sides.push_back( "joint_L_" ); - sides.push_back( "joint_R_" ); + 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( "hand" ); - rootBones.push_back( "wrist" ); + std::vector< Semantic > rootBones; + rootBones.push_back("elbow"); + rootBones.push_back("hand"); + rootBones.push_back("wrist"); - 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 > 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< Semantic > fingerBones; + fingerBones.push_back("1"); + fingerBones.push_back("2"); + fingerBones.push_back("3"); + fingerBones.push_back("4"); - std::vector< Index > palms; - for ( int s = 0; s < sides.size(); s++ ) { - Index rootJoint = 0; - for ( int rb = 0; rb < rootBones.size(); rb++ ) { - rootJoint = addJoint( sides[s] + rootBones[rb], rootJoint ); - } + 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 ); + // capture the hand index for debug + palms.push_back(rootJoint); - for ( int f = 0; f < fingers.size(); f++ ) { - for ( int b = 0; b < fingerBones.size(); b++ ) { - rootJoint = addJoint( sides[s] + fingers[f] + fingerBones[b], 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); } } } } Leapmotion::~Leapmotion() { -#ifdef HAVE_LEAPMOTION - // Remove the sample listener when done - _controller.removeListener(_listener); -#endif -} - - -void Leapmotion::init() { - // connect(Application::getInstance()->getFaceshift(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); - updateEnabled(); } #ifdef HAVE_LEAPMOTION -glm::quat quatFromLeapBase( float sideSign, const Leap::Matrix& basis ) { +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) ); + 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 ) ); + xAxis = glm::normalize(glm::cross(yAxis, zAxis)); glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); return orientation; } -glm::quat quatFromLeapBase( float sideSign, const Leap::Vector& dir, const Leap::Vector& normal ) { - glm::vec3 xAxis = glm::normalize( sideSign * glm::vec3( dir.x, dir.y, dir.z) ); - glm::vec3 yAxis = glm::normalize( -glm::vec3( normal.x, normal.y, normal.z) ); - glm::vec3 zAxis = glm::normalize( glm::cross( xAxis, yAxis ) ); - // yAxis = glm::normalize( glm::cross( zAxis, xAxis ) ); - glm::quat orientation = /*glm::inverse*/(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); - // orientation = glm::normalize( orientation ); - // return glm::quat(); - 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 ); +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 + // Check that the controller is actually active _active = _controller.isConnected(); if (!_active) { return; } // go through all the joints and increment their counter since last update - for ( auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++ ) { + for (auto jointIt = _jointsArray.begin(); jointIt != _jointsArray.end(); jointIt++) { (*jointIt).tickNewFrame(); } - float deltaTime = 0.001f; - // Get the most recent frame and report some basic information const Leap::Frame frame = _controller.frame(); - static int64_t lastFrame = -1; - int64_t newFrameNb = frame.id(); + static int64_t lastFrameID = -1; + int64_t newFrameID = frame.id(); - if ( (lastFrame >= newFrameNb) ) + // If too soon then exit + if (lastFrameID >= newFrameID) return; glm::vec3 delta(0.f); glm::quat handOri; - if ( !frame.hands().isEmpty() ) { - for ( int handNum = 0; handNum < frame.hands().count(); handNum++ ) { + 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 ); - Index handIndex = evalJointIndex( (side > 0), -1, 0 ); + int side = (hand.isRight() ? 1 : -1); JointTracker* parentJointTracker = _jointsArray.data(); - - // only in SDK 2.0.3 + + + int rootBranchIndex = -1; + Leap::Arm arm = hand.arm(); - if ( arm.isValid() ) { - glm::quat ori = quatFromLeapBase(float(side), arm.basis() ); - + if (arm.isValid()) { + glm::quat ori = quatFromLeapBase(float(side), arm.basis()); glm::vec3 pos = vec3FromLeapVector(arm.elbowPosition()); - JointTracker* elbow = editJointTracker( evalJointIndex( (side > 0), -1, 2 ) ); - elbow->editAbsFrame().setTranslation( pos ); - elbow->editAbsFrame().setRotation( ori ); - elbow->updateLocFromAbsTransform( parentJointTracker ); + 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), -1, 1 ) ); - wrist->editAbsFrame().setTranslation( pos ); - wrist->editAbsFrame().setRotation( ori ); - wrist->updateLocFromAbsTransform( parentJointTracker ); + 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; } @@ -359,12 +185,12 @@ void Leapmotion::update() { JointTracker* palmJoint = NULL; { glm::vec3 pos = vec3FromLeapVector(hand.palmPosition()); - glm::quat ori = quatFromLeapBase(float(side), hand.basis() ); + glm::quat ori = quatFromLeapBase(float(side), hand.basis()); - palmJoint = editJointTracker( evalJointIndex( (side > 0), -1, 0 ) ); - palmJoint->editAbsFrame().setTranslation( pos ); - palmJoint->editAbsFrame().setRotation( ori ); - palmJoint->updateLocFromAbsTransform( parentJointTracker ); + 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(); } @@ -377,19 +203,19 @@ void Leapmotion::update() { 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 ); + 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++ ) { + 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::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->editAbsFrame().setTranslation(vec3FromLeapVector(bp)); + ljointTracker->editAbsFrame().setRotation(quatFromLeapBase(float(side), bone.basis())); + ljointTracker->updateLocFromAbsTransform(parentJointTracker); ljointTracker->activeFrame(); } parentJointTracker = ljointTracker; @@ -399,83 +225,6 @@ void Leapmotion::update() { } } - lastFrame = newFrameNb; - - - - if ( false ) - { - - std::cout << "Frame id: " << frame.id() - << ", timestamp: " << frame.timestamp() - << ", hands: " << frame.hands().count() - << ", fingers: " << frame.fingers().count() - << ", tools: " << frame.tools().count() << std::endl; - - if (!frame.hands().isEmpty()) { - // Get the first hand - const Leap::Hand hand = frame.hands()[0]; - - // Check if the hand has any fingers - const Leap::FingerList fingers = hand.fingers(); - if (!fingers.isEmpty()) { - // Calculate the hand's average finger tip position - Leap::Vector avgPos; - for (int i = 0; i < fingers.count(); ++i) { - avgPos += fingers[i].tipPosition(); - } - - avgPos /= (float)fingers.count(); - std::cout << "Hand has " << fingers.count() - << " fingers, average finger tip position" << avgPos << std::endl; - } - - // Get the hand's sphere radius and palm position - std::cout << "Hand sphere radius: " << hand.sphereRadius() - << " mm, palm position: " << hand.palmPosition() << std::endl; - - // Get the hand's normal vector and direction - const Leap::Vector normal = hand.palmNormal(); - const Leap::Vector direction = hand.direction(); - - // Calculate the hand's pitch, roll, and yaw angles - const float RAD_TO_DEG = 180.0 / 3.1415; - std::cout << "Hand pitch: " << direction.pitch() * RAD_TO_DEG << " degrees, " - << "roll: " << normal.roll() * RAD_TO_DEG << " degrees, " - << "yaw: " << direction.yaw() * RAD_TO_DEG << " degrees" << std::endl << std::endl; - - - } - } - -#endif -} - -void Leapmotion::reset() { -#ifdef HAVE_LEAPMOTION - // By default we assume the _neckBase (in orb frame) is as high above the orb - // as the "torso" is below it. - _leapBasePos = glm::vec3(0, -LEAP_Y, LEAP_Z); - - glm::vec3 xAxis(1.f, 0.f, 0.f); - glm::vec3 yAxis(0.f, 1.f, 0.f); - glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis)); - xAxis = glm::normalize(glm::cross(yAxis, zAxis)); - _leapBaseOri = glm::inverse(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); -#endif -} - -void Leapmotion::updateEnabled() { - /* setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && - !Menu::getInstance()->isOptionChecked(MenuOption::Faceplus) && - !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && - Application::getInstance()->getFaceshift()->isConnectedOrConnecting()));*/ -} - -void Leapmotion::setEnabled(bool enabled) { -#ifdef HAVE_LEAPMOTION - if (_enabled == enabled) { - return; - } + lastFrameID = newFrameID; #endif } diff --git a/interface/src/devices/Leapmotion.h b/interface/src/devices/Leapmotion.h index 5ed642c3cb..36cb31d6e4 100644 --- a/interface/src/devices/Leapmotion.h +++ b/interface/src/devices/Leapmotion.h @@ -22,54 +22,26 @@ /// Handles interaction with the Leapmotion skeleton tracking suit. class Leapmotion : public MotionTracker { - Q_OBJECT - public: + static const Name NAME; + /// Leapmotion MotionTracker factory + static Leapmotion* create(); + + bool isActive() const { return _active; } + + virtual void update(); + +protected: Leapmotion(); virtual ~Leapmotion(); - void init(); - - bool isActive() const { return _active; } - - void update(); - void reset(); - -public slots: - - void updateEnabled(); - private: #ifdef HAVE_LEAPMOTION - - class SampleListener : public ::Leap::Listener - { - public: - SampleListener(); - virtual ~SampleListener(); - - virtual void onConnect(const ::Leap::Controller &); - virtual void onDisconnect(const ::Leap::Controller &); - virtual void onExit(const ::Leap::Controller &); - virtual void onFocusGained(const ::Leap::Controller &); - virtual void onFocusLost(const ::Leap::Controller &); - virtual void onFrame(const ::Leap::Controller &); - virtual void onInit(const ::Leap::Controller &); - virtual void onServiceConnect(const ::Leap::Controller &); - virtual void onServiceDisconnect(const ::Leap::Controller &); - - }; - - SampleListener _listener; + Leap::Listener _listener; Leap::Controller _controller; #endif - glm::vec3 _leapBasePos; - glm::quat _leapBaseOri; - void setEnabled(bool enabled); - - bool _enabled; bool _active; }; diff --git a/interface/src/devices/MotionTracker.cpp b/interface/src/devices/MotionTracker.cpp index 68c1d5fb93..2765358774 100644 --- a/interface/src/devices/MotionTracker.cpp +++ b/interface/src/devices/MotionTracker.cpp @@ -12,64 +12,60 @@ #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 } -//-------------------------------------------------------------------------------------- +// 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 ); + 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[0]), + dot(lry, rhs[0]), + dot(lrz, rhs[0]), - dot( lrx, rhs[1] ), - dot( lry, rhs[1] ), - dot( lrz, rhs[1] ), + 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[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 - ); + 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 ); + 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[0]), + dot(lry, rhs[0]), + dot(lrz, rhs[0]), - dot( lrx, rhs[1] ), - dot( lry, rhs[1] ), - dot( lrz, rhs[1] ), + 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[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 - ); + 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 ) ); + _jointsMap.insert(JointTracker::map::value_type(Semantic("Root"), 0)); } MotionTracker::~MotionTracker() @@ -80,45 +76,43 @@ bool MotionTracker::isConnected() const { return false; } -MotionTracker::Index MotionTracker::addJoint( const Semantic& semantic, Index parent ) { +MotionTracker::Index MotionTracker::addJoint(const Semantic& semantic, Index parent) { // Check the parent - if ( int(parent) < 0 ) + if (int(parent) < 0) return INVALID_PARENT; // Check that the semantic is not already in use - Index foundIndex = findJointIndex( semantic ); - if ( int(foundIndex) >= 0 ) + Index foundIndex = findJointIndex(semantic); + if (foundIndex >= 0) return INVALID_SEMANTIC; // All good then allocate the joint Index newIndex = _jointsArray.size(); - _jointsArray.push_back( JointTracker( semantic, parent ) ); - _jointsMap.insert( JointTracker::map::value_type( semantic, newIndex ) ); + _jointsArray.push_back(JointTracker(semantic, parent)); + _jointsMap.insert(JointTracker::map::value_type(semantic, newIndex)); return newIndex; } -MotionTracker::Index MotionTracker::findJointIndex( const Semantic& semantic ) const { - auto jointIt = _jointsMap.find( semantic ); - if ( jointIt != _jointsMap.end() ) +MotionTracker::Index MotionTracker::findJointIndex(const Semantic& semantic) const { + auto jointIt = _jointsMap.find(semantic); + if (jointIt != _jointsMap.end()) return (*jointIt).second; return INVALID_SEMANTIC; } void MotionTracker::updateAllAbsTransform() { - _jointsArray[0].updateAbsFromLocTransform( 0 ); + _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 < _jointsArray.size(); i++ ) { + for (Index i = 1; i < _jointsArray.size(); i++) { JointTracker* joint = _jointsArray.data() + i; - joint->updateAbsFromLocTransform( _jointsArray.data() + joint->getParent() ); + joint->updateAbsFromLocTransform(_jointsArray.data() + joint->getParent()); } } -//-------------------------------------------------------------------------------------- -// MotionTracker::JointTracker -//-------------------------------------------------------------------------------------- +// MotionTracker::JointTracker MotionTracker::JointTracker::JointTracker() : _locFrame(), _absFrame(), @@ -128,36 +122,34 @@ MotionTracker::JointTracker::JointTracker() : { } -MotionTracker::JointTracker::JointTracker( const Semantic& semantic, Index parent ) : - _semantic( semantic ), - _parent( parent ), - _lastUpdate( 0 ) +MotionTracker::JointTracker::JointTracker(const Semantic& semantic, Index parent) : + _semantic(semantic), + _parent(parent), + _lastUpdate(0) { } -MotionTracker::JointTracker::JointTracker( const JointTracker& tracker ) : - _locFrame( tracker._locFrame ), - _absFrame( tracker._absFrame ), - _semantic( tracker._semantic ), - _parent( tracker._parent ), - _lastUpdate( tracker._lastUpdate ) +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 = glm::mult( parentJoint->getAbsFrame()._transform, getLocFrame()._transform ); - editAbsFrame()._transform = ( parentJoint->getAbsFrame()._transform * getLocFrame()._transform ); + 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( glm::mat4( parentJoint->getAbsFrame()._transform ) ); - glm::mat4 ip = glm::inverse( parentJoint->getAbsFrame()._transform ); - // editLocFrame()._transform = glm::mult( ip, getAbsFrame()._transform ); - editLocFrame()._transform = ( ip * getAbsFrame()._transform ); + if (parentJoint) { + glm::mat4 ip = glm::inverse(parentJoint->getAbsFrame()._transform); + editLocFrame()._transform = (ip * getAbsFrame()._transform); } else { editLocFrame()._transform = getAbsFrame()._transform; } @@ -172,24 +164,22 @@ MotionTracker::Frame::Frame() : { } -void MotionTracker::Frame::setRotation( const glm::quat& rotation ) -{ - glm::mat3x3 rot = glm::mat3_cast( rotation ); - _transform[0] = glm::vec4( rot[0], 0.f ); - _transform[1] = glm::vec4( rot[1], 0.f ); - _transform[2] = glm::vec4( rot[2], 0.f ); +void MotionTracker::Frame::setRotation(const glm::quat& rotation) { + glm::mat3x3 rot = glm::mat3_cast(rotation); + _transform[0] = glm::vec4(rot[0], 0.f); + _transform[1] = glm::vec4(rot[1], 0.f); + _transform[2] = glm::vec4(rot[2], 0.f); } -void MotionTracker::Frame::getRotation( glm::quat& rotation ) const { - // rotation = glm::quat_cast( glm::mat3( _transform[0], _transform[1], _transform[2] ) ); - rotation = glm::quat_cast( _transform ); +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.f ); +void MotionTracker::Frame::setTranslation(const glm::vec3& translation) { + _transform[3] = glm::vec4(translation, 1.f); } -void MotionTracker::Frame::getTranslation( glm::vec3& translation ) const { - translation = glm::vec3( _transform[3] ); +void MotionTracker::Frame::getTranslation(glm::vec3& translation) const { + translation = glm::vec3(_transform[3]); } diff --git a/interface/src/devices/MotionTracker.h b/interface/src/devices/MotionTracker.h index a5befc9670..660c44c842 100644 --- a/interface/src/devices/MotionTracker.h +++ b/interface/src/devices/MotionTracker.h @@ -14,15 +14,12 @@ #include "DeviceTracker.h" -#include - #include #include #include /// Base class for device trackers. class MotionTracker : public DeviceTracker { - Q_OBJECT public: class Frame { @@ -31,36 +28,35 @@ public: glm::mat4 _transform; - void setRotation( const glm::quat& rotation ); - void getRotation( glm::quat& rotation ) const; + void setRotation(const glm::quat& rotation); + void getRotation(glm::quat& rotatio) const; - void setTranslation( const glm::vec3& translation ); - void getTranslation( glm::vec3& translation ) 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 unsigned int Index; - + typedef int 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 ); + 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; } + void setLocFrame(const Frame& frame) { editLocFrame() = frame; } const Frame& getAbsFrame() const { return _absFrame; } Frame& editAbsFrame() { return _absFrame; } - void setAbsFrame( const Frame& frame ) { editAbsFrame() = frame; } + void setAbsFrame(const Frame& frame) { editAbsFrame() = frame; } const Semantic& getSemantic() const { return _semantic; } const Index& getParent() const { return _parent; } @@ -81,29 +77,26 @@ public: int _lastUpdate; }; - virtual bool isConnected() const; Index numJointTrackers() const { return _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 ( int(index) < _jointsArray.size() ? _jointsArray.data() + index : NULL ); } - JointTracker* editJointTracker( Index index ) { return ( int(index) < _jointsArray.size() ? _jointsArray.data() + index : NULL ); } + const JointTracker* getJointTracker(Index index) const { return ((index > 0) && (index < _jointsArray.size()) ? _jointsArray.data() + index : NULL); } + JointTracker* editJointTracker(Index index) { return ((index > 0) && (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; + Index findJointIndex(const Semantic& semantic) const; protected: MotionTracker(); virtual ~MotionTracker(); - JointTracker::vector _jointsArray; - JointTracker::map _jointsMap; + 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. @@ -116,7 +109,7 @@ protected: /// 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 ); + 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. diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 98ceb90e44..a5d30b3c31 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -260,63 +260,69 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { return glm::vec2(widget->width(), widget->height()); } -AbstractInputController* ControllerScriptingInterface::createInputController( const QString& category, const QString& tracker ) -{ +AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { // This is where we retreive the Device Tracker category and then the sub tracker within it - auto icIt = _inputControllers.find( 0 ); - if ( icIt != _inputControllers.end() ) { + auto icIt = _inputControllers.find(0); + if (icIt != _inputControllers.end()) { return (*icIt).second; } else { - // Look for matching category - // TODO in this current implementation, we just pick the first device assuming there is one ( normally the LeapMotion) - // in the near future we need to change that to a real mapping between the device names and the cateory - int categoryID = 0; - MotionTracker* motionTracker = dynamic_cast< MotionTracker* > ( DeviceTracker::getDevice( categoryID ) ); - if ( motionTracker ) { - int trackerID = motionTracker->findJointIndex( tracker.toStdString() ); - if ( trackerID > 0 ) { - AbstractInputController* inputController = new InputController(categoryID,trackerID, this ); + // 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 - _inputControllers.insert( InputControllerMap::value_type( inputController->getKey(), inputController ) ); + 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) { + AbstractInputController* inputController = new InputController(deviceID, trackerID, this); - return inputController; + _inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController)); + + return inputController; + } } } + return 0; } } -void ControllerScriptingInterface::updateInputControllers() -{ - for ( auto it = _inputControllers.begin(); it != _inputControllers.end(); it++ ) { +void ControllerScriptingInterface::updateInputControllers() { + for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) { (*it).second->update(); } - } InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) : AbstractInputController(), - _deviceTrackerId( deviceTrackerId ), - _subTrackerId( subTrackerId ) + _deviceTrackerId(deviceTrackerId), + _subTrackerId(subTrackerId) { } -void InputController::update() -{ +void InputController::update() { _isActive = false; - MotionTracker* motionTracker = dynamic_cast< MotionTracker*> ( DeviceTracker::getDevice( _deviceTrackerId ) ); - if ( motionTracker ) { - if ( _subTrackerId < motionTracker->numJointTrackers() ) { - const MotionTracker::JointTracker* joint = motionTracker->getJointTracker( _subTrackerId ); + // TODO for now the InputController is only supporting a JointTracker from a MotionTracker + MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId)); + if (motionTracker) { + if (_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 ); + 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); @@ -325,7 +331,9 @@ void InputController::update() } } +const unsigned int INPUTCONTROLLER_KEY_DEVICE_OFFSET = 16; +const unsigned int INPUTCONTROLLER_KEY_DEVICE_MASK = 16; InputController::Key InputController::getKey() const { - return (_deviceTrackerId * 10000) + _subTrackerId; + return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId); } diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 6d3613f16a..cf5414554e 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -44,7 +44,6 @@ private: SpatialEvent _eventCache; bool _isActive; - signals: }; @@ -77,7 +76,7 @@ public: void updateInputControllers(); - void releaseInputController( AbstractInputController* input ); + void releaseInputController(AbstractInputController* input); public slots: virtual bool isPrimaryButtonPressed() const; @@ -114,7 +113,8 @@ public slots: virtual glm::vec2 getViewportDimensions() const; - virtual AbstractInputController* createInputController( const QString& category, const QString& tracker ); + /// Factory to create an InputController + virtual AbstractInputController* createInputController(const QString& deviceName, const QString& tracker); private: const PalmData* getPrimaryPalm() const;