From d7b1852164cf1db401393524e9c956da2818e4a0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 16 Mar 2015 15:25:44 -0700 Subject: [PATCH 01/12] Creating eachMatchingNode and using it in avatar mixer --- assignment-client/src/avatars/AvatarMixer.cpp | 44 ++++++++++++++----- libraries/networking/src/LimitedNodeList.h | 13 +++++- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 9616c8cb21..a6420c357a 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -119,12 +119,24 @@ void AvatarMixer::broadcastAvatarData() { auto nodeList = DependencyManager::get(); - AvatarMixerClientData* nodeData = NULL; - AvatarMixerClientData* otherNodeData = NULL; - - nodeList->eachNode([&](const SharedNodePointer& node) { - if (node->getLinkedData() && node->getType() == NodeType::Agent && node->getActiveSocket() - && (nodeData = reinterpret_cast(node->getLinkedData()))->getMutex().tryLock()) { + nodeList->eachMatchingNode( + [&](const SharedNodePointer& node)->bool { + if (!node->getLinkedData()) { + return false; + } + if (node->getType() != NodeType::Agent) { + return false; + } + if (!node->getActiveSocket()) { + return false; + } + return true; + }, + [&](const SharedNodePointer& node) { + AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); + if (!nodeData->getMutex().tryLock()) { + return; + } ++_sumListeners; // reset packet pointers for this node @@ -135,9 +147,21 @@ void AvatarMixer::broadcastAvatarData() { // this is an AGENT we have received head data from // send back a packet with other active node data to this node - nodeList->eachNode([&](const SharedNodePointer& otherNode) { - if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID() - && (otherNodeData = reinterpret_cast(otherNode->getLinkedData()))->getMutex().tryLock()) { + nodeList->eachMatchingNode( + [&](const SharedNodePointer& otherNode)->bool { + if (!otherNode->getLinkedData()) { + return false; + } + if (otherNode->getUUID() == node->getUUID()) { + return false; + } + return true; + }, + [&](const SharedNodePointer& otherNode) { + AvatarMixerClientData* otherNodeData = otherNodeData = reinterpret_cast(otherNode->getLinkedData()); + if (!otherNodeData->getMutex().tryLock()) { + return; + } AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); AvatarData& otherAvatar = otherNodeData->getAvatar(); @@ -202,13 +226,11 @@ void AvatarMixer::broadcastAvatarData() { } otherNodeData->getMutex().unlock(); - } }); nodeList->writeDatagram(mixedAvatarByteArray, node); nodeData->getMutex().unlock(); - } }); _lastFrameTimestamp = QDateTime::currentMSecsSinceEpoch(); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index a071eced31..532e8ffcf4 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -151,7 +151,18 @@ public: functor(it->second); } } - + + template + void eachMatchingNode(PredLambda predicate, NodeLambda functor) { + QReadLocker readLock(&_nodeMutex); + + for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) { + if (predicate(it->second)) { + functor(it->second); + } + } + } + template void eachNodeBreakable(BreakableNodeLambda functor) { QReadLocker readLock(&_nodeMutex); From 80b5a44cc45b19614348496146f334d87bcf1d55 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 17 Mar 2015 11:49:17 -0700 Subject: [PATCH 02/12] Adding a RAII version of the mutex locker that uses tryLock instead of lock --- libraries/shared/src/TryLocker.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 libraries/shared/src/TryLocker.h diff --git a/libraries/shared/src/TryLocker.h b/libraries/shared/src/TryLocker.h new file mode 100644 index 0000000000..e434ae4372 --- /dev/null +++ b/libraries/shared/src/TryLocker.h @@ -0,0 +1,31 @@ +// +// TryLocker.h +// libraries/shared/src +// +// Created by Brad Davis on 2015/03/16. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_TryLocker_h +#define hifi_TryLocker_h + +#include + +class MutexTryLocker { + QMutex & _mutex; + bool _locked{false}; +public: + MutexTryLocker(QMutex &m) : _mutex(m) {} + ~MutexTryLocker() { if (_locked) _mutex.unlock(); } + bool tryLock() { + if (_locked) { + return true; + } + return (_locked = _mutex.tryLock()); + } +} + +#endif // hifi_UUID_h From 6415ff99f61d9004e85632631bf7f7a4d2841284 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 17 Mar 2015 12:04:04 -0700 Subject: [PATCH 03/12] Work in progress --- assignment-client/src/avatars/AvatarMixer.cpp | 131 +++++++++--------- libraries/networking/src/BandwidthRecorder.h | 1 - libraries/networking/src/LimitedNodeList.cpp | 6 +- libraries/networking/src/NetworkPeer.cpp | 37 ++++- libraries/networking/src/NetworkPeer.h | 6 + libraries/shared/src/TryLocker.h | 9 +- 6 files changed, 115 insertions(+), 75 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index a6420c357a..bd0239cdc8 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -20,9 +20,9 @@ #include #include #include +#include #include "AvatarMixerClientData.h" - #include "AvatarMixer.h" const QString AVATAR_MIXER_LOGGING_NAME = "avatar-mixer"; @@ -134,7 +134,8 @@ void AvatarMixer::broadcastAvatarData() { }, [&](const SharedNodePointer& node) { AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); - if (!nodeData->getMutex().tryLock()) { + MutexTryLocker lock(nodeData->getMutex()); + if (!lock.tryLock()) { return; } ++_sumListeners; @@ -144,6 +145,7 @@ void AvatarMixer::broadcastAvatarData() { AvatarData& avatar = nodeData->getAvatar(); glm::vec3 myPosition = avatar.getPosition(); + float outputBandwidth = node->getBandwidthRecorder().getTotalAverageOutputKilobitsPerSecond(); // this is an AGENT we have received head data from // send back a packet with other active node data to this node @@ -155,82 +157,81 @@ void AvatarMixer::broadcastAvatarData() { if (otherNode->getUUID() == node->getUUID()) { return false; } + + // Check throttling value + if (!(_performanceThrottlingRatio == 0 || randFloat() < (1.0f - _performanceThrottlingRatio))) { + return; + } return true; }, [&](const SharedNodePointer& otherNode) { AvatarMixerClientData* otherNodeData = otherNodeData = reinterpret_cast(otherNode->getLinkedData()); - if (!otherNodeData->getMutex().tryLock()) { + MutexTryLocker lock(otherNodeData->getMutex()); + if (!lock.tryLock()) { return; } - - AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); AvatarData& otherAvatar = otherNodeData->getAvatar(); - glm::vec3 otherPosition = otherAvatar.getPosition(); - - float distanceToAvatar = glm::length(myPosition - otherPosition); + // Decide whether to send this avatar's data based on it's distance from us // The full rate distance is the distance at which EVERY update will be sent for this avatar // at a distance of twice the full rate distance, there will be a 50% chance of sending this avatar's update const float FULL_RATE_DISTANCE = 2.0f; - - // Decide whether to send this avatar's data based on it's distance from us - if ((_performanceThrottlingRatio == 0 || randFloat() < (1.0f - _performanceThrottlingRatio)) - && (distanceToAvatar == 0.0f || randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) { - QByteArray avatarByteArray; - avatarByteArray.append(otherNode->getUUID().toRfc4122()); - avatarByteArray.append(otherAvatar.toByteArray()); - - if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { - nodeList->writeDatagram(mixedAvatarByteArray, node); - - // reset the packet - mixedAvatarByteArray.resize(numPacketHeaderBytes); - } - - // copy the avatar into the mixedAvatarByteArray packet - mixedAvatarByteArray.append(avatarByteArray); - - // if the receiving avatar has just connected make sure we send out the mesh and billboard - // for this avatar (assuming they exist) - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPackets(); - - // we will also force a send of billboard or identity packet - // if either has changed in the last frame - - if (otherNodeData->getBillboardChangeTimestamp() > 0 - && (forceSend - || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp - || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); - billboardPacket.append(otherNode->getUUID().toRfc4122()); - billboardPacket.append(otherNodeData->getAvatar().getBillboard()); - nodeList->writeDatagram(billboardPacket, node); - - ++_sumBillboardPackets; - } - - if (otherNodeData->getIdentityChangeTimestamp() > 0 - && (forceSend - || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - - QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); - - QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); - individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); - identityPacket.append(individualData); - - nodeList->writeDatagram(identityPacket, node); - - ++_sumIdentityPackets; - } + glm::vec3 otherPosition = otherAvatar.getPosition(); + float distanceToAvatar = glm::length(myPosition - otherPosition); + + if (!(distanceToAvatar == 0.0f || randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) { + return; + } + + QByteArray avatarByteArray; + avatarByteArray.append(otherNode->getUUID().toRfc4122()); + avatarByteArray.append(otherAvatar.toByteArray()); + + if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { + nodeList->writeDatagram(mixedAvatarByteArray, node); + + // reset the packet + mixedAvatarByteArray.resize(numPacketHeaderBytes); + } + + // copy the avatar into the mixedAvatarByteArray packet + mixedAvatarByteArray.append(avatarByteArray); + + // if the receiving avatar has just connected make sure we send out the mesh and billboard + // for this avatar (assuming they exist) + bool forceSend = !nodeData->checkAndSetHasReceivedFirstPackets(); + + // we will also force a send of billboard or identity packet + // if either has changed in the last frame + + if (otherNodeData->getBillboardChangeTimestamp() > 0 + && (forceSend + || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp + || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { + QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); + billboardPacket.append(otherNode->getUUID().toRfc4122()); + billboardPacket.append(otherNodeData->getAvatar().getBillboard()); + nodeList->writeDatagram(billboardPacket, node); + + ++_sumBillboardPackets; + } + + if (otherNodeData->getIdentityChangeTimestamp() > 0 + && (forceSend + || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp + || randFloat() < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { + + QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); + + QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); + individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122()); + identityPacket.append(individualData); + + nodeList->writeDatagram(identityPacket, node); + + ++_sumIdentityPackets; } - - otherNodeData->getMutex().unlock(); }); - nodeList->writeDatagram(mixedAvatarByteArray, node); - - nodeData->getMutex().unlock(); }); _lastFrameTimestamp = QDateTime::currentMSecsSinceEpoch(); diff --git a/libraries/networking/src/BandwidthRecorder.h b/libraries/networking/src/BandwidthRecorder.h index c22665d2cc..f87d9d4d06 100644 --- a/libraries/networking/src/BandwidthRecorder.h +++ b/libraries/networking/src/BandwidthRecorder.h @@ -17,7 +17,6 @@ #include #include #include "DependencyManager.h" -#include "Node.h" #include "SimpleMovingAverage.h" diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 520dc650ed..98e1ed0572 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -263,8 +263,10 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, } emit dataSent(destinationNode->getType(), datagram.size()); - - return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); + auto bytesWritten = writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); + // Keep track of per-destination-node bandwidth + destinationNode->recordBytesSent(bytesWritten); + return bytesWritten; } // didn't have a destinationNode to send to, return 0 diff --git a/libraries/networking/src/NetworkPeer.cpp b/libraries/networking/src/NetworkPeer.cpp index eaaf57471c..eb072a91f0 100644 --- a/libraries/networking/src/NetworkPeer.cpp +++ b/libraries/networking/src/NetworkPeer.cpp @@ -15,6 +15,7 @@ #include #include "NetworkPeer.h" +#include "BandwidthRecorder.h" NetworkPeer::NetworkPeer() : _uuid(), @@ -96,4 +97,38 @@ QDebug operator<<(QDebug debug, const NetworkPeer &peer) { << "- public:" << peer.getPublicSocket() << "- local:" << peer.getLocalSocket(); return debug; -} \ No newline at end of file +} + + +// FIXME this is a temporary implementation to determine if this is the right approach. +// If so, migrate the BandwidthRecorder into the NetworkPeer class +using BandwidthRecorderPtr = QSharedPointer < BandwidthRecorder > ; +static QHash PEER_BANDWIDTH; + +BandwidthRecorder & getBandwidthRecorder(const QUuid & uuid) { + if (!PEER_BANDWIDTH.count(uuid)) { + PEER_BANDWIDTH.insert(uuid, BandwidthRecorderPtr(new BandwidthRecorder())); + } + return *PEER_BANDWIDTH[uuid].data(); +} + + +void NetworkPeer::recordBytesSent(int count) { + auto & bw = getBandwidthRecorder(_uuid); + bw.updateOutboundData(0, count); +} + +void NetworkPeer::recordBytesReceived(int count) { + auto & bw = getBandwidthRecorder(_uuid); + bw.updateInboundData(0, count); +} + +float NetworkPeer::getOutboundBandwidth() { + auto & bw = getBandwidthRecorder(_uuid); + return bw.getAverageOutputKilobitsPerSecond(0); +} + +float NetworkPeer::getInboundBandwidth() { + auto & bw = getBandwidthRecorder(_uuid); + return bw.getAverageInputKilobitsPerSecond(0); +} diff --git a/libraries/networking/src/NetworkPeer.h b/libraries/networking/src/NetworkPeer.h index bb92c54eb8..5bf798d2c5 100644 --- a/libraries/networking/src/NetworkPeer.h +++ b/libraries/networking/src/NetworkPeer.h @@ -54,6 +54,12 @@ public: int getConnectionAttempts() const { return _connectionAttempts; } void incrementConnectionAttempts() { ++_connectionAttempts; } void resetConnectionAttemps() { _connectionAttempts = 0; } + + void recordBytesSent(int count); + void recordBytesReceived(int count); + + float getOutboundBandwidth(); + float getInboundBandwidth(); friend QDataStream& operator<<(QDataStream& out, const NetworkPeer& peer); friend QDataStream& operator>>(QDataStream& in, NetworkPeer& peer); diff --git a/libraries/shared/src/TryLocker.h b/libraries/shared/src/TryLocker.h index e434ae4372..c5328b3b3a 100644 --- a/libraries/shared/src/TryLocker.h +++ b/libraries/shared/src/TryLocker.h @@ -18,13 +18,10 @@ class MutexTryLocker { QMutex & _mutex; bool _locked{false}; public: - MutexTryLocker(QMutex &m) : _mutex(m) {} + MutexTryLocker(QMutex &m) : _mutex(m), _locked(m.tryLock()) {} ~MutexTryLocker() { if (_locked) _mutex.unlock(); } - bool tryLock() { - if (_locked) { - return true; - } - return (_locked = _mutex.tryLock()); + bool isLocked() { + return _locked; } } From 870f1112e4bd213b0c4a03acee70180e85bf1442 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 17 Mar 2015 16:17:44 -0700 Subject: [PATCH 04/12] Fix thrust not being applied w/ Physics + Avatar --- interface/src/avatar/MyAvatar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bdb0877cda..6dc3d820ae 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1357,6 +1357,9 @@ void MyAvatar::updatePositionWithPhysics(float deltaTime) { // rotate back into world-frame _velocity = rotation * newLocalVelocity; + + _velocity += _thrust * deltaTime; + _thrust = glm::vec3(0.0f); } void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) { From a04bd09b83349e820dd6762bef3e0fa0aec69b87 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 17 Mar 2015 16:32:59 -0700 Subject: [PATCH 05/12] Set clip near distance per skeleton model if no separate head model --- interface/src/avatar/MyAvatar.cpp | 15 ++++++++++++--- interface/src/avatar/SkeletonModel.cpp | 7 ++++++- interface/src/avatar/SkeletonModel.h | 4 ++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bdb0877cda..642da60b18 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1028,7 +1028,18 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } - + + Camera *camera = Application::getInstance()->getCamera(); + const glm::vec3 cameraPos = camera->getPosition(); + + // Set near clip distance according to skeleton model dimensions if first person and there is no separate head model. + if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) { + camera->setNearClip(DEFAULT_NEAR_CLIP); + } else { + float clipDistance = _skeletonModel.getHeadClipDistance(); + camera->setNearClip(clipDistance); + } + // Render the body's voxels and head Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; @@ -1040,8 +1051,6 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo } // Render head so long as the camera isn't inside it - const Camera *camera = Application::getInstance()->getCamera(); - const glm::vec3 cameraPos = camera->getPosition(); if (shouldRenderHead(cameraPos, renderMode)) { getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4fdebd5f6f..3a61f69dee 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -37,7 +37,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) : _defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)), _standingFoot(NO_FOOT), _standingOffset(0.0f), - _clampedFootPosition(0.0f) + _clampedFootPosition(0.0f), + _headClipDistance(DEFAULT_NEAR_CLIP) { } @@ -78,6 +79,10 @@ void SkeletonModel::setJointStates(QVector states) { buildShapes(); } + Extents meshExtents = getMeshExtents(); + _headClipDistance = -(meshExtents.minimum.z / _scale.z - _defaultEyeModelPosition.z); + _headClipDistance = std::max(_headClipDistance, DEFAULT_NEAR_CLIP); + emit skeletonLoaded(); } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 5427fcaf25..298d74fb7a 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -110,6 +110,8 @@ public: bool hasSkeleton(); + float getHeadClipDistance() const { return _headClipDistance; } + signals: void skeletonLoaded(); @@ -160,6 +162,8 @@ private: int _standingFoot; glm::vec3 _standingOffset; glm::vec3 _clampedFootPosition; + + float _headClipDistance; // Near clip distance to use if no separate head model }; #endif // hifi_SkeletonModel_h From 7b54443bda95a8622a7306225f82c6b47d13610c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 17 Mar 2015 16:33:20 -0700 Subject: [PATCH 06/12] Adjust clip distance as HMD head moves backwards --- interface/src/avatar/MyAvatar.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 642da60b18..8af5982b3e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1037,6 +1037,16 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo camera->setNearClip(DEFAULT_NEAR_CLIP); } else { float clipDistance = _skeletonModel.getHeadClipDistance(); + if (OculusManager::isConnected()) { + // If avatar is horizontally in front of camera, increase clip distance by the amount it is in front. + glm::vec3 cameraToAvatar = _position - cameraPos; + cameraToAvatar.y = 0.0f; + glm::vec3 cameraLookAt = camera->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f); + float headOffset = glm::dot(cameraLookAt, cameraToAvatar); + if (headOffset > 0) { + clipDistance += headOffset; + } + } camera->setNearClip(clipDistance); } From 648a2e3b1d13b4fdb45eb62d08ac714462328f67 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 18 Mar 2015 12:43:49 -0700 Subject: [PATCH 07/12] Set clip distance on rendering frustum rather than camera This fixes wrong clipping distance used for rendering in FPV if also have rear view mirror. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8af5982b3e..25cb4d4c6a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1034,7 +1034,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo // Set near clip distance according to skeleton model dimensions if first person and there is no separate head model. if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) { - camera->setNearClip(DEFAULT_NEAR_CLIP); + renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); } else { float clipDistance = _skeletonModel.getHeadClipDistance(); if (OculusManager::isConnected()) { @@ -1047,7 +1047,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo clipDistance += headOffset; } } - camera->setNearClip(clipDistance); + renderFrustum->setNearClip(clipDistance); } // Render the body's voxels and head From 72957670ba14c9130e0a3e42378bbfca18857ecb Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Mar 2015 09:55:03 -0700 Subject: [PATCH 08/12] Some commentary --- assignment-client/src/avatars/AvatarMixer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index bd0239cdc8..151a9f8861 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -145,6 +145,10 @@ void AvatarMixer::broadcastAvatarData() { AvatarData& avatar = nodeData->getAvatar(); glm::vec3 myPosition = avatar.getPosition(); + // TODO use this along with the distance in the calculation of whether to send an update + // about a given otherNode to this node + // FIXME does this mean we should sort the othernodes by distance before iterating + // over them? float outputBandwidth = node->getBandwidthRecorder().getTotalAverageOutputKilobitsPerSecond(); // this is an AGENT we have received head data from From 54f2774d2e5e612b7602e2f779478c06fe8f6fe0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Mar 2015 15:45:11 -0700 Subject: [PATCH 09/12] Organize projects into folders for IDEs that support it --- CMakeLists.txt | 7 +++++++ cmake/macros/LinkHifiLibraries.cmake | 1 + tests/CMakeLists.txt | 1 + tools/CMakeLists.txt | 4 ++++ 4 files changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1555321c32..296a566fa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,9 @@ if (POLICY CMP0042) cmake_policy(SET CMP0042 OLD) endif () +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") + project(hifi) add_definitions(-DGLM_FORCE_RADIANS) @@ -173,9 +176,13 @@ endif () # add subdirectories for all targets if (NOT ANDROID) add_subdirectory(assignment-client) + set_target_properties(assignment-client PROPERTIES FOLDER "Apps") add_subdirectory(domain-server) + set_target_properties(domain-server PROPERTIES FOLDER "Apps") add_subdirectory(ice-server) + set_target_properties(ice-server PROPERTIES FOLDER "Apps") add_subdirectory(interface) + set_target_properties(interface PROPERTIES FOLDER "Apps") add_subdirectory(tests) add_subdirectory(tools) endif () diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index ed68103c0c..ef7467e170 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -16,6 +16,7 @@ macro(LINK_HIFI_LIBRARIES) foreach(HIFI_LIBRARY ${LIBRARIES_TO_LINK}) if (NOT TARGET ${HIFI_LIBRARY}) add_subdirectory("${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}" "${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}") + set_target_properties(${HIFI_LIBRARY} PROPERTIES FOLDER "Libraries") endif () include_directories("${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 862792d8ac..b6b57ca530 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,5 +4,6 @@ list(REMOVE_ITEM TEST_SUBDIRS "CMakeFiles") foreach(DIR ${TEST_SUBDIRS}) if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${DIR}") add_subdirectory(${DIR}) + set_target_properties("${DIR}-tests" PROPERTIES FOLDER "Tests") endif() endforeach() \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 08fe8fd7f3..5c7c306a62 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,8 +1,12 @@ # add the tool directories add_subdirectory(mtc) +set_target_properties(mtc PROPERTIES FOLDER "Tools") add_subdirectory(scribe) +set_target_properties(scribe PROPERTIES FOLDER "Tools") + find_package(VHACD) if(VHACD_FOUND) add_subdirectory(vhacd) +set_target_properties(vhacd PROPERTIES FOLDER "Tools") endif() From bf607e4c9cc634f6c383913c7be8ae2a1d340114 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Mar 2015 15:53:16 -0700 Subject: [PATCH 10/12] Fixing indentation and usage --- assignment-client/src/avatars/AvatarMixer.cpp | 8 ++++---- libraries/shared/src/TryLocker.h | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 151a9f8861..176fd51eea 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -135,7 +135,7 @@ void AvatarMixer::broadcastAvatarData() { [&](const SharedNodePointer& node) { AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); MutexTryLocker lock(nodeData->getMutex()); - if (!lock.tryLock()) { + if (!lock.isLocked()) { return; } ++_sumListeners; @@ -149,7 +149,7 @@ void AvatarMixer::broadcastAvatarData() { // about a given otherNode to this node // FIXME does this mean we should sort the othernodes by distance before iterating // over them? - float outputBandwidth = node->getBandwidthRecorder().getTotalAverageOutputKilobitsPerSecond(); + float outputBandwidth = node->getOutboundBandwidth(); // this is an AGENT we have received head data from // send back a packet with other active node data to this node @@ -164,14 +164,14 @@ void AvatarMixer::broadcastAvatarData() { // Check throttling value if (!(_performanceThrottlingRatio == 0 || randFloat() < (1.0f - _performanceThrottlingRatio))) { - return; + return false; } return true; }, [&](const SharedNodePointer& otherNode) { AvatarMixerClientData* otherNodeData = otherNodeData = reinterpret_cast(otherNode->getLinkedData()); MutexTryLocker lock(otherNodeData->getMutex()); - if (!lock.tryLock()) { + if (!lock.isLocked()) { return; } AvatarData& otherAvatar = otherNodeData->getAvatar(); diff --git a/libraries/shared/src/TryLocker.h b/libraries/shared/src/TryLocker.h index c5328b3b3a..f4b90575f1 100644 --- a/libraries/shared/src/TryLocker.h +++ b/libraries/shared/src/TryLocker.h @@ -15,14 +15,14 @@ #include class MutexTryLocker { - QMutex & _mutex; - bool _locked{false}; + QMutex & _mutex; + bool _locked{ false }; public: - MutexTryLocker(QMutex &m) : _mutex(m), _locked(m.tryLock()) {} - ~MutexTryLocker() { if (_locked) _mutex.unlock(); } - bool isLocked() { - return _locked; - } -} + MutexTryLocker(QMutex &m) : _mutex(m), _locked(m.tryLock()) {} + ~MutexTryLocker() { if (_locked) _mutex.unlock(); } + bool isLocked() { + return _locked; + } +}; -#endif // hifi_UUID_h +#endif // hifi_TryLocker_h From 599fe09e75fe6b2148ef0a14b410be1aaa3b00c2 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Mar 2015 17:24:58 -0700 Subject: [PATCH 11/12] type & squish --- libraries/networking/src/NetworkPeer.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/networking/src/NetworkPeer.cpp b/libraries/networking/src/NetworkPeer.cpp index eb072a91f0..c6026b3a23 100644 --- a/libraries/networking/src/NetworkPeer.cpp +++ b/libraries/networking/src/NetworkPeer.cpp @@ -102,33 +102,32 @@ QDebug operator<<(QDebug debug, const NetworkPeer &peer) { // FIXME this is a temporary implementation to determine if this is the right approach. // If so, migrate the BandwidthRecorder into the NetworkPeer class -using BandwidthRecorderPtr = QSharedPointer < BandwidthRecorder > ; +using BandwidthRecorderPtr = QSharedPointer; static QHash PEER_BANDWIDTH; -BandwidthRecorder & getBandwidthRecorder(const QUuid & uuid) { +BandwidthRecorder& getBandwidthRecorder(const QUuid & uuid) { if (!PEER_BANDWIDTH.count(uuid)) { PEER_BANDWIDTH.insert(uuid, BandwidthRecorderPtr(new BandwidthRecorder())); } return *PEER_BANDWIDTH[uuid].data(); } - void NetworkPeer::recordBytesSent(int count) { - auto & bw = getBandwidthRecorder(_uuid); + auto& bw = getBandwidthRecorder(_uuid); bw.updateOutboundData(0, count); } void NetworkPeer::recordBytesReceived(int count) { - auto & bw = getBandwidthRecorder(_uuid); + auto& bw = getBandwidthRecorder(_uuid); bw.updateInboundData(0, count); } float NetworkPeer::getOutboundBandwidth() { - auto & bw = getBandwidthRecorder(_uuid); + auto& bw = getBandwidthRecorder(_uuid); return bw.getAverageOutputKilobitsPerSecond(0); } float NetworkPeer::getInboundBandwidth() { - auto & bw = getBandwidthRecorder(_uuid); + auto& bw = getBandwidthRecorder(_uuid); return bw.getAverageInputKilobitsPerSecond(0); } From 7079b5f978514277f9eb65a939fb5d2f174f5206 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 19 Mar 2015 17:29:57 -0700 Subject: [PATCH 12/12] type & squish again --- libraries/shared/src/TryLocker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/TryLocker.h b/libraries/shared/src/TryLocker.h index f4b90575f1..a5c8077484 100644 --- a/libraries/shared/src/TryLocker.h +++ b/libraries/shared/src/TryLocker.h @@ -15,7 +15,7 @@ #include class MutexTryLocker { - QMutex & _mutex; + QMutex& _mutex; bool _locked{ false }; public: MutexTryLocker(QMutex &m) : _mutex(m), _locked(m.tryLock()) {}