From 49dedb72c97b3e44d5af3e9d80a929d136ea65e0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 May 2014 11:09:12 -0700 Subject: [PATCH 01/11] remove FingerData class and related cleanup --- interface/src/BuckyBalls.cpp | 8 +- interface/src/avatar/Avatar.cpp | 16 +-- interface/src/avatar/Hand.cpp | 64 ++--------- interface/src/avatar/SkeletonModel.cpp | 26 +---- interface/src/devices/SixenseManager.cpp | 29 ++--- .../ControllerScriptingInterface.cpp | 4 +- libraries/avatars/src/HandData.cpp | 107 +++--------------- libraries/avatars/src/HandData.h | 82 +++----------- libraries/shared/src/SharedUtil.h | 1 + 9 files changed, 63 insertions(+), 274 deletions(-) diff --git a/interface/src/BuckyBalls.cpp b/interface/src/BuckyBalls.cpp index e1ec41dca1..68d1167071 100644 --- a/interface/src/BuckyBalls.cpp +++ b/interface/src/BuckyBalls.cpp @@ -60,15 +60,13 @@ BuckyBalls::BuckyBalls() { void BuckyBalls::grab(PalmData& palm, float deltaTime) { float penetration; - glm::vec3 diff; - FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger - glm::vec3 fingerTipPosition = finger.getTipPosition(); + glm::vec3 fingerTipPosition = palm.getFingerTipPosition(); if (palm.getControllerButtons() & BUTTON_FWD) { if (!_bballIsGrabbed[palm.getSixenseID()]) { // Look for a ball to grab for (int i = 0; i < NUM_BBALLS; i++) { - diff = _bballPosition[i] - fingerTipPosition; + glm::vec3 diff = _bballPosition[i] - fingerTipPosition; penetration = glm::length(diff) - (_bballRadius[i] + COLLISION_RADIUS); if (penetration < 0.f) { _bballIsGrabbed[palm.getSixenseID()] = i; @@ -77,7 +75,7 @@ void BuckyBalls::grab(PalmData& palm, float deltaTime) { } if (_bballIsGrabbed[palm.getSixenseID()]) { // If ball being grabbed, move with finger - diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; + glm::vec3 diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; penetration = glm::length(diff) - (_bballRadius[_bballIsGrabbed[palm.getSixenseID()]] + COLLISION_RADIUS); _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] -= glm::normalize(diff) * penetration; glm::vec3 fingerTipVelocity = palm.getTipVelocity(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4de608fc6b..00b7b8c682 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -604,18 +604,6 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti const PalmData* palm = handData->getPalm(i); if (palm && palm->hasPaddle()) { // create a disk collision proxy where the hand is - glm::vec3 fingerAxis(0.0f); - for (size_t f = 0; f < palm->getNumFingers(); ++f) { - const FingerData& finger = (palm->getFingers())[f]; - if (finger.isActive()) { - // compute finger axis - glm::vec3 fingerTip = finger.getTipPosition(); - glm::vec3 fingerRoot = finger.getRootPosition(); - fingerAxis = glm::normalize(fingerTip - fingerRoot); - break; - } - } - int jointIndex = -1; glm::vec3 handPosition; if (i == 0) { @@ -626,8 +614,10 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti _skeletonModel.getRightHandPosition(handPosition); jointIndex = _skeletonModel.getRightHandJointIndex(); } + + glm::vec3 fingerAxis = palm->getFingerDirection(); glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis; - glm::vec3 diskNormal = palm->getNormal(); + glm::vec3 diskNormal = palm->getPalmDirection(); const float DISK_THICKNESS = 0.08f; // collide against the disk diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 576790714e..78eab424ab 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -176,8 +176,7 @@ void Hand::renderHandTargets(bool isMine) { if (!palm.isActive()) { continue; } - glm::vec3 targetPosition; - palm.getBallHoldPosition(targetPosition); + glm::vec3 targetPosition = palm.getFingerTipPosition(); glPushMatrix(); glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z); @@ -197,59 +196,20 @@ void Hand::renderHandTargets(bool isMine) { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; if (palm.isActive()) { - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - if (finger.isActive()) { - glColor4f(handColor.r, handColor.g, handColor.b, alpha); - glm::vec3 tip = finger.getTipPosition(); - glm::vec3 root = finger.getRootPosition(); - Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); - // Render sphere at palm/finger root - glm::vec3 palmNormal = root + palm.getNormal() * PALM_DISK_THICKNESS; - Avatar::renderJointConnectingCone(root, palmNormal, PALM_DISK_RADIUS, 0.0f); - glPushMatrix(); - glTranslatef(root.x, root.y, root.z); - glutSolidSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); - glPopMatrix(); - - } - } + glColor4f(handColor.r, handColor.g, handColor.b, alpha); + glm::vec3 tip = palm.getFingerTipPosition(); + glm::vec3 root = palm.getPosition(); + Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); + // Render sphere at palm/finger root + glm::vec3 offsetFromPalm = root + palm.getPalmDirection() * PALM_DISK_THICKNESS; + Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f); + glPushMatrix(); + glTranslatef(root.x, root.y, root.z); + glutSolidSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); + glPopMatrix(); } } - /* - // Draw the hand paddles - int MAX_NUM_PADDLES = 2; // one for left and one for right - glColor4f(handColor.r, handColor.g, handColor.b, 0.3f); - for (int i = 0; i < MAX_NUM_PADDLES; i++) { - const PalmData* palm = getPalm(i); - if (palm) { - // compute finger axis - glm::vec3 fingerAxis(0.f); - for (size_t f = 0; f < palm->getNumFingers(); ++f) { - const FingerData& finger = (palm->getFingers())[f]; - if (finger.isActive()) { - glm::vec3 fingerTip = finger.getTipPosition(); - glm::vec3 fingerRoot = finger.getRootPosition(); - fingerAxis = glm::normalize(fingerTip - fingerRoot); - break; - } - } - // compute paddle position - glm::vec3 handPosition; - if (i == SIXENSE_CONTROLLER_ID_LEFT_HAND) { - _owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition); - } else if (i == SIXENSE_CONTROLLER_ID_RIGHT_HAND) { - _owningAvatar->getSkeletonModel().getRightHandPosition(handPosition); - } - glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis; - glm::vec3 root = tip + palm->getNormal() * HAND_PADDLE_THICKNESS; - // render a very shallow cone as the paddle - Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f); - } - } - */ - glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8c21a3240f..7a6fadeb6b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -159,29 +159,13 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } else { getJointRotation(jointIndex, palmRotation, true); } - palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; + palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getPalmDirection()) * palmRotation; - // sort the finger indices by raw x, get the average direction - QVector fingerIndices; - glm::vec3 direction; - for (size_t i = 0; i < palm.getNumFingers(); i++) { - glm::vec3 fingerVector = palm.getFingers()[i].getTipPosition() - palm.getPosition(); - float length = glm::length(fingerVector); - if (length > EPSILON) { - direction += fingerVector / length; - } - fingerVector = glm::inverse(palmRotation) * fingerVector * -sign; - IndexValue indexValue = { (int)i, atan2f(fingerVector.z, fingerVector.x) }; - fingerIndices.append(indexValue); - } - qSort(fingerIndices.begin(), fingerIndices.end()); - // rotate forearm according to average finger direction - float directionLength = glm::length(direction); - const unsigned int MIN_ROTATION_FINGERS = 3; - if (directionLength > EPSILON && palm.getNumFingers() >= MIN_ROTATION_FINGERS) { - palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; - } + // NOTE: we're doing this in the avatar local frame, so we DON'T want to use Palm::getHandDirection() + // which returns the world-frame. + glm::vec3 direction = palm.getRawRotation() * glm::vec3(0.0f, 0.0f, 1.0f); + palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; // set hand position, rotation if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 0435519124..461b414b2b 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -106,7 +106,7 @@ void SixenseManager::update(float deltaTime) { palm->setControllerButtons(data->buttons); palm->setTrigger(data->trigger); palm->setJoystick(data->joystick_x, data->joystick_y); - + glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); // Transform the measured position into body frame. glm::vec3 neck = _neckBase; @@ -117,15 +117,12 @@ void SixenseManager::update(float deltaTime) { // Rotation of Palm glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation; - const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f); - glm::vec3 newNormal = rotation * PALM_VECTOR; - palm->setRawNormal(newNormal); palm->setRawRotation(rotation); // Compute current velocity from position change glm::vec3 rawVelocity; if (deltaTime > 0.f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f; + rawVelocity = (position - palm->getRawPosition()) * (METERS_PER_MILLIMETER / deltaTime); } else { rawVelocity = glm::vec3(0.0f); } @@ -140,29 +137,17 @@ void SixenseManager::update(float deltaTime) { _amountMoved = glm::vec3(0.0f); } - // initialize the "finger" based on the direction - FingerData finger(palm, hand); - finger.setActive(true); - finger.setRawRootPosition(position); - const float FINGER_LENGTH = 300.0f; // Millimeters + // Store the one fingertip in the palm structure so we can track velocity + const float FINGER_LENGTH = 300.0f; // meters const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; - finger.setRawTipPosition(position + rotation * FINGER_VECTOR); - - // Store the one fingertip in the palm structure so we can track velocity glm::vec3 oldTipPosition = palm->getTipRawPosition(); if (deltaTime > 0.f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f); + palm->setTipVelocity((newTipPosition - oldTipPosition) * (METERS_PER_MILLIMETER / deltaTime)); } else { palm->setTipVelocity(glm::vec3(0.f)); } palm->setTipPosition(newTipPosition); - - // three fingers indicates to the skeleton that we have enough data to determine direction - palm->getFingers().clear(); - palm->getFingers().push_back(finger); - palm->getFingers().push_back(finger); - palm->getFingers().push_back(finger); } if (numActiveControllers == 2) { @@ -171,7 +156,7 @@ void SixenseManager::update(float deltaTime) { // if the controllers haven't been moved in a while, disable const unsigned int MOVEMENT_DISABLE_SECONDS = 3; - if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * 1000 * 1000)) { + if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) { for (std::vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { it->setActive(false); } @@ -236,7 +221,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) if (_calibrationState == CALIBRATION_STATE_IDLE) { float reach = glm::distance(positionLeft, positionRight); - if (reach > 2.f * MINIMUM_ARM_REACH) { + if (reach > 2.0f * MINIMUM_ARM_REACH) { qDebug("started: sixense calibration"); _averageLeft = positionLeft; _averageRight = positionRight; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index aa14f769de..5e58ac66ea 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -198,9 +198,9 @@ glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex if (palmData) { switch (controlOfPalm) { case PALM_SPATIALCONTROL: - return palmData->getNormal(); + return palmData->getPalmDirection(); case TIP_SPATIALCONTROL: - return palmData->getNormal(); // currently the tip doesn't have a unique normal, use the palm normal + return palmData->getFingerDirection(); } } return glm::vec3(0); // bad index diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index c2e3b51cb3..109eab5c5d 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -26,7 +26,7 @@ HandData::HandData(AvatarData* owningAvatar) : addNewPalm(); } -glm::vec3 HandData::worldVectorToLeapVector(const glm::vec3& worldVector) const { +glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { return glm::inverse(getBaseOrientation()) * worldVector / LEAP_UNIT_SCALE; } @@ -66,7 +66,6 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) PalmData::PalmData(HandData* owningHandData) : _rawRotation(0.f, 0.f, 0.f, 1.f), _rawPosition(0.f), -_rawNormal(0.f, 1.f, 0.f), _rawVelocity(0.f), _rotationalVelocity(0.f), _totalPenetration(0.f), @@ -78,57 +77,11 @@ _numFramesWithoutData(0), _owningHandData(owningHandData), _isCollidingWithVoxel(false), _isCollidingWithPalm(false), -_collisionlessPaddleExpiry(0) -{ - for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { - _fingers.push_back(FingerData(this, owningHandData)); - } +_collisionlessPaddleExpiry(0) { } void PalmData::addToPosition(const glm::vec3& delta) { - // convert to Leap coordinates, then add to palm and finger positions - glm::vec3 leapDelta = _owningHandData->worldVectorToLeapVector(delta); - _rawPosition += leapDelta; - for (size_t i = 0; i < getNumFingers(); i++) { - FingerData& finger = _fingers[i]; - if (finger.isActive()) { - finger.setRawTipPosition(finger.getTipRawPosition() + leapDelta); - finger.setRawRootPosition(finger.getRootRawPosition() + leapDelta); - } - } -} - -FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) : -_tipRawPosition(0, 0, 0), -_rootRawPosition(0, 0, 0), -_isActive(false), -_leapID(LEAPID_INVALID), -_numFramesWithoutData(0), -_owningPalmData(owningPalmData), -_owningHandData(owningHandData) -{ - const int standardTrailLength = 10; - setTrailLength(standardTrailLength); -} - -void HandData::setFingerTrailLength(unsigned int length) { - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - finger.setTrailLength(length); - } - } -} - -void HandData::updateFingerTrails() { - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - finger.updateTrail(); - } - } + _rawPosition += _owningHandData->worldToLocalVector(delta); } bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, @@ -157,54 +110,20 @@ glm::vec3 HandData::getBasePosition() const { return _owningAvatarData->getPosition(); } -void FingerData::setTrailLength(unsigned int length) { - _tipTrailPositions.resize(length); - _tipTrailCurrentStartIndex = 0; - _tipTrailCurrentValidLength = 0; +glm::vec3 PalmData::getFingerTipPosition() const { + glm::vec3 fingerOffset(0.0f, 0.0f, 0.03f); + glm::vec3 palmOffset(0.0f, -0.08f, 0.0f); + return getPosition() + _owningHandData->localToWorldDirection(_rawRotation * (fingerOffset + palmOffset)); } -void FingerData::updateTrail() { - if (_tipTrailPositions.size() == 0) - return; - - if (_isActive) { - // Add the next point in the trail. - _tipTrailCurrentStartIndex--; - if (_tipTrailCurrentStartIndex < 0) - _tipTrailCurrentStartIndex = _tipTrailPositions.size() - 1; - - _tipTrailPositions[_tipTrailCurrentStartIndex] = getTipPosition(); - - if (_tipTrailCurrentValidLength < (int)_tipTrailPositions.size()) - _tipTrailCurrentValidLength++; - } - else { - // It's not active, so just kill the trail. - _tipTrailCurrentValidLength = 0; - } +glm::vec3 PalmData::getFingerDirection() const { + const glm::vec3 LOCAL_FINGER_DIRECTION(0.0f, 0.0f, 1.0f); + return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_FINGER_DIRECTION); } -int FingerData::getTrailNumPositions() { - return _tipTrailCurrentValidLength; -} - -const glm::vec3& FingerData::getTrailPosition(int index) { - if (index >= _tipTrailCurrentValidLength) { - static glm::vec3 zero(0,0,0); - return zero; - } - int posIndex = (index + _tipTrailCurrentStartIndex) % _tipTrailCurrentValidLength; - return _tipTrailPositions[posIndex]; -} - -void PalmData::getBallHoldPosition(glm::vec3& position) const { - const float BALL_FORWARD_OFFSET = 0.08f; // put the ball a bit forward of fingers - position = BALL_FORWARD_OFFSET * getNormal(); - if (_fingers.size() > 0) { - position += _fingers[0].getTipPosition(); - } else { - position += getPosition(); - } +glm::vec3 PalmData::getPalmDirection() const { + const glm::vec3 LOCAL_PALM_DIRECTION(0.0f, -1.0f, 0.0f); + return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_PALM_DIRECTION); } diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index a37e3a5814..968d7bbe38 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -21,7 +21,6 @@ #include "SharedUtil.h" class AvatarData; -class FingerData; class PalmData; const int NUM_HANDS = 2; @@ -41,17 +40,16 @@ public: HandData(AvatarData* owningAvatar); virtual ~HandData() {} - // These methods return the positions in Leap-relative space. - // To convert to world coordinates, use Hand::leapPositionToWorldPosition. - // position conversion - glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition) { - return getBasePosition() + getBaseOrientation() * (leapPosition * LEAP_UNIT_SCALE); + glm::vec3 localToWorldPosition(const glm::vec3& localPosition) { + return getBasePosition() + getBaseOrientation() * localPosition * LEAP_UNIT_SCALE; } - glm::vec3 leapDirectionToWorldDirection(const glm::vec3& leapDirection) { - return getBaseOrientation() * leapDirection; - } - glm::vec3 worldVectorToLeapVector(const glm::vec3& worldVector) const; + + glm::vec3 localToWorldDirection(const glm::vec3& localVector) { + return getBaseOrientation() * localVector; + } + + glm::vec3 worldToLocalVector(const glm::vec3& worldVector) const; std::vector& getPalms() { return _palms; } const std::vector& getPalms() const { return _palms; } @@ -63,9 +61,6 @@ public: /// both is not found. void getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const; - void setFingerTrailLength(unsigned int length); - void updateFingerTrails(); - /// Checks for penetration between the described sphere and the hand. /// \param penetratorCenter the center of the penetration test sphere /// \param penetratorRadius the radius of the penetration test sphere @@ -89,63 +84,18 @@ private: HandData& operator= (const HandData&); }; -class FingerData { -public: - FingerData(PalmData* owningPalmData, HandData* owningHandData); - - glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipRawPosition); } - glm::vec3 getRootPosition() const { return _owningHandData->leapPositionToWorldPosition(_rootRawPosition); } - const glm::vec3& getTipRawPosition() const { return _tipRawPosition; } - const glm::vec3& getRootRawPosition() const { return _rootRawPosition; } - bool isActive() const { return _isActive; } - int getLeapID() const { return _leapID; } - - void setActive(bool active) { _isActive = active; } - void setLeapID(int id) { _leapID = id; } - void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; } - void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; } - - void setTrailLength(unsigned int length); - void updateTrail(); - - int getTrailNumPositions(); - const glm::vec3& getTrailPosition(int index); - - void incrementFramesWithoutData() { _numFramesWithoutData++; } - void resetFramesWithoutData() { _numFramesWithoutData = 0; } - int getFramesWithoutData() const { return _numFramesWithoutData; } - -private: - glm::vec3 _tipRawPosition; - glm::vec3 _rootRawPosition; - bool _isActive; // This has current valid data - int _leapID; // the Leap's serial id for this tracked object - int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. - std::vector _tipTrailPositions; - int _tipTrailCurrentStartIndex; - int _tipTrailCurrentValidLength; - PalmData* _owningPalmData; - HandData* _owningHandData; -}; class PalmData { public: PalmData(HandData* owningHandData); - glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); } - glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); } - glm::vec3 getVelocity() const { return _owningHandData->leapDirectionToWorldDirection(_rawVelocity); } + glm::vec3 getPosition() const { return _owningHandData->localToWorldPosition(_rawPosition); } + glm::vec3 getVelocity() const { return _owningHandData->localToWorldDirection(_rawVelocity); } const glm::vec3& getRawPosition() const { return _rawPosition; } - const glm::vec3& getRawNormal() const { return _rawNormal; } bool isActive() const { return _isActive; } int getLeapID() const { return _leapID; } int getSixenseID() const { return _sixenseID; } - - std::vector& getFingers() { return _fingers; } - const std::vector& getFingers() const { return _fingers; } - size_t getNumFingers() const { return _fingers.size(); } - void setActive(bool active) { _isActive = active; } void setLeapID(int id) { _leapID = id; } void setSixenseID(int id) { _sixenseID = id; } @@ -153,7 +103,6 @@ public: void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; glm::quat getRawRotation() const { return _rawRotation; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } - void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; } void addToPosition(const glm::vec3& delta); @@ -162,11 +111,11 @@ public: void resolvePenetrations() { addToPosition(-_totalPenetration); _totalPenetration = glm::vec3(0.f); } void setTipPosition(const glm::vec3& position) { _tipPosition = position; } - const glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipPosition); } + const glm::vec3 getTipPosition() const { return _owningHandData->localToWorldPosition(_tipPosition); } const glm::vec3& getTipRawPosition() const { return _tipPosition; } void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; } - const glm::vec3 getTipVelocity() const { return _owningHandData->leapDirectionToWorldDirection(_tipVelocity); } + const glm::vec3 getTipVelocity() const { return _owningHandData->localToWorldDirection(_tipVelocity); } const glm::vec3& getTipRawVelocity() const { return _tipVelocity; } void incrementFramesWithoutData() { _numFramesWithoutData++; } @@ -198,11 +147,14 @@ public: /// Store position where the palm holds the ball. void getBallHoldPosition(glm::vec3& position) const; + // return world-frame: + glm::vec3 getFingerTipPosition() const; + glm::vec3 getFingerDirection() const; + glm::vec3 getPalmDirection() const; + private: - std::vector _fingers; glm::quat _rawRotation; glm::vec3 _rawPosition; - glm::vec3 _rawNormal; glm::vec3 _rawVelocity; glm::vec3 _rotationalVelocity; glm::quat _lastRotation; diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 4a3fe2a129..d111439b7e 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -54,6 +54,7 @@ static const float SQUARE_ROOT_OF_3 = (float)sqrt(3.f); static const float METERS_PER_DECIMETER = 0.1f; static const float METERS_PER_CENTIMETER = 0.01f; static const float METERS_PER_MILLIMETER = 0.001f; +static const float MILLIMETERS_PER_METER = 1000.0f; static const quint64 USECS_PER_MSEC = 1000; static const quint64 MSECS_PER_SECOND = 1000; static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; From efb3edf4006de207c23a9ad65de4355eccb024c1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 May 2014 11:39:21 -0700 Subject: [PATCH 02/11] Store sixense data in meters not millimeters --- interface/src/devices/SixenseManager.cpp | 22 ++++++++++++++-------- libraries/avatars/src/HandData.cpp | 2 +- libraries/avatars/src/HandData.h | 4 +--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 461b414b2b..1698cebcf9 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -22,9 +22,9 @@ const int CALIBRATION_STATE_Z = 3; const int CALIBRATION_STATE_COMPLETE = 4; // default (expected) location of neck in sixense space -const float NECK_X = 250.f; // millimeters -const float NECK_Y = 300.f; // millimeters -const float NECK_Z = 300.f; // millimeters +const float NECK_X = 0.25f; // meters +const float NECK_Y = 0.3f; // meters +const float NECK_Z = 0.3f; // meters #endif SixenseManager::SixenseManager() { @@ -107,7 +107,10 @@ void SixenseManager::update(float deltaTime) { palm->setTrigger(data->trigger); palm->setJoystick(data->joystick_x, data->joystick_y); + // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); + position *= METERS_PER_MILLIMETER; + // Transform the measured position into body frame. glm::vec3 neck = _neckBase; // Zeroing y component of the "neck" effectively raises the measured position a little bit. @@ -122,7 +125,7 @@ void SixenseManager::update(float deltaTime) { // Compute current velocity from position change glm::vec3 rawVelocity; if (deltaTime > 0.f) { - rawVelocity = (position - palm->getRawPosition()) * (METERS_PER_MILLIMETER / deltaTime); + rawVelocity = (position - palm->getRawPosition()) / deltaTime; } else { rawVelocity = glm::vec3(0.0f); } @@ -138,12 +141,12 @@ void SixenseManager::update(float deltaTime) { } // Store the one fingertip in the palm structure so we can track velocity - const float FINGER_LENGTH = 300.0f; // meters + 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) * (METERS_PER_MILLIMETER / deltaTime)); + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); } else { palm->setTipVelocity(glm::vec3(0.f)); } @@ -173,8 +176,8 @@ void SixenseManager::update(float deltaTime) { // (4) move arms a bit forward (Z) // (5) release BUTTON_FWD on both hands -const float MINIMUM_ARM_REACH = 300.f; // millimeters -const float MAXIMUM_NOISE_LEVEL = 50.f; // millimeters +const float MINIMUM_ARM_REACH = 0.3f; // meters +const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired void SixenseManager::updateCalibration(const sixenseControllerData* controllers) { @@ -214,10 +217,13 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) return; } + // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. const float* pos = dataLeft->pos; glm::vec3 positionLeft(pos[0], pos[1], pos[2]); + positionLeft *= METERS_PER_MILLIMETER; pos = dataRight->pos; glm::vec3 positionRight(pos[0], pos[1], pos[2]); + positionRight *= METERS_PER_MILLIMETER; if (_calibrationState == CALIBRATION_STATE_IDLE) { float reach = glm::distance(positionLeft, positionRight); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 109eab5c5d..4dad06fa84 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -27,7 +27,7 @@ HandData::HandData(AvatarData* owningAvatar) : } glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { - return glm::inverse(getBaseOrientation()) * worldVector / LEAP_UNIT_SCALE; + return glm::inverse(getBaseOrientation()) * worldVector; } PalmData& HandData::addNewPalm() { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 968d7bbe38..d1e11aed8e 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -30,8 +30,6 @@ const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND; const int LEAPID_INVALID = -1; const int SIXENSEID_INVALID = -1; -const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters - const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0; const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1; @@ -42,7 +40,7 @@ public: // position conversion glm::vec3 localToWorldPosition(const glm::vec3& localPosition) { - return getBasePosition() + getBaseOrientation() * localPosition * LEAP_UNIT_SCALE; + return getBasePosition() + getBaseOrientation() * localPosition; } glm::vec3 localToWorldDirection(const glm::vec3& localVector) { From cea472b7304b9498055d5b6ada716c8113644f0c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 May 2014 11:48:56 -0700 Subject: [PATCH 03/11] remove the last of Leap specific cruft --- interface/src/avatar/SkeletonModel.cpp | 4 ++-- libraries/avatars/src/HandData.cpp | 1 - libraries/avatars/src/HandData.h | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 7a6fadeb6b..a2e637f4e7 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -33,7 +33,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { return; // only simulate for own avatar } - // find the left and rightmost active Leap palms + // find the left and rightmost active palms int leftPalmIndex, rightPalmIndex; Hand* hand = _owningAvatar->getHand(); hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); @@ -42,7 +42,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (leftPalmIndex == -1) { - // no Leap data; set hands from mouse + // palms are not yet set, use mouse if (_owningAvatar->getHandState() == HAND_STATE_NULL) { restoreRightHandPosition(HAND_RESTORATION_RATE); } else { diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 4dad06fa84..446cf2bc2a 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -71,7 +71,6 @@ _rotationalVelocity(0.f), _totalPenetration(0.f), _controllerButtons(0), _isActive(false), -_leapID(LEAPID_INVALID), _sixenseID(SIXENSEID_INVALID), _numFramesWithoutData(0), _owningHandData(owningHandData), diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index d1e11aed8e..1f2d134c43 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -91,11 +91,9 @@ public: const glm::vec3& getRawPosition() const { return _rawPosition; } bool isActive() const { return _isActive; } - int getLeapID() const { return _leapID; } int getSixenseID() const { return _sixenseID; } void setActive(bool active) { _isActive = active; } - void setLeapID(int id) { _leapID = id; } void setSixenseID(int id) { _sixenseID = id; } void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; @@ -166,7 +164,6 @@ private: float _joystickX, _joystickY; bool _isActive; // This has current valid data - int _leapID; // the Leap's serial id for this tracked object int _sixenseID; // Sixense controller ID for this palm int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. HandData* _owningHandData; From e983be401354958de53788c311027566f8af64bc Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 May 2014 11:52:16 -0700 Subject: [PATCH 04/11] fix typo (finger length = 0.3m, not 0.03m) --- libraries/avatars/src/HandData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 446cf2bc2a..bd366f020a 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -110,7 +110,7 @@ glm::vec3 HandData::getBasePosition() const { } glm::vec3 PalmData::getFingerTipPosition() const { - glm::vec3 fingerOffset(0.0f, 0.0f, 0.03f); + glm::vec3 fingerOffset(0.0f, 0.0f, 0.3f); glm::vec3 palmOffset(0.0f, -0.08f, 0.0f); return getPosition() + _owningHandData->localToWorldDirection(_rawRotation * (fingerOffset + palmOffset)); } From 90d577a48c4050e3a85b34ea054b7aa7cb78c727 Mon Sep 17 00:00:00 2001 From: Kai Ludwig Date: Tue, 13 May 2014 00:37:36 +0200 Subject: [PATCH 05/11] Stats area is now always right of mirror display, regardless if mirror display is enabled or not as there is always a remaining audio meter. Display, resize and click cases have been adapted by removing the condition for checking display status of mirror. --- interface/src/Application.cpp | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b59fc3aa2..8858b6d324 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -686,11 +686,8 @@ void Application::resizeGL(int width, int height) { glLoadIdentity(); // update Stats width - int horizontalOffset = 0; - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - // mirror is enabled, let's set horizontal offset to give stats some margin - horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; - } + // let's set horizontal offset to give stats some margin to mirror + int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; Stats::getInstance()->resetWidth(width, horizontalOffset); } @@ -1164,10 +1161,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { _mousePressed = false; checkBandwidthMeterClick(); if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { - int horizontalOffset = 0; - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - horizontalOffset = MIRROR_VIEW_WIDTH; - } + // let's set horizontal offset to give stats some margin to mirror + int horizontalOffset = MIRROR_VIEW_WIDTH; Stats::getInstance()->checkClick(_mouseX, _mouseY, _mouseDragStartedX, _mouseDragStartedY, horizontalOffset); } } @@ -2732,11 +2727,8 @@ void Application::displayOverlay() { glPointSize(1.0f); if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { - int horizontalOffset = 0; - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - // mirror is enabled, let's set horizontal offset to give stats some margin - horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; - } + // let's set horizontal offset to give stats some margin to mirror + int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount(); // Onscreen text about position, servers, etc Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, _fps, _packetsPerSecond, _bytesPerSecond, voxelPacketsToProcess); From 8b15873488f7003dcb0c7e5ca36e2538474a895b Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 12 May 2014 16:37:52 -0600 Subject: [PATCH 06/11] Change to Oculus find path in Windows --- cmake/modules/FindLibOVR.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index c07b4c14c1..415eeeb1c5 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -49,7 +49,7 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(WINDOWS_LIBOVR_NAME "libovr.lib") endif() - find_library(LIBOVR_LIBRARIES "Lib/Win32/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARIES "Lib/Win32/VS2010/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) endif () if (LIBOVR_INCLUDE_DIRS AND LIBOVR_LIBRARIES) From 415bc64ce9cd9090c4eae9d8e3d8c58bddc7e085 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 12 May 2014 16:44:15 -0600 Subject: [PATCH 07/11] Moving stuff around --- cmake/modules/FindLibOVR.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index 415eeeb1c5..a85e1bec55 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -24,7 +24,7 @@ if (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(LIBOVR_SEARCH_DIRS "${LIBOVR_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/oculus") - find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include HINTS ${LIBOVR_SEARCH_DIRS}) + find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) if (APPLE) find_library(LIBOVR_LIBRARIES "Lib/MacOS/Release/libovr.a" HINTS ${LIBOVR_SEARCH_DIRS}) @@ -49,7 +49,7 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(WINDOWS_LIBOVR_NAME "libovr.lib") endif() - find_library(LIBOVR_LIBRARIES "Lib/Win32/VS2010/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARIES "Lib/Win32/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) endif () if (LIBOVR_INCLUDE_DIRS AND LIBOVR_LIBRARIES) From 1869248351b8c73e5c5a271a7d28f2978f34798a Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 12 May 2014 16:46:24 -0600 Subject: [PATCH 08/11] Moving stuff around --- cmake/modules/FindLibOVR.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index a85e1bec55..058dc0a228 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -24,7 +24,7 @@ if (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(LIBOVR_SEARCH_DIRS "${LIBOVR_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/oculus") - find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + find_path(LIBOVR_INCLUDE_DIRS OVR.h PATH_SUFFIXES Include HINTS ${LIBOVR_SEARCH_DIRS}) if (APPLE) find_library(LIBOVR_LIBRARIES "Lib/MacOS/Release/libovr.a" HINTS ${LIBOVR_SEARCH_DIRS}) @@ -49,7 +49,7 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(WINDOWS_LIBOVR_NAME "libovr.lib") endif() - find_library(LIBOVR_LIBRARIES "Lib/Win32/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARIES "Lib/Win32/${LIBOVR_NAME}" PATH_SUFFIXES VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) endif () if (LIBOVR_INCLUDE_DIRS AND LIBOVR_LIBRARIES) From c7e103e98992e24d6faf3a7ed3e3bcac10b9ecc9 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Mon, 12 May 2014 19:43:56 -0600 Subject: [PATCH 09/11] Not working with path_suffixes, testing something else --- cmake/modules/FindLibOVR.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index 058dc0a228..415eeeb1c5 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -49,7 +49,7 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) set(WINDOWS_LIBOVR_NAME "libovr.lib") endif() - find_library(LIBOVR_LIBRARIES "Lib/Win32/${LIBOVR_NAME}" PATH_SUFFIXES VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARIES "Lib/Win32/VS2010/${LIBOVR_NAME}" HINTS ${LIBOVR_SEARCH_DIRS}) endif () if (LIBOVR_INCLUDE_DIRS AND LIBOVR_LIBRARIES) From 55d96147578860f1898832be0549109f9fa3c374 Mon Sep 17 00:00:00 2001 From: Bennett Goble Date: Tue, 13 May 2014 00:58:49 -0400 Subject: [PATCH 10/11] Menu.cpp Typo: goToOrientation calling goToDestination. --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e1d0c6a574..2daf5b0240 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -889,7 +889,7 @@ void Menu::goToDomainDialog() { } void Menu::goToOrientation(QString orientation) { - LocationManager::getInstance().goToDestination(orientation); + LocationManager::getInstance().goToOrientation(orientation); } bool Menu::goToDestination(QString destination) { From 607094075ce050d3f504fcdfa296254e9e4fea3c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 13 May 2014 10:38:56 -0700 Subject: [PATCH 11/11] Revert "Merge pull request #2834 from andrew/thermonuclear" This reverts commit e088c3d1150aaee0401adc5e1fbe0bb4d9c9d6cc, reversing changes made to d124c0319d9aaefd9eb223db8db41f492a60ad0b. --- interface/src/BuckyBalls.cpp | 8 +- interface/src/avatar/Avatar.cpp | 16 ++- interface/src/avatar/Hand.cpp | 64 ++++++++-- interface/src/avatar/SkeletonModel.cpp | 30 +++-- interface/src/devices/SixenseManager.cpp | 45 ++++--- .../ControllerScriptingInterface.cpp | 4 +- libraries/avatars/src/HandData.cpp | 110 +++++++++++++++--- libraries/avatars/src/HandData.h | 87 +++++++++++--- libraries/shared/src/SharedUtil.h | 1 - 9 files changed, 288 insertions(+), 77 deletions(-) diff --git a/interface/src/BuckyBalls.cpp b/interface/src/BuckyBalls.cpp index 68d1167071..e1ec41dca1 100644 --- a/interface/src/BuckyBalls.cpp +++ b/interface/src/BuckyBalls.cpp @@ -60,13 +60,15 @@ BuckyBalls::BuckyBalls() { void BuckyBalls::grab(PalmData& palm, float deltaTime) { float penetration; - glm::vec3 fingerTipPosition = palm.getFingerTipPosition(); + glm::vec3 diff; + FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger + glm::vec3 fingerTipPosition = finger.getTipPosition(); if (palm.getControllerButtons() & BUTTON_FWD) { if (!_bballIsGrabbed[palm.getSixenseID()]) { // Look for a ball to grab for (int i = 0; i < NUM_BBALLS; i++) { - glm::vec3 diff = _bballPosition[i] - fingerTipPosition; + diff = _bballPosition[i] - fingerTipPosition; penetration = glm::length(diff) - (_bballRadius[i] + COLLISION_RADIUS); if (penetration < 0.f) { _bballIsGrabbed[palm.getSixenseID()] = i; @@ -75,7 +77,7 @@ void BuckyBalls::grab(PalmData& palm, float deltaTime) { } if (_bballIsGrabbed[palm.getSixenseID()]) { // If ball being grabbed, move with finger - glm::vec3 diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; + diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition; penetration = glm::length(diff) - (_bballRadius[_bballIsGrabbed[palm.getSixenseID()]] + COLLISION_RADIUS); _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] -= glm::normalize(diff) * penetration; glm::vec3 fingerTipVelocity = palm.getTipVelocity(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2bd0bbbc6d..41dc50b1fa 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -609,6 +609,18 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti const PalmData* palm = handData->getPalm(i); if (palm && palm->hasPaddle()) { // create a disk collision proxy where the hand is + glm::vec3 fingerAxis(0.0f); + for (size_t f = 0; f < palm->getNumFingers(); ++f) { + const FingerData& finger = (palm->getFingers())[f]; + if (finger.isActive()) { + // compute finger axis + glm::vec3 fingerTip = finger.getTipPosition(); + glm::vec3 fingerRoot = finger.getRootPosition(); + fingerAxis = glm::normalize(fingerTip - fingerRoot); + break; + } + } + int jointIndex = -1; glm::vec3 handPosition; if (i == 0) { @@ -619,10 +631,8 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti _skeletonModel.getRightHandPosition(handPosition); jointIndex = _skeletonModel.getRightHandJointIndex(); } - - glm::vec3 fingerAxis = palm->getFingerDirection(); glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis; - glm::vec3 diskNormal = palm->getPalmDirection(); + glm::vec3 diskNormal = palm->getNormal(); const float DISK_THICKNESS = 0.08f; // collide against the disk diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 35132af929..4774e23cb2 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -176,7 +176,8 @@ void Hand::renderHandTargets(bool isMine) { if (!palm.isActive()) { continue; } - glm::vec3 targetPosition = palm.getFingerTipPosition(); + glm::vec3 targetPosition; + palm.getBallHoldPosition(targetPosition); glPushMatrix(); glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z); @@ -196,20 +197,59 @@ void Hand::renderHandTargets(bool isMine) { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; if (palm.isActive()) { - glColor4f(handColor.r, handColor.g, handColor.b, alpha); - glm::vec3 tip = palm.getFingerTipPosition(); - glm::vec3 root = palm.getPosition(); - Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); - // Render sphere at palm/finger root - glm::vec3 offsetFromPalm = root + palm.getPalmDirection() * PALM_DISK_THICKNESS; - Avatar::renderJointConnectingCone(root, offsetFromPalm, PALM_DISK_RADIUS, 0.0f); - glPushMatrix(); - glTranslatef(root.x, root.y, root.z); - glutSolidSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); - glPopMatrix(); + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + if (finger.isActive()) { + glColor4f(handColor.r, handColor.g, handColor.b, alpha); + glm::vec3 tip = finger.getTipPosition(); + glm::vec3 root = finger.getRootPosition(); + Avatar::renderJointConnectingCone(root, tip, PALM_FINGER_ROD_RADIUS, PALM_FINGER_ROD_RADIUS); + // Render sphere at palm/finger root + glm::vec3 palmNormal = root + palm.getNormal() * PALM_DISK_THICKNESS; + Avatar::renderJointConnectingCone(root, palmNormal, PALM_DISK_RADIUS, 0.0f); + glPushMatrix(); + glTranslatef(root.x, root.y, root.z); + glutSolidSphere(PALM_BALL_RADIUS, 20.0f, 20.0f); + glPopMatrix(); + + } + } } } + /* + // Draw the hand paddles + int MAX_NUM_PADDLES = 2; // one for left and one for right + glColor4f(handColor.r, handColor.g, handColor.b, 0.3f); + for (int i = 0; i < MAX_NUM_PADDLES; i++) { + const PalmData* palm = getPalm(i); + if (palm) { + // compute finger axis + glm::vec3 fingerAxis(0.f); + for (size_t f = 0; f < palm->getNumFingers(); ++f) { + const FingerData& finger = (palm->getFingers())[f]; + if (finger.isActive()) { + glm::vec3 fingerTip = finger.getTipPosition(); + glm::vec3 fingerRoot = finger.getRootPosition(); + fingerAxis = glm::normalize(fingerTip - fingerRoot); + break; + } + } + // compute paddle position + glm::vec3 handPosition; + if (i == SIXENSE_CONTROLLER_ID_LEFT_HAND) { + _owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition); + } else if (i == SIXENSE_CONTROLLER_ID_RIGHT_HAND) { + _owningAvatar->getSkeletonModel().getRightHandPosition(handPosition); + } + glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis; + glm::vec3 root = tip + palm->getNormal() * HAND_PADDLE_THICKNESS; + // render a very shallow cone as the paddle + Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f); + } + } + */ + glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index a2e637f4e7..8c21a3240f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -33,7 +33,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { return; // only simulate for own avatar } - // find the left and rightmost active palms + // find the left and rightmost active Leap palms int leftPalmIndex, rightPalmIndex; Hand* hand = _owningAvatar->getHand(); hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex); @@ -42,7 +42,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); if (leftPalmIndex == -1) { - // palms are not yet set, use mouse + // no Leap data; set hands from mouse if (_owningAvatar->getHandState() == HAND_STATE_NULL) { restoreRightHandPosition(HAND_RESTORATION_RATE); } else { @@ -159,13 +159,29 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } else { getJointRotation(jointIndex, palmRotation, true); } - palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getPalmDirection()) * palmRotation; + palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; + // sort the finger indices by raw x, get the average direction + QVector fingerIndices; + glm::vec3 direction; + for (size_t i = 0; i < palm.getNumFingers(); i++) { + glm::vec3 fingerVector = palm.getFingers()[i].getTipPosition() - palm.getPosition(); + float length = glm::length(fingerVector); + if (length > EPSILON) { + direction += fingerVector / length; + } + fingerVector = glm::inverse(palmRotation) * fingerVector * -sign; + IndexValue indexValue = { (int)i, atan2f(fingerVector.z, fingerVector.x) }; + fingerIndices.append(indexValue); + } + qSort(fingerIndices.begin(), fingerIndices.end()); + // rotate forearm according to average finger direction - // NOTE: we're doing this in the avatar local frame, so we DON'T want to use Palm::getHandDirection() - // which returns the world-frame. - glm::vec3 direction = palm.getRawRotation() * glm::vec3(0.0f, 0.0f, 1.0f); - palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; + float directionLength = glm::length(direction); + const unsigned int MIN_ROTATION_FINGERS = 3; + if (directionLength > EPSILON && palm.getNumFingers() >= MIN_ROTATION_FINGERS) { + palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; + } // set hand position, rotation if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 1698cebcf9..0435519124 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -22,9 +22,9 @@ const int CALIBRATION_STATE_Z = 3; const int CALIBRATION_STATE_COMPLETE = 4; // default (expected) location of neck in sixense space -const float NECK_X = 0.25f; // meters -const float NECK_Y = 0.3f; // meters -const float NECK_Z = 0.3f; // meters +const float NECK_X = 250.f; // millimeters +const float NECK_Y = 300.f; // millimeters +const float NECK_Z = 300.f; // millimeters #endif SixenseManager::SixenseManager() { @@ -106,11 +106,8 @@ void SixenseManager::update(float deltaTime) { palm->setControllerButtons(data->buttons); palm->setTrigger(data->trigger); palm->setJoystick(data->joystick_x, data->joystick_y); - - // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. - glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); - position *= METERS_PER_MILLIMETER; + glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); // Transform the measured position into body frame. glm::vec3 neck = _neckBase; // Zeroing y component of the "neck" effectively raises the measured position a little bit. @@ -120,12 +117,15 @@ void SixenseManager::update(float deltaTime) { // Rotation of Palm glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation; + const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f); + glm::vec3 newNormal = rotation * PALM_VECTOR; + palm->setRawNormal(newNormal); palm->setRawRotation(rotation); // Compute current velocity from position change glm::vec3 rawVelocity; if (deltaTime > 0.f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; + rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f; } else { rawVelocity = glm::vec3(0.0f); } @@ -140,17 +140,29 @@ void SixenseManager::update(float deltaTime) { _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 + // initialize the "finger" based on the direction + FingerData finger(palm, hand); + finger.setActive(true); + finger.setRawRootPosition(position); + const float FINGER_LENGTH = 300.0f; // Millimeters const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; + finger.setRawTipPosition(position + rotation * FINGER_VECTOR); + + // Store the one fingertip in the palm structure so we can track velocity glm::vec3 oldTipPosition = palm->getTipRawPosition(); if (deltaTime > 0.f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f); } else { palm->setTipVelocity(glm::vec3(0.f)); } palm->setTipPosition(newTipPosition); + + // three fingers indicates to the skeleton that we have enough data to determine direction + palm->getFingers().clear(); + palm->getFingers().push_back(finger); + palm->getFingers().push_back(finger); + palm->getFingers().push_back(finger); } if (numActiveControllers == 2) { @@ -159,7 +171,7 @@ void SixenseManager::update(float deltaTime) { // if the controllers haven't been moved in a while, disable const unsigned int MOVEMENT_DISABLE_SECONDS = 3; - if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) { + if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * 1000 * 1000)) { for (std::vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { it->setActive(false); } @@ -176,8 +188,8 @@ void SixenseManager::update(float deltaTime) { // (4) move arms a bit forward (Z) // (5) release BUTTON_FWD on both hands -const float MINIMUM_ARM_REACH = 0.3f; // meters -const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters +const float MINIMUM_ARM_REACH = 300.f; // millimeters +const float MAXIMUM_NOISE_LEVEL = 50.f; // millimeters const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired void SixenseManager::updateCalibration(const sixenseControllerData* controllers) { @@ -217,17 +229,14 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) return; } - // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. const float* pos = dataLeft->pos; glm::vec3 positionLeft(pos[0], pos[1], pos[2]); - positionLeft *= METERS_PER_MILLIMETER; pos = dataRight->pos; glm::vec3 positionRight(pos[0], pos[1], pos[2]); - positionRight *= METERS_PER_MILLIMETER; if (_calibrationState == CALIBRATION_STATE_IDLE) { float reach = glm::distance(positionLeft, positionRight); - if (reach > 2.0f * MINIMUM_ARM_REACH) { + if (reach > 2.f * MINIMUM_ARM_REACH) { qDebug("started: sixense calibration"); _averageLeft = positionLeft; _averageRight = positionRight; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 5e58ac66ea..aa14f769de 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -198,9 +198,9 @@ glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex if (palmData) { switch (controlOfPalm) { case PALM_SPATIALCONTROL: - return palmData->getPalmDirection(); + return palmData->getNormal(); case TIP_SPATIALCONTROL: - return palmData->getFingerDirection(); + return palmData->getNormal(); // currently the tip doesn't have a unique normal, use the palm normal } } return glm::vec3(0); // bad index diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index bd366f020a..c2e3b51cb3 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -26,8 +26,8 @@ HandData::HandData(AvatarData* owningAvatar) : addNewPalm(); } -glm::vec3 HandData::worldToLocalVector(const glm::vec3& worldVector) const { - return glm::inverse(getBaseOrientation()) * worldVector; +glm::vec3 HandData::worldVectorToLeapVector(const glm::vec3& worldVector) const { + return glm::inverse(getBaseOrientation()) * worldVector / LEAP_UNIT_SCALE; } PalmData& HandData::addNewPalm() { @@ -66,21 +66,69 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) PalmData::PalmData(HandData* owningHandData) : _rawRotation(0.f, 0.f, 0.f, 1.f), _rawPosition(0.f), +_rawNormal(0.f, 1.f, 0.f), _rawVelocity(0.f), _rotationalVelocity(0.f), _totalPenetration(0.f), _controllerButtons(0), _isActive(false), +_leapID(LEAPID_INVALID), _sixenseID(SIXENSEID_INVALID), _numFramesWithoutData(0), _owningHandData(owningHandData), _isCollidingWithVoxel(false), _isCollidingWithPalm(false), -_collisionlessPaddleExpiry(0) { +_collisionlessPaddleExpiry(0) +{ + for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) { + _fingers.push_back(FingerData(this, owningHandData)); + } } void PalmData::addToPosition(const glm::vec3& delta) { - _rawPosition += _owningHandData->worldToLocalVector(delta); + // convert to Leap coordinates, then add to palm and finger positions + glm::vec3 leapDelta = _owningHandData->worldVectorToLeapVector(delta); + _rawPosition += leapDelta; + for (size_t i = 0; i < getNumFingers(); i++) { + FingerData& finger = _fingers[i]; + if (finger.isActive()) { + finger.setRawTipPosition(finger.getTipRawPosition() + leapDelta); + finger.setRawRootPosition(finger.getRootRawPosition() + leapDelta); + } + } +} + +FingerData::FingerData(PalmData* owningPalmData, HandData* owningHandData) : +_tipRawPosition(0, 0, 0), +_rootRawPosition(0, 0, 0), +_isActive(false), +_leapID(LEAPID_INVALID), +_numFramesWithoutData(0), +_owningPalmData(owningPalmData), +_owningHandData(owningHandData) +{ + const int standardTrailLength = 10; + setTrailLength(standardTrailLength); +} + +void HandData::setFingerTrailLength(unsigned int length) { + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.setTrailLength(length); + } + } +} + +void HandData::updateFingerTrails() { + for (size_t i = 0; i < getNumPalms(); ++i) { + PalmData& palm = getPalms()[i]; + for (size_t f = 0; f < palm.getNumFingers(); ++f) { + FingerData& finger = palm.getFingers()[f]; + finger.updateTrail(); + } + } } bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, @@ -109,20 +157,54 @@ glm::vec3 HandData::getBasePosition() const { return _owningAvatarData->getPosition(); } -glm::vec3 PalmData::getFingerTipPosition() const { - glm::vec3 fingerOffset(0.0f, 0.0f, 0.3f); - glm::vec3 palmOffset(0.0f, -0.08f, 0.0f); - return getPosition() + _owningHandData->localToWorldDirection(_rawRotation * (fingerOffset + palmOffset)); +void FingerData::setTrailLength(unsigned int length) { + _tipTrailPositions.resize(length); + _tipTrailCurrentStartIndex = 0; + _tipTrailCurrentValidLength = 0; } -glm::vec3 PalmData::getFingerDirection() const { - const glm::vec3 LOCAL_FINGER_DIRECTION(0.0f, 0.0f, 1.0f); - return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_FINGER_DIRECTION); +void FingerData::updateTrail() { + if (_tipTrailPositions.size() == 0) + return; + + if (_isActive) { + // Add the next point in the trail. + _tipTrailCurrentStartIndex--; + if (_tipTrailCurrentStartIndex < 0) + _tipTrailCurrentStartIndex = _tipTrailPositions.size() - 1; + + _tipTrailPositions[_tipTrailCurrentStartIndex] = getTipPosition(); + + if (_tipTrailCurrentValidLength < (int)_tipTrailPositions.size()) + _tipTrailCurrentValidLength++; + } + else { + // It's not active, so just kill the trail. + _tipTrailCurrentValidLength = 0; + } } -glm::vec3 PalmData::getPalmDirection() const { - const glm::vec3 LOCAL_PALM_DIRECTION(0.0f, -1.0f, 0.0f); - return _owningHandData->localToWorldDirection(_rawRotation * LOCAL_PALM_DIRECTION); +int FingerData::getTrailNumPositions() { + return _tipTrailCurrentValidLength; +} + +const glm::vec3& FingerData::getTrailPosition(int index) { + if (index >= _tipTrailCurrentValidLength) { + static glm::vec3 zero(0,0,0); + return zero; + } + int posIndex = (index + _tipTrailCurrentStartIndex) % _tipTrailCurrentValidLength; + return _tipTrailPositions[posIndex]; +} + +void PalmData::getBallHoldPosition(glm::vec3& position) const { + const float BALL_FORWARD_OFFSET = 0.08f; // put the ball a bit forward of fingers + position = BALL_FORWARD_OFFSET * getNormal(); + if (_fingers.size() > 0) { + position += _fingers[0].getTipPosition(); + } else { + position += getPosition(); + } } diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 1f2d134c43..a37e3a5814 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -21,6 +21,7 @@ #include "SharedUtil.h" class AvatarData; +class FingerData; class PalmData; const int NUM_HANDS = 2; @@ -30,6 +31,8 @@ const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND; const int LEAPID_INVALID = -1; const int SIXENSEID_INVALID = -1; +const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters + const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0; const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1; @@ -38,16 +41,17 @@ public: HandData(AvatarData* owningAvatar); virtual ~HandData() {} + // These methods return the positions in Leap-relative space. + // To convert to world coordinates, use Hand::leapPositionToWorldPosition. + // position conversion - glm::vec3 localToWorldPosition(const glm::vec3& localPosition) { - return getBasePosition() + getBaseOrientation() * localPosition; + glm::vec3 leapPositionToWorldPosition(const glm::vec3& leapPosition) { + return getBasePosition() + getBaseOrientation() * (leapPosition * LEAP_UNIT_SCALE); } - - glm::vec3 localToWorldDirection(const glm::vec3& localVector) { - return getBaseOrientation() * localVector; - } - - glm::vec3 worldToLocalVector(const glm::vec3& worldVector) const; + glm::vec3 leapDirectionToWorldDirection(const glm::vec3& leapDirection) { + return getBaseOrientation() * leapDirection; + } + glm::vec3 worldVectorToLeapVector(const glm::vec3& worldVector) const; std::vector& getPalms() { return _palms; } const std::vector& getPalms() const { return _palms; } @@ -59,6 +63,9 @@ public: /// both is not found. void getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const; + void setFingerTrailLength(unsigned int length); + void updateFingerTrails(); + /// Checks for penetration between the described sphere and the hand. /// \param penetratorCenter the center of the penetration test sphere /// \param penetratorRadius the radius of the penetration test sphere @@ -82,23 +89,71 @@ private: HandData& operator= (const HandData&); }; +class FingerData { +public: + FingerData(PalmData* owningPalmData, HandData* owningHandData); + + glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipRawPosition); } + glm::vec3 getRootPosition() const { return _owningHandData->leapPositionToWorldPosition(_rootRawPosition); } + const glm::vec3& getTipRawPosition() const { return _tipRawPosition; } + const glm::vec3& getRootRawPosition() const { return _rootRawPosition; } + bool isActive() const { return _isActive; } + int getLeapID() const { return _leapID; } + + void setActive(bool active) { _isActive = active; } + void setLeapID(int id) { _leapID = id; } + void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; } + void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; } + + void setTrailLength(unsigned int length); + void updateTrail(); + + int getTrailNumPositions(); + const glm::vec3& getTrailPosition(int index); + + void incrementFramesWithoutData() { _numFramesWithoutData++; } + void resetFramesWithoutData() { _numFramesWithoutData = 0; } + int getFramesWithoutData() const { return _numFramesWithoutData; } + +private: + glm::vec3 _tipRawPosition; + glm::vec3 _rootRawPosition; + bool _isActive; // This has current valid data + int _leapID; // the Leap's serial id for this tracked object + int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. + std::vector _tipTrailPositions; + int _tipTrailCurrentStartIndex; + int _tipTrailCurrentValidLength; + PalmData* _owningPalmData; + HandData* _owningHandData; +}; class PalmData { public: PalmData(HandData* owningHandData); - glm::vec3 getPosition() const { return _owningHandData->localToWorldPosition(_rawPosition); } - glm::vec3 getVelocity() const { return _owningHandData->localToWorldDirection(_rawVelocity); } + glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); } + glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); } + glm::vec3 getVelocity() const { return _owningHandData->leapDirectionToWorldDirection(_rawVelocity); } const glm::vec3& getRawPosition() const { return _rawPosition; } + const glm::vec3& getRawNormal() const { return _rawNormal; } bool isActive() const { return _isActive; } + int getLeapID() const { return _leapID; } int getSixenseID() const { return _sixenseID; } + + std::vector& getFingers() { return _fingers; } + const std::vector& getFingers() const { return _fingers; } + size_t getNumFingers() const { return _fingers.size(); } + void setActive(bool active) { _isActive = active; } + void setLeapID(int id) { _leapID = id; } void setSixenseID(int id) { _sixenseID = id; } void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; glm::quat getRawRotation() const { return _rawRotation; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } + void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; } void addToPosition(const glm::vec3& delta); @@ -107,11 +162,11 @@ public: void resolvePenetrations() { addToPosition(-_totalPenetration); _totalPenetration = glm::vec3(0.f); } void setTipPosition(const glm::vec3& position) { _tipPosition = position; } - const glm::vec3 getTipPosition() const { return _owningHandData->localToWorldPosition(_tipPosition); } + const glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipPosition); } const glm::vec3& getTipRawPosition() const { return _tipPosition; } void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; } - const glm::vec3 getTipVelocity() const { return _owningHandData->localToWorldDirection(_tipVelocity); } + const glm::vec3 getTipVelocity() const { return _owningHandData->leapDirectionToWorldDirection(_tipVelocity); } const glm::vec3& getTipRawVelocity() const { return _tipVelocity; } void incrementFramesWithoutData() { _numFramesWithoutData++; } @@ -143,14 +198,11 @@ public: /// Store position where the palm holds the ball. void getBallHoldPosition(glm::vec3& position) const; - // return world-frame: - glm::vec3 getFingerTipPosition() const; - glm::vec3 getFingerDirection() const; - glm::vec3 getPalmDirection() const; - private: + std::vector _fingers; glm::quat _rawRotation; glm::vec3 _rawPosition; + glm::vec3 _rawNormal; glm::vec3 _rawVelocity; glm::vec3 _rotationalVelocity; glm::quat _lastRotation; @@ -164,6 +216,7 @@ private: float _joystickX, _joystickY; bool _isActive; // This has current valid data + int _leapID; // the Leap's serial id for this tracked object int _sixenseID; // Sixense controller ID for this palm int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost. HandData* _owningHandData; diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index d111439b7e..4a3fe2a129 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -54,7 +54,6 @@ static const float SQUARE_ROOT_OF_3 = (float)sqrt(3.f); static const float METERS_PER_DECIMETER = 0.1f; static const float METERS_PER_CENTIMETER = 0.01f; static const float METERS_PER_MILLIMETER = 0.001f; -static const float MILLIMETERS_PER_METER = 1000.0f; static const quint64 USECS_PER_MSEC = 1000; static const quint64 MSECS_PER_SECOND = 1000; static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;