mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 19:29:47 +02:00
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:
parent
d6104e5d48
commit
c6e308bc87
10 changed files with 333 additions and 625 deletions
|
@ -1709,9 +1709,7 @@ void Application::init() {
|
||||||
_faceplus.init();
|
_faceplus.init();
|
||||||
_visage.init();
|
_visage.init();
|
||||||
|
|
||||||
Leapmotion* leap = new Leapmotion();
|
Leapmotion* leap = Leapmotion::create();
|
||||||
int index = DeviceTracker::registerDevice( "Leapmotion", leap );
|
|
||||||
// _leapmotion.init();
|
|
||||||
|
|
||||||
// fire off an immediate domain-server check in now that settings are loaded
|
// fire off an immediate domain-server check in now that settings are loaded
|
||||||
NodeList::getInstance()->sendDomainServerCheckIn();
|
NodeList::getInstance()->sendDomainServerCheckIn();
|
||||||
|
|
|
@ -312,35 +312,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
|
||||||
-MAX_LEAN, MAX_LEAN));
|
-MAX_LEAN, MAX_LEAN));
|
||||||
head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
|
head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
|
||||||
-MAX_LEAN, MAX_LEAN));
|
-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() {
|
void MyAvatar::moveWithLean() {
|
||||||
|
|
|
@ -11,72 +11,74 @@
|
||||||
|
|
||||||
#include "DeviceTracker.h"
|
#include "DeviceTracker.h"
|
||||||
|
|
||||||
// The singleton managing the connected devices
|
DeviceTracker::SingletonData::~SingletonData() {
|
||||||
//template <> DeviceTracker::Singleton DeviceTracker::Singleton::_singleton;
|
// Destroy all the device registered
|
||||||
//TemplateSingleton<DeviceTracker::SingletonData>::_singleton;
|
for (auto device = _devicesVector.begin(); device != _devicesVector.end(); device++) {
|
||||||
|
delete (*device);
|
||||||
int DeviceTracker::init() {
|
}
|
||||||
return Singleton::get()->_devicesMap.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceTracker::getNumDevices() {
|
int DeviceTracker::getNumDevices() {
|
||||||
return Singleton::get()->_devicesMap.size();
|
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 );
|
auto deviceIt = Singleton::get()->_devicesMap.find(name);
|
||||||
if ( deviceIt != Singleton::get()->_devicesMap.end() )
|
if (deviceIt != Singleton::get()->_devicesMap.end()) {
|
||||||
return (*deviceIt).second;
|
return (*deviceIt).second;
|
||||||
else
|
} else {
|
||||||
return -1;
|
return INVALID_DEVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceTracker* DeviceTracker::getDevice( const Name& name ) {
|
DeviceTracker* DeviceTracker::getDevice(const Name& name) {
|
||||||
return getDevice( getDeviceIndex( name ) );
|
return getDevice(getDeviceID(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceTracker* DeviceTracker::getDevice( int deviceNum ) {
|
DeviceTracker* DeviceTracker::getDevice(DeviceTracker::ID deviceID) {
|
||||||
if ( (deviceNum >= 0) && ( deviceNum < Singleton::get()->_devicesVector.size() ) ) {
|
if ((deviceID >= 0) && deviceID < Singleton::get()->_devicesVector.size()) {
|
||||||
return Singleton::get()->_devicesVector[ deviceNum ];
|
return Singleton::get()->_devicesVector[ deviceID ];
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceTracker::registerDevice( const Name& name, DeviceTracker* device ) {
|
DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker* device) {
|
||||||
if ( !device )
|
// Check that the device exists, if not exit
|
||||||
return -1;
|
if (!device) {
|
||||||
int index = getDeviceIndex( name );
|
return INVALID_DEVICE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()
|
void DeviceTracker::updateAll() {
|
||||||
{
|
for (auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++) {
|
||||||
for ( auto deviceIt = Singleton::get()->_devicesVector.begin(); deviceIt != Singleton::get()->_devicesVector.end(); deviceIt++ ) {
|
if ((*deviceIt))
|
||||||
if ( (*deviceIt) )
|
|
||||||
(*deviceIt)->update();
|
(*deviceIt)->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Core features of the Device Tracker
|
// Core features of the Device Tracker
|
||||||
|
DeviceTracker::DeviceTracker() :
|
||||||
DeviceTracker::DeviceTracker()
|
_ID(INVALID_DEVICE),
|
||||||
|
_name("Unkown")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceTracker::~DeviceTracker()
|
DeviceTracker::~DeviceTracker() {
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeviceTracker::isConnected() const {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceTracker::update() {
|
void DeviceTracker::update() {
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
#ifndef hifi_DeviceTracker_h
|
#ifndef hifi_DeviceTracker_h
|
||||||
#define hifi_DeviceTracker_h
|
#define hifi_DeviceTracker_h
|
||||||
|
|
||||||
#include <QObject>
|
#include <string>
|
||||||
#include <QVector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
// Singleton template class
|
// Singleton template class
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
class TemplateSingleton {
|
class TemplateSingleton {
|
||||||
public:
|
public:
|
||||||
|
@ -47,41 +46,67 @@ template <typename T>
|
||||||
TemplateSingleton<T> TemplateSingleton<T>::_singleton;
|
TemplateSingleton<T> TemplateSingleton<T>::_singleton;
|
||||||
|
|
||||||
/// Base class for device trackers.
|
/// Base class for device trackers.
|
||||||
class DeviceTracker : public QObject {
|
class DeviceTracker {
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// THe ID and Name types used to manage the pool of devices
|
||||||
typedef std::string Name;
|
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
|
// Singleton interface to register and query the devices currently connected
|
||||||
|
|
||||||
static int init();
|
|
||||||
static int getNumDevices();
|
static int getNumDevices();
|
||||||
static int getDeviceIndex( const Name& name );
|
static ID getDeviceID(const Name& name);
|
||||||
static DeviceTracker* getDevice( int deviceNum );
|
static DeviceTracker* getDevice(ID deviceID);
|
||||||
static DeviceTracker* getDevice( const Name& name );
|
static DeviceTracker* getDevice(const Name& name);
|
||||||
|
|
||||||
/// Update all the devices calling for their update() function
|
/// 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 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
|
// DeviceTracker interface
|
||||||
virtual bool isConnected() const;
|
|
||||||
virtual void update();
|
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:
|
protected:
|
||||||
DeviceTracker();
|
DeviceTracker();
|
||||||
virtual ~DeviceTracker();
|
virtual ~DeviceTracker();
|
||||||
|
|
||||||
private:
|
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 {
|
struct SingletonData {
|
||||||
typedef std::map< Name, int > Map;
|
typedef std::map< Name, ID > Map;
|
||||||
typedef std::vector< DeviceTracker* > Vector;
|
typedef std::vector< DeviceTracker* > Vector;
|
||||||
Map _devicesMap;
|
Map _devicesMap;
|
||||||
Vector _devicesVector;
|
Vector _devicesVector;
|
||||||
|
|
||||||
|
~SingletonData();
|
||||||
};
|
};
|
||||||
typedef TemplateSingleton< SingletonData > Singleton;
|
typedef TemplateSingleton< SingletonData > Singleton;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,191 +8,26 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
#include "SharedUtil.h"
|
||||||
#include <QTimer>
|
|
||||||
#include <QtDebug>
|
|
||||||
|
|
||||||
#include <FBXReader.h>
|
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "Leapmotion.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 PALMROOT_NUM_JOINTS = 3;
|
||||||
const int FINGER_NUM_JOINTS = 4;
|
const int FINGER_NUM_JOINTS = 4;
|
||||||
const int HAND_NUM_JOINTS = FINGER_NUM_JOINTS*5+PALMROOT_NUM_JOINTS;
|
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
|
// find the index of a joint from
|
||||||
// the side: true = right
|
// the side: true = right
|
||||||
// the finger & the bone:
|
// the finger & the bone:
|
||||||
// finger in [0..4] : bone in [0..3] a finger phalange
|
// finger in [0..4] : bone in [0..3] a finger phalange
|
||||||
// [-1] up the hand branch : bone in [0..2] <=> [ hand, forearm, arm]
|
// [-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
|
MotionTracker::Index offset = 1 // start after root
|
||||||
+ (int(isRightSide) * HAND_NUM_JOINTS) // then offset for side
|
+ (int(isRightSide) * HAND_NUM_JOINTS) // then offset for side
|
||||||
+ PALMROOT_NUM_JOINTS; // then add the arm/forearm/hand chain
|
+ 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
|
// from there go down in the correct finger and bone
|
||||||
return offset + (finger * FINGER_NUM_JOINTS) + bone;
|
return offset + (finger * FINGER_NUM_JOINTS) + bone;
|
||||||
} else {
|
} 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() :
|
Leapmotion::Leapmotion() :
|
||||||
MotionTracker(),
|
MotionTracker(),
|
||||||
_enabled(false),
|
|
||||||
_active(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
|
// Create the Leapmotion joint hierarchy
|
||||||
{
|
std::vector< Semantic > sides;
|
||||||
std::vector< Semantic > sides;
|
sides.push_back("joint_L_");
|
||||||
sides.push_back( "joint_L_" );
|
sides.push_back("joint_R_");
|
||||||
sides.push_back( "joint_R_" );
|
|
||||||
|
|
||||||
std::vector< Semantic > rootBones;
|
std::vector< Semantic > rootBones;
|
||||||
rootBones.push_back( "elbow" );
|
rootBones.push_back("elbow");
|
||||||
rootBones.push_back( "hand" );
|
rootBones.push_back("hand");
|
||||||
rootBones.push_back( "wrist" );
|
rootBones.push_back("wrist");
|
||||||
|
|
||||||
std::vector< Semantic > fingers;
|
std::vector< Semantic > fingers;
|
||||||
fingers.push_back( "thumb" );
|
fingers.push_back("thumb");
|
||||||
fingers.push_back( "index" );
|
fingers.push_back("index");
|
||||||
fingers.push_back( "middle" );
|
fingers.push_back("middle");
|
||||||
fingers.push_back( "ring" );
|
fingers.push_back("ring");
|
||||||
fingers.push_back( "pinky" );
|
fingers.push_back("pinky");
|
||||||
|
|
||||||
std::vector< Semantic > fingerBones;
|
std::vector< Semantic > fingerBones;
|
||||||
fingerBones.push_back( "1" );
|
fingerBones.push_back("1");
|
||||||
fingerBones.push_back( "2" );
|
fingerBones.push_back("2");
|
||||||
fingerBones.push_back( "3" );
|
fingerBones.push_back("3");
|
||||||
fingerBones.push_back( "4" );
|
fingerBones.push_back("4");
|
||||||
|
|
||||||
std::vector< Index > palms;
|
std::vector< Index > palms;
|
||||||
for ( int s = 0; s < sides.size(); s++ ) {
|
for (unsigned int s = 0; s < sides.size(); s++) {
|
||||||
Index rootJoint = 0;
|
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 );
|
rootJoint = addJoint(sides[s] + rootBones[rb], rootJoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// capture the hand index for debug
|
// capture the hand index for debug
|
||||||
palms.push_back( rootJoint );
|
palms.push_back(rootJoint);
|
||||||
|
|
||||||
for ( int f = 0; f < fingers.size(); f++ ) {
|
for (unsigned int f = 0; f < fingers.size(); f++) {
|
||||||
for ( int b = 0; b < fingerBones.size(); b++ ) {
|
for (unsigned int b = 0; b < fingerBones.size(); b++) {
|
||||||
rootJoint = addJoint( sides[s] + fingers[f] + fingerBones[b], rootJoint );
|
rootJoint = addJoint(sides[s] + fingers[f] + fingerBones[b], rootJoint);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Leapmotion::~Leapmotion() {
|
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
|
#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...
|
// 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 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 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 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)));
|
glm::quat orientation = (glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis)));
|
||||||
return orientation;
|
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 vec3FromLeapVector(const Leap::Vector& vec) {
|
||||||
glm::vec3 yAxis = glm::normalize( -glm::vec3( normal.x, normal.y, normal.z) );
|
return glm::vec3(vec.x * METERS_PER_MILLIMETER, vec.y * METERS_PER_MILLIMETER, vec.z * METERS_PER_MILLIMETER);
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Leapmotion::update() {
|
void Leapmotion::update() {
|
||||||
#ifdef HAVE_LEAPMOTION
|
#ifdef HAVE_LEAPMOTION
|
||||||
|
// Check that the controller is actually active
|
||||||
_active = _controller.isConnected();
|
_active = _controller.isConnected();
|
||||||
if (!_active) {
|
if (!_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// go through all the joints and increment their counter since last update
|
// 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();
|
(*jointIt).tickNewFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
float deltaTime = 0.001f;
|
|
||||||
|
|
||||||
// Get the most recent frame and report some basic information
|
// Get the most recent frame and report some basic information
|
||||||
const Leap::Frame frame = _controller.frame();
|
const Leap::Frame frame = _controller.frame();
|
||||||
static int64_t lastFrame = -1;
|
static int64_t lastFrameID = -1;
|
||||||
int64_t newFrameNb = frame.id();
|
int64_t newFrameID = frame.id();
|
||||||
|
|
||||||
if ( (lastFrame >= newFrameNb) )
|
// If too soon then exit
|
||||||
|
if (lastFrameID >= newFrameID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glm::vec3 delta(0.f);
|
glm::vec3 delta(0.f);
|
||||||
glm::quat handOri;
|
glm::quat handOri;
|
||||||
if ( !frame.hands().isEmpty() ) {
|
if (!frame.hands().isEmpty()) {
|
||||||
for ( int handNum = 0; handNum < frame.hands().count(); handNum++ ) {
|
for (int handNum = 0; handNum < frame.hands().count(); handNum++) {
|
||||||
|
|
||||||
const Leap::Hand hand = frame.hands()[handNum];
|
const Leap::Hand hand = frame.hands()[handNum];
|
||||||
int side = ( hand.isRight() ? 1 : -1 );
|
int side = (hand.isRight() ? 1 : -1);
|
||||||
Index handIndex = evalJointIndex( (side > 0), -1, 0 );
|
|
||||||
|
|
||||||
JointTracker* parentJointTracker = _jointsArray.data();
|
JointTracker* parentJointTracker = _jointsArray.data();
|
||||||
|
|
||||||
// only in SDK 2.0.3
|
|
||||||
|
int rootBranchIndex = -1;
|
||||||
|
|
||||||
Leap::Arm arm = hand.arm();
|
Leap::Arm arm = hand.arm();
|
||||||
if ( arm.isValid() ) {
|
if (arm.isValid()) {
|
||||||
glm::quat ori = quatFromLeapBase(float(side), arm.basis() );
|
glm::quat ori = quatFromLeapBase(float(side), arm.basis());
|
||||||
|
|
||||||
glm::vec3 pos = vec3FromLeapVector(arm.elbowPosition());
|
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().setTranslation(pos);
|
||||||
elbow->editAbsFrame().setRotation( ori );
|
elbow->editAbsFrame().setRotation(ori);
|
||||||
elbow->updateLocFromAbsTransform( parentJointTracker );
|
elbow->updateLocFromAbsTransform(parentJointTracker);
|
||||||
elbow->activeFrame();
|
elbow->activeFrame();
|
||||||
parentJointTracker = elbow;
|
parentJointTracker = elbow;
|
||||||
|
|
||||||
pos = vec3FromLeapVector(arm.wristPosition());
|
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().setTranslation(pos);
|
||||||
wrist->editAbsFrame().setRotation( ori );
|
wrist->editAbsFrame().setRotation(ori);
|
||||||
wrist->updateLocFromAbsTransform( parentJointTracker );
|
wrist->updateLocFromAbsTransform(parentJointTracker);
|
||||||
wrist->activeFrame();
|
wrist->activeFrame();
|
||||||
parentJointTracker = wrist;
|
parentJointTracker = wrist;
|
||||||
}
|
}
|
||||||
|
@ -359,12 +185,12 @@ void Leapmotion::update() {
|
||||||
JointTracker* palmJoint = NULL;
|
JointTracker* palmJoint = NULL;
|
||||||
{
|
{
|
||||||
glm::vec3 pos = vec3FromLeapVector(hand.palmPosition());
|
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 = editJointTracker(evalJointIndex((side > 0), rootBranchIndex, 0)); // 0 is the index of the palm joint
|
||||||
palmJoint->editAbsFrame().setTranslation( pos );
|
palmJoint->editAbsFrame().setTranslation(pos);
|
||||||
palmJoint->editAbsFrame().setRotation( ori );
|
palmJoint->editAbsFrame().setRotation(ori);
|
||||||
palmJoint->updateLocFromAbsTransform( parentJointTracker );
|
palmJoint->updateLocFromAbsTransform(parentJointTracker);
|
||||||
palmJoint->activeFrame();
|
palmJoint->activeFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,19 +203,19 @@ void Leapmotion::update() {
|
||||||
parentJointTracker = palmJoint;
|
parentJointTracker = palmJoint;
|
||||||
|
|
||||||
// surprisingly, Leap::Finger::Type start at 0 for thumb a until 4 for the pinky
|
// 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
|
// 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::Type type = Leap::Bone::Type(b + Leap::Bone::TYPE_METACARPAL);
|
||||||
Leap::Bone bone = fingers[i].bone( type );
|
Leap::Bone bone = fingers[i].bone(type);
|
||||||
JointTracker* ljointTracker = editJointTracker( fingerIndex + b );
|
JointTracker* ljointTracker = editJointTracker(fingerIndex + b);
|
||||||
if ( bone.isValid() ) {
|
if (bone.isValid()) {
|
||||||
Leap::Vector bp = bone.nextJoint();
|
Leap::Vector bp = bone.nextJoint();
|
||||||
|
|
||||||
ljointTracker->editAbsFrame().setTranslation( vec3FromLeapVector( bp ) );
|
ljointTracker->editAbsFrame().setTranslation(vec3FromLeapVector(bp));
|
||||||
ljointTracker->editAbsFrame().setRotation(quatFromLeapBase( float(side), bone.basis() ) );
|
ljointTracker->editAbsFrame().setRotation(quatFromLeapBase(float(side), bone.basis()));
|
||||||
ljointTracker->updateLocFromAbsTransform( parentJointTracker );
|
ljointTracker->updateLocFromAbsTransform(parentJointTracker);
|
||||||
ljointTracker->activeFrame();
|
ljointTracker->activeFrame();
|
||||||
}
|
}
|
||||||
parentJointTracker = ljointTracker;
|
parentJointTracker = ljointTracker;
|
||||||
|
@ -399,83 +225,6 @@ void Leapmotion::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastFrame = newFrameNb;
|
lastFrameID = newFrameID;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,54 +22,26 @@
|
||||||
|
|
||||||
/// Handles interaction with the Leapmotion skeleton tracking suit.
|
/// Handles interaction with the Leapmotion skeleton tracking suit.
|
||||||
class Leapmotion : public MotionTracker {
|
class Leapmotion : public MotionTracker {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const Name NAME;
|
||||||
|
|
||||||
|
/// Leapmotion MotionTracker factory
|
||||||
|
static Leapmotion* create();
|
||||||
|
|
||||||
|
bool isActive() const { return _active; }
|
||||||
|
|
||||||
|
virtual void update();
|
||||||
|
|
||||||
|
protected:
|
||||||
Leapmotion();
|
Leapmotion();
|
||||||
virtual ~Leapmotion();
|
virtual ~Leapmotion();
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
bool isActive() const { return _active; }
|
|
||||||
|
|
||||||
void update();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
void updateEnabled();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef HAVE_LEAPMOTION
|
#ifdef HAVE_LEAPMOTION
|
||||||
|
Leap::Listener _listener;
|
||||||
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::Controller _controller;
|
Leap::Controller _controller;
|
||||||
#endif
|
#endif
|
||||||
glm::vec3 _leapBasePos;
|
|
||||||
glm::quat _leapBaseOri;
|
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
|
||||||
|
|
||||||
bool _enabled;
|
|
||||||
bool _active;
|
bool _active;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,64 +12,60 @@
|
||||||
#include "MotionTracker.h"
|
#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 {
|
namespace glm {
|
||||||
mat4x3 mult( const mat4& lhs, const mat4x3& rhs ) {
|
mat4x3 mult(const mat4& lhs, const mat4x3& rhs) {
|
||||||
vec3 lrx( lhs[0].x, lhs[1].x, lhs[2].x );
|
vec3 lrx(lhs[0].x, lhs[1].x, lhs[2].x);
|
||||||
vec3 lry( lhs[0].y, lhs[1].y, lhs[2].y );
|
vec3 lry(lhs[0].y, lhs[1].y, lhs[2].y);
|
||||||
vec3 lrz( lhs[0].z, lhs[1].z, lhs[2].z );
|
vec3 lrz(lhs[0].z, lhs[1].z, lhs[2].z);
|
||||||
return mat4x3(
|
return mat4x3(
|
||||||
dot( lrx, rhs[0] ),
|
dot(lrx, rhs[0]),
|
||||||
dot( lry, rhs[0] ),
|
dot(lry, rhs[0]),
|
||||||
dot( lrz, rhs[0] ),
|
dot(lrz, rhs[0]),
|
||||||
|
|
||||||
dot( lrx, rhs[1] ),
|
dot(lrx, rhs[1]),
|
||||||
dot( lry, rhs[1] ),
|
dot(lry, rhs[1]),
|
||||||
dot( lrz, rhs[1] ),
|
dot(lrz, rhs[1]),
|
||||||
|
|
||||||
dot( lrx, rhs[2] ),
|
dot(lrx, rhs[2]),
|
||||||
dot( lry, rhs[2] ),
|
dot(lry, rhs[2]),
|
||||||
dot( lrz, rhs[2] ),
|
dot(lrz, rhs[2]),
|
||||||
|
|
||||||
dot( lrx, rhs[3] ) + lhs[3].x,
|
dot(lrx, rhs[3]) + lhs[3].x,
|
||||||
dot( lry, rhs[3] ) + lhs[3].y,
|
dot(lry, rhs[3]) + lhs[3].y,
|
||||||
dot( lrz, rhs[3] ) + lhs[3].z
|
dot(lrz, rhs[3]) + lhs[3].z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
mat4x3 mult( const mat4x3& lhs, const mat4x3& rhs ) {
|
mat4x3 mult(const mat4x3& lhs, const mat4x3& rhs) {
|
||||||
vec3 lrx( lhs[0].x, lhs[1].x, lhs[2].x );
|
vec3 lrx(lhs[0].x, lhs[1].x, lhs[2].x);
|
||||||
vec3 lry( lhs[0].y, lhs[1].y, lhs[2].y );
|
vec3 lry(lhs[0].y, lhs[1].y, lhs[2].y);
|
||||||
vec3 lrz( lhs[0].z, lhs[1].z, lhs[2].z );
|
vec3 lrz(lhs[0].z, lhs[1].z, lhs[2].z);
|
||||||
return mat4x3(
|
return mat4x3(
|
||||||
dot( lrx, rhs[0] ),
|
dot(lrx, rhs[0]),
|
||||||
dot( lry, rhs[0] ),
|
dot(lry, rhs[0]),
|
||||||
dot( lrz, rhs[0] ),
|
dot(lrz, rhs[0]),
|
||||||
|
|
||||||
dot( lrx, rhs[1] ),
|
dot(lrx, rhs[1]),
|
||||||
dot( lry, rhs[1] ),
|
dot(lry, rhs[1]),
|
||||||
dot( lrz, rhs[1] ),
|
dot(lrz, rhs[1]),
|
||||||
|
|
||||||
dot( lrx, rhs[2] ),
|
dot(lrx, rhs[2]),
|
||||||
dot( lry, rhs[2] ),
|
dot(lry, rhs[2]),
|
||||||
dot( lrz, rhs[2] ),
|
dot(lrz, rhs[2]),
|
||||||
|
|
||||||
dot( lrx, rhs[3] ) + lhs[3].x,
|
dot(lrx, rhs[3]) + lhs[3].x,
|
||||||
dot( lry, rhs[3] ) + lhs[3].y,
|
dot(lry, rhs[3]) + lhs[3].y,
|
||||||
dot( lrz, rhs[3] ) + lhs[3].z
|
dot(lrz, rhs[3]) + lhs[3].z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
// MotionTracker
|
// MotionTracker
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
MotionTracker::MotionTracker() :
|
MotionTracker::MotionTracker() :
|
||||||
DeviceTracker()
|
DeviceTracker()
|
||||||
{
|
{
|
||||||
_jointsArray.resize(1);
|
_jointsArray.resize(1);
|
||||||
_jointsMap.insert( JointTracker::map::value_type( Semantic( "Root" ), 0 ) );
|
_jointsMap.insert(JointTracker::map::value_type(Semantic("Root"), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionTracker::~MotionTracker()
|
MotionTracker::~MotionTracker()
|
||||||
|
@ -80,45 +76,43 @@ bool MotionTracker::isConnected() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionTracker::Index MotionTracker::addJoint( const Semantic& semantic, Index parent ) {
|
MotionTracker::Index MotionTracker::addJoint(const Semantic& semantic, Index parent) {
|
||||||
// Check the parent
|
// Check the parent
|
||||||
if ( int(parent) < 0 )
|
if (int(parent) < 0)
|
||||||
return INVALID_PARENT;
|
return INVALID_PARENT;
|
||||||
|
|
||||||
// Check that the semantic is not already in use
|
// Check that the semantic is not already in use
|
||||||
Index foundIndex = findJointIndex( semantic );
|
Index foundIndex = findJointIndex(semantic);
|
||||||
if ( int(foundIndex) >= 0 )
|
if (foundIndex >= 0)
|
||||||
return INVALID_SEMANTIC;
|
return INVALID_SEMANTIC;
|
||||||
|
|
||||||
// All good then allocate the joint
|
// All good then allocate the joint
|
||||||
Index newIndex = _jointsArray.size();
|
Index newIndex = _jointsArray.size();
|
||||||
_jointsArray.push_back( JointTracker( semantic, parent ) );
|
_jointsArray.push_back(JointTracker(semantic, parent));
|
||||||
_jointsMap.insert( JointTracker::map::value_type( semantic, newIndex ) );
|
_jointsMap.insert(JointTracker::map::value_type(semantic, newIndex));
|
||||||
|
|
||||||
return newIndex;
|
return newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionTracker::Index MotionTracker::findJointIndex( const Semantic& semantic ) const {
|
MotionTracker::Index MotionTracker::findJointIndex(const Semantic& semantic) const {
|
||||||
auto jointIt = _jointsMap.find( semantic );
|
auto jointIt = _jointsMap.find(semantic);
|
||||||
if ( jointIt != _jointsMap.end() )
|
if (jointIt != _jointsMap.end())
|
||||||
return (*jointIt).second;
|
return (*jointIt).second;
|
||||||
return INVALID_SEMANTIC;
|
return INVALID_SEMANTIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::updateAllAbsTransform() {
|
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
|
// 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;
|
JointTracker* joint = _jointsArray.data() + i;
|
||||||
joint->updateAbsFromLocTransform( _jointsArray.data() + joint->getParent() );
|
joint->updateAbsFromLocTransform(_jointsArray.data() + joint->getParent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
// MotionTracker::JointTracker
|
|
||||||
//--------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
// MotionTracker::JointTracker
|
||||||
MotionTracker::JointTracker::JointTracker() :
|
MotionTracker::JointTracker::JointTracker() :
|
||||||
_locFrame(),
|
_locFrame(),
|
||||||
_absFrame(),
|
_absFrame(),
|
||||||
|
@ -128,36 +122,34 @@ MotionTracker::JointTracker::JointTracker() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionTracker::JointTracker::JointTracker( const Semantic& semantic, Index parent ) :
|
MotionTracker::JointTracker::JointTracker(const Semantic& semantic, Index parent) :
|
||||||
_semantic( semantic ),
|
_semantic(semantic),
|
||||||
_parent( parent ),
|
_parent(parent),
|
||||||
_lastUpdate( 0 )
|
_lastUpdate(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionTracker::JointTracker::JointTracker( const JointTracker& tracker ) :
|
MotionTracker::JointTracker::JointTracker(const JointTracker& tracker) :
|
||||||
_locFrame( tracker._locFrame ),
|
_locFrame(tracker._locFrame),
|
||||||
_absFrame( tracker._absFrame ),
|
_absFrame(tracker._absFrame),
|
||||||
_semantic( tracker._semantic ),
|
_semantic(tracker._semantic),
|
||||||
_parent( tracker._parent ),
|
_parent(tracker._parent),
|
||||||
_lastUpdate( tracker._lastUpdate )
|
_lastUpdate(tracker._lastUpdate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::JointTracker::updateAbsFromLocTransform(const JointTracker* parentJoint) {
|
void MotionTracker::JointTracker::updateAbsFromLocTransform(const JointTracker* parentJoint) {
|
||||||
if ( parentJoint ) {
|
if (parentJoint) {
|
||||||
//editAbsFrame()._transform = glm::mult( parentJoint->getAbsFrame()._transform, getLocFrame()._transform );
|
editAbsFrame()._transform = (parentJoint->getAbsFrame()._transform * getLocFrame()._transform);
|
||||||
editAbsFrame()._transform = ( parentJoint->getAbsFrame()._transform * getLocFrame()._transform );
|
|
||||||
} else {
|
} else {
|
||||||
editAbsFrame()._transform = getLocFrame()._transform;
|
editAbsFrame()._transform = getLocFrame()._transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::JointTracker::updateLocFromAbsTransform(const JointTracker* parentJoint) {
|
void MotionTracker::JointTracker::updateLocFromAbsTransform(const JointTracker* parentJoint) {
|
||||||
if ( parentJoint ) {
|
if (parentJoint) {
|
||||||
// glm::mat4 ip = glm::inverse( glm::mat4( parentJoint->getAbsFrame()._transform ) );
|
glm::mat4 ip = glm::inverse(parentJoint->getAbsFrame()._transform);
|
||||||
glm::mat4 ip = glm::inverse( parentJoint->getAbsFrame()._transform );
|
editLocFrame()._transform = (ip * getAbsFrame()._transform);
|
||||||
// editLocFrame()._transform = glm::mult( ip, getAbsFrame()._transform );
|
|
||||||
editLocFrame()._transform = ( ip * getAbsFrame()._transform );
|
|
||||||
} else {
|
} else {
|
||||||
editLocFrame()._transform = getAbsFrame()._transform;
|
editLocFrame()._transform = getAbsFrame()._transform;
|
||||||
}
|
}
|
||||||
|
@ -172,24 +164,22 @@ 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);
|
||||||
glm::mat3x3 rot = glm::mat3_cast( rotation );
|
_transform[0] = glm::vec4(rot[0], 0.f);
|
||||||
_transform[0] = glm::vec4( rot[0], 0.f );
|
_transform[1] = glm::vec4(rot[1], 0.f);
|
||||||
_transform[1] = glm::vec4( rot[1], 0.f );
|
_transform[2] = glm::vec4(rot[2], 0.f);
|
||||||
_transform[2] = glm::vec4( rot[2], 0.f );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::Frame::getRotation( glm::quat& rotation ) const {
|
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);
|
||||||
rotation = glm::quat_cast( _transform );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::Frame::setTranslation( const glm::vec3& translation ) {
|
void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
|
||||||
_transform[3] = glm::vec4( translation, 1.f );
|
_transform[3] = glm::vec4(translation, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotionTracker::Frame::getTranslation( glm::vec3& translation ) const {
|
void MotionTracker::Frame::getTranslation(glm::vec3& translation) const {
|
||||||
translation = glm::vec3( _transform[3] );
|
translation = glm::vec3(_transform[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,12 @@
|
||||||
|
|
||||||
#include "DeviceTracker.h"
|
#include "DeviceTracker.h"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
/// Base class for device trackers.
|
/// Base class for device trackers.
|
||||||
class MotionTracker : public DeviceTracker {
|
class MotionTracker : public DeviceTracker {
|
||||||
Q_OBJECT
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Frame {
|
class Frame {
|
||||||
|
@ -31,36 +28,35 @@ public:
|
||||||
|
|
||||||
glm::mat4 _transform;
|
glm::mat4 _transform;
|
||||||
|
|
||||||
void setRotation( const glm::quat& rotation );
|
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 setTranslation(const glm::vec3& translation);
|
||||||
void getTranslation( glm::vec3& translation ) const;
|
void getTranslation(glm::vec3& translation) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Semantic and Index types to retreive the JointTrackers of this MotionTracker
|
||||||
typedef std::string Semantic;
|
typedef std::string Semantic;
|
||||||
typedef unsigned int Index;
|
typedef int Index;
|
||||||
|
|
||||||
static const Index INVALID_SEMANTIC = -1;
|
static const Index INVALID_SEMANTIC = -1;
|
||||||
static const Index INVALID_PARENT = -2;
|
static const Index INVALID_PARENT = -2;
|
||||||
|
|
||||||
|
|
||||||
class JointTracker {
|
class JointTracker {
|
||||||
public:
|
public:
|
||||||
typedef std::vector< JointTracker > vector;
|
typedef std::vector< JointTracker > vector;
|
||||||
typedef std::map< Semantic, Index > map;
|
typedef std::map< Semantic, Index > map;
|
||||||
|
|
||||||
JointTracker();
|
JointTracker();
|
||||||
JointTracker( const JointTracker& tracker );
|
JointTracker(const JointTracker& tracker);
|
||||||
JointTracker( const Semantic& semantic, Index parent );
|
JointTracker(const Semantic& semantic, Index parent);
|
||||||
|
|
||||||
const Frame& getLocFrame() const { return _locFrame; }
|
const Frame& getLocFrame() const { return _locFrame; }
|
||||||
Frame& editLocFrame() { 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; }
|
const Frame& getAbsFrame() const { return _absFrame; }
|
||||||
Frame& editAbsFrame() { 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 Semantic& getSemantic() const { return _semantic; }
|
||||||
const Index& getParent() const { return _parent; }
|
const Index& getParent() const { return _parent; }
|
||||||
|
@ -81,29 +77,26 @@ public:
|
||||||
int _lastUpdate;
|
int _lastUpdate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
virtual bool isConnected() const;
|
virtual bool isConnected() const;
|
||||||
|
|
||||||
Index numJointTrackers() const { return _jointsArray.size(); }
|
Index numJointTrackers() const { return _jointsArray.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Access a Joint from it's index.
|
/// Access a Joint from it's index.
|
||||||
/// Index 0 is always the "Root".
|
/// Index 0 is always the "Root".
|
||||||
/// if the index is Invalid then returns NULL.
|
/// if the index is Invalid then returns NULL.
|
||||||
const JointTracker* getJointTracker( Index index ) const { 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 ( int(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.
|
/// 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.
|
/// \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:
|
protected:
|
||||||
MotionTracker();
|
MotionTracker();
|
||||||
virtual ~MotionTracker();
|
virtual ~MotionTracker();
|
||||||
|
|
||||||
JointTracker::vector _jointsArray;
|
JointTracker::vector _jointsArray;
|
||||||
JointTracker::map _jointsMap;
|
JointTracker::map _jointsMap;
|
||||||
|
|
||||||
/// Adding joint is only done from the specialized Motion Tracker, hence this function is protected.
|
/// 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 hierarchy of joints must be created from the top down to the branches.
|
||||||
|
@ -116,7 +109,7 @@ protected:
|
||||||
/// Valid if everything went well.
|
/// Valid if everything went well.
|
||||||
/// INVALID_SEMANTIC if the semantic is already in use
|
/// INVALID_SEMANTIC if the semantic is already in use
|
||||||
/// INVALID_PARENT if the parent is not valid
|
/// 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
|
/// 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.
|
/// This is a generic way to update all the Joint's absFrame by combining the locFrame going down the hierarchy branch.
|
||||||
|
|
|
@ -260,63 +260,69 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
||||||
return glm::vec2(widget->width(), widget->height());
|
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
|
// This is where we retreive the Device Tracker category and then the sub tracker within it
|
||||||
auto icIt = _inputControllers.find( 0 );
|
auto icIt = _inputControllers.find(0);
|
||||||
if ( icIt != _inputControllers.end() ) {
|
if (icIt != _inputControllers.end()) {
|
||||||
return (*icIt).second;
|
return (*icIt).second;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Look for matching category
|
// Look for device
|
||||||
// TODO in this current implementation, we just pick the first device assuming there is one ( normally the LeapMotion)
|
DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString());
|
||||||
// in the near future we need to change that to a real mapping between the device names and the cateory
|
if (deviceID < 0) {
|
||||||
int categoryID = 0;
|
deviceID = 0;
|
||||||
MotionTracker* motionTracker = dynamic_cast< MotionTracker* > ( DeviceTracker::getDevice( categoryID ) );
|
}
|
||||||
if ( motionTracker ) {
|
// TODO in this current implementation, we just pick the device assuming there is one (normally the Leapmotion)
|
||||||
int trackerID = motionTracker->findJointIndex( tracker.toStdString() );
|
// in the near future we need to change that to a real mapping between the devices and the deviceName
|
||||||
if ( trackerID > 0 ) {
|
// ALso we need to expand the spec so we can fall back on the "default" controller per categories
|
||||||
AbstractInputController* inputController = new InputController(categoryID,trackerID, this );
|
|
||||||
|
|
||||||
_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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerScriptingInterface::updateInputControllers()
|
void ControllerScriptingInterface::updateInputControllers() {
|
||||||
{
|
for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) {
|
||||||
for ( auto it = _inputControllers.begin(); it != _inputControllers.end(); it++ ) {
|
|
||||||
(*it).second->update();
|
(*it).second->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
||||||
AbstractInputController(),
|
AbstractInputController(),
|
||||||
_deviceTrackerId( deviceTrackerId ),
|
_deviceTrackerId(deviceTrackerId),
|
||||||
_subTrackerId( subTrackerId )
|
_subTrackerId(subTrackerId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputController::update()
|
void InputController::update() {
|
||||||
{
|
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
|
|
||||||
MotionTracker* motionTracker = dynamic_cast< MotionTracker*> ( DeviceTracker::getDevice( _deviceTrackerId ) );
|
// TODO for now the InputController is only supporting a JointTracker from a MotionTracker
|
||||||
if ( motionTracker ) {
|
MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId));
|
||||||
if ( _subTrackerId < motionTracker->numJointTrackers() ) {
|
if (motionTracker) {
|
||||||
const MotionTracker::JointTracker* joint = motionTracker->getJointTracker( _subTrackerId );
|
if (_subTrackerId < motionTracker->numJointTrackers()) {
|
||||||
|
const MotionTracker::JointTracker* joint = motionTracker->getJointTracker(_subTrackerId);
|
||||||
|
|
||||||
if ( joint->isActive() ) {
|
if (joint->isActive()) {
|
||||||
joint->getAbsFrame().getTranslation( _eventCache.absTranslation );
|
joint->getAbsFrame().getTranslation(_eventCache.absTranslation);
|
||||||
joint->getAbsFrame().getRotation( _eventCache.absRotation );
|
joint->getAbsFrame().getRotation(_eventCache.absRotation);
|
||||||
joint->getLocFrame().getTranslation( _eventCache.locTranslation );
|
joint->getLocFrame().getTranslation(_eventCache.locTranslation);
|
||||||
joint->getLocFrame().getRotation( _eventCache.locRotation );
|
joint->getLocFrame().getRotation(_eventCache.locRotation);
|
||||||
|
|
||||||
_isActive = true;
|
_isActive = true;
|
||||||
emit spatialEvent(_eventCache);
|
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 {
|
InputController::Key InputController::getKey() const {
|
||||||
return (_deviceTrackerId * 10000) + _subTrackerId;
|
return (((_deviceTrackerId & INPUTCONTROLLER_KEY_DEVICE_MASK) << INPUTCONTROLLER_KEY_DEVICE_OFFSET) | _subTrackerId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ private:
|
||||||
SpatialEvent _eventCache;
|
SpatialEvent _eventCache;
|
||||||
bool _isActive;
|
bool _isActive;
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ public:
|
||||||
|
|
||||||
void updateInputControllers();
|
void updateInputControllers();
|
||||||
|
|
||||||
void releaseInputController( AbstractInputController* input );
|
void releaseInputController(AbstractInputController* input);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual bool isPrimaryButtonPressed() const;
|
virtual bool isPrimaryButtonPressed() const;
|
||||||
|
@ -114,7 +113,8 @@ public slots:
|
||||||
|
|
||||||
virtual glm::vec2 getViewportDimensions() const;
|
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:
|
private:
|
||||||
const PalmData* getPrimaryPalm() const;
|
const PalmData* getPrimaryPalm() const;
|
||||||
|
|
Loading…
Reference in a new issue