mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 14:42:19 +02:00
Revert "Revert "Add LeapMotion SDK support""
This reverts commit 8ce145085b3783782fafd051becbb0e339d5dfa1.
This commit is contained in:
parent
6b549a5269
commit
fe03743163
5 changed files with 609 additions and 0 deletions
44
cmake/modules/FindLeapMotion.cmake
Normal file
44
cmake/modules/FindLeapMotion.cmake
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Try to find the LeapMotion library
|
||||
#
|
||||
# You must provide a LEAPMOTION_ROOT_DIR which contains lib and include directories
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# LEAPMOTION_FOUND - system found LEAPMOTION
|
||||
# LEAPMOTION_INCLUDE_DIRS - the LEAPMOTION include directory
|
||||
# LEAPMOTION_LIBRARIES - Link this to use LEAPMOTION
|
||||
#
|
||||
# Created on 6/2/2014 by Sam Cake
|
||||
# Copyright (c) 2014 High Fidelity
|
||||
#
|
||||
|
||||
if (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LEAPMOTION_FOUND TRUE)
|
||||
else (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
|
||||
set(LEAPMOTION_SEARCH_DIRS "${LEAPMOTION_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/leapmotion")
|
||||
|
||||
find_path(LEAPMOTION_INCLUDE_DIRS Leap.h ${LEAPMOTION_ROOT_DIR}/include)
|
||||
|
||||
if (WIN32)
|
||||
find_library(LEAPMOTION_LIBRARIES Leap.lib ${LEAPMOTION_ROOT_DIR}/lib/x86)
|
||||
endif (WIN32)
|
||||
|
||||
if (LEAPMOTION_INCLUDE_DIRS AND LEAPMOTION_LIBRARIES)
|
||||
set(LEAPMOTION_FOUND TRUE)
|
||||
endif (LEAPMOTION_INCLUDE_DIRS AND LEAPMOTION_LIBRARIES)
|
||||
|
||||
if (LEAPMOTION_FOUND)
|
||||
if (NOT LEAPMOTION_FIND_QUIETLY)
|
||||
message(STATUS "Found LEAPMOTION... ${LEAPMOTION_LIBRARIES}")
|
||||
endif (NOT LEAPMOTION_FIND_QUIETLY)
|
||||
else ()
|
||||
if (LEAPMOTION_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find LEAPMOTION")
|
||||
endif (LEAPMOTION_FIND_REQUIRED)
|
||||
endif ()
|
||||
|
||||
# show the LEAPMOTION_INCLUDE_DIRS and LEAPMOTION_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES)
|
||||
|
||||
endif (LEAPMOTION_LIBRARIES AND LEAPMOTION_INCLUDE_DIRS)
|
|
@ -18,6 +18,7 @@ set(LIBOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/oculus")
|
|||
set(PRIOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/priovr")
|
||||
set(SIXENSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense")
|
||||
set(VISAGE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/visage")
|
||||
set(LEAPMOTION_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/leapmotion")
|
||||
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
find_package(Qt5LinguistToolsMacros)
|
||||
|
@ -138,6 +139,7 @@ find_package(PrioVR)
|
|||
find_package(SDL)
|
||||
find_package(Sixense)
|
||||
find_package(Visage)
|
||||
find_package(LeapMotion)
|
||||
find_package(ZLIB)
|
||||
find_package(Qxmpp)
|
||||
|
||||
|
@ -193,6 +195,13 @@ if (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
|
|||
target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}")
|
||||
endif (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
|
||||
|
||||
# and with LeapMotion library
|
||||
if (LEAPMOTION_FOUND AND NOT DISABLE_LEAPMOTION)
|
||||
add_definitions(-DHAVE_LEAPMOTION)
|
||||
include_directories(SYSTEM "${LEAPMOTION_INCLUDE_DIRS}")
|
||||
target_link_libraries(${TARGET_NAME} "${LEAPMOTION_LIBRARIES}")
|
||||
endif (LEAPMOTION_FOUND AND NOT DISABLE_LEAPMOTION)
|
||||
|
||||
# and with SDL for joysticks
|
||||
if (SDL_FOUND AND NOT DISABLE_SDL)
|
||||
add_definitions(-DHAVE_SDL)
|
||||
|
|
27
interface/external/leapmotion/readme.txt
vendored
Normal file
27
interface/external/leapmotion/readme.txt
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
Instructions for adding the Leap Motion library (LeapSDK) to Interface
|
||||
Sam Cake, June 10, 2014
|
||||
|
||||
You can download the Leap Developer Kit from https://developer.leapmotion.com/ (account creation required). Interface has been tested with SDK version LeapDeveloperKit_2.0.2+16391_win.
|
||||
|
||||
1. Copy the LeapSDK folders from the LeapDeveloperKit installation directory (Lib, Include) into the interface/externals/leapmotion folder.
|
||||
This readme.txt should be there as well.
|
||||
|
||||
The files neeeded in the folders are:
|
||||
|
||||
include/
|
||||
- Leap.h
|
||||
- Leap.i
|
||||
- LeapMath.h
|
||||
|
||||
lib/
|
||||
x86/
|
||||
- Leap.dll
|
||||
- Leap.lib
|
||||
- mscvcp120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
|
||||
- mscvcr120.dll (optional if you already have the Msdev 2012 SDK redistriuable installed)
|
||||
|
||||
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
|
||||
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'leapmotion' that contains the 2 folders mentioned above (Include, Lib).
|
||||
|
||||
2. Clear your build directory, run cmake and build, and you should be all set.
|
441
interface/src/devices/LeapMotionManager.cpp
Normal file
441
interface/src/devices/LeapMotionManager.cpp
Normal file
|
@ -0,0 +1,441 @@
|
|||
//
|
||||
// LeapMotionManager.cpp
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Sam Cake on 6/2/2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QTimer>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <FBXReader.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "LeapMotionManager.h"
|
||||
#include "ui/TextRenderer.h"
|
||||
|
||||
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
|
||||
|
||||
LeapMotionManager::SampleListener::SampleListener() : ::Leap::Listener()
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
|
||||
LeapMotionManager::SampleListener::~SampleListener()
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
|
||||
void LeapMotionManager::SampleListener::onConnect(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onDisconnect(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onExit(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onFocusGained(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onFocusLost(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onFrame(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onInit(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::SampleListener::onServiceConnect(const ::Leap::Controller &)
|
||||
{
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
}
|
||||
void LeapMotionManager::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
|
||||
|
||||
LeapMotionManager::LeapMotionManager() {
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
|
||||
// Have the sample listener receive events from the controller
|
||||
_controller.addListener(_listener);
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
LeapMotionManager::~LeapMotionManager() {
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
// Remove the sample listener when done
|
||||
_controller.removeListener(_listener);
|
||||
#endif
|
||||
}
|
||||
|
||||
const int HEAD_ROTATION_INDEX = 0;
|
||||
|
||||
glm::vec3 LeapMotionManager::getHandPos( unsigned int handNb ) const
|
||||
{
|
||||
if ( handNb < _hands.size() )
|
||||
{
|
||||
return _hands[ handNb ];
|
||||
}
|
||||
else
|
||||
return glm::vec3(0.f);
|
||||
}
|
||||
|
||||
void LeapMotionManager::update(float deltaTime) {
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
|
||||
if ( !_controller.isConnected() )
|
||||
return;
|
||||
|
||||
|
||||
// Get the most recent frame and report some basic information
|
||||
const Leap::Frame frame = _controller.frame();
|
||||
static _int64 lastFrame = -1;
|
||||
_hands.clear();
|
||||
_int64 newFrameNb = frame.id();
|
||||
|
||||
if ( (lastFrame >= newFrameNb) )
|
||||
return;
|
||||
|
||||
glm::vec3 delta(0.f);
|
||||
glm::quat handOri;
|
||||
if (!frame.hands().isEmpty())
|
||||
{
|
||||
// Get the first hand
|
||||
const Leap::Hand hand = frame.hands()[0];
|
||||
Leap::Vector lp = hand.palmPosition();
|
||||
glm::vec3 p(lp.x * METERS_PER_MILLIMETER, lp.y * METERS_PER_MILLIMETER, lp.z * METERS_PER_MILLIMETER );
|
||||
|
||||
Leap::Vector n = hand.palmNormal();
|
||||
glm::vec3 xAxis(n.x, n.y, n.z);
|
||||
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));
|
||||
handOri = glm::inverse(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis)));
|
||||
|
||||
_hands.push_back( p );
|
||||
|
||||
|
||||
//Leap::Vector dp = hand.translation( _controller.frame( lastFrame ) );
|
||||
Leap::Vector dp = hand.palmVelocity();
|
||||
delta = glm::vec3( dp.x * METERS_PER_MILLIMETER, dp.y * METERS_PER_MILLIMETER, dp.z * METERS_PER_MILLIMETER);
|
||||
}
|
||||
lastFrame = newFrameNb;
|
||||
|
||||
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||
Hand* hand = avatar->getHand();
|
||||
|
||||
// for ( int h = 0; h < frame.hands().count(); h++ )
|
||||
if ( _hands.size() )
|
||||
{
|
||||
|
||||
// Set palm position and normal based on Hydra position/orientation
|
||||
|
||||
// Either find a palm matching the sixense controller, or make a new one
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||
if (hand->getPalms()[j].getSixenseID() == 28) {
|
||||
palm = &(hand->getPalms()[j]);
|
||||
foundHand = true;
|
||||
}
|
||||
}
|
||||
if (!foundHand) {
|
||||
PalmData newPalm(hand);
|
||||
hand->getPalms().push_back(newPalm);
|
||||
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
|
||||
palm->setSixenseID(28);
|
||||
qDebug("Found new LeapMotion hand, ID %i", 28);
|
||||
}
|
||||
|
||||
palm->setActive(true);
|
||||
|
||||
// Read controller buttons and joystick into the hand
|
||||
//palm->setControllerButtons(data->buttons);
|
||||
//palm->setTrigger(data->trigger);
|
||||
//palm->setJoystick(data->joystick_x, data->joystick_y);
|
||||
|
||||
glm::vec3 position(_hands[0]);
|
||||
|
||||
// Transform the measured position into body frame.
|
||||
glm::vec3 neck = _leapBasePos;
|
||||
// Zeroing y component of the "neck" effectively raises the measured position a little bit.
|
||||
//neck.y = 0.f;
|
||||
position = _leapBaseOri * (position - neck);
|
||||
|
||||
// Rotation of Palm
|
||||
glm::quat rotation(handOri[3], -handOri[0], handOri[1], -handOri[2]);
|
||||
rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _leapBaseOri * rotation;
|
||||
|
||||
// Compute current velocity from position change
|
||||
glm::vec3 rawVelocity;
|
||||
if (deltaTime > 0.f) {
|
||||
// rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
||||
rawVelocity = delta / deltaTime;
|
||||
} else {
|
||||
rawVelocity = glm::vec3(0.0f);
|
||||
}
|
||||
palm->setRawVelocity(rawVelocity); // meters/sec
|
||||
|
||||
// Use a velocity sensitive filter to damp small motions and preserve large ones with
|
||||
// no latency.
|
||||
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
||||
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
|
||||
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
|
||||
|
||||
// use the velocity to determine whether there's any movement (if the hand isn't new)
|
||||
/* const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f;
|
||||
_amountMoved += rawVelocity * deltaTime;
|
||||
if (glm::length(_amountMoved) > MOVEMENT_DISTANCE_THRESHOLD && foundHand) {
|
||||
_lastMovement = usecTimestampNow();
|
||||
_amountMoved = glm::vec3(0.0f);
|
||||
}*/
|
||||
|
||||
// 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);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either find a palm matching the sixense controller, or make a new one
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (size_t j = 0; j < hand->getNumPalms(); j++) {
|
||||
if (hand->getPalms()[j].getSixenseID() == 28) {
|
||||
palm = &(hand->getPalms()[j]);
|
||||
foundHand = true;
|
||||
}
|
||||
}
|
||||
if (foundHand) {
|
||||
palm->setRawPosition(palm->getRawPosition());
|
||||
palm->setRawRotation(palm->getRawRotation());
|
||||
palm->setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if (numActiveControllers == 2) {
|
||||
updateCalibration(controllers);
|
||||
}
|
||||
*/
|
||||
|
||||
// }
|
||||
|
||||
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 LeapMotionManager::reset() {
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
if (!_controller.isConnected()) {
|
||||
return;
|
||||
}
|
||||
/* connect(Application::getInstance(), SIGNAL(renderingOverlay()), SLOT(renderCalibrationCountdown()));
|
||||
_calibrationCountdownStarted = QDateTime::currentDateTime();
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
void LeapMotionManager::renderCalibrationCountdown() {
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
/* const int COUNTDOWN_SECONDS = 3;
|
||||
int secondsRemaining = COUNTDOWN_SECONDS - _calibrationCountdownStarted.secsTo(QDateTime::currentDateTime());
|
||||
if (secondsRemaining == 0) {
|
||||
yei_tareSensors(_skeletalDevice);
|
||||
Application::getInstance()->disconnect(this);
|
||||
return;
|
||||
}
|
||||
static TextRenderer textRenderer(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2);
|
||||
QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "...";
|
||||
textRenderer.draw((Application::getInstance()->getGLWidget()->width() - textRenderer.computeWidth(text.constData())) / 2,
|
||||
Application::getInstance()->getGLWidget()->height() / 2,
|
||||
text);
|
||||
*/
|
||||
#endif
|
||||
}
|
88
interface/src/devices/LeapMotionManager.h
Normal file
88
interface/src/devices/LeapMotionManager.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// LeapMotionManager.h
|
||||
// interface/src/devices
|
||||
//
|
||||
// Created by Sam Cake on 6/2/2014
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_LeapMotionManager_h
|
||||
#define hifi_LeapMotionManager_h
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#ifdef HAVE_LEAPMOTION
|
||||
#include <Leap.h>
|
||||
/*extern "C" {
|
||||
#include <yei_skeletal_api.h>
|
||||
}*/
|
||||
#endif
|
||||
|
||||
/// Handles interaction with the LeapMotionManager skeleton tracking suit.
|
||||
class LeapMotionManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
LeapMotionManager();
|
||||
virtual ~LeapMotionManager();
|
||||
|
||||
bool isActive() const { return !_hands.isEmpty(); }
|
||||
|
||||
int nbHands() const { return _hands.size(); }
|
||||
|
||||
glm::vec3 getHandPos( unsigned int handNb ) const;
|
||||
|
||||
const QVector<int>& getHumanIKJointIndices() const { return _humanIKJointIndices; }
|
||||
const QVector<glm::quat>& getJointRotations() const { return _jointRotations; }
|
||||
|
||||
void update(float deltaTime);
|
||||
void reset();
|
||||
|
||||
private slots:
|
||||
|
||||
void renderCalibrationCountdown();
|
||||
|
||||
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::Controller _controller;
|
||||
#endif
|
||||
glm::vec3 _leapBasePos;
|
||||
glm::quat _leapBaseOri;
|
||||
QVector<glm::vec3> _hands;
|
||||
|
||||
QVector<int> _humanIKJointIndices;
|
||||
QVector<glm::quat> _jointRotations;
|
||||
QVector<glm::quat> _lastJointRotations;
|
||||
|
||||
QDateTime _calibrationCountdownStarted;
|
||||
};
|
||||
|
||||
#endif // hifi_LeapMotionManager_h
|
Loading…
Reference in a new issue