From 80d3f35b2eae56a0f6a5260a0ed15ccdc05dadc0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 24 Apr 2015 09:57:22 -0700 Subject: [PATCH 01/14] Controller disabled when not in physics engine --- .../physics/src/DynamicCharacterController.cpp | 16 ++++++++++------ .../physics/src/DynamicCharacterController.h | 6 +++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index 46ff2e524e..fa1a2d42d1 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -43,8 +43,8 @@ protected: DynamicCharacterController::DynamicCharacterController(AvatarData* avatarData) { _halfHeight = 1.0f; - _shape = NULL; - _rigidBody = NULL; + _shape = nullptr; + _rigidBody = nullptr; assert(avatarData); _avatarData = avatarData; @@ -257,6 +257,10 @@ void DynamicCharacterController::setEnabled(bool enabled) { } } +bool DynamicCharacterController::isEnabled() const { + return _enabled && _dynamicsWorld; +} + void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (_dynamicsWorld != world) { if (_dynamicsWorld) { @@ -264,7 +268,7 @@ void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) { _dynamicsWorld->removeRigidBody(_rigidBody); _dynamicsWorld->removeAction(this); } - _dynamicsWorld = NULL; + _dynamicsWorld = nullptr; } if (world && _rigidBody) { _dynamicsWorld = world; @@ -294,9 +298,9 @@ void DynamicCharacterController::updateShapeIfNecessary() { _pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE; // delete shape and RigidBody delete _rigidBody; - _rigidBody = NULL; + _rigidBody = nullptr; delete _shape; - _shape = NULL; + _shape = nullptr; // compute new dimensions from avatar's bounding box float x = _boxScale.x; @@ -316,7 +320,7 @@ void DynamicCharacterController::updateShapeIfNecessary() { // create new body float mass = 1.0f; btVector3 inertia(1.0f, 1.0f, 1.0f); - _rigidBody = new btRigidBody(mass, NULL, _shape, inertia); + _rigidBody = new btRigidBody(mass, nullptr, _shape, inertia); _rigidBody->setSleepingThresholds (0.0f, 0.0f); _rigidBody->setAngularFactor (0.0f); _rigidBody->setWorldTransform(btTransform(glmToBullet(_avatarData->getOrientation()), diff --git a/libraries/physics/src/DynamicCharacterController.h b/libraries/physics/src/DynamicCharacterController.h index f98343c49b..bd71a8bcdc 100644 --- a/libraries/physics/src/DynamicCharacterController.h +++ b/libraries/physics/src/DynamicCharacterController.h @@ -30,7 +30,7 @@ protected: glm::vec3 _shapeLocalOffset; glm::vec3 _boxScale; // used to compute capsule shape - AvatarData* _avatarData = NULL; + AvatarData* _avatarData = nullptr; bool _enabled; bool _isOnGround; @@ -41,7 +41,7 @@ protected: quint64 _jumpToHoverStart; uint32_t _pendingFlags; - btDynamicsWorld* _dynamicsWorld = NULL; + btDynamicsWorld* _dynamicsWorld = nullptr; btScalar _jumpSpeed; @@ -78,7 +78,7 @@ public: bool needsRemoval() const; bool needsAddition() const; void setEnabled(bool enabled); - bool isEnabled() const { return _enabled; } + bool isEnabled() const; void setDynamicsWorld(btDynamicsWorld* world); void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); From 7a222dff1d7fc92f58768e9da574b761316b994b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 27 Apr 2015 09:54:58 -0700 Subject: [PATCH 02/14] move one-liner isEnabled() to header --- libraries/physics/src/DynamicCharacterController.cpp | 4 ---- libraries/physics/src/DynamicCharacterController.h | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index fa1a2d42d1..0bd363dd1f 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -257,10 +257,6 @@ void DynamicCharacterController::setEnabled(bool enabled) { } } -bool DynamicCharacterController::isEnabled() const { - return _enabled && _dynamicsWorld; -} - void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (_dynamicsWorld != world) { if (_dynamicsWorld) { diff --git a/libraries/physics/src/DynamicCharacterController.h b/libraries/physics/src/DynamicCharacterController.h index bd71a8bcdc..06ff555f66 100644 --- a/libraries/physics/src/DynamicCharacterController.h +++ b/libraries/physics/src/DynamicCharacterController.h @@ -78,7 +78,8 @@ public: bool needsRemoval() const; bool needsAddition() const; void setEnabled(bool enabled); - bool isEnabled() const; + bool isEnabled() const { return _enabled && _dynamicsWorld; } + void setDynamicsWorld(btDynamicsWorld* world); void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); From 9576ad19a7f78001ec5f90df899190f6d931d128 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Apr 2015 10:52:46 -0700 Subject: [PATCH 03/14] Move "Stereo Audio" option into developerMenu.js And rename it "Stereo Input" to better relect what it does. --- examples/utilities/tools/developerMenuItems.js | 12 ++++++++++++ interface/src/Menu.cpp | 2 -- interface/src/Menu.h | 1 - libraries/audio-client/src/AudioClient.h | 8 +++----- libraries/audio/src/AbstractAudioInterface.h | 2 ++ .../script-engine/src/AudioScriptingInterface.cpp | 6 +++++- .../script-engine/src/AudioScriptingInterface.h | 2 ++ 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/examples/utilities/tools/developerMenuItems.js b/examples/utilities/tools/developerMenuItems.js index 58b5149307..ace2b032e2 100644 --- a/examples/utilities/tools/developerMenuItems.js +++ b/examples/utilities/tools/developerMenuItems.js @@ -13,6 +13,7 @@ var createdRenderMenu = false; var createdGeneratedAudioMenu = false; +var createdStereoInputMenuItem = false; var DEVELOPER_MENU = "Developer"; @@ -28,6 +29,7 @@ var AUDIO_SOURCE_INJECT = "Generated Audio"; var AUDIO_SOURCE_MENU = AUDIO_MENU + " > Generated Audio Source"; var AUDIO_SOURCE_PINK_NOISE = "Pink Noise"; var AUDIO_SOURCE_SINE_440 = "Sine 440hz"; +var AUDIO_STEREO_INPUT = "Stereo Input"; function setupMenus() { @@ -78,6 +80,10 @@ function setupMenus() { Audio.selectPinkNoise(); createdGeneratedAudioMenu = true; } + if (!Menu.menuItemExists(AUDIO_MENU, AUDIO_STEREO_INPUT)) { + Menu.addMenuItem({ menuName: AUDIO_MENU, menuItemName: AUDIO_STEREO_INPUT, isCheckable: true, isChecked: false }); + createdStereoInputMenuItem = true; + } } Menu.menuItemEvent.connect(function (menuItem) { @@ -99,6 +105,8 @@ Menu.menuItemEvent.connect(function (menuItem) { } else if (menuItem == AUDIO_SOURCE_SINE_440 && !createdGeneratedAudioMenu) { Audio.selectSine440(); Menu.setIsOptionChecked(AUDIO_SOURCE_PINK_NOISE, false); + } else if (menuItem == AUDIO_STEREO_INPUT) { + Audio.setStereoInput(Menu.isOptionChecked(AUDIO_STEREO_INPUT)) } }); @@ -125,6 +133,10 @@ function scriptEnding() { Menu.removeMenuItem(AUDIO_MENU, AUDIO_SOURCE_INJECT); Menu.removeMenu(AUDIO_SOURCE_MENU); } + + if (createdStereoInputMenuItem) { + Menu.removeMenuItem(AUDIO_MENU, AUDIO_STEREO_INPUT); + } } setupMenus(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 43c63eb383..4548ccd586 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -485,8 +485,6 @@ Menu::Menu() { audioIO.data(), SLOT(toggleServerEcho())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio, 0, false, audioIO.data(), SLOT(toggleLocalEcho())); - addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::StereoAudio, 0, false, - audioIO.data(), SLOT(toggleStereoInput())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, Qt::CTRL | Qt::Key_M, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 2c4e2b809f..fd0c230c17 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -238,7 +238,6 @@ namespace MenuOption { const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations"; const QString Stars = "Stars"; const QString Stats = "Stats"; - const QString StereoAudio = "Stereo Audio (disables spatial sound)"; const QString StopAllScripts = "Stop All Scripts"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString TestPing = "Test Ping"; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index bb145a209f..9d10184d13 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -108,8 +108,6 @@ public: bool isMuted() { return _muted; } - void setIsStereoInput(bool isStereoInput); - const AudioIOStats& getStats() const { return _stats; } float getInputRingBufferMsecsAvailable() const; @@ -146,14 +144,14 @@ public slots: virtual void enableAudioSourceInject(bool enable); virtual void selectAudioSourcePinkNoise(); virtual void selectAudioSourceSine440(); - + + virtual void setIsStereoInput(bool stereo); + void toggleAudioNoiseReduction() { _isNoiseGateEnabled = !_isNoiseGateEnabled; } void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; } void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; } - void toggleStereoInput() { setIsStereoInput(!_isStereoInput); } - void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer); void sendMuteEnvironmentPacket(); diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h index 9649d11ad2..a5855d75d1 100644 --- a/libraries/audio/src/AbstractAudioInterface.h +++ b/libraries/audio/src/AbstractAudioInterface.h @@ -31,6 +31,8 @@ public slots: virtual void enableAudioSourceInject(bool enable) = 0; virtual void selectAudioSourcePinkNoise() = 0; virtual void selectAudioSourceSine440() = 0; + + virtual void setIsStereoInput(bool stereo) = 0; }; Q_DECLARE_METATYPE(AbstractAudioInterface*) diff --git a/libraries/script-engine/src/AudioScriptingInterface.cpp b/libraries/script-engine/src/AudioScriptingInterface.cpp index 8bcc4a20cf..e210ee6f6e 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.cpp +++ b/libraries/script-engine/src/AudioScriptingInterface.cpp @@ -89,4 +89,8 @@ void AudioScriptingInterface::selectSine440() { } } - +void AudioScriptingInterface::setStereoInput(bool stereo) { + if (_localAudioInterface) { + _localAudioInterface->setIsStereoInput(stereo); + } +} diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index 9d02b8c9a1..bbc9a57db8 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -32,6 +32,8 @@ protected: Q_INVOKABLE void injectGeneratedNoise(bool inject); Q_INVOKABLE void selectPinkNoise(); Q_INVOKABLE void selectSine440(); + + Q_INVOKABLE void setStereoInput(bool stereo); signals: void mutedByMixer(); From 342d3576c96b62d98fbd2f436c49836ca0accc74 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Tue, 28 Apr 2015 14:46:39 -0700 Subject: [PATCH 04/14] Added ability to check if an avatar is within specified range of a position from javascript --- libraries/avatars/src/AvatarHashMap.cpp | 11 +++++++++++ libraries/avatars/src/AvatarHashMap.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index ae3a8c3e5c..d389846796 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -55,6 +55,17 @@ bool AvatarHashMap::containsAvatarWithDisplayName(const QString& displayName) { return !avatarWithDisplayName(displayName).isNull(); } +bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { + foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) { + glm::vec3 avatarPosition = sharedAvatar->getPosition(); + float distance = glm::distance(avatarPosition, position); + if (distance < range) { + return true; + } + } + return false; +} + AvatarWeakPointer AvatarHashMap::avatarWithDisplayName(const QString& displayName) { foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) { if (sharedAvatar->getDisplayName() == displayName) { diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index b59559e78c..b7d40e2acc 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -20,6 +20,7 @@ #include #include "AvatarData.h" +#include typedef QSharedPointer AvatarSharedPointer; typedef QWeakPointer AvatarWeakPointer; @@ -36,6 +37,7 @@ public: public slots: void processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer); bool containsAvatarWithDisplayName(const QString& displayName); + bool isAvatarInRange(const glm::vec3 & position, const float range); AvatarWeakPointer avatarWithDisplayName(const QString& displayname); private slots: From bfbad539e06a3881cf850cd9bcc4c7c0a0eeb786 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 28 Apr 2015 14:54:58 -0700 Subject: [PATCH 05/14] hack test --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cd7bedc19e..e588cb69f1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -166,7 +166,7 @@ void MyAvatar::simulate(float deltaTime) { if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); - Application::getInstance()->getCamera()->setScale(scale); + //Application::getInstance()->getCamera()->setScale(scale); } { From aec0bd16930adcb82d22beb6aa48a2bb9c98fe0e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 28 Apr 2015 16:26:17 -0700 Subject: [PATCH 06/14] dont change camera scale with avatar scale --- interface/src/avatar/MyAvatar.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e588cb69f1..60a760b2a8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -166,7 +166,6 @@ void MyAvatar::simulate(float deltaTime) { if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); - //Application::getInstance()->getCamera()->setScale(scale); } { From 664d1264653261f6ccee8049c50f1160eaf95d72 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 28 Apr 2015 16:34:33 -0700 Subject: [PATCH 07/14] remove scale from Camera class since it was only used by avatar and was causing problems with no obvious benefit --- interface/src/Camera.cpp | 5 ++--- interface/src/Camera.h | 5 +---- interface/src/avatar/MyAvatar.cpp | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e334fd7c65..6c6d165e7d 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -55,7 +55,6 @@ Camera::Camera() : _farClip(DEFAULT_FAR_CLIP), // default _hmdPosition(), _hmdRotation(), - _scale(1.0f), _isKeepLookingAt(false), _lookingAt(0.0f, 0.0f, 0.0f) { @@ -94,8 +93,8 @@ void Camera::setHmdRotation(const glm::quat& hmdRotation) { } float Camera::getFarClip() const { - return (_scale * _farClip < std::numeric_limits::max()) - ? _scale * _farClip + return (_farClip < std::numeric_limits::max()) + ? _farClip : std::numeric_limits::max() - 1; } diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 7c6951b920..10572d3513 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -54,7 +54,6 @@ public: void setFarClip(float f); void setEyeOffsetPosition(const glm::vec3& p) { _eyeOffsetPosition = p; } void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; } - void setScale(const float s) { _scale = s; } glm::quat getRotation() const { return _rotation * _hmdRotation; } const glm::vec3& getHmdPosition() const { return _hmdPosition; } @@ -63,11 +62,10 @@ public: CameraMode getMode() const { return _mode; } float getFieldOfView() const { return _fieldOfView; } float getAspectRatio() const { return _aspectRatio; } - float getNearClip() const { return _scale * _nearClip; } + float getNearClip() const { return _nearClip; } float getFarClip() const; const glm::vec3& getEyeOffsetPosition() const { return _eyeOffsetPosition; } const glm::quat& getEyeOffsetOrientation() const { return _eyeOffsetOrientation; } - float getScale() const { return _scale; } public slots: QString getModeString() const; void setModeString(const QString& mode); @@ -107,7 +105,6 @@ private: glm::quat _rotation; glm::vec3 _hmdPosition; glm::quat _hmdRotation; - float _scale; bool _isKeepLookingAt; glm::vec3 _lookingAt; }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 60a760b2a8..557d630ebf 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -672,8 +672,6 @@ void MyAvatar::loadData() { _leanScale = loadSetting(settings, "leanScale", 0.05f); _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); - Application::getInstance()->getCamera()->setScale(_scale); - // The old preferences only stored the face and skeleton URLs, we didn't track if the user wanted to use 1 or 2 urls // for their avatar, So we need to attempt to detect this old case and set our new preferences accordingly. If From f2dcacffd025a465333efdd4fd818b1af3767cef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Apr 2015 09:47:19 -0700 Subject: [PATCH 08/14] show avatar data receive rate by default with display name --- interface/src/avatar/Avatar.cpp | 16 ++++++++++++++-- libraries/avatars/src/AvatarData.cpp | 17 ++++++++++++----- libraries/avatars/src/AvatarData.h | 13 ++++++++----- libraries/avatars/src/AvatarHashMap.cpp | 4 ++-- libraries/shared/src/SimpleMovingAverage.cpp | 6 +++--- libraries/shared/src/SimpleMovingAverage.h | 7 +++++-- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3439317d8..94589623bf 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -581,7 +581,8 @@ void Avatar::renderBillboard() { glm::vec2 texCoordTopLeft(0.0f, 0.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f); - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); glPopMatrix(); @@ -709,11 +710,22 @@ void Avatar::renderDisplayName() { glm::vec4(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA)); glm::vec4 color(0.93f, 0.93f, 0.93f, _displayNameAlpha); + + // optionally render timing stats for this avatar with the display name + QString renderedDisplayName = _displayName; + + const float BYTES_PER_KILOBYTE = 1000.0f; + float kilobytesPerSecond = getAverageBytesReceivedPerSecond() / BYTES_PER_KILOBYTE; + + renderedDisplayName += QString(" - (%1 KBps, %2 Hz)") + .arg(QString::number(kilobytesPerSecond, 'f', 2)) + .arg(getReceiveRate()); + QByteArray ba = _displayName.toLocal8Bit(); const char* text = ba.data(); glDisable(GL_POLYGON_OFFSET_FILL); - textRenderer(DISPLAYNAME)->draw(text_x, text_y, text, color); + textRenderer(DISPLAYNAME)->draw(text_x, text_y, renderedDisplayName, color); glPopMatrix(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a8d2c209c3..f0e4eb118b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -58,11 +58,11 @@ AvatarData::AvatarData() : _billboard(), _errorLogExpiry(0), _owningAvatarMixer(), - _lastUpdateTimer(), _velocity(0.0f), _targetVelocity(0.0f), _localAABox(DEFAULT_LOCAL_AABOX_CORNER, DEFAULT_LOCAL_AABOX_SCALE) { + } AvatarData::~AvatarData() { @@ -268,9 +268,6 @@ bool AvatarData::shouldLogError(const quint64& now) { // read data in packet starting at byte offset and return number of bytes parsed int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { - // reset the last heard timer since we have new data for this AvatarData - _lastUpdateTimer.restart(); - // lazily allocate memory for HeadData in case we're not an Avatar instance if (!_headData) { _headData = new HeadData(this); @@ -555,7 +552,17 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { } } // numJoints * 8 bytes - return sourceBuffer - startPosition; + int numBytesRead = sourceBuffer - startPosition; + _averageBytesReceived.updateAverage(numBytesRead); + return numBytesRead; +} + +int AvatarData::getAverageBytesReceivedPerSecond() const { + return lrint(_averageBytesReceived.getAverageSampleValuePerSecond()); +} + +int AvatarData::getReceiveRate() const { + return lrint(1.0f / _averageBytesReceived.getEventDeltaAverage()); } bool AvatarData::hasReferential() { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 58e9c42c3c..0aa911112a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -46,9 +46,9 @@ typedef unsigned long long quint64; #include #include -#include - #include +#include +#include #include "AABox.h" #include "HandData.h" @@ -293,11 +293,13 @@ public: Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); } void setOwningAvatarMixer(const QWeakPointer& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; } - QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; } - const AABox& getLocalAABox() const { return _localAABox; } const Referential* getReferential() const { return _referential; } + int getUsecsSinceLastUpdate() const { return _averageBytesReceived.getUsecsSinceLastEvent(); } + int getAverageBytesReceivedPerSecond() const; + int getReceiveRate() const; + void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; } glm::vec3 getTargetVelocity() const { return _targetVelocity; } @@ -382,7 +384,6 @@ protected: quint64 _errorLogExpiry; ///< time in future when to log an error QWeakPointer _owningAvatarMixer; - QElapsedTimer _lastUpdateTimer; PlayerPointer _player; @@ -395,6 +396,8 @@ protected: AABox _localAABox; + SimpleMovingAverage _averageBytesReceived {}; + private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index ae3a8c3e5c..3e913acbd7 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -25,11 +25,11 @@ AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) return _avatarHash.erase(iterator); } -const qint64 AVATAR_SILENCE_THRESHOLD_MSECS = 5 * 1000; +const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * 1000 * 1000; bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) { return (sharedAvatar->getOwningAvatarMixer() == NULL - || sharedAvatar->getLastUpdateTimer().elapsed() > AVATAR_SILENCE_THRESHOLD_MSECS); + || sharedAvatar->getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS); } void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer) { diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index 90a9509c91..1d2574ecbf 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -52,9 +52,9 @@ void SimpleMovingAverage::reset() { float SimpleMovingAverage::getEventDeltaAverage() const { return (ONE_MINUS_WEIGHTING * _eventDeltaAverage) + - (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f)); + (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f )); } -float SimpleMovingAverage::getAverageSampleValuePerSecond() const { - return _average * (1.0f / getEventDeltaAverage()); +uint64_t SimpleMovingAverage::getUsecsSinceLastEvent() const { + return usecTimestampNow() - _lastEventTimestamp; } diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index 3eec9d5be8..4233411466 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -25,8 +25,11 @@ public: int getSampleCount() const { return _numSamples; }; float getAverage() const { return _average; }; - float getEventDeltaAverage() const; - float getAverageSampleValuePerSecond() const; + float getEventDeltaAverage() const; // returned in microseconds + float getAverageSampleValuePerSecond() const { return _average * (1.0f / getEventDeltaAverage()); } + + uint64_t getUsecsSinceLastEvent() const; + private: int _numSamples; uint64_t _lastEventTimestamp; From f9a25d7089483b0ff5804a058d757df80556a355 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Apr 2015 10:13:18 -0700 Subject: [PATCH 09/14] add Menu option to toggle Avatar receive stats --- interface/src/Menu.cpp | 7 ++++--- interface/src/Menu.h | 1 + interface/src/avatar/Avatar.cpp | 16 +++++++++------- interface/src/avatar/AvatarManager.h | 11 +++++++++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 868fa9270c..23f69b5e5b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -285,9 +285,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::OffAxisProjection, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false); - - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, - 0); // QML Qt::Key_Slash); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats); addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L, @@ -397,6 +394,10 @@ Menu::Menu() { QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true); ddeFiltering->setVisible(false); #endif + + auto avatarManager = DependencyManager::get(); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false, + avatarManager.data(), SLOT(setShouldShowReceiveStats(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 5b2d1430a6..62b6ac5656 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -147,6 +147,7 @@ namespace MenuOption { const QString AudioScopeTwentyFrames = "Twenty"; const QString AudioStats = "Audio Stats"; const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams"; + const QString AvatarReceiveStats = "Show Receive Stats"; const QString BandwidthDetails = "Bandwidth Details"; const QString BlueSpeechSphere = "Blue Sphere While Speaking"; const QString BookmarkLocation = "Bookmark Location"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 94589623bf..05f834255c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -713,14 +713,16 @@ void Avatar::renderDisplayName() { // optionally render timing stats for this avatar with the display name QString renderedDisplayName = _displayName; - - const float BYTES_PER_KILOBYTE = 1000.0f; - float kilobytesPerSecond = getAverageBytesReceivedPerSecond() / BYTES_PER_KILOBYTE; - renderedDisplayName += QString(" - (%1 KBps, %2 Hz)") - .arg(QString::number(kilobytesPerSecond, 'f', 2)) - .arg(getReceiveRate()); - + if (DependencyManager::get()->shouldShowReceiveStats()) { + const float BYTES_PER_KILOBYTE = 1000.0f; + float kilobytesPerSecond = getAverageBytesReceivedPerSecond() / BYTES_PER_KILOBYTE; + + renderedDisplayName += QString(" - (%1 KBps, %2 Hz)") + .arg(QString::number(kilobytesPerSecond, 'f', 2)) + .arg(getReceiveRate()); + } + QByteArray ba = _displayName.toLocal8Bit(); const char* text = ba.data(); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 1a833c5106..3c7f7296fe 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -40,7 +40,9 @@ public: void renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false); void clearOtherAvatars(); - + + bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } + class LocalLight { public: glm::vec3 color; @@ -49,7 +51,10 @@ public: Q_INVOKABLE void setLocalLights(const QVector& localLights); Q_INVOKABLE QVector getLocalLights() const; - + +public slots: + void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } + private: AvatarManager(QObject* parent = 0); AvatarManager(const AvatarManager& other); @@ -67,6 +72,8 @@ private: quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate. QVector _localLights; + + bool _shouldShowReceiveStats = false; }; Q_DECLARE_METATYPE(AvatarManager::LocalLight) From c52426385dbfd8252891b4842296d2363f9f5eaa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Apr 2015 18:20:54 -0700 Subject: [PATCH 10/14] code review comments for #4713 --- libraries/avatars/src/AvatarHashMap.cpp | 3 ++- libraries/shared/src/SimpleMovingAverage.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 3e913acbd7..a78d91fc43 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "AvatarLogging.h" #include "AvatarHashMap.h" @@ -25,7 +26,7 @@ AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) return _avatarHash.erase(iterator); } -const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * 1000 * 1000; +const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * USECS_PER_SECOND; bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) { return (sharedAvatar->getOwningAvatarMixer() == NULL diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index 1d2574ecbf..e1c9a27390 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -52,7 +52,7 @@ void SimpleMovingAverage::reset() { float SimpleMovingAverage::getEventDeltaAverage() const { return (ONE_MINUS_WEIGHTING * _eventDeltaAverage) + - (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f )); + (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f)); } uint64_t SimpleMovingAverage::getUsecsSinceLastEvent() const { From 1995fa6a5ee53fe3d58e8cb8179372334114f811 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Apr 2015 18:21:15 -0700 Subject: [PATCH 11/14] fix return value comment in SimpleMovingAverage --- libraries/shared/src/SimpleMovingAverage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index 4233411466..194a078194 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -25,7 +25,7 @@ public: int getSampleCount() const { return _numSamples; }; float getAverage() const { return _average; }; - float getEventDeltaAverage() const; // returned in microseconds + float getEventDeltaAverage() const; // returned in seconds float getAverageSampleValuePerSecond() const { return _average * (1.0f / getEventDeltaAverage()); } uint64_t getUsecsSinceLastEvent() const; From 61b4025526e798318f226912f26e5bbff46832fb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 29 Apr 2015 09:33:23 -0700 Subject: [PATCH 12/14] remove the uneeded curly braces for default ctor --- libraries/avatars/src/AvatarData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 0aa911112a..6a11f94cb6 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -396,7 +396,7 @@ protected: AABox _localAABox; - SimpleMovingAverage _averageBytesReceived {}; + SimpleMovingAverage _averageBytesReceived; private: // privatize the copy constructor and assignment operator so they cannot be called From 36a26ad416077bfae082f50cd5224a7a1d6bd6ea Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 29 Apr 2015 09:58:54 -0700 Subject: [PATCH 13/14] update BUILD.md for new OpenSSL req --- BUILD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index 0de8d32b82..a5ee32262f 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,8 +2,8 @@ * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 * [Qt](http://www.qt.io/download-open-source) ~> 5.4.1 -* [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g - * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. +* [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1m + * IMPORTANT: Using the recommended version of OpenSSL is critical to avoid security vulnerabilities. * [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) ####CMake External Project Dependencies From e933ab2e84d3a59eae9bca0deca33170133e9d65 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 29 Apr 2015 09:59:20 -0700 Subject: [PATCH 14/14] update win required version of OpenSSL --- BUILD_WIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 80b8c35502..169077ed78 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -71,7 +71,7 @@ Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html): * Visual C++ 2008 Redistributables -* Win32 OpenSSL v1.0.1L +* Win32 OpenSSL v1.0.1m Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.