From 3f2c6504a60ff304adc4c454907f450e891a1aeb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 12:27:47 -0800 Subject: [PATCH 1/7] fix for avatar scale bug, closes #1506 --- interface/src/Application.cpp | 4 ++-- interface/src/avatar/Avatar.cpp | 4 ++-- libraries/avatars/src/AvatarData.cpp | 8 ++++---- libraries/avatars/src/AvatarData.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..0830f6069f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2128,8 +2128,8 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: Avatar* avatar = *fade; const float SHRINK_RATE = 0.9f; avatar->setNewScale(avatar->getNewScale() * SHRINK_RATE); - const float MINIMUM_SCALE = 0.001f; - if (avatar->getNewScale() < MINIMUM_SCALE) { + + if (avatar->getNewScale() < MIN_AVATAR_SCALE) { delete avatar; _avatarFades.erase(fade--); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3b4793b39..525644b52b 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -439,14 +439,14 @@ void Avatar::goHome() { } void Avatar::increaseSize() { - if ((1.f + SCALING_RATIO) * _newScale < MAX_SCALE) { + if ((1.f + SCALING_RATIO) * _newScale < MAX_AVATAR_SCALE) { _newScale *= (1.f + SCALING_RATIO); qDebug("Changed scale to %f\n", _newScale); } } void Avatar::decreaseSize() { - if (MIN_SCALE < (1.f - SCALING_RATIO) * _newScale) { + if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _newScale) { _newScale *= (1.f - SCALING_RATIO); qDebug("Changed scale to %f\n", _newScale); } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 14115ced47..b81a0601bd 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -297,10 +297,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { } void AvatarData::setNewScale(float newScale) { - if (newScale > MAX_SCALE) { - newScale = MAX_SCALE; - } else if (newScale < MIN_SCALE) { - newScale = MIN_SCALE; + if (newScale > MAX_AVATAR_SCALE) { + newScale = MAX_AVATAR_SCALE; + } else if (newScale < MIN_AVATAR_SCALE) { + newScale = MIN_AVATAR_SCALE; } _newScale = newScale; qDebug() << "Changed scale to " << _newScale << "\n"; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index e7f359aff2..6ee320eae0 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -32,8 +32,8 @@ 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; -static const float MAX_SCALE = 1000.f; -static const float MIN_SCALE = .005f; +static const float MAX_AVATAR_SCALE = 1000.f; +static const float MIN_AVATAR_SCALE = .005f; const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation @@ -83,7 +83,7 @@ public: // Scale float getNewScale() const { return _newScale; } - void setNewScale(float); + void setNewScale(float newScale); // Hand State void setHandState(char s) { _handState = s; } From 2d5df389071c0af3f2714644ff92dfacd31b5765 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 13:51:51 -0800 Subject: [PATCH 2/7] Persist the user orientation as well as the position, show up a couple meters in front of (and facing) target. Closes #1367. --- interface/src/Application.cpp | 3 ++- interface/src/DataServerClient.cpp | 24 +++++++++++++++++------- interface/src/DataServerClient.h | 1 + interface/src/Menu.cpp | 5 +++-- interface/src/avatar/Profile.cpp | 26 ++++++++++++++++++++++++-- interface/src/avatar/Profile.h | 6 ++++++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 958995daae..6e050df72c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1347,8 +1347,9 @@ void Application::timer() { // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); - // give the MyAvatar object position to the Profile so it can propagate to the data-server + // give the MyAvatar object position, orientation to the Profile so it can propagate to the data-server _profile.updatePosition(_myAvatar.getPosition()); + _profile.updateOrientation(_myAvatar.getOrientation()); } static glm::vec3 getFaceVector(BoxFace face) { diff --git a/interface/src/DataServerClient.cpp b/interface/src/DataServerClient.cpp index 33fa59e3e4..56ab92dba3 100644 --- a/interface/src/DataServerClient.cpp +++ b/interface/src/DataServerClient.cpp @@ -175,25 +175,35 @@ void DataServerClient::processSendFromDataServer(unsigned char* packetData, int } } } - } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position - && valueList[i] != " " && valueList[i + 1] != " ") { + } else if (keyList[i] == DataServerKey::Domain && keyList[i + 1] == DataServerKey::Position && + keyList[i + 2] == DataServerKey::Orientation && valueList[i] != " " && + valueList[i + 1] != " " && valueList[i + 2] != " ") { QStringList coordinateItems = valueList[i + 1].split(','); + QStringList orientationItems = valueList[i + 2].split(','); - if (coordinateItems.size() == 3) { + if (coordinateItems.size() == 3 && orientationItems.size() == 3) { // send a node kill request, indicating to other clients that they should play the "disappeared" effect NodeList::getInstance()->sendKillNode(&NODE_TYPE_AVATAR_MIXER, 1); qDebug() << "Changing domain to" << valueList[i].toLocal8Bit().constData() << - "and position to" << valueList[i + 1].toLocal8Bit().constData() << + ", position to" << valueList[i + 1].toLocal8Bit().constData() << + ", and orientation to" << valueList[i + 2].toLocal8Bit().constData() << "to go to" << userString << "\n"; NodeList::getInstance()->setDomainHostname(valueList[i]); - glm::vec3 newPosition(coordinateItems[0].toFloat(), - coordinateItems[1].toFloat(), - coordinateItems[2].toFloat()); + // orient the user to face the target + glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), + orientationItems[1].toFloat(), orientationItems[2].toFloat()))) * + glm::angleAxis(180.0f, 0.0f, 1.0f, 0.0f); + Application::getInstance()->getAvatar()->setOrientation(newOrientation); + + // move the user a couple units away + const float DISTANCE_TO_USER = 2.0f; + glm::vec3 newPosition = glm::vec3(coordinateItems[0].toFloat(), coordinateItems[1].toFloat(), + coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; Application::getInstance()->getAvatar()->setPosition(newPosition); } diff --git a/interface/src/DataServerClient.h b/interface/src/DataServerClient.h index b0ccbe13ee..89ec944eb6 100644 --- a/interface/src/DataServerClient.h +++ b/interface/src/DataServerClient.h @@ -41,6 +41,7 @@ namespace DataServerKey { const QString FaceMeshURL = "mesh"; const QString SkeletonURL = "skeleton"; const QString Position = "position"; + const QString Orientation = "orientation"; const QString UUID = "uuid"; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 545a765dce..c77be1e0a9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -999,8 +999,9 @@ void Menu::goToUser() { int dialogReturn = userDialog.exec(); if (dialogReturn == QDialog::Accepted && !userDialog.textValue().isEmpty()) { // there's a username entered by the user, make a request to the data-server - DataServerClient::getValuesForKeysAndUserString((QStringList() << DataServerKey::Domain << DataServerKey::Position), - userDialog.textValue()); + DataServerClient::getValuesForKeysAndUserString( + QStringList() << DataServerKey::Domain << DataServerKey::Position << DataServerKey::Orientation, + userDialog.textValue()); } sendFakeEnterEvent(); diff --git a/interface/src/avatar/Profile.cpp b/interface/src/avatar/Profile.cpp index 4a185f5788..316ca195c9 100644 --- a/interface/src/avatar/Profile.cpp +++ b/interface/src/avatar/Profile.cpp @@ -18,6 +18,7 @@ Profile::Profile(const QString &username) : _uuid(), _lastDomain(), _lastPosition(0.0, 0.0, 0.0), + _lastOrientationSend(0), _faceModelURL() { if (!_username.isEmpty()) { @@ -69,6 +70,10 @@ void Profile::updateDomain(const QString& domain) { } } +static QByteArray createByteArray(const glm::vec3& vector) { + return QByteArray::number(vector.x) + ',' + QByteArray::number(vector.y) + ',' + QByteArray::number(vector.z); +} + void Profile::updatePosition(const glm::vec3 position) { if (_lastPosition != position) { @@ -90,12 +95,29 @@ void Profile::updatePosition(const glm::vec3 position) { gettimeofday(&lastPositionSend, NULL); // send the changed position to the data-server - QString positionString = QString("%1,%2,%3").arg(position.x).arg(position.y).arg(position.z); - DataServerClient::putValueForKey(DataServerKey::Position, positionString.toLocal8Bit().constData()); + DataServerClient::putValueForKey(DataServerKey::Position, createByteArray(position).constData()); } } } +void Profile::updateOrientation(const glm::quat& orientation) { + glm::vec3 eulerAngles = safeEulerAngles(orientation); + if (_lastOrientation == eulerAngles) { + return; + } + const uint64_t DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS = 5 * 1000 * 1000; + const float DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES = 5.0f; + + uint64_t now = usecTimestampNow(); + if (now - _lastOrientationSend >= DATA_SERVER_ORIENTATION_UPDATE_INTERVAL_USECS && + glm::distance(_lastOrientation, eulerAngles) >= DATA_SERVER_ORIENTATION_CHANGE_THRESHOLD_DEGREES) { + DataServerClient::putValueForKey(DataServerKey::Orientation, createByteArray(eulerAngles).constData()); + + _lastOrientation = eulerAngles; + _lastOrientationSend = now; + } +} + void Profile::saveData(QSettings* settings) { settings->beginGroup("Profile"); diff --git a/interface/src/avatar/Profile.h b/interface/src/avatar/Profile.h index eb3f531819..06f8de94a3 100644 --- a/interface/src/avatar/Profile.h +++ b/interface/src/avatar/Profile.h @@ -9,11 +9,14 @@ #ifndef __hifi__Profile__ #define __hifi__Profile__ +#include + #include #include #include #include +#include class Profile { public: @@ -34,6 +37,7 @@ public: void updateDomain(const QString& domain); void updatePosition(const glm::vec3 position); + void updateOrientation(const glm::quat& orientation); QString getLastDomain() const { return _lastDomain; } const glm::vec3& getLastPosition() const { return _lastPosition; } @@ -45,6 +49,8 @@ private: QUuid _uuid; QString _lastDomain; glm::vec3 _lastPosition; + glm::vec3 _lastOrientation; + uint64_t _lastOrientationSend; QUrl _faceModelURL; QUrl _skeletonModelURL; }; From 42e3bcfe9198500cc3eb503e312b56d42fccacd4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 13 Jan 2014 13:52:41 -0800 Subject: [PATCH 3/7] allow fade scale to get smaller than minimum avatar scale --- interface/src/Application.cpp | 9 ++++++--- interface/src/Menu.cpp | 2 +- interface/src/avatar/Avatar.cpp | 26 +++++++++++++------------- interface/src/avatar/MyAvatar.cpp | 12 ++++++------ libraries/avatars/src/AvatarData.cpp | 20 +++++++++----------- libraries/avatars/src/AvatarData.h | 7 ++++--- 6 files changed, 39 insertions(+), 37 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0830f6069f..5d808ff9d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2127,9 +2127,12 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm:: for (vector::iterator fade = _avatarFades.begin(); fade != _avatarFades.end(); fade++) { Avatar* avatar = *fade; const float SHRINK_RATE = 0.9f; - avatar->setNewScale(avatar->getNewScale() * SHRINK_RATE); - - if (avatar->getNewScale() < MIN_AVATAR_SCALE) { + + avatar->setTargetScale(avatar->getScale() * SHRINK_RATE); + + const float MIN_FADE_SCALE = 0.001; + + if (avatar->getTargetScale() < MIN_FADE_SCALE) { delete avatar; _avatarFades.erase(fade--); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 545a765dce..209bc76472 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -891,7 +891,7 @@ void Menu::editPreferences() { _maxVoxelPacketsPerSecond = maxVoxelsPPS->value(); applicationInstance->getAvatar()->setLeanScale(leanScale->value()); - applicationInstance->getAvatar()->setNewScale(avatarScale->value()); + applicationInstance->getAvatar()->setClampedTargetScale(avatarScale->value()); _audioJitterBufferSamples = audioJitterBufferSamples->value(); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 525644b52b..25365dba7a 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -167,8 +167,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { follow(NULL); } - if (_scale != _newScale) { - setScale(_newScale); + if (_scale != _targetScale) { + setScale(_targetScale); } // copy velocity so we can use it later for acceleration @@ -439,30 +439,30 @@ void Avatar::goHome() { } void Avatar::increaseSize() { - if ((1.f + SCALING_RATIO) * _newScale < MAX_AVATAR_SCALE) { - _newScale *= (1.f + SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); + if ((1.f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { + _targetScale *= (1.f + SCALING_RATIO); + qDebug("Changed scale to %f\n", _targetScale); } } void Avatar::decreaseSize() { - if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _newScale) { - _newScale *= (1.f - SCALING_RATIO); - qDebug("Changed scale to %f\n", _newScale); + if (MIN_AVATAR_SCALE < (1.f - SCALING_RATIO) * _targetScale) { + _targetScale *= (1.f - SCALING_RATIO); + qDebug("Changed scale to %f\n", _targetScale); } } void Avatar::resetSize() { - _newScale = 1.0f; - qDebug("Reseted scale to %f\n", _newScale); + _targetScale = 1.0f; + qDebug("Reseted scale to %f\n", _targetScale); } void Avatar::setScale(const float scale) { _scale = scale; - if (_newScale * (1.f - RESCALING_TOLERANCE) < _scale && - _scale < _newScale * (1.f + RESCALING_TOLERANCE)) { - _scale = _newScale; + if (_targetScale * (1.f - RESCALING_TOLERANCE) < _scale && + _scale < _targetScale * (1.f + RESCALING_TOLERANCE)) { + _scale = _targetScale; } _skeleton.setScale(_scale); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 161ea5b9d8..dabbb7812d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -92,12 +92,12 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } // Ajust, scale, position and lookAt position when following an other avatar - if (_leadingAvatar && _newScale != _leadingAvatar->getScale()) { - _newScale = _leadingAvatar->getScale(); + if (_leadingAvatar && _targetScale != _leadingAvatar->getScale()) { + _targetScale = _leadingAvatar->getScale(); } - if (_scale != _newScale) { - float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _newScale; + if (_scale != _targetScale) { + float scale = (1.f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); Application::getInstance()->getCamera()->setScale(scale); } @@ -513,7 +513,7 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("pupilDilation", _head.getPupilDilation()); settings->setValue("leanScale", _leanScale); - settings->setValue("scale", _newScale); + settings->setValue("scale", _targetScale); settings->endGroup(); } @@ -536,7 +536,7 @@ void MyAvatar::loadData(QSettings* settings) { _leanScale = loadSetting(settings, "leanScale", 0.05f); - _newScale = loadSetting(settings, "scale", 1.0f); + _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); Application::getInstance()->getCamera()->setScale(_scale); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b81a0601bd..f663f26cbf 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -29,7 +29,7 @@ AvatarData::AvatarData(Node* owningNode) : _bodyYaw(-90.0), _bodyPitch(0.0), _bodyRoll(0.0), - _newScale(1.0f), + _targetScale(1.0f), _leaderUUID(), _handState(0), _keyState(NO_KEY_DOWN), @@ -76,7 +76,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll); // Body scale - destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); + destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale); // Follow mode info memcpy(destinationBuffer, _leaderUUID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); @@ -198,7 +198,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll); // Body scale - sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale); + sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _targetScale); // Follow mode info _leaderUUID = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); @@ -296,12 +296,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { return sourceBuffer - startPosition; } -void AvatarData::setNewScale(float newScale) { - if (newScale > MAX_AVATAR_SCALE) { - newScale = MAX_AVATAR_SCALE; - } else if (newScale < MIN_AVATAR_SCALE) { - newScale = MIN_AVATAR_SCALE; - } - _newScale = newScale; - qDebug() << "Changed scale to " << _newScale << "\n"; +void AvatarData::setClampedTargetScale(float targetScale) { + + targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + + _targetScale = targetScale; + qDebug() << "Changed scale to " << _targetScale << "\n"; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6ee320eae0..8b46fd8493 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -82,8 +82,9 @@ public: void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } // Scale - float getNewScale() const { return _newScale; } - void setNewScale(float newScale); + float getTargetScale() const { return _targetScale; } + void setTargetScale(float targetScale) { _targetScale = targetScale; } + void setClampedTargetScale(float targetScale); // Hand State void setHandState(char s) { _handState = s; } @@ -132,7 +133,7 @@ protected: float _bodyRoll; // Body scale - float _newScale; + float _targetScale; // Following mode infos QUuid _leaderUUID; From 9d831a2ab50b8febee6bb8c785152ba09cbaa032 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 14:43:59 -0800 Subject: [PATCH 4/7] Orbit around voxel center, limit hover distance. --- interface/src/Application.cpp | 13 +++++++------ interface/src/Application.h | 2 +- libraries/voxels/src/VoxelTreeElement.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e888d7918..8d758974dd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1121,7 +1121,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; } if (_isHoverVoxel) { - _myAvatar.orbit(glm::vec3(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z) * (float)TREE_SCALE, deltaX, deltaY); + _myAvatar.orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); return; } } @@ -1618,10 +1618,9 @@ void Application::makeVoxel(glm::vec3 position, isDestructive); } -const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) { - return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, - (_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE, - (_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE); +glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel) { + return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.f) * TREE_SCALE, + (mouseVoxel.z + mouseVoxel.s / 2.f) * TREE_SCALE); } const float NUDGE_PRECISION_MIN = 1 / pow(2.0, 12.0); @@ -2245,7 +2244,9 @@ void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, if (!(_voxels.treeIsBusy() || _mousePressed)) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); - _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face); + const float MAX_HOVER_DISTANCE = 100.0f; + _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face) && + glm::distance(getMouseVoxelWorldCoordinates(_hoverVoxel), mouseRayOrigin) < MAX_HOVER_DISTANCE; } if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 92831ff9ce..1da7de0224 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -142,7 +142,7 @@ public: void removeVoxel(glm::vec3 position, float scale); - const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); + glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); QGLWidget* getGLWidget() { return _glWidget; } MyAvatar* getAvatar() { return &_myAvatar; } diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index 1eee7e4a5b..d30007aca1 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -92,4 +92,4 @@ protected: }; -#endif /* defined(__hifi__VoxelTreeElement__) */ \ No newline at end of file +#endif /* defined(__hifi__VoxelTreeElement__) */ From f21436a29e7298468408656ee39b2e4a6d933d07 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 15:02:46 -0800 Subject: [PATCH 5/7] Fix (hopefully) for warning on Windows build. --- interface/src/Application.cpp | 4 +--- libraries/metavoxels/src/MetavoxelData.cpp | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8d758974dd..5a6aec5fe8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2244,9 +2244,7 @@ void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, if (!(_voxels.treeIsBusy() || _mousePressed)) { { PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); - const float MAX_HOVER_DISTANCE = 100.0f; - _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face) && - glm::distance(getMouseVoxelWorldCoordinates(_hoverVoxel), mouseRayOrigin) < MAX_HOVER_DISTANCE; + _isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face); } if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) { diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 849d85960e..c04ee9f297 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -301,8 +301,8 @@ void MetavoxelNode::clearChildren(const AttributePointer& attribute) { } int MetavoxelPath::operator[](int index) const { - return _array.at(index * BITS_PER_ELEMENT) | (_array.at(index * BITS_PER_ELEMENT + 1) << 1) | - (_array.at(index * BITS_PER_ELEMENT + 2) << 2); + return (int)_array.at(index * BITS_PER_ELEMENT) | ((int)_array.at(index * BITS_PER_ELEMENT + 1) << 1) | + ((int)_array.at(index * BITS_PER_ELEMENT + 2) << 2); } MetavoxelPath& MetavoxelPath::operator+=(int element) { From 0694a7d4a5ebcde09793ec4be013361ebf788bfd Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 13 Jan 2014 16:09:36 -0800 Subject: [PATCH 6/7] When we fail to download textures or geometry, retry after steadily increasing delays. Closes #1471. --- interface/src/renderer/GeometryCache.cpp | 32 ++++++++++++++++------ interface/src/renderer/GeometryCache.h | 4 +++ interface/src/renderer/TextureCache.cpp | 35 ++++++++++++++++++------ interface/src/renderer/TextureCache.h | 8 ++++-- 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 1a32a70c71..7ec61a8942 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -251,18 +251,16 @@ QSharedPointer GeometryCache::getGeometry(const QUrl& url) { } NetworkGeometry::NetworkGeometry(const QUrl& url) : + _modelRequest(url), _modelReply(NULL), - _mappingReply(NULL) + _mappingReply(NULL), + _attempts(0) { if (!url.isValid()) { return; } - QNetworkRequest modelRequest(url); - modelRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - _modelReply = Application::getInstance()->getNetworkAccessManager()->get(modelRequest); - - connect(_modelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping())); - connect(_modelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleModelReplyError())); + _modelRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + makeModelRequest(); QUrl mappingURL = url; QString path = url.path(); @@ -312,12 +310,30 @@ glm::vec4 NetworkGeometry::computeAverageColor() const { return (totalTriangles == 0) ? glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) : totalColor / totalTriangles; } +void NetworkGeometry::makeModelRequest() { + _modelReply = Application::getInstance()->getNetworkAccessManager()->get(_modelRequest); + + connect(_modelReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(maybeReadModelWithMapping())); + connect(_modelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleModelReplyError())); +} + void NetworkGeometry::handleModelReplyError() { - qDebug() << _modelReply->errorString() << "\n"; + QDebug debug = qDebug() << _modelReply->errorString(); _modelReply->disconnect(this); _modelReply->deleteLater(); _modelReply = NULL; + + // retry with increasing delays + const int MAX_ATTEMPTS = 8; + const int BASE_DELAY_MS = 1000; + if (++_attempts < MAX_ATTEMPTS) { + QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(makeModelRequest())); + debug << " -- retrying...\n"; + + } else { + debug << "\n"; + } } void NetworkGeometry::handleMappingReplyError() { diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index d880d25855..8a68917ba5 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -10,6 +10,7 @@ #define __interface__GeometryCache__ #include +#include #include #include #include @@ -67,15 +68,18 @@ public: private slots: + void makeModelRequest(); void handleModelReplyError(); void handleMappingReplyError(); void maybeReadModelWithMapping(); private: + QNetworkRequest _modelRequest; QNetworkReply* _modelReply; QNetworkReply* _mappingReply; + int _attempts; FBXGeometry _geometry; QVector _meshes; }; diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index 778fb8fb12..6a7d64da5f 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -252,16 +252,17 @@ Texture::~Texture() { glDeleteTextures(1, &_id); } -NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) : _reply(NULL), _averageColor(1.0f, 1.0f, 1.0f, 1.0f) { +NetworkTexture::NetworkTexture(const QUrl& url, bool normalMap) : + _request(url), + _reply(NULL), + _attempts(0), + _averageColor(1.0f, 1.0f, 1.0f, 1.0f) { + if (!url.isValid()) { return; } - QNetworkRequest request(url); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - _reply = Application::getInstance()->getNetworkAccessManager()->get(request); - - connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); - connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); + _request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + makeRequest(); // default to white/blue glBindTexture(GL_TEXTURE_2D, getID()); @@ -279,6 +280,13 @@ void NetworkTexture::imageLoaded(const QImage& image) { // nothing by default } +void NetworkTexture::makeRequest() { + _reply = Application::getInstance()->getNetworkAccessManager()->get(_request); + + connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64))); + connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError())); +} + void NetworkTexture::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { if (bytesReceived < bytesTotal && !_reply->isFinished()) { return; @@ -314,11 +322,22 @@ void NetworkTexture::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTo } void NetworkTexture::handleReplyError() { - qDebug() << _reply->errorString() << "\n"; + QDebug debug = qDebug() << _reply->errorString(); _reply->disconnect(this); _reply->deleteLater(); _reply = NULL; + + // retry with increasing delays + const int MAX_ATTEMPTS = 8; + const int BASE_DELAY_MS = 1000; + if (++_attempts < MAX_ATTEMPTS) { + QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(makeRequest())); + debug << " -- retrying...\n"; + + } else { + debug << "\n"; + } } DilatableNetworkTexture::DilatableNetworkTexture(const QUrl& url, bool normalMap) : diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 40f2bc5ac3..d3f138254f 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -126,12 +127,15 @@ protected: private slots: + void makeRequest(); void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void handleReplyError(); - + private: - + + QNetworkRequest _request; QNetworkReply* _reply; + int _attempts; glm::vec4 _averageColor; }; From bcf9e04f563c944cd8bb9a1d7e8d2d79e236fb9e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Jan 2014 14:34:00 -0800 Subject: [PATCH 7/7] only output first starve for a PositionalAudioRingBuffer --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 13 +++++++++++-- libraries/audio/src/PositionalAudioRingBuffer.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 7037eb2154..c7084e0d1d 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -20,7 +20,8 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer:: _position(0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f), _willBeAddedToMix(false), - _shouldLoopbackForNode(false) + _shouldLoopbackForNode(false), + _shouldOutputStarveDebug(true) { } @@ -57,11 +58,19 @@ int PositionalAudioRingBuffer::parsePositionalData(unsigned char* sourceBuffer, bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) { - qDebug() << "Starved and do not have minimum samples to start. Buffer held back.\n"; + if (_shouldOutputStarveDebug) { + qDebug() << "Starved and do not have minimum samples to start. Buffer held back.\n"; + _shouldOutputStarveDebug = false; + } + return false; } else if (samplesAvailable() < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { qDebug() << "Do not have number of samples needed for interval. Buffer starved.\n"; _isStarved = true; + + // reset our _shouldOutputStarveDebug to true so the next is printed + _shouldOutputStarveDebug = true; + return false; } else { // good buffer, add this to the mix diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index 189ac34058..55ed627c4d 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -49,6 +49,7 @@ protected: glm::quat _orientation; bool _willBeAddedToMix; bool _shouldLoopbackForNode; + bool _shouldOutputStarveDebug; }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */