mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +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_fd);
|
||||
|
||||
LeapManager::terminate();
|
||||
|
||||
if (_settingsAutosave->isChecked()) {
|
||||
saveSettings();
|
||||
_settings->sync();
|
||||
|
@ -1645,6 +1647,8 @@ void Application::init() {
|
|||
QMetaObject::invokeMethod(_fullScreenMode, "trigger", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
LeapManager::initialize();
|
||||
|
||||
gettimeofday(&_timerStart, NULL);
|
||||
gettimeofday(&_lastTimeIdle, NULL);
|
||||
|
||||
|
@ -1803,7 +1807,8 @@ void Application::update(float deltaTime) {
|
|||
|
||||
// Leap finger-sensing device
|
||||
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
|
||||
if (_serialHeadSensor.isActive()) {
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
|
||||
//getters
|
||||
bool isInitialized () const { return _initialized;}
|
||||
bool isMyAvatar () const { return _owningAgent == NULL; }
|
||||
const Skeleton& getSkeleton () const { return _skeleton;}
|
||||
float getHeadYawRate () const { return _head.yawRate;}
|
||||
float getBodyYaw () const { return _bodyYaw;}
|
||||
|
@ -155,13 +156,13 @@ public:
|
|||
void writeAvatarDataToFile();
|
||||
void readAvatarDataFromFile();
|
||||
|
||||
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||
|
||||
private:
|
||||
// privatize copy constructor and assignment operator to avoid copying
|
||||
Avatar(const Avatar&);
|
||||
Avatar& operator= (const Avatar&);
|
||||
|
||||
bool isMyAvatar() const { return _owningAgent == NULL; }
|
||||
|
||||
struct AvatarBall
|
||||
{
|
||||
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 applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||
void checkForMouseRayTouching();
|
||||
void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,21 +21,18 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
_owningAvatar(owningAvatar),
|
||||
_renderAlpha(1.0),
|
||||
_lookingInMirror(false),
|
||||
_ballColor(0.0, 0.4, 0.0),
|
||||
_ballColor(0.0, 0.0, 0.4),
|
||||
_position(0.0, 0.4, 0.0),
|
||||
_orientation(0.0, 0.0, 0.0, 1.0)
|
||||
{
|
||||
}
|
||||
|
||||
void Hand::init() {
|
||||
_numLeapBalls = 0;
|
||||
for (int b = 0; b < MAX_AVATAR_LEAP_BALLS; b++) {
|
||||
_leapBall[b].position = glm::vec3(0.0, 0.0, 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;
|
||||
}
|
||||
// Different colors for my hand and others' hands
|
||||
if (_owningAvatar && _owningAvatar->isMyAvatar())
|
||||
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||
else
|
||||
_ballColor = glm::vec3(0.0, 0.0, 0.4);
|
||||
}
|
||||
|
||||
void Hand::reset() {
|
||||
|
@ -44,20 +41,27 @@ void Hand::reset() {
|
|||
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() {
|
||||
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();
|
||||
_position = head.getPosition() + head.getOrientation() * offset;
|
||||
_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 b = 0; b < _numLeapBalls; b++) {
|
||||
glm::vec3 pos = unitScale * _fingerPositions[b] + offset;
|
||||
_leapBall[b].rotation = _orientation;
|
||||
_leapBall[b].position = _position + _orientation * pos;
|
||||
for (int i = 0; i < _fingerTips.size(); ++i) {
|
||||
_leapBalls[i].rotation = _orientation;
|
||||
_leapBalls[i].position = leapPositionToWorldPosition(_fingerTips[i]);
|
||||
_leapBalls[i].radius = 0.01;
|
||||
_leapBalls[i].touchForce = 0.0;
|
||||
_leapBalls[i].isCollidable = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,23 +82,52 @@ void Hand::render(bool lookingInMirror) {
|
|||
void Hand::renderHandSpheres() {
|
||||
glPushMatrix();
|
||||
// Draw the leap balls
|
||||
for (int b = 0; b < _numLeapBalls; b++) {
|
||||
for (size_t i = 0; i < _leapBalls.size(); i++) {
|
||||
float alpha = 1.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();
|
||||
glTranslatef(_leapBall[b].position.x, _leapBall[b].position.y, _leapBall[b].position.z);
|
||||
glutSolidSphere(_leapBall[b].radius, 20.0f, 20.0f);
|
||||
glTranslatef(_leapBalls[i].position.x, _leapBalls[i].position.y, _leapBalls[i].position.z);
|
||||
glutSolidSphere(_leapBalls[i].radius, 20.0f, 20.0f);
|
||||
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();
|
||||
}
|
||||
|
||||
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerPositions) {
|
||||
_fingerPositions = fingerPositions;
|
||||
void Hand::setLeapFingers(const std::vector<glm::vec3>& fingerTips,
|
||||
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 "SerialInterface.h"
|
||||
#include <SharedUtil.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class Avatar;
|
||||
|
@ -41,11 +42,13 @@ public:
|
|||
void render(bool lookingInMirror);
|
||||
|
||||
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
|
||||
int getNumLeapBalls () const { return _numLeapBalls;}
|
||||
const glm::vec3& getLeapBallPosition (int which) const { return _leapBall[which].position;}
|
||||
const glm::vec3& getLeapBallPosition (int ball) const { return _leapBalls[ball].position;}
|
||||
|
||||
private:
|
||||
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
||||
|
@ -58,12 +61,12 @@ private:
|
|||
glm::vec3 _ballColor;
|
||||
glm::vec3 _position;
|
||||
glm::quat _orientation;
|
||||
int _numLeapBalls;
|
||||
HandBall _leapBall[ MAX_AVATAR_LEAP_BALLS ];
|
||||
std::vector<HandBall> _leapBalls;
|
||||
|
||||
// private methods
|
||||
void renderHandSpheres();
|
||||
void calculateGeometry();
|
||||
glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,25 +11,43 @@
|
|||
#include <dlfcn.h> // needed for RTLD_LAZY
|
||||
#include <sstream>
|
||||
|
||||
bool LeapManager::_isInitialized = false;
|
||||
bool LeapManager::_libraryExists = false;
|
||||
Leap::Controller* LeapManager::_controller = 0;
|
||||
HifiLeapListener* LeapManager::_listener = 0;
|
||||
Leap::Controller* LeapManager::_controller = NULL;
|
||||
HifiLeapListener* LeapManager::_listener = NULL;
|
||||
|
||||
class HifiLeapListener : public Leap::Listener {
|
||||
public:
|
||||
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) {
|
||||
#ifndef LEAP_STUBS
|
||||
Leap::Frame frame = controller.frame();
|
||||
int numFingers = frame.fingers().count();
|
||||
fingerPositions.resize(numFingers);
|
||||
fingerTips.resize(numFingers);
|
||||
fingerRoots.resize(numFingers);
|
||||
for (int i = 0; i < numFingers; ++i) {
|
||||
const Leap::Finger& thisFinger = frame.fingers()[i];
|
||||
const Leap::Vector pos = thisFinger.tipPosition();
|
||||
fingerPositions[i] = glm::vec3(pos.x, pos.y, pos.z);
|
||||
const Leap::Vector pos = thisFinger.stabilizedTipPosition();
|
||||
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;
|
||||
#endif
|
||||
|
@ -38,28 +56,61 @@ public:
|
|||
};
|
||||
|
||||
void LeapManager::initialize() {
|
||||
if (!_isInitialized) {
|
||||
#ifndef LEAP_STUBS
|
||||
if (dlopen("/usr/lib/libLeap.dylib", RTLD_LAZY)) {
|
||||
_libraryExists = true;
|
||||
_controller = new Leap::Controller();
|
||||
_listener = new HifiLeapListener();
|
||||
_controller->addListener(*_listener);
|
||||
}
|
||||
#endif
|
||||
_isInitialized = true;
|
||||
if (dlopen("/usr/lib/libLeap.dylib", RTLD_LAZY)) {
|
||||
_libraryExists = true;
|
||||
_controller = new Leap::Controller();
|
||||
_listener = new HifiLeapListener();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LeapManager::terminate() {
|
||||
delete _listener;
|
||||
delete _controller;
|
||||
_listener = NULL;
|
||||
_controller = NULL;
|
||||
}
|
||||
|
||||
void LeapManager::nextFrame() {
|
||||
initialize();
|
||||
if (_listener && _controller)
|
||||
_listener->onFrame(*_controller);
|
||||
}
|
||||
|
||||
const std::vector<glm::vec3>& LeapManager::getFingerPositions() {
|
||||
if (_listener)
|
||||
return _listener->fingerPositions;
|
||||
const std::vector<glm::vec3>& LeapManager::getFingerTips() {
|
||||
if (_listener) {
|
||||
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 {
|
||||
static std::vector<glm::vec3> empty;
|
||||
return empty;
|
||||
|
@ -69,17 +120,15 @@ const std::vector<glm::vec3>& LeapManager::getFingerPositions() {
|
|||
std::string LeapManager::statusString() {
|
||||
std::stringstream leapString;
|
||||
#ifndef LEAP_STUBS
|
||||
if (_isInitialized) {
|
||||
if (!_libraryExists)
|
||||
leapString << "Leap library at /usr/lib/libLeap.dylib does not exist.";
|
||||
else if (!_controller || !_listener || !_controller->devices().count())
|
||||
leapString << "Leap controller is not attached.";
|
||||
else {
|
||||
leapString << "Leap pointables: " << _listener->lastFrame.pointables().count();
|
||||
if (_listener->lastFrame.pointables().count() > 0) {
|
||||
Leap::Vector pos = _listener->lastFrame.pointables()[0].tipPosition();
|
||||
leapString << " pos: " << pos.x << " " << pos.y << " " << pos.z;
|
||||
}
|
||||
if (!_libraryExists)
|
||||
leapString << "Leap library at /usr/lib/libLeap.dylib does not exist.";
|
||||
else if (!_controller || !_listener || !_controller->devices().count())
|
||||
leapString << "Leap controller is not attached.";
|
||||
else {
|
||||
leapString << "Leap pointables: " << _listener->lastFrame.pointables().count();
|
||||
if (_listener->lastFrame.pointables().count() > 0) {
|
||||
Leap::Vector pos = _listener->lastFrame.pointables()[0].tipPosition();
|
||||
leapString << " pos: " << pos.x << " " << pos.y << " " << pos.z;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,19 +21,18 @@ namespace Leap {
|
|||
class LeapManager {
|
||||
public:
|
||||
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 void initialize();
|
||||
static void terminate();
|
||||
|
||||
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 Leap::Controller* _controller;
|
||||
static HifiLeapListener* _listener;
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__LeapManager__) */
|
||||
|
|
|
@ -125,13 +125,31 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
|||
*destinationBuffer++ = bitItems;
|
||||
|
||||
// leap hand data
|
||||
const std::vector<glm::vec3>& fingerPositions = _handData->getFingerPositions();
|
||||
*destinationBuffer++ = (unsigned char)fingerPositions.size();
|
||||
for (size_t i = 0; i < fingerPositions.size(); ++i)
|
||||
{
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].x, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].y, 4);
|
||||
destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].z, 4);
|
||||
// In order to make the hand data version-robust, hand data packing is just a series of vec3's,
|
||||
// with conventions. If a client doesn't know the conventions, they can just get the vec3's
|
||||
// and render them as balls, or ignore them, without crashing or disrupting anyone.
|
||||
// Current convention:
|
||||
// Zero or more fingetTip positions, followed by the same number of fingerRoot positions
|
||||
|
||||
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;
|
||||
|
@ -229,18 +247,20 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
// leap hand data
|
||||
if (sourceBuffer - startPosition < numBytes) // safety check
|
||||
{
|
||||
std::vector<glm::vec3> fingerPositions = _handData->getFingerPositions();
|
||||
unsigned int numFingers = *sourceBuffer++;
|
||||
if (numFingers > MAX_AVATAR_LEAP_BALLS) // safety check
|
||||
numFingers = 0;
|
||||
fingerPositions.resize(numFingers);
|
||||
for (size_t i = 0; i < numFingers; ++i)
|
||||
{
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].x), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].y), 4);
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerPositions[i].z), 4);
|
||||
std::vector<glm::vec3> fingerTips = _handData->getFingerTips();
|
||||
std::vector<glm::vec3> fingerRoots = _handData->getFingerRoots();
|
||||
unsigned int numFingerVectors = *sourceBuffer++;
|
||||
unsigned int numFingerTips = numFingerVectors / 2;
|
||||
unsigned int numFingerRoots = numFingerVectors - numFingerTips;
|
||||
fingerTips.resize(numFingerTips);
|
||||
fingerRoots.resize(numFingerRoots);
|
||||
for (size_t i = 0; i < numFingerTips; ++i) {
|
||||
sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].x), 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;
|
||||
|
|
|
@ -14,20 +14,27 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#define MAX_AVATAR_LEAP_BALLS 10
|
||||
|
||||
class AvatarData;
|
||||
|
||||
class HandData {
|
||||
public:
|
||||
HandData(AvatarData* owningAvatar);
|
||||
|
||||
const std::vector<glm::vec3>& getFingerPositions() const { return _fingerPositions; }
|
||||
void setFingerPositions(const std::vector<glm::vec3>& fingerPositions) { _fingerPositions = fingerPositions; }
|
||||
const std::vector<glm::vec3>& getFingerTips() const { return _fingerTips; }
|
||||
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;
|
||||
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;
|
||||
private:
|
||||
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
||||
|
|
Loading…
Reference in a new issue