diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 965cb70ec6..48530b9351 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -33,7 +33,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo Download and install the latest version of CMake 3.9. -Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. +Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.14 Version page](https://cmake.org/files/v3.14/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. ### Step 3. Create VCPKG environment variable In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them. diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 358b05222c..c3a4a94c7c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -739,6 +739,10 @@ void DomainServer::setupNodeListAndAssignments() { connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); + connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, this, + [this](const HifiSockAddr& localSockAddr) { + DependencyManager::get()->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, localSockAddr.getPort()); + }); // register as the packet receiver for the types we want PacketReceiver& packetReceiver = nodeList->getPacketReceiver(); diff --git a/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml b/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml index a6be398e53..becbd8ca61 100644 --- a/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml +++ b/interface/resources/qml/hifi/simplifiedUI/avatarApp/components/DisplayNameHeader.qml @@ -94,6 +94,7 @@ Item { text: MyAvatar.sessionDisplayName === "" ? MyAvatar.displayName : MyAvatar.sessionDisplayName maximumLength: 256 clip: true + selectByMouse: true anchors.fill: parent onEditingFinished: { if (MyAvatar.displayName !== text) { diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml index adb8344902..1f48d1d753 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/SettingsApp.qml @@ -17,6 +17,7 @@ import "./audio" as AudioSettings import "./general" as GeneralSettings import "./vr" as VrSettings import "./dev" as DevSettings +import "./about" as AboutSettings Rectangle { property string activeTabView: "generalTabView" @@ -76,6 +77,10 @@ Rectangle { tabTitle: "VR" tabViewName: "vrTabView" } + ListElement { + tabTitle: "About" + tabViewName: "aboutTabView" + } ListElement { tabTitle: "Dev" tabViewName: "devTabView" @@ -103,7 +108,7 @@ Rectangle { delegate: Item { visible: model.tabTitle !== "Dev" || (model.tabTitle === "Dev" && root.developerModeEnabled) - width: tabTitleText.paintedWidth + 64 + width: tabTitleText.paintedWidth + 32 height: parent.height HifiStylesUit.GraphikRegular { @@ -163,6 +168,12 @@ Rectangle { anchors.fill: parent } + AboutSettings.About { + id: aboutTabViewContainer + visible: activeTabView === "aboutTabView" + anchors.fill: parent + } + SimplifiedControls.VerticalScrollBar { parent: { if (activeTabView === "generalTabView") { @@ -173,6 +184,8 @@ Rectangle { vrTabViewContainer } else if (activeTabView === "devTabView") { devTabViewContainer + } else if (activeTabView === "aboutTabView") { + aboutTabViewContainer } } } diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml new file mode 100644 index 0000000000..76ab762a6b --- /dev/null +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/About.qml @@ -0,0 +1,218 @@ +// +// About.qml +// +// Created by Zach Fox on 2019-06-18 +// Copyright 2019 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 +// + +import QtQuick 2.10 +import QtQuick.Controls 2.3 +import "../../simplifiedConstants" as SimplifiedConstants +import "../../simplifiedControls" as SimplifiedControls +import stylesUit 1.0 as HifiStylesUit +import QtQuick.Layouts 1.3 + +Flickable { + id: root + contentWidth: parent.width + contentHeight: aboutColumnLayout.height + clip: true + + onVisibleChanged: { + if (visible) { + root.contentX = 0; + root.contentY = 0; + } + } + + + SimplifiedConstants.SimplifiedConstants { + id: simplifiedUI + } + + + ColumnLayout { + id: aboutColumnLayout + anchors.left: parent.left + anchors.leftMargin: 26 + anchors.right: parent.right + anchors.rightMargin: 26 + anchors.top: parent.top + spacing: 0 + + Image { + source: "images/logo.png" + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 16 + Layout.preferredWidth: 200 + Layout.preferredHeight: 150 + fillMode: Image.PreserveAspectFit + mipmap: true + } + + ColumnLayout { + id: platformInfoContainer + Layout.preferredWidth: parent.width + Layout.bottomMargin: 24 + spacing: 0 + + HifiStylesUit.GraphikSemiBold { + text: "Version " + Window.checkVersion() + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikSemiBold { + text: "Platform Info" + Layout.maximumWidth: parent.width + Layout.topMargin: 8 + Layout.bottomMargin: 8 + height: paintedHeight + size: 22 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "Computer Vendor/Model:" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + + Component.onCompleted: { + var computer = JSON.parse(PlatformInfo.getComputer()); + var computerVendor = computer.vendor; + if (computerVendor.length === 0) { + computerVendor = "Unknown"; + } + var computerModel = computer.model; + if (computerModel.length === 0) { + computerModel = "Unknown"; + } + + text = "Computer Vendor/Model: " + computerVendor + "/" + computerModel; + } + } + + HifiStylesUit.GraphikRegular { + text: "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "OS Type: " + PlatformInfo.getOperatingSystemType() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "CPU: " + PlatformInfo.getCPUBrand() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "# CPUs: " + PlatformInfo.getNumCPUs() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB" + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "GPU: " + PlatformInfo.getGraphicsCardType() + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + HifiStylesUit.GraphikRegular { + text: "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")) + Layout.maximumWidth: parent.width + height: paintedHeight + size: 16 + color: simplifiedUI.colors.text.white + wrapMode: Text.Wrap + } + + SimplifiedControls.Button { + Layout.topMargin: 8 + width: 200 + height: 32 + text: "Copy to Clipboard" + + onClicked: { + Window.copyToClipboard(root.buildPlatformInfoTextToCopy()); + } + } + } + } + + function buildPlatformInfoTextToCopy() { + var textToCopy = "**About Interface**\n"; + textToCopy += "Interface Version: " + Window.checkVersion() + "\n"; + textToCopy += "\n**Platform Info**\n"; + + var computer = JSON.parse(PlatformInfo.getComputer()); + var computerVendor = computer.vendor; + if (computerVendor.length === 0) { + computerVendor = "Unknown"; + } + var computerModel = computer.model; + if (computerModel.length === 0) { + computerModel = "Unknown"; + } + + textToCopy += "Computer Vendor/Model: " + computerVendor + "/" + computerModel + "\n"; + textToCopy += "Profiled Platform Tier: " + PlatformInfo.getTierProfiled() + "\n"; + textToCopy += "OS Type: " + PlatformInfo.getOperatingSystemType() + "\n"; + textToCopy += "CPU: " + PlatformInfo.getCPUBrand() + "\n"; + textToCopy += "# CPUs: " + PlatformInfo.getNumCPUs() + "\n"; + textToCopy += "# CPU Cores: " + PlatformInfo.getNumLogicalCores() + "\n"; + textToCopy += "RAM: " + PlatformInfo.getTotalSystemMemoryMB() + " MB\n"; + textToCopy += "GPU: " + PlatformInfo.getGraphicsCardType() + "\n"; + textToCopy += "VR Hand Controllers: " + (PlatformInfo.hasRiftControllers() ? "Rift" : (PlatformInfo.hasViveControllers() ? "Vive" : "None")); + + return textToCopy; + } +} diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/images/logo.png b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/images/logo.png new file mode 100644 index 0000000000..d480da86dd Binary files /dev/null and b/interface/resources/qml/hifi/simplifiedUI/settingsApp/about/images/logo.png differ diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3800a330bb..aba74806c0 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1416,6 +1416,10 @@ void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) { } } +void MyAvatar::setDebugDrawAnimPoseName(QString poseName) { + _debugDrawAnimPoseName.set(poseName); +} + void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) { if (isEnabled) { const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f); @@ -3086,15 +3090,26 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { } if (_enableDebugDrawAnimPose && animSkeleton) { - // build absolute AnimPoseVec from rig + AnimPoseVec absPoses; const Rig& rig = _skeletonModel->getRig(); - absPoses.reserve(rig.getJointStateCount()); - for (int i = 0; i < rig.getJointStateCount(); i++) { - absPoses.push_back(AnimPose(rig.getJointTransform(i))); + const glm::vec4 CYAN(0.1f, 0.6f, 0.6f, 1.0f); + + QString name = _debugDrawAnimPoseName.get(); + if (name.isEmpty()) { + // build absolute AnimPoseVec from rig transforms. i.e. the same that are used for rendering. + absPoses.reserve(rig.getJointStateCount()); + for (int i = 0; i < rig.getJointStateCount(); i++) { + absPoses.push_back(AnimPose(rig.getJointTransform(i))); + } + AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN); + } else { + AnimNode::ConstPointer node = rig.findAnimNodeByName(name); + if (node) { + rig.buildAbsoluteRigPoses(node->getPoses(), absPoses); + AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, CYAN); + } } - glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f); - AnimDebugDraw::getInstance().addAbsolutePoses("myAvatarAnimPoses", animSkeleton, absPoses, xform, cyan); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d60c023caa..f31e6e524e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2018,12 +2018,20 @@ public slots: void setEnableDebugDrawDefaultPose(bool isEnabled); /**jsdoc - * Displays animation debug graphics. + * Displays animation debug graphics. By default it shows the animation poses used for rendering. + * However, the property MyAvatar.setDebugDrawAnimPoseName can be used to draw a specific animation node. * @function MyAvatar.setEnableDebugDrawAnimPose * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawAnimPose(bool isEnabled); + /**jsdoc + * If set it determines which animation debug graphics to draw, when MyAvatar.setEnableDebugDrawAnimPose is set to true. + * @function MyAvatar.setDebugDrawAnimPoseName + * @param {boolean} enabled - true to show the debug graphics, false to hide. + */ + void setDebugDrawAnimPoseName(QString poseName); + /**jsdoc * Displays position debug graphics. * @function MyAvatar.setEnableDebugDrawPosition @@ -2666,6 +2674,8 @@ private: bool _enableDebugDrawIKChains { false }; bool _enableDebugDrawDetailedCollision { false }; + ThreadSafeValueCache _debugDrawAnimPoseName; + mutable bool _cauterizationNeedsUpdate { false }; // do we need to scan children and update their "cauterized" state? AudioListenerMode _audioListenerMode; diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 1a922e507d..e5edb46f69 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -10,10 +10,13 @@ #include "AnimClip.h" +#include + #include "GLMHelpers.h" #include "AnimationLogging.h" #include "AnimUtil.h" + AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) : AnimNode(AnimNode::Type::Clip, id), _startFrame(startFrame), @@ -107,6 +110,19 @@ static std::vector buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons return jointIndexMap; } +#ifdef USE_CUSTOM_ASSERT +#undef ASSERT +#define ASSERT(x) \ + do { \ + if (!(x)) { \ + int* bad_ptr = 0; \ + *bad_ptr = 0x0badf00d; \ + } \ + } while (0) +#else +#define ASSERT assert +#endif + void AnimClip::copyFromNetworkAnim() { assert(_networkAnim && _networkAnim->isLoaded() && _skeleton); _anim.clear(); @@ -165,11 +181,14 @@ void AnimClip::copyFromNetworkAnim() { for (int frame = 0; frame < animFrameCount; frame++) { const HFMAnimationFrame& animFrame = animModel.animationFrames[frame]; + ASSERT(frame >= 0 && frame < (int)animModel.animationFrames.size()); // extract the full rotations from the animFrame (including pre and post rotations from the animModel). std::vector animRotations; animRotations.reserve(animJointCount); for (int i = 0; i < animJointCount; i++) { + ASSERT(i >= 0 && i < (int)animModel.joints.size()); + ASSERT(i >= 0 && i < (int)animFrame.rotations.size()); animRotations.push_back(animModel.joints[i].preRotation * animFrame.rotations[i] * animModel.joints[i].postRotation); } @@ -180,10 +199,12 @@ void AnimClip::copyFromNetworkAnim() { std::vector avatarRotations; avatarRotations.reserve(avatarJointCount); for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) { + ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size()); int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex]; if (animJointIndex >= 0) { // This joint is in both animation and avatar. // Set the absolute rotation directly + ASSERT(animJointIndex >= 0 && animJointIndex < (int)animRotations.size()); avatarRotations.push_back(animRotations[animJointIndex]); } else { // This joint is NOT in the animation at all. @@ -192,6 +213,7 @@ void AnimClip::copyFromNetworkAnim() { glm::quat avatarParentAbsoluteRot; int avatarParentJointIndex = avatarSkeleton->getParentIndex(avatarJointIndex); if (avatarParentJointIndex >= 0) { + ASSERT(avatarParentJointIndex >= 0 && avatarParentJointIndex < (int)avatarRotations.size()); avatarParentAbsoluteRot = avatarRotations[avatarParentJointIndex]; } avatarRotations.push_back(avatarParentAbsoluteRot * avatarRelativeDefaultRot); @@ -201,6 +223,7 @@ void AnimClip::copyFromNetworkAnim() { // convert avatar rotations into relative frame avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations); + ASSERT(frame >= 0 && frame < (int)_anim.size()); _anim[frame].reserve(avatarJointCount); for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) { const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex); @@ -209,12 +232,15 @@ void AnimClip::copyFromNetworkAnim() { glm::vec3 relativeScale = avatarDefaultPose.scale(); glm::vec3 relativeTranslation; + ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarToAnimJointIndexMap.size()); int animJointIndex = avatarToAnimJointIndexMap[avatarJointIndex]; if (animJointIndex >= 0) { // This joint is in both animation and avatar. + ASSERT(animJointIndex >= 0 && animJointIndex < (int)animFrame.translations.size()); const glm::vec3& animTrans = animFrame.translations[animJointIndex]; // retarget translation from animation to avatar + ASSERT(animJointIndex >= 0 && animJointIndex < (int)animModel.animationFrames[0].translations.size()); const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex]; relativeTranslation = avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans); } else { @@ -224,6 +250,7 @@ void AnimClip::copyFromNetworkAnim() { } // build the final pose + ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarRotations.size()); _anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation)); } } diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 31e10ca2d5..ec5f2b7375 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -98,6 +98,8 @@ public: return result; } + const AnimPoseVec& getPoses() const { return getPosesInternal(); } + protected: virtual void setCurrentFrameInternal(float frame) {} diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 633a505d14..a58b8745d7 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -2232,6 +2232,14 @@ void Rig::initAnimGraph(const QUrl& url) { } } +AnimNode::ConstPointer Rig::findAnimNodeByName(const QString& name) const { + if (_animNode) { + return _animNode->findByName(name); + } else { + return nullptr; + } +} + bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const { if (_animSkeleton && _rootJointIndex >= 0) { modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteDefaultPose(_rootJointIndex).trans(); @@ -2258,7 +2266,7 @@ void Rig::applyOverridePoses() { } } -void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) { +void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const { DETAILED_PERFORMANCE_TIMER("buildAbsolute"); if (!_animSkeleton) { return; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 786d14200e..02fa965f64 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -196,6 +196,7 @@ public: void initAnimGraph(const QUrl& url); AnimNode::ConstPointer getAnimNode() const { return _animNode; } + AnimNode::ConstPointer findAnimNodeByName(const QString& name) const; AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; } QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList); void removeAnimationStateHandler(QScriptValue handler); @@ -243,7 +244,7 @@ public: Flow& getFlow() { return _internalFlow; } float getUnscaledEyeHeight() const; - + void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) const; signals: void onLoadComplete(); @@ -252,7 +253,6 @@ protected: bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); } void updateAnimationStateHandlers(); void applyOverridePoses(); - void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut); void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix); void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated, diff --git a/libraries/audio/src/AudioReverb.cpp b/libraries/audio/src/AudioReverb.cpp index a7c6fefd39..26f5528866 100644 --- a/libraries/audio/src/AudioReverb.cpp +++ b/libraries/audio/src/AudioReverb.cpp @@ -35,16 +35,6 @@ static const double SQRT2 = 1.41421356237309504880; static const double FIXQ31 = 2147483648.0; static const double FIXQ32 = 4294967296.0; -// Round an integer to the next power-of-two, at compile time. -// VS2013 does not support constexpr so macros are used instead. -#define SETBITS0(x) (x) -#define SETBITS1(x) (SETBITS0(x) | (SETBITS0(x) >> 1)) -#define SETBITS2(x) (SETBITS1(x) | (SETBITS1(x) >> 2)) -#define SETBITS3(x) (SETBITS2(x) | (SETBITS2(x) >> 4)) -#define SETBITS4(x) (SETBITS3(x) | (SETBITS3(x) >> 8)) -#define SETBITS5(x) (SETBITS4(x) | (SETBITS4(x) >> 16)) -#define NEXTPOW2(x) (SETBITS5((x) - 1) + 1) - // // Allpass delay modulation // @@ -111,6 +101,18 @@ static const int M_AP19 = 113; static const int M_AP20 = 107; static const int M_AP21 = 127; +// Round an integer to the next power-of-two, at compile time +constexpr uint32_t NEXTPOW2(uint32_t n) { + n -= 1; + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + n += 1; + return n; +} + // // Filter design tools using analog-matched response. // All filter types approximate the s-plane response, including cutoff > Nyquist. @@ -1796,6 +1798,18 @@ void AudioReverb::render(float** inputs, float** outputs, int numFrames) { #include +// unaligned load/store without undefined behavior +static inline __m128i mm_loadu_si32(void const* mem_addr) { + int32_t temp; + memcpy(&temp, mem_addr, sizeof(int32_t)); + return _mm_cvtsi32_si128(temp); +} + +static inline void mm_storeu_si32(void* mem_addr, __m128i a) { + int32_t temp = _mm_cvtsi128_si32(a); + memcpy(mem_addr, &temp, sizeof(int32_t)); +} + // convert int16_t to float, deinterleave stereo void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFrames) { __m128 scale = _mm_set1_ps(1/32768.0f); @@ -1816,7 +1830,7 @@ void AudioReverb::convertInput(const int16_t* input, float** outputs, int numFra _mm_storeu_ps(&outputs[1][i], f1); } for (; i < numFrames; i++) { - __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]); + __m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]); __m128i a1 = a0; // deinterleave and sign-extend @@ -1887,7 +1901,7 @@ void AudioReverb::convertOutput(float** inputs, int16_t* output, int numFrames) // interleave a0 = _mm_unpacklo_epi16(a0, a1); - *(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0); + mm_storeu_si32((__m128i*)&output[2*i], a0); } } diff --git a/libraries/audio/src/AudioSRC.cpp b/libraries/audio/src/AudioSRC.cpp index d488eccb6a..625f45e9ae 100644 --- a/libraries/audio/src/AudioSRC.cpp +++ b/libraries/audio/src/AudioSRC.cpp @@ -793,6 +793,18 @@ int AudioSRC::multirateFilter4(const float* input0, const float* input1, const f #include // SSE2 +// unaligned load/store without undefined behavior +static inline __m128i mm_loadu_si32(void const* mem_addr) { + int32_t temp; + memcpy(&temp, mem_addr, sizeof(int32_t)); + return _mm_cvtsi32_si128(temp); +} + +static inline void mm_storeu_si32(void* mem_addr, __m128i a) { + int32_t temp = _mm_cvtsi128_si32(a); + memcpy(mem_addr, &temp, sizeof(int32_t)); +} + // convert int16_t to float, deinterleave stereo void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames) { __m128 scale = _mm_set1_ps(1/32768.0f); @@ -839,7 +851,7 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames _mm_storeu_ps(&outputs[1][i], f1); } for (; i < numFrames; i++) { - __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[2*i]); + __m128i a0 = mm_loadu_si32((__m128i*)&input[2*i]); __m128i a1 = a0; // deinterleave and sign-extend @@ -878,9 +890,9 @@ void AudioSRC::convertInput(const int16_t* input, float** outputs, int numFrames _mm_storeu_ps(&outputs[3][i], _mm_shuffle_ps(f1, f3, _MM_SHUFFLE(3,1,3,1))); } for (; i < numFrames; i++) { - __m128i a0 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+0]); + __m128i a0 = mm_loadu_si32((__m128i*)&input[4*i+0]); __m128i a1 = a0; - __m128i a2 = _mm_cvtsi32_si128(*(int32_t*)&input[4*i+2]); + __m128i a2 = mm_loadu_si32((__m128i*)&input[4*i+2]); __m128i a3 = a2; // deinterleave and sign-extend @@ -986,7 +998,7 @@ void AudioSRC::convertOutput(float** inputs, int16_t* output, int numFrames) { // interleave a0 = _mm_unpacklo_epi16(a0, a1); - *(int32_t*)&output[2*i] = _mm_cvtsi128_si32(a0); + mm_storeu_si32((__m128i*)&output[2*i], a0); } } else if (_numChannels == 4) { diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 8fefe5820c..0b8c3fdd84 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -996,7 +996,7 @@ void LimitedNodeList::sendSTUNRequest() { const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10; if (!_hasCompletedInitialSTUN) { - qCDebug(networking) << "Sending intial stun request to" << STUN_SERVER_HOSTNAME; + qCDebug(networking) << "Sending initial stun request to" << STUN_SERVER_HOSTNAME; if (_numInitialSTUNRequests > NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL) { // we're still trying to do our initial STUN we're over the fail threshold @@ -1185,7 +1185,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) { // We now setup a timer here to fire every so often to check that our IP address has not changed. // Or, if we failed - if will check if we can eventually get a public socket - const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 30 * 1000; + const int STUN_IP_ADDRESS_CHECK_INTERVAL_MSECS = 10 * 1000; QTimer* stunOccasionalTimer = new QTimer { this }; connect(stunOccasionalTimer, &QTimer::timeout, this, &LimitedNodeList::sendSTUNRequest); @@ -1243,15 +1243,22 @@ void LimitedNodeList::errorTestingLocalSocket() { } void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { - if (sockAddr != _localSockAddr) { + if (sockAddr.getAddress() != _localSockAddr.getAddress()) { if (_localSockAddr.isNull()) { qCInfo(networking) << "Local socket is" << sockAddr; + _localSockAddr = sockAddr; } else { qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; + _localSockAddr = sockAddr; + if (_hasTCPCheckedLocalSocket) { // Force a port change for NAT: + reset(); + _nodeSocket.rebind(0); + _localSockAddr.setPort(_nodeSocket.localPort()); + qCInfo(networking) << "Local port changed to" << _localSockAddr.getPort(); + } } - _localSockAddr = sockAddr; emit localSockAddrChanged(_localSockAddr); } } diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 3a7a056c77..c56f276560 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -33,6 +33,7 @@ using namespace udt; Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) : QObject(parent), + _udpSocket(parent), _readyReadBackupTimer(new QTimer(this)), _shouldChangeSocketOptions(shouldChangeSocketOptions) { @@ -50,6 +51,7 @@ Socket::Socket(QObject* parent, bool shouldChangeSocketOptions) : } void Socket::bind(const QHostAddress& address, quint16 port) { + _udpSocket.bind(address, port); if (_shouldChangeSocketOptions) { @@ -75,7 +77,7 @@ void Socket::rebind() { } void Socket::rebind(quint16 localPort) { - _udpSocket.close(); + _udpSocket.abort(); bind(QHostAddress::AnyIPv4, localPort); } diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index fc9310a520..de4581d66e 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -37,7 +37,6 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness _fragColor0 = vec4(albedo, mix(packShadedMetallic(metallic), packScatteringMetallic(metallic), check)); _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(mix(emissive, vec3(scattering), check), occlusion); - _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0); } @@ -49,7 +48,6 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic)); _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(isLightmapEnabled() * lightmap, 1.0); - _fragColor3 = vec4(isLightmapEnabled() * lightmap * albedo, 1.0); } @@ -59,7 +57,7 @@ void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) { } _fragColor0 = vec4(color, packUnlit()); _fragColor1 = vec4(packNormal(normal), 1.0); - // _fragColor2 = vec4(vec3(0.0), 1.0); + _fragColor2 = vec4(vec3(0.0), 1.0); _fragColor3 = vec4(color, 1.0); } @@ -69,7 +67,8 @@ void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, floa } _fragColor0 = vec4(albedo.rgb, alpha); _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); - + _fragColor2 = vec4(vec3(0.0), 1.0); + _fragColor3 = vec4(0.0); } <@endif@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 82b7f3102a..51729fc5cf 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -41,33 +41,17 @@ namespace gr { using namespace render; -struct LightLocations { - bool shadowTransform{ false }; - void initialize(const gpu::ShaderPointer& program) { - shadowTransform = program->getReflection().validUniformBuffer(ru::Buffer::ShadowParams); - } -}; - -static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); +static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& program); void DeferredLightingEffect::init() { - _directionalAmbientSphereLightLocations = std::make_shared(); - _directionalSkyboxLightLocations = std::make_shared(); + loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight); + loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight); - _directionalAmbientSphereLightShadowLocations = std::make_shared(); - _directionalSkyboxLightShadowLocations = std::make_shared(); + loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow); + loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow); - _localLightLocations = std::make_shared(); - _localLightOutlineLocations = std::make_shared(); - - loadLightProgram(shader::render_utils::program::directional_ambient_light, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations); - loadLightProgram(shader::render_utils::program::directional_skybox_light, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); - - loadLightProgram(shader::render_utils::program::directional_ambient_light_shadow, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations); - loadLightProgram(shader::render_utils::program::directional_skybox_light_shadow, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations); - - loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight, _localLightLocations); - loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline, _localLightOutlineLocations); + loadLightProgram(shader::render_utils::program::local_lights_shading, true, _localLight); + loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline); } // FIXME: figure out how to move lightFrame into a varying in GeometryCache and RenderPipelines @@ -123,15 +107,9 @@ void DeferredLightingEffect::unsetLocalLightsBatch(gpu::Batch& batch) { batch.setUniformBuffer(ru::Buffer::LightClusterFrustumGrid, nullptr); } -static gpu::ShaderPointer makeLightProgram(int programId, LightLocationsPtr& locations) { +static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline) { + gpu::ShaderPointer program = gpu::Shader::createProgram(programId); - locations->initialize(program); - return program; -} - -static void loadLightProgram(int programId, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) { - - gpu::ShaderPointer program = makeLightProgram(programId, locations); auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); @@ -456,7 +434,6 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Setup the global directional pass pipeline auto program = deferredLightingEffect->_directionalSkyboxLight; - LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; { if (keyLightCastShadows) { @@ -464,20 +441,16 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // otherwise use the ambient sphere version if (hasAmbientMap) { program = deferredLightingEffect->_directionalSkyboxLightShadow; - locations = deferredLightingEffect->_directionalSkyboxLightShadowLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLightShadow; - locations = deferredLightingEffect->_directionalAmbientSphereLightShadowLocations; } } else { // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version if (hasAmbientMap) { program = deferredLightingEffect->_directionalSkyboxLight; - locations = deferredLightingEffect->_directionalSkyboxLightLocations; } else { program = deferredLightingEffect->_directionalAmbientSphereLight; - locations = deferredLightingEffect->_directionalAmbientSphereLightLocations; } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 1cc6ca4767..84b3127443 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -37,10 +37,6 @@ #include "SubsurfaceScattering.h" #include "AmbientOcclusionEffect.h" - -struct LightLocations; -using LightLocationsPtr = std::shared_ptr; - // THis is where we currently accumulate the local lights, let s change that sooner than later class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY @@ -72,15 +68,6 @@ private: gpu::PipelinePointer _localLight; gpu::PipelinePointer _localLightOutline; - LightLocationsPtr _directionalSkyboxLightLocations; - LightLocationsPtr _directionalAmbientSphereLightLocations; - - LightLocationsPtr _directionalSkyboxLightShadowLocations; - LightLocationsPtr _directionalAmbientSphereLightShadowLocations; - - LightLocationsPtr _localLightLocations; - LightLocationsPtr _localLightOutlineLocations; - friend class LightClusteringPass; friend class RenderDeferredSetup; friend class RenderDeferredLocals; diff --git a/libraries/render-utils/src/deferred_light.slv b/libraries/render-utils/src/deferred_light.slv index 164fd9fb3b..2a68aa0e27 100644 --- a/libraries/render-utils/src/deferred_light.slv +++ b/libraries/render-utils/src/deferred_light.slv @@ -18,7 +18,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; void main(void) { const float depth = 1.0; - const vec4 UNIT_QUAD[4] = vec4[4]( + const mat4 UNIT_QUAD = mat4( vec4(-1.0, -1.0, depth, 1.0), vec4(1.0, -1.0, depth, 1.0), vec4(-1.0, 1.0, depth, 1.0), @@ -26,7 +26,7 @@ void main(void) { ); vec4 pos = UNIT_QUAD[gl_VertexID]; - _texCoord01.xy = (pos.xy + 1.0) * 0.5; + _texCoord01 = vec4((pos.xy + 1.0) * 0.5, 0.0, 0.0); gl_Position = pos; } diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h index 9f84d9c8b7..9147117792 100644 --- a/libraries/shared/src/Preferences.h +++ b/libraries/shared/src/Preferences.h @@ -115,48 +115,39 @@ protected: const Lambda _triggerHandler; }; - -template -class TypedPreference : public Preference { -public: - using Getter = std::function; - using Setter = std::function; - - TypedPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : Preference(category, name), _getter(getter), _setter(setter) { } - - T getValue() const { return _value; } - void setValue(const T& value) { if (_value != value) { _value = value; emitValueChanged(); } } - void load() override { _value = _getter(); } - void save() const override { - T oldValue = _getter(); - if (_value != oldValue) { - _setter(_value); - } - } - -protected: - T _value; - const Getter _getter; - const Setter _setter; -}; - -class BoolPreference : public TypedPreference { +class BoolPreference : public Preference { Q_OBJECT Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged) public: + using Getter = std::function; + using Setter = std::function; + BoolPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : TypedPreference(category, name, getter, setter) { } + : Preference(category, name), _getter(getter), _setter(setter) { } + + bool getValue() const { return _value; } + void setValue(const bool& value) { if (_value != value) { _value = value; emitValueChanged(); } } + void load() override { _value = _getter(); } + void save() const override { + bool oldValue = _getter(); + if (_value != oldValue) { + _setter(_value); + } + } signals: void valueChanged(); protected: + bool _value; + const Getter _getter; + const Setter _setter; + void emitValueChanged() override { emit valueChanged(); } }; -class FloatPreference : public TypedPreference { +class FloatPreference : public Preference { Q_OBJECT Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged) Q_PROPERTY(float min READ getMin CONSTANT) @@ -165,8 +156,21 @@ class FloatPreference : public TypedPreference { Q_PROPERTY(float decimals READ getDecimals CONSTANT) public: + using Getter = std::function; + using Setter = std::function; + FloatPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : TypedPreference(category, name, getter, setter) { } + : Preference(category, name), _getter(getter), _setter(setter) { } + + float getValue() const { return _value; } + void setValue(const float& value) { if (_value != value) { _value = value; emitValueChanged(); } } + void load() override { _value = _getter(); } + void save() const override { + float oldValue = _getter(); + if (_value != oldValue) { + _setter(_value); + } + } float getMin() const { return _min; } void setMin(float min) { _min = min; }; @@ -186,14 +190,17 @@ signals: protected: void emitValueChanged() override { emit valueChanged(); } + float _value; + const Getter _getter; + const Setter _setter; + float _decimals { 0 }; float _min { 0 }; float _max { 1 }; float _step { 0.1f }; }; - -class IntPreference : public TypedPreference { +class IntPreference : public Preference { Q_OBJECT Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged) Q_PROPERTY(float min READ getMin CONSTANT) @@ -202,8 +209,21 @@ class IntPreference : public TypedPreference { Q_PROPERTY(int decimals READ getDecimals CONSTANT) public: + using Getter = std::function; + using Setter = std::function; + IntPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : TypedPreference(category, name, getter, setter) { } + : Preference(category, name), _getter(getter), _setter(setter) { } + + int getValue() const { return _value; } + void setValue(const int& value) { if (_value != value) { _value = value; emitValueChanged(); } } + void load() override { _value = _getter(); } + void save() const override { + int oldValue = _getter(); + if (_value != oldValue) { + _setter(_value); + } + } float getMin() const { return _min; } void setMin(float min) { _min = min; }; @@ -221,6 +241,10 @@ signals: void valueChanged(); protected: + int _value; + const Getter _getter; + const Setter _setter; + void emitValueChanged() override { emit valueChanged(); } int _min { std::numeric_limits::min() }; @@ -229,19 +253,37 @@ protected: int _decimals { 0 }; }; -class StringPreference : public TypedPreference { +class StringPreference : public Preference { Q_OBJECT Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged) public: + using Getter = std::function; + using Setter = std::function; + StringPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : TypedPreference(category, name, getter, setter) { } + : Preference(category, name), _getter(getter), _setter(setter) { } + + + QString getValue() const { return _value; } + void setValue(const QString& value) { if (_value != value) { _value = value; emitValueChanged(); } } + void load() override { _value = _getter(); } + void save() const override { + QString oldValue = _getter(); + if (_value != oldValue) { + _setter(_value); + } + } signals: void valueChanged(); protected: void emitValueChanged() override { emit valueChanged(); } + + QString _value; + const Getter _getter; + const Setter _setter; }; class SliderPreference : public FloatPreference { @@ -303,7 +345,7 @@ public: ComboBoxPreference(const QString& category, const QString& name, Getter getter, Setter setter) : EditPreference(category, name, getter, setter) { } Type getType() override { return ComboBox; } - + const QStringList& getItems() { return _items; } void setItems(const QStringList& items) { _items = items; } @@ -342,6 +384,9 @@ class CheckPreference : public BoolPreference { Q_OBJECT Q_PROPERTY(bool indented READ getIndented CONSTANT) public: + using Getter = std::function; + using Setter = std::function; + CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter) : BoolPreference(category, name, getter, setter) { } Type getType() override { return Checkbox; }