From 2f51e635543a731fbd267eb810ce2a12c6757e3f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 7 Mar 2017 01:29:20 +0100 Subject: [PATCH 01/47] Since the deck is currently only capable of handling one clip, add temporary _length reset in FIXME section --- libraries/recording/src/recording/Deck.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index 61eb86c91f..5a32ff4984 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -33,6 +33,7 @@ void Deck::queueClip(ClipPointer clip, float timeOffset) { // FIXME disabling multiple clips for now _clips.clear(); + _length = 0.0f; // if the time offset is not zero, wrap in an OffsetClip if (timeOffset != 0.0f) { From b54d6cb0e1fda141c8c81749ef1a35b78b31df3f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Mar 2017 00:07:49 +0100 Subject: [PATCH 02/47] stop avatar controller while playing back a recording, which makes it not collide anymore --- interface/src/avatar/MyAvatar.cpp | 3 +++ interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 4 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 969268c549..318608e3a8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -154,9 +154,12 @@ MyAvatar::MyAvatar(RigPointer rig) : if (recordingInterface->getPlayFromCurrentLocation()) { setRecordingBasis(); } + _wasCharacterControllerEnabled = _characterController.isEnabled(); + _characterController.setEnabled(false); } else { clearRecordingBasis(); useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); + _characterController.setEnabled(_wasCharacterControllerEnabled); } auto audioIO = DependencyManager::get(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3cc665b533..00923e78cc 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -411,6 +411,7 @@ private: SharedSoundPointer _collisionSound; MyCharacterController _characterController; + bool _wasCharacterControllerEnabled { true }; AvatarWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; From b954d5b0e94276d752b14ab4ca4fb321d826784a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Mar 2017 00:08:57 +0100 Subject: [PATCH 03/47] stop the playback after the clip stopped playing rather than pause. Allows you to click play again without having to move the position back. --- libraries/recording/src/recording/Deck.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index 5a32ff4984..186516e01c 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -154,8 +154,8 @@ void Deck::processFrames() { // if doing relative movement emit looped(); } else { - // otherwise pause playback - pause(); + // otherwise stop playback + stop(); } return; } From 6b26f5f3a30595f2b16389800fe3325ded88b616 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Mar 2017 00:09:56 +0100 Subject: [PATCH 04/47] Fix the timer display --- .../developer/utilities/record/recorder.js | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/scripts/developer/utilities/record/recorder.js b/scripts/developer/utilities/record/recorder.js index 0e335116d5..7338105483 100644 --- a/scripts/developer/utilities/record/recorder.js +++ b/scripts/developer/utilities/record/recorder.js @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* globals HIFI_PUBLIC_BUCKET:true, Tool, ToolBar */ + HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; Script.include("/~/system/libraries/toolBars.js"); @@ -47,7 +49,7 @@ setupTimer(); var watchStop = false; function setupToolBar() { - if (toolBar != null) { + if (toolBar !== null) { print("Multiple calls to Recorder.js:setupToolBar()"); return; } @@ -112,15 +114,15 @@ function setupTimer() { text: (0.00).toFixed(3), backgroundColor: COLOR_OFF, x: 0, y: 0, - width: 0, height: 0, - leftMargin: 10, topMargin: 10, + width: 200, height: 37, + leftMargin: 5, topMargin: 10, alpha: 1.0, backgroundAlpha: 1.0, visible: true }); slider = { x: 0, y: 0, w: 200, h: 20, - pos: 0.0, // 0.0 <= pos <= 1.0 + pos: 0.0 // 0.0 <= pos <= 1.0 }; slider.background = Overlays.addOverlay("text", { text: "", @@ -148,16 +150,17 @@ function updateTimer() { var text = ""; if (Recording.isRecording()) { text = formatTime(Recording.recorderElapsed()); - } else { - text = formatTime(Recording.playerElapsed()) + " / " + - formatTime(Recording.playerLength()); + text = formatTime(Recording.playerElapsed()) + " / " + formatTime(Recording.playerLength()); } + var timerWidth = text.length * 8 + ((Recording.isRecording()) ? 15 : 0); + Overlays.editOverlay(timer, { - text: text - }) - toolBar.changeSpacing(text.length * 8 + ((Recording.isRecording()) ? 15 : 0), spacing); + text: text, + width: timerWidth + }); + toolBar.changeSpacing(timerWidth, spacing); if (Recording.isRecording()) { slider.pos = 1.0; @@ -173,7 +176,7 @@ function updateTimer() { function formatTime(time) { var MIN_PER_HOUR = 60; var SEC_PER_MIN = 60; - var MSEC_PER_SEC = 1000; + var MSEC_DIGITS = 3; var hours = Math.floor(time / (SEC_PER_MIN * MIN_PER_HOUR)); time -= hours * (SEC_PER_MIN * MIN_PER_HOUR); @@ -184,11 +187,9 @@ function formatTime(time) { var seconds = time; var text = ""; - text += (hours > 0) ? hours + ":" : - ""; - text += (minutes > 0) ? ((minutes < 10 && text != "") ? "0" : "") + minutes + ":" : - ""; - text += ((seconds < 10 && text != "") ? "0" : "") + seconds.toFixed(3); + text += (hours > 0) ? hours + ":" : ""; + text += (minutes > 0) ? ((minutes < 10 && text !== "") ? "0" : "") + minutes + ":" : ""; + text += ((seconds < 10 && text !== "") ? "0" : "") + seconds.toFixed(MSEC_DIGITS); return text; } @@ -205,16 +206,16 @@ function moveUI() { Overlays.editOverlay(slider.background, { x: slider.x, - y: slider.y, + y: slider.y }); Overlays.editOverlay(slider.foreground, { x: slider.x, - y: slider.y, + y: slider.y }); } function mousePressEvent(event) { - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); if (recordIcon === toolBar.clicked(clickedOverlay, false) && !Recording.isPlaying()) { if (!Recording.isRecording()) { @@ -226,7 +227,8 @@ function mousePressEvent(event) { toolBar.setAlpha(ALPHA_OFF, loadIcon); } else { Recording.stopRecording(); - toolBar.selectTool(recordIcon, true ); + toolBar.selectTool(recordIcon, true); + Recording.setPlayerTime(0); Recording.loadLastRecording(); toolBar.setAlpha(ALPHA_ON, playIcon); toolBar.setAlpha(ALPHA_ON, playLoopIcon); @@ -263,7 +265,7 @@ function mousePressEvent(event) { toolBar.setAlpha(ALPHA_OFF, loadIcon); } } else if (saveIcon === toolBar.clicked(clickedOverlay)) { - if (!Recording.isRecording() && !Recording.isPlaying() && Recording.playerLength() != 0) { + if (!Recording.isRecording() && !Recording.isPlaying() && Recording.playerLength() !== 0) { recordingFile = Window.save("Save recording to file", ".", "Recordings (*.hfr)"); if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { Recording.saveRecording(recordingFile); @@ -282,8 +284,8 @@ function mousePressEvent(event) { } } } else if (Recording.playerLength() > 0 && - slider.x < event.x && event.x < slider.x + slider.w && - slider.y < event.y && event.y < slider.y + slider.h) { + slider.x < event.x && event.x < slider.x + slider.w && + slider.y < event.y && event.y < slider.y + slider.h) { isSliding = true; slider.pos = (event.x - slider.x) / slider.w; Recording.setPlayerTime(slider.pos * Recording.playerLength()); @@ -308,7 +310,7 @@ function mouseReleaseEvent(event) { function update() { var newDimensions = Controller.getViewportDimensions(); - if (windowDimensions.x != newDimensions.x || windowDimensions.y != newDimensions.y) { + if (windowDimensions.x !== newDimensions.x || windowDimensions.y !== newDimensions.y) { windowDimensions = newDimensions; moveUI(); } From b21bd3afa9d22cd87ce2193493ddee3c65789e51 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Mar 2017 01:14:11 +0100 Subject: [PATCH 05/47] Make the time and slider follow the record.js toolbar --- .../developer/utilities/record/recorder.js | 50 +++++++++++-------- scripts/system/libraries/toolBars.js | 4 ++ 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/scripts/developer/utilities/record/recorder.js b/scripts/developer/utilities/record/recorder.js index 7338105483..dcbbe2145f 100644 --- a/scripts/developer/utilities/record/recorder.js +++ b/scripts/developer/utilities/record/recorder.js @@ -16,7 +16,7 @@ Script.include("/~/system/libraries/toolBars.js"); var recordingFile = "recording.hfr"; -function setPlayerOptions() { +function setDefaultPlayerOptions() { Recording.setPlayFromCurrentLocation(true); Recording.setPlayerUseDisplayName(false); Recording.setPlayerUseAttachments(false); @@ -40,10 +40,10 @@ var saveIcon; var loadIcon; var spacing; var timerOffset; -setupToolBar(); - var timer = null; var slider = null; + +setupToolBar(); setupTimer(); var watchStop = false; @@ -58,6 +58,8 @@ function setupToolBar() { toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); + toolBar.onMove = onToolbarMove; + toolBar.setBack(COLOR_TOOL_BAR, ALPHA_OFF); recordIcon = toolBar.addTool({ @@ -146,6 +148,26 @@ function setupTimer() { }); } +function onToolbarMove(newX, newY, deltaX, deltaY) { + print(newX); + Overlays.editOverlay(timer, { + x: newX + timerOffset - ToolBar.SPACING, + y: newY - ToolBar.SPACING + }); + + slider.x = newX - ToolBar.SPACING; + slider.y = newY - slider.h - ToolBar.SPACING; + + Overlays.editOverlay(slider.background, { + x: slider.x, + y: slider.y + }); + Overlays.editOverlay(slider.foreground, { + x: slider.x, + y: slider.y + }); +} + function updateTimer() { var text = ""; if (Recording.isRecording()) { @@ -196,22 +218,6 @@ function formatTime(time) { function moveUI() { var relative = { x: 70, y: 40 }; toolBar.move(relative.x, windowDimensions.y - relative.y); - Overlays.editOverlay(timer, { - x: relative.x + timerOffset - ToolBar.SPACING, - y: windowDimensions.y - relative.y - ToolBar.SPACING - }); - - slider.x = relative.x - ToolBar.SPACING; - slider.y = windowDimensions.y - relative.y - slider.h - ToolBar.SPACING; - - Overlays.editOverlay(slider.background, { - x: slider.x, - y: slider.y - }); - Overlays.editOverlay(slider.foreground, { - x: slider.x, - y: slider.y - }); } function mousePressEvent(event) { @@ -228,6 +234,9 @@ function mousePressEvent(event) { } else { Recording.stopRecording(); toolBar.selectTool(recordIcon, true); + setDefaultPlayerOptions(); + // Plays the recording at the same spot as you recorded it + Recording.setPlayFromCurrentLocation(false); Recording.setPlayerTime(0); Recording.loadLastRecording(); toolBar.setAlpha(ALPHA_ON, playIcon); @@ -242,7 +251,6 @@ function mousePressEvent(event) { toolBar.setAlpha(ALPHA_ON, saveIcon); toolBar.setAlpha(ALPHA_ON, loadIcon); } else if (Recording.playerLength() > 0) { - setPlayerOptions(); Recording.setPlayerLoop(false); Recording.startPlaying(); toolBar.setAlpha(ALPHA_OFF, recordIcon); @@ -257,7 +265,6 @@ function mousePressEvent(event) { toolBar.setAlpha(ALPHA_ON, saveIcon); toolBar.setAlpha(ALPHA_ON, loadIcon); } else if (Recording.playerLength() > 0) { - setPlayerOptions(); Recording.setPlayerLoop(true); Recording.startPlaying(); toolBar.setAlpha(ALPHA_OFF, recordIcon); @@ -276,6 +283,7 @@ function mousePressEvent(event) { recordingFile = Window.browse("Load recording from file", ".", "Recordings (*.hfr *.rec *.HFR *.REC)"); if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { Recording.loadRecording(recordingFile); + setDefaultPlayerOptions(); } if (Recording.playerLength() > 0) { toolBar.setAlpha(ALPHA_ON, playIcon); diff --git a/scripts/system/libraries/toolBars.js b/scripts/system/libraries/toolBars.js index e49f8c4004..351f10e7bd 100644 --- a/scripts/system/libraries/toolBars.js +++ b/scripts/system/libraries/toolBars.js @@ -160,6 +160,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit visible: false }); this.spacing = []; + this.onMove = null; this.addTool = function(properties, selectable, selected) { if (direction == ToolBar.HORIZONTAL) { @@ -254,6 +255,9 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit y: y - ToolBar.SPACING }); } + if (this.onMove !== null) { + this.onMove(x, y, dx, dy); + }; } this.setAlpha = function(alpha, tool) { From 097db9a7f98bbab309cf30033e26c4b2d461df17 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Mar 2017 01:41:20 +0100 Subject: [PATCH 06/47] - debug message removal (oops) - smaller timer textbox, allows you to grab around the edges and still drag the toolbar --- scripts/developer/utilities/record/recorder.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/record/recorder.js b/scripts/developer/utilities/record/recorder.js index dcbbe2145f..ba1c8b0393 100644 --- a/scripts/developer/utilities/record/recorder.js +++ b/scripts/developer/utilities/record/recorder.js @@ -90,7 +90,7 @@ function setupToolBar() { visible: true }, false); - timerOffset = toolBar.width; + timerOffset = toolBar.width + ToolBar.SPACING; spacing = toolBar.addSpacing(0); saveIcon = toolBar.addTool({ @@ -116,8 +116,8 @@ function setupTimer() { text: (0.00).toFixed(3), backgroundColor: COLOR_OFF, x: 0, y: 0, - width: 200, height: 37, - leftMargin: 5, topMargin: 10, + width: 200, height: 25, + leftMargin: 5, topMargin: 3, alpha: 1.0, backgroundAlpha: 1.0, visible: true }); @@ -149,10 +149,9 @@ function setupTimer() { } function onToolbarMove(newX, newY, deltaX, deltaY) { - print(newX); Overlays.editOverlay(timer, { x: newX + timerOffset - ToolBar.SPACING, - y: newY - ToolBar.SPACING + y: newY }); slider.x = newX - ToolBar.SPACING; @@ -182,7 +181,7 @@ function updateTimer() { text: text, width: timerWidth }); - toolBar.changeSpacing(timerWidth, spacing); + toolBar.changeSpacing(timerWidth + ToolBar.SPACING, spacing); if (Recording.isRecording()) { slider.pos = 1.0; From 8bf9b70915002ca49b8ad100164ddd108c70093f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:33 -0800 Subject: [PATCH 07/47] Revert "don't blend animations for otherAvatars" This reverts commit faa272c67c103e36b5324ecc8eb14bb18e773745. --- interface/src/avatar/CauterizedModel.cpp | 6 ++ interface/src/avatar/CauterizedModel.h | 1 + interface/src/avatar/SkeletonModel.cpp | 4 +- libraries/animation/src/Rig.cpp | 71 ++++++++++-------------- 4 files changed, 39 insertions(+), 43 deletions(-) diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index 0c3d863649..843779dd3b 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -95,6 +95,12 @@ void CauterizedModel::createCollisionRenderItemSet() { Model::createCollisionRenderItemSet(); } +// Called within Model::simulate call, below. +void CauterizedModel::updateRig(float deltaTime, glm::mat4 parentTransform) { + Model::updateRig(deltaTime, parentTransform); + _needsUpdateClusterMatrices = true; +} + void CauterizedModel::updateClusterMatrices() { PerformanceTimer perfTimer("CauterizedModel::updateClusterMatrices"); diff --git a/interface/src/avatar/CauterizedModel.h b/interface/src/avatar/CauterizedModel.h index ba12aee32b..01e0b13650 100644 --- a/interface/src/avatar/CauterizedModel.h +++ b/interface/src/avatar/CauterizedModel.h @@ -37,6 +37,7 @@ public: void createVisibleRenderItemSet() override; void createCollisionRenderItemSet() override; + virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override; virtual void updateClusterMatrices() override; void updateRenderItems() override; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 88590a6f69..4b77323bba 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -166,7 +166,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState); // evaluate AnimGraph animation and update jointStates. - Model::updateRig(deltaTime, parentTransform); + CauterizedModel::updateRig(deltaTime, parentTransform); Rig::EyeParameters eyeParams; eyeParams.worldHeadOrientation = headParams.worldHeadOrientation; @@ -179,7 +179,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromEyeParameters(eyeParams); } else { - Model::updateRig(deltaTime, parentTransform); + CauterizedModel::updateRig(deltaTime, parentTransform); // This is a little more work than we really want. // diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 84e34adec7..c47da7c0b0 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1307,50 +1307,39 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { void Rig::copyJointsFromJointData(const QVector& jointDataVec) { PerformanceTimer perfTimer("copyJoints"); PROFILE_RANGE(simulation_animation_detail, "copyJoints"); - if (!_animSkeleton) { - return; - } - if (jointDataVec.size() != (int)_internalPoseSet._relativePoses.size()) { - // animations haven't fully loaded yet. - _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); - } + if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._relativePoses.size()) { + // make a vector of rotations in absolute-geometry-frame + const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); + std::vector rotations; + rotations.reserve(absoluteDefaultPoses.size()); + const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); + for (int i = 0; i < jointDataVec.size(); i++) { + const JointData& data = jointDataVec.at(i); + if (data.rotationSet) { + // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame + rotations.push_back(rigToGeometryRot * data.rotation); + } else { + rotations.push_back(absoluteDefaultPoses[i].rot()); + } + } - // make a vector of rotations in absolute-geometry-frame - const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); - std::vector rotations; - rotations.reserve(absoluteDefaultPoses.size()); - const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); - for (int i = 0; i < jointDataVec.size(); i++) { - const JointData& data = jointDataVec.at(i); - if (data.rotationSet) { - // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame - rotations.push_back(rigToGeometryRot * data.rotation); - } else { - rotations.push_back(absoluteDefaultPoses[i].rot()); + // convert rotations from absolute to parent relative. + _animSkeleton->convertAbsoluteRotationsToRelative(rotations); + + // store new relative poses + const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); + for (int i = 0; i < jointDataVec.size(); i++) { + const JointData& data = jointDataVec.at(i); + _internalPoseSet._relativePoses[i].scale() = Vectors::ONE; + _internalPoseSet._relativePoses[i].rot() = rotations[i]; + if (data.translationSet) { + // JointData translations are in scaled relative-frame so we scale back to regular relative-frame + _internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation; + } else { + _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans(); + } } } - - // convert rotations from absolute to parent relative. - _animSkeleton->convertAbsoluteRotationsToRelative(rotations); - - // store new relative poses - const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); - for (int i = 0; i < jointDataVec.size(); i++) { - const JointData& data = jointDataVec.at(i); - _internalPoseSet._relativePoses[i].scale() = Vectors::ONE; - _internalPoseSet._relativePoses[i].rot() = rotations[i]; - if (data.translationSet) { - // JointData translations are in scaled relative-frame so we scale back to regular relative-frame - _internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation; - } else { - _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans(); - } - } - - // build absolute poses and copy to externalPoseSet - buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); - QWriteLocker writeLock(&_externalPoseSetLock); - _externalPoseSet = _internalPoseSet; } void Rig::computeAvatarBoundingCapsule( From 9a9f07df7111322e21371ffa4938b4691b235c24 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:48 -0800 Subject: [PATCH 08/47] Revert "expand avatar update time budget" This reverts commit 4bbbcb61be14c8233987941ad1fc89d4a6934e32. --- interface/src/avatar/AvatarManager.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7417f73102..6b426bcde8 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -157,6 +157,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { lock.unlock(); PerformanceTimer perfTimer("otherAvatars"); + uint64_t startTime = usecTimestampNow(); auto avatarMap = getHashCopy(); QList avatarList = avatarMap.values(); @@ -193,9 +194,10 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { }); render::PendingChanges pendingChanges; - uint64_t startTime = usecTimestampNow(); - const uint64_t UPDATE_BUDGET = 2000; // usec - uint64_t updateExpiry = startTime + UPDATE_BUDGET; + const uint64_t RENDER_UPDATE_BUDGET = 1500; // usec + const uint64_t MAX_UPDATE_BUDGET = 2000; // usec + uint64_t renderExpiry = startTime + RENDER_UPDATE_BUDGET; + uint64_t maxExpiry = startTime + MAX_UPDATE_BUDGET; int numAvatarsUpdated = 0; int numAVatarsNotUpdated = 0; @@ -221,7 +223,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float OUT_OF_VIEW_THRESHOLD = 0.5f * AvatarData::OUT_OF_VIEW_PENALTY; uint64_t now = usecTimestampNow(); - if (now < updateExpiry) { + if (now < renderExpiry) { // we're within budget bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; if (inView && avatar->hasNewJointData()) { @@ -230,13 +232,21 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { avatar->simulate(deltaTime, inView); avatar->updateRenderItem(pendingChanges); avatar->setLastRenderUpdateTime(startTime); + } else if (now < maxExpiry) { + // we've spent most of our time budget, but we still simulate() the avatar as it if were out of view + // --> some avatars may freeze until their priority trickles up + bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; + if (inView && avatar->hasNewJointData()) { + numAVatarsNotUpdated++; + } + avatar->simulate(deltaTime, false); } else { - // we've spent our full time budget --> bail on the rest of the avatar updates + // we've spent ALL of our time budget --> bail on the rest of the avatar updates // --> more avatars may freeze until their priority trickles up // --> some scale or fade animations may glitch // --> some avatar velocity measurements may be a little off - // no time simulate, but we take the time to count how many were tragically missed + // HACK: no time simulate, but we will take the time to count how many were tragically missed bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; if (!inView) { break; From 188287e345ff43dcc11c79bf20376fba775d5699 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:52 -0800 Subject: [PATCH 09/47] Revert "minor cleanup" This reverts commit 14e7392a89e3291891bb00bdb44349995f0aeac1. --- interface/src/avatar/Avatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6e1f44f5ac..f5fe82ef4b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -351,6 +351,7 @@ void Avatar::simulate(float deltaTime, bool inView) { _jointDataSimulationRate.increment(); _skeletonModel->simulate(deltaTime, true); + _skeletonModelSimulationRate.increment(); locationChanged(); // joints changed, so if there are any children, update them. _hasNewJointData = false; @@ -366,8 +367,8 @@ void Avatar::simulate(float deltaTime, bool inView) { } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. _skeletonModel->simulate(deltaTime, false); + _skeletonModelSimulationRate.increment(); } - _skeletonModelSimulationRate.increment(); } // update animation for display name fade in/out From a68674adccedab1004e1dbc0ec9e811eb5f2d4b4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:54 -0800 Subject: [PATCH 10/47] Revert "remove unnecessary context brackets" This reverts commit 0657ca1e5e4096daa30e28791e10f5aa05ca48c8. --- libraries/avatars/src/AvatarData.cpp | 78 ++++++++++++++-------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8025c680ca..6e4553ff8a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2332,48 +2332,50 @@ void AvatarData::sortAvatars( std::function getBoundingRadius, std::function shouldIgnore) { - PROFILE_RANGE(simulation, "sort"); - uint64_t now = usecTimestampNow(); + { + PROFILE_RANGE(simulation, "sort"); + uint64_t now = usecTimestampNow(); - glm::vec3 frustumCenter = cameraView.getPosition(); - const glm::vec3& forward = cameraView.getDirection(); - for (int32_t i = 0; i < avatarList.size(); ++i) { - const auto& avatar = avatarList.at(i); + glm::vec3 frustumCenter = cameraView.getPosition(); + const glm::vec3& forward = cameraView.getDirection(); + for (int32_t i = 0; i < avatarList.size(); ++i) { + const auto& avatar = avatarList.at(i); - if (shouldIgnore(avatar)) { - continue; - } - - // priority = weighted linear combination of: - // (a) apparentSize - // (b) proximity to center of view - // (c) time since last update - glm::vec3 avatarPosition = avatar->getPosition(); - glm::vec3 offset = avatarPosition - frustumCenter; - float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero - - // FIXME - AvatarData has something equivolent to this - float radius = getBoundingRadius(avatar); - - float apparentSize = 2.0f * radius / distance; - float cosineAngle = glm::dot(offset, forward) / distance; - float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); - - // NOTE: we are adding values of different units to get a single measure of "priority". - // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. - // These weights are pure magic tuning and should be hard coded in the relation below, - // but are currently exposed for anyone who would like to explore fine tuning: - float priority = _avatarSortCoefficientSize * apparentSize - + _avatarSortCoefficientCenter * cosineAngle - + _avatarSortCoefficientAge * age; - - // decrement priority of avatars outside keyhole - if (distance > cameraView.getCenterRadius()) { - if (!cameraView.sphereIntersectsFrustum(avatarPosition, radius)) { - priority += OUT_OF_VIEW_PENALTY; + if (shouldIgnore(avatar)) { + continue; } + + // priority = weighted linear combination of: + // (a) apparentSize + // (b) proximity to center of view + // (c) time since last update + glm::vec3 avatarPosition = avatar->getPosition(); + glm::vec3 offset = avatarPosition - frustumCenter; + float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero + + // FIXME - AvatarData has something equivolent to this + float radius = getBoundingRadius(avatar); + + float apparentSize = 2.0f * radius / distance; + float cosineAngle = glm::dot(offset, forward) / distance; + float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); + + // NOTE: we are adding values of different units to get a single measure of "priority". + // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. + // These weights are pure magic tuning and should be hard coded in the relation below, + // but are currently exposed for anyone who would like to explore fine tuning: + float priority = _avatarSortCoefficientSize * apparentSize + + _avatarSortCoefficientCenter * cosineAngle + + _avatarSortCoefficientAge * age; + + // decrement priority of avatars outside keyhole + if (distance > cameraView.getCenterRadius()) { + if (!cameraView.sphereIntersectsFrustum(avatarPosition, radius)) { + priority += OUT_OF_VIEW_PENALTY; + } + } + sortedAvatarsOut.push(AvatarPriority(avatar, priority)); } - sortedAvatarsOut.push(AvatarPriority(avatar, priority)); } } From 50288bd4ba3591aa0cffadfc994606143f349ea5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:56 -0800 Subject: [PATCH 11/47] Revert "remove unused variable" This reverts commit 92a32b46512094c1acd82fcd6c65c1d6ee49713b. --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 49b4b1ced4..584d3d0e6a 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -168,6 +168,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { QList avatarList; std::unordered_map avatarDataToNodes; + int listItem = 0; std::for_each(_begin, _end, [&](const SharedNodePointer& otherNode) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); @@ -175,6 +176,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // but not have yet sent data that's linked to the node. Check for that case and don't // consider those nodes. if (otherNodeData) { + listItem++; AvatarSharedPointer otherAvatar = otherNodeData->getAvatarSharedPointer(); avatarList << otherAvatar; avatarDataToNodes[otherAvatar] = otherNode; From 97c376a09c99f567b0fa90abd490eb542cd93c42 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:08:58 -0800 Subject: [PATCH 12/47] Revert "avoid unnecessary copy of priority_queue" This reverts commit e54812430e871190fca541e2d3d744aee5e997d3. --- .../src/avatars/AvatarMixerSlave.cpp | 4 +-- interface/src/avatar/AvatarManager.cpp | 4 +-- libraries/avatars/src/AvatarData.cpp | 28 ++++++++++--------- libraries/avatars/src/AvatarData.h | 3 +- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 584d3d0e6a..dd25aa4c4b 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -185,8 +185,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); - std::priority_queue sortedAvatars; - AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, + std::priority_queue sortedAvatars = AvatarData::sortAvatars( + avatarList, cameraView, [&](AvatarSharedPointer avatar)->uint64_t{ auto avatarNode = avatarDataToNodes[avatar]; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 6b426bcde8..d806c042b9 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -164,8 +164,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { ViewFrustum cameraView; qApp->copyDisplayViewFrustum(cameraView); - std::priority_queue sortedAvatars; - AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, + std::priority_queue sortedAvatars = AvatarData::sortAvatars( + avatarList, cameraView, [](AvatarSharedPointer avatar)->uint64_t{ return std::static_pointer_cast(avatar)->getLastRenderUpdateTime(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6e4553ff8a..e7ec201aa1 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2324,20 +2324,20 @@ float AvatarData::_avatarSortCoefficientSize { 0.5f }; float AvatarData::_avatarSortCoefficientCenter { 0.25 }; float AvatarData::_avatarSortCoefficientAge { 1.0f }; -void AvatarData::sortAvatars( - QList avatarList, - const ViewFrustum& cameraView, - std::priority_queue& sortedAvatarsOut, - std::function getLastUpdated, - std::function getBoundingRadius, - std::function shouldIgnore) { +std::priority_queue AvatarData::sortAvatars( + QList avatarList, + const ViewFrustum& cameraView, + std::function getLastUpdated, + std::function getBoundingRadius, + std::function shouldIgnore) { + uint64_t startTime = usecTimestampNow(); + + glm::vec3 frustumCenter = cameraView.getPosition(); + + std::priority_queue sortedAvatars; { PROFILE_RANGE(simulation, "sort"); - uint64_t now = usecTimestampNow(); - - glm::vec3 frustumCenter = cameraView.getPosition(); - const glm::vec3& forward = cameraView.getDirection(); for (int32_t i = 0; i < avatarList.size(); ++i) { const auto& avatar = avatarList.at(i); @@ -2356,9 +2356,10 @@ void AvatarData::sortAvatars( // FIXME - AvatarData has something equivolent to this float radius = getBoundingRadius(avatar); + const glm::vec3& forward = cameraView.getDirection(); float apparentSize = 2.0f * radius / distance; float cosineAngle = glm::dot(offset, forward) / distance; - float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); + float age = (float)(startTime - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); // NOTE: we are adding values of different units to get a single measure of "priority". // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. @@ -2374,9 +2375,10 @@ void AvatarData::sortAvatars( priority += OUT_OF_VIEW_PENALTY; } } - sortedAvatarsOut.push(AvatarPriority(avatar, priority)); + sortedAvatars.push(AvatarPriority(avatar, priority)); } } + return sortedAvatars; } QScriptValue AvatarEntityMapToScriptValue(QScriptEngine* engine, const AvatarEntityMap& value) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c2240f400f..12209d9c31 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -597,10 +597,9 @@ public: static const float OUT_OF_VIEW_PENALTY; - static void sortAvatars( + static std::priority_queue sortAvatars( QList avatarList, const ViewFrustum& cameraView, - std::priority_queue& sortedAvatarsOut, std::function getLastUpdated, std::function getBoundingRadius, std::function shouldIgnore); From a0befa7f958543445ffbc9d4a7975e92752cb127 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 8 Mar 2017 14:28:44 -0800 Subject: [PATCH 13/47] Trivial PR to trigger build --- interface/resources/qml/controls/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/controls/README.md b/interface/resources/qml/controls/README.md index 7f05f32a63..1245e42e97 100644 --- a/interface/resources/qml/controls/README.md +++ b/interface/resources/qml/controls/README.md @@ -1,2 +1,3 @@ These are our own custom controls with the same names as existing controls, but customized for readability / usability in VR. + From a974282bdfbf4a456c5255a3f2bd6e49835c6339 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 10 Mar 2017 11:55:36 -0800 Subject: [PATCH 14/47] bolding timestamps on log --- interface/resources/styles/log_dialog.qss | 4 +-- interface/src/ui/BaseLogDialog.cpp | 41 ++++++++++++++++++----- interface/src/ui/BaseLogDialog.h | 4 +-- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index 1fc4df0717..9ce5aeccc2 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -1,6 +1,6 @@ QPlainTextEdit { - font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; + font-family: Courier New, Courier, Monotype; font-size: 16px; padding-left: 28px; padding-top: 7px; @@ -11,7 +11,7 @@ QPlainTextEdit { } QLineEdit { - font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; + font-family: Courier New, Courier, Monotype; padding-left: 7px; background-color: #CCCCCC; border-width: 0; diff --git a/interface/src/ui/BaseLogDialog.cpp b/interface/src/ui/BaseLogDialog.cpp index 7e0027e0a8..c316206e7a 100644 --- a/interface/src/ui/BaseLogDialog.cpp +++ b/interface/src/ui/BaseLogDialog.cpp @@ -28,17 +28,22 @@ const int SEARCH_BUTTON_LEFT = 25; const int SEARCH_BUTTON_WIDTH = 20; const int SEARCH_TOGGLE_BUTTON_WIDTH = 50; const int SEARCH_TEXT_WIDTH = 240; +const int TIME_STAMP_LENGTH = 16; const QColor HIGHLIGHT_COLOR = QColor("#3366CC"); +const QColor BOLD_COLOR = QColor("#445c8c"); +const QString BOLD_PATTERN = "\\[\\d*\\/.*:\\d*:\\d*\\]"; -class KeywordHighlighter : public QSyntaxHighlighter { +class Highlighter : public QSyntaxHighlighter { public: - KeywordHighlighter(QTextDocument* parent = nullptr); + Highlighter(QTextDocument* parent = nullptr); + void setBold(int indexToBold); QString keyword; - + protected: void highlightBlock(const QString& text) override; private: + QTextCharFormat boldFormat; QTextCharFormat keywordFormat; }; @@ -101,9 +106,8 @@ void BaseLogDialog::initControls() { _logTextBox = new QPlainTextEdit(this); _logTextBox->setReadOnly(true); _logTextBox->show(); - _highlighter = new KeywordHighlighter(_logTextBox->document()); + _highlighter = new Highlighter(_logTextBox->document()); connect(_logTextBox, SIGNAL(selectionChanged()), SLOT(updateSelection())); - } void BaseLogDialog::showEvent(QShowEvent* event) { @@ -116,7 +120,9 @@ void BaseLogDialog::resizeEvent(QResizeEvent* event) { void BaseLogDialog::appendLogLine(QString logLine) { if (logLine.contains(_searchTerm, Qt::CaseInsensitive)) { + int indexToBold = _logTextBox->document()->characterCount(); _logTextBox->appendPlainText(logLine.trimmed()); + _highlighter->setBold(indexToBold); } } @@ -175,6 +181,7 @@ void BaseLogDialog::showLogData() { _logTextBox->clear(); _logTextBox->appendPlainText(getCurrentLog()); _logTextBox->ensureCursorVisible(); + _highlighter->rehighlight(); } void BaseLogDialog::updateSelection() { @@ -187,16 +194,28 @@ void BaseLogDialog::updateSelection() { } } -KeywordHighlighter::KeywordHighlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) { +Highlighter::Highlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) { + boldFormat.setFontWeight(75); + boldFormat.setForeground(BOLD_COLOR); keywordFormat.setForeground(HIGHLIGHT_COLOR); -} + } -void KeywordHighlighter::highlightBlock(const QString& text) { +void Highlighter::highlightBlock(const QString& text) { + QRegExp expression(BOLD_PATTERN); + + int index = text.indexOf(expression, 0); + + while (index >= 0) { + int length = expression.matchedLength(); + setFormat(index, length, boldFormat); + index = text.indexOf(expression, index + length); + } + if (keyword.isNull() || keyword.isEmpty()) { return; } - int index = text.indexOf(keyword, 0, Qt::CaseInsensitive); + index = text.indexOf(keyword, 0, Qt::CaseInsensitive); int length = keyword.length(); while (index >= 0) { @@ -204,3 +223,7 @@ void KeywordHighlighter::highlightBlock(const QString& text) { index = text.indexOf(keyword, index + length, Qt::CaseInsensitive); } } + +void Highlighter::setBold(int indexToBold) { + setFormat(indexToBold, TIME_STAMP_LENGTH, boldFormat); +} diff --git a/interface/src/ui/BaseLogDialog.h b/interface/src/ui/BaseLogDialog.h index d097010bae..e18d23937f 100644 --- a/interface/src/ui/BaseLogDialog.h +++ b/interface/src/ui/BaseLogDialog.h @@ -23,7 +23,7 @@ const int BUTTON_MARGIN = 8; class QPushButton; class QLineEdit; class QPlainTextEdit; -class KeywordHighlighter; +class Highlighter; class BaseLogDialog : public QDialog { Q_OBJECT @@ -56,7 +56,7 @@ private: QPushButton* _searchPrevButton { nullptr }; QPushButton* _searchNextButton { nullptr }; QString _searchTerm; - KeywordHighlighter* _highlighter { nullptr }; + Highlighter* _highlighter { nullptr }; void initControls(); void showLogData(); From 1bba59a45903f4c94378bef89990a5bc0e857ad6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 14:38:02 -0700 Subject: [PATCH 15/47] Revert "Revert "avoid unnecessary copy of priority_queue"" This reverts commit 97c376a09c99f567b0fa90abd490eb542cd93c42. --- .../src/avatars/AvatarMixerSlave.cpp | 4 +-- interface/src/avatar/AvatarManager.cpp | 4 +-- libraries/avatars/src/AvatarData.cpp | 28 +++++++++---------- libraries/avatars/src/AvatarData.h | 3 +- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index dd25aa4c4b..584d3d0e6a 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -185,8 +185,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { AvatarSharedPointer thisAvatar = nodeData->getAvatarSharedPointer(); ViewFrustum cameraView = nodeData->getViewFrustom(); - std::priority_queue sortedAvatars = AvatarData::sortAvatars( - avatarList, cameraView, + std::priority_queue sortedAvatars; + AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, [&](AvatarSharedPointer avatar)->uint64_t{ auto avatarNode = avatarDataToNodes[avatar]; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index d806c042b9..6b426bcde8 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -164,8 +164,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { ViewFrustum cameraView; qApp->copyDisplayViewFrustum(cameraView); - std::priority_queue sortedAvatars = AvatarData::sortAvatars( - avatarList, cameraView, + std::priority_queue sortedAvatars; + AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, [](AvatarSharedPointer avatar)->uint64_t{ return std::static_pointer_cast(avatar)->getLastRenderUpdateTime(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index e7ec201aa1..6e4553ff8a 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2324,20 +2324,20 @@ float AvatarData::_avatarSortCoefficientSize { 0.5f }; float AvatarData::_avatarSortCoefficientCenter { 0.25 }; float AvatarData::_avatarSortCoefficientAge { 1.0f }; -std::priority_queue AvatarData::sortAvatars( - QList avatarList, - const ViewFrustum& cameraView, - std::function getLastUpdated, - std::function getBoundingRadius, - std::function shouldIgnore) { +void AvatarData::sortAvatars( + QList avatarList, + const ViewFrustum& cameraView, + std::priority_queue& sortedAvatarsOut, + std::function getLastUpdated, + std::function getBoundingRadius, + std::function shouldIgnore) { - uint64_t startTime = usecTimestampNow(); - - glm::vec3 frustumCenter = cameraView.getPosition(); - - std::priority_queue sortedAvatars; { PROFILE_RANGE(simulation, "sort"); + uint64_t now = usecTimestampNow(); + + glm::vec3 frustumCenter = cameraView.getPosition(); + const glm::vec3& forward = cameraView.getDirection(); for (int32_t i = 0; i < avatarList.size(); ++i) { const auto& avatar = avatarList.at(i); @@ -2356,10 +2356,9 @@ std::priority_queue AvatarData::sortAvatars( // FIXME - AvatarData has something equivolent to this float radius = getBoundingRadius(avatar); - const glm::vec3& forward = cameraView.getDirection(); float apparentSize = 2.0f * radius / distance; float cosineAngle = glm::dot(offset, forward) / distance; - float age = (float)(startTime - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); + float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); // NOTE: we are adding values of different units to get a single measure of "priority". // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. @@ -2375,10 +2374,9 @@ std::priority_queue AvatarData::sortAvatars( priority += OUT_OF_VIEW_PENALTY; } } - sortedAvatars.push(AvatarPriority(avatar, priority)); + sortedAvatarsOut.push(AvatarPriority(avatar, priority)); } } - return sortedAvatars; } QScriptValue AvatarEntityMapToScriptValue(QScriptEngine* engine, const AvatarEntityMap& value) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 12209d9c31..c2240f400f 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -597,9 +597,10 @@ public: static const float OUT_OF_VIEW_PENALTY; - static std::priority_queue sortAvatars( + static void sortAvatars( QList avatarList, const ViewFrustum& cameraView, + std::priority_queue& sortedAvatarsOut, std::function getLastUpdated, std::function getBoundingRadius, std::function shouldIgnore); From 4637fcefe9321d217c7d30c1c250faf00221186e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 14:38:04 -0700 Subject: [PATCH 16/47] Revert "Revert "remove unused variable"" This reverts commit 50288bd4ba3591aa0cffadfc994606143f349ea5. --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 584d3d0e6a..49b4b1ced4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -168,7 +168,6 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { QList avatarList; std::unordered_map avatarDataToNodes; - int listItem = 0; std::for_each(_begin, _end, [&](const SharedNodePointer& otherNode) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); @@ -176,7 +175,6 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // but not have yet sent data that's linked to the node. Check for that case and don't // consider those nodes. if (otherNodeData) { - listItem++; AvatarSharedPointer otherAvatar = otherNodeData->getAvatarSharedPointer(); avatarList << otherAvatar; avatarDataToNodes[otherAvatar] = otherNode; From 71eb24386b058fd20394fff10f3b6544531a8de5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 14:38:06 -0700 Subject: [PATCH 17/47] Revert "Revert "remove unnecessary context brackets"" This reverts commit a68674adccedab1004e1dbc0ec9e811eb5f2d4b4. --- libraries/avatars/src/AvatarData.cpp | 80 ++++++++++++++-------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6e4553ff8a..8025c680ca 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2332,50 +2332,48 @@ void AvatarData::sortAvatars( std::function getBoundingRadius, std::function shouldIgnore) { - { - PROFILE_RANGE(simulation, "sort"); - uint64_t now = usecTimestampNow(); + PROFILE_RANGE(simulation, "sort"); + uint64_t now = usecTimestampNow(); - glm::vec3 frustumCenter = cameraView.getPosition(); - const glm::vec3& forward = cameraView.getDirection(); - for (int32_t i = 0; i < avatarList.size(); ++i) { - const auto& avatar = avatarList.at(i); + glm::vec3 frustumCenter = cameraView.getPosition(); + const glm::vec3& forward = cameraView.getDirection(); + for (int32_t i = 0; i < avatarList.size(); ++i) { + const auto& avatar = avatarList.at(i); - if (shouldIgnore(avatar)) { - continue; - } - - // priority = weighted linear combination of: - // (a) apparentSize - // (b) proximity to center of view - // (c) time since last update - glm::vec3 avatarPosition = avatar->getPosition(); - glm::vec3 offset = avatarPosition - frustumCenter; - float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero - - // FIXME - AvatarData has something equivolent to this - float radius = getBoundingRadius(avatar); - - float apparentSize = 2.0f * radius / distance; - float cosineAngle = glm::dot(offset, forward) / distance; - float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); - - // NOTE: we are adding values of different units to get a single measure of "priority". - // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. - // These weights are pure magic tuning and should be hard coded in the relation below, - // but are currently exposed for anyone who would like to explore fine tuning: - float priority = _avatarSortCoefficientSize * apparentSize - + _avatarSortCoefficientCenter * cosineAngle - + _avatarSortCoefficientAge * age; - - // decrement priority of avatars outside keyhole - if (distance > cameraView.getCenterRadius()) { - if (!cameraView.sphereIntersectsFrustum(avatarPosition, radius)) { - priority += OUT_OF_VIEW_PENALTY; - } - } - sortedAvatarsOut.push(AvatarPriority(avatar, priority)); + if (shouldIgnore(avatar)) { + continue; } + + // priority = weighted linear combination of: + // (a) apparentSize + // (b) proximity to center of view + // (c) time since last update + glm::vec3 avatarPosition = avatar->getPosition(); + glm::vec3 offset = avatarPosition - frustumCenter; + float distance = glm::length(offset) + 0.001f; // add 1mm to avoid divide by zero + + // FIXME - AvatarData has something equivolent to this + float radius = getBoundingRadius(avatar); + + float apparentSize = 2.0f * radius / distance; + float cosineAngle = glm::dot(offset, forward) / distance; + float age = (float)(now - getLastUpdated(avatar)) / (float)(USECS_PER_SECOND); + + // NOTE: we are adding values of different units to get a single measure of "priority". + // Thus we multiply each component by a conversion "weight" that scales its units relative to the others. + // These weights are pure magic tuning and should be hard coded in the relation below, + // but are currently exposed for anyone who would like to explore fine tuning: + float priority = _avatarSortCoefficientSize * apparentSize + + _avatarSortCoefficientCenter * cosineAngle + + _avatarSortCoefficientAge * age; + + // decrement priority of avatars outside keyhole + if (distance > cameraView.getCenterRadius()) { + if (!cameraView.sphereIntersectsFrustum(avatarPosition, radius)) { + priority += OUT_OF_VIEW_PENALTY; + } + } + sortedAvatarsOut.push(AvatarPriority(avatar, priority)); } } From 031d144c0404d67264c59826b03ce8bbcf8fb72d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 14:38:08 -0700 Subject: [PATCH 18/47] Revert "Revert "minor cleanup"" This reverts commit 188287e345ff43dcc11c79bf20376fba775d5699. --- interface/src/avatar/Avatar.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f5fe82ef4b..6e1f44f5ac 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -351,7 +351,6 @@ void Avatar::simulate(float deltaTime, bool inView) { _jointDataSimulationRate.increment(); _skeletonModel->simulate(deltaTime, true); - _skeletonModelSimulationRate.increment(); locationChanged(); // joints changed, so if there are any children, update them. _hasNewJointData = false; @@ -367,8 +366,8 @@ void Avatar::simulate(float deltaTime, bool inView) { } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. _skeletonModel->simulate(deltaTime, false); - _skeletonModelSimulationRate.increment(); } + _skeletonModelSimulationRate.increment(); } // update animation for display name fade in/out From 203325fd2a5761ef623ace5f67da477e0a380c48 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 14:38:09 -0700 Subject: [PATCH 19/47] Revert "Revert "expand avatar update time budget"" This reverts commit 9a9f07df7111322e21371ffa4938b4691b235c24. --- interface/src/avatar/AvatarManager.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 6b426bcde8..7417f73102 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -157,7 +157,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { lock.unlock(); PerformanceTimer perfTimer("otherAvatars"); - uint64_t startTime = usecTimestampNow(); auto avatarMap = getHashCopy(); QList avatarList = avatarMap.values(); @@ -194,10 +193,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { }); render::PendingChanges pendingChanges; - const uint64_t RENDER_UPDATE_BUDGET = 1500; // usec - const uint64_t MAX_UPDATE_BUDGET = 2000; // usec - uint64_t renderExpiry = startTime + RENDER_UPDATE_BUDGET; - uint64_t maxExpiry = startTime + MAX_UPDATE_BUDGET; + uint64_t startTime = usecTimestampNow(); + const uint64_t UPDATE_BUDGET = 2000; // usec + uint64_t updateExpiry = startTime + UPDATE_BUDGET; int numAvatarsUpdated = 0; int numAVatarsNotUpdated = 0; @@ -223,7 +221,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const float OUT_OF_VIEW_THRESHOLD = 0.5f * AvatarData::OUT_OF_VIEW_PENALTY; uint64_t now = usecTimestampNow(); - if (now < renderExpiry) { + if (now < updateExpiry) { // we're within budget bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; if (inView && avatar->hasNewJointData()) { @@ -232,21 +230,13 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { avatar->simulate(deltaTime, inView); avatar->updateRenderItem(pendingChanges); avatar->setLastRenderUpdateTime(startTime); - } else if (now < maxExpiry) { - // we've spent most of our time budget, but we still simulate() the avatar as it if were out of view - // --> some avatars may freeze until their priority trickles up - bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; - if (inView && avatar->hasNewJointData()) { - numAVatarsNotUpdated++; - } - avatar->simulate(deltaTime, false); } else { - // we've spent ALL of our time budget --> bail on the rest of the avatar updates + // we've spent our full time budget --> bail on the rest of the avatar updates // --> more avatars may freeze until their priority trickles up // --> some scale or fade animations may glitch // --> some avatar velocity measurements may be a little off - // HACK: no time simulate, but we will take the time to count how many were tragically missed + // no time simulate, but we take the time to count how many were tragically missed bool inView = sortData.priority > OUT_OF_VIEW_THRESHOLD; if (!inView) { break; From 0b237fa644265458868f8c93668bd95ca992347c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 15:17:35 -0700 Subject: [PATCH 20/47] Revert "Revert "don't blend animations for otherAvatars"" This reverts commit 8bf9b70915002ca49b8ad100164ddd108c70093f. --- interface/src/avatar/CauterizedModel.cpp | 6 -- interface/src/avatar/CauterizedModel.h | 1 - interface/src/avatar/SkeletonModel.cpp | 4 +- libraries/animation/src/Rig.cpp | 71 ++++++++++++++---------- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index 843779dd3b..0c3d863649 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -95,12 +95,6 @@ void CauterizedModel::createCollisionRenderItemSet() { Model::createCollisionRenderItemSet(); } -// Called within Model::simulate call, below. -void CauterizedModel::updateRig(float deltaTime, glm::mat4 parentTransform) { - Model::updateRig(deltaTime, parentTransform); - _needsUpdateClusterMatrices = true; -} - void CauterizedModel::updateClusterMatrices() { PerformanceTimer perfTimer("CauterizedModel::updateClusterMatrices"); diff --git a/interface/src/avatar/CauterizedModel.h b/interface/src/avatar/CauterizedModel.h index 01e0b13650..ba12aee32b 100644 --- a/interface/src/avatar/CauterizedModel.h +++ b/interface/src/avatar/CauterizedModel.h @@ -37,7 +37,6 @@ public: void createVisibleRenderItemSet() override; void createCollisionRenderItemSet() override; - virtual void updateRig(float deltaTime, glm::mat4 parentTransform) override; virtual void updateClusterMatrices() override; void updateRenderItems() override; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4b77323bba..88590a6f69 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -166,7 +166,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->computeMotionAnimationState(deltaTime, position, velocity, orientation, ccState); // evaluate AnimGraph animation and update jointStates. - CauterizedModel::updateRig(deltaTime, parentTransform); + Model::updateRig(deltaTime, parentTransform); Rig::EyeParameters eyeParams; eyeParams.worldHeadOrientation = headParams.worldHeadOrientation; @@ -179,7 +179,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromEyeParameters(eyeParams); } else { - CauterizedModel::updateRig(deltaTime, parentTransform); + Model::updateRig(deltaTime, parentTransform); // This is a little more work than we really want. // diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index c47da7c0b0..84e34adec7 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1307,39 +1307,50 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { void Rig::copyJointsFromJointData(const QVector& jointDataVec) { PerformanceTimer perfTimer("copyJoints"); PROFILE_RANGE(simulation_animation_detail, "copyJoints"); - if (_animSkeleton && jointDataVec.size() == (int)_internalPoseSet._relativePoses.size()) { - // make a vector of rotations in absolute-geometry-frame - const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); - std::vector rotations; - rotations.reserve(absoluteDefaultPoses.size()); - const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); - for (int i = 0; i < jointDataVec.size(); i++) { - const JointData& data = jointDataVec.at(i); - if (data.rotationSet) { - // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame - rotations.push_back(rigToGeometryRot * data.rotation); - } else { - rotations.push_back(absoluteDefaultPoses[i].rot()); - } - } + if (!_animSkeleton) { + return; + } + if (jointDataVec.size() != (int)_internalPoseSet._relativePoses.size()) { + // animations haven't fully loaded yet. + _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); + } - // convert rotations from absolute to parent relative. - _animSkeleton->convertAbsoluteRotationsToRelative(rotations); - - // store new relative poses - const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); - for (int i = 0; i < jointDataVec.size(); i++) { - const JointData& data = jointDataVec.at(i); - _internalPoseSet._relativePoses[i].scale() = Vectors::ONE; - _internalPoseSet._relativePoses[i].rot() = rotations[i]; - if (data.translationSet) { - // JointData translations are in scaled relative-frame so we scale back to regular relative-frame - _internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation; - } else { - _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans(); - } + // make a vector of rotations in absolute-geometry-frame + const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses(); + std::vector rotations; + rotations.reserve(absoluteDefaultPoses.size()); + const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); + for (int i = 0; i < jointDataVec.size(); i++) { + const JointData& data = jointDataVec.at(i); + if (data.rotationSet) { + // JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame + rotations.push_back(rigToGeometryRot * data.rotation); + } else { + rotations.push_back(absoluteDefaultPoses[i].rot()); } } + + // convert rotations from absolute to parent relative. + _animSkeleton->convertAbsoluteRotationsToRelative(rotations); + + // store new relative poses + const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses(); + for (int i = 0; i < jointDataVec.size(); i++) { + const JointData& data = jointDataVec.at(i); + _internalPoseSet._relativePoses[i].scale() = Vectors::ONE; + _internalPoseSet._relativePoses[i].rot() = rotations[i]; + if (data.translationSet) { + // JointData translations are in scaled relative-frame so we scale back to regular relative-frame + _internalPoseSet._relativePoses[i].trans() = _invGeometryOffset.scale() * data.translation; + } else { + _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans(); + } + } + + // build absolute poses and copy to externalPoseSet + buildAbsoluteRigPoses(_internalPoseSet._relativePoses, _internalPoseSet._absolutePoses); + QWriteLocker writeLock(&_externalPoseSetLock); + _externalPoseSet = _internalPoseSet; } void Rig::computeAvatarBoundingCapsule( From efc7fbacb14a800c46982f9b870620f010930b97 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 7 Mar 2017 10:03:38 -0800 Subject: [PATCH 21/47] Bug fix for potential crash when getting DebugDraw::instance (cherry picked from commit b0ad9a8110b8206115700e30ddd48d26959218a7) --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f870bd9f83..e35dcc674d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -608,6 +608,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } } + // make sure the debug draw singleton is initialized on the main thread. + DebugDraw::getInstance().removeMarker(""); _runningMarker.startRunningMarker(); From d38b994f4c2a577b47adc9d5868ef098ec2d2d0e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 7 Mar 2017 16:07:30 -0800 Subject: [PATCH 22/47] Fix for potential crash due to DebugDraw data race. (cherry picked from commit 1b8a624edb81e8f62e2cb257b74e588653daaab2) --- libraries/render-utils/src/AnimDebugDraw.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c8746d5c60..6066385847 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -346,7 +346,9 @@ void AnimDebugDraw::update() { numVerts += (int)markerMap.size() * VERTICES_PER_BONE; auto myAvatarMarkerMap = DebugDraw::getInstance().getMyAvatarMarkerMap(); numVerts += (int)myAvatarMarkerMap.size() * VERTICES_PER_BONE; - numVerts += (int)DebugDraw::getInstance().getRays().size() * VERTICES_PER_RAY; + auto rays = DebugDraw::getInstance().getRays(); + DebugDraw::getInstance().clearRays(); + numVerts += (int)rays.size() * VERTICES_PER_RAY; // allocate verts! std::vector vertices; @@ -398,10 +400,9 @@ void AnimDebugDraw::update() { } // draw rays from shared DebugDraw singleton - for (auto& iter : DebugDraw::getInstance().getRays()) { + for (auto& iter : rays) { addLine(std::get<0>(iter), std::get<1>(iter), std::get<2>(iter), v); } - DebugDraw::getInstance().clearRays(); data._vertexBuffer->resize(sizeof(AnimDebugDrawData::Vertex) * numVerts); data._vertexBuffer->setSubData(0, vertices); From 6747f553bf507ec33e64e75d25d3422427b53970 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 7 Mar 2017 18:13:42 -0800 Subject: [PATCH 23/47] Add DebugDraw to .eslintrc config file (cherry picked from commit c7cd0fdc3821ac932ad4e86e02c2797c5800182c) --- .eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.js b/.eslintrc.js index c708decc51..9635142d1a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,6 +17,7 @@ module.exports = { "Clipboard": false, "Controller": false, "DialogsManager": false, + "DebugDraw": false, "Entities": false, "FaceTracker": false, "GlobalServices": false, From 34889d38c9e096f3ab3222fe13be9294cf85690a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 1 Mar 2017 17:49:52 -0800 Subject: [PATCH 24/47] Override all roles instead of just fly --- scripts/tutorials/entity_scripts/sit.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 2ba19231e0..7968cde5f1 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -2,7 +2,7 @@ Script.include("/~/system/libraries/utils.js"); var SETTING_KEY = "com.highfidelity.avatar.isSitting"; - var ROLE = "fly"; + var ROLES = MyAvatar.getAnimationRoles(); var ANIMATION_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/animations/sitting_idle.fbx"; var ANIMATION_FPS = 30; var ANIMATION_FIRST_FRAME = 1; @@ -85,7 +85,9 @@ if (previousValue === "") { MyAvatar.characterControllerEnabled = false; MyAvatar.hmdLeanRecenterEnabled = false; - MyAvatar.overrideRoleAnimation(ROLE, ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); + for (i in ROLES) { + MyAvatar.overrideRoleAnimation(ROLES[i], ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); + } MyAvatar.resetSensorsAndBody(); } @@ -110,8 +112,10 @@ this.sitUp = function() { this.setSeatUser(null); - if (Settings.getValue(SETTING_KEY) === this.entityID) { - MyAvatar.restoreRoleAnimation(ROLE); + if (Settings.getValue(SETTING_KEY) === this.entityID) { + for (i in ROLES) { + MyAvatar.restoreRoleAnimation(ROLES[i]); + } MyAvatar.characterControllerEnabled = true; MyAvatar.hmdLeanRecenterEnabled = true; From 1a375432e09d02c3a0c43c1f558a8634d0842659 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 6 Mar 2017 16:09:31 -0800 Subject: [PATCH 25/47] Only grab primary clicks --- scripts/tutorials/entity_scripts/sit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 7968cde5f1..9e41ba2824 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -250,11 +250,11 @@ this.cleanupOverlay(); } - this.clickDownOnEntity = function () { + this.clickDownOnEntity = function (id, event) { if (isInEditMode() || (MyAvatar.sessionUUID === this.getSeatUser())) { return; } - if (this.canSitDesktop()) { + if (event.isPrimaryButton && this.canSitDesktop()) { this.sitDown(); } } From f0d971fc6f47dfb444ad7289611f3c1abeaa38ea Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 6 Mar 2017 16:10:11 -0800 Subject: [PATCH 26/47] Put avatar in front of chair on situp to avoid infinite collisions --- scripts/tutorials/entity_scripts/sit.js | 41 +++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 9e41ba2824..1412740f85 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -14,6 +14,7 @@ var DESKTOP_UI_CHECK_INTERVAL = 250; var DESKTOP_MAX_DISTANCE = 5; var SIT_DELAY = 25 + var MAX_RESET_DISTANCE = 0.5 this.entityID = null; this.timers = {}; @@ -24,7 +25,7 @@ } this.unload = function() { if (MyAvatar.sessionUUID === this.getSeatUser()) { - this.sitUp(this.entityID); + this.sitUp(); } if (this.interval) { Script.clearInterval(this.interval); @@ -110,9 +111,13 @@ } this.sitUp = function() { + if (MyAvatar.sessionUUID !== this.getSeatUser()) { + // Duplicate call, bail + return; + } this.setSeatUser(null); - if (Settings.getValue(SETTING_KEY) === this.entityID) { + if (Settings.getValue(SETTING_KEY) === this.entityID) { for (i in ROLES) { MyAvatar.restoreRoleAnimation(ROLES[i]); } @@ -187,15 +192,26 @@ } } - this.update = function(dt) { if (MyAvatar.sessionUUID === this.getSeatUser()) { - var properties = Entities.getEntityProperties(this.entityID, ["position"]); + var properties = Entities.getEntityProperties(this.entityID); var avatarDistance = Vec3.distance(MyAvatar.position, properties.position); var ikError = MyAvatar.getIKErrorOnLastSolve(); if (avatarDistance > RELEASE_DISTANCE || ikError > MAX_IK_ERROR) { print("IK error: " + ikError + ", distance from chair: " + avatarDistance); - this.sitUp(this.entityID); + + // Move avatar in front of the chair to avoid getting stuck in collision hulls + if (avatarDistance < MAX_RESET_DISTANCE) { + var offset = { x: 0, y: 1.0, z: -0.5 - properties.dimensions.z * properties.registrationPoint.z }; + Vec3.print("offset:", Vec3.multiplyQbyV(properties.rotation, offset)); + var position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.rotation, offset)); + MyAvatar.position = position; + } + + var that = this; + Script.setTimeout(function() { + that.sitUp(); + }, SIT_DELAY); } } } @@ -207,7 +223,20 @@ if (RELEASE_KEYS.indexOf(event.text) !== -1) { var that = this; this.timers[event.text] = Script.setTimeout(function() { - that.sitUp(); + var properties = Entities.getEntityProperties(that.entityID); + var avatarDistance = Vec3.distance(MyAvatar.position, properties.position); + + // Move avatar in front of the chair to avoid getting stuck in collision hulls + if (avatarDistance < MAX_RESET_DISTANCE) { + var offset = { x: 0, y: 1.0, z: -0.5 - properties.dimensions.z * properties.registrationPoint.z }; + Vec3.print("offset1:", Vec3.multiplyQbyV(properties.rotation, offset)); + var position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.rotation, offset)); + MyAvatar.position = position; + } + + Script.setTimeout(function() { + that.sitUp(); + }, SIT_DELAY); }, RELEASE_TIME); } } From 9e6312ba0e66741327f31fc39dc5583515856bb8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 13 Mar 2017 17:22:06 -0800 Subject: [PATCH 27/47] Make sit script more stable. --- scripts/tutorials/entity_scripts/sit.js | 147 ++++++++++++------------ 1 file changed, 76 insertions(+), 71 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 1412740f85..8dc73b0bd8 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -10,8 +10,8 @@ var RELEASE_KEYS = ['w', 'a', 's', 'd', 'UP', 'LEFT', 'DOWN', 'RIGHT']; var RELEASE_TIME = 500; // ms var RELEASE_DISTANCE = 0.2; // meters - var MAX_IK_ERROR = 20; - var DESKTOP_UI_CHECK_INTERVAL = 250; + var MAX_IK_ERROR = 30; + var DESKTOP_UI_CHECK_INTERVAL = 100; var DESKTOP_MAX_DISTANCE = 5; var SIT_DELAY = 25 var MAX_RESET_DISTANCE = 0.5 @@ -19,15 +19,16 @@ this.entityID = null; this.timers = {}; this.animStateHandlerID = null; + this.interval = null; this.preload = function(entityID) { this.entityID = entityID; } this.unload = function() { - if (MyAvatar.sessionUUID === this.getSeatUser()) { + if (Settings.getValue(SETTING_KEY) === this.entityID) { this.sitUp(); } - if (this.interval) { + if (this.interval !== null) { Script.clearInterval(this.interval); this.interval = null; } @@ -35,42 +36,60 @@ } this.setSeatUser = function(user) { - var userData = Entities.getEntityProperties(this.entityID, ["userData"]).userData; - userData = JSON.parse(userData); + try { + var userData = Entities.getEntityProperties(this.entityID, ["userData"]).userData; + userData = JSON.parse(userData); - if (user) { - userData.seat.user = user; - } else { - delete userData.seat.user; + if (user !== null) { + userData.seat.user = user; + } else { + delete userData.seat.user; + } + + Entities.editEntity(this.entityID, { + userData: JSON.stringify(userData) + }); + } catch (e) { + // Do Nothing } - - Entities.editEntity(this.entityID, { - userData: JSON.stringify(userData) - }); } this.getSeatUser = function() { - var properties = Entities.getEntityProperties(this.entityID, ["userData", "position"]); - var userData = JSON.parse(properties.userData); + try { + var properties = Entities.getEntityProperties(this.entityID, ["userData", "position"]); + var userData = JSON.parse(properties.userData); - if (userData.seat.user && userData.seat.user !== MyAvatar.sessionUUID) { - var avatar = AvatarList.getAvatar(userData.seat.user); - if (avatar && Vec3.distance(avatar.position, properties.position) > RELEASE_DISTANCE) { - return null; + // If MyAvatar return my uuid + if (userData.seat.user === MyAvatar.sessionUUID) { + return userData.seat.user; } + + + // If Avatar appears to be sitting + if (userData.seat.user) { + var avatar = AvatarList.getAvatar(userData.seat.user); + if (avatar && (Vec3.distance(avatar.position, properties.position) < RELEASE_DISTANCE)) { + return userData.seat.user; + } + } + } catch (e) { + // Do nothing } - return userData.seat.user; + + // Nobody on the seat + return null; } + // Is the seat used this.checkSeatForAvatar = function() { var seatUser = this.getSeatUser(); - var avatarIdentifiers = AvatarList.getAvatarIdentifiers(); - for (var i in avatarIdentifiers) { - var avatar = AvatarList.getAvatar(avatarIdentifiers[i]); - if (avatar && avatar.sessionUUID === seatUser) { - return true; - } + + // If MyAvatar appears to be sitting + if (seatUser === MyAvatar.sessionUUID) { + var properties = Entities.getEntityProperties(this.entityID, ["position"]); + return Vec3.distance(MyAvatar.position, properties.position) < RELEASE_DISTANCE; } - return false; + + return seatUser !== null; } this.sitDown = function() { @@ -79,10 +98,9 @@ return; } - this.setSeatUser(MyAvatar.sessionUUID); - var previousValue = Settings.getValue(SETTING_KEY); Settings.setValue(SETTING_KEY, this.entityID); + this.setSeatUser(MyAvatar.sessionUUID); if (previousValue === "") { MyAvatar.characterControllerEnabled = false; MyAvatar.hmdLeanRecenterEnabled = false; @@ -92,32 +110,34 @@ MyAvatar.resetSensorsAndBody(); } - var that = this; - Script.setTimeout(function() { - var properties = Entities.getEntityProperties(that.entityID, ["position", "rotation"]); - var index = MyAvatar.getJointIndex("Hips"); - MyAvatar.pinJoint(index, properties.position, properties.rotation); + var properties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); + var index = MyAvatar.getJointIndex("Hips"); + MyAvatar.pinJoint(index, properties.position, properties.rotation); - that.animStateHandlerID = MyAvatar.addAnimationStateHandler(function(properties) { - return { headType: 0 }; - }, ["headType"]); - Script.update.connect(that, that.update); - Controller.keyPressEvent.connect(that, that.keyPressed); - Controller.keyReleaseEvent.connect(that, that.keyReleased); - for (var i in RELEASE_KEYS) { - Controller.captureKeyEvents({ text: RELEASE_KEYS[i] }); - } - }, SIT_DELAY); + this.animStateHandlerID = MyAvatar.addAnimationStateHandler(function(properties) { + return { headType: 0 }; + }, ["headType"]); + Script.update.connect(this, this.update); + Controller.keyPressEvent.connect(this, this.keyPressed); + Controller.keyReleaseEvent.connect(this, this.keyReleased); + for (var i in RELEASE_KEYS) { + Controller.captureKeyEvents({ text: RELEASE_KEYS[i] }); + } } this.sitUp = function() { - if (MyAvatar.sessionUUID !== this.getSeatUser()) { - // Duplicate call, bail - return; + MyAvatar.removeAnimationStateHandler(this.animStateHandlerID); + Script.update.disconnect(this, this.update); + Controller.keyPressEvent.disconnect(this, this.keyPressed); + Controller.keyReleaseEvent.disconnect(this, this.keyReleased); + for (var i in RELEASE_KEYS) { + Controller.releaseKeyEvents({ text: RELEASE_KEYS[i] }); } - this.setSeatUser(null); + this.setSeatUser(null); if (Settings.getValue(SETTING_KEY) === this.entityID) { + Settings.setValue(SETTING_KEY, ""); + for (i in ROLES) { MyAvatar.restoreRoleAnimation(ROLES[i]); } @@ -133,16 +153,6 @@ MyAvatar.bodyPitch = 0.0; MyAvatar.bodyRoll = 0.0; }, SIT_DELAY); - - Settings.setValue(SETTING_KEY, ""); - } - - MyAvatar.removeAnimationStateHandler(this.animStateHandlerID); - Script.update.disconnect(this, this.update); - Controller.keyPressEvent.disconnect(this, this.keyPressed); - Controller.keyReleaseEvent.disconnect(this, this.keyReleased); - for (var i in RELEASE_KEYS) { - Controller.releaseKeyEvents({ text: RELEASE_KEYS[i] }); } } @@ -203,15 +213,11 @@ // Move avatar in front of the chair to avoid getting stuck in collision hulls if (avatarDistance < MAX_RESET_DISTANCE) { var offset = { x: 0, y: 1.0, z: -0.5 - properties.dimensions.z * properties.registrationPoint.z }; - Vec3.print("offset:", Vec3.multiplyQbyV(properties.rotation, offset)); var position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.rotation, offset)); MyAvatar.position = position; } - var that = this; - Script.setTimeout(function() { - that.sitUp(); - }, SIT_DELAY); + this.sitUp(); } } } @@ -223,20 +229,19 @@ if (RELEASE_KEYS.indexOf(event.text) !== -1) { var that = this; this.timers[event.text] = Script.setTimeout(function() { + delete that.timers[event.text]; + var properties = Entities.getEntityProperties(that.entityID); var avatarDistance = Vec3.distance(MyAvatar.position, properties.position); // Move avatar in front of the chair to avoid getting stuck in collision hulls if (avatarDistance < MAX_RESET_DISTANCE) { var offset = { x: 0, y: 1.0, z: -0.5 - properties.dimensions.z * properties.registrationPoint.z }; - Vec3.print("offset1:", Vec3.multiplyQbyV(properties.rotation, offset)); var position = Vec3.sum(properties.position, Vec3.multiplyQbyV(properties.rotation, offset)); MyAvatar.position = position; } - Script.setTimeout(function() { - that.sitUp(); - }, SIT_DELAY); + that.sitUp(); }, RELEASE_TIME); } } @@ -256,7 +261,7 @@ } this.hoverEnterEntity = function(event) { - if (isInEditMode() || (MyAvatar.sessionUUID === this.getSeatUser())) { + if (isInEditMode() || this.interval !== null) { return; } @@ -272,7 +277,7 @@ }, DESKTOP_UI_CHECK_INTERVAL); } this.hoverLeaveEntity = function(event) { - if (this.interval) { + if (this.interval !== null) { Script.clearInterval(this.interval); this.interval = null; } @@ -280,7 +285,7 @@ } this.clickDownOnEntity = function (id, event) { - if (isInEditMode() || (MyAvatar.sessionUUID === this.getSeatUser())) { + if (isInEditMode()) { return; } if (event.isPrimaryButton && this.canSitDesktop()) { From b14a4faf610269a56554be1b05f2b6ea1310cb34 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 14 Mar 2017 10:54:22 -0800 Subject: [PATCH 28/47] Guard against script loading before avatar --- scripts/tutorials/entity_scripts/sit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/tutorials/entity_scripts/sit.js b/scripts/tutorials/entity_scripts/sit.js index 8dc73b0bd8..ffce196572 100644 --- a/scripts/tutorials/entity_scripts/sit.js +++ b/scripts/tutorials/entity_scripts/sit.js @@ -2,7 +2,6 @@ Script.include("/~/system/libraries/utils.js"); var SETTING_KEY = "com.highfidelity.avatar.isSitting"; - var ROLES = MyAvatar.getAnimationRoles(); var ANIMATION_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/clement/production/animations/sitting_idle.fbx"; var ANIMATION_FPS = 30; var ANIMATION_FIRST_FRAME = 1; @@ -104,6 +103,7 @@ if (previousValue === "") { MyAvatar.characterControllerEnabled = false; MyAvatar.hmdLeanRecenterEnabled = false; + var ROLES = MyAvatar.getAnimationRoles(); for (i in ROLES) { MyAvatar.overrideRoleAnimation(ROLES[i], ANIMATION_URL, ANIMATION_FPS, true, ANIMATION_FIRST_FRAME, ANIMATION_LAST_FRAME); } @@ -137,7 +137,7 @@ this.setSeatUser(null); if (Settings.getValue(SETTING_KEY) === this.entityID) { Settings.setValue(SETTING_KEY, ""); - + var ROLES = MyAvatar.getAnimationRoles(); for (i in ROLES) { MyAvatar.restoreRoleAnimation(ROLES[i]); } From 0abcda86a8b17cae2f8425cf2d24c0d725352fe3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 13 Mar 2017 18:52:31 -0400 Subject: [PATCH 29/47] mv AudioNoiseGate to audio --- libraries/audio-client/src/AudioClient.h | 2 +- libraries/{audio-client => audio}/src/AudioNoiseGate.cpp | 8 ++++---- libraries/{audio-client => audio}/src/AudioNoiseGate.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename libraries/{audio-client => audio}/src/AudioNoiseGate.cpp (99%) rename libraries/{audio-client => audio}/src/AudioNoiseGate.h (96%) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 512b4bb3c1..7e9acc0586 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -45,13 +45,13 @@ #include #include #include +#include #include #include #include "AudioIOStats.h" -#include "AudioNoiseGate.h" #ifdef _WIN32 #pragma warning( push ) diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio/src/AudioNoiseGate.cpp similarity index 99% rename from libraries/audio-client/src/AudioNoiseGate.cpp rename to libraries/audio/src/AudioNoiseGate.cpp index 8a9134b5dc..c99b31b989 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio/src/AudioNoiseGate.cpp @@ -1,6 +1,6 @@ // // AudioNoiseGate.cpp -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioNoiseGate.h" + #include #include -#include - -#include "AudioNoiseGate.h" +#include "AudioConstants.h" const float AudioNoiseGate::CLIPPING_THRESHOLD = 0.90f; diff --git a/libraries/audio-client/src/AudioNoiseGate.h b/libraries/audio/src/AudioNoiseGate.h similarity index 96% rename from libraries/audio-client/src/AudioNoiseGate.h rename to libraries/audio/src/AudioNoiseGate.h index f72e92b0d5..d47cebf853 100644 --- a/libraries/audio-client/src/AudioNoiseGate.h +++ b/libraries/audio/src/AudioNoiseGate.h @@ -1,6 +1,6 @@ // // AudioNoiseGate.h -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -48,4 +48,4 @@ private: int _blocksToClose; }; -#endif // hifi_AudioNoiseGate_h \ No newline at end of file +#endif // hifi_AudioNoiseGate_h From f43706dfe1f2f2ed87b5e8793b8f1b147b56b8e7 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 13 Mar 2017 18:56:54 -0400 Subject: [PATCH 30/47] clean AudioNoiseGate --- libraries/audio/src/AudioNoiseGate.cpp | 38 ++++++-------------------- libraries/audio/src/AudioNoiseGate.h | 11 +++----- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/libraries/audio/src/AudioNoiseGate.cpp b/libraries/audio/src/AudioNoiseGate.cpp index c99b31b989..604897af8a 100644 --- a/libraries/audio/src/AudioNoiseGate.cpp +++ b/libraries/audio/src/AudioNoiseGate.cpp @@ -19,19 +19,13 @@ const float AudioNoiseGate::CLIPPING_THRESHOLD = 0.90f; AudioNoiseGate::AudioNoiseGate() : - _inputBlockCounter(0), _lastLoudness(0.0f), - _quietestBlock(std::numeric_limits::max()), - _loudestBlock(0.0f), _didClipInLastBlock(false), _dcOffset(0.0f), _measuredFloor(0.0f), _sampleCounter(0), _isOpen(false), - _blocksToClose(0) -{ - -} + _blocksToClose(0) {} void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { // @@ -80,7 +74,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { float loudness = 0; int thisSample = 0; int samplesOverNoiseGate = 0; - + const float NOISE_GATE_HEIGHT = 7.0f; const int NOISE_GATE_WIDTH = 5; const int NOISE_GATE_CLOSE_BLOCK_DELAY = 5; @@ -88,36 +82,22 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { // Check clipping, and check if should open noise gate _didClipInLastBlock = false; - + for (int i = 0; i < numSamples; i++) { thisSample = std::abs(samples[i]); if (thisSample >= ((float) AudioConstants::MAX_SAMPLE_VALUE * CLIPPING_THRESHOLD)) { _didClipInLastBlock = true; } - + loudness += thisSample; // Noise Reduction: Count peaks above the average loudness if (thisSample > (_measuredFloor * NOISE_GATE_HEIGHT)) { samplesOverNoiseGate++; } } - + _lastLoudness = fabs(loudness / numSamples); - - if (_quietestBlock > _lastLoudness) { - _quietestBlock = _lastLoudness; - } - if (_loudestBlock < _lastLoudness) { - _loudestBlock = _lastLoudness; - } - - const int FRAMES_FOR_NOISE_DETECTION = 400; - if (_inputBlockCounter++ > FRAMES_FOR_NOISE_DETECTION) { - _quietestBlock = std::numeric_limits::max(); - _loudestBlock = 0.0f; - _inputBlockCounter = 0; - } - + // If Noise Gate is enabled, check and turn the gate on and off float averageOfAllSampleBlocks = 0.0f; _sampleBlocks[_sampleCounter++] = _lastLoudness; @@ -130,7 +110,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { averageOfAllSampleBlocks += _sampleBlocks[j]; } thisAverage /= NOISE_GATE_BLOCKS_TO_AVERAGE; - + if (thisAverage < smallestSample) { smallestSample = thisAverage; } @@ -138,7 +118,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { averageOfAllSampleBlocks /= NUMBER_OF_NOISE_SAMPLE_BLOCKS; _measuredFloor = smallestSample; _sampleCounter = 0; - + } _closedInLastBlock = false; @@ -156,7 +136,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { } if (!_isOpen) { // First block after being closed gets faded to silence, we fade across - // the entire block on fading out. All subsequent blocks are muted by being slammed + // the entire block on fading out. All subsequent blocks are muted by being slammed // to zeros if (_closedInLastBlock) { float fadeSlope = (1.0f / numSamples); diff --git a/libraries/audio/src/AudioNoiseGate.h b/libraries/audio/src/AudioNoiseGate.h index d47cebf853..8430f120e5 100644 --- a/libraries/audio/src/AudioNoiseGate.h +++ b/libraries/audio/src/AudioNoiseGate.h @@ -19,24 +19,21 @@ const int NUMBER_OF_NOISE_SAMPLE_BLOCKS = 300; class AudioNoiseGate { public: AudioNoiseGate(); - + void gateSamples(int16_t* samples, int numSamples); void removeDCOffset(int16_t* samples, int numSamples); - + bool clippedInLastBlock() const { return _didClipInLastBlock; } bool closedInLastBlock() const { return _closedInLastBlock; } bool openedInLastBlock() const { return _openedInLastBlock; } bool isOpen() const { return _isOpen; } float getMeasuredFloor() const { return _measuredFloor; } float getLastLoudness() const { return _lastLoudness; } - + static const float CLIPPING_THRESHOLD; - + private: - int _inputBlockCounter; float _lastLoudness; - float _quietestBlock; - float _loudestBlock; bool _didClipInLastBlock; float _dcOffset; float _measuredFloor; From a9658ce9fb7be82821759539fb1bc0820998f3c8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 14 Mar 2017 17:15:23 -0700 Subject: [PATCH 31/47] Revert "Trivial PR to trigger build" This reverts commit a0befa7f958543445ffbc9d4a7975e92752cb127. --- interface/resources/qml/controls/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/controls/README.md b/interface/resources/qml/controls/README.md index 1245e42e97..7f05f32a63 100644 --- a/interface/resources/qml/controls/README.md +++ b/interface/resources/qml/controls/README.md @@ -1,3 +1,2 @@ These are our own custom controls with the same names as existing controls, but customized for readability / usability in VR. - From b1e5e43faa068dcf3f2092d7b9c24022d5931324 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 13 Mar 2017 18:52:31 -0400 Subject: [PATCH 32/47] mv AudioNoiseGate to audio --- libraries/audio-client/src/AudioClient.h | 2 +- libraries/{audio-client => audio}/src/AudioNoiseGate.cpp | 8 ++++---- libraries/{audio-client => audio}/src/AudioNoiseGate.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) rename libraries/{audio-client => audio}/src/AudioNoiseGate.cpp (99%) rename libraries/{audio-client => audio}/src/AudioNoiseGate.h (96%) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 512b4bb3c1..7e9acc0586 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -45,13 +45,13 @@ #include #include #include +#include #include #include #include "AudioIOStats.h" -#include "AudioNoiseGate.h" #ifdef _WIN32 #pragma warning( push ) diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio/src/AudioNoiseGate.cpp similarity index 99% rename from libraries/audio-client/src/AudioNoiseGate.cpp rename to libraries/audio/src/AudioNoiseGate.cpp index 8a9134b5dc..c99b31b989 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio/src/AudioNoiseGate.cpp @@ -1,6 +1,6 @@ // // AudioNoiseGate.cpp -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioNoiseGate.h" + #include #include -#include - -#include "AudioNoiseGate.h" +#include "AudioConstants.h" const float AudioNoiseGate::CLIPPING_THRESHOLD = 0.90f; diff --git a/libraries/audio-client/src/AudioNoiseGate.h b/libraries/audio/src/AudioNoiseGate.h similarity index 96% rename from libraries/audio-client/src/AudioNoiseGate.h rename to libraries/audio/src/AudioNoiseGate.h index f72e92b0d5..d47cebf853 100644 --- a/libraries/audio-client/src/AudioNoiseGate.h +++ b/libraries/audio/src/AudioNoiseGate.h @@ -1,6 +1,6 @@ // // AudioNoiseGate.h -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -48,4 +48,4 @@ private: int _blocksToClose; }; -#endif // hifi_AudioNoiseGate_h \ No newline at end of file +#endif // hifi_AudioNoiseGate_h From e6fbdf8f0699c5bf2741668befc4eda072cb19a2 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 15 Feb 2017 06:03:50 +0000 Subject: [PATCH 33/47] add isNoiseGateEnabled to Agent --- assignment-client/src/Agent.cpp | 8 ++++++++ assignment-client/src/Agent.h | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index be23dcfa25..3562975c4d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -483,6 +483,14 @@ void Agent::setIsListeningToAudioStream(bool isListeningToAudioStream) { _isListeningToAudioStream = isListeningToAudioStream; } +void Agent::setIsNoiseGateEnabled(bool isNoiseGateEnabled) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setIsNoiseGateEnabled", Q_ARG(bool, isNoiseGateEnabled)); + return; + } + _isNoiseGateEnabled = isNoiseGateEnabled; +} + void Agent::setIsAvatar(bool isAvatar) { // this must happen on Agent's main thread if (QThread::currentThread() != thread()) { diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 0ce7b71d5d..6bece4e945 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -38,6 +38,7 @@ class Agent : public ThreadedAssignment { Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar) Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound) Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream) + Q_PROPERTY(bool isNoiseGateEnabled READ isNoiseGateEnabled WRITE setIsNoiseGateEnabled) Q_PROPERTY(float lastReceivedAudioLoudness READ getLastReceivedAudioLoudness) Q_PROPERTY(QUuid sessionUUID READ getSessionUUID) @@ -52,6 +53,9 @@ public: bool isListeningToAudioStream() const { return _isListeningToAudioStream; } void setIsListeningToAudioStream(bool isListeningToAudioStream); + bool isNoiseGateEnabled() const { return _isNoiseGateEnabled; } + void setIsNoiseGateEnabled(bool isNoiseGateEnabled); + float getLastReceivedAudioLoudness() const { return _lastReceivedAudioLoudness; } QUuid getSessionUUID() const; @@ -106,6 +110,8 @@ private: QTimer* _avatarIdentityTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; + bool _isNoiseGateEnabled { false }; + CodecPluginPointer _codec; QString _selectedCodecName; Encoder* _encoder { nullptr }; From 0c657a1d558bbd1d19e24932f9ee6e26cf02de6d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 15 Mar 2017 10:57:12 -0700 Subject: [PATCH 34/47] add parameter to unload to remove entityID from map --- .../src/scripts/EntityScriptServer.cpp | 4 ++-- .../src/EntityTreeRenderer.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 23 ++++++++----------- libraries/script-engine/src/ScriptEngine.h | 2 +- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 47071b10b7..f674ab006c 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -455,13 +455,13 @@ void EntityScriptServer::addingEntity(const EntityItemID& entityID) { void EntityScriptServer::deletingEntity(const EntityItemID& entityID) { if (_entityViewer.getTree() && !_shuttingDown && _entitiesScriptEngine) { - _entitiesScriptEngine->unloadEntityScript(entityID); + _entitiesScriptEngine->unloadEntityScript(entityID, true); } } void EntityScriptServer::entityServerScriptChanging(const EntityItemID& entityID, const bool reload) { if (_entityViewer.getTree() && !_shuttingDown) { - _entitiesScriptEngine->unloadEntityScript(entityID); + _entitiesScriptEngine->unloadEntityScript(entityID, true); checkAndCallPreload(entityID, reload); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 27e00b47c6..c6bd70a0cb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -940,7 +940,7 @@ void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event) { void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { if (_tree && !_shuttingDown && _entitiesScriptEngine) { - _entitiesScriptEngine->unloadEntityScript(entityID); + _entitiesScriptEngine->unloadEntityScript(entityID, true); } forceRecheckEntities(); // reset our state to force checking our inside/outsideness of entities diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 73a79f1bc6..e8a2b105db 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -541,16 +541,6 @@ void ScriptEngine::init() { auto entityScriptingInterface = DependencyManager::get(); entityScriptingInterface->init(); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityID) { - if (_entityScripts.contains(entityID)) { - if (isEntityScriptRunning(entityID)) { - qCWarning(scriptengine) << "deletingEntity while entity script is still running!" << entityID; - } - _entityScripts.remove(entityID); - emit entityScriptDetailsUpdated(); - } - }); - // register various meta-types registerMetaTypes(this); @@ -1844,7 +1834,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co processDeferredEntityLoads(entityScript, entityID); } -void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { +void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap) { if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "*** WARNING *** ScriptEngine::unloadEntityScript() called on wrong thread [" << QThread::currentThread() << "], invoking on correct thread [" << thread() << "] " @@ -1852,7 +1842,8 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { #endif QMetaObject::invokeMethod(this, "unloadEntityScript", - Q_ARG(const EntityItemID&, entityID)); + Q_ARG(const EntityItemID&, entityID), + Q_ARG(bool, shouldRemoveFromMap)); return; } #ifdef THREAD_DEBUGGING @@ -1867,7 +1858,12 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { } else { qCDebug(scriptengine) << "unload called while !running" << entityID << oldDetails.status; } - if (oldDetails.status != EntityScriptStatus::UNLOADED) { + + if (shouldRemoveFromMap) { + // this was a deleted entity, we've been asked to remove it from the map + _entityScripts.remove(entityID); + emit entityScriptDetailsUpdated(); + } else if (oldDetails.status != EntityScriptStatus::UNLOADED) { EntityScriptDetails newDetails; newDetails.status = EntityScriptStatus::UNLOADED; newDetails.lastModified = QDateTime::currentMSecsSinceEpoch(); @@ -1875,6 +1871,7 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID) { newDetails.scriptText = oldDetails.scriptText; setEntityScriptDetails(entityID, newDetails); } + stopAllTimersForEntityScript(entityID); { // FIXME: shouldn't have to do this here, but currently something seems to be firing unloads moments after firing initial load requests diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index b988ccfe90..681499779c 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -171,7 +171,7 @@ public: return _entityScripts.contains(entityID) && _entityScripts[entityID].status == EntityScriptStatus::RUNNING; } Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload); - Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID); // will call unload method + Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method Q_INVOKABLE void unloadAllEntityScripts(); Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const QStringList& params = QStringList()) override; From 3e68018a129a4debfeea14f856b58cdbcc54218a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Mar 2017 14:33:32 -0700 Subject: [PATCH 35/47] Fix node persmissions hash --- libraries/networking/src/NodePermissions.h | 40 ++++++++++++++++------ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index 5d2755f9b5..091eb18909 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -13,18 +13,31 @@ #define hifi_NodePermissions_h #include +#include #include #include #include #include - +#include +#include #include "GroupRank.h" class NodePermissions; using NodePermissionsPointer = std::shared_ptr; -using NodePermissionsKey = QPair; // name, rankID +using NodePermissionsKey = std::pair; // name, rankID using NodePermissionsKeyList = QList>; +namespace std { + template<> + struct hash { + size_t operator()(const NodePermissionsKey& key) const { + size_t result = qHash(key.first); + result <<= 32; + result |= qHash(key.second); + return result; + } + }; +} class NodePermissions { public: @@ -100,27 +113,32 @@ public: NodePermissionsMap() { } NodePermissionsPointer& operator[](const NodePermissionsKey& key) { NodePermissionsKey dataKey(key.first.toLower(), key.second); - if (!_data.contains(dataKey)) { + if (0 == _data.count(dataKey)) { _data[dataKey] = NodePermissionsPointer(new NodePermissions(key)); } return _data[dataKey]; } NodePermissionsPointer operator[](const NodePermissionsKey& key) const { - return _data.value(NodePermissionsKey(key.first.toLower(), key.second)); + NodePermissionsPointer result; + auto itr = _data.find(NodePermissionsKey(key.first.toLower(), key.second)); + if (_data.end() != itr) { + result = itr->second; + } + return result; } bool contains(const NodePermissionsKey& key) const { - return _data.contains(NodePermissionsKey(key.first.toLower(), key.second)); + return 0 != _data.count(NodePermissionsKey(key.first.toLower(), key.second)); } - bool contains(const QString& keyFirst, QUuid keySecond) const { - return _data.contains(NodePermissionsKey(keyFirst.toLower(), keySecond)); + bool contains(const QString& keyFirst, const QUuid& keySecond) const { + return 0 != _data.count(NodePermissionsKey(keyFirst.toLower(), keySecond)); } - QList keys() const { return _data.keys(); } - QHash get() { return _data; } + //QList keys() const { return _data.keys(); } + std::unordered_map get() { return _data; } void clear() { _data.clear(); } - void remove(const NodePermissionsKey& key) { _data.remove(key); } + void remove(const NodePermissionsKey& key) { _data.erase(key); } private: - QHash _data; + std::unordered_map _data; }; From f250c0d29888f3741fbf9c32edae066369894031 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Mar 2017 14:41:13 -0700 Subject: [PATCH 36/47] simpler bindTransform() for ModelMeshPartPayload --- .../src/avatar/CauterizedMeshPartPayload.cpp | 52 +++++-------------- .../src/avatar/CauterizedMeshPartPayload.h | 7 +-- interface/src/avatar/CauterizedModel.cpp | 23 +++++++- .../render-utils/src/MeshPartPayload.cpp | 29 +++++------ libraries/render-utils/src/MeshPartPayload.h | 6 ++- libraries/render-utils/src/Model.cpp | 16 +++--- 6 files changed, 64 insertions(+), 69 deletions(-) diff --git a/interface/src/avatar/CauterizedMeshPartPayload.cpp b/interface/src/avatar/CauterizedMeshPartPayload.cpp index c8ec90dcee..72a98bd994 100644 --- a/interface/src/avatar/CauterizedMeshPartPayload.cpp +++ b/interface/src/avatar/CauterizedMeshPartPayload.cpp @@ -20,33 +20,11 @@ using namespace render; CauterizedMeshPartPayload::CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} -void CauterizedMeshPartPayload::updateTransformForSkinnedCauterizedMesh(const Transform& transform, - const QVector& clusterMatrices, - const QVector& cauterizedClusterMatrices) { - _transform = transform; - _cauterizedTransform = transform; - - if (clusterMatrices.size() > 0) { - _worldBound = AABox(); - for (auto& clusterMatrix : clusterMatrices) { - AABox clusterBound = _localBound; - clusterBound.transform(clusterMatrix); - _worldBound += clusterBound; - } - - _worldBound.transform(transform); - if (clusterMatrices.size() == 1) { - _transform = _transform.worldTransform(Transform(clusterMatrices[0])); - if (cauterizedClusterMatrices.size() != 0) { - _cauterizedTransform = _cauterizedTransform.worldTransform(Transform(cauterizedClusterMatrices[0])); - } else { - _cauterizedTransform = _transform; - } - } - } else { - _worldBound = _localBound; - _worldBound.transform(_drawTransform); - } +void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( + const Transform& renderTransform, + const gpu::BufferPointer& buffer) { + _cauterizedTransform = renderTransform; + _cauterizedClusterBuffer = buffer; } void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { @@ -55,20 +33,16 @@ void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::S SkeletonModel* skeleton = static_cast(_model); bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE) && skeleton->getEnableCauterization(); - if (state.clusterBuffer) { - if (useCauterizedMesh) { - const Model::MeshState& cState = skeleton->getCauterizeMeshState(_meshIndex); - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, cState.clusterBuffer); - } else { - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer); + if (useCauterizedMesh) { + if (_cauterizedClusterBuffer) { + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _cauterizedClusterBuffer); + } + batch.setModelTransform(_cauterizedTransform); + } else { + if (_clusterBuffer) { + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _clusterBuffer); } batch.setModelTransform(_transform); - } else { - if (useCauterizedMesh) { - batch.setModelTransform(_cauterizedTransform); - } else { - batch.setModelTransform(_transform); - } } } diff --git a/interface/src/avatar/CauterizedMeshPartPayload.h b/interface/src/avatar/CauterizedMeshPartPayload.h index f4319ead6f..dc88e950c1 100644 --- a/interface/src/avatar/CauterizedMeshPartPayload.h +++ b/interface/src/avatar/CauterizedMeshPartPayload.h @@ -17,12 +17,13 @@ class CauterizedMeshPartPayload : public ModelMeshPartPayload { public: CauterizedMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); - void updateTransformForSkinnedCauterizedMesh(const Transform& transform, - const QVector& clusterMatrices, - const QVector& cauterizedClusterMatrices); + + void updateTransformForCauterizedMesh(const Transform& renderTransform, const gpu::BufferPointer& buffer); void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; + private: + gpu::BufferPointer _cauterizedClusterBuffer; Transform _cauterizedTransform; }; diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index 1ca87a498a..8ac14fcb6f 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -191,6 +191,9 @@ void CauterizedModel::updateRenderItems() { return; } + // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. + self->updateClusterMatrices(); + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); Transform modelTransform; @@ -209,15 +212,31 @@ void CauterizedModel::updateRenderItems() { if (data._model && data._model->isLoaded()) { // Ensure the model geometry was not reset between frames if (deleteGeometryCounter == data._model->getGeometryCounter()) { - // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. - data._model->updateClusterMatrices(); + // this stuff identical to what happens in regular Model + const Model::MeshState& state = data._model->getMeshState(data._meshIndex); + Transform renderTransform = modelTransform; + if (state.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); + // this stuff for cauterized mesh + CauterizedModel* cModel = static_cast(data._model); + const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); + renderTransform = modelTransform; + if (cState.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); + } + data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer); + +/* // update the model transform and bounding box for this render item. const Model::MeshState& state = data._model->getMeshState(data._meshIndex); CauterizedModel* cModel = static_cast(data._model); assert(data._meshIndex < cModel->_cauterizeMeshStates.size()); const Model::MeshState& cState = cModel->_cauterizeMeshStates.at(data._meshIndex); data.updateTransformForSkinnedCauterizedMesh(modelTransform, state.clusterMatrices, cState.clusterMatrices); +*/ } } }); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 5b3d285b47..d4b28dbddb 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -372,19 +372,12 @@ void ModelMeshPartPayload::notifyLocationChanged() { } -void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& transform, const QVector& clusterMatrices) { - _transform = transform; - - if (clusterMatrices.size() > 0) { - _worldBound = _adjustedLocalBound; - _worldBound.transform(_transform); - if (clusterMatrices.size() == 1) { - _transform = _transform.worldTransform(Transform(clusterMatrices[0])); - } - } else { - _worldBound = _localBound; - _worldBound.transform(_transform); - } +void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& renderTransform, const Transform& boundTransform, + const gpu::BufferPointer& buffer) { + _transform = renderTransform; + _worldBound = _adjustedLocalBound; + _worldBound.transform(boundTransform); + _clusterBuffer = buffer; } ItemKey ModelMeshPartPayload::getKey() const { @@ -532,9 +525,8 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { // Still relying on the raw data from the model - const Model::MeshState& state = _model->getMeshState(_meshIndex); - if (state.clusterBuffer) { - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, state.clusterBuffer); + if (_clusterBuffer) { + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _clusterBuffer); } batch.setModelTransform(_transform); } @@ -590,8 +582,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { auto locations = args->_pipeline->locations; assert(locations); - // Bind the model transform and the skinCLusterMatrices if needed + // update the clusterMatrices if necessary + // TODO: we want to remove this updateClusterMatrices() call in this context + // but I recall we tried this before and broke something. - Andrew _model->updateClusterMatrices(); + bindTransform(batch, locations, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c585c95025..ef74011c40 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -89,8 +89,9 @@ public: typedef Payload::DataPointer Pointer; void notifyLocationChanged() override; - void updateTransformForSkinnedMesh(const Transform& transform, - const QVector& clusterMatrices); + void updateTransformForSkinnedMesh(const Transform& renderTransform, + const Transform& boundTransform, + const gpu::BufferPointer& buffer); float computeFadeAlpha() const; @@ -108,6 +109,7 @@ public: void computeAdjustedLocalBound(const QVector& clusterMatrices); + gpu::BufferPointer _clusterBuffer; Model* _model; int _meshIndex; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 48c1d29b68..3cd0fc65f6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -227,6 +227,10 @@ void Model::updateRenderItems() { return; } + // lazy update of cluster matrices used for rendering. + // We need to update them here, so we can correctly update the bounding box. + self->updateClusterMatrices(); + render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; @@ -240,12 +244,12 @@ void Model::updateRenderItems() { Transform modelTransform = data._model->getTransform(); modelTransform.setScale(glm::vec3(1.0f)); - // lazy update of cluster matrices used for rendering. We need to update them here, so we can correctly update the bounding box. - data._model->updateClusterMatrices(); - - // update the model transform and bounding box for this render item. - const Model::MeshState& state = data._model->_meshStates.at(data._meshIndex); - data.updateTransformForSkinnedMesh(modelTransform, state.clusterMatrices); + const Model::MeshState& state = data._model->getMeshState(data._meshIndex); + Transform renderTransform = modelTransform; + if (state.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); } } }); From b8ded015c6d085b8b1a022bb3e09d4d74d87e0e6 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Mar 2017 14:37:43 -0700 Subject: [PATCH 37/47] Fix packetlist compilation on VS 2017 --- libraries/networking/src/udt/PacketQueue.cpp | 23 ++++++++++++-------- libraries/networking/src/udt/PacketQueue.h | 5 +++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index bb20982ca4..9560f2f187 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -15,6 +15,10 @@ using namespace udt; +PacketQueue::PacketQueue() { + _channels.emplace_back(new std::list()); +} + MessageNumber PacketQueue::getNextMessageNumber() { static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_SIZE; _currentMessageNumber = (_currentMessageNumber + 1) % MAX_MESSAGE_NUMBER; @@ -24,7 +28,7 @@ MessageNumber PacketQueue::getNextMessageNumber() { bool PacketQueue::isEmpty() const { LockGuard locker(_packetsLock); // Only the main channel and it is empty - return (_channels.size() == 1) && _channels.front().empty(); + return (_channels.size() == 1) && _channels.front()->empty(); } PacketQueue::PacketPointer PacketQueue::takePacket() { @@ -34,19 +38,19 @@ PacketQueue::PacketPointer PacketQueue::takePacket() { } // Find next non empty channel - if (_channels[nextIndex()].empty()) { + if (_channels[nextIndex()]->empty()) { nextIndex(); } auto& channel = _channels[_currentIndex]; - Q_ASSERT(!channel.empty()); + Q_ASSERT(!channel->empty()); // Take front packet - auto packet = std::move(channel.front()); - channel.pop_front(); + auto packet = std::move(channel->front()); + channel->pop_front(); // Remove now empty channel (Don't remove the main channel) - if (channel.empty() && _currentIndex != 0) { - channel.swap(_channels.back()); + if (channel->empty() && _currentIndex != 0) { + channel->swap(*_channels.back()); _channels.pop_back(); --_currentIndex; } @@ -61,7 +65,7 @@ unsigned int PacketQueue::nextIndex() { void PacketQueue::queuePacket(PacketPointer packet) { LockGuard locker(_packetsLock); - _channels.front().push_back(std::move(packet)); + _channels.front()->push_back(std::move(packet)); } void PacketQueue::queuePacketList(PacketListPointer packetList) { @@ -70,5 +74,6 @@ void PacketQueue::queuePacketList(PacketListPointer packetList) { } LockGuard locker(_packetsLock); - _channels.push_back(std::move(packetList->_packets)); + _channels.emplace_back(new std::list()); + _channels.back()->swap(packetList->_packets); } diff --git a/libraries/networking/src/udt/PacketQueue.h b/libraries/networking/src/udt/PacketQueue.h index 69784fd8db..2b3d3a4b5b 100644 --- a/libraries/networking/src/udt/PacketQueue.h +++ b/libraries/networking/src/udt/PacketQueue.h @@ -30,10 +30,11 @@ class PacketQueue { using LockGuard = std::lock_guard; using PacketPointer = std::unique_ptr; using PacketListPointer = std::unique_ptr; - using Channel = std::list; + using Channel = std::unique_ptr>; using Channels = std::vector; public: + PacketQueue(); void queuePacket(PacketPointer packet); void queuePacketList(PacketListPointer packetList); @@ -49,7 +50,7 @@ private: MessageNumber _currentMessageNumber { 0 }; mutable Mutex _packetsLock; // Protects the packets to be sent. - Channels _channels = Channels(1); // One channel per packet list + Main channel + Channels _channels; // One channel per packet list + Main channel unsigned int _currentIndex { 0 }; }; From cf848d73e4fd0dce38d6aafda2772893259b663b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Mar 2017 16:03:36 -0700 Subject: [PATCH 38/47] don't updateClusterMatrices() in render() --- libraries/render-utils/src/MeshPartPayload.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index d4b28dbddb..41a1bb4c74 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -582,11 +582,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { auto locations = args->_pipeline->locations; assert(locations); - // update the clusterMatrices if necessary - // TODO: we want to remove this updateClusterMatrices() call in this context - // but I recall we tried this before and broke something. - Andrew - _model->updateClusterMatrices(); - bindTransform(batch, locations, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed From 2837ae91832e67a26ad0daef3eb4ae27b3f173c1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Mar 2017 16:13:15 -0700 Subject: [PATCH 39/47] More VS 2017/2015 fixes --- .../src/DomainServerSettingsManager.cpp | 32 +++++++------------ libraries/networking/src/NodePermissions.h | 12 +++++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 661a6213b8..c3890d7ce5 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -246,10 +246,11 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList _agentPermissions[editorKey]->set(NodePermissions::Permission::canAdjustLocks); } - QList> permissionsSets; + QList> permissionsSets; permissionsSets << _standardAgentPermissions.get() << _agentPermissions.get(); foreach (auto permissionsSet, permissionsSets) { - foreach (NodePermissionsKey userKey, permissionsSet.keys()) { + for (auto entry : permissionsSet) { + const auto& userKey = entry.first; if (onlyEditorsAreRezzers) { if (permissionsSet[userKey]->can(NodePermissions::Permission::canAdjustLocks)) { permissionsSet[userKey]->set(NodePermissions::Permission::canRezPermanentEntities); @@ -1355,18 +1356,12 @@ QStringList DomainServerSettingsManager::getAllKnownGroupNames() { // extract all the group names from the group-permissions and group-forbiddens settings QSet result; - QHashIterator i(_groupPermissions.get()); - while (i.hasNext()) { - i.next(); - NodePermissionsKey key = i.key(); - result += key.first; + for (const auto& entry : _groupPermissions.get()) { + result += entry.first.first; } - QHashIterator j(_groupForbiddens.get()); - while (j.hasNext()) { - j.next(); - NodePermissionsKey key = j.key(); - result += key.first; + for (const auto& entry : _groupForbiddens.get()) { + result += entry.first.first; } return result.toList(); @@ -1377,20 +1372,17 @@ bool DomainServerSettingsManager::setGroupID(const QString& groupName, const QUu _groupIDs[groupName.toLower()] = groupID; _groupNames[groupID] = groupName; - QHashIterator i(_groupPermissions.get()); - while (i.hasNext()) { - i.next(); - NodePermissionsPointer perms = i.value(); + + for (const auto& entry : _groupPermissions.get()) { + auto& perms = entry.second; if (perms->getID().toLower() == groupName.toLower() && !perms->isGroup()) { changed = true; perms->setGroupID(groupID); } } - QHashIterator j(_groupForbiddens.get()); - while (j.hasNext()) { - j.next(); - NodePermissionsPointer perms = j.value(); + for (const auto& entry : _groupForbiddens.get()) { + auto& perms = entry.second; if (perms->getID().toLower() == groupName.toLower() && !perms->isGroup()) { changed = true; perms->setGroupID(groupID); diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index 091eb18909..6fa005e360 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -132,8 +132,16 @@ public: bool contains(const QString& keyFirst, const QUuid& keySecond) const { return 0 != _data.count(NodePermissionsKey(keyFirst.toLower(), keySecond)); } - //QList keys() const { return _data.keys(); } - std::unordered_map get() { return _data; } + + QList keys() const { + QList result; + for (const auto& entry : _data) { + result.push_back(entry.first); + } + return result; + } + + const std::unordered_map& get() { return _data; } void clear() { _data.clear(); } void remove(const NodePermissionsKey& key) { _data.erase(key); } From d3fa28d4bc25f484857079757756f87c752a7c75 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Mar 2017 16:17:59 -0700 Subject: [PATCH 40/47] remove cruft and fix indentation --- .../src/avatar/CauterizedMeshPartPayload.cpp | 6 +-- interface/src/avatar/CauterizedModel.cpp | 51 ++++++++----------- libraries/render-utils/src/Model.cpp | 12 ++--- 3 files changed, 30 insertions(+), 39 deletions(-) diff --git a/interface/src/avatar/CauterizedMeshPartPayload.cpp b/interface/src/avatar/CauterizedMeshPartPayload.cpp index 72a98bd994..d60f334442 100644 --- a/interface/src/avatar/CauterizedMeshPartPayload.cpp +++ b/interface/src/avatar/CauterizedMeshPartPayload.cpp @@ -21,7 +21,7 @@ CauterizedMeshPartPayload::CauterizedMeshPartPayload(Model* model, int meshIndex : ModelMeshPartPayload(model, meshIndex, partIndex, shapeIndex, transform, offsetTransform) {} void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( - const Transform& renderTransform, + const Transform& renderTransform, const gpu::BufferPointer& buffer) { _cauterizedTransform = renderTransform; _cauterizedClusterBuffer = buffer; @@ -33,12 +33,12 @@ void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::S SkeletonModel* skeleton = static_cast(_model); bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE) && skeleton->getEnableCauterization(); - if (useCauterizedMesh) { + if (useCauterizedMesh) { if (_cauterizedClusterBuffer) { batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _cauterizedClusterBuffer); } batch.setModelTransform(_cauterizedTransform); - } else { + } else { if (_clusterBuffer) { batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _clusterBuffer); } diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index 8ac14fcb6f..d8db83fbb7 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -26,8 +26,8 @@ CauterizedModel::~CauterizedModel() { } void CauterizedModel::deleteGeometry() { - Model::deleteGeometry(); - _cauterizeMeshStates.clear(); + Model::deleteGeometry(); + _cauterizeMeshStates.clear(); } bool CauterizedModel::updateGeometry() { @@ -41,7 +41,7 @@ bool CauterizedModel::updateGeometry() { _cauterizeMeshStates.append(state); } } - return needsFullUpdate; + return needsFullUpdate; } void CauterizedModel::createVisibleRenderItemSet() { @@ -86,13 +86,13 @@ void CauterizedModel::createVisibleRenderItemSet() { } } } else { - Model::createVisibleRenderItemSet(); + Model::createVisibleRenderItemSet(); } } void CauterizedModel::createCollisionRenderItemSet() { // Temporary HACK: use base class method for now - Model::createCollisionRenderItemSet(); + Model::createCollisionRenderItemSet(); } void CauterizedModel::updateClusterMatrices() { @@ -122,8 +122,8 @@ void CauterizedModel::updateClusterMatrices() { state.clusterBuffer->setSubData(0, state.clusterMatrices.size() * sizeof(glm::mat4), (const gpu::Byte*) state.clusterMatrices.constData()); } - } - } + } + } // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. if (!_cauterizeBoneSet.empty()) { @@ -212,31 +212,22 @@ void CauterizedModel::updateRenderItems() { if (data._model && data._model->isLoaded()) { // Ensure the model geometry was not reset between frames if (deleteGeometryCounter == data._model->getGeometryCounter()) { - // this stuff identical to what happens in regular Model - const Model::MeshState& state = data._model->getMeshState(data._meshIndex); - Transform renderTransform = modelTransform; - if (state.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); - } - data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); - - // this stuff for cauterized mesh - CauterizedModel* cModel = static_cast(data._model); - const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); - renderTransform = modelTransform; - if (cState.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); - } - data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer); - -/* - // update the model transform and bounding box for this render item. + // this stuff identical to what happens in regular Model const Model::MeshState& state = data._model->getMeshState(data._meshIndex); + Transform renderTransform = modelTransform; + if (state.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); + } + data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); + + // this stuff for cauterized mesh CauterizedModel* cModel = static_cast(data._model); - assert(data._meshIndex < cModel->_cauterizeMeshStates.size()); - const Model::MeshState& cState = cModel->_cauterizeMeshStates.at(data._meshIndex); - data.updateTransformForSkinnedCauterizedMesh(modelTransform, state.clusterMatrices, cState.clusterMatrices); -*/ + const Model::MeshState& cState = cModel->getCauterizeMeshState(data._meshIndex); + renderTransform = modelTransform; + if (cState.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(cState.clusterMatrices[0])); + } + data.updateTransformForCauterizedMesh(renderTransform, cState.clusterBuffer); } } }); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3cd0fc65f6..c584b0bc21 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -228,7 +228,7 @@ void Model::updateRenderItems() { } // lazy update of cluster matrices used for rendering. - // We need to update them here, so we can correctly update the bounding box. + // We need to update them here so we can correctly update the bounding box. self->updateClusterMatrices(); render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); @@ -245,10 +245,10 @@ void Model::updateRenderItems() { modelTransform.setScale(glm::vec3(1.0f)); const Model::MeshState& state = data._model->getMeshState(data._meshIndex); - Transform renderTransform = modelTransform; - if (state.clusterMatrices.size() == 1) { - renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); - } + Transform renderTransform = modelTransform; + if (state.clusterMatrices.size() == 1) { + renderTransform = modelTransform.worldTransform(Transform(state.clusterMatrices[0])); + } data.updateTransformForSkinnedMesh(renderTransform, modelTransform, state.clusterBuffer); } } @@ -1052,7 +1052,7 @@ void Model::updateRig(float deltaTime, glm::mat4 parentTransform) { } void Model::computeMeshPartLocalBounds() { - for (auto& part : _modelMeshRenderItemsSet) { + for (auto& part : _modelMeshRenderItemsSet) { assert(part->_meshIndex < _modelMeshRenderItemsSet.size()); const Model::MeshState& state = _meshStates.at(part->_meshIndex); part->computeAdjustedLocalBound(state.clusterMatrices); From 361e03fc78786da67554d75cf7c81d9e7db02536 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Mar 2017 16:57:31 -0700 Subject: [PATCH 41/47] remove unused variable --- interface/src/avatar/CauterizedMeshPartPayload.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/CauterizedMeshPartPayload.cpp b/interface/src/avatar/CauterizedMeshPartPayload.cpp index d60f334442..c11f92083b 100644 --- a/interface/src/avatar/CauterizedMeshPartPayload.cpp +++ b/interface/src/avatar/CauterizedMeshPartPayload.cpp @@ -29,7 +29,6 @@ void CauterizedMeshPartPayload::updateTransformForCauterizedMesh( void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { // Still relying on the raw data from the model - const Model::MeshState& state = _model->getMeshState(_meshIndex); SkeletonModel* skeleton = static_cast(_model); bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE) && skeleton->getEnableCauterization(); From 4367e3d036ddfa8359459b2d86acb06254727fdd Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 15 Mar 2017 18:13:10 -0700 Subject: [PATCH 42/47] PR comments --- domain-server/src/DomainServerSettingsManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index c3890d7ce5..d6b57b450a 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -246,8 +246,10 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList _agentPermissions[editorKey]->set(NodePermissions::Permission::canAdjustLocks); } - QList> permissionsSets; - permissionsSets << _standardAgentPermissions.get() << _agentPermissions.get(); + std::list> permissionsSets{ + _standardAgentPermissions.get(), + _agentPermissions.get() + }; foreach (auto permissionsSet, permissionsSets) { for (auto entry : permissionsSet) { const auto& userKey = entry.first; @@ -301,7 +303,6 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList } QVariantMap& DomainServerSettingsManager::getDescriptorsMap() { - static const QString DESCRIPTORS{ "descriptors" }; auto& settingsMap = getSettingsMap(); From 60d10f3374c9bb7459570558f7052216e9fac5d9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Mar 2017 20:44:19 -0700 Subject: [PATCH 43/47] command-line utility for fetching an asset from a remote asset-server --- tools/CMakeLists.txt | 2 + tools/atp-get/CMakeLists.txt | 3 + tools/atp-get/src/ATPGetApp.cpp | 269 ++++++++++++++++++++++++++++++++ tools/atp-get/src/ATPGetApp.h | 52 ++++++ tools/atp-get/src/main.cpp | 31 ++++ 5 files changed, 357 insertions(+) create mode 100644 tools/atp-get/CMakeLists.txt create mode 100644 tools/atp-get/src/ATPGetApp.cpp create mode 100644 tools/atp-get/src/ATPGetApp.h create mode 100644 tools/atp-get/src/main.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a85a112bf5..16aa17cd7b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -17,3 +17,5 @@ set_target_properties(ac-client PROPERTIES FOLDER "Tools") add_subdirectory(skeleton-dump) set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") +add_subdirectory(atp-get) +set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") diff --git a/tools/atp-get/CMakeLists.txt b/tools/atp-get/CMakeLists.txt new file mode 100644 index 0000000000..b1646dc023 --- /dev/null +++ b/tools/atp-get/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET_NAME atp-get) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared networking) diff --git a/tools/atp-get/src/ATPGetApp.cpp b/tools/atp-get/src/ATPGetApp.cpp new file mode 100644 index 0000000000..30054fffea --- /dev/null +++ b/tools/atp-get/src/ATPGetApp.cpp @@ -0,0 +1,269 @@ +// +// ATPGetApp.cpp +// tools/atp-get/src +// +// Created by Seth Alves on 2017-3-15 +// Copyright 2017 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 +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ATPGetApp.h" + +ATPGetApp::ATPGetApp(int argc, char* argv[]) : + QCoreApplication(argc, argv) +{ + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity ATP-Get"); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + + const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); + parser.addOption(domainAddressOption); + + const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); + parser.addOption(cacheSTUNOption); + + const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); + parser.addOption(listenPortOption); + + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + _verbose = parser.isSet(verboseOutput); + if (!_verbose) { + QLoggingCategory::setFilterRules("qt.network.ssl.warning=false"); + + const_cast(&networking())->setEnabled(QtDebugMsg, false); + const_cast(&networking())->setEnabled(QtInfoMsg, false); + const_cast(&networking())->setEnabled(QtWarningMsg, false); + + const_cast(&shared())->setEnabled(QtDebugMsg, false); + const_cast(&shared())->setEnabled(QtInfoMsg, false); + const_cast(&shared())->setEnabled(QtWarningMsg, false); + } + + + QStringList filenames = parser.positionalArguments(); + if (filenames.empty() || filenames.size() > 2) { + qDebug() << "give remote url and optional local filename as arguments"; + parser.showHelp(); + Q_UNREACHABLE(); + } + + _url = QUrl(filenames[0]); + if (_url.scheme() != "atp") { + qDebug() << "url should start with atp:"; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (filenames.size() == 2) { + _localOutputFile = filenames[1]; + } + + QString domainServerAddress = "127.0.0.1:40103"; + if (parser.isSet(domainAddressOption)) { + domainServerAddress = parser.value(domainAddressOption); + } + + if (_verbose) { + qDebug() << "domain-server address is" << domainServerAddress; + } + + int listenPort = INVALID_PORT; + if (parser.isSet(listenPortOption)) { + listenPort = parser.value(listenPortOption).toInt(); + } + + Setting::init(); + DependencyManager::registerInheritance(); + + DependencyManager::set([&]{ return QString("Mozilla/5.0 (HighFidelityATPGet)"); }); + DependencyManager::set(); + DependencyManager::set(NodeType::Agent, listenPort); + + + auto nodeList = DependencyManager::get(); + + // start the nodeThread so its event loop is running + QThread* nodeThread = new QThread(this); + nodeThread->setObjectName("NodeList Thread"); + nodeThread->start(); + + // make sure the node thread is given highest priority + nodeThread->setPriority(QThread::TimeCriticalPriority); + + // setup a timer for domain-server check ins + QTimer* domainCheckInTimer = new QTimer(nodeList.data()); + connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); + domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); + + // put the NodeList and datagram processing on the node thread + nodeList->moveToThread(nodeThread); + + const DomainHandler& domainHandler = nodeList->getDomainHandler(); + + connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); + // connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); + // connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); + connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPGetApp::domainConnectionRefused); + + connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPGetApp::nodeAdded); + connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPGetApp::nodeKilled); + connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPGetApp::nodeActivated); + // connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID); + // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPGetApp::setSessionUUID); + connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPGetApp::notifyPacketVersionMismatch); + + nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer + << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); + + DependencyManager::get()->handleLookupString(domainServerAddress, false); + + auto assetClient = DependencyManager::set(); + assetClient->init(); + + QTimer* doTimer = new QTimer(this); + doTimer->setSingleShot(true); + connect(doTimer, &QTimer::timeout, this, &ATPGetApp::timedOut); + doTimer->start(4000); +} + +ATPGetApp::~ATPGetApp() { +} + + +void ATPGetApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { + qDebug() << "domainConnectionRefused"; +} + +void ATPGetApp::domainChanged(const QString& domainHostname) { + if (_verbose) { + qDebug() << "domainChanged"; + } +} + +void ATPGetApp::nodeAdded(SharedNodePointer node) { + if (_verbose) { + qDebug() << "node added: " << node->getType(); + } +} + +void ATPGetApp::nodeActivated(SharedNodePointer node) { + if (node->getType() == NodeType::AssetServer) { + lookup(); + } +} + +void ATPGetApp::nodeKilled(SharedNodePointer node) { + qDebug() << "nodeKilled"; +} + +void ATPGetApp::timedOut() { + finish(1); +} + +void ATPGetApp::notifyPacketVersionMismatch() { + if (_verbose) { + qDebug() << "packet version mismatch"; + } + finish(1); +} + +void ATPGetApp::lookup() { + + auto path = _url.path(); + qDebug() << "path is " << path; + + auto request = DependencyManager::get()->createGetMappingRequest(path); + QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { + auto result = request->getError(); + if (result == GetMappingRequest::NotFound) { + qDebug() << "not found"; + } else if (result == GetMappingRequest::NoError) { + qDebug() << "found, hash is " << request->getHash(); + download(request->getHash()); + } else { + qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString(); + } + request->deleteLater(); + }); + request->start(); +} + +void ATPGetApp::download(AssetHash hash) { + auto assetClient = DependencyManager::get(); + auto assetRequest = new AssetRequest(hash); + + connect(assetRequest, &AssetRequest::finished, this, [this](AssetRequest* request) mutable { + Q_ASSERT(request->getState() == AssetRequest::Finished); + + if (request->getError() == AssetRequest::Error::NoError) { + QString data = QString::fromUtf8(request->getData()); + if (_localOutputFile == "") { + QTextStream cout(stdout); + cout << data; + } else { + QFile outputHandle(_localOutputFile); + if (outputHandle.open(QIODevice::ReadWrite)) { + QTextStream stream( &outputHandle ); + stream << data; + } else { + qDebug() << "couldn't open output file:" << _localOutputFile; + } + } + } + + request->deleteLater(); + finish(0); + }); + + assetRequest->start(); +} + +void ATPGetApp::finish(int exitCode) { + auto nodeList = DependencyManager::get(); + + // send the domain a disconnect packet, force stoppage of domain-server check-ins + nodeList->getDomainHandler().disconnect(); + nodeList->setIsShuttingDown(true); + + // tell the packet receiver we're shutting down, so it can drop packets + nodeList->getPacketReceiver().setShouldDropPackets(true); + + QThread* nodeThread = DependencyManager::get()->thread(); + // remove the NodeList from the DependencyManager + DependencyManager::destroy(); + // ask the node thread to quit and wait until it is done + nodeThread->quit(); + nodeThread->wait(); + + QCoreApplication::exit(exitCode); +} diff --git a/tools/atp-get/src/ATPGetApp.h b/tools/atp-get/src/ATPGetApp.h new file mode 100644 index 0000000000..5507d2aa62 --- /dev/null +++ b/tools/atp-get/src/ATPGetApp.h @@ -0,0 +1,52 @@ +// +// ATPGetApp.h +// tools/atp-get/src +// +// Created by Seth Alves on 2017-3-15 +// Copyright 2017 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_ATPGetApp_h +#define hifi_ATPGetApp_h + +#include +#include +#include +#include +#include +#include +#include +#include + + +class ATPGetApp : public QCoreApplication { + Q_OBJECT +public: + ATPGetApp(int argc, char* argv[]); + ~ATPGetApp(); + +private slots: + void domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo); + void domainChanged(const QString& domainHostname); + void nodeAdded(SharedNodePointer node); + void nodeActivated(SharedNodePointer node); + void nodeKilled(SharedNodePointer node); + void notifyPacketVersionMismatch(); + +private: + NodeList* _nodeList; + void timedOut(); + void lookup(); + void download(AssetHash hash); + void finish(int exitCode); + bool _verbose; + + QUrl _url; + QString _localOutputFile; +}; + +#endif // hifi_ATPGetApp_h diff --git a/tools/atp-get/src/main.cpp b/tools/atp-get/src/main.cpp new file mode 100644 index 0000000000..bddf30c666 --- /dev/null +++ b/tools/atp-get/src/main.cpp @@ -0,0 +1,31 @@ +// +// main.cpp +// tools/atp-get/src +// +// Created by Seth Alves on 2017-3-15 +// Copyright 2017 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 + +#include +#include +#include +#include + +#include + +#include "ATPGetApp.h" + +using namespace std; + +int main(int argc, char * argv[]) { + QCoreApplication::setApplicationName(BuildInfo::AC_CLIENT_SERVER_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + + ATPGetApp app(argc, argv); + + return app.exec(); +} From 438fb42da45cc429d82a33a0b15f54bd07599601 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Mar 2017 20:54:08 -0700 Subject: [PATCH 44/47] oops --- tools/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 16aa17cd7b..8dc993e6fe 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -18,4 +18,4 @@ add_subdirectory(skeleton-dump) set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") add_subdirectory(atp-get) -set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") +set_target_properties(atp-get PROPERTIES FOLDER "Tools") From e7a16d4294a26c724b5f30dabf504088227ed7c9 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Thu, 16 Mar 2017 10:53:35 -0700 Subject: [PATCH 45/47] code standard fixes --- interface/src/ui/BaseLogDialog.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/BaseLogDialog.cpp b/interface/src/ui/BaseLogDialog.cpp index c316206e7a..571d3ac403 100644 --- a/interface/src/ui/BaseLogDialog.cpp +++ b/interface/src/ui/BaseLogDialog.cpp @@ -29,6 +29,7 @@ const int SEARCH_BUTTON_WIDTH = 20; const int SEARCH_TOGGLE_BUTTON_WIDTH = 50; const int SEARCH_TEXT_WIDTH = 240; const int TIME_STAMP_LENGTH = 16; +const int FONT_WEIGHT = 75; const QColor HIGHLIGHT_COLOR = QColor("#3366CC"); const QColor BOLD_COLOR = QColor("#445c8c"); const QString BOLD_PATTERN = "\\[\\d*\\/.*:\\d*:\\d*\\]"; @@ -38,7 +39,7 @@ public: Highlighter(QTextDocument* parent = nullptr); void setBold(int indexToBold); QString keyword; - + protected: void highlightBlock(const QString& text) override; @@ -94,7 +95,7 @@ void BaseLogDialog::initControls() { _leftPad += SEARCH_TOGGLE_BUTTON_WIDTH + BUTTON_MARGIN; _searchPrevButton->show(); connect(_searchPrevButton, SIGNAL(clicked()), SLOT(toggleSearchPrev())); - + _searchNextButton = new QPushButton(this); _searchNextButton->setObjectName("searchNextButton"); _searchNextButton->setGeometry(_leftPad, ELEMENT_MARGIN, SEARCH_TOGGLE_BUTTON_WIDTH, ELEMENT_HEIGHT); @@ -134,7 +135,7 @@ void BaseLogDialog::handleSearchTextChanged(QString searchText) { if (searchText.isEmpty()) { return; } - + QTextCursor cursor = _logTextBox->textCursor(); if (cursor.hasSelection()) { QString selectedTerm = cursor.selectedText(); @@ -142,16 +143,16 @@ void BaseLogDialog::handleSearchTextChanged(QString searchText) { return; } } - + cursor.setPosition(0, QTextCursor::MoveAnchor); _logTextBox->setTextCursor(cursor); bool foundTerm = _logTextBox->find(searchText); - + if (!foundTerm) { cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); _logTextBox->setTextCursor(cursor); } - + _searchTerm = searchText; _highlighter->keyword = searchText; _highlighter->rehighlight(); @@ -195,10 +196,10 @@ void BaseLogDialog::updateSelection() { } Highlighter::Highlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) { - boldFormat.setFontWeight(75); + boldFormat.setFontWeight(FONT_WEIGHT); boldFormat.setForeground(BOLD_COLOR); keywordFormat.setForeground(HIGHLIGHT_COLOR); - } +} void Highlighter::highlightBlock(const QString& text) { QRegExp expression(BOLD_PATTERN); @@ -206,11 +207,11 @@ void Highlighter::highlightBlock(const QString& text) { int index = text.indexOf(expression, 0); while (index >= 0) { - int length = expression.matchedLength(); - setFormat(index, length, boldFormat); - index = text.indexOf(expression, index + length); + int length = expression.matchedLength(); + setFormat(index, length, boldFormat); + index = text.indexOf(expression, index + length); } - + if (keyword.isNull() || keyword.isEmpty()) { return; } From 3b8c82491a74bfafdd6d230591e9230d8f883f93 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 13 Mar 2017 19:27:00 -0400 Subject: [PATCH 46/47] add AudioNoiseGate to Agent --- assignment-client/src/Agent.cpp | 24 +++++++++++++++++++----- assignment-client/src/Agent.h | 2 ++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 3562975c4d..a0c80453e0 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -371,25 +371,39 @@ void Agent::executeScript() { using namespace recording; static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::getAudioFrameName()); Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) { - const QByteArray& audio = frame->data; static quint16 audioSequenceNumber{ 0 }; - Transform audioTransform; + QByteArray audio(frame->data); + + if (_isNoiseGateEnabled) { + static int numSamples = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; + _noiseGate.gateSamples(reinterpret_cast(audio.data()), numSamples); + } + + computeLoudness(&audio, scriptedAvatar); + + // the codec needs a flush frame before sending silent packets, so + // do not send one if the gate closed in this block (eventually this can be crossfaded). + auto packetType = PacketType::MicrophoneAudioNoEcho; + if (scriptedAvatar->getAudioLoudness() == 0.0f && !_noiseGate.closedInLastBlock()) { + packetType = PacketType::SilentAudioFrame; + } + + Transform audioTransform; auto headOrientation = scriptedAvatar->getHeadOrientation(); audioTransform.setTranslation(scriptedAvatar->getPosition()); audioTransform.setRotation(headOrientation); - computeLoudness(&audio, scriptedAvatar); - QByteArray encodedBuffer; if (_encoder) { _encoder->encode(audio, encodedBuffer); } else { encodedBuffer = audio; } + AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber, audioTransform, scriptedAvatar->getPosition(), glm::vec3(0), - PacketType::MicrophoneAudioNoEcho, _selectedCodecName); + packetType, _selectedCodecName); }); auto avatarHashMap = DependencyManager::set(); diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 6bece4e945..620ac8e047 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -29,6 +29,7 @@ #include +#include "AudioNoiseGate.h" #include "MixedAudioStream.h" #include "avatars/ScriptableAvatar.h" @@ -110,6 +111,7 @@ private: QTimer* _avatarIdentityTimer = nullptr; QHash _outgoingScriptAudioSequenceNumbers; + AudioNoiseGate _noiseGate; bool _isNoiseGateEnabled { false }; CodecPluginPointer _codec; From 0cee9ee172e6d864af514a386e2b72c7fba4af6d Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Thu, 16 Mar 2017 11:57:46 -0700 Subject: [PATCH 47/47] font change --- interface/resources/styles/log_dialog.qss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/styles/log_dialog.qss b/interface/resources/styles/log_dialog.qss index 9ce5aeccc2..d3ae4e0a00 100644 --- a/interface/resources/styles/log_dialog.qss +++ b/interface/resources/styles/log_dialog.qss @@ -1,6 +1,6 @@ QPlainTextEdit { - font-family: Courier New, Courier, Monotype; + font-family: Inconsolata, Consolas, Courier New, monospace; font-size: 16px; padding-left: 28px; padding-top: 7px; @@ -11,7 +11,7 @@ QPlainTextEdit { } QLineEdit { - font-family: Courier New, Courier, Monotype; + font-family: Inconsolata, Consolas, Courier New, monospace; padding-left: 7px; background-color: #CCCCCC; border-width: 0;