mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-17 13:48:45 +02:00
Merge pull request #614 from machinelevel/dev4
(changed per requests and re-merged) Two Leap-related crashes fixed, plu...
This commit is contained in:
commit
00fa688aba
8 changed files with 208 additions and 91 deletions
|
@ -956,6 +956,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();
|
||||||
|
@ -1648,6 +1650,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);
|
||||||
|
|
||||||
|
@ -1806,7 +1810,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,19 @@ 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);
|
|
||||||
_leapBall[b].radius = 0.01;
|
|
||||||
_leapBall[b].touchForce = 0.0;
|
|
||||||
_leapBall[b].isCollidable = true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hand::reset() {
|
void Hand::reset() {
|
||||||
|
@ -44,20 +42,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 +83,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