From cb6f542b9f36f6ae765b48a260a30896295cf19b Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Wed, 17 Jul 2013 17:00:23 -0700 Subject: [PATCH] First-pass finger motion trails --- interface/src/Hand.cpp | 31 ++++++++++++++ interface/src/Hand.h | 1 + libraries/avatars/src/HandData.cpp | 65 ++++++++++++++++++++++++++++++ libraries/avatars/src/HandData.h | 11 +++++ 4 files changed, 108 insertions(+) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index bbfd58c5b1..6e9cf1ca7f 100755 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -95,6 +95,7 @@ void Hand::render(bool lookingInMirror) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); + renderFingerTrails(); renderHandSpheres(); } @@ -173,6 +174,35 @@ void Hand::renderHandSpheres() { glPopMatrix(); } +void Hand::renderFingerTrails() { + // Draw the finger root cones + 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]; + int numPositions = finger.getTrailNumPositions(); + if (numPositions > 0) { + glBegin(GL_TRIANGLE_STRIP); + for (int t = 0; t < numPositions; ++t) + { + const glm::vec3& center = finger.getTrailPosition(t); + const float halfWidth = 0.001f; + const glm::vec3 edgeDirection(1.0f, 0.0f, 0.0f); + glm::vec3 edge0 = center + edgeDirection * halfWidth; + glm::vec3 edge1 = center - edgeDirection * halfWidth; + float alpha = 1.0f - ((float)t / (float)(numPositions - 1)); + glColor4f(1.0f, 0.0f, 0.0f, alpha); + glVertex3fv((float*)&edge0); + glVertex3fv((float*)&edge1); + } + glEnd(); + } + } + } + } +} + void Hand::setLeapFingers(const std::vector& fingerTips, const std::vector& fingerRoots) { // TODO: add id-checking here to increase finger stability @@ -193,6 +223,7 @@ void Hand::setLeapFingers(const std::vector& fingerTips, } } } + updateFingerTrails(); } void Hand::setLeapHands(const std::vector& handPositions, diff --git a/interface/src/Hand.h b/interface/src/Hand.h index fb6b863458..aed406dea5 100755 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -74,6 +74,7 @@ private: // private methods void renderRaveGloveStage(); void renderHandSpheres(); + void renderFingerTrails(); void calculateGeometry(); }; diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 32e83b352d..ffe5615823 100755 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -16,6 +16,8 @@ HandData::HandData(AvatarData* owningAvatar) : for (int i = 0; i < 2; ++i) { _palms.push_back(PalmData(this)); } + const int standardTrailLength = 30; + setFingerTrailLength(standardTrailLength); } PalmData::PalmData(HandData* owningHandData) : @@ -80,3 +82,66 @@ void HandData::decodeRemoteData(const std::vector& fingerVectors) { } } +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(); + } + } +} + +void FingerData::setTrailLength(unsigned int length) { + _tipTrailPositions.resize(length); + _tipTrailCurrentStartIndex = 0; + _tipTrailCurrentValidLength = 0; +} + +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 < _tipTrailPositions.size()) + _tipTrailCurrentValidLength++; + } + else { + // It's not active, so just shorten the trail. + if (_tipTrailCurrentValidLength > 0) + _tipTrailCurrentValidLength--; + } +} + +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]; +} + + + diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 65b32ff5c6..f52171b403 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -40,6 +40,9 @@ public: std::vector& getPalms() { return _palms; } size_t getNumPalms() { return _palms.size(); } + void setFingerTrailLength(unsigned int length); + void updateFingerTrails(); + // Use these for sending and receiving hand data void encodeRemoteData(std::vector& fingerVectors); void decodeRemoteData(const std::vector& fingerVectors); @@ -69,11 +72,19 @@ public: void setActive(bool active) { _isActive = active; } 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); + private: glm::vec3 _tipRawPosition; glm::vec3 _rootRawPosition; bool _isActive; // This has current valid data + std::vector _tipTrailPositions; + int _tipTrailCurrentStartIndex; + int _tipTrailCurrentValidLength; PalmData* _owningPalmData; HandData* _owningHandData; };