From 37541e4ed2ce178508db014664139d650e78b324 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 10 Feb 2017 14:29:29 -0800 Subject: [PATCH 01/38] Start capping the time budget for draw opaque --- .../render-utils/src/RenderDeferredTask.cpp | 3 +- libraries/render/src/render/DrawTask.cpp | 105 ++++++++++++++++++ libraries/render/src/render/DrawTask.h | 2 +- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55a9c8b9e4..82db502af1 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -295,7 +295,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); if (_stateSort) { - renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, 2.0, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 2829c6f8e7..d6f09f735c 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -123,6 +123,111 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons } } + +void render::renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems) { + + auto& scene = sceneContext->_scene; + RenderArgs* args = renderContext->args; + auto now = usecTimestampNow(); + + int numItemsToDraw = (int)inItems.size(); + if (maxDrawnItems != -1) { + numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); + } + + using SortedPipelines = std::vector; + using SortedShapes = std::unordered_map, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>; + SortedPipelines sortedPipelines; + SortedShapes sortedShapes; + std::vector ownPipelineBucket; + + { + PROFILE_RANGE(render_detail, "sort"); + + for (auto i = 0; i < numItemsToDraw; ++i) { + auto item = scene->getItem(inItems[i].id); + + { + assert(item.getKey().isShape()); + const auto key = item.getShapeKey(); + if (key.isValid() && !key.hasOwnPipeline()) { + auto& bucket = sortedShapes[key]; + if (bucket.empty()) { + sortedPipelines.push_back(key); + } + bucket.push_back(item); + } else if (key.hasOwnPipeline()) { + ownPipelineBucket.push_back(item); + } else { + qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; + } + } + } + } + + { + PROFILE_RANGE(render_detail, "render"); + + // Then render + quint64 usecHalfBudget = 1000 * 0.5 * mstimeBudget; + quint64 usecBudget = 1000 * mstimeBudget; + + int numDrawCalls = 0; + int numDrawcallsChecks = 128; + int numChecks = 0; + int numChecksBudget = 4; + + for (auto& pipelineKey : sortedPipelines) { + auto& bucket = sortedShapes[pipelineKey]; + args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); + if (!args->_pipeline) { + continue; + } + for (auto& item : bucket) { + item.render(args); + + numDrawCalls++; + if ((numDrawCalls % numDrawcallsChecks) == 0) { + auto newNow = usecTimestampNow(); + if ((newNow - now) > usecHalfBudget) { + if ((newNow - now) > usecBudget) { + return; + } + + usecHalfBudget += (usecHalfBudget / 2); + numDrawcallsChecks / 2; + numChecks++; + if (numChecks > numChecksBudget) { + return; + } + } + } + } + } + args->_pipeline = nullptr; + for (auto& item : ownPipelineBucket) { + item.render(args); + + numDrawCalls++; + if ((numDrawCalls % numDrawcallsChecks) == 0) { + auto newNow = usecTimestampNow(); + if ((newNow - now) > usecHalfBudget) { + if ((newNow - now) > usecBudget) { + return; + } + + usecHalfBudget += (usecHalfBudget / 2); + numDrawcallsChecks / 2; + numChecks++; + if (numChecks > numChecksBudget) { + return; + } + } + } + } + } +} + void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 27f07921c3..042a927caf 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -19,7 +19,7 @@ namespace render { void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); - +void renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems = -1); class DrawLightConfig : public Job::Config { From 9261e81ba2f4004fad6b613e54ee29acaf6ee8ce Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 10 Feb 2017 17:47:56 -0800 Subject: [PATCH 02/38] Cleaning up the interface --- .../render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.h | 5 ++++- scripts/developer/utilities/render/culling.qml | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 82db502af1..24e284a416 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -296,7 +296,7 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R if (_stateSort) { // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); - renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, 2.0, _maxDrawn); + renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, _maxTimeBudget, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 8a95447e67..2d9a7d4888 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -85,6 +85,7 @@ class DrawStateSortConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + Q_PROPERTY(float maxTimeBudget MEMBER maxTimeBudget NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) public: @@ -92,6 +93,7 @@ public: void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; + float maxTimeBudget { 8.0f }; // 8ms maximum bool stateSort{ true }; signals: @@ -111,12 +113,13 @@ public: DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _maxTimeBudget = config.maxTimeBudget; _stateSort = config.stateSort; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config + float _maxTimeBudget; //ms time budget bool _stateSort; }; diff --git a/scripts/developer/utilities/render/culling.qml b/scripts/developer/utilities/render/culling.qml index e3f5e67bbe..4157b5e4dd 100644 --- a/scripts/developer/utilities/render/culling.qml +++ b/scripts/developer/utilities/render/culling.qml @@ -95,6 +95,7 @@ Column { GroupBox { title: "Render Items" + Column{ Column{ Repeater { @@ -110,5 +111,20 @@ Column { } } } + + Column{ + Repeater { + model: [ "Draw Opaque [ms]:DrawOpaqueDeferred" ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: Render.getConfig(modelData.split(":")[1]) + property: "maxTimeBudget" + max: 10.0 + min: 0.0 + } + } + } + } } } From 55611d2373f6fd4fa7f1e1ced5687ac634529c3a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 14:56:07 -0800 Subject: [PATCH 03/38] Backing up to master --- .../render-utils/src/RenderDeferredTask.cpp | 3 +- .../render-utils/src/RenderDeferredTask.h | 5 +- libraries/render/src/render/DrawTask.cpp | 105 ------------------ libraries/render/src/render/DrawTask.h | 1 - .../developer/utilities/render/culling.qml | 16 --- 5 files changed, 2 insertions(+), 128 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 24e284a416..55a9c8b9e4 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -295,8 +295,7 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); if (_stateSort) { - // renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); - renderStateSortShapesCapped(sceneContext, renderContext, _shapePlumber, inItems, _maxTimeBudget, _maxDrawn); + renderStateSortShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } else { renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2d9a7d4888..8a95447e67 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -85,7 +85,6 @@ class DrawStateSortConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) - Q_PROPERTY(float maxTimeBudget MEMBER maxTimeBudget NOTIFY dirty) Q_PROPERTY(bool stateSort MEMBER stateSort NOTIFY dirty) public: @@ -93,7 +92,6 @@ public: void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } int maxDrawn{ -1 }; - float maxTimeBudget { 8.0f }; // 8ms maximum bool stateSort{ true }; signals: @@ -113,13 +111,12 @@ public: DrawStateSortDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config& config) { _maxDrawn = config.maxDrawn; _maxTimeBudget = config.maxTimeBudget; _stateSort = config.stateSort; } + void configure(const Config& config) { _maxDrawn = config.maxDrawn; _stateSort = config.stateSort; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config - float _maxTimeBudget; //ms time budget bool _stateSort; }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index d6f09f735c..2829c6f8e7 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -123,111 +123,6 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons } } - -void render::renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems) { - - auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->args; - auto now = usecTimestampNow(); - - int numItemsToDraw = (int)inItems.size(); - if (maxDrawnItems != -1) { - numItemsToDraw = glm::min(numItemsToDraw, maxDrawnItems); - } - - using SortedPipelines = std::vector; - using SortedShapes = std::unordered_map, render::ShapeKey::Hash, render::ShapeKey::KeyEqual>; - SortedPipelines sortedPipelines; - SortedShapes sortedShapes; - std::vector ownPipelineBucket; - - { - PROFILE_RANGE(render_detail, "sort"); - - for (auto i = 0; i < numItemsToDraw; ++i) { - auto item = scene->getItem(inItems[i].id); - - { - assert(item.getKey().isShape()); - const auto key = item.getShapeKey(); - if (key.isValid() && !key.hasOwnPipeline()) { - auto& bucket = sortedShapes[key]; - if (bucket.empty()) { - sortedPipelines.push_back(key); - } - bucket.push_back(item); - } else if (key.hasOwnPipeline()) { - ownPipelineBucket.push_back(item); - } else { - qCDebug(renderlogging) << "Item could not be rendered with invalid key" << key; - } - } - } - } - - { - PROFILE_RANGE(render_detail, "render"); - - // Then render - quint64 usecHalfBudget = 1000 * 0.5 * mstimeBudget; - quint64 usecBudget = 1000 * mstimeBudget; - - int numDrawCalls = 0; - int numDrawcallsChecks = 128; - int numChecks = 0; - int numChecksBudget = 4; - - for (auto& pipelineKey : sortedPipelines) { - auto& bucket = sortedShapes[pipelineKey]; - args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); - if (!args->_pipeline) { - continue; - } - for (auto& item : bucket) { - item.render(args); - - numDrawCalls++; - if ((numDrawCalls % numDrawcallsChecks) == 0) { - auto newNow = usecTimestampNow(); - if ((newNow - now) > usecHalfBudget) { - if ((newNow - now) > usecBudget) { - return; - } - - usecHalfBudget += (usecHalfBudget / 2); - numDrawcallsChecks / 2; - numChecks++; - if (numChecks > numChecksBudget) { - return; - } - } - } - } - } - args->_pipeline = nullptr; - for (auto& item : ownPipelineBucket) { - item.render(args); - - numDrawCalls++; - if ((numDrawCalls % numDrawcallsChecks) == 0) { - auto newNow = usecTimestampNow(); - if ((newNow - now) > usecHalfBudget) { - if ((newNow - now) > usecBudget) { - return; - } - - usecHalfBudget += (usecHalfBudget / 2); - numDrawcallsChecks / 2; - numChecks++; - if (numChecks > numChecksBudget) { - return; - } - } - } - } - } -} - void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 042a927caf..890001ded0 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -19,7 +19,6 @@ namespace render { void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); -void renderStateSortShapesCapped(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, double mstimeBudget, int maxDrawnItems = -1); class DrawLightConfig : public Job::Config { diff --git a/scripts/developer/utilities/render/culling.qml b/scripts/developer/utilities/render/culling.qml index 4157b5e4dd..e3f5e67bbe 100644 --- a/scripts/developer/utilities/render/culling.qml +++ b/scripts/developer/utilities/render/culling.qml @@ -95,7 +95,6 @@ Column { GroupBox { title: "Render Items" - Column{ Column{ Repeater { @@ -111,20 +110,5 @@ Column { } } } - - Column{ - Repeater { - model: [ "Draw Opaque [ms]:DrawOpaqueDeferred" ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - integral: false - config: Render.getConfig(modelData.split(":")[1]) - property: "maxTimeBudget" - max: 10.0 - min: 0.0 - } - } - } - } } } From 3cd422e5081b69e206975ac2f3effc5ea54419b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 15:02:12 -0800 Subject: [PATCH 04/38] Last clean up --- libraries/render/src/render/DrawTask.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 890001ded0..6e0e5ba10b 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -20,7 +20,6 @@ void renderItems(const SceneContextPointer& sceneContext, const RenderContextPoi void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); void renderStateSortShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemBounds& inItems, int maxDrawnItems = -1); - class DrawLightConfig : public Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) From a00216cb4f43d967ac49f6e05a528eab00a44b5b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 21 Feb 2017 18:20:55 -0800 Subject: [PATCH 05/38] debugging the emissive issue for verlay in front --- .../render-utils/src/RenderPipelines.cpp | 7 +- .../render-utils/src/overlay3D_model.slf | 134 ++++++++++++++++++ .../src/overlay3D_translucent.slf | 2 + 3 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 libraries/render-utils/src/overlay3D_model.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index c5a6c4b6ca..53fc9153e8 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -50,6 +50,7 @@ #include "overlay3D_vert.h" #include "overlay3D_frag.h" +#include "overlay3D_model_frag.h" #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" @@ -70,17 +71,19 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); - auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); + auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); + auto pixelMaterial = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); + auto opaqueMaterialProgram = gpu::Shader::createProgram(vertex, pixelMaterial); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 16; i++) { bool isCulled = (i & 1); bool isBiased = (i & 2); bool isOpaque = (i & 4); diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf new file mode 100644 index 0000000000..dcc5eac58c --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -0,0 +1,134 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D.slf +// fragment shader +// +// Created by Sam Gateau on 6/16/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +<@include model/Light.slh@> +<$declareLightBuffer()$> +<$declareLightAmbientBuffer()$> + +<@include LightingModel.slh@> + +<@include LightDirectional.slh@> +<$declareLightingDirectional()$> + +<@include model/Material.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { + + // Need the light now + Light light = getLight(); + vec3 lightDirection = getLightDirection(light); + vec3 lightIrradiance = getLightIrradiance(light); + + LightAmbient ambient = getLightAmbient(); + + TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, normal, fragNormal)$> + vec3 fragEyeVectorView = normalize(-position); + vec3 fragEyeDir; + <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> + + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); + + // Directional + vec3 directionalDiffuse; + vec3 directionalSpecular; + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); + color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); + + return vec4(color, opacity); +} + + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic <= 0.5) { + metallic = 0.0; + } else { + fresnel = albedo; + metallic = 1.0; + } + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + vec4 color = evalGlobalColor(occlusionTex, + fragPosition, + fragNormal, + albedo, + metallic, + fresnel, + roughness, + opacity); + + color.rgb += emissive; + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + + /*_fragColor = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + fragNormal, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);*/ +} \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 9bdac2d21f..0343567127 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,6 +82,8 @@ void main(void) { fragRoughness, fragOpacity); + color.xyz += vec3(1.0, 0.0, 0.0) * fragOpacity; + // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } From c7b164d8f26d1bb45666f1c1ad96c354b648b4ae Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 22 Feb 2017 18:21:18 -0800 Subject: [PATCH 06/38] Adding differenciation for the Material shapeKey bit --- .../render-utils/src/MeshPartPayload.cpp | 4 ++ .../render-utils/src/RenderPipelines.cpp | 66 ++++++++++--------- libraries/render/src/render/ShapePipeline.h | 9 ++- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 4cb4e2a316..5b3d285b47 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -97,6 +97,8 @@ ShapeKey MeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; + builder.withMaterial(); + if (drawMaterialKey.isTranslucent()) { builder.withTranslucent(); } @@ -478,6 +480,8 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; + builder.withMaterial(); + if (isTranslucent || _fadeState != FADE_COMPLETE) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 53fc9153e8..19284814fc 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -106,6 +106,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { } ShapeKey::Filter::Builder builder; + isCulled ? builder.withCullFace() : builder.withoutCullFace(); isBiased ? builder.withDepthBias() : builder.withoutDepthBias(); isOpaque ? builder.withOpaque() : builder.withTranslucent(); @@ -113,6 +114,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -147,78 +149,78 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // TODO: Refactor this to use a filter // Opaques addPipeline( - Key::Builder(), + Key::Builder().withMaterial(), modelVertex, modelPixel); addPipeline( - Key::Builder().withUnlit(), + Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( - Key::Builder().withTangents(), + Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSpecular(), + Key::Builder().withMaterial().withSpecular(), modelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withTangents().withSpecular(), + Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); // Translucents addPipeline( - Key::Builder().withTranslucent(), + Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withUnlit(), + Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); addPipeline( - Key::Builder().withTranslucent().withTangents(), + Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withSpecular(), + Key::Builder().withMaterial().withTranslucent().withSpecular(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withTangents().withSpecular(), + Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), modelNormalMapVertex, modelTranslucentPixel); addPipeline( // FIXME: Ignore lightmap for translucents meshpart - Key::Builder().withTranslucent().withLightmap(), + Key::Builder().withMaterial().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); // Lightmapped addPipeline( - Key::Builder().withLightmap(), + Key::Builder().withMaterial().withLightmap(), modelLightmapVertex, modelLightmapPixel); addPipeline( - Key::Builder().withLightmap().withTangents(), + Key::Builder().withMaterial().withLightmap().withTangents(), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); addPipeline( - Key::Builder().withLightmap().withSpecular(), + Key::Builder().withMaterial().withLightmap().withSpecular(), modelLightmapVertex, modelLightmapSpecularMapPixel); addPipeline( - Key::Builder().withLightmap().withTangents().withSpecular(), + Key::Builder().withMaterial().withLightmap().withTangents().withSpecular(), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); // Skinned addPipeline( - Key::Builder().withSkinned(), + Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel); addPipeline( - Key::Builder().withSkinned().withTangents(), + Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSkinned().withSpecular(), + Key::Builder().withMaterial().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); // Skinned and Translucent addPipeline( - Key::Builder().withSkinned().withTranslucent(), + Key::Builder().withMaterial().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withTangents(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), skinModelNormalMapVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), skinModelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withSkinned().withTranslucent().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), skinModelNormalMapVertex, modelTranslucentPixel); // Depth-only addPipeline( @@ -247,32 +249,32 @@ void initForwardPipelines(render::ShapePlumber& plumber) { auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); // Opaques addPipeline( - Key::Builder(), + Key::Builder().withMaterial(), modelVertex, modelPixel); addPipeline( - Key::Builder().withUnlit(), + Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( - Key::Builder().withTangents(), + Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSpecular(), + Key::Builder().withMaterial().withSpecular(), modelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withTangents().withSpecular(), + Key::Builder().withMaterial().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); // Skinned addPipeline( - Key::Builder().withSkinned(), + Key::Builder().withMaterial().withSkinned(), skinModelVertex, modelPixel); addPipeline( - Key::Builder().withSkinned().withTangents(), + Key::Builder().withMaterial().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); addPipeline( - Key::Builder().withSkinned().withSpecular(), + Key::Builder().withMaterial().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), + Key::Builder().withMaterial().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index e7a14d2f2b..e55c1d4bc4 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -22,7 +22,8 @@ namespace render { class ShapeKey { public: enum FlagBit { - TRANSLUCENT = 0, + MATERIAL = 0, + TRANSLUCENT, LIGHTMAP, TANGENTS, SPECULAR, @@ -53,6 +54,7 @@ public: ShapeKey build() const { return ShapeKey{_flags}; } + Builder& withMaterial() { _flags.set(MATERIAL); return (*this); } Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); } Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } Builder& withTangents() { _flags.set(TANGENTS); return (*this); } @@ -89,6 +91,9 @@ public: Filter build() const { return Filter(_flags, _mask); } + Builder& withMaterial() { _flags.set(MATERIAL); _mask.set(MATERIAL); return (*this); } + Builder& withoutMaterial() { _flags.reset(MATERIAL); _mask.set(MATERIAL); return (*this); } + Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } @@ -134,6 +139,7 @@ public: Flags _mask{0}; }; + bool useMaterial() const { return _flags[MATERIAL]; } bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } bool hasSpecular() const { return _flags[SPECULAR]; } @@ -170,6 +176,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { debug << "[ShapeKey: OWN_PIPELINE]"; } else { debug << "[ShapeKey:" + << "useMaterial:" << key.useMaterial() << "hasLightmap:" << key.hasLightmap() << "hasTangents:" << key.hasTangents() << "hasSpecular:" << key.hasSpecular() From 6d59144a4f6be81935376fb8893a1d1c04ea6363 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 23 Feb 2017 17:42:02 -0800 Subject: [PATCH 07/38] Trying to fix the emissive for overlay in front ? --- interface/src/ui/overlays/OverlaysPayload.cpp | 6 +++++- libraries/render-utils/src/RenderPipelines.cpp | 9 +++++---- libraries/render-utils/src/overlay3D_model.slf | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 277a86e93f..4aa3edbe6c 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -62,7 +62,11 @@ namespace render { if (overlay->is3D()) { auto overlay3D = std::dynamic_pointer_cast(overlay); if (overlay3D->isAA()) - return (overlay3D->getDrawInFront() ? LAYER_3D_FRONT : LAYER_3D); + if (overlay3D->getDrawInFront()) { + return LAYER_3D_FRONT; + } else { + return LAYER_3D; + } else return LAYER_NO_AA; } else { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 19284814fc..cbbd1cd193 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -71,6 +71,7 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); + auto vertexModel = gpu::Shader::createVertex(std::string(model_vert)); auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); @@ -81,7 +82,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); - auto opaqueMaterialProgram = gpu::Shader::createProgram(vertex, pixelMaterial); + auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); for (int i = 0; i < 16; i++) { bool isCulled = (i & 1); @@ -113,9 +114,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); + plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().withoutUnlit().build(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index dcc5eac58c..cd4179b112 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,9 +112,10 @@ void main(void) { opacity); color.rgb += emissive; - + color.rgb = vec3(0.5, 0.5, 1.0); // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 0.9); + //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, From 67031850aab6e723a230b8d06507c90b6a9790f1 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 00:05:54 -0800 Subject: [PATCH 08/38] Deep dive into the shape key and filters and the PLumber construction --- libraries/render-utils/src/RenderPipelines.cpp | 4 ++-- libraries/render/src/render/ShapePipeline.cpp | 4 ++++ libraries/render/src/render/ShapePipeline.h | 7 ------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index cbbd1cd193..59d8baacf8 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -84,7 +84,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); - for (int i = 0; i < 16; i++) { + for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); bool isBiased = (i & 2); bool isOpaque = (i & 4); @@ -115,7 +115,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withMaterial().withoutUnlit().build(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 48e8ee43d5..cec1971165 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -39,6 +39,10 @@ void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit } } else { // Add the brand new pipeline and cache its location in the lib + auto precedent = _pipelineMap.find(key); + if (precedent != _pipelineMap.end()) { + qCDebug(renderlogging) << "Key already assigned: " << key; + } _pipelineMap.insert(PipelineMap::value_type(key, pipeline)); } } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index e55c1d4bc4..c7e494ee4c 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -29,7 +29,6 @@ public: SPECULAR, UNLIT, SKINNED, - STEREO, DEPTH_ONLY, DEPTH_BIAS, WIREFRAME, @@ -61,7 +60,6 @@ public: Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } - Builder& withStereo() { _flags.set(STEREO); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withDepthBias() { _flags.set(DEPTH_BIAS); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } @@ -112,9 +110,6 @@ public: Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } - Builder& withStereo() { _flags.set(STEREO); _mask.set(STEREO); return (*this); } - Builder& withoutStereo() { _flags.reset(STEREO); _mask.set(STEREO); return (*this); } - Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } @@ -146,7 +141,6 @@ public: bool isUnlit() const { return _flags[UNLIT]; } bool isTranslucent() const { return _flags[TRANSLUCENT]; } bool isSkinned() const { return _flags[SKINNED]; } - bool isStereo() const { return _flags[STEREO]; } bool isDepthOnly() const { return _flags[DEPTH_ONLY]; } bool isDepthBiased() const { return _flags[DEPTH_BIAS]; } bool isWireFrame() const { return _flags[WIREFRAME]; } @@ -183,7 +177,6 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "isUnlit:" << key.isUnlit() << "isTranslucent:" << key.isTranslucent() << "isSkinned:" << key.isSkinned() - << "isStereo:" << key.isStereo() << "isDepthOnly:" << key.isDepthOnly() << "isDepthBiased:" << key.isDepthBiased() << "isWireFrame:" << key.isWireFrame() From e1aad8bd63950baa11b5e520924d07a633f1af49 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 00:35:10 -0800 Subject: [PATCH 09/38] Deep dive into the shape key and filters and the PLumber construction --- .../src/model-networking/TextureCache.cpp | 8 ------- .../src/model-networking/TextureCache.h | 4 ---- libraries/render-utils/src/DeferredBuffer.slh | 21 ------------------- libraries/render-utils/src/GeometryCache.cpp | 15 ------------- .../render-utils/src/RenderPipelines.cpp | 7 ++----- libraries/render/src/render/ShapePipeline.cpp | 5 ----- libraries/render/src/render/ShapePipeline.h | 3 --- 7 files changed, 2 insertions(+), 61 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index f371207981..8a4e85cfe6 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -154,14 +154,6 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() { return _blackTexture; } - -const gpu::TexturePointer& TextureCache::getNormalFittingTexture() { - if (!_normalFittingTexture) { - _normalFittingTexture = getImageTexture(PathUtils::resourcesPath() + "images/normalFittingScale.dds"); - } - return _normalFittingTexture; -} - /// Extra data for creating textures. class TextureExtra { public: diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index cb509490c6..77311afae6 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -124,9 +124,6 @@ public: /// Returns the a black texture (useful for a default). const gpu::TexturePointer& getBlackTexture(); - // Returns a map used to compress the normals through a fitting scale algorithm - const gpu::TexturePointer& getNormalFittingTexture(); - /// Returns a texture version of an image file static gpu::TexturePointer getImageTexture(const QString& path, Type type = Type::DEFAULT_TEXTURE, QVariantMap options = QVariantMap()); @@ -151,7 +148,6 @@ private: gpu::TexturePointer _grayTexture; gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; - gpu::TexturePointer _normalFittingTexture; }; #endif // hifi_TextureCache_h diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index a4b69bd70e..a13c2ec5d1 100644 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -65,25 +65,4 @@ float packUnlit() { return FRAG_PACK_UNLIT; } - - <@endif@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index c277b9be64..e0dee7b953 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -414,8 +414,6 @@ _nextID(0) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } ); GeometryCache::_simpleTransparentPipeline = @@ -424,8 +422,6 @@ _nextID(0) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } ); GeometryCache::_simpleWirePipeline = @@ -1770,7 +1766,6 @@ static void buildWebShader(const std::string& vertShaderText, const std::string& shaderPointerOut = gpu::Shader::createProgram(VS, PS); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*shaderPointerOut, slotBindings); auto state = std::make_shared(); state->setCullMode(gpu::State::CULL_NONE); @@ -1784,9 +1779,6 @@ static void buildWebShader(const std::string& vertShaderText, const std::string& void GeometryCache::bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA) { batch.setPipeline(getOpaqueWebBrowserProgram(isAA)); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram(bool isAA) { @@ -1802,9 +1794,6 @@ gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram(bool isAA) { void GeometryCache::bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA) { batch.setPipeline(getTransparentWebBrowserProgram(isAA)); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getTransparentWebBrowserProgram(bool isAA) { @@ -1827,9 +1816,6 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool tra batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); } - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); } gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) { @@ -1846,7 +1832,6 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 59d8baacf8..158daad54c 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -114,9 +114,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().withoutMaterial().build(), unlitProgram, state, &batchSetter); + plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -325,9 +325,6 @@ void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { // Set a default albedo map batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); // Set a default material if (pipeline.locations->materialBufferUnit >= 0) { diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index cec1971165..1c8e73f5d7 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -69,16 +69,11 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING)); gpu::Shader::makeProgram(*program, slotBindings); auto locations = std::make_shared(); - locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - if (program->getTextures().findLocation("normalFittingMap") > -1) { - locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - } locations->albedoTextureUnit = program->getTextures().findLocation("albedoMap"); locations->roughnessTextureUnit = program->getTextures().findLocation("roughnessMap"); locations->normalTextureUnit = program->getTextures().findLocation("normalMap"); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index c7e494ee4c..1e0f1cad76 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -213,8 +213,6 @@ public: OCCLUSION, SCATTERING, LIGHT_AMBIENT, - - NORMAL_FITTING = 10, }; }; @@ -226,7 +224,6 @@ public: int metallicTextureUnit; int emissiveTextureUnit; int occlusionTextureUnit; - int normalFittingMapUnit; int lightingModelBufferUnit; int skinClusterBufferUnit; int materialBufferUnit; From 5257194c4825406920c9aa614a7d7e9e5f2a703f Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 24 Feb 2017 01:11:59 -0800 Subject: [PATCH 10/38] SImplify the overlay PLumber --- libraries/render-utils/src/RenderPipelines.cpp | 7 ++++--- libraries/render-utils/src/overlay3D_model.slf | 4 ++-- libraries/render-utils/src/overlay3D_translucent.slf | 3 ++- libraries/render/src/render/ShapePipeline.h | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 158daad54c..508b035a5a 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -114,9 +114,10 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withMaterial().build(), opaqueMaterialProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); + + plumber.addPipeline(builder.withoutUnlit().withMaterial().build().key(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index cd4179b112..979a6f2201 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,9 +112,9 @@ void main(void) { opacity); color.rgb += emissive; - color.rgb = vec3(0.5, 0.5, 1.0); + // color.rgb = vec3(0.5, 0.5, 1.0); // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 0.9); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 0343567127..9f00cdf982 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,7 +82,8 @@ void main(void) { fragRoughness, fragOpacity); - color.xyz += vec3(1.0, 0.0, 0.0) * fragOpacity; + color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; + color.w = 1.0; // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 1e0f1cad76..0c77a15184 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -128,6 +128,7 @@ public: Flags _mask{0}; }; Filter(const Filter::Builder& builder) : Filter(builder._flags, builder._mask) {} + ShapeKey key() const { return ShapeKey(_flags); } protected: friend class ShapePlumber; Flags _flags{0}; From 1b501487fd9eb019cd2894aeb8caba9c49ab623e Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Feb 2017 16:03:28 -0800 Subject: [PATCH 11/38] simple shader checks --- libraries/render-utils/src/overlay3D_model.slf | 6 ++---- scripts/system/pal.js | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 979a6f2201..75198cdfe4 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,10 +112,8 @@ void main(void) { opacity); color.rgb += emissive; - // color.rgb = vec3(0.5, 0.5, 1.0); - // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 36ecc1f084..962923eeef 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -175,7 +175,8 @@ function HighlightedEntity(id, entityProperties) { }, lineWidth: 1.0, ignoreRayIntersection: true, - drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. + //drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. + drawInFront: true // Arguable. For now, let's not distract with mysterious wires around the scene. }); HighlightedEntity.overlays.push(this); } From 9ffdc03dc9eae75a71df822d1ce6f0cc8ef67d1c Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 24 Feb 2017 18:25:24 -0800 Subject: [PATCH 12/38] setting the shaeKeys for the overly properly because most of them are CustomPipleline --- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.h | 3 ++- libraries/render-utils/src/overlay3D_model.slf | 7 +++++-- libraries/render-utils/src/overlay3D_translucent.slf | 4 ++-- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index ae0173f054..b51f83ec87 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -263,7 +263,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 8af4c1d908..3cb3c6115d 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -116,7 +116,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 45d63d9cf1..2350ec36ab 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -116,7 +116,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 2556bc84aa..d64f6db9df 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -61,7 +61,7 @@ void Shape3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Shape3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 07c2861f16..0c3dd48094 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -58,7 +58,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 2e2d586abc..41dabe83fd 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -132,7 +132,7 @@ void Text3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Text3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index bfc37ccf60..96051beb2b 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -275,7 +275,7 @@ void Web3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Web3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index c585c95025..fa8742c40c 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,7 +118,8 @@ public: private: mutable quint64 _fadeStartTime { 0 }; - mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + //mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + mutable uint8_t _fadeState { FADE_COMPLETE }; }; namespace render { diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 75198cdfe4..6c21f95a91 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -112,8 +112,11 @@ void main(void) { opacity); color.rgb += emissive; - - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + color.rgb += vec3(1, 0.0, 0.0); + // Apply standard tone mapping + // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); + _fragColor = vec4(albedo, 0.5); + //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 9f00cdf982..3604fd88c5 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,8 +82,8 @@ void main(void) { fragRoughness, fragOpacity); - color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; - color.w = 1.0; + // color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; + // color.w = 1.0; // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); From a53d5e8fbddd2ea03d30528fea17e6914e0b9b83 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 25 Feb 2017 13:00:37 -0800 Subject: [PATCH 13/38] adjusted the PLumber shape keys to coever non material shapes in main pass --- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- libraries/render-utils/src/MeshPartPayload.h | 4 ++-- libraries/render-utils/src/RenderDeferredTask.cpp | 6 ++---- libraries/render-utils/src/RenderPipelines.cpp | 9 +++++++++ libraries/render-utils/src/overlay3D_model.slf | 6 +++--- libraries/render-utils/src/overlay3D_translucent.slf | 3 --- 12 files changed, 23 insertions(+), 19 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index b51f83ec87..ae0173f054 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -263,7 +263,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withUnlit(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 3cb3c6115d..8af4c1d908 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -116,7 +116,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 2350ec36ab..45d63d9cf1 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -116,7 +116,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index d64f6db9df..2556bc84aa 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -61,7 +61,7 @@ void Shape3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Shape3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 0c3dd48094..07c2861f16 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -58,7 +58,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 41dabe83fd..2e2d586abc 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -132,7 +132,7 @@ void Text3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Text3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 96051beb2b..bfc37ccf60 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -275,7 +275,7 @@ void Web3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Web3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index fa8742c40c..9d021f4f34 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -118,8 +118,8 @@ public: private: mutable quint64 _fadeStartTime { 0 }; - //mutable uint8_t _fadeState { FADE_WAITING_TO_START }; - mutable uint8_t _fadeState { FADE_COMPLETE }; + mutable uint8_t _fadeState { FADE_WAITING_TO_START }; + // mutable uint8_t _fadeState { FADE_COMPLETE }; }; namespace render { diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 55a9c8b9e4..5d03cac58f 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -75,7 +75,6 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // GPU jobs: Start preparing the primary, deferred and lighting buffer const auto primaryFramebuffer = addJob("PreparePrimaryBuffer"); - // const auto fullFrameRangeTimer = addJob("BeginRangeTimer"); const auto opaqueRangeTimer = addJob("BeginOpaqueRangeTimer", "DrawOpaques"); const auto prepareDeferredInputs = PrepareDeferred::Inputs(primaryFramebuffer, lightingModel).hasVarying(); @@ -167,6 +166,8 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // Bounds do not draw on stencil buffer, so they must come last addJob("DrawMetaBounds", metas); + addJob("DrawOverlaysOpaques", overlayOpaques); + addJob("DrawOverlaysTransparents", overlayTransparents); // Debugging Deferred buffer job const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); @@ -207,9 +208,6 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { // Blit! addJob("Blit", primaryFramebuffer); - - // addJob("RangeTimer", fullFrameRangeTimer); - } void BeginGPURangeTimer::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 508b035a5a..93bc7b77df 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -156,6 +156,9 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); + addPipeline( + Key::Builder().withUnlit(), + modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -169,9 +172,15 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withMaterial().withTranslucent(), modelVertex, modelTranslucentPixel); + addPipeline( + Key::Builder().withTranslucent(), + modelVertex, modelTranslucentPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); + addPipeline( + Key::Builder().withTranslucent().withUnlit(), + modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 6c21f95a91..42c08d21bc 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -114,9 +114,9 @@ void main(void) { color.rgb += emissive; color.rgb += vec3(1, 0.0, 0.0); // Apply standard tone mapping - // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - _fragColor = vec4(albedo, 0.5); - //_fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); + //_fragColor = vec4(albedo, 0.5); + // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); /*_fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index 3604fd88c5..9bdac2d21f 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -82,9 +82,6 @@ void main(void) { fragRoughness, fragOpacity); - // color.xyz += vec3(0.0, 1.0, 0.0) * fragOpacity; - // color.w = 1.0; - // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } From 709c2e4240b038ecc109b4e189957569d8876a5c Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 27 Feb 2017 02:52:00 -0800 Subject: [PATCH 14/38] Fixing the emissive on overlayfor models --- .../render-utils/src/RenderDeferredTask.cpp | 19 +++-- .../render-utils/src/RenderPipelines.cpp | 12 ++- .../render-utils/src/overlay3D_model.slf | 70 +++------------- .../src/overlay3D_model_translucent.slf | 83 +++++++++++++++++++ .../utilities/render/deferredLighting.qml | 24 +++++- 5 files changed, 135 insertions(+), 73 deletions(-) create mode 100644 libraries/render-utils/src/overlay3D_model_translucent.slf diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 5d03cac58f..676d176cca 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -153,22 +153,25 @@ RenderDeferredTask::RenderDeferredTask(RenderFetchCullSortTask::Output items) { const auto toneMappingInputs = render::Varying(ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer)); addJob("ToneMapping", toneMappingInputs); + { // DEbug the bounds of the rendered items, still look at the zbuffer + addJob("DrawMetaBounds", metas); + addJob("DrawOpaqueBounds", opaques); + addJob("DrawTransparentBounds", transparents); + } + // Overlays const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).hasVarying(); const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).hasVarying(); addJob("DrawOverlay3DOpaque", overlayOpaquesInputs, true); addJob("DrawOverlay3DTransparent", overlayTransparentsInputs, false); + { // DEbug the bounds of the rendered OVERLAY items, still look at the zbuffer + addJob("DrawOverlayOpaqueBounds", overlayOpaques); + addJob("DrawOverlayTransparentBounds", overlayTransparents); + } - // Debugging stages + // Debugging stages { - - - // Bounds do not draw on stencil buffer, so they must come last - addJob("DrawMetaBounds", metas); - addJob("DrawOverlaysOpaques", overlayOpaques); - addJob("DrawOverlaysTransparents", overlayTransparents); - // Debugging Deferred buffer job const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer)); addJob("DebugDeferredBuffer", debugFramebuffers); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 93bc7b77df..d753c679c6 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -51,6 +51,7 @@ #include "overlay3D_vert.h" #include "overlay3D_frag.h" #include "overlay3D_model_frag.h" +#include "overlay3D_model_translucent_frag.h" #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" @@ -72,17 +73,19 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto vertexModel = gpu::Shader::createVertex(std::string(model_vert)); - auto pixel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); - auto pixelMaterial = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixelModel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); + auto pixelModelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); - auto opaqueMaterialProgram = gpu::Shader::createProgram(vertexModel, pixelMaterial); + auto materialOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); + auto materialTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -114,8 +117,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; + auto materialProgram = isOpaque ? materialOpaqueProgram : materialTranslucentProgram; - plumber.addPipeline(builder.withoutUnlit().withMaterial().build().key(), opaqueMaterialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().build().key(), materialProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index 42c08d21bc..bb0d84a513 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -11,15 +11,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -<@include model/Light.slh@> -<$declareLightBuffer()$> -<$declareLightAmbientBuffer()$> - -<@include LightingModel.slh@> - -<@include LightDirectional.slh@> -<$declareLightingDirectional()$> +<@include DeferredGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> <@include model/Material.slh@> @@ -29,35 +22,6 @@ <@include MaterialTextures.slh@> <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> -vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { - - // Need the light now - Light light = getLight(); - vec3 lightDirection = getLightDirection(light); - vec3 lightIrradiance = getLightIrradiance(light); - - LightAmbient ambient = getLightAmbient(); - - TransformCamera cam = getTransformCamera(); - vec3 fragNormal; - <$transformEyeToWorldDir(cam, normal, fragNormal)$> - vec3 fragEyeVectorView = normalize(-position); - vec3 fragEyeDir; - <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - - vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); - - // Directional - vec3 directionalDiffuse; - vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); - color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); - color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); - - return vec4(color, opacity); -} - - in vec2 _texCoord0; in vec2 _texCoord1; in vec4 _position; @@ -98,27 +62,13 @@ void main(void) { vec3 fragPosition = _position.xyz; - vec3 fragNormal = normalize(_normal); + //vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, _normal, fragNormal)$>; - vec4 color = evalGlobalColor(occlusionTex, - fragPosition, - fragNormal, - albedo, - metallic, - fresnel, - roughness, - opacity); - - color.rgb += emissive; - color.rgb += vec3(1, 0.0, 0.0); - // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), 1.0); - //_fragColor = vec4(albedo, 0.5); - // _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); - - /*_fragColor = vec4(evalGlobalLightingAlphaBlended( + vec4 color = vec4(evalSkyboxGlobalColor( cam._viewInverse, 1.0, occlusionTex, @@ -127,10 +77,12 @@ void main(void) { albedo, fresnel, metallic, - emissive, - roughness, opacity), + roughness), opacity); + // And emissive + color.rgb += emissive * isEmissiveEnabled(); + // Apply standard tone mapping - _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w);*/ + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); } \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf new file mode 100644 index 0000000000..748eea329c --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -0,0 +1,83 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D_model_transparent.slf +// +// Created by Sam Gateau on 2/27/2017. +// 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 DeferredGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include model/Material.slh@> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec2 _texCoord1; +in vec4 _position; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float metallic = getMaterialMetallic(mat); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic <= 0.5) { + metallic = 0.0; + } else { + fresnel = albedo; + metallic = 1.0; + } + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + + vec3 fragPosition = _position.xyz; + + TransformCamera cam = getTransformCamera(); + vec3 fragNormal; + <$transformEyeToWorldDir(cam, _normal, fragNormal)$> + + vec4 color = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + occlusionTex, + fragPosition, + fragNormal, + albedo, + fresnel, + metallic, + emissive, + roughness, opacity), + opacity); + + // Apply standard tone mapping + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 0ac4cbc5b5..99a9f258e3 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -159,13 +159,33 @@ Column { } } - Row { + Column { id: metas CheckBox { - text: "Draw Meta Bounds" + text: "Metas" checked: Render.getConfig("DrawMetaBounds")["enabled"] onCheckedChanged: { Render.getConfig("DrawMetaBounds")["enabled"] = checked } } + CheckBox { + text: "Opaques" + checked: Render.getConfig("DrawOpaqueBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOpaqueBounds")["enabled"] = checked } + } + CheckBox { + text: "Transparents" + checked: Render.getConfig("DrawTransparentBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawTransparentBounds")["enabled"] = checked } + } + CheckBox { + text: "Overlay Opaques" + checked: Render.getConfig("DrawOverlayOpaqueBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOverlayOpaqueBounds")["enabled"] = checked } + } + CheckBox { + text: "Overlay Transparents" + checked: Render.getConfig("DrawOverlayTransparentBounds")["enabled"] + onCheckedChanged: { Render.getConfig("DrawOverlayTransparentBounds")["enabled"] = checked } + } } } From 6ac85aee7e22f1fd29b0ae257f9b0a033d0213f4 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 28 Feb 2017 18:12:35 -0800 Subject: [PATCH 15/38] Adding support for the unliti materials too for overlay's --- .../render-utils/src/RenderPipelines.cpp | 8 ++++ .../src/overlay3D_model_translucent_unlit.slf | 43 ++++++++++++++++++ .../src/overlay3D_model_unlit.slf | 44 +++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 libraries/render-utils/src/overlay3D_model_translucent_unlit.slf create mode 100644 libraries/render-utils/src/overlay3D_model_unlit.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d753c679c6..3b279ff6d9 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -55,6 +55,8 @@ #include "overlay3D_translucent_frag.h" #include "overlay3D_unlit_frag.h" #include "overlay3D_translucent_unlit_frag.h" +#include "overlay3D_model_unlit_frag.h" +#include "overlay3D_model_translucent_unlit_frag.h" using namespace render; @@ -79,6 +81,8 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); auto pixelModel = gpu::Shader::createPixel(std::string(overlay3D_model_frag)); auto pixelModelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_frag)); + auto pixelModelUnlit = gpu::Shader::createPixel(std::string(overlay3D_model_unlit_frag)); + auto pixelModelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_model_translucent_unlit_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); @@ -86,6 +90,8 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); auto materialOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); auto materialTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); + auto materialUnlitOpaqueProgram = gpu::Shader::createProgram(vertexModel, pixelModel); + auto materialUnlitTranslucentProgram = gpu::Shader::createProgram(vertexModel, pixelModelTranslucent); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -118,8 +124,10 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; auto materialProgram = isOpaque ? materialOpaqueProgram : materialTranslucentProgram; + auto materialUnlitProgram = isOpaque ? materialUnlitOpaqueProgram : materialUnlitTranslucentProgram; plumber.addPipeline(builder.withMaterial().build().key(), materialProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withMaterial().withUnlit().build().key(), materialUnlitProgram, state, &batchSetter); plumber.addPipeline(builder.withoutUnlit().withoutMaterial().build().key(), simpleProgram, state, &lightBatchSetter); plumber.addPipeline(builder.withUnlit().withoutMaterial().build().key(), unlitProgram, state, &batchSetter); } diff --git a/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf new file mode 100644 index 0000000000..3dd8138272 --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_translucent_unlit.slf @@ -0,0 +1,43 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D-model_transparent_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 2/28/2017. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include LightingModel.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + vec4 color = vec4(albedo * isUnlitEnabled(), opacity); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} \ No newline at end of file diff --git a/libraries/render-utils/src/overlay3D_model_unlit.slf b/libraries/render-utils/src/overlay3D_model_unlit.slf new file mode 100644 index 0000000000..80c2bb971e --- /dev/null +++ b/libraries/render-utils/src/overlay3D_model_unlit.slf @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// overlay3D-model_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 2/28/2017. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include LightingModel.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + vec4 color = vec4(albedo * isUnlitEnabled(), opacity); + + _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); +} From 6d4abca0c122d855825fdb2cf3212ab89ba8220f Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 4 Mar 2017 11:12:19 +0200 Subject: [PATCH 16/38] Base line progress --- .../tutorials/entity_scripts/magneticBlock.js | 68 +++++++++++++++++++ scripts/tutorials/makeBlocks.js | 0 2 files changed, 68 insertions(+) create mode 100644 scripts/tutorials/entity_scripts/magneticBlock.js create mode 100644 scripts/tutorials/makeBlocks.js diff --git a/scripts/tutorials/entity_scripts/magneticBlock.js b/scripts/tutorials/entity_scripts/magneticBlock.js new file mode 100644 index 0000000000..6eb0900db5 --- /dev/null +++ b/scripts/tutorials/entity_scripts/magneticBlock.js @@ -0,0 +1,68 @@ +(function(){ + + // Helper for detecting nearby objects + function findEntitiesInRange(releasedProperties) { + var dimensions = releasedProperties.dimensions; + return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) *1.5); + } + function getNearestValidEntityProperties(id) { + var releasedProperties = Entities.getEntityProperties(id,["position", "rotation", "dimensions"]); + var entities = findEntitiesInRange(releasedProperties); + var nearestEntity = null; + var nearest = -1; + var releaseSize = Vec3.length(releasedProperties.dimensions); + entities.forEach(function(entityId) { + print('ftest ' + entityId); + var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']); + var distance = Vec3.distance(releasedProperties.position, entity.position); + var scale = releaseSize/Vec3.length(entity.dimensions); + if ((nearest === -1 || distance < nearest && scale >= 0.5 && scale <= 2 ) && entity.id !== entityId) { + nearestEntity = entity; + dnearest = distance; + } + }) + return nearestEntity; + + } + + // Create the 'class' + function MagneticBlock () { } + // Bind pre-emptive events + MagneticBlock.prototype = { + // When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor + preload: function (id) { + /* + We will now override any existing userdata with the grabbable property. + Only retrieving userData + */ + var val = Entities.getEntityProperties(id, ['userData']) + var userData = {}; + if (val.userData && val.userData.length > 0 ) { + try { + userData = JSON.parse(val.userData); + } catch (e) {} + } + // Object must be triggerable inorder to bind events. + userData.grabbableKey = {grabbable: true}; + // Apply the new properties to entity of id + Entities.editEntity(id, {userData: JSON.stringify(userData)}); + this.held = false; + + // We will now create a custom binding, to keep the 'current' context as these are callbacks called without context + var t = this; + this.callbacks = {}; + this.callbacks["releaseGrab"] = function () { + var nearest = getNearestValidEntityProperties(id); + + print(JSON.stringify(nearest)); + } + + this.releaseGrab = this.callbacks["releaseGrab"]; + + Script.scriptEnding.connect( function () { + Script.removeEventHandler(id, "releaseGrab", this.callbacks["releaseGrab"]); //continueNearGrab + }) + } + } + return new MagneticBlock(); +}) diff --git a/scripts/tutorials/makeBlocks.js b/scripts/tutorials/makeBlocks.js new file mode 100644 index 0000000000..e69de29bb2 From ea3f7f02749856c9ca7bde0fc7a77f2464b13ffe Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 4 Mar 2017 18:50:30 +0200 Subject: [PATCH 17/38] Initial Magnetic block --- scripts/system/assets/sounds/entitySnap.wav | Bin 0 -> 30858 bytes .../tutorials/entity_scripts/magneticBlock.js | 79 ++++++++++++++---- scripts/tutorials/makeBlocks.js | 15 ++++ 3 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 scripts/system/assets/sounds/entitySnap.wav diff --git a/scripts/system/assets/sounds/entitySnap.wav b/scripts/system/assets/sounds/entitySnap.wav new file mode 100644 index 0000000000000000000000000000000000000000..4584f3dcaa7469e2efd170c68a30ed306674ca91 GIT binary patch literal 30858 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 0.5 && scale <= 2 ) && entity.id !== entityId) { - nearestEntity = entity; - dnearest = distance; + if(entityId !== releasedProperties.id) { + var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']); + var distance = Vec3.distance(releasedProperties.position, entity.position); + var scale = releaseSize/Vec3.length(entity.dimensions); + + if (distance < nearest && (scale >= 0.5 && scale <= 2)) { + nearestEntity = entity; + nearest = distance; + } } }) return nearestEntity; - } - // Create the 'class' function MagneticBlock () { } // Bind pre-emptive events @@ -52,13 +56,56 @@ var t = this; this.callbacks = {}; this.callbacks["releaseGrab"] = function () { - var nearest = getNearestValidEntityProperties(id); + var released = Entities.getEntityProperties(id,["position", "rotation", "dimensions"]); + var target = getNearestValidEntityProperties(released); + if (target !== null) { + // We found nearest, now lets do the snap calculations + // Plays the snap sound between the two objects. + Audio.playSound(SNAPSOUND, { + volume: 1, + position: Vec3.mix(target.position, released.position, 0.5) + }); + // Check Nearest Axis + var difference = Vec3.subtract(released.position, target.position); + var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference); - print(JSON.stringify(nearest)); + var abs = { + x: Math.abs(relativeDifference.x), + y: Math.abs(relativeDifference.y), + z: Math.abs(relativeDifference.z) + }; + + if (abs.x >= abs.y && abs.x >= abs.z) { + relativeDifference.y = 0; + relativeDifference.z = 0; + if (relativeDifference.x > 0) { + relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2; + } else { + relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2; + } + } else if (abs.y >= abs.x && abs.y >= abs.z) { + relativeDifference.x = 0; + relativeDifference.z = 0; + if (relativeDifference.y > 0) { + relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2; + } else { + relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2; + } + } else if (abs.z >= abs.x && abs.z >= abs.y ) { + relativeDifference.x = 0; + relativeDifference.y = 0; + if (relativeDifference.z > 0) { + relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2; + } else { + relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2; + } + } + var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference); + Entities.editEntity(id, {rotation: target.rotation, position: Vec3.sum(target.position, newPosition)}) + } } this.releaseGrab = this.callbacks["releaseGrab"]; - Script.scriptEnding.connect( function () { Script.removeEventHandler(id, "releaseGrab", this.callbacks["releaseGrab"]); //continueNearGrab }) diff --git a/scripts/tutorials/makeBlocks.js b/scripts/tutorials/makeBlocks.js index e69de29bb2..6a8b95bb3f 100644 --- a/scripts/tutorials/makeBlocks.js +++ b/scripts/tutorials/makeBlocks.js @@ -0,0 +1,15 @@ +// Toy +const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum. +const MIN_COLOR_VALUE = 127; +function newColor() { + color = { + red: randomPastelRGBComponent(), + green: randomPastelRGBComponent(), + blue: randomPastelRGBComponent() + }; + return color; + } +// Helper functions. +function randomPastelRGBComponent() { + return Math.floor(Math.random() * MAX_RGB_COMPONENT_VALUE) + MIN_COLOR_VALUE; +} From fe19b5511ce5b1f04c42e6db7369c1c9f075c289 Mon Sep 17 00:00:00 2001 From: Menithal Date: Sat, 4 Mar 2017 21:55:21 +0200 Subject: [PATCH 18/38] Fixed up blocks scripts --- .../tutorials/entity_scripts/magneticBlock.js | 240 ++++++++++-------- scripts/tutorials/makeBlocks.js | 79 ++++-- 2 files changed, 193 insertions(+), 126 deletions(-) diff --git a/scripts/tutorials/entity_scripts/magneticBlock.js b/scripts/tutorials/entity_scripts/magneticBlock.js index 73f317e3b2..a375025671 100644 --- a/scripts/tutorials/entity_scripts/magneticBlock.js +++ b/scripts/tutorials/entity_scripts/magneticBlock.js @@ -1,115 +1,133 @@ -(function(){ +// +// magneticBlock.js +// +// Created by Matti Lahtinen 4/3/2017 +// 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 +// +// Makes the entity the script is bound to connect to nearby, similarly sized entities, like a magnet. +(function() { + const SNAPSOUND_SOURCE = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs")); + // Preload trick for faster playback + const RANGE_MULTIPLER = 1.5; - const SNAPSOUND = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs")); - const RANGE_MULTIPLER = 1.5; - - // Helper for detecting nearby objects - function findEntitiesInRange(releasedProperties) { - var dimensions = releasedProperties.dimensions; - return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); - } - - function getNearestValidEntityProperties(releasedProperties) { - var entities = findEntitiesInRange(releasedProperties); - var nearestEntity = null; - var nearest = 9999999999999; - var releaseSize = Vec3.length(releasedProperties.dimensions); - entities.forEach(function(entityId) { - if(entityId !== releasedProperties.id) { - var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']); - var distance = Vec3.distance(releasedProperties.position, entity.position); - var scale = releaseSize/Vec3.length(entity.dimensions); - - if (distance < nearest && (scale >= 0.5 && scale <= 2)) { - nearestEntity = entity; - nearest = distance; - } - } - }) - return nearestEntity; - } - // Create the 'class' - function MagneticBlock () { } - // Bind pre-emptive events - MagneticBlock.prototype = { - // When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor - preload: function (id) { - /* - We will now override any existing userdata with the grabbable property. - Only retrieving userData - */ - var val = Entities.getEntityProperties(id, ['userData']) - var userData = {}; - if (val.userData && val.userData.length > 0 ) { - try { - userData = JSON.parse(val.userData); - } catch (e) {} - } - // Object must be triggerable inorder to bind events. - userData.grabbableKey = {grabbable: true}; - // Apply the new properties to entity of id - Entities.editEntity(id, {userData: JSON.stringify(userData)}); - this.held = false; - - // We will now create a custom binding, to keep the 'current' context as these are callbacks called without context - var t = this; - this.callbacks = {}; - this.callbacks["releaseGrab"] = function () { - var released = Entities.getEntityProperties(id,["position", "rotation", "dimensions"]); - var target = getNearestValidEntityProperties(released); - if (target !== null) { - // We found nearest, now lets do the snap calculations - // Plays the snap sound between the two objects. - Audio.playSound(SNAPSOUND, { - volume: 1, - position: Vec3.mix(target.position, released.position, 0.5) - }); - // Check Nearest Axis - var difference = Vec3.subtract(released.position, target.position); - var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference); - - var abs = { - x: Math.abs(relativeDifference.x), - y: Math.abs(relativeDifference.y), - z: Math.abs(relativeDifference.z) - }; - - if (abs.x >= abs.y && abs.x >= abs.z) { - relativeDifference.y = 0; - relativeDifference.z = 0; - if (relativeDifference.x > 0) { - relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2; - } else { - relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2; - } - } else if (abs.y >= abs.x && abs.y >= abs.z) { - relativeDifference.x = 0; - relativeDifference.z = 0; - if (relativeDifference.y > 0) { - relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2; - } else { - relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2; - } - } else if (abs.z >= abs.x && abs.z >= abs.y ) { - relativeDifference.x = 0; - relativeDifference.y = 0; - if (relativeDifference.z > 0) { - relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2; - } else { - relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2; - } - } - var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference); - Entities.editEntity(id, {rotation: target.rotation, position: Vec3.sum(target.position, newPosition)}) - } - } - - this.releaseGrab = this.callbacks["releaseGrab"]; - Script.scriptEnding.connect( function () { - Script.removeEventHandler(id, "releaseGrab", this.callbacks["releaseGrab"]); //continueNearGrab - }) + // Helper for detecting nearby objects + function findEntitiesInRange(releasedProperties) { + var dimensions = releasedProperties.dimensions; + return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); } - } - return new MagneticBlock(); + + function getNearestValidEntityProperties(releasedProperties) { + var entities = findEntitiesInRange(releasedProperties); + var nearestEntity = null; + var nearest = 9999999999999; + var releaseSize = Vec3.length(releasedProperties.dimensions); + entities.forEach(function(entityId) { + if (entityId !== releasedProperties.id) { + var entity = Entities.getEntityProperties(entityId, ['position', 'rotation', 'dimensions']); + var distance = Vec3.distance(releasedProperties.position, entity.position); + var scale = releaseSize / Vec3.length(entity.dimensions); + + if (distance < nearest && (scale >= 0.5 && scale <= 2)) { + nearestEntity = entity; + nearest = distance; + } + } + }) + return nearestEntity; + } + // Create the 'class' + function MagneticBlock() {} + // Bind pre-emptive events + MagneticBlock.prototype = { + // When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor + preload: function(id) { + /* + We will now override any existing userdata with the grabbable property. + Only retrieving userData + */ + var val = Entities.getEntityProperties(id, ['userData']) + var userData = {grabbableKey: {}}; + + if (val.userData && val.userData.length > 0) { + try { + userData = JSON.parse(val.userData); + } catch (e) { + } + } + // Object must be triggerable inorder to bind events. + userData.grabbableKey.grabbable = true; + + // Apply the new properties to entity of id + Entities.editEntity(id, { + userData: JSON.stringify(userData) + }); + this.held = false; + // We will now create a custom binding, to keep the 'current' context as these are callbacks called without context + var t = this; + this.callbacks = {}; + this.releaseGrab = function() { + var released = Entities.getEntityProperties(id, ["position", "rotation", "dimensions"]); + var target = getNearestValidEntityProperties(released); + if (target !== null) { + // We found nearest, now lets do the snap calculations + // Plays the snap sound between the two objects. + Audio.playSound(SNAPSOUND_SOURCE, { + volume: 1, + position: Vec3.mix(target.position, released.position, 0.5) + }); + // Check Nearest Axis + var difference = Vec3.subtract(released.position, target.position); + var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference); + + var abs = { + x: Math.abs(relativeDifference.x), + y: Math.abs(relativeDifference.y), + z: Math.abs(relativeDifference.z) + }; + // Check what value is greater. Simplified. + if (abs.x >= abs.y && abs.x >= abs.z) { + relativeDifference.y = 0; + relativeDifference.z = 0; + if (relativeDifference.x > 0) { + relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2; + } else { + relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2; + } + } else if (abs.y >= abs.x && abs.y >= abs.z) { + relativeDifference.x = 0; + relativeDifference.z = 0; + if (relativeDifference.y > 0) { + relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2; + } else { + relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2; + } + } else if (abs.z >= abs.x && abs.z >= abs.y) { + relativeDifference.x = 0; + relativeDifference.y = 0; + if (relativeDifference.z > 0) { + relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2; + } else { + relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2; + } + } + // Can be expanded upon to work in nearest rotation as well, but was not in spec. + var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference); + Entities.editEntity(id, { + rotation: target.rotation, + position: Vec3.sum(target.position, newPosition) + }) + } + } + + Script.scriptEnding.connect(function() { + Script.removeEventHandler(id, "releaseGrab", this.releaseGrab); + }) + } + } + return new MagneticBlock(); }) diff --git a/scripts/tutorials/makeBlocks.js b/scripts/tutorials/makeBlocks.js index 6a8b95bb3f..bb4974498c 100644 --- a/scripts/tutorials/makeBlocks.js +++ b/scripts/tutorials/makeBlocks.js @@ -1,15 +1,64 @@ -// Toy -const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum. -const MIN_COLOR_VALUE = 127; -function newColor() { - color = { - red: randomPastelRGBComponent(), - green: randomPastelRGBComponent(), - blue: randomPastelRGBComponent() - }; - return color; - } -// Helper functions. -function randomPastelRGBComponent() { - return Math.floor(Math.random() * MAX_RGB_COMPONENT_VALUE) + MIN_COLOR_VALUE; -} +// +// makeBlocks.js +// +// Created by Matti Lahtinen 4/3/2017 +// 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 +// +// Creates multiple "magnetic" blocks with random colors that users clones of and snap together. + + +(function() { + const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum. + const MIN_COLOR_VALUE = 127; + const SIZE = 0.3; + const LIFETIME = 600; + + // Random Pastel Generator based on Piper's script + function newColor() { + color = { + red: randomPastelRGBComponent(), + green: randomPastelRGBComponent(), + blue: randomPastelRGBComponent() + }; + return color; + } + // Helper functions. + function randomPastelRGBComponent() { + return Math.floor(Math.random() * MAX_RGB_COMPONENT_VALUE) + MIN_COLOR_VALUE; + } + + var SCRIPT_URL = Script.resolvePath("./entity_scripts/magneticBlock.js"); + + var frontVector = Quat.getFront(MyAvatar.orientation); + frontVector.y -=.25; + for(var x =0; x < 3; x++) { + for (var y = 0; y < 3; y++) { + + var frontOffset = { + x: 0, + y: SIZE * y + SIZE, + z: SIZE * x + SIZE + }; + + Entities.addEntity({ + type: "Box", + name: "MagneticBlock-" + y +'-' + x, + dimensions: { + x: SIZE, + y: SIZE, + z: SIZE + }, + userData: JSON.stringify({grabbableKey: { cloneable: true, grabbable: true, cloneLifetime : LIFETIME, cloneLimit: 9999}}), + position: Vec3.sum(MyAvatar.position, Vec3.sum(frontOffset, frontVector)), + color: newColor(), + script: SCRIPT_URL + }); + } + } + + Script.stop(); +})(); From 04d3bf0c3802e1a77dee971eca94a915ca6c1dc6 Mon Sep 17 00:00:00 2001 From: Menithal Date: Mon, 6 Mar 2017 10:55:47 +0200 Subject: [PATCH 19/38] Cleanup and safeguards - RegistrationPoint can no longer be set for magnetic blocks, will set it to 0.5 on snap. - Simplified axis lock logic --- .../tutorials/entity_scripts/magneticBlock.js | 147 ++++++++++-------- 1 file changed, 80 insertions(+), 67 deletions(-) diff --git a/scripts/tutorials/entity_scripts/magneticBlock.js b/scripts/tutorials/entity_scripts/magneticBlock.js index a375025671..911e9c0eb5 100644 --- a/scripts/tutorials/entity_scripts/magneticBlock.js +++ b/scripts/tutorials/entity_scripts/magneticBlock.js @@ -12,13 +12,14 @@ (function() { const SNAPSOUND_SOURCE = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs")); - // Preload trick for faster playback const RANGE_MULTIPLER = 1.5; + const MAX_SCALE = 2; + const MIN_SCALE = 0.5; - // Helper for detecting nearby objects - function findEntitiesInRange(releasedProperties) { - var dimensions = releasedProperties.dimensions; - return Entities.findEntities(releasedProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); + // Helper for detecting nearby objects near entityProperties, with the scale calculated by the dimensions of the object. + function findEntitiesInRange(entityProperties) { + var dimensions = entityProperties.dimensions; + return Entities.findEntities(entityProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); } function getNearestValidEntityProperties(releasedProperties) { @@ -32,7 +33,7 @@ var distance = Vec3.distance(releasedProperties.position, entity.position); var scale = releaseSize / Vec3.length(entity.dimensions); - if (distance < nearest && (scale >= 0.5 && scale <= 2)) { + if (distance < nearest && (scale >= MIN_SCALE && scale <= MAX_SCALE)) { nearestEntity = entity; nearest = distance; } @@ -51,82 +52,94 @@ Only retrieving userData */ var val = Entities.getEntityProperties(id, ['userData']) - var userData = {grabbableKey: {}}; - + var userData = { + grabbableKey: {} + }; + // Check if existing userData field exists. if (val.userData && val.userData.length > 0) { try { userData = JSON.parse(val.userData); + if (!userData.grabbableKey) { + userData.grabbableKey = {}; // If by random change there is no grabbableKey in the userData. + } } catch (e) { + // if user data is not valid json, we will simply overwrite it. } } - // Object must be triggerable inorder to bind events. + // Object must be triggerable inorder to bind releaseGrabEvent userData.grabbableKey.grabbable = true; // Apply the new properties to entity of id Entities.editEntity(id, { userData: JSON.stringify(userData) }); - this.held = false; - // We will now create a custom binding, to keep the 'current' context as these are callbacks called without context - var t = this; - this.callbacks = {}; - this.releaseGrab = function() { - var released = Entities.getEntityProperties(id, ["position", "rotation", "dimensions"]); - var target = getNearestValidEntityProperties(released); - if (target !== null) { - // We found nearest, now lets do the snap calculations - // Plays the snap sound between the two objects. - Audio.playSound(SNAPSOUND_SOURCE, { - volume: 1, - position: Vec3.mix(target.position, released.position, 0.5) - }); - // Check Nearest Axis - var difference = Vec3.subtract(released.position, target.position); - var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference); - - var abs = { - x: Math.abs(relativeDifference.x), - y: Math.abs(relativeDifference.y), - z: Math.abs(relativeDifference.z) - }; - // Check what value is greater. Simplified. - if (abs.x >= abs.y && abs.x >= abs.z) { - relativeDifference.y = 0; - relativeDifference.z = 0; - if (relativeDifference.x > 0) { - relativeDifference.x = target.dimensions.x / 2 + released.dimensions.x / 2; - } else { - relativeDifference.x = -target.dimensions.x / 2 - released.dimensions.x / 2; - } - } else if (abs.y >= abs.x && abs.y >= abs.z) { - relativeDifference.x = 0; - relativeDifference.z = 0; - if (relativeDifference.y > 0) { - relativeDifference.y = target.dimensions.y / 2 + released.dimensions.y / 2; - } else { - relativeDifference.y = -target.dimensions.y / 2 - released.dimensions.y / 2; - } - } else if (abs.z >= abs.x && abs.z >= abs.y) { - relativeDifference.x = 0; - relativeDifference.y = 0; - if (relativeDifference.z > 0) { - relativeDifference.z = target.dimensions.z / 2 + released.dimensions.z / 2; - } else { - relativeDifference.z = -target.dimensions.z / 2 - released.dimensions.z / 2; - } - } - // Can be expanded upon to work in nearest rotation as well, but was not in spec. - var newPosition = Vec3.multiplyQbyV(target.rotation, relativeDifference); - Entities.editEntity(id, { - rotation: target.rotation, - position: Vec3.sum(target.position, newPosition) - }) - } - } - Script.scriptEnding.connect(function() { Script.removeEventHandler(id, "releaseGrab", this.releaseGrab); }) + }, + releaseGrab: function(entityId) { + // Release grab is called with entityId, + var released = Entities.getEntityProperties(entityId, ["position", "rotation", "dimensions"]); + var target = getNearestValidEntityProperties(released); + if (target !== null) { + // We found nearest, now lets do the snap calculations + // Plays the snap sound between the two objects. + Audio.playSound(SNAPSOUND_SOURCE, { + volume: 1, + position: Vec3.mix(target.position, released.position, 0.5) + }); + // Check Nearest Axis + var difference = Vec3.subtract(released.position, target.position); + var relativeDifference = Vec3.multiplyQbyV(Quat.inverse(target.rotation), difference); + + var abs = { + x: Math.abs(relativeDifference.x), + y: Math.abs(relativeDifference.y), + z: Math.abs(relativeDifference.z) + }; + // Check what value is greater. and lock down to that axis. + var newRelative = { + x: 0, + y: 0, + z: 0 + } + if (abs.x >= abs.y && abs.x >= abs.z) { + newRelative.x = target.dimensions.x / 2 + released.dimensions.x / 2; + if (relativeDifference.x < 0) { + newRelative.x = -newRelative.x; + } + } else if (abs.y >= abs.x && abs.y >= abs.z) { + newRelative.y = target.dimensions.y / 2 + released.dimensions.y / 2; + if (relativeDifference.y < 0) { + newRelative.y = -newRelative.y; + } + } else if (abs.z >= abs.x && abs.z >= abs.y) { + newRelative.z = target.dimensions.z / 2 + released.dimensions.z / 2; + if (relativeDifference.z < 0) { + newRelative.z = -newRelative.z; + } + } + // Can be expanded upon to work in nearest 90 degree rotation as well, but was not in spec. + var newPosition = Vec3.multiplyQbyV(target.rotation, newRelative); + Entities.editEntity(entityId, { + // Script relies on the registrationPoint being at the very center of the object. Thus override. + registrationPoint: { + x: 0.5, + y: 0.5, + z: 0.5 + }, + rotation: target.rotation, + position: Vec3.sum(target.position, newPosition) + }); + // Script relies on the registrationPoint being at the very center of the object. Thus override. + Entities.editEntity(target.id, { + registrationPoint: { + x: 0.5, + y: 0.5, + z: 0.5 + } + }) + } } } return new MagneticBlock(); From c9c07c4269bdd2a742b0ece1e1647bec1ce30d33 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 09:38:23 -0800 Subject: [PATCH 20/38] Basically rebase and squash --- .../src/avatars/AvatarMixerSlave.cpp | 24 +++++---- interface/src/avatar/AvatarManager.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 48 ++++++++++++----- libraries/avatars/src/AvatarData.h | 3 +- scripts/system/pal.js | 52 +++++++------------ 5 files changed, 71 insertions(+), 58 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 49b4b1ced4..1c386caab7 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -137,14 +137,18 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // keep track of the number of other avatar frames skipped int numAvatarsWithSkippedFrames = 0; - // When this is true, the AvatarMixer will send Avatar data to a client about avatars that are not in the view frustrum - bool getsOutOfView = nodeData->getRequestsDomainListData(); - - // When this is true, the AvatarMixer will send Avatar data to a client about avatars that they've ignored - bool getsIgnoredByMe = getsOutOfView; + // When this is true, the AvatarMixer will send Avatar data to a client + // about avatars they've ignored or that are out of view + bool PALIsOpen = nodeData->getRequestsDomainListData(); // When this is true, the AvatarMixer will send Avatar data to a client about avatars that have ignored them - bool getsAnyIgnored = getsIgnoredByMe && node->getCanKick(); + bool getsAnyIgnored = PALIsOpen && node->getCanKick(); + + // Increase minimumBytesPerAvatar if the PAL is open or we're gettingAnyIgnored + if (PALIsOpen || getsAnyIgnored) { + minimumBytesPerAvatar += sizeof(AvatarDataPacket::AvatarGlobalPosition) + + sizeof(AvatarDataPacket::AudioLoudness); + } // setup a PacketList for the avatarPackets auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData); @@ -222,7 +226,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // or that has ignored the viewing node if (!avatarNode->getLinkedData() || avatarNode->getUUID() == node->getUUID() - || (node->isIgnoringNodeWithID(avatarNode->getUUID()) && !getsIgnoredByMe) + || (node->isIgnoringNodeWithID(avatarNode->getUUID()) && !PALIsOpen) || (avatarNode->isIgnoringNodeWithID(node->getUUID()) && !getsAnyIgnored)) { shouldIgnore = true; } else { @@ -335,9 +339,9 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { if (overBudget) { overBudgetAvatars++; _stats.overBudgetAvatars++; - detail = AvatarData::NoData; - } else if (!isInView && !getsOutOfView) { - detail = AvatarData::NoData; + detail = (PALIsOpen || getsAnyIgnored) ? AvatarData::PALMinimum : AvatarData::NoData; + } else if (!isInView) { + detail = (PALIsOpen || getsAnyIgnored) ? AvatarData::PALMinimum : AvatarData::NoData; nodeData->incrementAvatarOutOfView(); } else { detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7417f73102..94ce444416 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -329,7 +329,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID, KillAvatarReason remo } void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { - AvatarHashMap::handleRemovedAvatar(removedAvatar); + AvatarHashMap::handleRemovedAvatar(removedAvatar, removalReason); // removedAvatar is a shared pointer to an AvatarData but we need to get to the derived Avatar // class in this context so we can call methods that don't exist at the base class. diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8025c680ca..7b33ada89c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -186,6 +186,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent bool cullSmallChanges = (dataDetail == CullSmallData); bool sendAll = (dataDetail == SendAllData); bool sendMinimum = (dataDetail == MinimumData); + bool sendPALMinimum = (dataDetail == PALMinimum); lazyInitHeadData(); @@ -222,24 +223,45 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent auto parentID = getParentID(); bool hasAvatarGlobalPosition = true; // always include global position - bool hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime); - bool hasAvatarBoundingBox = sendAll || avatarBoundingBoxChangedSince(lastSentTime); - bool hasAvatarScale = sendAll || avatarScaleChangedSince(lastSentTime); - bool hasLookAtPosition = sendAll || lookAtPositionChangedSince(lastSentTime); - bool hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime); - bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime); - bool hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime); + bool hasAvatarOrientation = false; + bool hasAvatarBoundingBox = false; + bool hasAvatarScale = false; + bool hasLookAtPosition = false; + bool hasAudioLoudness = false; + bool hasSensorToWorldMatrix = false; + bool hasAdditionalFlags = false; // local position, and parent info only apply to avatars that are parented. The local position // and the parent info can change independently though, so we track their "changed since" // separately - bool hasParentInfo = sendAll || parentInfoChangedSince(lastSentTime); - bool hasAvatarLocalPosition = hasParent() && (sendAll || - tranlationChangedSince(lastSentTime) || - parentInfoChangedSince(lastSentTime)); + bool hasParentInfo = false; + bool hasAvatarLocalPosition = false; - bool hasFaceTrackerInfo = !dropFaceTracking && hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime)); - bool hasJointData = sendAll || !sendMinimum; + bool hasFaceTrackerInfo = false; + bool hasJointData = false; + + if (sendPALMinimum) { + hasAudioLoudness = true; + } else { + hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime); + hasAvatarBoundingBox = sendAll || avatarBoundingBoxChangedSince(lastSentTime); + hasAvatarScale = sendAll || avatarScaleChangedSince(lastSentTime); + hasLookAtPosition = sendAll || lookAtPositionChangedSince(lastSentTime); + hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime); + hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime); + hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime); + + // local position, and parent info only apply to avatars that are parented. The local position + // and the parent info can change independently though, so we track their "changed since" + // separately + hasParentInfo = sendAll || parentInfoChangedSince(lastSentTime); + hasAvatarLocalPosition = hasParent() && (sendAll || + tranlationChangedSince(lastSentTime) || + parentInfoChangedSince(lastSentTime)); + + hasFaceTrackerInfo = !dropFaceTracking && hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime)); + hasJointData = sendAll || !sendMinimum; + } // Leading flags, to indicate how much data is actually included in the packet... AvatarDataPacket::HasFlags packetStateFlags = diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c2240f400f..ac6c2fcbe0 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -379,7 +379,8 @@ public: MinimumData, CullSmallData, IncludeSmallData, - SendAllData + SendAllData, + PALMinimum } AvatarDataDetail; virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 4914cbe34c..f9d0a60f5a 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -526,17 +526,23 @@ var button; var buttonName = "PEOPLE"; var tablet = null; +function onTabletScreenChanged(type, url) { + if (type !== "QML" || url !== "../Pal.qml") { + off(); + } +} + function startup() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/people-i.svg", - activeIcon: "icons/tablet-icons/people-a.svg", sortOrder: 7 }); tablet.fromQml.connect(fromQml); button.clicked.connect(onTabletButtonClicked); tablet.screenChanged.connect(onTabletScreenChanged); + Users.usernameFromIDReply.connect(usernameFromIDReply); Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); @@ -567,39 +573,17 @@ function off() { Users.requestsDomainListData = false; } -var onPalScreen = false; -var shouldActivateButton = false; - function onTabletButtonClicked() { - if (onPalScreen) { - // for toolbar-mode: go back to home screen, this will close the window. - tablet.gotoHomeScreen(); - } else { - shouldActivateButton = true; - tablet.loadQMLSource("../Pal.qml"); - onPalScreen = true; - Users.requestsDomainListData = true; - populateUserList(); - isWired = true; - Script.update.connect(updateOverlays); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); - audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS); - } -} - -function onTabletScreenChanged(type, url) { - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onPalScreen = false; - - // disable sphere overlays when not on pal screen. - if (type !== "QML" || url !== "../Pal.qml") { - off(); - } + tablet.loadQMLSource("../Pal.qml"); + Users.requestsDomainListData = true; + populateUserList(); + isWired = true; + Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS); } // @@ -699,12 +683,14 @@ function shutdown() { button.clicked.disconnect(onTabletButtonClicked); tablet.removeButton(button); tablet.screenChanged.disconnect(onTabletScreenChanged); + Users.usernameFromIDReply.disconnect(usernameFromIDReply); Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); Messages.messageReceived.disconnect(receiveMessage); Users.avatarDisconnected.disconnect(avatarDisconnected); + off(); } From b927472e4e272846c59e8ab0cbc1904a48fa9540 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 11:25:04 -0800 Subject: [PATCH 21/38] Fixup after rebase --- scripts/system/pal.js | 52 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index f9d0a60f5a..4914cbe34c 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -526,23 +526,17 @@ var button; var buttonName = "PEOPLE"; var tablet = null; -function onTabletScreenChanged(type, url) { - if (type !== "QML" || url !== "../Pal.qml") { - off(); - } -} - function startup() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); button = tablet.addButton({ text: buttonName, icon: "icons/tablet-icons/people-i.svg", + activeIcon: "icons/tablet-icons/people-a.svg", sortOrder: 7 }); tablet.fromQml.connect(fromQml); button.clicked.connect(onTabletButtonClicked); tablet.screenChanged.connect(onTabletScreenChanged); - Users.usernameFromIDReply.connect(usernameFromIDReply); Window.domainChanged.connect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.connect(clearLocalQMLDataAndClosePAL); @@ -573,17 +567,39 @@ function off() { Users.requestsDomainListData = false; } +var onPalScreen = false; +var shouldActivateButton = false; + function onTabletButtonClicked() { - tablet.loadQMLSource("../Pal.qml"); - Users.requestsDomainListData = true; - populateUserList(); - isWired = true; - Script.update.connect(updateOverlays); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); - audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS); + if (onPalScreen) { + // for toolbar-mode: go back to home screen, this will close the window. + tablet.gotoHomeScreen(); + } else { + shouldActivateButton = true; + tablet.loadQMLSource("../Pal.qml"); + onPalScreen = true; + Users.requestsDomainListData = true; + populateUserList(); + isWired = true; + Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS); + } +} + +function onTabletScreenChanged(type, url) { + // for toolbar mode: change button to active when window is first openend, false otherwise. + button.editProperties({isActive: shouldActivateButton}); + shouldActivateButton = false; + onPalScreen = false; + + // disable sphere overlays when not on pal screen. + if (type !== "QML" || url !== "../Pal.qml") { + off(); + } } // @@ -683,14 +699,12 @@ function shutdown() { button.clicked.disconnect(onTabletButtonClicked); tablet.removeButton(button); tablet.screenChanged.disconnect(onTabletScreenChanged); - Users.usernameFromIDReply.disconnect(usernameFromIDReply); Window.domainChanged.disconnect(clearLocalQMLDataAndClosePAL); Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL); Messages.subscribe(CHANNEL); Messages.messageReceived.disconnect(receiveMessage); Users.avatarDisconnected.disconnect(avatarDisconnected); - off(); } From 81ce5cffcd6eb53dff514b8a41acca148acb62a0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 11:47:42 -0800 Subject: [PATCH 22/38] Force-send ID packets when PAL is open --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 1c386caab7..e6ca5e49df 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -311,7 +311,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // make sure we send out identity packets to and from new arrivals. - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()); + // Also make sure we send identity packets if the PAL is open. + bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()) || (PALIsOpen || getsAnyIgnored); // FIXME - this clause seems suspicious "... || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp ..." if (!overBudget From 4025601c2bfc8e9510585d7fcdb8ede57a80545e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 14:28:29 -0800 Subject: [PATCH 23/38] Force send ID even when 'overBudget' --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index e6ca5e49df..37406675b9 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -311,15 +311,16 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // make sure we send out identity packets to and from new arrivals. - // Also make sure we send identity packets if the PAL is open. bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()) || (PALIsOpen || getsAnyIgnored); // FIXME - this clause seems suspicious "... || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp ..." - if (!overBudget + if ((!overBudget && otherNodeData->getIdentityChangeTimestamp().time_since_epoch().count() > 0 && (forceSend || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || distribution(generator) < IDENTITY_SEND_PROBABILITY)) { + || distribution(generator) < IDENTITY_SEND_PROBABILITY)) || + // Also make sure we send identity packets if the PAL is open. + (PALIsOpen || getsAnyIgnored)) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } From 9969d422d6d07eeeea29b2c3a925934edfa7dcf4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 15:38:30 -0800 Subject: [PATCH 24/38] Cleanup --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 37406675b9..88b363b73a 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -311,7 +311,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); // make sure we send out identity packets to and from new arrivals. - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()) || (PALIsOpen || getsAnyIgnored); + bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()); // FIXME - this clause seems suspicious "... || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp ..." if ((!overBudget From cfb8534d71dd3b1da32a11e02a3ba1374d0add9c Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 24 Feb 2017 17:00:57 -0800 Subject: [PATCH 25/38] Comment --- libraries/avatars/src/AvatarData.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 7b33ada89c..06df75d451 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -250,10 +250,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime); hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime); hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime); - - // local position, and parent info only apply to avatars that are parented. The local position - // and the parent info can change independently though, so we track their "changed since" - // separately hasParentInfo = sendAll || parentInfoChangedSince(lastSentTime); hasAvatarLocalPosition = hasParent() && (sendAll || tranlationChangedSince(lastSentTime) || From 718ecea404459d9eb779ada40c5b99e1103fc7b2 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 27 Feb 2017 16:10:53 -0800 Subject: [PATCH 26/38] Potential non-spammy solution using pseudo-state --- .../src/avatars/AvatarMixerSlave.cpp | 31 ++++++++++++------- .../src/avatars/AvatarMixerSlave.h | 12 +++++++ libraries/avatars/src/AvatarData.h | 4 +-- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 88b363b73a..15cf89754e 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -80,16 +80,6 @@ int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, static const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45; -// FIXME - There is some old logic (unchanged as of 2/17/17) that randomly decides to send an identity -// packet. That logic had the following comment about the constants it uses... -// -// An 80% chance of sending a identity packet within a 5 second interval. -// assuming 60 htz update rate. -// -// Assuming the calculation of the constant is in fact correct for 80% and 60hz and 5 seconds (an assumption -// that I have not verified) then the constant is definitely wrong now, since we send at 45hz. -const float IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; - void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { quint64 start = usecTimestampNow(); @@ -150,6 +140,23 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { sizeof(AvatarDataPacket::AudioLoudness); } + if (PALIsOpen) { + if (_identitySendProbability == DEFAULT_IDENTITY_SEND_PROBABILITY) + { + // The client has just opened the PAL. Force all identity packets to be sent to + // this client. + _identitySendProbability = 1.0f; + } else { + // The user recently opened the PAL, but we've already gone through the above conditional. + // We want to receive identity updates more often than default when the PAL is open + // to be more confident that the user will see the most up-to-date information in the PAL. + _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY * 2; + } + } else { + // If the PAL is closed, reset the identitySendProbability to the default. + _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY; + } + // setup a PacketList for the avatarPackets auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData); @@ -318,9 +325,9 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { && otherNodeData->getIdentityChangeTimestamp().time_since_epoch().count() > 0 && (forceSend || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || distribution(generator) < IDENTITY_SEND_PROBABILITY)) || + || distribution(generator) < _identitySendProbability)) || // Also make sure we send identity packets if the PAL is open. - (PALIsOpen || getsAnyIgnored)) { + ((PALIsOpen || getsAnyIgnored) && distribution(generator) < _identitySendProbability)) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } diff --git a/assignment-client/src/avatars/AvatarMixerSlave.h b/assignment-client/src/avatars/AvatarMixerSlave.h index 04141d9d72..2fa5fa4484 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.h +++ b/assignment-client/src/avatars/AvatarMixerSlave.h @@ -101,6 +101,18 @@ private: float _maxKbpsPerNode { 0.0f }; float _throttlingRatio { 0.0f }; + + // FIXME - There is some old logic (unchanged as of 2/17/17) that randomly decides to send an identity + // packet. That logic had the following comment about the constants it uses... + // + // An 80% chance of sending a identity packet within a 5 second interval. + // assuming 60 htz update rate. + // + // Assuming the calculation of the constant is in fact correct for 80% and 60hz and 5 seconds (an assumption + // that I have not verified) then the constant is definitely wrong now, since we send at 45hz. + const float DEFAULT_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; + float _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY; + AvatarMixerSlaveStats _stats; }; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ac6c2fcbe0..f0759aedbd 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -376,11 +376,11 @@ public: typedef enum { NoData, + PALMinimum, MinimumData, CullSmallData, IncludeSmallData, - SendAllData, - PALMinimum + SendAllData } AvatarDataDetail; virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail); From 8bdbbd4b25aa2cb8d943cacf3724a4bb13a95224 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Mar 2017 09:07:27 -0800 Subject: [PATCH 27/38] CR feedback 1 --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 15cf89754e..49353fd88f 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -134,15 +134,14 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // When this is true, the AvatarMixer will send Avatar data to a client about avatars that have ignored them bool getsAnyIgnored = PALIsOpen && node->getCanKick(); - // Increase minimumBytesPerAvatar if the PAL is open or we're gettingAnyIgnored - if (PALIsOpen || getsAnyIgnored) { + // Increase minimumBytesPerAvatar if the PAL is open + if (PALIsOpen) { minimumBytesPerAvatar += sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness); } if (PALIsOpen) { - if (_identitySendProbability == DEFAULT_IDENTITY_SEND_PROBABILITY) - { + if (_identitySendProbability == DEFAULT_IDENTITY_SEND_PROBABILITY) { // The client has just opened the PAL. Force all identity packets to be sent to // this client. _identitySendProbability = 1.0f; @@ -327,7 +326,7 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp || distribution(generator) < _identitySendProbability)) || // Also make sure we send identity packets if the PAL is open. - ((PALIsOpen || getsAnyIgnored) && distribution(generator) < _identitySendProbability)) { + (PALIsOpen && distribution(generator) < _identitySendProbability)) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } @@ -348,9 +347,9 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { if (overBudget) { overBudgetAvatars++; _stats.overBudgetAvatars++; - detail = (PALIsOpen || getsAnyIgnored) ? AvatarData::PALMinimum : AvatarData::NoData; + detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; } else if (!isInView) { - detail = (PALIsOpen || getsAnyIgnored) ? AvatarData::PALMinimum : AvatarData::NoData; + detail = PALIsOpen ? AvatarData::PALMinimum : AvatarData::NoData; nodeData->incrementAvatarOutOfView(); } else { detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO From fda87b3a531c95856a949d5df1d9e4032883f20a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Mar 2017 09:09:41 -0800 Subject: [PATCH 28/38] Quick cleanup --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 49353fd88f..47efb39c3c 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -134,13 +134,10 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // When this is true, the AvatarMixer will send Avatar data to a client about avatars that have ignored them bool getsAnyIgnored = PALIsOpen && node->getCanKick(); - // Increase minimumBytesPerAvatar if the PAL is open if (PALIsOpen) { + // Increase minimumBytesPerAvatar if the PAL is open minimumBytesPerAvatar += sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness); - } - - if (PALIsOpen) { if (_identitySendProbability == DEFAULT_IDENTITY_SEND_PROBABILITY) { // The client has just opened the PAL. Force all identity packets to be sent to // this client. From 5fa5e6e0a74eabcfe1ab99ecd216bde4734044fc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Mar 2017 14:27:50 -0800 Subject: [PATCH 29/38] First pass at implementing Brad's simplification ideas --- .../src/avatars/AvatarMixerClientData.cpp | 10 ------- .../src/avatars/AvatarMixerClientData.h | 9 ++---- .../src/avatars/AvatarMixerSlave.cpp | 28 ++----------------- .../src/avatars/AvatarMixerSlave.h | 12 -------- 4 files changed, 6 insertions(+), 53 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 717e14535f..43b8816111 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -65,15 +65,6 @@ int AvatarMixerClientData::parseData(ReceivedMessage& message) { // compute the offset to the data payload return _avatar->parseDataFromBuffer(message.readWithoutCopy(message.getBytesLeftToRead())); } - -bool AvatarMixerClientData::checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid) { - if (_hasReceivedFirstPacketsFrom.find(uuid) == _hasReceivedFirstPacketsFrom.end()) { - _hasReceivedFirstPacketsFrom.insert(uuid); - return false; - } - return true; -} - uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) const { // return the matching PacketSequenceNumber, or the default if we don't have it auto nodeMatch = _lastBroadcastTimes.find(nodeUUID); @@ -103,7 +94,6 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble); } DependencyManager::get()->sendUnreliablePacket(*killPacket, *self); - _hasReceivedFirstPacketsFrom.erase(other->getUUID()); } } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 51b8d692e2..1449005246 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -45,8 +45,6 @@ public: const AvatarData* getConstAvatarData() const { return _avatar.get(); } AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; } - bool checkAndSetHasReceivedFirstPacketsFrom(const QUuid& uuid); - uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const; void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber) { _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; } @@ -63,8 +61,8 @@ public: uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; } - HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } - void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); } + uint64_t getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } + void flagIdentityChange() { _identityChangeTimestamp = usecTimestampNow(); } bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; } void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; } @@ -139,7 +137,6 @@ private: uint16_t _lastReceivedSequenceNumber { 0 }; std::unordered_map _lastBroadcastSequenceNumbers; - std::unordered_set _hasReceivedFirstPacketsFrom; std::unordered_map _lastBroadcastTimes; // this is a map of the last time we encoded an "other" avatar for @@ -147,7 +144,7 @@ private: std::unordered_map _lastOtherAvatarEncodeTime; std::unordered_map> _lastOtherAvatarSentJoints; - HRCTime _identityChangeTimestamp; + uint64_t _identityChangeTimestamp; bool _avatarSessionDisplayNameMustChange{ false }; int _numAvatarsSentLastFrame = 0; diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 47efb39c3c..60dfad7687 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -138,19 +138,6 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { // Increase minimumBytesPerAvatar if the PAL is open minimumBytesPerAvatar += sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness); - if (_identitySendProbability == DEFAULT_IDENTITY_SEND_PROBABILITY) { - // The client has just opened the PAL. Force all identity packets to be sent to - // this client. - _identitySendProbability = 1.0f; - } else { - // The user recently opened the PAL, but we've already gone through the above conditional. - // We want to receive identity updates more often than default when the PAL is open - // to be more confident that the user will see the most up-to-date information in the PAL. - _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY * 2; - } - } else { - // If the PAL is closed, reset the identitySendProbability to the default. - _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY; } // setup a PacketList for the avatarPackets @@ -313,18 +300,9 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { const AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); - // make sure we send out identity packets to and from new arrivals. - bool forceSend = !nodeData->checkAndSetHasReceivedFirstPacketsFrom(otherNode->getUUID()); - - // FIXME - this clause seems suspicious "... || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp ..." - if ((!overBudget - && otherNodeData->getIdentityChangeTimestamp().time_since_epoch().count() > 0 - && (forceSend - || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || distribution(generator) < _identitySendProbability)) || - // Also make sure we send identity packets if the PAL is open. - (PALIsOpen && distribution(generator) < _identitySendProbability)) { - + // If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO + // the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A. + if (nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) { identityBytesSent += sendIdentityPacket(otherNodeData, node); } diff --git a/assignment-client/src/avatars/AvatarMixerSlave.h b/assignment-client/src/avatars/AvatarMixerSlave.h index 2fa5fa4484..04141d9d72 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.h +++ b/assignment-client/src/avatars/AvatarMixerSlave.h @@ -101,18 +101,6 @@ private: float _maxKbpsPerNode { 0.0f }; float _throttlingRatio { 0.0f }; - - // FIXME - There is some old logic (unchanged as of 2/17/17) that randomly decides to send an identity - // packet. That logic had the following comment about the constants it uses... - // - // An 80% chance of sending a identity packet within a 5 second interval. - // assuming 60 htz update rate. - // - // Assuming the calculation of the constant is in fact correct for 80% and 60hz and 5 seconds (an assumption - // that I have not verified) then the constant is definitely wrong now, since we send at 45hz. - const float DEFAULT_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; - float _identitySendProbability = DEFAULT_IDENTITY_SEND_PROBABILITY; - AvatarMixerSlaveStats _stats; }; From 5418a7c2304c2773fb09584070b28e8707db13f3 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 1 Mar 2017 16:54:53 -0800 Subject: [PATCH 30/38] Important addition before rebase --- assignment-client/src/avatars/AvatarMixerClientData.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 43b8816111..0df3edbd11 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -94,6 +94,7 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble); } DependencyManager::get()->sendUnreliablePacket(*killPacket, *self); + setLastBroadcastTime(other->getUUID(), 0); } } From 685bd95105f96b828ce62292b8b83b3291c6e83a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 3 Mar 2017 11:21:55 -0800 Subject: [PATCH 31/38] I think I'm done. Not straightforward! --- assignment-client/src/avatars/AvatarMixer.cpp | 26 ++++++++++++++++++- .../src/avatars/AvatarMixerClientData.cpp | 2 +- .../src/avatars/AvatarMixerSlave.cpp | 3 ++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 0f6863f9ae..1d1a1a57a8 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -409,7 +409,31 @@ void AvatarMixer::handleKillAvatarPacket(QSharedPointer message void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer message, SharedNodePointer senderNode) { auto start = usecTimestampNow(); - senderNode->parseIgnoreRequestMessage(message); + auto nodeList = DependencyManager::get(); + AvatarMixerClientData* nodeData = reinterpret_cast(senderNode->getLinkedData()); + bool addToIgnore; + message->readPrimitive(&addToIgnore); + while (message->getBytesLeftToRead()) { + // parse out the UUID being ignored from the packet + QUuid ignoredUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + // Reset the lastBroadcastTime for the ignored avatar to 0 + // so the AvatarMixer knows it'll have to send identity data about the ignored avatar + // to the ignorer if the ignorer unignores. + nodeData->setLastBroadcastTime(ignoredUUID, 0); + + // Reset the lastBroadcastTime for the ignorer (FROM THE PERSPECTIVE OF THE IGNORED) to 0 + // so the AvatarMixer knows it'll have to send identity data about the ignorer + // to the ignored if the ignorer unignores. + auto ignoredNode = nodeList->nodeWithUUID(ignoredUUID); + AvatarMixerClientData* ignoredNodeData = reinterpret_cast(ignoredNode->getLinkedData()); + ignoredNodeData->setLastBroadcastTime(senderNode->getUUID(), 0); + + if (addToIgnore) { + senderNode->addIgnoredNode(ignoredUUID); + } else { + senderNode->removeIgnoredNode(ignoredUUID); + } + } auto end = usecTimestampNow(); _handleNodeIgnoreRequestPacketElapsedTime += (end - start); } diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 0df3edbd11..15a7f50fa3 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -93,8 +93,8 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe } else { killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble); } - DependencyManager::get()->sendUnreliablePacket(*killPacket, *self); setLastBroadcastTime(other->getUUID(), 0); + DependencyManager::get()->sendUnreliablePacket(*killPacket, *self); } } diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 60dfad7687..05de209e81 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -222,7 +222,8 @@ void AvatarMixerSlave::broadcastAvatarData(const SharedNodePointer& node) { } else { // Check to see if the space bubble is enabled - if (node->isIgnoreRadiusEnabled() || avatarNode->isIgnoreRadiusEnabled()) { + // Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored + if (node->isIgnoreRadiusEnabled() || (avatarNode->isIgnoreRadiusEnabled() && !getsAnyIgnored)) { // Define the scale of the box for the current other node glm::vec3 otherNodeBoxScale = (avatarNodeData->getPosition() - avatarNodeData->getGlobalBoundingBoxCorner()) * 2.0f; From 0000b8fb2159a9b489fa61cd56f6b21ed9fa021e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 3 Mar 2017 17:01:57 -0800 Subject: [PATCH 32/38] OMG I think it's actually fully working --- assignment-client/src/avatars/AvatarMixer.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 1d1a1a57a8..c10a616818 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -365,6 +365,28 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointerreadPrimitive(&isRequesting); nodeData->setRequestsDomainListData(isRequesting); qCDebug(avatars) << "node" << nodeData->getNodeID() << "requestsDomainListData" << isRequesting; + + // If we just opened the PAL... + if (isRequesting) { + // For each node in the NodeList... + auto nodeList = DependencyManager::get(); + nodeList->eachMatchingNode( + // Discover the valid nodes we're ignoring... + [&](const SharedNodePointer& node)->bool { + if (node->getUUID() != senderNode->getUUID() && + (nodeData->isRadiusIgnoring(node->getUUID()) || + senderNode->isIgnoringNodeWithID(node->getUUID()))) { + return true; + } + return false; + }, + // ...For those nodes, reset the lastBroadcastTime to 0 + // so that the AvatarMixer will send Identity data to us + [&](const SharedNodePointer& node) { + nodeData->setLastBroadcastTime(node->getUUID(), 0); + } + ); + } } } auto end = usecTimestampNow(); From d50a0e33a99b6cb0181186f8fae1dd496dd1f3f2 Mon Sep 17 00:00:00 2001 From: Menithal Date: Mon, 6 Mar 2017 21:07:16 +0200 Subject: [PATCH 33/38] CR. Run through Lint ECMAScript 5 standard Meaning all const are out, non-variable definitions are out, etc --- .../tutorials/entity_scripts/magneticBlock.js | 37 +++++++++++-------- scripts/tutorials/makeBlocks.js | 32 ++++++++++------ 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/scripts/tutorials/entity_scripts/magneticBlock.js b/scripts/tutorials/entity_scripts/magneticBlock.js index 911e9c0eb5..7771a3668d 100644 --- a/scripts/tutorials/entity_scripts/magneticBlock.js +++ b/scripts/tutorials/entity_scripts/magneticBlock.js @@ -11,21 +11,23 @@ // Makes the entity the script is bound to connect to nearby, similarly sized entities, like a magnet. (function() { - const SNAPSOUND_SOURCE = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs")); - const RANGE_MULTIPLER = 1.5; - const MAX_SCALE = 2; - const MIN_SCALE = 0.5; + var SNAPSOUND_SOURCE = SoundCache.getSound(Script.resolvePath("../../system/assets/sounds/entitySnap.wav?xrs")); + var RANGE_MULTIPLER = 1.5; + var MAX_SCALE = 2; + var MIN_SCALE = 0.5; // Helper for detecting nearby objects near entityProperties, with the scale calculated by the dimensions of the object. function findEntitiesInRange(entityProperties) { var dimensions = entityProperties.dimensions; - return Entities.findEntities(entityProperties.position, ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); + // Average of the dimensions instead of full value. + return Entities.findEntities(entityProperties.position, + ((dimensions.x + dimensions.y + dimensions.z) / 3) * RANGE_MULTIPLER); } function getNearestValidEntityProperties(releasedProperties) { var entities = findEntitiesInRange(releasedProperties); var nearestEntity = null; - var nearest = 9999999999999; + var nearest = Number.MAX_SAFE_INTEGER; var releaseSize = Vec3.length(releasedProperties.dimensions); entities.forEach(function(entityId) { if (entityId !== releasedProperties.id) { @@ -38,27 +40,30 @@ nearest = distance; } } - }) + }); return nearestEntity; } // Create the 'class' function MagneticBlock() {} // Bind pre-emptive events MagneticBlock.prototype = { - // When script is bound to an entity, preload is the first callback called with the entityID. It will behave as the constructor + /* + When script is bound to an entity, preload is the first callback called with the entityID. + It will behave as the constructor + */ preload: function(id) { /* We will now override any existing userdata with the grabbable property. Only retrieving userData */ - var val = Entities.getEntityProperties(id, ['userData']) + var entity = Entities.getEntityProperties(id, ['userData']); var userData = { grabbableKey: {} }; // Check if existing userData field exists. - if (val.userData && val.userData.length > 0) { + if (entity.userData && entity.userData.length > 0) { try { - userData = JSON.parse(val.userData); + userData = JSON.parse(entity.userData); if (!userData.grabbableKey) { userData.grabbableKey = {}; // If by random change there is no grabbableKey in the userData. } @@ -75,7 +80,7 @@ }); Script.scriptEnding.connect(function() { Script.removeEventHandler(id, "releaseGrab", this.releaseGrab); - }) + }); }, releaseGrab: function(entityId) { // Release grab is called with entityId, @@ -102,7 +107,7 @@ x: 0, y: 0, z: 0 - } + }; if (abs.x >= abs.y && abs.x >= abs.z) { newRelative.x = target.dimensions.x / 2 + released.dimensions.x / 2; if (relativeDifference.x < 0) { @@ -138,9 +143,9 @@ y: 0.5, z: 0.5 } - }) + }); } } - } + }; return new MagneticBlock(); -}) +}); diff --git a/scripts/tutorials/makeBlocks.js b/scripts/tutorials/makeBlocks.js index bb4974498c..54bdead792 100644 --- a/scripts/tutorials/makeBlocks.js +++ b/scripts/tutorials/makeBlocks.js @@ -12,19 +12,20 @@ (function() { - const MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum. - const MIN_COLOR_VALUE = 127; - const SIZE = 0.3; - const LIFETIME = 600; - + var MAX_RGB_COMPONENT_VALUE = 256 / 2; // Limit the values to half the maximum. + var MIN_COLOR_VALUE = 127; + var SIZE = 0.3; + var LIFETIME = 600; + var VERTICAL_OFFSET = -0.25; + var ROWS = 3; + var COLUMNS = 3; // Random Pastel Generator based on Piper's script function newColor() { - color = { + return { red: randomPastelRGBComponent(), green: randomPastelRGBComponent(), blue: randomPastelRGBComponent() }; - return color; } // Helper functions. function randomPastelRGBComponent() { @@ -34,9 +35,9 @@ var SCRIPT_URL = Script.resolvePath("./entity_scripts/magneticBlock.js"); var frontVector = Quat.getFront(MyAvatar.orientation); - frontVector.y -=.25; - for(var x =0; x < 3; x++) { - for (var y = 0; y < 3; y++) { + frontVector.y += VERTICAL_OFFSET; + for (var x = 0; x < COLUMNS; x++) { + for (var y = 0; y < ROWS; y++) { var frontOffset = { x: 0, @@ -46,13 +47,20 @@ Entities.addEntity({ type: "Box", - name: "MagneticBlock-" + y +'-' + x, + name: "MagneticBlock-" + y + '-' + x, dimensions: { x: SIZE, y: SIZE, z: SIZE }, - userData: JSON.stringify({grabbableKey: { cloneable: true, grabbable: true, cloneLifetime : LIFETIME, cloneLimit: 9999}}), + userData: JSON.stringify({ + grabbableKey: { + cloneable: true, + grabbable: true, + cloneLifetime: LIFETIME, + cloneLimit: 9999 + } + }), position: Vec3.sum(MyAvatar.position, Vec3.sum(frontOffset, frontVector)), color: newColor(), script: SCRIPT_URL From 01ba44c572d66be6c86d79390918bda798576ba6 Mon Sep 17 00:00:00 2001 From: Menithal Date: Mon, 6 Mar 2017 21:32:27 +0200 Subject: [PATCH 34/38] Fixed print --- scripts/tutorials/entity_scripts/magneticBlock.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/tutorials/entity_scripts/magneticBlock.js b/scripts/tutorials/entity_scripts/magneticBlock.js index 7771a3668d..1ec5f2a6c6 100644 --- a/scripts/tutorials/entity_scripts/magneticBlock.js +++ b/scripts/tutorials/entity_scripts/magneticBlock.js @@ -27,7 +27,7 @@ function getNearestValidEntityProperties(releasedProperties) { var entities = findEntitiesInRange(releasedProperties); var nearestEntity = null; - var nearest = Number.MAX_SAFE_INTEGER; + var nearest = Number.MAX_VALUE - 1; var releaseSize = Vec3.length(releasedProperties.dimensions); entities.forEach(function(entityId) { if (entityId !== releasedProperties.id) { @@ -56,14 +56,14 @@ We will now override any existing userdata with the grabbable property. Only retrieving userData */ - var entity = Entities.getEntityProperties(id, ['userData']); + var entityProperties = Entities.getEntityProperties(id, ['userData']); var userData = { grabbableKey: {} }; // Check if existing userData field exists. - if (entity.userData && entity.userData.length > 0) { + if (entityProperties.userData && entityProperties.userData.length > 0) { try { - userData = JSON.parse(entity.userData); + userData = JSON.parse(entityProperties.userData); if (!userData.grabbableKey) { userData.grabbableKey = {}; // If by random change there is no grabbableKey in the userData. } From 21f36d72123a292f2045dd96504ea74f80581551 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 6 Mar 2017 12:41:00 -0800 Subject: [PATCH 35/38] removing comments and restoring the correct behavior for Pal.js --- libraries/render-utils/src/MeshPartPayload.h | 1 - scripts/system/pal.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 9d021f4f34..c585c95025 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -119,7 +119,6 @@ public: private: mutable quint64 _fadeStartTime { 0 }; mutable uint8_t _fadeState { FADE_WAITING_TO_START }; - // mutable uint8_t _fadeState { FADE_COMPLETE }; }; namespace render { diff --git a/scripts/system/pal.js b/scripts/system/pal.js index ae9c8265aa..70b2739c96 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -184,8 +184,7 @@ function HighlightedEntity(id, entityProperties) { }, lineWidth: 1.0, ignoreRayIntersection: true, - //drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. - drawInFront: true // Arguable. For now, let's not distract with mysterious wires around the scene. + drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. }); HighlightedEntity.overlays.push(this); } From 51739f2f99bbbe4a1f8a4f9ed6bb538a85fff19e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Mar 2017 15:02:26 +1300 Subject: [PATCH 36/38] Remove Developer > Network > Bandwith Details dialog --- interface/src/Application.cpp | 6 -- interface/src/Application.h | 2 +- interface/src/Menu.cpp | 2 - interface/src/Menu.h | 1 - interface/src/ui/BandwidthDialog.cpp | 135 --------------------------- interface/src/ui/BandwidthDialog.h | 94 ------------------- interface/src/ui/DialogsManager.cpp | 15 --- interface/src/ui/DialogsManager.h | 4 - interface/src/ui/HMDToolsDialog.cpp | 3 - 9 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 interface/src/ui/BandwidthDialog.cpp delete mode 100644 interface/src/ui/BandwidthDialog.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ba63f4f064..f870bd9f83 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4236,12 +4236,6 @@ void Application::updateDialogs(float deltaTime) const { PerformanceWarning warn(showWarnings, "Application::updateDialogs()"); auto dialogsManager = DependencyManager::get(); - // Update bandwidth dialog, if any - BandwidthDialog* bandwidthDialog = dialogsManager->getBandwidthDialog(); - if (bandwidthDialog) { - bandwidthDialog->update(); - } - QPointer octreeStatsDialog = dialogsManager->getOctreeStatsDialog(); if (octreeStatsDialog) { octreeStatsDialog->update(); diff --git a/interface/src/Application.h b/interface/src/Application.h index ec6d9b19f7..c4ba760153 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -51,6 +51,7 @@ #include #include "avatar/MyAvatar.h" +#include "BandwidthRecorder.h" #include "Bookmarks.h" #include "Camera.h" #include "ConnectionMonitor.h" @@ -61,7 +62,6 @@ #include "scripting/ControllerScriptingInterface.h" #include "scripting/DialogsManagerScriptingInterface.h" #include "ui/ApplicationOverlay.h" -#include "ui/BandwidthDialog.h" #include "ui/EntityScriptServerLogDialog.h" #include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c131367aee..beacbaccab 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -566,8 +566,6 @@ Menu::Menu() { dialogsManager.data(), SLOT(toggleDiskCacheEditor())); addActionToQMenuAndActionHash(networkMenu, MenuOption::ShowDSConnectTable, 0, dialogsManager.data(), SLOT(showDomainConnectionDialog())); - addActionToQMenuAndActionHash(networkMenu, MenuOption::BandwidthDetails, 0, - dialogsManager.data(), SLOT(bandwidthDetails())); #if (PR_BUILD || DEV_BUILD) addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::SendWrongProtocolVersion, 0, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 1b2564735b..c806ffa9ee 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -49,7 +49,6 @@ namespace MenuOption { const QString AutoMuteAudio = "Auto Mute Microphone"; const QString AvatarReceiveStats = "Show Receive Stats"; const QString Back = "Back"; - const QString BandwidthDetails = "Bandwidth Details"; const QString BinaryEyelidControl = "Binary Eyelid Control"; const QString BookmarkLocation = "Bookmark Location"; const QString Bookmarks = "Bookmarks"; diff --git a/interface/src/ui/BandwidthDialog.cpp b/interface/src/ui/BandwidthDialog.cpp deleted file mode 100644 index f07c844894..0000000000 --- a/interface/src/ui/BandwidthDialog.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// BandwidthDialog.cpp -// interface/src/ui -// -// Created by Tobias Schwinger on 6/21/13. -// Copyright 2013 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 "BandwidthRecorder.h" -#include "ui/BandwidthDialog.h" - -#include -#include - -#include -#include - - -BandwidthChannelDisplay::BandwidthChannelDisplay(QVector nodeTypesToFollow, - QFormLayout* form, - char const* const caption, char const* unitCaption, - const float unitScale, unsigned colorRGBA) : - _nodeTypesToFollow(nodeTypesToFollow), - _caption(caption), - _unitCaption(unitCaption), - _unitScale(unitScale), - _colorRGBA(colorRGBA) -{ - _label = new QLabel(); - _label->setAlignment(Qt::AlignRight); - - QPalette palette = _label->palette(); - unsigned rgb = colorRGBA >> 8; - rgb = ((rgb & 0xfefefeu) >> 1) + ((rgb & 0xf8f8f8) >> 3); - palette.setColor(QPalette::WindowText, QColor::fromRgb(rgb)); - _label->setPalette(palette); - - form->addRow(QString(" ") + _caption + " Bandwidth In/Out:", _label); -} - - - -void BandwidthChannelDisplay::bandwidthAverageUpdated() { - float inTotal = 0.; - float outTotal = 0.; - - QSharedPointer bandwidthRecorder = DependencyManager::get(); - - for (int i = 0; i < _nodeTypesToFollow.size(); ++i) { - inTotal += bandwidthRecorder->getAverageInputKilobitsPerSecond(_nodeTypesToFollow.at(i)); - outTotal += bandwidthRecorder->getAverageOutputKilobitsPerSecond(_nodeTypesToFollow.at(i)); - } - - _strBuf = - QString("").setNum((int) (inTotal * _unitScale)) + "/" + - QString("").setNum((int) (outTotal * _unitScale)) + " " + _unitCaption; -} - - -void BandwidthChannelDisplay::paint() { - _label->setText(_strBuf); -} - - -BandwidthDialog::BandwidthDialog(QWidget* parent) : - QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) { - - this->setWindowTitle("Bandwidth Details"); - - // Create layout - QFormLayout* form = new QFormLayout(); - form->setSizeConstraint(QLayout::SetFixedSize); - this->QDialog::setLayout(form); - - QSharedPointer bandwidthRecorder = DependencyManager::get(); - - _allChannelDisplays[0] = _audioChannelDisplay = - new BandwidthChannelDisplay({NodeType::AudioMixer}, form, "Audio", "Kbps", 1.0, COLOR0); - _allChannelDisplays[1] = _avatarsChannelDisplay = - new BandwidthChannelDisplay({NodeType::Agent, NodeType::AvatarMixer}, form, "Avatars", "Kbps", 1.0, COLOR1); - _allChannelDisplays[2] = _octreeChannelDisplay = - new BandwidthChannelDisplay({NodeType::EntityServer}, form, "Octree", "Kbps", 1.0, COLOR2); - _allChannelDisplays[3] = _octreeChannelDisplay = - new BandwidthChannelDisplay({NodeType::DomainServer}, form, "Domain", "Kbps", 1.0, COLOR2); - _allChannelDisplays[4] = _otherChannelDisplay = - new BandwidthChannelDisplay({NodeType::Unassigned}, form, "Other", "Kbps", 1.0, COLOR2); - _allChannelDisplays[5] = _totalChannelDisplay = - new BandwidthChannelDisplay({ - NodeType::DomainServer, NodeType::EntityServer, - NodeType::AudioMixer, NodeType::Agent, - NodeType::AvatarMixer, NodeType::Unassigned - }, form, "Total", "Kbps", 1.0, COLOR2); - - connect(averageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateTimerTimeout())); - averageUpdateTimer->start(1000); -} - - -BandwidthDialog::~BandwidthDialog() { - for (unsigned int i = 0; i < _CHANNELCOUNT; i++) { - delete _allChannelDisplays[i]; - } -} - - -void BandwidthDialog::updateTimerTimeout() { - for (unsigned int i = 0; i < _CHANNELCOUNT; i++) { - _allChannelDisplays[i]->bandwidthAverageUpdated(); - } -} - - -void BandwidthDialog::paintEvent(QPaintEvent* event) { - for (unsigned int i=0; i<_CHANNELCOUNT; i++) - _allChannelDisplays[i]->paint(); - this->QDialog::paintEvent(event); -} - -void BandwidthDialog::reject() { - - // Just regularly close upon ESC - this->QDialog::close(); -} - -void BandwidthDialog::closeEvent(QCloseEvent* event) { - - this->QDialog::closeEvent(event); - emit closed(); -} - diff --git a/interface/src/ui/BandwidthDialog.h b/interface/src/ui/BandwidthDialog.h deleted file mode 100644 index a53cc21030..0000000000 --- a/interface/src/ui/BandwidthDialog.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// BandwidthDialog.h -// interface/src/ui -// -// Created by Tobias Schwinger on 6/21/13. -// Copyright 2013 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_BandwidthDialog_h -#define hifi_BandwidthDialog_h - -#include -#include -#include -#include -#include - -#include "Node.h" -#include "BandwidthRecorder.h" - - -const unsigned int COLOR0 = 0x33cc99ff; -const unsigned int COLOR1 = 0xffef40c0; -const unsigned int COLOR2 = 0xd0d0d0a0; - - -class BandwidthChannelDisplay : public QObject { - Q_OBJECT - - public: - BandwidthChannelDisplay(QVector nodeTypesToFollow, - QFormLayout* form, - char const* const caption, char const* unitCaption, float unitScale, unsigned colorRGBA); - void paint(); - - private: - QVector _nodeTypesToFollow; - QLabel* _label; - QString _strBuf; - char const* const _caption; - char const* _unitCaption; - float const _unitScale; - unsigned _colorRGBA; - - - public slots: - void bandwidthAverageUpdated(); -}; - - -class BandwidthDialog : public QDialog { - Q_OBJECT -public: - BandwidthDialog(QWidget* parent); - ~BandwidthDialog(); - - void paintEvent(QPaintEvent*) override; - -private: - BandwidthChannelDisplay* _audioChannelDisplay; - BandwidthChannelDisplay* _avatarsChannelDisplay; - BandwidthChannelDisplay* _octreeChannelDisplay; - BandwidthChannelDisplay* _domainChannelDisplay; - BandwidthChannelDisplay* _otherChannelDisplay; - BandwidthChannelDisplay* _totalChannelDisplay; // sums of all the other channels - - static const unsigned int _CHANNELCOUNT = 6; - BandwidthChannelDisplay* _allChannelDisplays[_CHANNELCOUNT]; - - -signals: - - void closed(); - -public slots: - - void reject() override; - void updateTimerTimeout(); - - -protected: - - // Emits a 'closed' signal when this dialog is closed. - void closeEvent(QCloseEvent*) override; - -private: - QTimer* averageUpdateTimer = new QTimer(this); - -}; - -#endif // hifi_BandwidthDialog_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 03c71d8573..3252fef4f0 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -19,7 +19,6 @@ #include #include "AddressBarDialog.h" -#include "BandwidthDialog.h" #include "CachesSizeDialog.h" #include "ConnectionFailureDialog.h" #include "DiskCacheEditor.h" @@ -108,20 +107,6 @@ void DialogsManager::cachesSizeDialog() { _cachesSizeDialog->raise(); } -void DialogsManager::bandwidthDetails() { - if (! _bandwidthDialog) { - _bandwidthDialog = new BandwidthDialog(qApp->getWindow()); - connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater())); - - if (_hmdToolsDialog) { - _hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle()); - } - - _bandwidthDialog->show(); - } - _bandwidthDialog->raise(); -} - void DialogsManager::lodTools() { if (!_lodToolsDialog) { maybeCreateDialog(_lodToolsDialog); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index c02c1fc2c3..54aef38984 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -21,7 +21,6 @@ class AnimationsDialog; class AttachmentsDialog; -class BandwidthDialog; class CachesSizeDialog; class DiskCacheEditor; class LodToolsDialog; @@ -36,7 +35,6 @@ class DialogsManager : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - QPointer getBandwidthDialog() const { return _bandwidthDialog; } QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } @@ -53,7 +51,6 @@ public slots: void showLoginDialog(); void octreeStatsDetails(); void cachesSizeDialog(); - void bandwidthDetails(); void lodTools(); void hmdTools(bool showTools); void showScriptEditor(); @@ -79,7 +76,6 @@ private: QPointer _animationsDialog; QPointer _attachmentsDialog; - QPointer _bandwidthDialog; QPointer _cachesSizeDialog; QPointer _diskCacheEditor; QPointer _ircInfoBox; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index a596403948..55c321723e 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -79,9 +79,6 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) : // what screens we're allowed on watchWindow(windowHandle()); auto dialogsManager = DependencyManager::get(); - if (dialogsManager->getBandwidthDialog()) { - watchWindow(dialogsManager->getBandwidthDialog()->windowHandle()); - } if (dialogsManager->getOctreeStatsDialog()) { watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle()); } From ff9d6d657cc64907c3695591a8bb5e97b9ee14b6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 6 Mar 2017 19:35:00 -0800 Subject: [PATCH 37/38] Remove weighted offset, special case downward pressure --- .../animation/src/AnimInverseKinematics.cpp | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 173af3fdf6..fa8e4654f6 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -488,13 +488,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars // measure new _hipsOffset for next frame // by looking for discrepancies between where a targeted endEffector is // and where it wants to be (after IK solutions are done) - - // use weighted average between HMD and other targets - float HMD_WEIGHT = 10.0f; - float OTHER_WEIGHT = 1.0f; - float totalWeight = 0.0f; - - glm::vec3 additionalHipsOffset = Vectors::ZERO; + glm::vec3 newHipsOffset = Vectors::ZERO; for (auto& target: targets) { int targetIndex = target.getIndex(); if (targetIndex == _headIndex && _headIndex != -1) { @@ -505,42 +499,34 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars glm::vec3 under = _skeleton->getAbsolutePose(_headIndex, underPoses).trans(); glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans(); const float HEAD_OFFSET_SLAVE_FACTOR = 0.65f; - additionalHipsOffset += (OTHER_WEIGHT * HEAD_OFFSET_SLAVE_FACTOR) * (under- actual); - totalWeight += OTHER_WEIGHT; + newHipsOffset += HEAD_OFFSET_SLAVE_FACTOR * (actual - under); } else if (target.getType() == IKTarget::Type::HmdHead) { + // we want to shift the hips to bring the head to its designated position glm::vec3 actual = _skeleton->getAbsolutePose(_headIndex, _relativePoses).trans(); - glm::vec3 thisOffset = target.getTranslation() - actual; - glm::vec3 futureHipsOffset = _hipsOffset + thisOffset; - if (glm::length(glm::vec2(futureHipsOffset.x, futureHipsOffset.z)) < _maxHipsOffsetLength) { - // it is imperative to shift the hips and bring the head to its designated position - // so we slam newHipsOffset here and ignore all other targets - additionalHipsOffset = futureHipsOffset - _hipsOffset; - totalWeight = 0.0f; - break; - } else { - additionalHipsOffset += HMD_WEIGHT * (target.getTranslation() - actual); - totalWeight += HMD_WEIGHT; - } + _hipsOffset += target.getTranslation() - actual; + // and ignore all other targets + newHipsOffset = _hipsOffset; + break; + } else if (target.getType() == IKTarget::Type::RotationAndPosition) { + glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans(); + glm::vec3 targetPosition = target.getTranslation(); + newHipsOffset += targetPosition - actualPosition; + + // Add downward pressure on the hips + newHipsOffset *= 0.95f; + newHipsOffset -= 1.0f; } } else if (target.getType() == IKTarget::Type::RotationAndPosition) { glm::vec3 actualPosition = _skeleton->getAbsolutePose(targetIndex, _relativePoses).trans(); glm::vec3 targetPosition = target.getTranslation(); - additionalHipsOffset += OTHER_WEIGHT * (targetPosition - actualPosition); - totalWeight += OTHER_WEIGHT; + newHipsOffset += targetPosition - actualPosition; } } - if (totalWeight > 1.0f) { - additionalHipsOffset /= totalWeight; - } - - // Add downward pressure on the hips - additionalHipsOffset *= 0.95f; - additionalHipsOffset -= 1.0f; // smooth transitions by relaxing _hipsOffset toward the new value const float HIPS_OFFSET_SLAVE_TIMESCALE = 0.10f; float tau = dt < HIPS_OFFSET_SLAVE_TIMESCALE ? dt / HIPS_OFFSET_SLAVE_TIMESCALE : 1.0f; - _hipsOffset += additionalHipsOffset * tau; + _hipsOffset += (newHipsOffset - _hipsOffset) * tau; // clamp the hips offset float hipsOffsetLength = glm::length(_hipsOffset); From 2d2b2094fd7d79c9c636de3f9fcd765774f400a3 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 7 Mar 2017 10:11:09 +0100 Subject: [PATCH 38/38] Adding ability for QML/JS file to be visible in QtCreator. Also changed files will be installed to destination --- CMakeLists.txt | 11 +++++++++++ interface/CMakeLists.txt | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ab7e55343..0703866ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,17 @@ foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS}) include(${CUSTOM_MACRO}) endforeach() +file(GLOB_RECURSE JS_SRC scripts/*.js) +add_custom_target(js SOURCES ${JS_SRC}) + +if (UNIX) + install( + DIRECTORY "${CMAKE_SOURCE_DIR}/scripts" + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/interface + COMPONENT ${CLIENT_COMPONENT} + ) +endif() + if (ANDROID) file(GLOB ANDROID_CUSTOM_MACROS "cmake/android/*.cmake") foreach(CUSTOM_MACRO ${ANDROID_CUSTOM_MACROS}) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 868a2cf933..dbc484d0b9 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -63,6 +63,17 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") # add them to the interface source files set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") +file(GLOB_RECURSE QML_SRC resources/qml/*.qml resources/qml/*.js) +add_custom_target(qml SOURCES ${QML_SRC}) + +if (UNIX) + install( + DIRECTORY "${CMAKE_SOURCE_DIR}/interface/resources/qml" + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/resources + COMPONENT ${CLIENT_COMPONENT} + ) +endif() + # translation disabled until we strip out the line numbers # set(QM ${TARGET_NAME}_en.qm) # set(TS ${TARGET_NAME}_en.ts)