From 02d57699916c60fe3aa816b192c170bd2cb1592e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 9 Apr 2019 12:57:03 -0700 Subject: [PATCH 01/16] Better head vs camera checks for avatar head cauterization * cameraInsideHead() check now uses detailed avatar collision when possible. * head is now more constantly hidden in first person camera mode * getEyeModelPositions() uses a better estimate when avatar eye joints are missing. * moved findPointKDopDisplacement from Rig.cpp into AnimUtil.cpp * added isPlayingOverrideAnimation() method to Rig class --- interface/src/avatar/MyAvatar.cpp | 29 +++++++- libraries/animation/src/AnimUtil.cpp | 69 +++++++++++++++++++ libraries/animation/src/AnimUtil.h | 6 ++ libraries/animation/src/Rig.cpp | 68 ------------------ libraries/animation/src/Rig.h | 5 +- .../src/avatars-renderer/SkeletonModel.cpp | 29 ++------ libraries/shared/src/AvatarConstants.h | 1 + 7 files changed, 112 insertions(+), 95 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 568b492b46..dcd768f2ae 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3180,17 +3180,40 @@ int MyAvatar::sendAvatarDataPacket(bool sendAll) { return bytesSent; } -const float RENDER_HEAD_CUTOFF_DISTANCE = 0.47f; - bool MyAvatar::cameraInsideHead(const glm::vec3& cameraPosition) const { + if (!_skeletonModel) { + return false; + } + + // transform cameraPosition into rig coordinates + AnimPose rigToWorld = AnimPose(getWorldOrientation() * Quaternions::Y_180, getWorldPosition()); + AnimPose worldToRig = rigToWorld.inverse(); + glm::vec3 rigCameraPosition = worldToRig * cameraPosition; + + // use head k-dop shape to determine if camera is inside head. + const Rig& rig = _skeletonModel->getRig(); + int headJointIndex = rig.indexOfJoint("Head"); + if (headJointIndex >= 0) { + const HFMModel& hfmModel = _skeletonModel->getHFMModel(); + AnimPose headPose; + if (rig.getAbsoluteJointPoseInRigFrame(headJointIndex, headPose)) { + glm::vec3 displacement; + const HFMJointShapeInfo& headShapeInfo = hfmModel.joints[headJointIndex].shapeInfo; + return findPointKDopDisplacement(rigCameraPosition, headPose, headShapeInfo, displacement); + } + } + + // fall back to simple distance check. + const float RENDER_HEAD_CUTOFF_DISTANCE = 0.47f; return glm::length(cameraPosition - getHeadPosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getModelScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE; bool firstPerson = qApp->getCamera().getMode() == CAMERA_MODE_FIRST_PERSON; + bool overrideAnim = _skeletonModel ? _skeletonModel->getRig().isPlayingOverrideAnimation() : false; bool insideHead = cameraInsideHead(renderArgs->getViewFrustum().getPosition()); - return !defaultMode || !firstPerson || !insideHead; + return !defaultMode || (!firstPerson && !insideHead) || (overrideAnim && !insideHead); } void MyAvatar::setHasScriptedBlendshapes(bool hasScriptedBlendshapes) { diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index c23e228556..5fca2b4f88 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -142,3 +142,72 @@ glm::quat computeBodyFacingFromHead(const glm::quat& headRot, const glm::vec3& u return glmExtractRotation(bodyMat); } + + +const float INV_SQRT_3 = 1.0f / sqrtf(3.0f); +const int DOP14_COUNT = 14; +const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { + Vectors::UNIT_X, + -Vectors::UNIT_X, + Vectors::UNIT_Y, + -Vectors::UNIT_Y, + Vectors::UNIT_Z, + -Vectors::UNIT_Z, + glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3), + -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) +}; + +// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose. +// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward +// such that it lies on the surface of the kdop. +bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) { + + // transform point into local space of jointShape. + glm::vec3 localPoint = shapePose.inverse().xformPoint(point); + + // Only works for 14-dop shape infos. + if (shapeInfo.dots.size() != DOP14_COUNT) { + return false; + } + + glm::vec3 minDisplacement(FLT_MAX); + float minDisplacementLen = FLT_MAX; + glm::vec3 p = localPoint - shapeInfo.avgPoint; + float pLen = glm::length(p); + if (pLen > 0.0f) { + int slabCount = 0; + for (int i = 0; i < DOP14_COUNT; i++) { + float dot = glm::dot(p, DOP14_NORMALS[i]); + if (dot > 0.0f && dot < shapeInfo.dots[i]) { + slabCount++; + float distToPlane = pLen * (shapeInfo.dots[i] / dot); + float displacementLen = distToPlane - pLen; + + // keep track of the smallest displacement + if (displacementLen < minDisplacementLen) { + minDisplacementLen = displacementLen; + minDisplacement = (p / pLen) * displacementLen; + } + } + } + if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { + // we are within the k-dop so push the point along the minimum displacement found + displacementOut = shapePose.xformVectorFast(minDisplacement); + return true; + } else { + // point is outside of kdop + return false; + } + } else { + // point is directly on top of shapeInfo.avgPoint. + // push the point out along the x axis. + displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); + return true; + } +} diff --git a/libraries/animation/src/AnimUtil.h b/libraries/animation/src/AnimUtil.h index cf190e8dbf..c2925e31e8 100644 --- a/libraries/animation/src/AnimUtil.h +++ b/libraries/animation/src/AnimUtil.h @@ -128,4 +128,10 @@ protected: bool _snapshotValid { false }; }; + +// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose. +// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward +// such that it lies on the surface of the kdop. +bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut); + #endif diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 43e94d23e8..6e434eb68d 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1521,74 +1521,6 @@ void Rig::updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headPos } } -const float INV_SQRT_3 = 1.0f / sqrtf(3.0f); -const int DOP14_COUNT = 14; -const glm::vec3 DOP14_NORMALS[DOP14_COUNT] = { - Vectors::UNIT_X, - -Vectors::UNIT_X, - Vectors::UNIT_Y, - -Vectors::UNIT_Y, - Vectors::UNIT_Z, - -Vectors::UNIT_Z, - glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), - -glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), - glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), - -glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), - glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), - -glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), - glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3), - -glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) -}; - -// returns true if the given point lies inside of the k-dop, specified by shapeInfo & shapePose. -// if the given point does lie within the k-dop, it also returns the amount of displacement necessary to push that point outward -// such that it lies on the surface of the kdop. -static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& shapePose, const HFMJointShapeInfo& shapeInfo, glm::vec3& displacementOut) { - - // transform point into local space of jointShape. - glm::vec3 localPoint = shapePose.inverse().xformPoint(point); - - // Only works for 14-dop shape infos. - if (shapeInfo.dots.size() != DOP14_COUNT) { - return false; - } - - glm::vec3 minDisplacement(FLT_MAX); - float minDisplacementLen = FLT_MAX; - glm::vec3 p = localPoint - shapeInfo.avgPoint; - float pLen = glm::length(p); - if (pLen > 0.0f) { - int slabCount = 0; - for (int i = 0; i < DOP14_COUNT; i++) { - float dot = glm::dot(p, DOP14_NORMALS[i]); - if (dot > 0.0f && dot < shapeInfo.dots[i]) { - slabCount++; - float distToPlane = pLen * (shapeInfo.dots[i] / dot); - float displacementLen = distToPlane - pLen; - - // keep track of the smallest displacement - if (displacementLen < minDisplacementLen) { - minDisplacementLen = displacementLen; - minDisplacement = (p / pLen) * displacementLen; - } - } - } - if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { - // we are within the k-dop so push the point along the minimum displacement found - displacementOut = shapePose.xformVectorFast(minDisplacement); - return true; - } else { - // point is outside of kdop - return false; - } - } else { - // point is directly on top of shapeInfo.avgPoint. - // push the point out along the x axis. - displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); - return true; - } -} - glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const HFMJointShapeInfo& hipsShapeInfo, const HFMJointShapeInfo& spineShapeInfo, const HFMJointShapeInfo& spine1ShapeInfo, const HFMJointShapeInfo& spine2ShapeInfo) const { glm::vec3 position = handPosition; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index df13ff5c2b..1a511b2487 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -116,8 +116,9 @@ public: void destroyAnimGraph(); void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); + bool isPlayingOverrideAnimation() const { return _userAnimState.clipNodeEnum != UserAnimState::None; }; void restoreAnimation(); - + void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void triggerNetworkRole(const QString& role); void restoreNetworkAnimation(); @@ -333,7 +334,7 @@ protected: RigRole _state { RigRole::Idle }; RigRole _desiredState { RigRole::Idle }; float _desiredStateAge { 0.0f }; - + struct NetworkAnimState { enum ClipNodeEnum { None = 0, diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index fbcf36a8c9..6276b049a1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -270,28 +270,13 @@ bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& getJointPosition(_rig.indexOfJoint("RightEye"), secondEyePosition)) { return true; } - // no eye joints; try to estimate based on head/neck joints - glm::vec3 neckPosition, headPosition; - if (getJointPosition(_rig.indexOfJoint("Neck"), neckPosition) && - getJointPosition(_rig.indexOfJoint("Head"), headPosition)) { - const float EYE_PROPORTION = 0.6f; - glm::vec3 baseEyePosition = glm::mix(neckPosition, headPosition, EYE_PROPORTION); - glm::quat headRotation; - getJointRotation(_rig.indexOfJoint("Head"), headRotation); - const float EYES_FORWARD = 0.25f; - const float EYE_SEPARATION = 0.1f; - float headHeight = glm::distance(neckPosition, headPosition); - firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight; - secondEyePosition = baseEyePosition + headRotation * glm::vec3(-EYE_SEPARATION, 0.0f, EYES_FORWARD) * headHeight; - return true; - } else if (getJointPosition(_rig.indexOfJoint("Head"), headPosition)) { - glm::vec3 baseEyePosition = headPosition; - glm::quat headRotation; - getJointRotation(_rig.indexOfJoint("Head"), headRotation); - const float EYES_FORWARD_HEAD_ONLY = 0.30f; - const float EYE_SEPARATION = 0.1f; - firstEyePosition = baseEyePosition + headRotation * glm::vec3(EYE_SEPARATION, 0.0f, EYES_FORWARD_HEAD_ONLY); - secondEyePosition = baseEyePosition + headRotation * glm::vec3(-EYE_SEPARATION, 0.0f, EYES_FORWARD_HEAD_ONLY); + + glm::vec3 headPosition; + if (getJointPosition(_rig.indexOfJoint("Head"), headPosition)) { + float heightRatio = _rig.getUnscaledEyeHeight() / DEFAULT_AVATAR_EYE_HEIGHT; + glm::vec3 ipdOffset = glm::vec3(DEFAULT_AVATAR_IPD / 2.0f, 0.0f, 0.0f); + firstEyePosition = headPosition + heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET + ipdOffset); + secondEyePosition = headPosition + heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET - ipdOffset); return true; } return false; diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 5166cb7a0b..9338249e99 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -42,6 +42,7 @@ const float DEFAULT_AVATAR_HIPS_MASS = 40.0f; const float DEFAULT_AVATAR_HEAD_MASS = 20.0f; const float DEFAULT_AVATAR_LEFTHAND_MASS = 2.0f; const float DEFAULT_AVATAR_RIGHTHAND_MASS = 2.0f; +const float DEFAULT_AVATAR_IPD = 0.064f; // Used when avatar is missing joints... (avatar space) const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; From ca7cfc0240c3a3a0ae32e8463987e9ac833fcf2b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Apr 2019 09:44:56 -0700 Subject: [PATCH 02/16] only call onMove on lastMouseEvent change --- scripts/system/libraries/entitySelectionTool.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index d2f3ece5f1..3fdc1d6652 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1347,12 +1347,16 @@ SelectionDisplay = (function() { }; that.updateLastMouseEvent = function(event) { - if (activeTool && lastMouseEvent !== null) { + if (activeTool && lastMouseEvent !== null) { + var change = lastMouseEvent.isShifted !== event.isShifted || lastMouseEvent.isMeta !== event.isMeta || + lastMouseEvent.isControl !== event.isControl || lastMouseEvent.isAlt !== event.isAlt; lastMouseEvent.isShifted = event.isShifted; lastMouseEvent.isMeta = event.isMeta; lastMouseEvent.isControl = event.isControl; - lastMouseEvent.isAlt = event.isAlt; - activeTool.onMove(lastMouseEvent); + lastMouseEvent.isAlt = event.isAlt; + if (change) { + activeTool.onMove(lastMouseEvent); + } } }; From 39cf3c3d83fd09f88160a32cc1fa4c13578a3095 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Wed, 3 Apr 2019 12:27:32 -0700 Subject: [PATCH 03/16] Fix TextureBaker failures and heap corruption in MaterialBaker --- libraries/baking/src/MaterialBaker.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/baking/src/MaterialBaker.cpp b/libraries/baking/src/MaterialBaker.cpp index 9fcd7d0354..7fc2573d7b 100644 --- a/libraries/baking/src/MaterialBaker.cpp +++ b/libraries/baking/src/MaterialBaker.cpp @@ -144,7 +144,12 @@ void MaterialBaker::processMaterial() { connect(textureBaker.data(), &TextureBaker::finished, this, &MaterialBaker::handleFinishedTextureBaker); _textureBakers.insert(textureKey, textureBaker); textureBaker->moveToThread(_getNextOvenWorkerThreadOperator ? _getNextOvenWorkerThreadOperator() : thread()); - QMetaObject::invokeMethod(textureBaker.data(), "bake"); + // By default, Qt will invoke this bake immediately if the TextureBaker is on the same worker thread as this MaterialBaker. + // We don't want that, because threads may be waiting for work while this thread is stuck processing a TextureBaker. + // On top of that, _textureBakers isn't fully populated. + // So, use Qt::QueuedConnection. + // TODO: Better thread utilization at the top level, not just the MaterialBaker level + QMetaObject::invokeMethod(textureBaker.data(), "bake", Qt::QueuedConnection); } _materialsNeedingRewrite.insert(textureKey, networkMaterial.second); } else { From 7aeb4bca87d3625f46f2babd829e903187cba6c4 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 11 Apr 2019 14:05:15 -0700 Subject: [PATCH 04/16] Include head rotation in getEyeModelPositions --- .../src/avatars-renderer/SkeletonModel.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 6276b049a1..295a0e9f52 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -271,12 +271,18 @@ bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& return true; } + int headJointIndex = _rig.indexOfJoint("Head"); glm::vec3 headPosition; - if (getJointPosition(_rig.indexOfJoint("Head"), headPosition)) { + if (getJointPosition(headJointIndex, headPosition)) { + + // get head joint rotation. + glm::quat headRotation; + getJointRotation(headJointIndex, headRotation); + float heightRatio = _rig.getUnscaledEyeHeight() / DEFAULT_AVATAR_EYE_HEIGHT; glm::vec3 ipdOffset = glm::vec3(DEFAULT_AVATAR_IPD / 2.0f, 0.0f, 0.0f); - firstEyePosition = headPosition + heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET + ipdOffset); - secondEyePosition = headPosition + heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET - ipdOffset); + firstEyePosition = headPosition + headRotation * heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET + ipdOffset); + secondEyePosition = headPosition + headRotation * heightRatio * (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET - ipdOffset); return true; } return false; From a5e94eea755e2347a9b033a1e12994a7ce4d8a88 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 11 Apr 2019 17:36:09 -0700 Subject: [PATCH 05/16] Increase ping interval for unconnected Nodes --- libraries/networking/src/NetworkPeer.h | 2 +- libraries/networking/src/NodeList.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/networking/src/NetworkPeer.h b/libraries/networking/src/NetworkPeer.h index b75d2f8b86..43fbc753eb 100644 --- a/libraries/networking/src/NetworkPeer.h +++ b/libraries/networking/src/NetworkPeer.h @@ -26,7 +26,7 @@ const quint16 ICE_SERVER_DEFAULT_PORT = 7337; const int ICE_HEARBEAT_INTERVAL_MSECS = 2 * 1000; const int MAX_ICE_CONNECTION_ATTEMPTS = 5; -const int UDP_PUNCH_PING_INTERVAL_MS = 25; +const int UDP_PUNCH_PING_INTERVAL_MS = 250; class NetworkPeer : public QObject { Q_OBJECT diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 0021a594bc..0a4c63d712 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -752,11 +752,11 @@ void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SendAudioPing); } - // every second we're trying to ping this node and we're not getting anywhere - debug that out - const int NUM_DEBUG_CONNECTION_ATTEMPTS = 1000 / (UDP_PUNCH_PING_INTERVAL_MS); + // every two seconds we're trying to ping this node and we're not getting anywhere - debug that out + const int NUM_DEBUG_CONNECTION_ATTEMPTS = 2000 / (UDP_PUNCH_PING_INTERVAL_MS); if (node->getConnectionAttempts() > 0 && node->getConnectionAttempts() % NUM_DEBUG_CONNECTION_ATTEMPTS == 0) { - qCDebug(networking) << "No response to UDP hole punch pings for node" << node->getUUID() << "in last second."; + qCDebug(networking) << "No response to UDP hole punch pings for node" << node->getUUID() << "in last 2 s."; } auto nodeID = node->getUUID(); From 7180d8b99b68bbf983f79438770b6aacb0acaf77 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 11 Apr 2019 17:56:27 -0700 Subject: [PATCH 06/16] Clear delayed Node-adds upon restart --- libraries/networking/src/LimitedNodeList.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 18a180ad79..82f3459c15 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -588,6 +588,8 @@ void LimitedNodeList::eraseAllNodes() { foreach(const SharedNodePointer& killedNode, killedNodes) { handleNodeKill(killedNode); } + + _delayedNodeAdds.clear(); } void LimitedNodeList::reset() { @@ -755,7 +757,7 @@ void LimitedNodeList::delayNodeAdd(NewNodeInfo info) { } void LimitedNodeList::removeDelayedAdd(QUuid nodeUUID) { - auto it = std::find_if(_delayedNodeAdds.begin(), _delayedNodeAdds.end(), [&](auto info) { + auto it = std::find_if(_delayedNodeAdds.begin(), _delayedNodeAdds.end(), [&](const auto& info) { return info.uuid == nodeUUID; }); if (it != _delayedNodeAdds.end()) { @@ -764,7 +766,7 @@ void LimitedNodeList::removeDelayedAdd(QUuid nodeUUID) { } bool LimitedNodeList::isDelayedNode(QUuid nodeUUID) { - auto it = std::find_if(_delayedNodeAdds.begin(), _delayedNodeAdds.end(), [&](auto info) { + auto it = std::find_if(_delayedNodeAdds.begin(), _delayedNodeAdds.end(), [&](const auto& info) { return info.uuid == nodeUUID; }); return it != _delayedNodeAdds.end(); From 87deb348a8fce5ddb31fdcbaccff6163ac569d37 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 12 Apr 2019 14:07:06 -0700 Subject: [PATCH 07/16] Adjust run speed constants. --- libraries/shared/src/AvatarConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 5166cb7a0b..5b65390620 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -102,6 +102,6 @@ static const float MAX_AVATAR_HEIGHT = 1000.0f * DEFAULT_AVATAR_HEIGHT; // meter static const float MIN_AVATAR_HEIGHT = 0.005f * DEFAULT_AVATAR_HEIGHT; // meters static const float MIN_AVATAR_RADIUS = 0.5f * MIN_AVATAR_HEIGHT; static const float AVATAR_WALK_SPEED_SCALAR = 1.0f; -static const float AVATAR_SPRINT_SPEED_SCALAR = 2.0f; +static const float AVATAR_SPRINT_SPEED_SCALAR = 3.0f; #endif // hifi_AvatarConstants_h From d342d93ec9191b5ba7d232e7f989be845dc6c6cc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 Apr 2019 14:47:48 -0700 Subject: [PATCH 08/16] fix material targets when re-opening properties to same entity --- scripts/system/html/js/entityProperties.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 78a6e26ff0..021a27152a 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3503,6 +3503,7 @@ function loaded() { deleteJSONMaterialEditor(); } } + lastEntityID = null; resetProperties(); showGroupsForType("None"); From 3bf8fb5d954d3562e5d57e8935478acd58adaa56 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Fri, 12 Apr 2019 16:40:41 -0700 Subject: [PATCH 09/16] Case21707 - Wallet doesn't work if user has unicode characters in windows username --- interface/src/commerce/Wallet.cpp | 134 ++++++++++++++++-------------- 1 file changed, 72 insertions(+), 62 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 37f28960e5..e00cd44fa9 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -96,28 +96,32 @@ int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { } } -EC_KEY* readKeys(const char* filename) { - FILE* fp; - EC_KEY *key = NULL; - if ((fp = fopen(filename, "rt"))) { +EC_KEY* readKeys(QString filename) { + QFile file(filename); + EC_KEY* key = NULL; + if (file.open(QFile::ReadOnly)) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) { + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + if ((key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL))) { // now read private key qCDebug(commerce) << "read public key"; - if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) { + if (key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL)) { qCDebug(commerce) << "read private key"; - fclose(fp); - return key; + BIO_free(bufio); + file.close(); + } else { + qCDebug(commerce) << "failed to read private key"; } - qCDebug(commerce) << "failed to read private key"; } else { qCDebug(commerce) << "failed to read public key"; } - fclose(fp); + BIO_free(bufio); + file.close(); } else { qCDebug(commerce) << "failed to open key file" << filename; } @@ -131,8 +135,7 @@ bool Wallet::writeBackupInstructions() { QFile outputFile(outputFilename); bool retval = false; - if (getKeyFilePath().isEmpty()) - { + if (getKeyFilePath().isEmpty()) { return false; } @@ -152,7 +155,7 @@ bool Wallet::writeBackupInstructions() { outputFile.write(text.toUtf8()); // Close the output file - outputFile.close(); + outputFile.close(); retval = true; qCDebug(commerce) << "wrote html file successfully"; @@ -165,28 +168,35 @@ bool Wallet::writeBackupInstructions() { return retval; } -bool writeKeys(const char* filename, EC_KEY* keys) { - FILE* fp; +bool writeKeys(QString filename, EC_KEY* keys) { + BIO* bio = BIO_new(BIO_s_mem()); bool retval = false; - if ((fp = fopen(filename, "wt"))) { - if (!PEM_write_EC_PUBKEY(fp, keys)) { - fclose(fp); - qCCritical(commerce) << "failed to write public key"; - return retval; - } + if (!PEM_write_bio_EC_PUBKEY(bio, keys)) { + BIO_free(bio); + qCCritical(commerce) << "failed to write public key"; + return retval; + } - if (!PEM_write_ECPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { - fclose(fp); - qCCritical(commerce) << "failed to write private key"; - return retval; - } + if (!PEM_write_bio_ECPrivateKey(bio, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { + BIO_free(bio); + qCCritical(commerce) << "failed to write private key"; + return retval; + } + QFile file(filename); + if (!file.open(QIODevice::WriteOnly)) { + const char* bio_data; + long bio_size = BIO_get_mem_data(bio, &bio_data); + + QByteArray keyBytes(bio_data, bio_size); + file.write(keyBytes); retval = true; qCDebug(commerce) << "wrote keys successfully"; - fclose(fp); + file.close(); } else { qCDebug(commerce) << "failed to open key file" << filename; } + BIO_free(bio); return retval; } @@ -215,7 +225,6 @@ QByteArray Wallet::getWallet() { } QPair generateECKeypair() { - EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); QPair retval{}; @@ -235,7 +244,6 @@ QPair generateECKeypair() { if (publicKeyLength <= 0 || privateKeyLength <= 0) { qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error(); - // cleanup the EC struct EC_KEY_free(keyPair); @@ -251,8 +259,7 @@ QPair generateECKeypair() { return retval; } - - if (!writeKeys(keyFilePath().toStdString().c_str(), keyPair)) { + if (!writeKeys(keyFilePath(), keyPair)) { qCDebug(commerce) << "couldn't save keys!"; return retval; } @@ -273,13 +280,18 @@ QPair generateECKeypair() { // END copied code (which will soon change) // the public key can just go into a byte array -QByteArray readPublicKey(const char* filename) { - FILE* fp; - EC_KEY* key = NULL; - if ((fp = fopen(filename, "r"))) { +QByteArray readPublicKey(QString filename) { + QByteArray retval; + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) { + + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + + EC_KEY* key = PEM_read_bio_EC_PUBKEY(bufio, NULL, NULL, NULL); + if (key) { // file read successfully unsigned char* publicKeyDER = NULL; int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER); @@ -287,32 +299,35 @@ QByteArray readPublicKey(const char* filename) { // cleanup EC_KEY_free(key); - fclose(fp); qCDebug(commerce) << "parsed public key file successfully"; - QByteArray retval((char*)publicKeyDER, publicKeyLength); + retval.setRawData((char*)publicKeyDER, publicKeyLength); OPENSSL_free(publicKeyDER); - return retval; } else { qCDebug(commerce) << "couldn't parse" << filename; } - fclose(fp); + BIO_free(bufio); + file.close(); } else { qCDebug(commerce) << "couldn't open" << filename; } - return QByteArray(); + return retval; } // the private key should be read/copied into heap memory. For now, we need the EC_KEY struct // so I'll return that. -EC_KEY* readPrivateKey(const char* filename) { - FILE* fp; +EC_KEY* readPrivateKey(QString filename) { + QFile file(filename); EC_KEY* key = NULL; - if ((fp = fopen(filename, "r"))) { + if (file.open(QIODevice::ReadOnly)) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) { + + QByteArray pemKeyBytes = file.readAll(); + BIO* bufio = BIO_new_mem_buf((void*)pemKeyBytes.constData(), pemKeyBytes.length()); + + if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { qCDebug(commerce) << "parsed private key file successfully"; } else { @@ -320,7 +335,8 @@ EC_KEY* readPrivateKey(const char* filename) { // if the passphrase is wrong, then let's not cache it DependencyManager::get()->setPassphrase(""); } - fclose(fp); + BIO_free(bufio); + file.close(); } else { qCDebug(commerce) << "couldn't open" << filename; } @@ -361,7 +377,7 @@ Wallet::Wallet() { if (wallet->getKeyFilePath().isEmpty() || !wallet->getSecurityImage()) { if (keyStatus == "preexisting") { status = (uint) WalletStatus::WALLET_STATUS_PREEXISTING; - } else{ + } else { status = (uint) WalletStatus::WALLET_STATUS_NOT_SET_UP; } } else if (!wallet->walletIsAuthenticatedWithPassphrase()) { @@ -569,10 +585,10 @@ bool Wallet::walletIsAuthenticatedWithPassphrase() { } // otherwise, we have a passphrase but no keys, so we have to check - auto publicKey = readPublicKey(keyFilePath().toStdString().c_str()); + auto publicKey = readPublicKey(keyFilePath()); if (publicKey.size() > 0) { - if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) { + if (auto key = readPrivateKey(keyFilePath())) { EC_KEY_free(key); // be sure to add the public key so we don't do this over and over @@ -631,8 +647,7 @@ QStringList Wallet::listPublicKeys() { QString Wallet::signWithKey(const QByteArray& text, const QString& key) { EC_KEY* ecPrivateKey = NULL; - auto keyFilePathString = keyFilePath().toStdString(); - if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { + if (ecPrivateKey = readPrivateKey(keyFilePath())) { unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)]; unsigned int signatureBytes = 0; @@ -641,12 +656,8 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); - - int retrn = ECDSA_sign(0, - reinterpret_cast(hashedPlaintext.constData()), - hashedPlaintext.size(), - sig, - &signatureBytes, ecPrivateKey); + int retrn = ECDSA_sign(0, reinterpret_cast(hashedPlaintext.constData()), hashedPlaintext.size(), + sig, &signatureBytes, ecPrivateKey); EC_KEY_free(ecPrivateKey); QByteArray signature(reinterpret_cast(sig), signatureBytes); @@ -682,7 +693,6 @@ void Wallet::updateImageProvider() { } void Wallet::chooseSecurityImage(const QString& filename) { - if (_securityImage) { delete _securityImage; } @@ -754,7 +764,7 @@ QString Wallet::getKeyFilePath() { } bool Wallet::writeWallet(const QString& newPassphrase) { - EC_KEY* keys = readKeys(keyFilePath().toStdString().c_str()); + EC_KEY* keys = readKeys(keyFilePath()); auto ledger = DependencyManager::get(); // Remove any existing locker, because it will be out of date. if (!_publicKeys.isEmpty() && !ledger->receiveAt(_publicKeys.first(), _publicKeys.first(), QByteArray())) { @@ -768,7 +778,7 @@ bool Wallet::writeWallet(const QString& newPassphrase) { setPassphrase(newPassphrase); } - if (writeKeys(tempFileName.toStdString().c_str(), keys)) { + if (writeKeys(tempFileName, keys)) { if (writeSecurityImage(_securityImage, tempFileName)) { // ok, now move the temp file to the correct spot QFile(QString(keyFilePath())).remove(); @@ -834,10 +844,10 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize); } - EC_KEY* ec = readKeys(keyFilePath().toStdString().c_str()); + EC_KEY* ec = readKeys(keyFilePath()); QString sig; - if (ec) { + if (ec) { ERR_clear_error(); sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString FIXME should pass ec as string so we can tell which key to sign with status = 1; From 246f11ba02ddce4d8aa0787f9b4bb9d5c09fc641 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Fri, 12 Apr 2019 17:11:35 -0700 Subject: [PATCH 10/16] fixing bubble --- interface/src/avatar/AvatarManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 575d87dfb7..6c0eb4a371 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -498,8 +498,10 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar // on the creation of entities for that avatar instance and the deletion of entities for this instance avatar->removeAvatarEntitiesFromTree(); if (removalReason != KillAvatarReason::AvatarDisconnected) { - emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID()); - emit DependencyManager::get()->enteredIgnoreRadius(); + if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { + emit AvatarInputs::getInstance()->avatarEnteredIgnoreRadius(avatar->getSessionUUID()); + emit DependencyManager::get()->enteredIgnoreRadius(); + } workload::Transaction workloadTransaction; workloadTransaction.remove(avatar->getSpaceIndex()); From e36a8fc6a2a4a6221e970a6947a1b56847f4d398 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Fri, 12 Apr 2019 18:36:14 -0700 Subject: [PATCH 11/16] Fix osx/ubuntu build error --- interface/src/commerce/Wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index e00cd44fa9..e6f8491053 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -110,7 +110,7 @@ EC_KEY* readKeys(QString filename) { qCDebug(commerce) << "read public key"; - if (key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL)) { + if ((key = PEM_read_bio_ECPrivateKey(bufio, &key, passwordCallback, NULL))) { qCDebug(commerce) << "read private key"; BIO_free(bufio); file.close(); @@ -647,7 +647,7 @@ QStringList Wallet::listPublicKeys() { QString Wallet::signWithKey(const QByteArray& text, const QString& key) { EC_KEY* ecPrivateKey = NULL; - if (ecPrivateKey = readPrivateKey(keyFilePath())) { + if ((ecPrivateKey = readPrivateKey(keyFilePath()))) { unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)]; unsigned int signatureBytes = 0; From 8f9d8372d8ea9e85afdae870a497d00b2fab91c0 Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Fri, 12 Apr 2019 20:30:03 -0700 Subject: [PATCH 12/16] Public Key was getting corrupted. --- interface/src/commerce/Wallet.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index e6f8491053..2054206f87 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -302,8 +302,11 @@ QByteArray readPublicKey(QString filename) { qCDebug(commerce) << "parsed public key file successfully"; - retval.setRawData((char*)publicKeyDER, publicKeyLength); + QByteArray retval((char*)publicKeyDER, publicKeyLength); OPENSSL_free(publicKeyDER); + BIO_free(bufio); + file.close(); + return retval; } else { qCDebug(commerce) << "couldn't parse" << filename; } @@ -312,7 +315,7 @@ QByteArray readPublicKey(QString filename) { } else { qCDebug(commerce) << "couldn't open" << filename; } - return retval; + return QByteArray(); } // the private key should be read/copied into heap memory. For now, we need the EC_KEY struct @@ -387,7 +390,7 @@ Wallet::Wallet() { } else { status = (uint) WalletStatus::WALLET_STATUS_READY; } - + qCDebug(commerce) << "WALLET STATUS:" + keyStatus + " " + status; walletScriptingInterface->setWalletStatus(status); }); From 12d7e357227777cf04780c95288aa3845fff6906 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 15 Apr 2019 10:56:07 -0700 Subject: [PATCH 13/16] Add separate constant for desktop run. HMD run affected negatively by 3x multiplier. This will need to be cleaned up in a future release. --- interface/src/avatar/MyAvatar.cpp | 7 ++++++- libraries/shared/src/AvatarConstants.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c0cf63d7e4..ee0e9ebc4d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -4798,7 +4798,12 @@ bool MyAvatar::isReadyForPhysics() const { } void MyAvatar::setSprintMode(bool sprint) { - _walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; + if (qApp->isHMDMode()) { + _walkSpeedScalar = sprint ? AVATAR_DESKTOP_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; + } + else { + _walkSpeedScalar = sprint ? AVATAR_HMD_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; + } } void MyAvatar::setIsInWalkingState(bool isWalking) { diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 5b65390620..b2ee4caa7c 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -102,6 +102,7 @@ static const float MAX_AVATAR_HEIGHT = 1000.0f * DEFAULT_AVATAR_HEIGHT; // meter static const float MIN_AVATAR_HEIGHT = 0.005f * DEFAULT_AVATAR_HEIGHT; // meters static const float MIN_AVATAR_RADIUS = 0.5f * MIN_AVATAR_HEIGHT; static const float AVATAR_WALK_SPEED_SCALAR = 1.0f; -static const float AVATAR_SPRINT_SPEED_SCALAR = 3.0f; +static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 2.0f; +static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 3.0f; #endif // hifi_AvatarConstants_h From 3949ca26385a2803fd9a9a8fa1b30f682c9cd5fc Mon Sep 17 00:00:00 2001 From: Roxanne Skelly Date: Mon, 15 Apr 2019 12:35:36 -0700 Subject: [PATCH 14/16] Remove logging and bump build. --- interface/src/commerce/Wallet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 2054206f87..5644f9ea4c 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -390,7 +390,6 @@ Wallet::Wallet() { } else { status = (uint) WalletStatus::WALLET_STATUS_READY; } - qCDebug(commerce) << "WALLET STATUS:" + keyStatus + " " + status; walletScriptingInterface->setWalletStatus(status); }); From 8f87afd7db64d6eb5a067c7733f31530e8c72a91 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Mon, 15 Apr 2019 10:37:28 -0700 Subject: [PATCH 15/16] Disable baking of embedded material textures in material entities --- tools/oven/src/DomainBaker.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/oven/src/DomainBaker.cpp b/tools/oven/src/DomainBaker.cpp index 8a4489fcac..50a3d212c0 100644 --- a/tools/oven/src/DomainBaker.cpp +++ b/tools/oven/src/DomainBaker.cpp @@ -412,9 +412,13 @@ void DomainBaker::enumerateEntities() { if (entity.contains(MATERIAL_URL_KEY)) { addMaterialBaker(MATERIAL_URL_KEY, entity[MATERIAL_URL_KEY].toString(), true, *it); } + // FIXME: Disabled for now because relative texture URLs are not supported for embedded materials in material entities + // We need to make texture URLs absolute in this particular case only, keeping in mind that FSTBaker also uses embedded materials + /* if (entity.contains(MATERIAL_DATA_KEY)) { addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it); } + */ } } From d0abb863661997220a077aa9c1173df305b4bb59 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 15 Apr 2019 17:26:22 -0700 Subject: [PATCH 16/16] Reversed costants because no sleep. >_< --- libraries/shared/src/AvatarConstants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index b2ee4caa7c..b4545cedf0 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -102,7 +102,7 @@ static const float MAX_AVATAR_HEIGHT = 1000.0f * DEFAULT_AVATAR_HEIGHT; // meter static const float MIN_AVATAR_HEIGHT = 0.005f * DEFAULT_AVATAR_HEIGHT; // meters static const float MIN_AVATAR_RADIUS = 0.5f * MIN_AVATAR_HEIGHT; static const float AVATAR_WALK_SPEED_SCALAR = 1.0f; -static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 2.0f; -static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 3.0f; +static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 3.0f; +static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 2.0f; #endif // hifi_AvatarConstants_h