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
This commit is contained in:
samcake 2014-07-09 15:52:57 -07:00
parent d6104e5d48
commit c6e308bc87
10 changed files with 333 additions and 625 deletions

View file

@ -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();

View file

@ -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() {

View file

@ -11,54 +11,60 @@
#include "DeviceTracker.h"
// The singleton managing the connected devices
//template <> DeviceTracker::Singleton DeviceTracker::Singleton::_singleton;
//TemplateSingleton<DeviceTracker::SingletonData>::_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 ) {
DeviceTracker::ID DeviceTracker::getDeviceID(const Name& name) {
auto deviceIt = Singleton::get()->_devicesMap.find(name);
if ( deviceIt != Singleton::get()->_devicesMap.end() )
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 ) );
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;
}
void DeviceTracker::updateAll()
{
// 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))
(*deviceIt)->update();
@ -66,17 +72,13 @@ void DeviceTracker::updateAll()
}
// 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() {

View file

@ -12,12 +12,11 @@
#ifndef hifi_DeviceTracker_h
#define hifi_DeviceTracker_h
#include <QObject>
#include <QVector>
#include <string>
#include <vector>
#include <map>
//--------------------------------------------------------------------------------------
// Singleton template class
//--------------------------------------------------------------------------------------
template < typename T >
class TemplateSingleton {
public:
@ -47,41 +46,67 @@ template <typename T>
TemplateSingleton<T> TemplateSingleton<T>::_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 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;
};

View file

@ -8,185 +8,20 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QTimer>
#include <QtDebug>
#include <FBXReader.h>
#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 offset = 1 // start after root
@ -201,22 +36,34 @@ 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_");
@ -240,35 +87,24 @@ Leapmotion::Leapmotion() :
fingerBones.push_back("4");
std::vector< Index > palms;
for ( int s = 0; s < sides.size(); s++ ) {
for (unsigned int s = 0; s < sides.size(); s++) {
Index rootJoint = 0;
for ( int rb = 0; rb < rootBones.size(); rb++ ) {
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 ( int f = 0; f < fingers.size(); f++ ) {
for ( int b = 0; b < fingerBones.size(); b++ ) {
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
@ -284,17 +120,7 @@ glm::quat quatFromLeapBase( float sideSign, const Leap::Matrix& basis ) {
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);
}
@ -303,6 +129,7 @@ glm::vec3 vec3FromLeapVector( const Leap::Vector& vec ) {
void Leapmotion::update() {
#ifdef HAVE_LEAPMOTION
// Check that the controller is actually active
_active = _controller.isConnected();
if (!_active) {
return;
@ -313,14 +140,13 @@ void Leapmotion::update() {
(*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);
@ -330,17 +156,17 @@ void Leapmotion::update() {
const Leap::Hand hand = frame.hands()[handNum];
int side = (hand.isRight() ? 1 : -1);
Index handIndex = evalJointIndex( (side > 0), -1, 0 );
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());
glm::vec3 pos = vec3FromLeapVector(arm.elbowPosition());
JointTracker* elbow = editJointTracker( evalJointIndex( (side > 0), -1, 2 ) );
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);
@ -348,7 +174,7 @@ void Leapmotion::update() {
parentJointTracker = elbow;
pos = vec3FromLeapVector(arm.wristPosition());
JointTracker* wrist = editJointTracker( evalJointIndex( (side > 0), -1, 1 ) );
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);
@ -361,7 +187,7 @@ void Leapmotion::update() {
glm::vec3 pos = vec3FromLeapVector(hand.palmPosition());
glm::quat ori = quatFromLeapBase(float(side), hand.basis());
palmJoint = editJointTracker( evalJointIndex( (side > 0), -1, 0 ) );
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);
@ -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
}

View file

@ -22,54 +22,26 @@
/// Handles interaction with the Leapmotion skeleton tracking suit.
class Leapmotion : public MotionTracker {
Q_OBJECT
public:
static const Name NAME;
Leapmotion();
virtual ~Leapmotion();
void init();
/// Leapmotion MotionTracker factory
static Leapmotion* create();
bool isActive() const { return _active; }
void update();
void reset();
virtual void update();
public slots:
void updateEnabled();
protected:
Leapmotion();
virtual ~Leapmotion();
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;
};

View file

@ -12,9 +12,7 @@
#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);
@ -62,9 +60,7 @@ namespace glm {
}
}
//--------------------------------------------------------------------------------------
// MotionTracker
//--------------------------------------------------------------------------------------
MotionTracker::MotionTracker() :
DeviceTracker()
{
@ -87,7 +83,7 @@ MotionTracker::Index MotionTracker::addJoint( const Semantic& semantic, Index pa
// Check that the semantic is not already in use
Index foundIndex = findJointIndex(semantic);
if ( int(foundIndex) >= 0 )
if (foundIndex >= 0)
return INVALID_SEMANTIC;
// All good then allocate the joint
@ -115,10 +111,8 @@ void MotionTracker::updateAllAbsTransform() {
}
}
//--------------------------------------------------------------------------------------
// MotionTracker::JointTracker
//--------------------------------------------------------------------------------------
// MotionTracker::JointTracker
MotionTracker::JointTracker::JointTracker() :
_locFrame(),
_absFrame(),
@ -143,9 +137,9 @@ MotionTracker::JointTracker::JointTracker( const JointTracker& tracker ) :
_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);
} else {
editAbsFrame()._transform = getLocFrame()._transform;
@ -154,9 +148,7 @@ void MotionTracker::JointTracker::updateAbsFromLocTransform(const JointTracker*
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);
} else {
editLocFrame()._transform = getAbsFrame()._transform;
@ -172,8 +164,7 @@ MotionTracker::Frame::Frame() :
{
}
void MotionTracker::Frame::setRotation( const glm::quat& rotation )
{
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);
@ -181,7 +172,6 @@ void MotionTracker::Frame::setRotation( const glm::quat& rotation )
}
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);
}

View file

@ -14,15 +14,12 @@
#include "DeviceTracker.h"
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
/// Base class for device trackers.
class MotionTracker : public DeviceTracker {
Q_OBJECT
public:
class Frame {
@ -32,19 +29,18 @@ public:
glm::mat4 _transform;
void setRotation(const glm::quat& rotation);
void getRotation( glm::quat& rotation ) const;
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 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;
@ -81,18 +77,15 @@ 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.

View file

@ -260,39 +260,45 @@ 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()) {
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 ) );
// 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) {
int trackerID = motionTracker->findJointIndex( tracker.toStdString() );
MotionTracker::Index trackerID = motionTracker->findJointIndex(tracker.toStdString());
if (trackerID > 0) {
AbstractInputController* inputController = new InputController(categoryID,trackerID, this );
AbstractInputController* inputController = new InputController(deviceID, trackerID, this);
_inputControllers.insert(InputControllerMap::value_type(inputController->getKey(), inputController));
return inputController;
}
}
}
return 0;
}
}
void ControllerScriptingInterface::updateInputControllers()
{
void ControllerScriptingInterface::updateInputControllers() {
for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) {
(*it).second->update();
}
}
@ -303,10 +309,10 @@ InputController::InputController(int deviceTrackerId, int subTrackerId, QObject*
{
}
void InputController::update()
{
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 (_subTrackerId < motionTracker->numJointTrackers()) {
@ -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);
}

View file

@ -44,7 +44,6 @@ private:
SpatialEvent _eventCache;
bool _isActive;
signals:
};
@ -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;