From cabd6ccbad23c9d5655ee1050eacc60e4bb68cb4 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 27 Nov 2013 11:47:23 -0800 Subject: [PATCH 1/4] Advertise to others whether we have chat circling enabled, only include people with it enabled when doing the computations. --- interface/src/avatar/MyAvatar.cpp | 7 +++++-- libraries/avatars/src/AvatarData.cpp | 5 +++++ libraries/avatars/src/AvatarData.h | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 65670aa4f3..1257788d60 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1161,17 +1161,20 @@ bool operator<(const SortedAvatar& s1, const SortedAvatar& s2) { } void MyAvatar::updateChatCircle(float deltaTime) { - if (!Menu::getInstance()->isOptionChecked(MenuOption::ChatCircling)) { + if (!(_isChatCirclingEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ChatCircling))) { return; } - // find all members and sort by distance + // find all circle-enabled members and sort by distance QVector sortedAvatars; NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { SortedAvatar sortedAvatar; sortedAvatar.avatar = (Avatar*)node->getLinkedData(); + if (!sortedAvatar.avatar->isChatCirclingEnabled()) { + continue; + } sortedAvatar.distance = glm::distance(_position, sortedAvatar.avatar->getPosition()); sortedAvatars.append(sortedAvatar); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dc5a9c96d3..042deb9d3d 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -120,6 +120,9 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { setSemiNibbleAt(bitItems,HAND_STATE_START_BIT,_handState); // faceshift state if (_headData->_isFaceshiftConnected) { setAtBit(bitItems, IS_FACESHIFT_CONNECTED); } + if (_isChatCirclingEnabled) { + setAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); + } *destinationBuffer++ = bitItems; // If it is connected, pack up the data @@ -248,6 +251,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { _headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); + _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); + // If it is connected, pack up the data if (_headData->_isFaceshiftConnected) { memcpy(&_headData->_leftEyeBlink, sourceBuffer, sizeof(float)); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index b99be1bb09..13c9b1e049 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -30,6 +30,7 @@ const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits const int IS_FACESHIFT_CONNECTED = 4; // 5th bit +const int IS_CHAT_CIRCLING_ENABLED = 5; const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation @@ -93,6 +94,8 @@ public: const std::string& setChatMessage() const { return _chatMessage; } QString getQStringChatMessage() { return QString(_chatMessage.data()); } + bool isChatCirclingEnabled() const { return _isChatCirclingEnabled; } + const QUuid& getLeaderUUID() const { return _leaderUUID; } void setHeadData(HeadData* headData) { _headData = headData; } @@ -124,6 +127,8 @@ protected: // chat message std::string _chatMessage; + bool _isChatCirclingEnabled; + std::vector _joints; HeadData* _headData; From b294b328ddde092bf910d8571ba5ea024554968f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 27 Nov 2013 12:56:31 -0800 Subject: [PATCH 2/4] Only render ball avatars when "avatars as balls" is checked. --- interface/src/Application.cpp | 6 +++--- interface/src/avatar/Avatar.cpp | 22 ++++++++++------------ interface/src/avatar/Avatar.h | 4 ++-- interface/src/avatar/Head.cpp | 16 +++++++++++----- interface/src/avatar/Head.h | 2 +- interface/src/avatar/MyAvatar.cpp | 16 ++++++---------- interface/src/avatar/MyAvatar.h | 4 ++-- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58629df41e..0c0d5d072f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3850,7 +3850,7 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (!avatar->isInitialized()) { avatar->init(); } - avatar->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + avatar->render(false); avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); } @@ -3860,12 +3860,12 @@ void Application::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { // render avatar fades Glower glower; for (vector::iterator fade = _avatarFades.begin(); fade != _avatarFades.end(); fade++) { - (*fade)->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + (*fade)->render(false); } } // Render my own Avatar - _myAvatar.render(forceRenderHead, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)); + _myAvatar.render(forceRenderHead); _myAvatar.setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors)); if (Menu::getInstance()->isOptionChecked(MenuOption::LookAtIndicator) && _lookatTargetAvatar) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 44e1f0aad1..0db3e6e3ee 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -21,6 +21,7 @@ #include "DataServerClient.h" #include "Hand.h" #include "Head.h" +#include "Menu.h" #include "Physics.h" #include "world.h" #include "devices/OculusManager.h" @@ -394,7 +395,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; - if (!_skeletonModel.getHeadPosition(headPosition)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) || !_skeletonModel.getHeadPosition(headPosition)) { headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; } _head.setPosition(headPosition); @@ -439,7 +440,7 @@ static TextRenderer* textRenderer() { return renderer; } -void Avatar::render(bool forceRenderHead, bool renderAvatarBalls) { +void Avatar::render(bool forceRenderHead) { if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { _hand.setRaveLights(RAVE_LIGHTS_AVATAR); @@ -455,7 +456,7 @@ void Avatar::render(bool forceRenderHead, bool renderAvatarBalls) { Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f); // render body - renderBody(forceRenderHead, renderAvatarBalls); + renderBody(forceRenderHead); // render sphere when far away const float MAX_ANGLE = 10.f; @@ -666,7 +667,8 @@ void Avatar::updateArmIKAndConstraints(float deltaTime, AvatarJointID fingerTipJ float distance = glm::length(armVector); // don't let right hand get dragged beyond maximum arm length... - float armLength = _skeletonModel.isActive() ? _skeletonModel.getRightArmLength() : _skeleton.getArmLength(); + float armLength = (_skeletonModel.isActive() && !Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) ? + _skeletonModel.getRightArmLength() : _skeleton.getArmLength(); const float ARM_RETRACTION = 0.75f; float retractedArmLength = armLength * ARM_RETRACTION; if (distance > retractedArmLength) { @@ -713,7 +715,7 @@ float Avatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { return 1.0f; } -void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { +void Avatar::renderBody(bool forceRenderHead) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video @@ -721,7 +723,7 @@ void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { if (alpha > 0.0f) { _head.getVideoFace().render(1.0f); } - } else if (renderAvatarBalls || !(_voxels.getVoxelURL().isValid() || _skeletonModel.isActive())) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { // Render the body as balls and cones glm::vec3 skinColor, darkSkinColor; getSkinColors(skinColor, darkSkinColor); @@ -738,7 +740,7 @@ void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { // Always render other people, and render myself when beyond threshold distance if (b == BODY_BALL_HEAD_BASE) { // the head is rendered as a special if (alpha > 0.0f) { - _head.render(alpha, false); + _head.render(alpha, true); } } else if (alpha > 0.0f) { // Render the body ball sphere @@ -746,10 +748,6 @@ void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { skinColor.g - _bodyBall[b].touchForce * 0.2f, skinColor.b - _bodyBall[b].touchForce * 0.1f); - if (b == BODY_BALL_NECK_BASE && _head.getFaceModel().isActive()) { - continue; // don't render the neck if we have a face model - } - if ((b != BODY_BALL_HEAD_TOP ) && (b != BODY_BALL_HEAD_BASE )) { glPushMatrix(); @@ -793,7 +791,7 @@ void Avatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { void Avatar::getSkinColors(glm::vec3& lighter, glm::vec3& darker) { lighter = glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]); darker = glm::vec3(DARK_SKIN_COLOR[0], DARK_SKIN_COLOR[1], DARK_SKIN_COLOR[2]); - if (_head.getFaceModel().isActive()) { + if (!Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) && _head.getFaceModel().isActive()) { lighter = glm::vec3(_head.getFaceModel().computeAverageColor()); const float SKIN_DARKENING = 0.9f; darker = lighter * SKIN_DARKENING; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index d633871891..cc18ce7f1a 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -141,7 +141,7 @@ public: void init(); void simulate(float deltaTime, Transmitter* transmitter); void follow(Avatar* leadingAvatar); - void render(bool forceRenderHead, bool renderAvatarBalls); + void render(bool forceRenderHead); //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); } @@ -256,7 +256,7 @@ private: // private methods... glm::vec3 calculateAverageEyePosition() { return _head.calculateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat) float getBallRenderAlpha(int ball, bool forceRenderHead) const; - void renderBody(bool forceRenderHead, bool renderAvatarBalls); + void renderBody(bool forceRenderHead); void initializeBodyBalls(); void resetBodyBalls(); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 0390506716..5dd59ed159 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -250,7 +250,9 @@ void Head::simulate(float deltaTime, bool isMine) { calculateGeometry(); // the blend face may have custom eye meshes - _faceModel.getEyePositions(_leftEyePosition, _rightEyePosition); + if (!Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { + _faceModel.getEyePositions(_leftEyePosition, _rightEyePosition); + } } void Head::calculateGeometry() { @@ -295,10 +297,11 @@ void Head::calculateGeometry() { + up * _scale * NOSE_UPTURN; } -void Head::render(float alpha, bool isMine) { +void Head::render(float alpha, bool renderAvatarBalls) { _renderAlpha = alpha; - if (!(_videoFace.render(alpha) || _faceModel.render(alpha))) { + bool lookatVectorsVisible = _renderLookatVectors; + if (renderAvatarBalls) { glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); @@ -309,9 +312,12 @@ void Head::render(float alpha, bool isMine) { renderMouth(); renderNose(); renderEyeBrows(); + + } else if (!_videoFace.render(alpha)) { + lookatVectorsVisible &= _faceModel.render(alpha); } - - if (_renderLookatVectors) { + + if (lookatVectorsVisible) { renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); } } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 323375985d..47e998059d 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -44,7 +44,7 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine); - void render(float alpha, bool isMine); + void render(float alpha, bool renderAvatarBalls); void renderMohawk(); void setScale(float scale); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1257788d60..baedb1bc6b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -325,7 +325,7 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { _skeletonModel.simulate(deltaTime); _head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); glm::vec3 headPosition; - if (!_skeletonModel.getHeadPosition(headPosition)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls) || !_skeletonModel.getHeadPosition(headPosition)) { headPosition = _bodyBall[BODY_BALL_HEAD_BASE].position; } _head.setPosition(headPosition); @@ -497,7 +497,7 @@ static TextRenderer* textRenderer() { return renderer; } -void MyAvatar::render(bool forceRenderHead, bool renderAvatarBalls) { +void MyAvatar::render(bool forceRenderHead) { if (Application::getInstance()->getAvatar()->getHand().isRaveGloveActive()) { _hand.setRaveLights(RAVE_LIGHTS_AVATAR); @@ -507,7 +507,7 @@ void MyAvatar::render(bool forceRenderHead, bool renderAvatarBalls) { renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), _scale * 0.1f, 0.2f); // render body - renderBody(forceRenderHead, renderAvatarBalls); + renderBody(forceRenderHead); // if this is my avatar, then render my interactions with the other avatar _avatarTouch.render(Application::getInstance()->getCamera()->getPosition()); @@ -648,7 +648,7 @@ float MyAvatar::getBallRenderAlpha(int ball, bool forceRenderHead) const { (distanceToCamera - DO_NOT_RENDER_INSIDE) / (RENDER_OPAQUE_OUTSIDE - DO_NOT_RENDER_INSIDE), 0.f, 1.f); } -void MyAvatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { +void MyAvatar::renderBody(bool forceRenderHead) { if (_head.getVideoFace().isFullFrame()) { // Render the full-frame video @@ -656,7 +656,7 @@ void MyAvatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { if (alpha > 0.0f) { _head.getVideoFace().render(1.0f); } - } else if (renderAvatarBalls || !(_voxels.getVoxelURL().isValid() || _skeletonModel.isActive())) { + } else if (Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls)) { // Render the body as balls and cones glm::vec3 skinColor, darkSkinColor; getSkinColors(skinColor, darkSkinColor); @@ -690,10 +690,6 @@ void MyAvatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { alpha); } - if (b == BODY_BALL_NECK_BASE && _head.getFaceModel().isActive()) { - continue; // don't render the neck if we have a face model - } - if ((b != BODY_BALL_HEAD_TOP ) && (b != BODY_BALL_HEAD_BASE )) { glPushMatrix(); @@ -729,7 +725,7 @@ void MyAvatar::renderBody(bool forceRenderHead, bool renderAvatarBalls) { } float alpha = getBallRenderAlpha(BODY_BALL_HEAD_BASE, forceRenderHead); if (alpha > 0.0f) { - _head.render(alpha, true); + _head.render(alpha, false); } } _hand.render(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2d90a32108..790f76b233 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -20,7 +20,7 @@ public: void reset(); void simulate(float deltaTime, Transmitter* transmitter); void updateFromGyrosAndOrWebcam(bool turnWithHead); - void render(bool forceRenderHead, bool renderAvatarBalls); + void render(bool forceRenderHead); void renderScreenTint(ScreenTintLayer layer); // setters @@ -82,7 +82,7 @@ private: // private methods float getBallRenderAlpha(int ball, bool forceRenderHead) const; - void renderBody(bool forceRenderHead, bool renderAvatarBalls); + void renderBody(bool forceRenderHead); void updateThrust(float deltaTime, Transmitter * transmitter); void updateHandMovementAndTouching(float deltaTime, bool enableHandMovement); void updateAvatarCollisions(float deltaTime); From d8259f67f0940339397a5198893d9dcda9ee0f49 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 27 Nov 2013 13:09:52 -0800 Subject: [PATCH 3/4] Re-request skeleton/face URLs on login. --- interface/src/avatar/Profile.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 69411e2eff..4a185f5788 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -23,6 +23,8 @@ Profile::Profile(const QString &username) : if (!_username.isEmpty()) { // we've been given a new username, ask the data-server for profile DataServerClient::getClientValueForKey(DataServerKey::UUID); + DataServerClient::getClientValueForKey(DataServerKey::FaceMeshURL); + DataServerClient::getClientValueForKey(DataServerKey::SkeletonURL); // send our current domain server to the data-server updateDomain(NodeList::getInstance()->getDomainHostname()); From ac714773d3f99eb6cb9f73200009fe1a09cc1bd5 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 27 Nov 2013 13:13:36 -0800 Subject: [PATCH 4/4] Initialize chat circling flag. --- libraries/avatars/src/AvatarData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 042deb9d3d..0a90f4db96 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -33,6 +33,7 @@ AvatarData::AvatarData(Node* owningNode) : _leaderUUID(), _handState(0), _keyState(NO_KEY_DOWN), + _isChatCirclingEnabled(false), _headData(NULL), _handData(NULL) {