From 1c797405daa20ab4eb6edf374ad39df2fd99cf92 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 28 Jun 2013 07:57:02 -0700 Subject: [PATCH 1/2] Hand rework in preparation for adding send/receive hand data - Added Hand.cpp, Hand.h, HandData.cpp, HandData.h, roughly matching the equivalent Head files - Cleaned up Avatar by moving hand work into Hand files - Added fixed-point data packing, for use in sending hand offsets --- interface/src/Application.cpp | 2 +- interface/src/Avatar.cpp | 68 +++----------------- interface/src/Avatar.h | 12 +--- interface/src/Hand.cpp | 94 ++++++++++++++++++++++++++++ interface/src/Hand.h | 69 ++++++++++++++++++++ interface/src/Head.h | 1 + libraries/avatars/src/AvatarData.cpp | 27 +++++++- libraries/avatars/src/AvatarData.h | 7 +++ libraries/avatars/src/HandData.cpp | 15 +++++ libraries/avatars/src/HandData.h | 36 +++++++++++ 10 files changed, 258 insertions(+), 73 deletions(-) create mode 100755 interface/src/Hand.cpp create mode 100755 interface/src/Hand.h mode change 100644 => 100755 libraries/avatars/src/AvatarData.cpp mode change 100644 => 100755 libraries/avatars/src/AvatarData.h create mode 100755 libraries/avatars/src/HandData.cpp create mode 100755 libraries/avatars/src/HandData.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1d2fb990e5..776fbfc9bb 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1674,7 +1674,7 @@ void Application::update(float deltaTime) { // Leap finger-sensing device LeapManager::nextFrame(); - _myAvatar.setLeapFingers(LeapManager::getFingerPositions()); + _myAvatar.getHand().setLeapFingers(LeapManager::getFingerPositions()); // Read serial port interface devices if (_serialHeadSensor.isActive()) { diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 98b3ad06a1..98a5c1ea2a 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -13,6 +13,7 @@ #include "world.h" #include "Application.h" #include "Avatar.h" +#include "Hand.h" #include "Head.h" #include "Log.h" #include "ui/TextRenderer.h" @@ -64,6 +65,7 @@ Avatar::Avatar(Agent* owningAgent) : AvatarData(owningAgent), _initialized(false), _head(this), + _hand(this), _ballSpringsInitialized(false), _TEST_bigSphereRadius(0.5f), _TEST_bigSpherePosition(5.0f, _TEST_bigSphereRadius, 5.0f), @@ -96,6 +98,7 @@ Avatar::Avatar(Agent* owningAgent) : { // give the pointer to our head to inherited _headData variable from AvatarData _headData = &_head; + _handData = &_hand; for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = false; @@ -104,7 +107,6 @@ Avatar::Avatar(Agent* owningAgent) : _skeleton.initialize(); initializeBodyBalls(); - initializeLeapBalls(); _height = _skeleton.getHeight() + _bodyBall[ BODY_BALL_LEFT_HEEL ].radius + _bodyBall[ BODY_BALL_HEAD_BASE ].radius; @@ -264,35 +266,22 @@ void Avatar::initializeBodyBalls() { */ } -void Avatar::initializeLeapBalls() { - - _numLeapBalls = 0; - - for (int b = 0; b < MAX_AVATAR_LEAP_BALLS; b++) { - _leapBall[b].parentJoint = AVATAR_JOINT_NULL; - _leapBall[b].parentOffset = glm::vec3(0.0, 0.0, 0.0); - _leapBall[b].position = glm::vec3(0.0, 0.0, 0.0); - _leapBall[b].velocity = glm::vec3(0.0, 0.0, 0.0); - _leapBall[b].radius = 0.01; - _leapBall[b].touchForce = 0.0; - _leapBall[b].isCollidable = true; - _leapBall[b].jointTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - } -} - Avatar::~Avatar() { _headData = NULL; + _handData = NULL; delete _balls; } void Avatar::init() { _head.init(); + _hand.init(); _voxels.init(); _initialized = true; } void Avatar::reset() { _head.reset(); + _hand.reset(); } // Update avatar head rotation with sensor data @@ -543,9 +532,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // update body balls updateBodyBalls(deltaTime); - // update leap balls - updateLeapBalls(deltaTime); - // test for avatar collision response with the big sphere if (usingBigSphereCollisionTest) { updateCollisionWithSphere(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime); @@ -1167,23 +1153,6 @@ void Avatar::updateBodyBalls(float deltaTime) { _bodyBall[BODY_BALL_HEAD_TOP].rotation * _skeleton.joint[BODY_BALL_HEAD_TOP].bindPosePosition; } -void Avatar::setLeapFingers(const std::vector& fingerPositions) { - _numLeapBalls = fingerPositions.size(); // just to test - - float unitScale = 0.001; // convert mm to meters - glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it - - for (int b = 0; b < _numLeapBalls; b++) { - glm::vec3 pos = unitScale * fingerPositions[b] + offset; - _leapBall[b].rotation = _head.getOrientation(); - _leapBall[b].position = _bodyBall[BODY_BALL_HEAD_BASE].position + - _head.getOrientation() * pos; - } -} - -void Avatar::updateLeapBalls(float deltaTime) { -} - void Avatar::updateArmIKAndConstraints(float deltaTime) { // determine the arm vector @@ -1306,30 +1275,7 @@ void Avatar::renderBody(bool lookingInMirror, bool renderAvatarBalls) { } } } - // Draw the leap balls - for (int b = 0; b < _numLeapBalls; b++) { - float alpha = 1.0f; - - if (alpha > 0.0f) { - // Render the body ball sphere - if (_owningAgent || true) { - glColor3f(SKIN_COLOR[0] + _leapBall[b].touchForce * 0.3f, - SKIN_COLOR[1] - _leapBall[b].touchForce * 0.2f, - SKIN_COLOR[2] - _leapBall[b].touchForce * 0.1f); - } else { - glColor4f(SKIN_COLOR[0] + _leapBall[b].touchForce * 0.3f, - SKIN_COLOR[1] - _leapBall[b].touchForce * 0.2f, - SKIN_COLOR[2] - _leapBall[b].touchForce * 0.1f, - alpha); - } - glColor4f(0.0, 0.4, 0.0, 1.0); // Just to test - - glPushMatrix(); - glTranslatef(_leapBall[b].position.x, _leapBall[b].position.y, _leapBall[b].position.z); - glutSolidSphere(_leapBall[b].radius, 20.0f, 20.0f); - glPopMatrix(); - } - } + _hand.render(lookingInMirror); } else { // Render the body's voxels float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, lookingInMirror); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index e8cc2f5029..1cdda74fbe 100755 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -18,6 +18,7 @@ #include "InterfaceConfig.h" #include "SerialInterface.h" #include "Balls.h" +#include "Hand.h" #include "Head.h" #include "Skeleton.h" #include "Transmitter.h" @@ -56,8 +57,6 @@ enum AvatarBodyBallID NUM_AVATAR_BODY_BALLS }; -#define MAX_AVATAR_LEAP_BALLS 10 - enum DriveKeys { FWD = 0, @@ -105,7 +104,6 @@ public: void setGravity (glm::vec3 gravity); void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction); void setOrientation (const glm::quat& orientation); - void setLeapFingers (const std::vector& fingerPositions); //getters bool isInitialized () const { return _initialized;} @@ -115,8 +113,6 @@ public: bool getIsNearInteractingOther () const { return _avatarTouch.getAbleToReachOtherAvatar();} const glm::vec3& getHeadJointPosition () const { return _skeleton.joint[ AVATAR_JOINT_HEAD_BASE ].position;} const glm::vec3& getBallPosition (AvatarJointID j) const { return _bodyBall[j].position;} - int getNumLeapBalls () const { return _numLeapBalls;} - const glm::vec3& getLeapBallPosition (int which) const { return _leapBall[which].position;} glm::vec3 getBodyRightDirection () const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection () const { return getOrientation() * IDENTITY_UP; } glm::vec3 getBodyFrontDirection () const { return getOrientation() * IDENTITY_FRONT; } @@ -131,6 +127,7 @@ public: float getAbsoluteHeadYaw () const; float getAbsoluteHeadPitch () const; Head& getHead () {return _head; } + Hand& getHand () {return _hand; } glm::quat getOrientation () const; glm::quat getWorldAlignedOrientation() const; @@ -180,6 +177,7 @@ private: bool _initialized; Head _head; + Hand _hand; Skeleton _skeleton; bool _ballSpringsInitialized; float _TEST_bigSphereRadius; @@ -190,8 +188,6 @@ private: float _bodyRollDelta; glm::vec3 _movedHandOffset; AvatarBall _bodyBall[ NUM_AVATAR_BODY_BALLS ]; - AvatarBall _leapBall[ MAX_AVATAR_LEAP_BALLS ]; - int _numLeapBalls; AvatarMode _mode; glm::vec3 _handHoldingPosition; glm::vec3 _velocity; @@ -226,10 +222,8 @@ private: float getBallRenderAlpha(int ball, bool lookingInMirror) const; void renderBody(bool lookingInMirror, bool renderAvatarBalls); void initializeBodyBalls(); - void initializeLeapBalls(); void resetBodyBalls(); void updateBodyBalls( float deltaTime ); - void updateLeapBalls( float deltaTime ); void calculateBoneLengths(); void readSensors(); void updateHandMovementAndTouching(float deltaTime); diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp new file mode 100755 index 0000000000..30219c27c9 --- /dev/null +++ b/interface/src/Hand.cpp @@ -0,0 +1,94 @@ +// +// Hand.cpp +// interface +// +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include + +#include + +#include "Application.h" +#include "Avatar.h" +#include "Hand.h" +#include "Util.h" +#include "renderer/ProgramObject.h" + +using namespace std; + +Hand::Hand(Avatar* owningAvatar) : + HandData((AvatarData*)owningAvatar), + _owningAvatar(owningAvatar), + _renderAlpha(1.0), + _lookingInMirror(false), + _ballColor(0.0f, 0.4f, 0.0f) +{ +} + +void Hand::init() { + _numLeapBalls = 0; + for (int b = 0; b < MAX_AVATAR_LEAP_BALLS; b++) { + _leapBall[b].position = glm::vec3(0.0, 0.0, 0.0); + _leapBall[b].velocity = glm::vec3(0.0, 0.0, 0.0); + _leapBall[b].radius = 0.01; + _leapBall[b].touchForce = 0.0; + _leapBall[b].isCollidable = true; + } +} + +void Hand::reset() { +} + +void Hand::simulate(float deltaTime, bool isMine) { +} + +void Hand::calculateGeometry() { +} + + +void Hand::render(bool lookingInMirror) { + + _renderAlpha = 1.0; + _lookingInMirror = lookingInMirror; + + calculateGeometry(); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_RESCALE_NORMAL); + + renderHandSpheres(); +} + +void Hand::renderHandSpheres() { + glPushMatrix(); + // Draw the leap balls + for (int b = 0; b < _numLeapBalls; b++) { + float alpha = 1.0f; + + if (alpha > 0.0f) { + glColor4f(_ballColor.r, _ballColor.g, _ballColor.b, alpha); // Just to test + + glPushMatrix(); + glTranslatef(_leapBall[b].position.x, _leapBall[b].position.y, _leapBall[b].position.z); + glutSolidSphere(_leapBall[b].radius, 20.0f, 20.0f); + glPopMatrix(); + } + } + glPopMatrix(); +} + +void Hand::setLeapFingers(const std::vector& fingerPositions) { + _numLeapBalls = fingerPositions.size(); // just to test + + float unitScale = 0.001; // convert mm to meters + glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it + + Head& head = _owningAvatar->getHead(); + for (int b = 0; b < _numLeapBalls; b++) { + glm::vec3 pos = unitScale * fingerPositions[b] + offset; + _leapBall[b].rotation = head.getOrientation(); + _leapBall[b].position = head.getPosition() + head.getOrientation() * pos; + } +} + + diff --git a/interface/src/Hand.h b/interface/src/Hand.h new file mode 100755 index 0000000000..180ad00a7b --- /dev/null +++ b/interface/src/Hand.h @@ -0,0 +1,69 @@ +// +// Hand.h +// interface +// +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef hifi_Hand_h +#define hifi_Hand_h + +#include +#include +#include "Balls.h" +#include "world.h" +#include "InterfaceConfig.h" +#include "SerialInterface.h" +#include + +#define MAX_AVATAR_LEAP_BALLS 10 + +class Avatar; +class ProgramObject; + +class Hand : public HandData { +public: + Hand(Avatar* owningAvatar); + + struct HandBall + { + glm::vec3 position; // the actual dynamic position of the ball at any given time + glm::quat rotation; // the rotation of the ball + glm::vec3 velocity; // the velocity of the ball + float radius; // the radius of the ball + bool isCollidable; // whether or not the ball responds to collisions + float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball + }; + + void init(); + void reset(); + void simulate(float deltaTime, bool isMine); + void render(bool lookingInMirror); + + void setFingerPositions(std::vector fingerPositions) { _fingerPositions = fingerPositions; } + void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } + void setLeapFingers (const std::vector& fingerPositions); + + // getters + int getNumLeapBalls () const { return _numLeapBalls;} + const glm::vec3& getLeapBallPosition (int which) const { return _leapBall[which].position;} + +private: + // disallow copies of the Hand, copy of owning Avatar is disallowed too + Hand(const Hand&); + Hand& operator= (const Hand&); + + Avatar* _owningAvatar; + float _renderAlpha; + bool _lookingInMirror; + std::vector _fingerPositions; + glm::vec3 _ballColor; + int _numLeapBalls; + HandBall _leapBall[ MAX_AVATAR_LEAP_BALLS ]; + + // private methods + void renderHandSpheres(); + void calculateGeometry(); +}; + +#endif diff --git a/interface/src/Head.h b/interface/src/Head.h index 2cc5c9df00..85976d33d8 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -51,6 +51,7 @@ public: glm::quat getOrientation() const; glm::quat getCameraOrientation (float pitchYawScale) const; + glm::vec3 getPosition() const { return _position; } glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getUpDirection () const { return getOrientation() * IDENTITY_UP; } glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp old mode 100644 new mode 100755 index 8fb9fa05d1..dba7217d28 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -36,13 +36,15 @@ AvatarData::AvatarData(Agent* owningAgent) : _wantColor(true), _wantDelta(false), _wantOcclusionCulling(false), - _headData(NULL) + _headData(NULL), + _handData(NULL) { } AvatarData::~AvatarData() { delete _headData; + delete _handData; } int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { @@ -56,6 +58,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { if (!_headData) { _headData = new HeadData(this); } + // lazily allocate memory for HeadData in case we're not an Avatar instance + if (!_handData) { + _handData = new HandData(this); + } // Body world position memcpy(destinationBuffer, &_position, sizeof(float) * 3); @@ -128,7 +134,12 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { if (!_headData) { _headData = new HeadData(this); } - + + // lazily allocate memory for HandData in case we're not an Avatar instance + if (!_handData) { + _handData = new HandData(this); + } + // increment to push past the packet header sourceBuffer += sizeof(PACKET_HEADER_HEAD_DATA); @@ -214,6 +225,18 @@ glm::vec3 AvatarData::calculateCameraDirection() const { } +// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc +int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix) { + int16_t outVal = (int16_t)(scalar * (float)(1 << radix)); + memcpy(buffer, &outVal, sizeof(uint16_t)); + return sizeof(uint16_t); +} + +int unpackFloatScalarFromSignedTwoByteFixed(uint16_t* byteFixedPointer, float* destinationPointer, int radix) { + *destinationPointer = *byteFixedPointer / (float)(1 << radix); + return sizeof(uint16_t); +} + 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 old mode 100644 new mode 100755 index 4a94db133b..c8a926fe89 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -17,6 +17,7 @@ #include #include "HeadData.h" +#include "HandData.h" const int WANT_RESIN_AT_BIT = 0; const int WANT_COLOR_AT_BIT = 1; @@ -97,6 +98,7 @@ public: void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } void setHeadData(HeadData* headData) { _headData = headData; } + void setHandData(HandData* handData) { _handData = handData; } protected: glm::vec3 _position; @@ -131,6 +133,7 @@ protected: bool _wantOcclusionCulling; HeadData* _headData; + HandData* _handData; private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); @@ -164,4 +167,8 @@ int unpackClipValueFromTwoByte(unsigned char* buffer, float& clipValue); int packFloatToByte(unsigned char* buffer, float value, float scaleBy); int unpackFloatFromByte(unsigned char* buffer, float& value, float scaleBy); +// Allows sending of fixed-point numbers: radix 1 makes 15.1 number, radix 8 makes 8.8 number, etc +int packFloatScalarToSignedTwoByteFixed(unsigned char* buffer, float scalar, int radix); +int unpackFloatScalarFromSignedTwoByteFixed(uint16_t* byteFixedPointer, float* destinationPointer, int radix); + #endif /* defined(__hifi__AvatarData__) */ diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp new file mode 100755 index 0000000000..986d030a3c --- /dev/null +++ b/libraries/avatars/src/HandData.cpp @@ -0,0 +1,15 @@ +// +// HandData.cpp +// hifi +// +// Created by Stephen Birarda on 5/20/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include "HandData.h" + +HandData::HandData(AvatarData* owningAvatar) : + _owningAvatarData(owningAvatar) +{ + +} diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h new file mode 100755 index 0000000000..d31bc8bf1a --- /dev/null +++ b/libraries/avatars/src/HandData.h @@ -0,0 +1,36 @@ +// +// HandData.h +// hifi +// +// Created by Eric Johnston on 6/26/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__HandData__ +#define __hifi__HandData__ + +#include +#include + +#include + +class AvatarData; + +class HandData { +public: + HandData(AvatarData* owningAvatar); + + const std::vector& getFingerPositions() const { return _fingerPositions; } + void setFingerPositions(const std::vector& fingerPositions) { _fingerPositions = fingerPositions; } + + friend class AvatarData; +protected: + std::vector _fingerPositions; + AvatarData* _owningAvatarData; +private: + // privatize copy ctor and assignment operator so copies of this object cannot be made + HandData(const HandData&); + HandData& operator= (const HandData&); +}; + +#endif /* defined(__hifi__HandData__) */ From 0ff3554dd85eb9c9b4e5a726cd2b897c8fcc8a07 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 28 Jun 2013 11:34:20 -0700 Subject: [PATCH 2/2] Networked Leap fingers - Simplified finger updates and storage - added pack and unpack for the fingers - not yet tested between multiple machines, but *should* be harmless and backward-packet-compatible --- interface/src/Hand.cpp | 30 +++++++++++++++++----------- interface/src/Hand.h | 6 +++--- libraries/avatars/src/AvatarData.cpp | 27 +++++++++++++++++++++++++ libraries/avatars/src/HandData.h | 2 ++ 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 30219c27c9..5a44546d7b 100755 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -21,7 +21,9 @@ Hand::Hand(Avatar* owningAvatar) : _owningAvatar(owningAvatar), _renderAlpha(1.0), _lookingInMirror(false), - _ballColor(0.0f, 0.4f, 0.0f) + _ballColor(0.0, 0.4, 0.0), + _position(0.0, 0.4, 0.0), + _orientation(0.0, 0.0, 0.0, 1.0) { } @@ -43,6 +45,20 @@ void Hand::simulate(float deltaTime, bool isMine) { } void Hand::calculateGeometry() { + glm::vec3 offset(0.1, -0.1, -0.15); // place the hand in front of the face where we can see it + + Head& head = _owningAvatar->getHead(); + _position = head.getPosition() + head.getOrientation() * offset; + _orientation = head.getOrientation(); + + _numLeapBalls = _fingerPositions.size(); + + float unitScale = 0.001; // convert mm to meters + for (int b = 0; b < _numLeapBalls; b++) { + glm::vec3 pos = unitScale * _fingerPositions[b] + offset; + _leapBall[b].rotation = _orientation; + _leapBall[b].position = _position + _orientation * pos; + } } @@ -78,17 +94,7 @@ void Hand::renderHandSpheres() { } void Hand::setLeapFingers(const std::vector& fingerPositions) { - _numLeapBalls = fingerPositions.size(); // just to test - - float unitScale = 0.001; // convert mm to meters - glm::vec3 offset(0.2, -0.2, -0.3); // place the hand in front of the face where we can see it - - Head& head = _owningAvatar->getHead(); - for (int b = 0; b < _numLeapBalls; b++) { - glm::vec3 pos = unitScale * fingerPositions[b] + offset; - _leapBall[b].rotation = head.getOrientation(); - _leapBall[b].position = head.getPosition() + head.getOrientation() * pos; - } + _fingerPositions = fingerPositions; } diff --git a/interface/src/Hand.h b/interface/src/Hand.h index 180ad00a7b..49eed1f817 100755 --- a/interface/src/Hand.h +++ b/interface/src/Hand.h @@ -10,13 +10,13 @@ #include #include +#include #include "Balls.h" #include "world.h" #include "InterfaceConfig.h" #include "SerialInterface.h" #include -#define MAX_AVATAR_LEAP_BALLS 10 class Avatar; class ProgramObject; @@ -40,7 +40,6 @@ public: void simulate(float deltaTime, bool isMine); void render(bool lookingInMirror); - void setFingerPositions(std::vector fingerPositions) { _fingerPositions = fingerPositions; } void setBallColor (glm::vec3 ballColor ) { _ballColor = ballColor; } void setLeapFingers (const std::vector& fingerPositions); @@ -56,8 +55,9 @@ private: Avatar* _owningAvatar; float _renderAlpha; bool _lookingInMirror; - std::vector _fingerPositions; glm::vec3 _ballColor; + glm::vec3 _position; + glm::quat _orientation; int _numLeapBalls; HandBall _leapBall[ MAX_AVATAR_LEAP_BALLS ]; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dba7217d28..c8e53b6652 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -124,6 +124,16 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { setSemiNibbleAt(bitItems,HAND_STATE_START_BIT,_handState); *destinationBuffer++ = bitItems; + // leap hand data + const std::vector& fingerPositions = _handData->getFingerPositions(); + *destinationBuffer++ = (unsigned char)fingerPositions.size(); + for (size_t i = 0; i < fingerPositions.size(); ++i) + { + destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].x, 4); + destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].y, 4); + destinationBuffer += packFloatScalarToSignedTwoByteFixed(destinationBuffer, fingerPositions[i].z, 4); + } + return destinationBuffer - bufferStart; } @@ -216,6 +226,23 @@ 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); + // leap hand data + if (sourceBuffer - startPosition < numBytes) // safety check + { + std::vector fingerPositions = _handData->getFingerPositions(); + unsigned int numFingers = *sourceBuffer++; + if (numFingers > MAX_AVATAR_LEAP_BALLS) // safety check + numFingers = 0; + fingerPositions.resize(numFingers); + for (size_t i = 0; i < numFingers; ++i) + { + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((uint16_t*) sourceBuffer, &(fingerPositions[i].x), 4); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((uint16_t*) sourceBuffer, &(fingerPositions[i].y), 4); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((uint16_t*) sourceBuffer, &(fingerPositions[i].z), 4); + } + _handData->setFingerPositions(fingerPositions); + } + return sourceBuffer - startPosition; } diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index d31bc8bf1a..86c582a07f 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -14,6 +14,8 @@ #include +#define MAX_AVATAR_LEAP_BALLS 10 + class AvatarData; class HandData {