From 03de2f3ea7db92e948035d2b87bb66ec8c86b897 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 5 Aug 2013 11:41:42 -0700 Subject: [PATCH 1/4] Render a green plane with fog, per Grayson's request. --- interface/src/Application.cpp | 17 ++++++ interface/src/renderer/GeometryCache.cpp | 70 +++++++++++++++++++++++- interface/src/renderer/GeometryCache.h | 6 +- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6087a4493e..5399c274e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2893,6 +2893,23 @@ void Application::displaySide(Camera& whichCamera) { //draw a grid ground plane.... if (_renderGroundPlaneOn->isChecked()) { + // draw grass plane with fog + glEnable(GL_FOG); + const float FOG_COLOR[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glFogfv(GL_FOG_COLOR, FOG_COLOR); + glFogi(GL_FOG_MODE, GL_EXP2); + glFogf(GL_FOG_DENSITY, 0.025f); + glPushMatrix(); + const float GRASS_PLANE_SIZE = 256.0f; + glTranslatef(-GRASS_PLANE_SIZE * 0.5f, -0.01f, GRASS_PLANE_SIZE * 0.5f); + glScalef(GRASS_PLANE_SIZE, 1.0f, GRASS_PLANE_SIZE); + glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + glColor3ub(70, 134, 74); + const int GRASS_DIVISIONS = 40; + _geometryCache.renderSquare(GRASS_DIVISIONS, GRASS_DIVISIONS); + glPopMatrix(); + glDisable(GL_FOG); + renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude()); } // Draw voxels diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 971f18706e..8331a5deb9 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -18,7 +18,7 @@ GeometryCache::~GeometryCache() { } void GeometryCache::renderHemisphere(int slices, int stacks) { - VerticesIndices& vbo = _hemisphereVBOs[SlicesStacks(slices, stacks)]; + VerticesIndices& vbo = _hemisphereVBOs[IntPair(slices, stacks)]; int vertices = slices * (stacks - 1) + 1; int indices = slices * 2 * 3 * (stacks - 2) + slices * 3; if (vbo.first == 0) { @@ -95,3 +95,71 @@ void GeometryCache::renderHemisphere(int slices, int stacks) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + +void GeometryCache::renderSquare(int xDivisions, int yDivisions) { + VerticesIndices& vbo = _squareVBOs[IntPair(xDivisions, yDivisions)]; + int xVertices = xDivisions + 1; + int yVertices = yDivisions + 1; + int vertices = xVertices * yVertices; + int indices = 2 * 3 * xDivisions * yDivisions; + if (vbo.first == 0) { + GLfloat* vertexData = new GLfloat[vertices * 3]; + GLfloat* vertex = vertexData; + for (int i = 0; i <= yDivisions; i++) { + float y = (float)i / yDivisions; + + for (int j = 0; j <= xDivisions; j++) { + *(vertex++) = (float)j / xDivisions; + *(vertex++) = y; + *(vertex++) = 0.0f; + } + } + + glGenBuffers(1, &vbo.first); + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat); + glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); + delete[] vertexData; + + GLushort* indexData = new GLushort[indices]; + GLushort* index = indexData; + for (int i = 0; i < yDivisions; i++) { + GLushort bottom = i * xVertices; + GLushort top = bottom + xVertices; + for (int j = 0; j < xDivisions; j++) { + int next = j + 1; + + *(index++) = bottom + j; + *(index++) = top + next; + *(index++) = top + j; + + *(index++) = bottom + j; + *(index++) = bottom + next; + *(index++) = top + next; + } + } + + glGenBuffers(1, &vbo.second); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + const int BYTES_PER_INDEX = sizeof(GLushort); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); + delete[] indexData; + + } else { + glBindBuffer(GL_ARRAY_BUFFER, vbo.first); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second); + } + glEnableClientState(GL_VERTEX_ARRAY); + + // all vertices have the same normal + glNormal3f(0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, 0, 0); + + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index 0c5ccea06f..bfce642554 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -19,13 +19,15 @@ public: ~GeometryCache(); void renderHemisphere(int slices, int stacks); + void renderSquare(int xDivisions, int yDivisions); private: - typedef QPair SlicesStacks; + typedef QPair IntPair; typedef QPair VerticesIndices; - QHash _hemisphereVBOs; + QHash _hemisphereVBOs; + QHash _squareVBOs; }; #endif /* defined(__interface__GeometryCache__) */ From 2722cfa5acbfd1d4670667f5bc6393900060bdec Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 5 Aug 2013 11:58:09 -0700 Subject: [PATCH 2/4] Fix for GCC warning. #import? --- libraries/avatars/src/Agent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/avatars/src/Agent.cpp b/libraries/avatars/src/Agent.cpp index f027bc1f55..156499430d 100644 --- a/libraries/avatars/src/Agent.cpp +++ b/libraries/avatars/src/Agent.cpp @@ -6,8 +6,8 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#import -#import +#include +#include #include @@ -85,4 +85,4 @@ void Agent::run(QUrl scriptURL) { } } -} \ No newline at end of file +} From 25537f78a1a35fc246b2da9e82f6cd61229c5223 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 5 Aug 2013 12:18:59 -0700 Subject: [PATCH 3/4] reset the song mix menu item after clip is done --- interface/src/Application.cpp | 12 ++++++++++-- interface/src/Application.h | 4 ++-- interface/src/Audio.cpp | 6 ++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a3bd6c4718..d638ae2b0a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,13 +2128,21 @@ void Application::toggleMixedSong() { QByteArray filenameArray = filename.toLocal8Bit(); _audio.importSongToMixWithMicrophone(filenameArray.data()); - _rawAudioMicrophoneMix->setText("Stop Mixing Song"); + resetSongMixMenuItem(); } else { _audio.stopMixingSongWithMicrophone(); - _rawAudioMicrophoneMix->setText("Mix RAW Song"); + resetSongMixMenuItem(); } } +void Application::resetSongMixMenuItem() { + if (_audio.getSongFileBytes() == 0) { + _rawAudioMicrophoneMix->setText("Mix RAW Song"); + } else { + _rawAudioMicrophoneMix->setText("Stop Mixing Song"); + } + +} void Application::updateFrustumRenderModeAction() { switch (_frustumDrawingMode) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 4745196bf4..1e84de91e8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -105,12 +105,12 @@ public: QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; } GeometryCache* getGeometryCache() { return &_geometryCache; } + + void resetSongMixMenuItem(); public slots: - void sendAvatarFaceVideoMessage(int frameCount, const QByteArray& data); - private slots: void timer(); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index f5a6479985..3e011f5e05 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -154,7 +154,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o currentPacketPtr += sizeof(headOrientation); // check if we have a song to add to our audio - if (_songFileBytes > 0 && _songFileStream->tellg() <= _songFileBytes) { + if (_songFileBytes > 0 && _songFileStream->tellg() != -1) { // iterate over BUFFER_LENGTH_SAMPLES_PER_CHANNEL from the song file and add that to our audio for (int i = 0; i < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { int16_t songSample = 0; @@ -180,6 +180,9 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o // reset the _songFileBytes back to zero _songFileBytes = 0; + + // call Application stopMixingSong method to fix menu item + Application::getInstance()->resetSongMixMenuItem(); } // copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet @@ -501,7 +504,6 @@ void Audio::importSongToMixWithMicrophone(const char* filename) { } void Audio::stopMixingSongWithMicrophone() { - qDebug("Stop mixing called!"); _songFileBytes = 0; } From a3a5c3d6d49f5dfcc28c88f3402cb48cd94e3379 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Mon, 5 Aug 2013 13:25:05 -0700 Subject: [PATCH 4/4] 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;