From a3a5c3d6d49f5dfcc28c88f3402cb48cd94e3379 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Mon, 5 Aug 2013 13:25:05 -0700 Subject: [PATCH] Rave glove demo: Network rave data Sending glove modes over the network, and fixed ghost-fingers-left-behind issue. Issues addressed: https://basecamp.com/2151194/projects/2058851-avatar/todos/54607028-bug-phantom-leap https://basecamp.com/2151194/projects/2058851-avatar/todos/54633674-demo-make --- interface/src/avatar/Hand.cpp | 2 - interface/src/avatar/Hand.h | 22 +--- libraries/avatars/src/AvatarData.cpp | 59 ++++------- libraries/avatars/src/AvatarData.h | 4 + libraries/avatars/src/HandData.cpp | 141 ++++++++++++++++++------- libraries/avatars/src/HandData.h | 29 ++++- libraries/shared/src/PacketHeaders.cpp | 2 +- 7 files changed, 156 insertions(+), 103 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index eabd9e7ffc..7b74a1b7d8 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -22,9 +22,7 @@ Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), _raveGloveClock(0.0f), - _raveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR), _raveGloveInitialized(false), - _isRaveGloveActive(false), _owningAvatar(owningAvatar), _renderAlpha(1.0), _lookingInMirror(false), diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index beb7b8d516..39845141aa 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -23,22 +23,6 @@ class Avatar; class ProgramObject; -enum RaveGloveEffectsMode -{ - RAVE_GLOVE_EFFECTS_MODE_NULL = -1, - RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR, - RAVE_GLOVE_EFFECTS_MODE_TRAILS, - RAVE_GLOVE_EFFECTS_MODE_FIRE, - RAVE_GLOVE_EFFECTS_MODE_WATER, - RAVE_GLOVE_EFFECTS_MODE_FLASHY, - RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER, - RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER, - RAVE_GLOVE_EFFECTS_MODE_SNAKE, - RAVE_GLOVE_EFFECTS_MODE_PULSE, - RAVE_GLOVE_EFFECTS_MODE_THROB, - NUM_RAVE_GLOVE_EFFECTS_MODES -}; - class Hand : public HandData { public: Hand(Avatar* owningAvatar); @@ -61,13 +45,11 @@ public: void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } void updateRaveGloveParticles(float deltaTime); void updateRaveGloveEmitters(); - void setRaveGloveActive(bool active) { _isRaveGloveActive = active; } void setRaveGloveEffectsMode(QKeyEvent* event); // getters const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;} const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;} - bool isRaveGloveActive() const { return _isRaveGloveActive; } private: // disallow copies of the Hand, copy of owning Avatar is disallowed too @@ -76,10 +58,8 @@ private: ParticleSystem _raveGloveParticleSystem; float _raveGloveClock; - int _raveGloveMode; bool _raveGloveInitialized; int _raveGloveEmitter[NUM_FINGERS]; - bool _isRaveGloveActive; Avatar* _owningAvatar; float _renderAlpha; @@ -93,7 +73,7 @@ private: const std::vector& handNormals); void renderRaveGloveStage(); - void setRaveGloveMode(int mode); + virtual void setRaveGloveMode(int mode); void renderLeapHandSpheres(); void renderLeapHands(); void renderLeapHand(PalmData& hand); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 9c254453e1..c86e712808 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -129,21 +129,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { *destinationBuffer++ = bitItems; // leap hand data - std::vector fingerVectors; - -//printf("about to call _handData->encodeRemoteData(fingerVectors);\n"); - _handData->encodeRemoteData(fingerVectors); - - if (fingerVectors.size() > 255) - fingerVectors.clear(); // safety. We shouldn't ever get over 255, so consider that invalid. - - *destinationBuffer++ = (unsigned char)fingerVectors.size(); - - for (size_t i = 0; i < fingerVectors.size(); ++i) { - destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].x, fingerVectorRadix); - destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].y, fingerVectorRadix); - destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerVectors[i].z, fingerVectorRadix); - } + destinationBuffer += _handData->encodeRemoteData(destinationBuffer); // skeleton joints *destinationBuffer++ = (unsigned char)_joints.size(); @@ -246,34 +232,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // hand state, stored as a semi-nibble in the bitItems _handState = getSemiNibbleAt(bitItems,HAND_STATE_START_BIT); -//printf("about to call leap hand data code in AvatarData::parseData...\n"); - // leap hand data if (sourceBuffer - startPosition < numBytes) { - -//printf("got inside of 'if (sourceBuffer - startPosition < numBytes)'\n"); - - // check passed, bytes match - unsigned int numFingerVectors = *sourceBuffer++; - -//printf("numFingerVectors = %d\n", numFingerVectors); - - - if (numFingerVectors > 0) { - -//printf("ok, we got fingers in AvatarData::parseData\n"); - - std::vector fingerVectors(numFingerVectors); - for (size_t i = 0; i < numFingerVectors; ++i) { - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].x), fingerVectorRadix); - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].y), fingerVectorRadix); - sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerVectors[i].z), fingerVectorRadix); - } - -//printf("about to call _handData->decodeRemoteData(fingerVectors);\n"); - _handData->decodeRemoteData(fingerVectors); - } + sourceBuffer += _handData->decodeRemoteData(sourceBuffer); } // skeleton joints @@ -307,6 +269,23 @@ int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* de return sizeof(int16_t); } +int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix) { + const unsigned char* startPosition = destBuffer; + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.x, radix); + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.y, radix); + destBuffer += packFloatScalarToSignedTwoByteFixed(destBuffer, srcVector.z, radix); + return destBuffer - startPosition; +} + +int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix) { + const unsigned char* startPosition = sourceBuffer; + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.x), radix); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.y), radix); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(destination.z), radix); + return sourceBuffer - startPosition; +} + + int packFloatAngleToTwoByte(unsigned char* buffer, float angle) { const float ANGLE_CONVERSION_RATIO = (std::numeric_limits::max() / 360.0); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 209d822426..0fcfef21da 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -184,4 +184,8 @@ int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy); int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix); int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* destinationPointer, int radix); +// A convenience for sending vec3's as fixed-poimt floats +int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix); +int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix); + #endif /* defined(__hifi__AvatarData__) */ diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 0b91191d92..fb3d437489 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -7,11 +7,20 @@ // #include "HandData.h" +#include "AvatarData.h" + +// Glove flags +#define GLOVE_FLAG_RAVE 0x01 + +// When converting between fixed and float, use this as the radix. +const int fingerVectorRadix = 4; HandData::HandData(AvatarData* owningAvatar) : _basePosition(0.0f, 0.0f, 0.0f), _baseOrientation(0.0f, 0.0f, 0.0f, 1.0f), - _owningAvatarData(owningAvatar) + _owningAvatarData(owningAvatar), + _isRaveGloveActive(false), + _raveGloveMode(RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) { // Start with two palms addNewPalm(); @@ -49,53 +58,113 @@ _owningHandData(owningHandData) setTrailLength(standardTrailLength); } -void HandData::encodeRemoteData(std::vector& fingerVectors) { - fingerVectors.clear(); - - for (size_t i = 0; i < getNumPalms(); ++i) { +int HandData::encodeRemoteData(unsigned char* destinationBuffer) { + const unsigned char* startPosition = destinationBuffer; - PalmData& palm = getPalms()[i]; - if (!palm.isActive()) { - continue; + unsigned char gloveFlags = 0; + if (isRaveGloveActive()) + gloveFlags |= GLOVE_FLAG_RAVE; + + *destinationBuffer++ = gloveFlags; + *destinationBuffer++ = getRaveGloveMode(); + + unsigned int numHands = 0; + for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { + PalmData& palm = getPalms()[handIndex]; + if (palm.isActive()) { + numHands++; } - fingerVectors.push_back(palm.getRawPosition()); - fingerVectors.push_back(palm.getRawNormal()); - for (size_t f = 0; f < palm.getNumFingers(); ++f) { - FingerData& finger = palm.getFingers()[f]; - - if (finger.isActive()) { - fingerVectors.push_back(finger.getTipRawPosition()); - fingerVectors.push_back(finger.getRootRawPosition()); + } + *destinationBuffer++ = numHands; + + for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { + PalmData& palm = getPalms()[handIndex]; + if (palm.isActive()) { + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, palm.getRawPosition(), fingerVectorRadix); + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, palm.getRawNormal(), fingerVectorRadix); + + unsigned int numFingers = 0; + for (unsigned int fingerIndex = 0; fingerIndex < palm.getNumFingers(); ++fingerIndex) { + FingerData& finger = palm.getFingers()[fingerIndex]; + if (finger.isActive()) { + numFingers++; + } } - else { - fingerVectors.push_back(glm::vec3(0,0,0)); - fingerVectors.push_back(glm::vec3(0,0,0)); + *destinationBuffer++ = numFingers; + + for (unsigned int fingerIndex = 0; fingerIndex < palm.getNumFingers(); ++fingerIndex) { + FingerData& finger = palm.getFingers()[fingerIndex]; + if (finger.isActive()) { + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, finger.getTipRawPosition(), fingerVectorRadix); + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, finger.getRootRawPosition(), fingerVectorRadix); + } } } } + // One byte for error checking safety. + size_t checkLength = destinationBuffer - startPosition; + *destinationBuffer++ = (unsigned char)checkLength; + + return destinationBuffer - startPosition; } -void HandData::decodeRemoteData(const std::vector& fingerVectors) { - size_t vectorIndex = 0; - for (size_t i = 0; i < getNumPalms(); ++i) { - PalmData& palm = getPalms()[i]; - // If a palm is active, there will be - // 1 vector for its position - // 1 vector for normal - // 10 vectors for fingers (5 tip/root pairs) - bool palmActive = fingerVectors.size() >= i * 12; - palm.setActive(palmActive); - if (palmActive) { - palm.setRawPosition(fingerVectors[vectorIndex++]); - palm.setRawNormal(fingerVectors[vectorIndex++]); - for (size_t f = 0; f < NUM_FINGERS_PER_HAND; ++f) { - FingerData& finger = palm.getFingers()[f]; +int HandData::decodeRemoteData(unsigned char* sourceBuffer) { + const unsigned char* startPosition = sourceBuffer; + + unsigned char gloveFlags = *sourceBuffer++; + char effectsMode = *sourceBuffer++; + unsigned int numHands = *sourceBuffer++; + + for (unsigned int handIndex = 0; handIndex < numHands; ++handIndex) { + if (handIndex >= getNumPalms()) + addNewPalm(); + PalmData& palm = getPalms()[handIndex]; + + glm::vec3 handPosition; + glm::vec3 handNormal; + sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, handPosition, fingerVectorRadix); + sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, handNormal, fingerVectorRadix); + unsigned int numFingers = *sourceBuffer++; + + palm.setRawPosition(handPosition); + palm.setRawNormal(handNormal); + palm.setActive(true); + + for (unsigned int fingerIndex = 0; fingerIndex < numFingers; ++fingerIndex) { + if (fingerIndex < palm.getNumFingers()) { + FingerData& finger = palm.getFingers()[fingerIndex]; + + glm::vec3 tipPosition; + glm::vec3 rootPosition; + sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, tipPosition, fingerVectorRadix); + sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, rootPosition, fingerVectorRadix); + + finger.setRawTipPosition(tipPosition); + finger.setRawRootPosition(rootPosition); finger.setActive(true); - finger.setRawTipPosition(fingerVectors[vectorIndex++]); - finger.setRawRootPosition(fingerVectors[vectorIndex++]); } } + // Turn off any fingers which weren't used. + for (unsigned int fingerIndex = numFingers; fingerIndex < palm.getNumFingers(); ++fingerIndex) { + FingerData& finger = palm.getFingers()[fingerIndex]; + finger.setActive(false); + } } + // Turn off any hands which weren't used. + for (unsigned int handIndex = numHands; handIndex < getNumPalms(); ++handIndex) { + PalmData& palm = getPalms()[handIndex]; + palm.setActive(false); + } + + setRaveGloveActive((gloveFlags & GLOVE_FLAG_RAVE) != 0); + setRaveGloveMode(effectsMode); + + // One byte for error checking safety. + unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); + unsigned char checkLength = *sourceBuffer++; + assert(checkLength == requiredLength); + + return sourceBuffer - startPosition; } void HandData::setFingerTrailLength(unsigned int length) { diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 1a7a99f2db..f0a546f184 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -25,6 +25,22 @@ const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND; const int LEAPID_INVALID = -1; +enum RaveGloveEffectsMode +{ + RAVE_GLOVE_EFFECTS_MODE_NULL = -1, + RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR, + RAVE_GLOVE_EFFECTS_MODE_TRAILS, + RAVE_GLOVE_EFFECTS_MODE_FIRE, + RAVE_GLOVE_EFFECTS_MODE_WATER, + RAVE_GLOVE_EFFECTS_MODE_FLASHY, + RAVE_GLOVE_EFFECTS_MODE_BOZO_SPARKLER, + RAVE_GLOVE_EFFECTS_MODE_LONG_SPARKLER, + RAVE_GLOVE_EFFECTS_MODE_SNAKE, + RAVE_GLOVE_EFFECTS_MODE_PULSE, + RAVE_GLOVE_EFFECTS_MODE_THROB, + NUM_RAVE_GLOVE_EFFECTS_MODES +}; + class HandData { public: HandData(AvatarData* owningAvatar); @@ -49,15 +65,22 @@ public: void updateFingerTrails(); // Use these for sending and receiving hand data - void encodeRemoteData(std::vector& fingerVectors); - void decodeRemoteData(const std::vector& fingerVectors); - + int encodeRemoteData(unsigned char* destinationBuffer); + int decodeRemoteData(unsigned char* sourceBuffer); + + void setRaveGloveActive(bool active) { _isRaveGloveActive = active; } + virtual void setRaveGloveMode(int effectsMode) { _raveGloveMode = effectsMode; } + bool isRaveGloveActive() const { return _isRaveGloveActive; } + int getRaveGloveMode() { return _raveGloveMode; } + friend class AvatarData; protected: glm::vec3 _basePosition; // Hands are placed relative to this glm::quat _baseOrientation; // Hands are placed relative to this AvatarData* _owningAvatarData; std::vector _palms; + bool _isRaveGloveActive; + int _raveGloveMode; private: // privatize copy ctor and assignment operator so copies of this object cannot be made HandData(const HandData&); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 2e7b95c7f7..a88be677f2 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_HEAD_DATA: - return 2; + return 3; case PACKET_TYPE_AVATAR_FACE_VIDEO: return 1;