From 4af37668047ab36ae95ff2f563293e7e97a8719a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 9 Mar 2016 14:28:26 -0800 Subject: [PATCH 01/14] Don't reset sensors when initializing or changing display plugins. This should fix the issue with the Oculus starting up with the UI aligned to the HMD on your desk, rather then the configured default sitting pose. --- interface/src/Application.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 660e597752..654e58c170 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -3287,6 +3288,14 @@ void Application::update(float deltaTime) { // update sensorToWorldMatrix for rendering camera. myAvatar->updateSensorToWorldMatrix(); + + // AJT: TODO: make this a menu item. + const bool DRAW_SENSOR_TO_WORLD_MATRIX = true; + if (DRAW_SENSOR_TO_WORLD_MATRIX) { + // draw the origin of the room in world space. + glm::mat4 m = myAvatar->getSensorToWorldMatrix(); + DebugDraw::getInstance().addMarker("room", glmExtractRotation(m), extractTranslation(m), glm::vec4(1)); + } } @@ -4811,7 +4820,7 @@ void Application::updateDisplayMode() { } } emit activeDisplayPluginChanged(); - resetSensors(); + Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } From 5df616be37406f5385ec5f58965501c55438dcd2 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 9 Mar 2016 16:24:08 -0800 Subject: [PATCH 02/14] OpenVR: More usable UI Sphere overlay location Also, added a debug option to display SensorToWorld matrix in Developer > Avatar menu. --- interface/src/Application.cpp | 8 -------- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 12 ++++++++++++ interface/src/avatar/MyAvatar.h | 2 ++ plugins/openvr/src/OpenVrDisplayPlugin.cpp | 17 ++++++++++++++++- 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 654e58c170..d575160f99 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3288,14 +3288,6 @@ void Application::update(float deltaTime) { // update sensorToWorldMatrix for rendering camera. myAvatar->updateSensorToWorldMatrix(); - - // AJT: TODO: make this a menu item. - const bool DRAW_SENSOR_TO_WORLD_MATRIX = true; - if (DRAW_SENSOR_TO_WORLD_MATRIX) { - // draw the origin of the room in world space. - glm::mat4 m = myAvatar->getSensorToWorldMatrix(); - DebugDraw::getInstance().addMarker("room", glmExtractRotation(m), extractTranslation(m), glm::vec4(1)); - } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d605516380..919ee0f3c3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -471,6 +471,8 @@ Menu::Menu() { avatar, SLOT(setUseAnimPreAndPostRotations(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true, avatar, SLOT(setEnableInverseKinematics(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSensorToWorldMatrix, 0, false, + avatar, SLOT(setEnableDebugDrawSensorToWorldMatrix(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl, Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()), diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fb00416af0..8ffd7efb36 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -144,6 +144,7 @@ namespace MenuOption { const QString RenderResolutionHalf = "1/2"; const QString RenderResolutionThird = "1/3"; const QString RenderResolutionQuarter = "1/4"; + const QString RenderSensorToWorldMatrix = "Show SensorToWorld Matrix"; const QString ResetAvatarSize = "Reset Avatar Size"; const QString ResetSensors = "Reset Sensors"; const QString RunningScripts = "Running Scripts..."; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 397627434f..a5b69f2be6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -442,6 +442,10 @@ void MyAvatar::updateSensorToWorldMatrix() { _sensorToWorldMatrix = desiredMat * glm::inverse(_bodySensorMatrix); lateUpdatePalms(); + + if (_enableDebugDrawSensorToWorldMatrix) { + DebugDraw::getInstance().addMarker("sensorToWorldMatrix", glmExtractRotation(_sensorToWorldMatrix), extractTranslation(_sensorToWorldMatrix), glm::vec4(1)); + } } // Update avatar head rotation with sensor data @@ -695,6 +699,14 @@ void MyAvatar::setEnableDebugDrawPosition(bool isEnabled) { } } +void MyAvatar::setEnableDebugDrawSensorToWorldMatrix(bool isEnabled) { + _enableDebugDrawSensorToWorldMatrix = isEnabled; + + if (!isEnabled) { + DebugDraw::getInstance().removeMarker("sensorToWorldMatrix"); + } +} + void MyAvatar::setEnableMeshVisible(bool isEnabled) { render::ScenePointer scene = qApp->getMain3DScene(); _skeletonModel.setVisibleInScene(isEnabled, scene); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 731cba8153..8e5c1796b1 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -267,6 +267,7 @@ public slots: void setEnableDebugDrawDefaultPose(bool isEnabled); void setEnableDebugDrawAnimPose(bool isEnabled); void setEnableDebugDrawPosition(bool isEnabled); + void setEnableDebugDrawSensorToWorldMatrix(bool isEnabled); bool getEnableMeshVisible() const { return _skeletonModel.isVisible(); } void setEnableMeshVisible(bool isEnabled); void setUseAnimPreAndPostRotations(bool isEnabled); @@ -429,6 +430,7 @@ private: bool _enableDebugDrawDefaultPose { false }; bool _enableDebugDrawAnimPose { false }; + bool _enableDebugDrawSensorToWorldMatrix { false }; AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index e5708572f6..57a896dd4d 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -68,6 +68,21 @@ void OpenVrDisplayPlugin::activate() { _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); HmdDisplayPlugin::activate(); + + // set up default sensor space such that the UI overlay will align with the front of the room. + auto chaperone = vr::VRChaperone(); + if (chaperone) { + float const UI_RADIUS = 1.0f; + float const UI_HEIGHT = 1.6f; + float const UI_Z_OFFSET = 0.5; + + float xSize, zSize; + chaperone->GetPlayAreaSize(&xSize, &zSize); + glm::vec3 uiPos(0.0f, UI_HEIGHT, 0.5f * zSize - UI_RADIUS + UI_Z_OFFSET); + _sensorResetMat = glm::inverse(createMatFromQuatAndPos(Quaternions::Y_180, uiPos)); + } else { + qDebug() << "OpenVR: error could not get chaperone pointer"; + } } void OpenVrDisplayPlugin::deactivate() { @@ -115,7 +130,7 @@ glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const { #endif vr::TrackedDevicePose_t predictedTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; - _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount); + _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, predictedSecondsFromNow, predictedTrackedDevicePose, vr::k_unMaxTrackedDeviceCount); // copy and process predictedTrackedDevicePoses for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { From 40fbe2d1e5dd8b36db967babe346be57bde4dbf3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:33:07 -0800 Subject: [PATCH 03/14] Reuse procedurals on entities --- .../entities-renderer/src/RenderableBoxEntityItem.cpp | 7 ++++--- .../entities-renderer/src/RenderableSphereEntityItem.cpp | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index 671043813e..58d9b6b391 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -31,7 +31,9 @@ EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID, void RenderableBoxEntityItem::setUserData(const QString& value) { if (value != getUserData()) { BoxEntityItem::setUserData(value); - _procedural.reset(); + if (_procedural) { + _procedural->parse(value); + } } } @@ -40,7 +42,6 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { Q_ASSERT(getType() == EntityTypes::Box); Q_ASSERT(args->_batch); - if (!_procedural) { _procedural.reset(new Procedural(this->getUserData())); _procedural->_vertexSource = simple_vert; @@ -62,7 +63,7 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { } batch.setModelTransform(transToCenter); // we want to include the scale as well - if (_procedural && _procedural->ready()) { + if (_procedural->ready()) { _procedural->prepare(batch, getPosition(), getDimensions()); auto color = _procedural->getColor(cubeColor); batch._glColor4f(color.r, color.g, color.b, color.a); diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp index b5867fb1ee..78ff77ce89 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.cpp @@ -36,7 +36,9 @@ EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entity void RenderableSphereEntityItem::setUserData(const QString& value) { if (value != getUserData()) { SphereEntityItem::setUserData(value); - _procedural.reset(); + if (_procedural) { + _procedural->parse(value); + } } } From 5f1b8805cf76d9b7ef96341ac58a8a49e9a4c3df Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 9 Mar 2016 17:37:51 -0800 Subject: [PATCH 04/14] Removed unnecessary include --- interface/src/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 426efbd914..66662a7500 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include From 42d27557a11ed30db5c1869c87c72fabce0cae1b Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 9 Mar 2016 18:42:03 -0800 Subject: [PATCH 05/14] OpenVR: remove 180 y rotation for UI bounds. Turns out the room I was using was misconfigured. --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 57a896dd4d..83c834161b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -79,7 +79,7 @@ void OpenVrDisplayPlugin::activate() { float xSize, zSize; chaperone->GetPlayAreaSize(&xSize, &zSize); glm::vec3 uiPos(0.0f, UI_HEIGHT, 0.5f * zSize - UI_RADIUS + UI_Z_OFFSET); - _sensorResetMat = glm::inverse(createMatFromQuatAndPos(Quaternions::Y_180, uiPos)); + _sensorResetMat = glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos)); } else { qDebug() << "OpenVR: error could not get chaperone pointer"; } From 4022474b48e1eef6c267b79ae65a95b4135f05ae Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:33:19 -0800 Subject: [PATCH 06/14] Constrain procedural updates to render thread --- .../procedural/src/procedural/Procedural.cpp | 153 +++++++++++------- .../procedural/src/procedural/Procedural.h | 46 ++++-- 2 files changed, 132 insertions(+), 67 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index b1e4bd53ed..f7c4a783aa 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -69,74 +69,108 @@ Procedural::Procedural(const QString& userDataJson) { } void Procedural::parse(const QString& userDataJson) { - _enabled = false; auto proceduralData = getProceduralData(userDataJson); - if (proceduralData.isObject()) { - parse(proceduralData.toObject()); - } + // Instead of parsing, prep for a parse on the rendering thread + // This will be called by Procedural::ready + _proceduralData = proceduralData.toObject(); + _proceduralDataDirty = true; } -void Procedural::parse(const QJsonObject& proceduralData) { - // grab the version number - { - auto version = proceduralData[VERSION_KEY]; - if (version.isDouble()) { - _version = (uint8_t)(floor(version.toDouble())); - } +bool Procedural::parseVersion(const QJsonValue& version) { + if (version.isDouble()) { + _version = (uint8_t)(floor(version.toDouble())); + } else { + // All unversioned shaders default to V1 + _version = 1; + } + return (_version == 1 || _version == 2); +} + +bool Procedural::parseUrl(const QUrl& shaderUrl) { + if (!shaderUrl.isValid()) { + qWarning() << "Invalid shader URL: " << shaderUrl; + return false; } - // Get the path to the shader - { - QString shaderUrl = proceduralData[URL_KEY].toString(); - shaderUrl = ResourceManager::normalizeURL(shaderUrl); - _shaderUrl = QUrl(shaderUrl); - if (!_shaderUrl.isValid()) { - qWarning() << "Invalid shader URL: " << shaderUrl; - return; - } - - if (_shaderUrl.isLocalFile()) { - _shaderPath = _shaderUrl.toLocalFile(); - qDebug() << "Shader path: " << _shaderPath; - if (!QFile(_shaderPath).exists()) { - return; - } - } else { - qDebug() << "Shader url: " << _shaderUrl; - _networkShader = ShaderCache::instance().getShader(_shaderUrl); - } + if (_shaderUrl == shaderUrl) { + return true; } - // Grab any custom uniforms - { - auto uniforms = proceduralData[UNIFORMS_KEY]; - if (uniforms.isObject()) { - _parsedUniforms = uniforms.toObject(); + _shaderUrl = shaderUrl; + + if (_shaderUrl.isLocalFile()) { + _shaderPath = _shaderUrl.toLocalFile(); + qDebug() << "Shader path: " << _shaderPath; + if (!QFile(_shaderPath).exists()) { + return false;; } + } else { + qDebug() << "Shader url: " << _shaderUrl; + _networkShader = ShaderCache::instance().getShader(_shaderUrl); } - // Grab any textures - { - auto channels = proceduralData[CHANNELS_KEY]; - if (channels.isArray()) { - auto textureCache = DependencyManager::get(); - _parsedChannels = channels.toArray(); - size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size()); - for (size_t i = 0; i < channelCount; ++i) { - QString url = _parsedChannels.at((int)i).toString(); - _channels[i] = textureCache->getTexture(QUrl(url)); - } - } + return true; +} + +bool Procedural::parseUniforms(const QJsonObject& uniforms) { + if (_parsedUniforms != uniforms) { + _parsedUniforms = uniforms; + _uniformsDirty = true; + } + + return true; +} + +bool Procedural::parseTextures(const QJsonArray& channels) { + if (_parsedChannels != channels) { + _parsedChannels = channels; + + auto textureCache = DependencyManager::get(); + size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size()); + for (size_t i = 0; i < channelCount; ++i) { + QString url = _parsedChannels.at((int)i).toString(); + _channels[i] = textureCache->getTexture(QUrl(url)); + } + + _channelsDirty = true; + } + + return true; +} + +void Procedural::parse(QJsonObject proceduralData) { + _enabled = false; + + if (proceduralData.isEmpty()) { + return; + } + + auto version = proceduralData[VERSION_KEY]; + auto shaderUrl = proceduralData[URL_KEY].toString(); + shaderUrl = ResourceManager::normalizeURL(shaderUrl); + auto uniforms = proceduralData[UNIFORMS_KEY].toObject(); + auto channels = proceduralData[CHANNELS_KEY].toArray(); + + if (parseVersion(proceduralData[VERSION_KEY]) && + parseUrl(shaderUrl) && + parseUniforms(uniforms) && + parseTextures(channels)) { + _enabled = true; } - _enabled = true; } bool Procedural::ready() { + // Load any changes to the procedural + if (_proceduralDataDirty) { + parse(_proceduralData); + _proceduralDataDirty = false; + } + if (!_enabled) { return false; } - // Do we have a network or local shader + // Do we have a network or local shader, and if so, is it loaded? if (_shaderPath.isEmpty() && (!_networkShader || !_networkShader->isLoaded())) { return false; } @@ -160,15 +194,14 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm QFile file(_shaderPath); file.open(QIODevice::ReadOnly); _shaderSource = QTextStream(&file).readAll(); - _pipelineDirty = true; + _shaderDirty = true; _shaderModified = lastModified; } } else if (_networkShader && _networkShader->isLoaded()) { _shaderSource = _networkShader->_source; } - if (!_pipeline || _pipelineDirty) { - _pipelineDirty = true; + if (!_pipeline || _shaderDirty) { if (!_vertexShader) { _vertexShader = gpu::Shader::createVertex(_vertexSource); } @@ -214,11 +247,15 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm batch.setPipeline(_pipeline); - if (_pipelineDirty) { - _pipelineDirty = false; + if (_shaderDirty || _uniformsDirty) { setupUniforms(); } + if (_shaderDirty || _uniformsDirty || _channelsDirty) { + setupChannels(_shaderDirty || _uniformsDirty); + } + + _shaderDirty = _uniformsDirty = _channelsDirty = false; for (auto lambda : _uniforms) { lambda(batch); @@ -359,8 +396,14 @@ void Procedural::setupUniforms() { batch._glUniform(_standardUniformSlots[POSITION], _entityPosition); }); } +} +void Procedural::setupChannels(bool shouldCreate) { if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) { + if (!shouldCreate) { + // Instead of modifying the last element, just remove and recreate it. + _uniforms.pop_back(); + } _uniforms.push_back([=](gpu::Batch& batch) { vec3 channelSizes[MAX_PROCEDURAL_TEXTURE_CHANNELS]; for (size_t i = 0; i < MAX_PROCEDURAL_TEXTURE_CHANNELS; ++i) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 1b02fbd435..41493664b1 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -28,27 +28,24 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; // FIXME better encapsulation // FIXME better mechanism for extending to things rendered using shaders other than simple.slv struct Procedural { +public: static QJsonValue getProceduralData(const QString& proceduralJson); Procedural(const QString& userDataJson); void parse(const QString& userDataJson); - void parse(const QJsonObject&); + bool ready(); void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size); - void setupUniforms(); + glm::vec4 getColor(const glm::vec4& entityColor); - bool _enabled{ false }; - uint8_t _version{ 1 }; + bool _enabled { false }; + uint8_t _version { 1 }; std::string _vertexSource; std::string _fragmentSource; - QString _shaderSource; - QString _shaderPath; - QUrl _shaderUrl; - quint64 _shaderModified{ 0 }; - bool _pipelineDirty{ true }; + gpu::StatePointer _state; enum StandardUniforms { DATE, @@ -60,23 +57,48 @@ struct Procedural { NUM_STANDARD_UNIFORMS }; - int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; - +protected: + // Procedural metadata uint64_t _start{ 0 }; int32_t _frameCount{ 0 }; + + // Rendering object descriptions, from userData + QJsonObject _proceduralData; + QString _shaderSource; + QString _shaderPath; + QUrl _shaderUrl; + quint64 _shaderModified { 0 }; NetworkShaderPointer _networkShader; QJsonObject _parsedUniforms; QJsonArray _parsedChannels; + bool _proceduralDataDirty { true }; + bool _shaderDirty { true }; + bool _uniformsDirty { true }; + bool _channelsDirty { true }; + // Rendering objects UniformLambdas _uniforms; + int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; gpu::PipelinePointer _pipeline; gpu::ShaderPointer _vertexShader; gpu::ShaderPointer _fragmentShader; gpu::ShaderPointer _shader; - gpu::StatePointer _state; + + // Entity metadata glm::vec3 _entityDimensions; glm::vec3 _entityPosition; + +private: + // This should only be called from the render thread, as it shares data with Procedural::prepare + void parse(QJsonObject); + bool parseVersion(const QJsonValue& version); + bool parseUrl(const QUrl& url); + bool parseUniforms(const QJsonObject& uniforms); + bool parseTextures(const QJsonArray& channels); + + void setupUniforms(); + void setupChannels(bool shouldCreate); }; #endif From 74e1d322215e67244ea22823565758fcb2aa19b6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 9 Mar 2016 17:48:24 -0800 Subject: [PATCH 07/14] Reuse procedural on skybox --- .../src/EntityTreeRenderer.cpp | 7 +----- .../procedural/src/procedural/Procedural.cpp | 3 +++ .../procedural/src/procedural/Procedural.h | 7 +++--- .../src/procedural/ProceduralSkybox.cpp | 23 ++++++++----------- .../src/procedural/ProceduralSkybox.h | 6 ++--- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 44c3146b41..421213151a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -341,12 +341,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetUserData()) { userData = zone->getUserData(); - auto procedural = std::make_shared(userData); - if (procedural->_enabled) { - skybox->setProcedural(procedural); - } else { - skybox->setProcedural(ProceduralPointer()); - } + skybox->setProcedural(userData); } if (zone->getSkyboxProperties().getURL().isEmpty()) { skybox->setCubemap(gpu::TexturePointer()); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index f7c4a783aa..cc9e5841ed 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -62,6 +62,9 @@ QJsonValue Procedural::getProceduralData(const QString& proceduralJson) { return doc.object()[PROCEDURAL_USER_DATA_KEY]; } +Procedural::Procedural() { + _state = std::make_shared(); +} Procedural::Procedural(const QString& userDataJson) { parse(userDataJson); diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 41493664b1..0d602eab4f 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -31,6 +31,7 @@ struct Procedural { public: static QJsonValue getProceduralData(const QString& proceduralJson); + Procedural(); Procedural(const QString& userDataJson); void parse(const QString& userDataJson); @@ -39,7 +40,6 @@ public: glm::vec4 getColor(const glm::vec4& entityColor); - bool _enabled { false }; uint8_t _version { 1 }; std::string _vertexSource; @@ -59,8 +59,9 @@ public: protected: // Procedural metadata - uint64_t _start{ 0 }; - int32_t _frameCount{ 0 }; + bool _enabled { false }; + uint64_t _start { 0 }; + int32_t _frameCount { 0 }; // Rendering object descriptions, from userData QJsonObject _proceduralData; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 167d49cbaf..f3ee08dd7a 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -19,6 +19,10 @@ #include "ProceduralSkybox_frag.h" ProceduralSkybox::ProceduralSkybox() : model::Skybox() { + _procedural._vertexSource = ProceduralSkybox_vert; + _procedural._fragmentSource = ProceduralSkybox_frag; + // Adjust the pipeline state for background using the stencil test + _procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : @@ -27,14 +31,8 @@ ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : } -void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) { - _procedural = procedural; - if (_procedural) { - _procedural->_vertexSource = ProceduralSkybox_vert; - _procedural->_fragmentSource = ProceduralSkybox_frag; - // Adjust the pipeline state for background using the stencil test - _procedural->_state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - } +void ProceduralSkybox::setProcedural(const QString& userData) { + _procedural.parse(userData); } void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { @@ -42,12 +40,10 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) con } void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) { - if (!(skybox._procedural)) { + if (!(skybox._procedural.ready())) { skybox.updateDataBuffer(); Skybox::render(batch, viewFrustum, skybox); - } - - if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) { + } else { gpu::TexturePointer skymap = skybox.getCubemap(); // FIXME: skymap->isDefined may not be threadsafe assert(skymap && skymap->isDefined()); @@ -62,8 +58,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, batch.setModelTransform(Transform()); // only for Mac batch.setResourceTexture(0, skybox.getCubemap()); - skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1)); + skybox._procedural.prepare(batch, glm::vec3(0), glm::vec3(1)); batch.draw(gpu::TRIANGLE_STRIP, 4); } } - diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index 057a1ccc74..37cc2baaaf 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -17,8 +17,6 @@ #include "Procedural.h" -typedef std::shared_ptr ProceduralPointer; - class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); @@ -26,13 +24,13 @@ public: ProceduralSkybox& operator= (const ProceduralSkybox& skybox); virtual ~ProceduralSkybox() {}; - void setProcedural(const ProceduralPointer& procedural); + void setProcedural(const QString& userData); virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); protected: - ProceduralPointer _procedural; + mutable Procedural _procedural; }; typedef std::shared_ptr< ProceduralSkybox > ProceduralSkyboxPointer; From 153f7fc3aa9088fffdcc22b3524a0877da9aa996 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 10 Mar 2016 09:45:47 -0800 Subject: [PATCH 08/14] OpenVR: adjusted translation of UI sphere overlay --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 83c834161b..b86a7f9ebc 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -78,7 +78,7 @@ void OpenVrDisplayPlugin::activate() { float xSize, zSize; chaperone->GetPlayAreaSize(&xSize, &zSize); - glm::vec3 uiPos(0.0f, UI_HEIGHT, 0.5f * zSize - UI_RADIUS + UI_Z_OFFSET); + glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET); _sensorResetMat = glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos)); } else { qDebug() << "OpenVR: error could not get chaperone pointer"; From 1640314076cf29cf6f51b28499322dc0c9743201 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 10:12:22 -0800 Subject: [PATCH 09/14] Use one procedural for skybox (avoid copies) --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- .../procedural/src/procedural/ProceduralSkybox.cpp | 10 ---------- libraries/procedural/src/procedural/ProceduralSkybox.h | 4 +--- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 421213151a..5cf1b1548a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -341,7 +341,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetUserData()) { userData = zone->getUserData(); - skybox->setProcedural(userData); + skybox->parse(userData); } if (zone->getSkyboxProperties().getURL().isEmpty()) { skybox->setCubemap(gpu::TexturePointer()); diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index f3ee08dd7a..9c311acb3d 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -25,16 +25,6 @@ ProceduralSkybox::ProceduralSkybox() : model::Skybox() { _procedural._state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } -ProceduralSkybox::ProceduralSkybox(const ProceduralSkybox& skybox) : - model::Skybox(skybox), - _procedural(skybox._procedural) { - -} - -void ProceduralSkybox::setProcedural(const QString& userData) { - _procedural.parse(userData); -} - void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const { ProceduralSkybox::render(batch, frustum, (*this)); } diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.h b/libraries/procedural/src/procedural/ProceduralSkybox.h index 37cc2baaaf..e817ce271d 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.h +++ b/libraries/procedural/src/procedural/ProceduralSkybox.h @@ -20,11 +20,9 @@ class ProceduralSkybox: public model::Skybox { public: ProceduralSkybox(); - ProceduralSkybox(const ProceduralSkybox& skybox); - ProceduralSkybox& operator= (const ProceduralSkybox& skybox); virtual ~ProceduralSkybox() {}; - void setProcedural(const QString& userData); + void parse(const QString& userData) { _procedural.parse(userData); } virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const; static void render(gpu::Batch& batch, const ViewFrustum& frustum, const ProceduralSkybox& skybox); From 9b89e46e65eb4b80d13d2cfbaadc4f36e123c924 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 10:12:55 -0800 Subject: [PATCH 10/14] Make procedural userData thread-safe --- libraries/procedural/src/procedural/Procedural.cpp | 2 ++ libraries/procedural/src/procedural/Procedural.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index cc9e5841ed..6cf9f05372 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -75,6 +75,7 @@ void Procedural::parse(const QString& userDataJson) { auto proceduralData = getProceduralData(userDataJson); // Instead of parsing, prep for a parse on the rendering thread // This will be called by Procedural::ready + std::lock_guard lock(_proceduralDataMutex); _proceduralData = proceduralData.toObject(); _proceduralDataDirty = true; } @@ -165,6 +166,7 @@ void Procedural::parse(QJsonObject proceduralData) { bool Procedural::ready() { // Load any changes to the procedural if (_proceduralDataDirty) { + std::lock_guard lock(_proceduralDataMutex); parse(_proceduralData); _proceduralDataDirty = false; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 0d602eab4f..75872ca2bc 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -65,6 +65,7 @@ protected: // Rendering object descriptions, from userData QJsonObject _proceduralData; + std::mutex _proceduralDataMutex; QString _shaderSource; QString _shaderPath; QUrl _shaderUrl; From 64042327eca3e3bff21b4ca17c937d30b6e555f1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 11:08:15 -0800 Subject: [PATCH 11/14] Use version tmp var --- libraries/procedural/src/procedural/Procedural.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 6cf9f05372..9670b66676 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -155,7 +155,7 @@ void Procedural::parse(QJsonObject proceduralData) { auto uniforms = proceduralData[UNIFORMS_KEY].toObject(); auto channels = proceduralData[CHANNELS_KEY].toArray(); - if (parseVersion(proceduralData[VERSION_KEY]) && + if (parseVersion(version) && parseUrl(shaderUrl) && parseUniforms(uniforms) && parseTextures(channels)) { From 6d11dd465ca50b2a7fffaf00b3da4dee5c0753a2 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 10 Mar 2016 13:12:09 -0800 Subject: [PATCH 12/14] Application: reset avatar on displayMode change but not HMD sensor. --- interface/src/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 66662a7500..795145ca5c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4857,6 +4857,9 @@ void Application::updateDisplayMode() { } emit activeDisplayPluginChanged(); + // reset the avatar, to set head and hand palms back to a resonable default pose. + getMyAvatar()->reset(false); + Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } From 505ae71e30fa4c571f690b6af1fb8f7819e93e4d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 10 Mar 2016 15:22:19 -0800 Subject: [PATCH 13/14] Pass px userData by const ref --- libraries/procedural/src/procedural/Procedural.cpp | 2 +- libraries/procedural/src/procedural/Procedural.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 9670b66676..11df332c5c 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -142,7 +142,7 @@ bool Procedural::parseTextures(const QJsonArray& channels) { return true; } -void Procedural::parse(QJsonObject proceduralData) { +void Procedural::parse(const QJsonObject& proceduralData) { _enabled = false; if (proceduralData.isEmpty()) { diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 75872ca2bc..cac3f782e4 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -93,7 +93,7 @@ protected: private: // This should only be called from the render thread, as it shares data with Procedural::prepare - void parse(QJsonObject); + void parse(const QJsonObject&); bool parseVersion(const QJsonValue& version); bool parseUrl(const QUrl& url); bool parseUniforms(const QJsonObject& uniforms); From a88f22fa3c33795a3e193fb4294c9ef932f67f41 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 10 Mar 2016 15:58:04 -0800 Subject: [PATCH 14/14] Removing white spaces --- libraries/render/src/render/Scene.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index b2eac380ad..b7cfc367b8 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -78,7 +78,7 @@ public: // WARNING, There is No check on the validity of the ID, so this could return a bad Item const Item& getItem(const ItemID& id) const { return _items[id]; } - // Access the spatialized items + // Access the spatialized items const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; } // Access non-spatialized items (overlays, backgrounds)