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__) */