mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 08:23:04 +02:00
(changed per requests and re-merged) Two Leap-related crashes fixed, plus Leap improvements
1. Fixed thread-crash at terminate() time by terminating the LeapManager properly 2. Fixed an intermittent thread-crash when Leap active by removing auto-connection between controller and listener 3. Added fingerRoot positions to display and data packet 4. Introduced a vec3-based convention so that more finger data may be added without causing trouble for old clients and servers 5. My avatar's fingers are different color from others
This commit is contained in:
parent
e85f498ef3
commit
5d59bcbec7
8 changed files with 208 additions and 92 deletions
|
@ -953,6 +953,8 @@ void Application::terminate() {
|
||||||
// Close serial port
|
// Close serial port
|
||||||
// close(serial_fd);
|
// close(serial_fd);
|
||||||
|
|
||||||
|
LeapManager::terminate();
|
||||||
|
|
||||||
if (_settingsAutosave->isChecked()) {
|
if (_settingsAutosave->isChecked()) {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
_settings->sync();
|
_settings->sync();
|
||||||
|
@ -1645,6 +1647,8 @@ void Application::init() {
|
||||||
QMetaObject::invokeMethod(_fullScreenMode, "trigger", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(_fullScreenMode, "trigger", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LeapManager::initialize();
|
||||||
|
|
||||||
gettimeofday(&_timerStart, NULL);
|
gettimeofday(&_timerStart, NULL);
|
||||||
gettimeofday(&_lastTimeIdle, NULL);
|
gettimeofday(&_lastTimeIdle, NULL);
|
||||||
|
|
||||||
|
@ -1803,7 +1807,8 @@ void Application::update(float deltaTime) {
|
||||||
|
|
||||||
// Leap finger-sensing device
|
// Leap finger-sensing device
|
||||||
LeapManager::nextFrame();
|
LeapManager::nextFrame();
|
||||||
_myAvatar.getHand().setLeapFingers(LeapManager::getFingerPositions());
|
_myAvatar.getHand().setLeapFingers(LeapManager::getFingerTips(), LeapManager::getFingerRoots());
|
||||||
|
_myAvatar.getHand().setLeapHands(LeapManager::getHandPositions(), LeapManager::getHandNormals());
|
||||||
|
|
||||||
// Read serial port interface devices
|
// Read serial port interface devices
|
||||||
if (_serialHeadSensor.isActive()) {
|
if (_serialHeadSensor.isActive()) {
|
||||||
|
|
|
@ -107,6 +107,7 @@ public:
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
bool isInitialized () const { return _initialized;}
|
bool isInitialized () const { return _initialized;}
|
||||||
|
bool isMyAvatar () const { return _owningAgent == NULL; }
|
||||||
const Skeleton& getSkeleton () const { return _skeleton;}
|
const Skeleton& getSkeleton () const { return _skeleton;}
|
||||||
float getHeadYawRate () const { return _head.yawRate;}
|
float getHeadYawRate () const { return _head.yawRate;}
|
||||||
float getBodyYaw () const { return _bodyYaw;}
|
float getBodyYaw () const { return _bodyYaw;}
|
||||||
|
@ -155,13 +156,13 @@ public:
|
||||||
void writeAvatarDataToFile();
|
void writeAvatarDataToFile();
|
||||||
void readAvatarDataFromFile();
|
void readAvatarDataFromFile();
|
||||||
|
|
||||||
|
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// privatize copy constructor and assignment operator to avoid copying
|
// privatize copy constructor and assignment operator to avoid copying
|
||||||
Avatar(const Avatar&);
|
Avatar(const Avatar&);
|
||||||
Avatar& operator= (const Avatar&);
|
Avatar& operator= (const Avatar&);
|
||||||
|
|
||||||
bool isMyAvatar() const { return _owningAgent == NULL; }
|
|
||||||
|
|
||||||
struct AvatarBall
|
struct AvatarBall
|
||||||
{
|
{
|
||||||
AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position
|
AvatarJointID parentJoint; // the skeletal joint that serves as a reference for determining the position
|
||||||
|
@ -237,7 +238,6 @@ private:
|
||||||
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
|
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
|
||||||
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||||
void checkForMouseRayTouching();
|
void checkForMouseRayTouching();
|
||||||
void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,21 +21,18 @@ Hand::Hand(Avatar* owningAvatar) :
|
||||||
_owningAvatar(owningAvatar),
|
_owningAvatar(owningAvatar),
|
||||||
_renderAlpha(1.0),
|
_renderAlpha(1.0),
|
||||||
_lookingInMirror(false),
|
_lookingInMirror(false),
|
||||||
_ballColor(0.0, 0.4, 0.0),
|
_ballColor(0.0, 0.0, 0.4),
|
||||||
_position(0.0, 0.4, 0.0),
|
_position(0.0, 0.4, 0.0),
|
||||||
_orientation(0.0, 0.0, 0.0, 1.0)
|
_orientation(0.0, 0.0, 0.0, 1.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::init() {
|
void Hand::init() {
|
||||||
_numLeapBalls = 0;
|
// Different colors for my hand and others' hands
|
||||||
for (int b = 0; b < MAX_AVATAR_LEAP_BALLS; b++) {
|
if (_owningAvatar && _owningAvatar->isMyAvatar())
|
||||||
_leapBall[b].position = glm::vec3(0.0, 0.0, 0.0);
|
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||||
_leapBall[b].velocity = glm::vec3(0.0, 0.0, 0.0);
|
else
|
||||||
_leapBall[b].radius = 0.01;
|
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
||||||
_leapBall[b].touchForce = 0.0;
|
|
||||||
_leapBall[b].isCollidable = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::reset() {
|
void Hand::reset() {
|
||||||
|
@ -44,20 +41,27 @@ void Hand::reset() {
|
||||||
void Hand::simulate(float deltaTime, bool isMine) {
|
void Hand::simulate(float deltaTime, bool isMine) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 Hand::leapPositionToWorldPosition(const glm::vec3& leapPosition) {
|
||||||
|
float unitScale = 0.001; // convert mm to meters
|
||||||
|
return _position + _orientation * (leapPosition * unitScale);
|
||||||
|
}
|
||||||
|
|
||||||
void Hand::calculateGeometry() {
|
void Hand::calculateGeometry() {
|
||||||
glm::vec3 offset(0.1, -0.1, -0.15); // place the hand in front of the face where we can see it
|
glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it
|
||||||
|
|
||||||
Head& head = _owningAvatar->getHead();
|
Head& head = _owningAvatar->getHead();
|
||||||
_position = head.getPosition() + head.getOrientation() * offset;
|
_position = head.getPosition() + head.getOrientation() * offset;
|
||||||
_orientation = head.getOrientation();
|
_orientation = head.getOrientation();
|
||||||
|
|
||||||
_numLeapBalls = _fingerPositions.size();
|
int numLeapBalls = _fingerTips.size() + _fingerRoots.size();
|
||||||
|
_leapBalls.resize(numLeapBalls);
|
||||||
|
|
||||||
float unitScale = 0.001; // convert mm to meters
|
for (int i = 0; i < _fingerTips.size(); ++i) {
|
||||||
for (int b = 0; b < _numLeapBalls; b++) {
|
_leapBalls[i].rotation = _orientation;
|
||||||
glm::vec3 pos = unitScale * _fingerPositions[b] + offset;
|
_leapBalls[i].position = leapPositionToWorldPosition(_fingerTips[i]);
|
||||||
_leapBall[b].rotation = _orientation;
|
_leapBalls[i].radius = 0.01;
|
||||||
_leapBall[b].position = _position + _orientation * pos;
|
_leapBalls[i].touchForce = 0.0;
|
||||||
|
_leapBalls[i].isCollidable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,23 +82,52 @@ void Hand::render(bool lookingInMirror) {
|
||||||
void Hand::renderHandSpheres() {
|
void Hand::renderHandSpheres() {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
// Draw the leap balls
|
// Draw the leap balls
|
||||||
for (int b = 0; b < _numLeapBalls; b++) {
|
for (size_t i = 0; i < _leapBalls.size(); i++) {
|
||||||
float alpha = 1.0f;
|
float alpha = 1.0f;
|
||||||
|
|
||||||
if (alpha > 0.0f) {
|
if (alpha > 0.0f) {
|
||||||
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, alpha); // Just to test
|
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, alpha);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_leapBall[b].position.x, _leapBall[b].position.y, _leapBall[b].position.z);
|
glTranslatef(_leapBalls[i].position.x, _leapBalls[i].position.y, _leapBalls[i].position.z);
|
||||||
glutSolidSphere(_leapBall[b].radius, 20.0f, 20.0f);
|
glutSolidSphere(_leapBalls[i].radius, 20.0f, 20.0f);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw the finger root cones
|
||||||
|
if (_fingerTips.size() == _fingerRoots.size()) {
|
||||||
|
for (size_t i = 0; i < _fingerTips.size(); ++i) {
|
||||||
|
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.5);
|
||||||
|
glm::vec3 tip = leapPositionToWorldPosition(_fingerTips[i]);
|
||||||
|
glm::vec3 root = leapPositionToWorldPosition(_fingerRoots[i]);
|
||||||
|
Avatar::renderJointConnectingCone(root, tip, 0.001, 0.003);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the palms
|
||||||
|
if (_handPositions.size() == _handNormals.size()) {
|
||||||
|
for (size_t i = 0; i < _handPositions.size(); ++i) {
|
||||||
|
glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, 0.25);
|
||||||
|
glm::vec3 tip = leapPositionToWorldPosition(_handPositions[i]);
|
||||||
|
glm::vec3 root = leapPositionToWorldPosition(_handPositions[i] + (_handNormals[i] * 2.0f));
|
||||||
|
Avatar::renderJointConnectingCone(root, tip, 0.05, 0.03);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerPositions) {
|
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerTips,
|
||||||
_fingerPositions = fingerPositions;
|
const std::vector<glm::vec3>& fingerRoots) {
|
||||||
|
_fingerTips = fingerTips;
|
||||||
|
_fingerRoots = fingerRoots;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hand::setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||||
|
const std::vector<glm::vec3>& handNormals) {
|
||||||
|
_handPositions = handPositions;
|
||||||
|
_handNormals = handNormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "SerialInterface.h"
|
#include "SerialInterface.h"
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
|
@ -41,11 +42,13 @@ public:
|
||||||
void render(bool lookingInMirror);
|
void render(bool lookingInMirror);
|
||||||
|
|
||||||
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; }
|
||||||
void setLeapFingers (const std::vector<glm::vec3>& fingerPositions);
|
void setLeapFingers (const std::vector<glm::vec3>& fingerTips,
|
||||||
|
const std::vector<glm::vec3>& fingerRoots);
|
||||||
|
void setLeapHands (const std::vector<glm::vec3>& handPositions,
|
||||||
|
const std::vector<glm::vec3>& handNormals);
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
int getNumLeapBalls () const { return _numLeapBalls;}
|
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
|
||||||
const glm::vec3& getLeapBallPosition (int which) const { return _leapBall[which].position;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
||||||
|
@ -58,12 +61,12 @@ private:
|
||||||
glm::vec3 _ballColor;
|
glm::vec3 _ballColor;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
glm::quat _orientation;
|
glm::quat _orientation;
|
||||||
int _numLeapBalls;
|
std::vector<HandBall> _leapBalls;
|
||||||
HandBall _leapBall[ MAX_AVATAR_LEAP_BALLS ];
|
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
void renderHandSpheres();
|
void renderHandSpheres();
|
||||||
void calculateGeometry();
|
void calculateGeometry();
|
||||||
|
glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,25 +11,43 @@
|
||||||
#include <dlfcn.h> // needed for RTLD_LAZY
|
#include <dlfcn.h> // needed for RTLD_LAZY
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
bool LeapManager::_isInitialized = false;
|
|
||||||
bool LeapManager::_libraryExists = false;
|
bool LeapManager::_libraryExists = false;
|
||||||
Leap::Controller* LeapManager::_controller = 0;
|
Leap::Controller* LeapManager::_controller = NULL;
|
||||||
HifiLeapListener* LeapManager::_listener = 0;
|
HifiLeapListener* LeapManager::_listener = NULL;
|
||||||
|
|
||||||
class HifiLeapListener : public Leap::Listener {
|
class HifiLeapListener : public Leap::Listener {
|
||||||
public:
|
public:
|
||||||
Leap::Frame lastFrame;
|
Leap::Frame lastFrame;
|
||||||
std::vector<glm::vec3> fingerPositions;
|
std::vector<glm::vec3> fingerTips;
|
||||||
|
std::vector<glm::vec3> fingerRoots;
|
||||||
|
std::vector<glm::vec3> handPositions;
|
||||||
|
std::vector<glm::vec3> handNormals;
|
||||||
|
|
||||||
virtual void onFrame(const Leap::Controller& controller) {
|
virtual void onFrame(const Leap::Controller& controller) {
|
||||||
#ifndef LEAP_STUBS
|
#ifndef LEAP_STUBS
|
||||||
Leap::Frame frame = controller.frame();
|
Leap::Frame frame = controller.frame();
|
||||||
int numFingers = frame.fingers().count();
|
int numFingers = frame.fingers().count();
|
||||||
fingerPositions.resize(numFingers);
|
fingerTips.resize(numFingers);
|
||||||
|
fingerRoots.resize(numFingers);
|
||||||
for (int i = 0; i < numFingers; ++i) {
|
for (int i = 0; i < numFingers; ++i) {
|
||||||
const Leap::Finger& thisFinger = frame.fingers()[i];
|
const Leap::Finger& thisFinger = frame.fingers()[i];
|
||||||
const Leap::Vector pos = thisFinger.tipPosition();
|
const Leap::Vector pos = thisFinger.stabilizedTipPosition();
|
||||||
fingerPositions[i] = glm::vec3(pos.x, pos.y, pos.z);
|
fingerTips[i] = glm::vec3(pos.x, pos.y, pos.z);
|
||||||
|
|
||||||
|
const Leap::Vector root = pos - thisFinger.direction() * thisFinger.length();
|
||||||
|
fingerRoots[i] = glm::vec3(root.x, root.y, root.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numHands = frame.hands().count();
|
||||||
|
handPositions.resize(numHands);
|
||||||
|
handNormals.resize(numHands);
|
||||||
|
for (int i = 0; i < numHands; ++i) {
|
||||||
|
const Leap::Hand& thisHand = frame.hands()[i];
|
||||||
|
const Leap::Vector pos = thisHand.palmPosition();
|
||||||
|
handPositions[i] = glm::vec3(pos.x, pos.y, pos.z);
|
||||||
|
|
||||||
|
const Leap::Vector norm = thisHand.palmNormal();
|
||||||
|
handNormals[i] = glm::vec3(norm.x, norm.y, norm.z);
|
||||||
}
|
}
|
||||||
lastFrame = frame;
|
lastFrame = frame;
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,28 +56,61 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void LeapManager::initialize() {
|
void LeapManager::initialize() {
|
||||||
if (!_isInitialized) {
|
|
||||||
#ifndef LEAP_STUBS
|
#ifndef LEAP_STUBS
|
||||||
if (dlopen("/usr/lib/libLeap.dylib", RTLD_LAZY)) {
|
if (dlopen("/usr/lib/libLeap.dylib", RTLD_LAZY)) {
|
||||||
_libraryExists = true;
|
_libraryExists = true;
|
||||||
_controller = new Leap::Controller();
|
_controller = new Leap::Controller();
|
||||||
_listener = new HifiLeapListener();
|
_listener = new HifiLeapListener();
|
||||||
_controller->addListener(*_listener);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_isInitialized = true;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeapManager::terminate() {
|
||||||
|
delete _listener;
|
||||||
|
delete _controller;
|
||||||
|
_listener = NULL;
|
||||||
|
_controller = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeapManager::nextFrame() {
|
void LeapManager::nextFrame() {
|
||||||
initialize();
|
|
||||||
if (_listener && _controller)
|
if (_listener && _controller)
|
||||||
_listener->onFrame(*_controller);
|
_listener->onFrame(*_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<glm::vec3>& LeapManager::getFingerPositions() {
|
const std::vector<glm::vec3>& LeapManager::getFingerTips() {
|
||||||
if (_listener)
|
if (_listener) {
|
||||||
return _listener->fingerPositions;
|
return _listener->fingerTips;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
static std::vector<glm::vec3> empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<glm::vec3>& LeapManager::getFingerRoots() {
|
||||||
|
if (_listener) {
|
||||||
|
return _listener->fingerRoots;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
static std::vector<glm::vec3> empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<glm::vec3>& LeapManager::getHandPositions() {
|
||||||
|
if (_listener) {
|
||||||
|
return _listener->handPositions;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
static std::vector<glm::vec3> empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<glm::vec3>& LeapManager::getHandNormals() {
|
||||||
|
if (_listener) {
|
||||||
|
return _listener->handNormals;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
static std::vector<glm::vec3> empty;
|
static std::vector<glm::vec3> empty;
|
||||||
return empty;
|
return empty;
|
||||||
|
@ -69,17 +120,15 @@ const std::vector<glm::vec3>& LeapManager::getFingerPositions() {
|
||||||
std::string LeapManager::statusString() {
|
std::string LeapManager::statusString() {
|
||||||
std::stringstream leapString;
|
std::stringstream leapString;
|
||||||
#ifndef LEAP_STUBS
|
#ifndef LEAP_STUBS
|
||||||
if (_isInitialized) {
|
if (!_libraryExists)
|
||||||
if (!_libraryExists)
|
leapString << "Leap library at /usr/lib/libLeap.dylib does not exist.";
|
||||||
leapString << "Leap library at /usr/lib/libLeap.dylib does not exist.";
|
else if (!_controller || !_listener || !_controller->devices().count())
|
||||||
else if (!_controller || !_listener || !_controller->devices().count())
|
leapString << "Leap controller is not attached.";
|
||||||
leapString << "Leap controller is not attached.";
|
else {
|
||||||
else {
|
leapString << "Leap pointables: " << _listener->lastFrame.pointables().count();
|
||||||
leapString << "Leap pointables: " << _listener->lastFrame.pointables().count();
|
if (_listener->lastFrame.pointables().count() > 0) {
|
||||||
if (_listener->lastFrame.pointables().count() > 0) {
|
Leap::Vector pos = _listener->lastFrame.pointables()[0].tipPosition();
|
||||||
Leap::Vector pos = _listener->lastFrame.pointables()[0].tipPosition();
|
leapString << " pos: " << pos.x << " " << pos.y << " " << pos.z;
|
||||||
leapString << " pos: " << pos.x << " " << pos.y << " " << pos.z;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,19 +21,18 @@ namespace Leap {
|
||||||
class LeapManager {
|
class LeapManager {
|
||||||
public:
|
public:
|
||||||
static void nextFrame(); // called once per frame to get new Leap data
|
static void nextFrame(); // called once per frame to get new Leap data
|
||||||
static const std::vector<glm::vec3>& getFingerPositions();
|
static const std::vector<glm::vec3>& getFingerTips();
|
||||||
|
static const std::vector<glm::vec3>& getFingerRoots();
|
||||||
|
static const std::vector<glm::vec3>& getHandPositions();
|
||||||
|
static const std::vector<glm::vec3>& getHandNormals();
|
||||||
static std::string statusString();
|
static std::string statusString();
|
||||||
|
static void initialize();
|
||||||
|
static void terminate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void initialize();
|
|
||||||
static bool _isInitialized; // We've looked for the library and hooked it up if it's there.
|
|
||||||
static bool _libraryExists; // The library is present, so we won't crash if we call it.
|
static bool _libraryExists; // The library is present, so we won't crash if we call it.
|
||||||
static Leap::Controller* _controller;
|
static Leap::Controller* _controller;
|
||||||
static HifiLeapListener* _listener;
|
static HifiLeapListener* _listener;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__LeapManager__) */
|
#endif /* defined(__hifi__LeapManager__) */
|
||||||
|
|
|
@ -125,13 +125,31 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
||||||
*destinationBuffer++ = bitItems;
|
*destinationBuffer++ = bitItems;
|
||||||
|
|
||||||
// leap hand data
|
// leap hand data
|
||||||
const std::vector<glm::vec3>& fingerPositions = _handData->getFingerPositions();
|
// In order to make the hand data version-robust, hand data packing is just a series of vec3's,
|
||||||
*destinationBuffer++ = (unsigned char)fingerPositions.size();
|
// with conventions. If a client doesn't know the conventions, they can just get the vec3's
|
||||||
for (size_t i = 0; i < fingerPositions.size(); ++i)
|
// and render them as balls, or ignore them, without crashing or disrupting anyone.
|
||||||
{
|
// Current convention:
|
||||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].x, 4);
|
// Zero or more fingetTip positions, followed by the same number of fingerRoot positions
|
||||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].y, 4);
|
|
||||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].z, 4);
|
const std::vector<glm::vec3>& fingerTips = _handData->getFingerTips();
|
||||||
|
const std::vector<glm::vec3>& fingerRoots = _handData->getFingerRoots();
|
||||||
|
size_t numFingerVectors = fingerTips.size() + fingerRoots.size();
|
||||||
|
if (numFingerVectors > 255)
|
||||||
|
numFingerVectors = 0; // safety. We shouldn't ever get over 255, so consider that invalid.
|
||||||
|
|
||||||
|
*destinationBuffer++ = (unsigned char)numFingerVectors;
|
||||||
|
|
||||||
|
if (numFingerVectors > 0) {
|
||||||
|
for (size_t i = 0; i < fingerTips.size(); ++i) {
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].x, 4);
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].y, 4);
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerTips[i].z, 4);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < fingerRoots.size(); ++i) {
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].x, 4);
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].y, 4);
|
||||||
|
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerRoots[i].z, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return destinationBuffer - bufferStart;
|
return destinationBuffer - bufferStart;
|
||||||
|
@ -229,18 +247,20 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
// leap hand data
|
// leap hand data
|
||||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
if (sourceBuffer - startPosition < numBytes) // safety check
|
||||||
{
|
{
|
||||||
std::vector<glm::vec3> fingerPositions = _handData->getFingerPositions();
|
std::vector<glm::vec3> fingerTips = _handData->getFingerTips();
|
||||||
unsigned int numFingers = *sourceBuffer++;
|
std::vector<glm::vec3> fingerRoots = _handData->getFingerRoots();
|
||||||
if (numFingers > MAX_AVATAR_LEAP_BALLS) // safety check
|
unsigned int numFingerVectors = *sourceBuffer++;
|
||||||
numFingers = 0;
|
unsigned int numFingerTips = numFingerVectors / 2;
|
||||||
fingerPositions.resize(numFingers);
|
unsigned int numFingerRoots = numFingerVectors - numFingerTips;
|
||||||
for (size_t i = 0; i < numFingers; ++i)
|
fingerTips.resize(numFingerTips);
|
||||||
{
|
fingerRoots.resize(numFingerRoots);
|
||||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].x), 4);
|
for (size_t i = 0; i < numFingerTips; ++i) {
|
||||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].y), 4);
|
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].x), 4);
|
||||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].z), 4);
|
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].y), 4);
|
||||||
|
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].z), 4);
|
||||||
}
|
}
|
||||||
_handData->setFingerPositions(fingerPositions);
|
_handData->setFingerTips(fingerTips);
|
||||||
|
_handData->setFingerRoots(fingerRoots);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sourceBuffer - startPosition;
|
return sourceBuffer - startPosition;
|
||||||
|
|
|
@ -14,20 +14,27 @@
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#define MAX_AVATAR_LEAP_BALLS 10
|
|
||||||
|
|
||||||
class AvatarData;
|
class AvatarData;
|
||||||
|
|
||||||
class HandData {
|
class HandData {
|
||||||
public:
|
public:
|
||||||
HandData(AvatarData* owningAvatar);
|
HandData(AvatarData* owningAvatar);
|
||||||
|
|
||||||
const std::vector<glm::vec3>& getFingerPositions() const { return _fingerPositions; }
|
const std::vector<glm::vec3>& getFingerTips() const { return _fingerTips; }
|
||||||
void setFingerPositions(const std::vector<glm::vec3>& fingerPositions) { _fingerPositions = fingerPositions; }
|
const std::vector<glm::vec3>& getFingerRoots() const { return _fingerRoots; }
|
||||||
|
const std::vector<glm::vec3>& getHandPositions() const { return _handPositions; }
|
||||||
|
const std::vector<glm::vec3>& getHandNormals() const { return _handNormals; }
|
||||||
|
void setFingerTips(const std::vector<glm::vec3>& fingerTips) { _fingerTips = fingerTips; }
|
||||||
|
void setFingerRoots(const std::vector<glm::vec3>& fingerRoots) { _fingerRoots = fingerRoots; }
|
||||||
|
void setHandPositions(const std::vector<glm::vec3>& handPositons) { _handPositions = handPositons; }
|
||||||
|
void setHandNormals(const std::vector<glm::vec3>& handNormals) { _handNormals = handNormals; }
|
||||||
|
|
||||||
friend class AvatarData;
|
friend class AvatarData;
|
||||||
protected:
|
protected:
|
||||||
std::vector<glm::vec3> _fingerPositions;
|
std::vector<glm::vec3> _fingerTips;
|
||||||
|
std::vector<glm::vec3> _fingerRoots;
|
||||||
|
std::vector<glm::vec3> _handPositions;
|
||||||
|
std::vector<glm::vec3> _handNormals;
|
||||||
AvatarData* _owningAvatarData;
|
AvatarData* _owningAvatarData;
|
||||||
private:
|
private:
|
||||||
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
||||||
|
|
Loading…
Reference in a new issue