From d7791982acafd444b09927419fc685da4e472f35 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Mon, 29 Jun 2015 15:19:50 -0700 Subject: [PATCH 01/39] Starting stats branch --- libraries/render/src/render/Stats.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 libraries/render/src/render/Stats.h diff --git a/libraries/render/src/render/Stats.h b/libraries/render/src/render/Stats.h new file mode 100644 index 0000000000..5291581d7e --- /dev/null +++ b/libraries/render/src/render/Stats.h @@ -0,0 +1,29 @@ +// +// Stats.h +// render/src/render +// +// Created by Niraj Venkat on 6/29/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 +// + +#ifndef hifi_render_Stats_h +#define hifi_render_Stats_h + +#include "DrawTask.h" +#include "gpu/Batch.h" +#include + + +namespace render { + class DrawStats { + public: + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); + + typedef Job::ModelI JobModel; + }; +} + +#endif // hifi_render_Stats_h From 20cb519c14ff85a9e7e3a54a794c42f6e0bc2f3e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 30 Jun 2015 08:19:00 -0700 Subject: [PATCH 02/39] first draft at using the status of the item for representing stats and current data about it in the DrawStatus phase --- libraries/gpu/src/gpu/Config.slh | 3 +- .../render-utils/src/RenderDeferredTask.cpp | 4 + libraries/render/src/render/DrawStatus.cpp | 101 ++++++++++++++++++ libraries/render/src/render/DrawStatus.h | 34 ++++++ libraries/render/src/render/DrawTask.cpp | 7 +- libraries/render/src/render/Scene.h | 21 +++- .../render/src/render/drawItemBounds.slf | 19 ++++ .../render/src/render/drawItemBounds.slv | 43 ++++++++ 8 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 libraries/render/src/render/DrawStatus.cpp create mode 100644 libraries/render/src/render/DrawStatus.h create mode 100644 libraries/render/src/render/drawItemBounds.slf create mode 100644 libraries/render/src/render/drawItemBounds.slv diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 28f447a696..a16ee372ae 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -18,7 +18,8 @@ <@elif GLPROFILE == MAC_GL @> <@def GPU_FEATURE_PROFILE GPU_LEGACY@> <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> - <@def VERSION_HEADER #version 120@> + <@def VERSION_HEADER #version 120 +#extension GL_EXT_gpu_shader4 : enable@> <@else@> <@def GPU_FEATURE_PROFILE GPU_LEGACY@> <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e0c66eb604..db2b657126 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -17,6 +17,8 @@ #include "RenderArgs.h" #include "TextureCache.h" +#include "render/DrawStatus.h" + #include #include "overlay3D_vert.h" @@ -49,6 +51,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { ))); _jobs.push_back(Job(new CullItems::JobModel("CullOpaque", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); + auto& renderedOpaques = _jobs.back().getOutput(); _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput()))); _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); _jobs.push_back(Job(new ResetGLState::JobModel())); @@ -65,6 +68,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new CullItems::JobModel("CullTransparent", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); + _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques))); _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); _jobs.push_back(Job(new ResetGLState::JobModel())); } diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp new file mode 100644 index 0000000000..eaf39b6893 --- /dev/null +++ b/libraries/render/src/render/DrawStatus.cpp @@ -0,0 +1,101 @@ +// +// DrawStatus.cpp +// render/src/render +// +// Created by Niraj Venkat on 5/21/15. +// Copyright 20154 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include + +#include "DrawStatus.h" + +#include +#include "gpu/GPULogging.h" + + +#include "gpu/Batch.h" +#include "gpu/Context.h" + +#include "ViewFrustum.h" +#include "RenderArgs.h" + +#include "drawItemBounds_vert.h" +#include "drawItemBounds_frag.h" + +using namespace render; + + + +const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { + if (!_drawItemBoundsPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Good to go add the brand new pipeline + _drawItemBoundsPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _drawItemBoundsPipeline; +} + +void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + + gpu::Batch batch; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + + // batch.setModelTransform(Transform()); + // bind the unit cube geometry + + // bind the one gpu::Pipeline we need + batch.setPipeline(getDrawItemBoundsPipeline()); + + for (auto& item : inItems) { + if (!item.bounds.isInvalid()) { + Transform model; + model.setTranslation(item.bounds.getCorner()); + if (!item.bounds.isNull()) { + model.setScale(item.bounds.getDimensions()); + } + + batch.setModelTransform(model); + batch.draw(gpu::LINE_STRIP, 13, 0); + } + } + + // Before rendering the batch make sure we re in sync with gl state + args->_context->syncCache(); + renderContext->args->_context->syncCache(); + args->_context->render((batch)); + args->_batch = nullptr; + +} \ No newline at end of file diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h new file mode 100644 index 0000000000..a1e962ebec --- /dev/null +++ b/libraries/render/src/render/DrawStatus.h @@ -0,0 +1,34 @@ +// +// DrawStatus.h +// render/src/render +// +// Created by Niraj Venkat on 6/29/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 +// + +#ifndef hifi_render_DrawStatus_h +#define hifi_render_DrawStatus_h + +#include "DrawTask.h" +#include "gpu/Batch.h" +#include + + +namespace render { + class DrawStatus { + gpu::PipelinePointer _drawItemBoundsPipeline; + + public: + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); + + typedef Job::ModelI JobModel; + + const gpu::PipelinePointer& getDrawItemBoundsPipeline(); + }; +} + +#endif // hifi_render_DrawStatus_h diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 6076ec0006..70eeb00a3d 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -128,9 +128,10 @@ struct ItemBound { float _nearDepth = 0.0f; float _farDepth = 0.0f; ItemID _id = 0; + AABox _bounds; ItemBound() {} - ItemBound(float centerDepth, float nearDepth, float farDepth, ItemID id) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id) {} + ItemBound(float centerDepth, float nearDepth, float farDepth, ItemID id, const AABox& bounds) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id), _bounds(bounds) {} }; struct FrontToBackSort { @@ -167,7 +168,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende auto bound = itemDetails.bounds; // item.getBound(); float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); - itemBounds.emplace_back(ItemBound(distance, distance, distance, itemDetails.id)); + itemBounds.emplace_back(ItemBound(distance, distance, distance, itemDetails.id, bound)); } // sort against Z @@ -181,7 +182,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende // FInally once sorted result to a list of itemID for (auto& itemBound : itemBounds) { - outItems.emplace_back(itemBound._id); + outItems.emplace_back(ItemIDAndBounds(itemBound._id, itemBound._bounds)); } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 5ec9f0c951..444b45800a 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -196,12 +196,19 @@ public: // Bound is the AABBox fully containing this item typedef AABox Bound; - // Stats records the life history and performances of this item while performing at rendering and updating. + // Status records the life history and performances of this item while performing at rendering and updating. // This is Used for monitoring and dynamically adjust the quality - class Stats { + class Status { public: + typedef glm::ivec2 Value; + typedef std::function Getter; + int _firstFrame; + std::vector _values; + + void addGetter(Getter& getter) { _values.push_back(getter); } }; + typedef std::shared_ptr StatusPointer; // Update Functor class UpdateFunctorInterface { @@ -222,7 +229,14 @@ public: virtual const model::MaterialKey getMaterialKey() const = 0; ~PayloadInterface() {} + + // Status interface is local to the base class + const StatusPointer& getStatus() const { return _status; } + void addStatusGetter(Status::Getter& getter) { _status->addGetter(getter); } + protected: + StatusPointer _status; + friend class Item; virtual void update(const UpdateFunctorPointer& functor) = 0; }; @@ -253,6 +267,9 @@ public: // Shape Type Interface const model::MaterialKey getMaterialKey() const { return _payload->getMaterialKey(); } + // Access the status + const StatusPointer& getStatus() const { return _payload->getStatus(); } + protected: PayloadPointer _payload; ItemKey _key; diff --git a/libraries/render/src/render/drawItemBounds.slf b/libraries/render/src/render/drawItemBounds.slf new file mode 100644 index 0000000000..b5d1a297bf --- /dev/null +++ b/libraries/render/src/render/drawItemBounds.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// drawItemBounds.frag +// fragment shader +// +// Created by Sam Gateau on 6/29/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 +// + +varying vec4 varColor; + + +void main(void) { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv new file mode 100644 index 0000000000..e1193a9874 --- /dev/null +++ b/libraries/render/src/render/drawItemBounds.slv @@ -0,0 +1,43 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemBounds.slv +// vertex shader +// +// Created by Sam Gateau on 6/29/2015. +// 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +void main(void) { + const vec4 UNIT_BOX[13] = vec4[13]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 1.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(0.0, 1.0, 1.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(0.0, 0.0, 0.0, 1.0) + ); + vec4 pos = UNIT_BOX[gl_VertexID]; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + // varTexcoord = (pos.xy + 1) * 0.5; +} \ No newline at end of file From 8bd5e15f739adc890ec2c8c75bdb1027a2cc7170 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 30 Jun 2015 14:43:57 -0700 Subject: [PATCH 03/39] Exposing the viewport to the shader and have a first draft of the draw status pipeline --- libraries/gpu/src/gpu/Batch.cpp | 6 ++ libraries/gpu/src/gpu/Batch.h | 2 + libraries/gpu/src/gpu/Format.h | 1 + libraries/gpu/src/gpu/GLBackend.cpp | 1 + libraries/gpu/src/gpu/GLBackend.h | 10 ++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 14 ++++ libraries/gpu/src/gpu/GLBackendShader.cpp | 10 +++ libraries/gpu/src/gpu/GLBackendTransform.cpp | 21 +++++- libraries/gpu/src/gpu/Transform.slh | 8 +++ libraries/render/src/render/DrawStatus.cpp | 41 ++++++++++++ libraries/render/src/render/DrawStatus.h | 4 +- .../render/src/render/drawItemStatus.slf | 19 ++++++ .../render/src/render/drawItemStatus.slv | 66 +++++++++++++++++++ 13 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 libraries/render/src/render/drawItemStatus.slf create mode 100644 libraries/render/src/render/drawItemStatus.slv diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index bff99e7ec3..ee028e79e6 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -159,6 +159,12 @@ void Batch::setProjectionTransform(const Mat4& proj) { _params.push_back(cacheData(sizeof(Mat4), &proj)); } +void Batch::setViewportTransform(const Vec4i& viewport) { + ADD_COMMAND(setViewportTransform); + + _params.push_back(cacheData(sizeof(Vec4i), &viewport)); +} + void Batch::setPipeline(const PipelinePointer& pipeline) { ADD_COMMAND(setPipeline); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 9c97db65ef..599a748d9b 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -105,6 +105,7 @@ public: void setModelTransform(const Transform& model); void setViewTransform(const Transform& view); void setProjectionTransform(const Mat4& proj); + void setViewportTransform(const Vec4i& viewport); // Viewport is xy = low left corner in the framebuffer, zw = width height of the viewport // Pipeline Stage void setPipeline(const PipelinePointer& pipeline); @@ -177,6 +178,7 @@ public: COMMAND_setModelTransform, COMMAND_setViewTransform, COMMAND_setProjectionTransform, + COMMAND_setViewportTransform, COMMAND_setPipeline, COMMAND_setStateBlendFactor, diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 7cf913430d..ac71cc7940 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -38,6 +38,7 @@ typedef uint32 Offset; typedef glm::mat4 Mat4; typedef glm::mat3 Mat3; typedef glm::vec4 Vec4; +typedef glm::ivec4 Vec4i; typedef glm::vec3 Vec3; typedef glm::vec2 Vec2; typedef glm::ivec2 Vec2i; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 9004c4a8fe..112e34eaea 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -29,6 +29,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setModelTransform), (&::gpu::GLBackend::do_setViewTransform), (&::gpu::GLBackend::do_setProjectionTransform), + (&::gpu::GLBackend::do_setViewportTransform), (&::gpu::GLBackend::do_setPipeline), (&::gpu::GLBackend::do_setStateBlendFactor), diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 28236c68c9..0ee0f8d349 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -96,7 +96,9 @@ public: #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else + GLuint _transformObject_model = -1; GLuint _transformCamera_viewInverse = -1; + GLuint _transformCamera_viewport = -1; #endif GLShader(); @@ -267,7 +269,8 @@ protected: void do_setModelTransform(Batch& batch, uint32 paramOffset); void do_setViewTransform(Batch& batch, uint32 paramOffset); void do_setProjectionTransform(Batch& batch, uint32 paramOffset); - + void do_setViewportTransform(Batch& batch, uint32 paramOffset); + void initTransform(); void killTransform(); // Synchronize the state cache of this Backend with the actual real state of the GL Context @@ -281,9 +284,11 @@ protected: Transform _model; Transform _view; Mat4 _projection; + Vec4i _viewport; bool _invalidModel; bool _invalidView; bool _invalidProj; + bool _invalidViewport; GLenum _lastMode; @@ -296,6 +301,7 @@ protected: _invalidModel(true), _invalidView(true), _invalidProj(false), + _invalidViewport(false), _lastMode(GL_TEXTURE) {} } _transform; @@ -329,7 +335,9 @@ protected: #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else + GLint _program_transformObject_model = -1; GLint _program_transformCamera_viewInverse = -1; + GLint _program_transformCamera_viewport = -1; #endif State::Data _stateCache; diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index f4449e9ea1..e4dd90cac0 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -73,7 +73,9 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else + _pipeline._program_transformObject_model = -1; _pipeline._program_transformCamera_viewInverse = -1; + _pipeline._program_transformCamera_viewport = -1; #endif _pipeline._state = nullptr; @@ -91,7 +93,9 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else + _pipeline._program_transformObject_model = pipelineObject->_program->_transformObject_model; _pipeline._program_transformCamera_viewInverse = pipelineObject->_program->_transformCamera_viewInverse; + _pipeline._program_transformCamera_viewport = pipelineObject->_program->_transformCamera_viewport; #endif } @@ -143,10 +147,20 @@ void GLBackend::updatePipeline() { #if (GPU_TRANSFORM_PROFILE == GPU_CORE) #else + // If shader program needs the model we need to provide it + if (_pipeline._program_transformObject_model >= 0) { + glUniformMatrix4fv(_pipeline._program_transformObject_model, 1, false, (const GLfloat*) &_transform._transformObject._model); + } + // If shader program needs the inverseView we need to provide it if (_pipeline._program_transformCamera_viewInverse >= 0) { glUniformMatrix4fv(_pipeline._program_transformCamera_viewInverse, 1, false, (const GLfloat*) &_transform._transformCamera._viewInverse); } + + // If shader program needs the viewport we need to provide it + if (_pipeline._program_transformCamera_viewport >= 0) { + glUniform4fv(_pipeline._program_transformCamera_viewport, 1, (const GLfloat*) &_transform._transformCamera._viewport); + } #endif } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 45adbcdb3c..ec02c1333b 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -111,10 +111,20 @@ void makeBindings(GLBackend::GLShader* shader) { shader->_transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT; } #else + loc = glGetUniformLocation(glprogram, "transformObject_model"); + if (loc >= 0) { + shader->_transformObject_model = loc; + } + loc = glGetUniformLocation(glprogram, "transformCamera_viewInverse"); if (loc >= 0) { shader->_transformCamera_viewInverse = loc; } + + loc = glGetUniformLocation(glprogram, "transformCamera_viewport"); + if (loc >= 0) { + shader->_transformCamera_viewport = loc; + } #endif } diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 2e3c2dca70..21a2d57271 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -31,6 +31,12 @@ void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { _transform._invalidProj = true; } +void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) { + memcpy(&_transform._viewport, batch.editData(batch._params[paramOffset]._uint), sizeof(Vec4i)); + _transform._invalidViewport = true; +} + + void GLBackend::initTransform() { #if (GPU_TRANSFORM_PROFILE == GPU_CORE) glGenBuffers(1, &_transform._transformObjectBuffer); @@ -57,10 +63,13 @@ void GLBackend::killTransform() { } void GLBackend::syncTransformStateCache() { + _transform._invalidViewport = true; _transform._invalidProj = true; _transform._invalidView = true; _transform._invalidModel = true; + glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport); + GLint currentMode; glGetIntegerv(GL_MATRIX_MODE, ¤tMode); _transform._lastMode = currentMode; @@ -78,6 +87,13 @@ void GLBackend::updateTransform() { GLint originalMatrixMode; glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode); // Check all the dirty flags and update the state accordingly + if (_transform._invalidViewport) { + _transform._transformCamera._viewport = glm::vec4(_transform._viewport); + + // Where we assign the GL viewport + glViewport(_transform._viewport.x, _transform._viewport.y, _transform._viewport.z, _transform._viewport.w); + } + if (_transform._invalidProj) { _transform._transformCamera._projection = _transform._projection; _transform._transformCamera._projectionInverse = glm::inverse(_transform._projection); @@ -100,7 +116,7 @@ void GLBackend::updateTransform() { } #if (GPU_TRANSFORM_PROFILE == GPU_CORE) - if (_transform._invalidView || _transform._invalidProj) { + if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) { glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); @@ -162,7 +178,8 @@ void GLBackend::updateTransform() { #endif // Flags are clean - _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; + _transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false; + glMatrixMode(originalMatrixMode); } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index d01fe128ae..274032a642 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -87,10 +87,18 @@ TransformCamera getTransformCamera() { } uniform mat4 transformCamera_viewInverse; +uniform vec4 transformCamera_viewport; <@endif@> <@endfunc@> +<@func transformCameraViewport(cameraTransform, viewport)@> +<@if GPU_TRANSFORM_PROFILE == GPU_CORE@> + <$viewport$> = <$cameraTransform$>._viewport; +<@else@> + <$viewport$> = transformCamera_viewport; +<@endif@> +<@endfunc@> <@func transformModelToClipPos(cameraTransform, objectTransform, modelPos, clipPos)@> <@if GPU_TRANSFORM_PROFILE == GPU_CORE@> diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index eaf39b6893..afe9aa3798 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -26,6 +26,8 @@ #include "drawItemBounds_vert.h" #include "drawItemBounds_frag.h" +#include "drawItemStatus_vert.h" +#include "drawItemStatus_frag.h" using namespace render; @@ -55,6 +57,30 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { return _drawItemBoundsPipeline; } +const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() { + if (!_drawItemStatusPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Good to go add the brand new pipeline + _drawItemStatusPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _drawItemStatusPipeline; +} + void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); @@ -92,6 +118,21 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex } } + batch.setPipeline(getDrawItemStatusPipeline()); + + for (auto& item : inItems) { + if (!item.bounds.isInvalid()) { + Transform model; + model.setTranslation(item.bounds.getCorner()); + if (!item.bounds.isNull()) { + model.setScale(item.bounds.getDimensions()); + } + + batch.setModelTransform(model); + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); + } + } + // Before rendering the batch make sure we re in sync with gl state args->_context->syncCache(); renderContext->args->_context->syncCache(); diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index a1e962ebec..079f223ff5 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -14,12 +14,11 @@ #include "DrawTask.h" #include "gpu/Batch.h" -#include - namespace render { class DrawStatus { gpu::PipelinePointer _drawItemBoundsPipeline; + gpu::PipelinePointer _drawItemStatusPipeline; public: @@ -28,6 +27,7 @@ namespace render { typedef Job::ModelI JobModel; const gpu::PipelinePointer& getDrawItemBoundsPipeline(); + const gpu::PipelinePointer& getDrawItemStatusPipeline(); }; } diff --git a/libraries/render/src/render/drawItemStatus.slf b/libraries/render/src/render/drawItemStatus.slf new file mode 100644 index 0000000000..dcf5d3ee25 --- /dev/null +++ b/libraries/render/src/render/drawItemStatus.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// drawItemStatus.frag +// fragment shader +// +// Created by Sam Gateau on 6/30/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 +// + +varying vec4 varColor; + + +void main(void) { + gl_FragColor = varColor; +} diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv new file mode 100644 index 0000000000..da99d2692e --- /dev/null +++ b/libraries/render/src/render/drawItemStatus.slv @@ -0,0 +1,66 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemStatus.slv +// vertex shader +// +// Created by Sam Gateau on 6/30/2015. +// 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec4 varColor; + +attribute vec4 inStatus; + +vec3 paintRainbow(float nv) { + float v = nv * 5.f; + if ( v < 0.f ) + return vec3(1.f, 0.f, 0.f); + else if ( v < 1.f) + return vec3(1.f, v, 0.f); + else if ( v < 2.f) + return vec3(1.f - (v-1.f), 1.f, 0.f); + else if ( v < 3.f) + return vec3(0.f, 1.f, (v-2.f)); + else if ( v < 4.f) + return vec3(0.f, 1.f - (v-3.f), 1.f ); + else if ( v < 5.f) + return vec3((v-4.f), 0.f, 1.f ); + else + return vec3(1.f, 0.f, 1.f); +} + +void main(void) { + const vec2 ICON_PIXEL_SIZE = vec2(10, 10); + const vec4 UNIT_QUAD[4] = vec4[4]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0) + ); + + // Use the status for showing a color ? + varColor = vec4(paintRainbow(inStatus.x), 1.0); + + + vec4 anchorPoint = vec4(0.5, 0.5, 0.5, 1.0); + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$> + + vec4 pos = UNIT_QUAD[gl_VertexID]; + + vec4 viewport; + <$transformCameraViewport(cam, viewport)$>; + vec2 clipIconSize = vec2(ICON_PIXEL_SIZE.x / viewport.z, ICON_PIXEL_SIZE.y / viewport.w); + + gl_Position = anchorPoint + anchorPoint.w * vec4(pos.xy * clipIconSize, 0.0, 0.0); +} \ No newline at end of file From aa55de46c2fb26c99e39b21cad930ed7deb75e5f Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Tue, 30 Jun 2015 16:09:45 -0700 Subject: [PATCH 04/39] Drawing full bounding box --- libraries/render/src/render/DrawStatus.cpp | 36 +++++----- libraries/render/src/render/Stats.h | 29 --------- .../render/src/render/drawItemBounds.slv | 65 +++++++++++-------- 3 files changed, 55 insertions(+), 75 deletions(-) delete mode 100644 libraries/render/src/render/Stats.h diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index eaf39b6893..e95a47e872 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -33,23 +33,23 @@ using namespace render; const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { if (!_drawItemBoundsPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag))); - gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - - gpu::Shader::BindingSet slotBindings; - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - - state->setDepthTest(true, false, gpu::LESS_EQUAL); - - // Blend on transparent - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); - - // Good to go add the brand new pipeline + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Good to go add the brand new pipeline _drawItemBoundsPipeline.reset(gpu::Pipeline::create(program, state)); } return _drawItemBoundsPipeline; @@ -88,7 +88,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex } batch.setModelTransform(model); - batch.draw(gpu::LINE_STRIP, 13, 0); + batch.draw(gpu::LINES, 24, 0); } } diff --git a/libraries/render/src/render/Stats.h b/libraries/render/src/render/Stats.h deleted file mode 100644 index 5291581d7e..0000000000 --- a/libraries/render/src/render/Stats.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Stats.h -// render/src/render -// -// Created by Niraj Venkat on 6/29/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 -// - -#ifndef hifi_render_Stats_h -#define hifi_render_Stats_h - -#include "DrawTask.h" -#include "gpu/Batch.h" -#include - - -namespace render { - class DrawStats { - public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); - - typedef Job::ModelI JobModel; - }; -} - -#endif // hifi_render_Stats_h diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv index e1193a9874..74c4fe3ab5 100644 --- a/libraries/render/src/render/drawItemBounds.slv +++ b/libraries/render/src/render/drawItemBounds.slv @@ -1,38 +1,47 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// drawItemBounds.slv -// vertex shader -// -// Created by Sam Gateau on 6/29/2015. -// 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 gpu/Transform.slh@> - -<$declareStandardTransform()$> - +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemBounds.slv +// vertex shader +// +// Created by Sam Gateau on 6/29/2015. +// 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + void main(void) { - const vec4 UNIT_BOX[13] = vec4[13]( + const vec4 UNIT_BOX[8] = vec4[8]( vec4(0.0, 0.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0), - vec4(0.0, 1.0, 0.0, 1.0), - vec4(0.0, 0.0, 0.0, 1.0), - vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), vec4(1.0, 0.0, 1.0, 1.0), - vec4(0.0, 0.0, 1.0, 1.0), - vec4(0.0, 0.0, 0.0, 1.0), - vec4(0.0, 1.0, 0.0, 1.0), vec4(0.0, 1.0, 1.0, 1.0), - vec4(0.0, 0.0, 1.0, 1.0), - vec4(0.0, 0.0, 0.0, 1.0) + vec4(1.0, 1.0, 1.0, 1.0) ); - vec4 pos = UNIT_BOX[gl_VertexID]; + const int UNIT_BOX_LINE_INDICES[24] = int[24]( + 0, 1, + 1, 3, + 3, 2, + 2, 0, + 4, 5, + 5, 7, + 7, 6, + 6, 4, + 2, 6, + 3, 7, + 0, 4, + 1, 5 + ); + vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; // standard transform TransformCamera cam = getTransformCamera(); From 2f04a9d3da68147037b0738a866bf8c7f03f2835 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 1 Jul 2015 07:47:46 -0700 Subject: [PATCH 05/39] refining the shader pipeline and trying to pass a Status Getter from the model and fails --- .../src/RenderableModelEntityItem.cpp | 17 +++- libraries/gpu/src/gpu/GLBackend.cpp | 12 +++ libraries/render-utils/src/Model.cpp | 32 +++++++ libraries/render-utils/src/Model.h | 1 + libraries/render/src/render/DrawStatus.cpp | 95 ++++++++++++++----- libraries/render/src/render/DrawStatus.h | 9 ++ libraries/render/src/render/Scene.h | 13 ++- .../render/src/render/drawItemBounds.slv | 5 + .../render/src/render/drawItemStatus.slv | 6 +- 9 files changed, 159 insertions(+), 31 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 14a64d289e..c5c92837bf 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -177,7 +177,22 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p pendingChanges.resetItem(_myMetaItem, renderPayload); if (_model) { - return _model->addToScene(scene, pendingChanges); + // return _model->addToScene(scene, pendingChanges); + + render::Item::Status::Getter statusGetter = [this] () -> render::Item::Status::Value { + quint64 now = usecTimestampNow(); + /* if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { + return glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); + renderBoundingBox(entity, args, 0.16f, redColor); + } + */ + if (now - this->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { + return 256; + } + return 0; + }; + return _model->addToScene(scene, pendingChanges, statusGetter); + } return true; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 112e34eaea..b7b2744c31 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -191,6 +191,18 @@ void GLBackend::do_drawIndexed(Batch& batch, uint32 paramOffset) { } void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) { + updateInput(); + updateTransform(); + updatePipeline(); + + GLint numInstances = batch._params[paramOffset + 4]._uint; + Primitive primitiveType = (Primitive)batch._params[paramOffset + 3]._uint; + GLenum mode = _primitiveToGLmode[primitiveType]; + uint32 numVertices = batch._params[paramOffset + 2]._uint; + uint32 startVertex = batch._params[paramOffset + 1]._uint; + uint32 startInstance = batch._params[paramOffset + 0]._uint; + + glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); (void) CHECK_GL_ERROR(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 93f3f345f0..f617ecf26f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -910,6 +910,38 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan return somethingAdded; } +bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter) { + if (!_meshGroupsKnown && isLoadedWithTextures()) { + segregateMeshGroups(); + } + + bool somethingAdded = false; + + foreach (auto renderItem, _transparentRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + renderPayload->addStatusGetter(statusGetter); + pendingChanges.resetItem(item, renderPayload); + _renderItems.insert(item, renderPayload); + somethingAdded = true; + } + + foreach (auto renderItem, _opaqueRenderItems) { + auto item = scene->allocateID(); + auto renderData = MeshPartPayload::Pointer(renderItem); + auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); + renderPayload->addStatusGetter(statusGetter); + pendingChanges.resetItem(item, renderPayload); + _renderItems.insert(item, renderPayload); + somethingAdded = true; + } + + _readyWhenAdded = readyToAddToScene(); + + return somethingAdded; +} + void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { foreach (auto item, _renderItems.keys()) { pendingChanges.removeItem(item); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3748403b97..5e440d012d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -118,6 +118,7 @@ public: bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return !_needsReload && isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); /// Sets the URL of the model to render. diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index afe9aa3798..ef91efda71 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -42,6 +42,9 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() { gpu::Shader::BindingSet slotBindings; gpu::Shader::makeProgram(*program, slotBindings); + _drawItemBoundPosLoc = program->getUniforms().findLocation("inBoundPos"); + _drawItemBoundDimLoc = program->getUniforms().findLocation("inBoundDim"); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(true, false, gpu::LESS_EQUAL); @@ -66,6 +69,10 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() { gpu::Shader::BindingSet slotBindings; gpu::Shader::makeProgram(*program, slotBindings); + _drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos"); + _drawItemStatusDimLoc = program->getUniforms().findLocation("inBoundDim"); + _drawItemStatusValueLoc = program->getUniforms().findLocation("inStatus"); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); state->setDepthTest(false, false, gpu::LESS_EQUAL); @@ -85,7 +92,49 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex assert(renderContext->args); assert(renderContext->args->_viewFrustum); RenderArgs* args = renderContext->args; + auto& scene = sceneContext->_scene; + // FIrst thing, we collect the bound and the status for all the items we want to render + int nbItems = 0; + { + if (!_itemBounds) { + _itemBounds.reset(new gpu::Buffer()); + } + if (!_itemStatus) { + _itemStatus.reset(new gpu::Buffer()); + } + + _itemBounds->resize((inItems.size() * sizeof(AABox))); + _itemStatus->resize((inItems.size() * sizeof(glm::vec4))); + AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); + glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + for (auto& item : inItems) { + if (!item.bounds.isInvalid()) { + if (!item.bounds.isNull()) { + (*itemAABox) = item.bounds; + } else { + (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); + } + auto& itemScene = scene->getItem(item.id); + auto& status = itemScene.getStatus(); + if (status) { + status->getValue((*itemStatus)); + } else { + (*itemStatus) = glm::vec4(-1.0f); + } + + nbItems++; + itemAABox++; + itemStatus++; + } + } + } + + if (nbItems == 0) { + return; + } + + // Allright, something to render let's do it gpu::Batch batch; glm::mat4 projMat; @@ -97,46 +146,40 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); - - // batch.setModelTransform(Transform()); - // bind the unit cube geometry +/* if (!_drawItemFormat) { + _drawItemFormat.reset(new gpu::Stream::Format()); + _drawItemFormat->setAttribute(0, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); + _drawItemFormat->setAttribute(1, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), sizeof(glm::vec3), gpu::Stream::PER_INSTANCE); + } +*/ // bind the one gpu::Pipeline we need batch.setPipeline(getDrawItemBoundsPipeline()); - for (auto& item : inItems) { - if (!item.bounds.isInvalid()) { - Transform model; - model.setTranslation(item.bounds.getCorner()); - if (!item.bounds.isNull()) { - model.setScale(item.bounds.getDimensions()); - } + AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); + glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); - batch.setModelTransform(model); - batch.draw(gpu::LINE_STRIP, 13, 0); - } + for (int i = 0; i < nbItems; i++) { + + batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const GLfloat*) (itemAABox + i)); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + + batch.draw(gpu::LINE_STRIP, 13, 0); } batch.setPipeline(getDrawItemStatusPipeline()); + for (int i = 0; i < nbItems; i++) { + batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const GLfloat*) (itemAABox + i)); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + batch._glUniform4fv(_drawItemStatusValueLoc, 1, (const GLfloat*) (itemStatus + i)); - for (auto& item : inItems) { - if (!item.bounds.isInvalid()) { - Transform model; - model.setTranslation(item.bounds.getCorner()); - if (!item.bounds.isNull()) { - model.setScale(item.bounds.getDimensions()); - } - - batch.setModelTransform(model); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } + batch.draw(gpu::TRIANGLE_STRIP, 4, 0); } // Before rendering the batch make sure we re in sync with gl state args->_context->syncCache(); renderContext->args->_context->syncCache(); args->_context->render((batch)); - args->_batch = nullptr; - } \ No newline at end of file diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 079f223ff5..ca4763d33b 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -17,8 +17,17 @@ namespace render { class DrawStatus { + int _drawItemBoundPosLoc = -1; + int _drawItemBoundDimLoc = -1; + int _drawItemStatusPosLoc = -1; + int _drawItemStatusDimLoc = -1; + int _drawItemStatusValueLoc = -1; + + gpu::Stream::FormatPointer _drawItemFormat; gpu::PipelinePointer _drawItemBoundsPipeline; gpu::PipelinePointer _drawItemStatusPipeline; + gpu::BufferPointer _itemBounds; + gpu::BufferPointer _itemStatus; public: diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 444b45800a..75dc92dbdf 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -200,13 +200,22 @@ public: // This is Used for monitoring and dynamically adjust the quality class Status { public: - typedef glm::ivec2 Value; + typedef unsigned char Value; typedef std::function Getter; int _firstFrame; std::vector _values; void addGetter(Getter& getter) { _values.push_back(getter); } + void getValue(glm::vec4& value) { + for (unsigned int i = 0; i < value.length(); i++) { + if (i < _values.size()) { + value[i] = _values[i]() / 256; + } else { + value[i] = 0.0f; + } + } + } }; typedef std::shared_ptr StatusPointer; @@ -232,7 +241,7 @@ public: // Status interface is local to the base class const StatusPointer& getStatus() const { return _status; } - void addStatusGetter(Status::Getter& getter) { _status->addGetter(getter); } + void addStatusGetter(Status::Getter& getter) { if (!_status) { _status.reset(new Status());} _status->addGetter(getter); } protected: StatusPointer _status; diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv index e1193a9874..a74d105cf1 100644 --- a/libraries/render/src/render/drawItemBounds.slv +++ b/libraries/render/src/render/drawItemBounds.slv @@ -16,6 +16,9 @@ <$declareStandardTransform()$> +uniform vec3 inBoundPos; +uniform vec3 inBoundDim; + void main(void) { const vec4 UNIT_BOX[13] = vec4[13]( vec4(0.0, 0.0, 0.0, 1.0), @@ -34,6 +37,8 @@ void main(void) { ); vec4 pos = UNIT_BOX[gl_VertexID]; + pos.xyz = inBoundPos + inBoundDim * pos.xyz; + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index da99d2692e..01f47862bc 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -18,7 +18,9 @@ varying vec4 varColor; -attribute vec4 inStatus; +uniform vec3 inBoundPos; +uniform vec3 inBoundDim; +uniform vec4 inStatus; vec3 paintRainbow(float nv) { float v = nv * 5.f; @@ -51,7 +53,7 @@ void main(void) { varColor = vec4(paintRainbow(inStatus.x), 1.0); - vec4 anchorPoint = vec4(0.5, 0.5, 0.5, 1.0); + vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$> From dfa6b03a6ba1feb3ef1f1e5da12cee284428bc20 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 1 Jul 2015 14:20:35 -0700 Subject: [PATCH 06/39] Making the first statusGetter noitify --- .../src/RenderableModelEntityItem.cpp | 20 ++++++++++++++++++- libraries/render/src/render/Scene.h | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c5c92837bf..4bbe2cac52 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -229,7 +229,25 @@ void RenderableModelEntityItem::render(RenderArgs* args) { render::PendingChanges pendingChanges; if (_model->needsFixupInScene()) { _model->removeFromScene(scene, pendingChanges); - _model->addToScene(scene, pendingChanges); + + + render::Item::Status::Getter statusGetter = [this] () -> render::Item::Status::Value { + quint64 now = usecTimestampNow(); + /* if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { + return glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); + renderBoundingBox(entity, args, 0.16f, redColor); + } + */ + /*if (now - this->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { + return 256; + } + return 0;*/ + static int i = 0; + return (i++)%256; + + }; + + _model->addToScene(scene, pendingChanges, statusGetter); } scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 75dc92dbdf..02bb03f285 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -210,7 +210,7 @@ public: void getValue(glm::vec4& value) { for (unsigned int i = 0; i < value.length(); i++) { if (i < _values.size()) { - value[i] = _values[i]() / 256; + value[i] = _values[i]() / 256.0f; } else { value[i] = 0.0f; } From b23f68107c6dc74b6f4bca7717cf8bbd3937d150 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 1 Jul 2015 14:52:23 -0700 Subject: [PATCH 07/39] Adding the gpu_shader4 for linux and fixing function name for mac --- libraries/gpu/src/gpu/Config.slh | 5 +++-- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index a16ee372ae..76be161822 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -18,12 +18,13 @@ <@elif GLPROFILE == MAC_GL @> <@def GPU_FEATURE_PROFILE GPU_LEGACY@> <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> - <@def VERSION_HEADER #version 120 + <@def VERSION_HEADER #version 120 #extension GL_EXT_gpu_shader4 : enable@> <@else@> <@def GPU_FEATURE_PROFILE GPU_LEGACY@> <@def GPU_TRANSFORM_PROFILE GPU_LEGACY@> - <@def VERSION_HEADER #version 120@> + <@def VERSION_HEADER #version 120 +#extension GL_EXT_gpu_shader4 : enable@> <@endif@> <@endif@> diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index b7b2744c31..bb855c46d4 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -202,7 +202,7 @@ void GLBackend::do_drawInstanced(Batch& batch, uint32 paramOffset) { uint32 startVertex = batch._params[paramOffset + 1]._uint; uint32 startInstance = batch._params[paramOffset + 0]._uint; - glDrawArraysInstanced(mode, startVertex, numVertices, numInstances); + glDrawArraysInstancedARB(mode, startVertex, numVertices, numInstances); (void) CHECK_GL_ERROR(); } From 219bcd19edc8d0f7d12695b1b12d5395bf49be20 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Wed, 1 Jul 2015 16:40:42 -0700 Subject: [PATCH 08/39] Status bar update --- libraries/render/src/render/DrawStatus.cpp | 2 +- .../render/src/render/drawItemStatus.slv | 31 ++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index f61a4e56c3..25dea092b2 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -174,7 +174,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); batch._glUniform4fv(_drawItemStatusValueLoc, 1, (const GLfloat*) (itemStatus + i)); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); + batch.draw(gpu::TRIANGLES, 24, 0); } // Before rendering the batch make sure we re in sync with gl state diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 01f47862bc..048493c67e 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -42,27 +42,44 @@ vec3 paintRainbow(float nv) { void main(void) { const vec2 ICON_PIXEL_SIZE = vec2(10, 10); - const vec4 UNIT_QUAD[4] = vec4[4]( + const int NUM_VERTICES = 6; + const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(1.0, -1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0), + vec4(1.0, -1.0, 0.0, 1.0), vec4(1.0, 1.0, 0.0, 1.0) ); - // Use the status for showing a color ? - varColor = vec4(paintRainbow(inStatus.x), 1.0); - - vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$> + + int notifNum = gl_VertexID / NUM_VERTICES; + int twoTriID = gl_VertexID - notifNum * NUM_VERTICES; + vec4 pos = UNIT_QUAD[twoTriID]; - vec4 pos = UNIT_QUAD[gl_VertexID]; + // Use the status for showing a color ? + if(notifNum == 0) { + varColor = vec4(paintRainbow(inStatus.x), 1.0); + } else if(notifNum == 1) { + varColor = vec4(paintRainbow(inStatus.y), 1.0); + } else if(notifNum == 2) { + varColor = vec4(paintRainbow(inStatus.z), 1.0); + } else { + varColor = vec4(paintRainbow(inStatus.w), 1.0); + } vec4 viewport; <$transformCameraViewport(cam, viewport)$>; vec2 clipIconSize = vec2(ICON_PIXEL_SIZE.x / viewport.z, ICON_PIXEL_SIZE.y / viewport.w); - gl_Position = anchorPoint + anchorPoint.w * vec4(pos.xy * clipIconSize, 0.0, 0.0); + //Offset size in pixels + float offset = 3.5f; + pos.x += offset * notifNum; + + gl_Position = anchorPoint + (anchorPoint.w * vec4(pos.xy * clipIconSize, 0.0, 0.0)); + } \ No newline at end of file From e8b11f119899732065c4e5a15a8f48d781815367 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 1 Jul 2015 17:27:41 -0700 Subject: [PATCH 09/39] Exposing the display Item Status to js to turn it on/off --- examples/utilities/tools/renderEngineDebug.js | 6 ++++ interface/src/Application.cpp | 2 ++ .../render-utils/src/RenderDeferredTask.cpp | 7 +++++ .../render-utils/src/RenderDeferredTask.h | 5 +++ libraries/render/src/render/DrawStatus.cpp | 7 +---- libraries/render/src/render/DrawTask.h | 31 ++++++++++++++++--- libraries/render/src/render/Engine.h | 2 ++ libraries/render/src/render/Scene.cpp | 9 ++++++ libraries/render/src/render/Scene.h | 15 +++------ .../src/SceneScriptingInterface.h | 6 ++++ 10 files changed, 68 insertions(+), 22 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index 8185a24078..d337290927 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -66,6 +66,12 @@ panel.newSlider("Max Drawn Overlay3Ds", -1, 100, function(value) { return (value); } ); +panel.newCheckbox("Display status", + function(value) { Scene.setEngineDisplayItemStatus(value); }, + function() { return Scene.doEngineDisplayItemStatus(); }, + function(value) { return (value); } +); + var tickTackPeriod = 500; function updateCounters() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2e2722aec2..95b9998778 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3526,6 +3526,8 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._maxDrawnTransparentItems = sceneInterface->getEngineMaxDrawnTransparentItems(); renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems(); + renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus(); + renderArgs->_shouldRender = LODManager::shouldRender; renderContext.args = renderArgs; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index db2b657126..1012624134 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -68,7 +68,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new CullItems::JobModel("CullTransparent", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput()))); + _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques))); + _jobs.back().setEnabled(false); + _drawStatusJobIndex = _jobs.size() - 1; + _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); _jobs.push_back(Job(new ResetGLState::JobModel())); } @@ -89,6 +93,9 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } + // Make sure we turn the displayItemStatus on/off + setDrawItemStatus(renderContext->_drawItemStatus); + renderContext->args->_context->syncCache(); for (auto job : _jobs) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2f65c5ade6..3d11e97634 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -70,6 +70,11 @@ public: render::Jobs _jobs; + int _drawStatusJobIndex = -1; + + void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } } + bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } + virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); }; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index f61a4e56c3..4961e744d9 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -116,12 +116,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); } auto& itemScene = scene->getItem(item.id); - auto& status = itemScene.getStatus(); - if (status) { - status->getValue((*itemStatus)); - } else { - (*itemStatus) = glm::vec4(-1.0f); - } + (*itemStatus) = itemScene.getStatusValues(); nbItems++; itemAABox++; diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 8a4d424005..a0139732f6 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -77,6 +77,9 @@ public: Job(const Job& other) : _concept(other._concept) {} ~Job(); + bool isEnabled() const { return _concept->isEnabled(); } + void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } + const std::string& getName() const { return _concept->getName(); } const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } @@ -92,6 +95,7 @@ public: class Concept { std::string _name; + bool _isEnabled = true; public: Concept() : _name() {} Concept(const std::string& name) : _name(name) {} @@ -99,7 +103,10 @@ public: void setName(const std::string& name) { _name = name; } const std::string& getName() const { return _name; } - + + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } + virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; @@ -119,7 +126,11 @@ public: Model(Data data): _data(data) {} Model(Data data, const std::string& name): Concept(name), _data(data) {} - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRun(_data, sceneContext, renderContext); } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } + } }; template class ModelI : public Concept { @@ -135,7 +146,11 @@ public: ModelI(const std::string& name, const Varying& input): Concept(name), _input(input) {} ModelI(const std::string& name, Data data): Concept(name), _data(data) {} - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunI(_data, sceneContext, renderContext, _input.get()); } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunI(_data, sceneContext, renderContext, _input.get()); + } + } }; template class ModelO : public Concept { @@ -155,7 +170,9 @@ public: ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - jobRunO(_data, sceneContext, renderContext, _output.edit()); + if (isEnabled()) { + jobRunO(_data, sceneContext, renderContext, _output.edit()); + } } }; @@ -177,7 +194,11 @@ public: void setInput(const Varying& input) { _input = input; } - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); + } + } }; std::shared_ptr _concept; diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 054f7e5ce4..1c600b13d6 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -49,6 +49,8 @@ public: int _numDrawnOverlay3DItems = 0; int _maxDrawnOverlay3DItems = -1; + bool _drawItemStatus = false; + RenderContext() {} }; typedef std::shared_ptr RenderContextPointer; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 1d2e54541b..7de1e6650c 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -53,6 +53,15 @@ void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { (*this)[ItemFilter::Builder::transparentShape().withLayered()]; } +void Item::Status::getValues(glm::vec4& values) { + for (int i = 0; i < values.length(); i++) { + if (i < _values.size()) { + values[i] = _values[i]() / 256.0f; + } else { + values[i] = -1.0f; + } + } +} void Item::resetPayload(const PayloadPointer& payload) { if (!payload) { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 02bb03f285..9b459e0f3e 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -202,20 +202,12 @@ public: public: typedef unsigned char Value; typedef std::function Getter; + typedef std::vector Getters; - int _firstFrame; - std::vector _values; + Getters _values; void addGetter(Getter& getter) { _values.push_back(getter); } - void getValue(glm::vec4& value) { - for (unsigned int i = 0; i < value.length(); i++) { - if (i < _values.size()) { - value[i] = _values[i]() / 256.0f; - } else { - value[i] = 0.0f; - } - } - } + void getValues(glm::vec4& values); }; typedef std::shared_ptr StatusPointer; @@ -278,6 +270,7 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } + glm::vec4 getStatusValues() const { glm::vec4 values(-1.f); auto& status = getStatus(); if (status) { status->getValues(values); }; return values; } protected: PayloadPointer _payload; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 8359aa58fa..674b452528 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -106,6 +106,10 @@ public: Q_INVOKABLE int getEngineMaxDrawnTransparentItems() { return _maxDrawnTransparentItems; } Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; } Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; } + + Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; } + Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; } + signals: void shouldRenderAvatarsChanged(bool shouldRenderAvatars); void shouldRenderEntitiesChanged(bool shouldRenderEntities); @@ -136,6 +140,8 @@ protected: int _maxDrawnTransparentItems = -1; int _maxDrawnOverlay3DItems = -1; + bool _drawItemStatus = false; + }; #endif // hifi_SceneScriptingInterface_h From ee998d0c74e6309f6f2a4cc12469d9a1003f07d5 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Wed, 1 Jul 2015 17:30:50 -0700 Subject: [PATCH 10/39] Icon size is a pixel if the inStatus is -1 --- .../render/src/render/drawItemStatus.slv | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 048493c67e..cf9e3a5429 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -41,7 +41,7 @@ vec3 paintRainbow(float nv) { } void main(void) { - const vec2 ICON_PIXEL_SIZE = vec2(10, 10); + vec2 ICON_PIXEL_SIZE = vec2(10, 10); const int NUM_VERTICES = 6; const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES]( vec4(-1.0, -1.0, 0.0, 1.0), @@ -61,15 +61,33 @@ void main(void) { int twoTriID = gl_VertexID - notifNum * NUM_VERTICES; vec4 pos = UNIT_QUAD[twoTriID]; + bool isPixel = false; // Use the status for showing a color ? + // Also changes the size of the notification if(notifNum == 0) { varColor = vec4(paintRainbow(inStatus.x), 1.0); + if(inStatus.x == -1) { + isPixel = true; + } } else if(notifNum == 1) { varColor = vec4(paintRainbow(inStatus.y), 1.0); + if(inStatus.y == -1) { + isPixel = true; + } } else if(notifNum == 2) { varColor = vec4(paintRainbow(inStatus.z), 1.0); + if(inStatus.z == -1) { + isPixel = true; + } } else { varColor = vec4(paintRainbow(inStatus.w), 1.0); + if(inStatus.w == -1) { + isPixel = true; + } + } + + if(isPixel) { + ICON_PIXEL_SIZE = vec2(1, 1); } vec4 viewport; From b13a4b2a71d6b027ae109c06ba2aeae85b5e7596 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 11:07:47 -0700 Subject: [PATCH 11/39] add edit update stats --- interface/src/devices/TV3DManager.cpp | 1 - interface/src/ui/ApplicationCompositor.cpp | 5 ---- interface/src/ui/ApplicationOverlay.cpp | 3 --- interface/src/ui/AvatarInputs.cpp | 1 - interface/src/ui/OctreeStatsDialog.cpp | 15 ++++++++++++ interface/src/ui/OctreeStatsDialog.h | 4 ++++ libraries/entities/src/EntityItem.cpp | 9 +++++++ libraries/entities/src/EntityTree.cpp | 28 ++++++++++++++++++++++ libraries/entities/src/EntityTree.h | 13 ++++++++++ 9 files changed, 69 insertions(+), 10 deletions(-) diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 41e549a861..e945b5e79a 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -109,7 +109,6 @@ void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) { glScissor(portalX, portalY, portalW, portalH); glm::mat4 projection = glm::frustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); - float fov = atan(1.0f / projection[1][1]); projection = glm::translate(projection, vec3(eye.modelTranslation, 0, 0)); eyeCamera.setProjection(projection); diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 6cdf690d99..bb19392458 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -25,18 +25,13 @@ // Used to animate the magnification windows -static const float MAG_SPEED = 0.08f; static const quint64 MSECS_TO_USECS = 1000ULL; static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; -static const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; static const float reticleSize = TWO_PI / 100.0f; -static const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; -static const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; - static const float CURSOR_PIXEL_SIZE = 32.0f; static const float MOUSE_PITCH_RANGE = 1.0f * PI; static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 63f68b86ce..e7d220893f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -36,9 +36,6 @@ #include "ui/Stats.h" #include "ui/AvatarInputs.h" -const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; -const int AUDIO_METER_GAP = 5; -const int MUTE_ICON_PADDING = 10; const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; static const float ORTHO_NEAR_CLIP = -10000; diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index 11f744aaca..870038cd01 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -67,7 +67,6 @@ void AvatarInputs::update() { AI_UPDATE(cameraMuted, Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking)); auto audioIO = DependencyManager::get(); - const float CLIPPING_INDICATOR_TIME = 1.0f; const float AUDIO_METER_AVERAGING = 0.5; const float LOG2 = log(2.0f); const float METER_LOUDNESS_SCALE = 2.8f / 5.0f; diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 462811fc1c..4e55e3beef 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -50,6 +50,7 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _localElements = AddStatItem("Local Elements"); _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); + _entityUpdateTime = AddStatItem("Entity Update Time"); layout()->setSizeConstraint(QLayout::SetFixedSize); } @@ -203,6 +204,20 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); + label = _labels[_entityUpdateTime]; + auto entites = Application::getInstance()->getEntities()->getTree(); + quint64 averageEditDelta = entites->getAverageEditDeltas(); + QString averageEditDeltaString = locale.toString((uint)averageEditDelta); + quint64 maxEditDelta = entites->getMaxEditDelta(); + QString maxEditDeltaString = locale.toString((uint)maxEditDelta); + + statsValue.str(""); + statsValue << + "Average: " << qPrintable(averageEditDeltaString) << " (usecs) / " << + "Max: " << qPrintable(maxEditDeltaString) << " (usecs)"; + label->setText(statsValue.str().c_str()); + + showAllOctreeServers(); this->QDialog::paintEvent(event); diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 03683d8171..5ddda8067a 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -63,6 +63,10 @@ private: int _serverElements; int _localElements; int _localElementsMemory; + + int _entityUpdateTime; + + int _octreeServerLables[MAX_VOXEL_SERVERS]; int _octreeServerLabelsCount; details _extraServerDetails[MAX_VOXEL_SERVERS]; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 74b7a36504..e24f6846fd 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -414,6 +414,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(lastEditedFromBuffer); bytesRead += sizeof(lastEditedFromBuffer); lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew; + + // Tracking for editing roundtrips here. We will tell our EntityTree that we just got incoming data about + // and entity that was edited at some time in the past. The tree will determine how it wants to track this + // information. + if (_element && _element->getTree()) { + _element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted); + } + if (lastEditedFromBufferAdjusted > now) { lastEditedFromBufferAdjusted = now; } @@ -486,6 +494,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now); #endif } + encodedUpdateDelta = updateDeltaCoder; // determine true length dataAt += encodedUpdateDelta.size(); bytesRead += encodedUpdateDelta.size(); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 6a652d609b..0fbe6d40ed 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -34,6 +34,7 @@ EntityTree::EntityTree(bool shouldReaverage) : _simulation(NULL) { _rootElement = createNewElement(); + resetClientEditStats(); } EntityTree::~EntityTree() { @@ -60,6 +61,8 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) { } _entityToElementMap.clear(); Octree::eraseAllOctreeElements(createNewRoot); + + resetClientEditStats(); } bool EntityTree::handlesEditPacketType(PacketType packetType) const { @@ -1104,3 +1107,28 @@ bool EntityTree::readFromMap(QVariantMap& map) { return true; } + +void EntityTree::resetClientEditStats() { + _treeResetTime = usecTimestampNow(); + _maxEditDelta = 0; + _totalEditDeltas = 0; + _totalTrackedEdits = 0; +} + + + +void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime) { + // we don't want to track all edit deltas, just those edits that have happend + // since we connected to this domain. This will filter out all previously created + // content and only track new edits + if (lastEditedTime > _treeResetTime) { + quint64 now = usecTimestampNow(); + quint64 sinceEdit = now - lastEditedTime; + + _totalEditDeltas += sinceEdit; + _totalTrackedEdits++; + if (sinceEdit > _maxEditDelta) { + _maxEditDelta = sinceEdit; + } + } +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index fa72cc7691..9db57af383 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -185,6 +185,12 @@ public: virtual quint64 getAverageCreateTime() const { return _totalCreates == 0 ? 0 : _totalCreateTime / _totalCreates; } virtual quint64 getAverageLoggingTime() const { return _totalEditMessages == 0 ? 0 : _totalLoggingTime / _totalEditMessages; } + void trackIncomingEntityLastEdited(quint64 lastEditedTime); + quint64 getAverageEditDeltas() const + { return _totalTrackedEdits == 0 ? 0 : _totalEditDeltas / _totalTrackedEdits; } + quint64 getMaxEditDelta() const + { return _maxEditDelta; } + signals: void deletingEntity(const EntityItemID& entityID); void addingEntity(const EntityItemID& entityID); @@ -230,6 +236,13 @@ private: quint64 _totalUpdateTime = 0; quint64 _totalCreateTime = 0; quint64 _totalLoggingTime = 0; + + // these performance statistics are only used in the client + void resetClientEditStats(); + int _totalTrackedEdits = 0; + quint64 _totalEditDeltas = 0; + quint64 _maxEditDelta = 0; + quint64 _treeResetTime = 0; }; #endif // hifi_EntityTree_h From 63b585da0fda9cccd69453513c5ba545c39e44e3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 13:28:12 -0700 Subject: [PATCH 12/39] added updates per second stat --- interface/src/ui/OctreeStatsDialog.cpp | 43 ++++++++++++++++++++++++-- interface/src/ui/OctreeStatsDialog.h | 6 +++- libraries/entities/src/EntityTree.h | 4 +-- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 4e55e3beef..9426f2b2e0 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -25,7 +25,9 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* model) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint), - _model(model) { + _model(model), + _averageUpdatesPerSecond(SAMPLES_PER_SECOND) +{ _statCount = 0; _octreeServerLabelsCount = 0; @@ -51,6 +53,7 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); _entityUpdateTime = AddStatItem("Entity Update Time"); + _entityUpdates = AddStatItem("Entity Updates"); layout()->setSizeConstraint(QLayout::SetFixedSize); } @@ -204,19 +207,53 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); + // Entity Edits update time label = _labels[_entityUpdateTime]; auto entites = Application::getInstance()->getEntities()->getTree(); - quint64 averageEditDelta = entites->getAverageEditDeltas(); + auto averageEditDelta = entites->getAverageEditDeltas(); + auto maxEditDelta = entites->getMaxEditDelta(); + QString averageEditDeltaString = locale.toString((uint)averageEditDelta); - quint64 maxEditDelta = entites->getMaxEditDelta(); QString maxEditDeltaString = locale.toString((uint)maxEditDelta); statsValue.str(""); statsValue << "Average: " << qPrintable(averageEditDeltaString) << " (usecs) / " << "Max: " << qPrintable(maxEditDeltaString) << " (usecs)"; + label->setText(statsValue.str().c_str()); + // Entity Edits + label = _labels[_entityUpdates]; + auto totalTrackedEdits = entites->getTotalTrackedEdits(); + + // track our updated per second + const quint64 SAMPLING_WINDOW = USECS_PER_SECOND / SAMPLES_PER_SECOND; + quint64 now = usecTimestampNow(); + quint64 sinceLastWindow = now - _lastWindowAt; + auto editsInLastWindow = totalTrackedEdits - _lastKnownTrackedEdits; + float sinceLastWindowInSeconds = (float)sinceLastWindow / (float)USECS_PER_SECOND; + float recentUpdatesPerSecond = (float)editsInLastWindow / sinceLastWindowInSeconds; + if (sinceLastWindow > SAMPLING_WINDOW) { + _averageUpdatesPerSecond.updateAverage(recentUpdatesPerSecond); + _lastWindowAt = now; + _lastKnownTrackedEdits = totalTrackedEdits; + } + + auto updatesPerSecond = _averageUpdatesPerSecond.getAverage(); + if (updatesPerSecond < 1) { + updatesPerSecond = 0; // we don't really care about small updates per second so suppress those + } + + QString totalTrackedEditsString = locale.toString((uint)totalTrackedEdits); + QString updatesPerSecondString = locale.toString(updatesPerSecond); + + statsValue.str(""); + statsValue << + "" << qPrintable(updatesPerSecondString) << " updates per second / " << + "" << qPrintable(totalTrackedEditsString) << " total updates "; + + label->setText(statsValue.str().c_str()); showAllOctreeServers(); diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 5ddda8067a..acbf766510 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -65,7 +65,11 @@ private: int _localElementsMemory; int _entityUpdateTime; - + int _entityUpdates; + const int SAMPLES_PER_SECOND = 10; + SimpleMovingAverage _averageUpdatesPerSecond; + quint64 _lastWindowAt = 0; + quint64 _lastKnownTrackedEdits = 0; int _octreeServerLables[MAX_VOXEL_SERVERS]; int _octreeServerLabelsCount; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 9db57af383..92c726729d 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -188,8 +188,8 @@ public: void trackIncomingEntityLastEdited(quint64 lastEditedTime); quint64 getAverageEditDeltas() const { return _totalTrackedEdits == 0 ? 0 : _totalEditDeltas / _totalTrackedEdits; } - quint64 getMaxEditDelta() const - { return _maxEditDelta; } + quint64 getMaxEditDelta() const { return _maxEditDelta; } + quint64 getTotalTrackedEdits() const { return _totalTrackedEdits; } signals: void deletingEntity(const EntityItemID& entityID); From 5c4d4893def43ca46c10f39eef2a0ce38c4662d5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 13:44:28 -0700 Subject: [PATCH 13/39] added bytes per edit stats --- interface/src/ui/OctreeStatsDialog.cpp | 13 ++++++++----- libraries/entities/src/EntityItem.cpp | 15 ++++++++------- libraries/entities/src/EntityTree.cpp | 3 ++- libraries/entities/src/EntityTree.h | 5 ++++- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 9426f2b2e0..c8784f69b8 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -209,9 +209,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Entity Edits update time label = _labels[_entityUpdateTime]; - auto entites = Application::getInstance()->getEntities()->getTree(); - auto averageEditDelta = entites->getAverageEditDeltas(); - auto maxEditDelta = entites->getMaxEditDelta(); + auto entities = Application::getInstance()->getEntities()->getTree(); + auto averageEditDelta = entities->getAverageEditDeltas(); + auto maxEditDelta = entities->getMaxEditDelta(); QString averageEditDeltaString = locale.toString((uint)averageEditDelta); QString maxEditDeltaString = locale.toString((uint)maxEditDelta); @@ -225,7 +225,8 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Entity Edits label = _labels[_entityUpdates]; - auto totalTrackedEdits = entites->getTotalTrackedEdits(); + auto totalTrackedEdits = entities->getTotalTrackedEdits(); + auto bytesPerEdit = entities->getAverageEditBytes(); // track our updated per second const quint64 SAMPLING_WINDOW = USECS_PER_SECOND / SAMPLES_PER_SECOND; @@ -247,11 +248,13 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { QString totalTrackedEditsString = locale.toString((uint)totalTrackedEdits); QString updatesPerSecondString = locale.toString(updatesPerSecond); + QString bytesPerEditString = locale.toString(bytesPerEdit); statsValue.str(""); statsValue << "" << qPrintable(updatesPerSecondString) << " updates per second / " << - "" << qPrintable(totalTrackedEditsString) << " total updates "; + "" << qPrintable(totalTrackedEditsString) << " total updates / " << + "Average Size: " << qPrintable(bytesPerEditString) << " bytes "; label->setText(statsValue.str().c_str()); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e24f6846fd..0f681ba5f7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -415,13 +415,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef bytesRead += sizeof(lastEditedFromBuffer); lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew; - // Tracking for editing roundtrips here. We will tell our EntityTree that we just got incoming data about - // and entity that was edited at some time in the past. The tree will determine how it wants to track this - // information. - if (_element && _element->getTree()) { - _element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted); - } - if (lastEditedFromBufferAdjusted > now) { lastEditedFromBufferAdjusted = now; } @@ -646,6 +639,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } + // Tracking for editing roundtrips here. We will tell our EntityTree that we just got incoming data about + // and entity that was edited at some time in the past. The tree will determine how it wants to track this + // information. + if (_element && _element->getTree()) { + _element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted, bytesRead); + } + + return bytesRead; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 0fbe6d40ed..ae4d8ab236 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1117,7 +1117,7 @@ void EntityTree::resetClientEditStats() { -void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime) { +void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytesRead) { // we don't want to track all edit deltas, just those edits that have happend // since we connected to this domain. This will filter out all previously created // content and only track new edits @@ -1126,6 +1126,7 @@ void EntityTree::trackIncomingEntityLastEdited(quint64 lastEditedTime) { quint64 sinceEdit = now - lastEditedTime; _totalEditDeltas += sinceEdit; + _totalEditBytes += bytesRead; _totalTrackedEdits++; if (sinceEdit > _maxEditDelta) { _maxEditDelta = sinceEdit; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 92c726729d..263cff2171 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -185,9 +185,11 @@ public: virtual quint64 getAverageCreateTime() const { return _totalCreates == 0 ? 0 : _totalCreateTime / _totalCreates; } virtual quint64 getAverageLoggingTime() const { return _totalEditMessages == 0 ? 0 : _totalLoggingTime / _totalEditMessages; } - void trackIncomingEntityLastEdited(quint64 lastEditedTime); + void trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytesRead); quint64 getAverageEditDeltas() const { return _totalTrackedEdits == 0 ? 0 : _totalEditDeltas / _totalTrackedEdits; } + quint64 getAverageEditBytes() const + { return _totalTrackedEdits == 0 ? 0 : _totalEditBytes / _totalTrackedEdits; } quint64 getMaxEditDelta() const { return _maxEditDelta; } quint64 getTotalTrackedEdits() const { return _totalTrackedEdits; } @@ -240,6 +242,7 @@ private: // these performance statistics are only used in the client void resetClientEditStats(); int _totalTrackedEdits = 0; + quint64 _totalEditBytes = 0; quint64 _totalEditDeltas = 0; quint64 _maxEditDelta = 0; quint64 _treeResetTime = 0; From 8be1fd28e53124b4121a5d9ee427b0955b5bdf2d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 2 Jul 2015 13:57:00 -0700 Subject: [PATCH 14/39] stripping naked gl calls from overlays to allow vive and oculus plugins to work --- .../src/ui/overlays/BillboardOverlay.cpp | 25 +------ interface/src/ui/overlays/Grid3DOverlay.cpp | 69 +------------------ .../src/ui/overlays/LocalModelsOverlay.cpp | 22 +++--- interface/src/ui/overlays/OverlaysPayload.cpp | 12 ++-- .../src/ui/overlays/Rectangle3DOverlay.cpp | 63 +---------------- interface/src/ui/overlays/Sphere3DOverlay.cpp | 21 +++--- libraries/render-utils/src/paintStrokes.slf | 27 ++++++++ libraries/render-utils/src/paintStrokes.slv | 35 ++++++++++ 8 files changed, 92 insertions(+), 182 deletions(-) create mode 100644 libraries/render-utils/src/paintStrokes.slf create mode 100644 libraries/render-utils/src/paintStrokes.slv diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 288a950bbb..913eb749a9 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -94,30 +94,7 @@ void BillboardOverlay::render(RenderArgs* args) { batch->setUniformTexture(0, args->_whiteTexture); // restore default white color after me } else { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.5f); - - glEnable(GL_TEXTURE_2D); - glDisable(GL_LIGHTING); - - glBindTexture(GL_TEXTURE_2D, _texture->getID()); - - glPushMatrix(); { - glTranslatef(getPosition().x, getPosition().y, getPosition().z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glScalef(_dimensions.x, _dimensions.y, 1.0f); - - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, - glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); - - } glPopMatrix(); - - glDisable(GL_TEXTURE_2D); - glEnable(GL_LIGHTING); - glDisable(GL_ALPHA_TEST); - - glBindTexture(GL_TEXTURE_2D, 0); + qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 6316c8cd77..295dc1b2b5 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -90,74 +90,7 @@ void Grid3DOverlay::render(RenderArgs* args) { DependencyManager::get()->renderGrid(*batch, MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS, gridColor); } } else { - if (!_gridProgram.isLinked()) { - if (!_gridProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/grid.vert")) { - qDebug() << "Failed to compile: " + _gridProgram.log(); - return; - } - if (!_gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag")) { - qDebug() << "Failed to compile: " + _gridProgram.log(); - return; - } - if (!_gridProgram.link()) { - qDebug() << "Failed to link: " + _gridProgram.log(); - return; - } - } - - // Render code largely taken from MetavoxelEditor::render() - glDisable(GL_LIGHTING); - - glDepthMask(GL_FALSE); - - glPushMatrix(); - - glm::quat rotation = getRotation(); - - glm::vec3 axis = glm::axis(rotation); - - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - glLineWidth(1.5f); - - glm::vec3 position = getPosition(); - - _gridProgram.bind(); - - // Minor grid - glPushMatrix(); - { - glTranslatef(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2), - spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2), position.z); - - float scale = MINOR_GRID_DIVISIONS * spacing; - glScalef(scale, scale, scale); - - DependencyManager::get()->renderGrid(MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS, gridColor); - } - glPopMatrix(); - - // Major grid - glPushMatrix(); - { - glLineWidth(4.0f); - spacing *= _majorGridEvery; - glTranslatef(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2), - spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2), position.z); - - float scale = MAJOR_GRID_DIVISIONS * spacing; - glScalef(scale, scale, scale); - - DependencyManager::get()->renderGrid(MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS, gridColor); - } - glPopMatrix(); - - _gridProgram.release(); - - glPopMatrix(); - - glEnable(GL_LIGHTING); - glDepthMask(GL_TRUE); + qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index 912196041f..6e0b53f0c2 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -32,25 +32,25 @@ void LocalModelsOverlay::update(float deltatime) { void LocalModelsOverlay::render(RenderArgs* args) { if (_visible) { - float glowLevel = getGlowLevel(); Glower* glower = NULL; if (glowLevel > 0.0f) { glower = new Glower(glowLevel); } - - glPushMatrix(); { - Application* app = Application::getInstance(); - glm::vec3 oldTranslation = app->getViewMatrixTranslation(); - app->setViewMatrixTranslation(oldTranslation + getPosition()); - _entityTreeRenderer->render(args); - Application::getInstance()->setViewMatrixTranslation(oldTranslation); - } glPopMatrix(); - + + auto batch = args ->_batch; + Application* app = Application::getInstance(); + glm::vec3 oldTranslation = app->getViewMatrixTranslation(); + Transform transform = Transform(); + transform.setTranslation(oldTranslation + getPosition()); + batch->setViewTransform(transform); + _entityTreeRenderer->render(args); + transform.setTranslation(oldTranslation); + batch->setViewTransform(transform); + if (glower) { delete glower; } - } } diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index b7cacef80c..e6b37d693b 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -62,19 +62,19 @@ namespace render { template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { if (args) { if (overlay->getAnchor() == Overlay::MY_AVATAR) { - glPushMatrix(); + auto batch = args->_batch; MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); glm::quat myAvatarRotation = avatar->getOrientation(); glm::vec3 myAvatarPosition = avatar->getPosition(); float angle = glm::degrees(glm::angle(myAvatarRotation)); glm::vec3 axis = glm::axis(myAvatarRotation); float myAvatarScale = avatar->getScale(); - - glTranslatef(myAvatarPosition.x, myAvatarPosition.y, myAvatarPosition.z); - glRotatef(angle, axis.x, axis.y, axis.z); - glScalef(myAvatarScale, myAvatarScale, myAvatarScale); + Transform transform = Transform(); + transform.setTranslation(myAvatarPosition); + transform.setRotation(glm::angleAxis(angle, axis)); + transform.setScale(myAvatarScale); + batch->setModelTransform(transform); overlay->render(args); - glPopMatrix(); } else { overlay->render(args); } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 74bbd1bca8..6f35ccb3d0 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -88,69 +88,8 @@ void Rectangle3DOverlay::render(RenderArgs* args) { } } } else { - glDisable(GL_LIGHTING); - float glowLevel = getGlowLevel(); - Glower* glower = NULL; - if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); - } - - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - //glScalef(dimensions.x, dimensions.y, 1.0f); - - glLineWidth(_lineWidth); - - auto geometryCache = DependencyManager::get(); - - // for our overlay, is solid means we draw a solid "filled" rectangle otherwise we just draw a border line... - if (getIsSolid()) { - glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f); - DependencyManager::get()->renderQuad(topLeft, bottomRight, rectangleColor); - } else { - if (getIsDashedLine()) { - - glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 point3(halfDimensions.x, halfDimensions.y, 0.0f); - glm::vec3 point4(-halfDimensions.x, halfDimensions.y, 0.0f); - - geometryCache->renderDashedLine(point1, point2, rectangleColor); - geometryCache->renderDashedLine(point2, point3, rectangleColor); - geometryCache->renderDashedLine(point3, point4, rectangleColor); - geometryCache->renderDashedLine(point4, point1, rectangleColor); - - } else { - - if (halfDimensions != _previousHalfDimensions) { - QVector border; - border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f); - border << glm::vec3(halfDimensions.x, -halfDimensions.y, 0.0f); - border << glm::vec3(halfDimensions.x, halfDimensions.y, 0.0f); - border << glm::vec3(-halfDimensions.x, halfDimensions.y, 0.0f); - border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f); - geometryCache->updateVertices(_geometryCacheID, border, rectangleColor); - - _previousHalfDimensions = halfDimensions; - - } - geometryCache->renderVertices(gpu::LINE_STRIP, _geometryCacheID); - } - } - - glPopMatrix(); - glPopMatrix(); - - if (glower) { - delete glower; - } + qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index e129954db9..dd60ee4af8 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -55,17 +55,16 @@ void Sphere3DOverlay::render(RenderArgs* args) { glower = new Glower(glowLevel); } - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - DependencyManager::get()->renderSphere(1.0f, SLICES, SLICES, sphereColor, _isSolid); - glPopMatrix(); - glPopMatrix(); + Transform transform = Transform(); + transform.setTranslation(position); + glm::vec3 axis = glm::axis(rotation); + transform.setRotation(glm::angleAxis(glm::angle(rotation), axis)); + + glm::vec3 positionToCenter = center - position; + transform.setTranslation(positionToCenter); + transform.setScale(dimensions); + DependencyManager::get()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid); + if (glower) { delete glower; diff --git a/libraries/render-utils/src/paintStrokes.slf b/libraries/render-utils/src/paintStrokes.slf new file mode 100644 index 0000000000..bbbb44cc51 --- /dev/null +++ b/libraries/render-utils/src/paintStrokes.slf @@ -0,0 +1,27 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 DeferredBufferWrite.slh@> + +// the interpolated normal +varying vec4 interpolatedNormal; + +void main(void) { + packDeferredFragment( + normalize(interpolatedNormal.xyz), + glowIntensity, + gl_Color.rgb, + gl_FrontMaterial.specular.rgb, + gl_FrontMaterial.shininess); +} diff --git a/libraries/render-utils/src/paintStrokes.slv b/libraries/render-utils/src/paintStrokes.slv new file mode 100644 index 0000000000..380734e70c --- /dev/null +++ b/libraries/render-utils/src/paintStrokes.slv @@ -0,0 +1,35 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple.vert +// vertex shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +// the interpolated normal +varying vec4 interpolatedNormal; + +void main(void) { + gl_TexCoord[0] = gl_MultiTexCoord0; + + // pass along the diffuse color + gl_FrontColor = gl_Color; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); +} \ No newline at end of file From 4db2b8dd59031611ce0c2a94329a0384160cafe0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 2 Jul 2015 15:05:45 -0700 Subject: [PATCH 15/39] removed shader code used in a different branch --- libraries/render-utils/src/paintStrokes.slf | 27 ---------------- libraries/render-utils/src/paintStrokes.slv | 35 --------------------- 2 files changed, 62 deletions(-) delete mode 100644 libraries/render-utils/src/paintStrokes.slf delete mode 100644 libraries/render-utils/src/paintStrokes.slv diff --git a/libraries/render-utils/src/paintStrokes.slf b/libraries/render-utils/src/paintStrokes.slf deleted file mode 100644 index bbbb44cc51..0000000000 --- a/libraries/render-utils/src/paintStrokes.slf +++ /dev/null @@ -1,27 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple.frag -// fragment shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 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 DeferredBufferWrite.slh@> - -// the interpolated normal -varying vec4 interpolatedNormal; - -void main(void) { - packDeferredFragment( - normalize(interpolatedNormal.xyz), - glowIntensity, - gl_Color.rgb, - gl_FrontMaterial.specular.rgb, - gl_FrontMaterial.shininess); -} diff --git a/libraries/render-utils/src/paintStrokes.slv b/libraries/render-utils/src/paintStrokes.slv deleted file mode 100644 index 380734e70c..0000000000 --- a/libraries/render-utils/src/paintStrokes.slv +++ /dev/null @@ -1,35 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// simple.vert -// vertex shader -// -// Created by Andrzej Kapolka on 9/15/14. -// Copyright 2014 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 gpu/Transform.slh@> - -<$declareStandardTransform()$> - -// the interpolated normal -varying vec4 interpolatedNormal; - -void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - - // pass along the diffuse color - gl_FrontColor = gl_Color; - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); -} \ No newline at end of file From be8fe2533843180eb64a56ee6d17807395661b48 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 15:06:07 -0700 Subject: [PATCH 16/39] Trying to finalize the look and behavior of th estatus indicators --- .../src/RenderableModelEntityItem.cpp | 51 +++++------- libraries/gpu/src/gpu/Batch.h | 2 + libraries/gpu/src/gpu/GLBackend.cpp | 26 ++++++ libraries/gpu/src/gpu/GLBackend.h | 1 + libraries/render-utils/src/Model.cpp | 6 +- libraries/render-utils/src/Model.h | 2 +- libraries/render/src/render/DrawStatus.cpp | 8 +- libraries/render/src/render/Scene.cpp | 8 +- libraries/render/src/render/Scene.h | 32 ++++++-- .../render/src/render/drawItemStatus.slv | 80 +++++++++---------- 10 files changed, 129 insertions(+), 87 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 4bbe2cac52..3a8857eaa3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -179,19 +179,17 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p if (_model) { // return _model->addToScene(scene, pendingChanges); - render::Item::Status::Getter statusGetter = [this] () -> render::Item::Status::Value { - quint64 now = usecTimestampNow(); - /* if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { - return glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); - renderBoundingBox(entity, args, 0.16f, redColor); - } - */ - if (now - this->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { - return 256; - } - return 0; - }; - return _model->addToScene(scene, pendingChanges, statusGetter); + render::Item::Status::Getters statusGetters; + statusGetters.push_back([this] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - this->getLastEditedFromRemote(); + return render::Item::Status::Value((delta < 0.1f * USECS_PER_SECOND), 1.0f); + }); + statusGetters.push_back([this] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - this->getLastBroadcast(); + return render::Item::Status::Value((delta < 0.2f * USECS_PER_SECOND), 0.5f); + }); + + return _model->addToScene(scene, pendingChanges, statusGetters); } @@ -230,24 +228,17 @@ void RenderableModelEntityItem::render(RenderArgs* args) { if (_model->needsFixupInScene()) { _model->removeFromScene(scene, pendingChanges); - - render::Item::Status::Getter statusGetter = [this] () -> render::Item::Status::Value { - quint64 now = usecTimestampNow(); - /* if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) { - return glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f); - renderBoundingBox(entity, args, 0.16f, redColor); - } - */ - /*if (now - this->getLastBroadcast() < 0.2f * USECS_PER_SECOND) { - return 256; - } - return 0;*/ - static int i = 0; - return (i++)%256; + render::Item::Status::Getters statusGetters; + statusGetters.push_back([this] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - this->getLastEditedFromRemote(); + return render::Item::Status::Value((delta < 0.1f * USECS_PER_SECOND), 1.0f); + }); + statusGetters.push_back([this] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - this->getLastBroadcast(); + return render::Item::Status::Value((delta < 0.2f * USECS_PER_SECOND), 0.5f); + }); - }; - - _model->addToScene(scene, pendingChanges, statusGetter); + _model->addToScene(scene, pendingChanges, statusGetters); } scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 599a748d9b..835e872b4a 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -155,6 +155,7 @@ public: void _glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); void _glUniform3fv(GLint location, GLsizei count, const GLfloat* value); void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value); + void _glUniform4iv(GLint location, GLsizei count, const GLint* value); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void _glEnableVertexAttribArray(GLint location); @@ -219,6 +220,7 @@ public: COMMAND_glUniform3f, COMMAND_glUniform3fv, COMMAND_glUniform4fv, + COMMAND_glUniform4iv, COMMAND_glUniformMatrix4fv, COMMAND_glEnableVertexAttribArray, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index bb855c46d4..302dc0e8be 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -68,6 +68,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniform3f), (&::gpu::GLBackend::do_glUniform3fv), (&::gpu::GLBackend::do_glUniform4fv), + (&::gpu::GLBackend::do_glUniform4iv), (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glEnableVertexAttribArray), @@ -605,6 +606,31 @@ void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void Batch::_glUniform4iv(GLint location, GLsizei count, const GLint* value) { + ADD_COMMAND_GL(glUniform4iv); + + const int VEC4_SIZE = 4 * sizeof(int); + _params.push_back(cacheData(count * VEC4_SIZE, value)); + _params.push_back(count); + _params.push_back(location); + + DO_IT_NOW(_glUniform4iv, 3); +} +void GLBackend::do_glUniform4iv(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } + updatePipeline(); + glUniform4iv( + batch._params[paramOffset + 2]._int, + batch._params[paramOffset + 1]._uint, + (const GLint*)batch.editData(batch._params[paramOffset + 0]._uint)); + + (void) CHECK_GL_ERROR(); +} + void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0ee0f8d349..d798e9aaac 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -398,6 +398,7 @@ protected: void do_glUniform3f(Batch& batch, uint32 paramOffset); void do_glUniform3fv(Batch& batch, uint32 paramOffset); void do_glUniform4fv(Batch& batch, uint32 paramOffset); + void do_glUniform4iv(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f617ecf26f..1b94c70e57 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -910,7 +910,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan return somethingAdded; } -bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter) { +bool Model::addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters) { if (!_meshGroupsKnown && isLoadedWithTextures()) { segregateMeshGroups(); } @@ -921,7 +921,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); - renderPayload->addStatusGetter(statusGetter); + renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); _renderItems.insert(item, renderPayload); somethingAdded = true; @@ -931,7 +931,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan auto item = scene->allocateID(); auto renderData = MeshPartPayload::Pointer(renderItem); auto renderPayload = render::PayloadPointer(new MeshPartPayload::Payload(renderData)); - renderPayload->addStatusGetter(statusGetter); + renderPayload->addStatusGetters(statusGetters); pendingChanges.resetItem(item, renderPayload); _renderItems.insert(item, renderPayload); somethingAdded = true; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5e440d012d..a6ce566a36 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -118,7 +118,7 @@ public: bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return !_needsReload && isRenderable() && isActive() && isLoadedWithTextures(); } bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); - bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getter& statusGetter); + bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); /// Sets the URL of the model to render. diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 41df3c0130..b73df702be 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -107,7 +107,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex _itemBounds->resize((inItems.size() * sizeof(AABox))); _itemStatus->resize((inItems.size() * sizeof(glm::vec4))); AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); - glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); for (auto& item : inItems) { if (!item.bounds.isInvalid()) { if (!item.bounds.isNull()) { @@ -116,7 +116,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); } auto& itemScene = scene->getItem(item.id); - (*itemStatus) = itemScene.getStatusValues(); + (*itemStatus) = itemScene.getStatusCompressedValues(); nbItems++; itemAABox++; @@ -154,7 +154,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch.setPipeline(getDrawItemBoundsPipeline()); AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); - glm::vec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const GLfloat*) (itemAABox + i)); @@ -167,7 +167,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const GLfloat*) (itemAABox + i)); batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); - batch._glUniform4fv(_drawItemStatusValueLoc, 1, (const GLfloat*) (itemStatus + i)); + batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const GLint*) (itemStatus + i)); batch.draw(gpu::TRIANGLES, 24, 0); } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 7de1e6650c..ca56f00960 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -53,12 +53,14 @@ void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { (*this)[ItemFilter::Builder::transparentShape().withLayered()]; } -void Item::Status::getValues(glm::vec4& values) { +const Item::Status::Value Item::Status::Value::INVALID{ std::numeric_limits::min(), std::numeric_limits::min() }; + +void Item::Status::getCompressedValues(glm::ivec4& values) { for (int i = 0; i < values.length(); i++) { if (i < _values.size()) { - values[i] = _values[i]() / 256.0f; + values[i] = _values[i]().getRaw(); } else { - values[i] = -1.0f; + values[i] = Value::INVALID.getRaw(); } } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 9b459e0f3e..5b66f8fcf9 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -200,14 +201,27 @@ public: // This is Used for monitoring and dynamically adjust the quality class Status { public: - typedef unsigned char Value; + class Value { + short _x = 0; + short _y = 0; + Value(short x, short y) : _x(x), _y(y) {} + public: + const static Value INVALID; // Invlaid value meanss the status won't show + + Value(float x, float y = 1.0f) { setX(x); setY(y); } + void setX(float x) { _x = std::numeric_limits::max() * std::max(std::min(x, 1.0f), -1.0f); } + void setY(float y) { _y = std::numeric_limits::max() * std::max(std::min(y, 1.0f), -1.0f); } + + int getRaw() const { return *((const int*) this); } + }; + typedef std::function Getter; typedef std::vector Getters; Getters _values; - void addGetter(Getter& getter) { _values.push_back(getter); } - void getValues(glm::vec4& values); + void addGetter(const Getter& getter) { _values.push_back(getter); } + void getCompressedValues(glm::ivec4& values); }; typedef std::shared_ptr StatusPointer; @@ -233,7 +247,15 @@ public: // Status interface is local to the base class const StatusPointer& getStatus() const { return _status; } - void addStatusGetter(Status::Getter& getter) { if (!_status) { _status.reset(new Status());} _status->addGetter(getter); } + void addStatusGetter(const Status::Getter& getter) { if (!_status) { _status.reset(new Status());} _status->addGetter(getter); } + void addStatusGetters(const Status::Getters& getters) { + if (!_status) { + _status.reset(new Status()); + } + for (auto& g : getters) { + _status->addGetter(g); + } + } protected: StatusPointer _status; @@ -270,7 +292,7 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } - glm::vec4 getStatusValues() const { glm::vec4 values(-1.f); auto& status = getStatus(); if (status) { status->getValues(values); }; return values; } + glm::ivec4 getStatusCompressedValues() const { glm::ivec4 values(Status::Value::INVALID.getRaw()); auto& status = getStatus(); if (status) { status->getCompressedValues(values); }; return values; } protected: PayloadPointer _payload; diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index cf9e3a5429..dda528bc51 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -20,12 +20,12 @@ varying vec4 varColor; uniform vec3 inBoundPos; uniform vec3 inBoundDim; -uniform vec4 inStatus; +uniform ivec4 inStatus; vec3 paintRainbow(float nv) { float v = nv * 5.f; if ( v < 0.f ) - return vec3(1.f, 0.f, 0.f); + return vec3(0.f, 0.f, 0.f); else if ( v < 1.f) return vec3(1.f, v, 0.f); else if ( v < 2.f) @@ -37,11 +37,18 @@ vec3 paintRainbow(float nv) { else if ( v < 5.f) return vec3((v-4.f), 0.f, 1.f ); else - return vec3(1.f, 0.f, 1.f); + return vec3(1.f, 1.f, 1.f); +} + +vec2 unpackStatus(uint v) { + // return unpackSnorm2x16(uint(packed)); + return vec2(clamp((float(v & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0), + clamp((float((v >> 16) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0)); } void main(void) { - vec2 ICON_PIXEL_SIZE = vec2(10, 10); + const vec2 ICON_PIXEL_SIZE = vec2(10, 10); + const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2); const int NUM_VERTICES = 6; const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES]( vec4(-1.0, -1.0, 0.0, 1.0), @@ -52,52 +59,43 @@ void main(void) { vec4(1.0, 1.0, 0.0, 1.0) ); + // anchor point in clip space vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0); TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$> - - int notifNum = gl_VertexID / NUM_VERTICES; - int twoTriID = gl_VertexID - notifNum * NUM_VERTICES; - vec4 pos = UNIT_QUAD[twoTriID]; - bool isPixel = false; - // Use the status for showing a color ? + // Which icon are we dealing with ? + int iconNum = gl_VertexID / NUM_VERTICES; + + // if invalid, just kill + if (inStatus[iconNum] == 0x80008000) { + gl_Position = anchorPoint; + varColor = vec4(1.0); + return; + } + + // unpack to get x and y satus + vec2 iconStatus = unpackStatus(uint(inStatus[iconNum])); + + // Use the status for showing a color + varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0); + // Also changes the size of the notification - if(notifNum == 0) { - varColor = vec4(paintRainbow(inStatus.x), 1.0); - if(inStatus.x == -1) { - isPixel = true; - } - } else if(notifNum == 1) { - varColor = vec4(paintRainbow(inStatus.y), 1.0); - if(inStatus.y == -1) { - isPixel = true; - } - } else if(notifNum == 2) { - varColor = vec4(paintRainbow(inStatus.z), 1.0); - if(inStatus.z == -1) { - isPixel = true; - } - } else { - varColor = vec4(paintRainbow(inStatus.w), 1.0); - if(inStatus.w == -1) { - isPixel = true; - } - } + vec2 iconScale = ICON_PIXEL_SIZE; + iconScale = max(vec2(1, 1), (iconScale * iconStatus.x)); - if(isPixel) { - ICON_PIXEL_SIZE = vec2(1, 1); - } + //Offset icon to the right based on the iconNum + vec2 offset = vec2(iconNum * (ICON_PIXEL_SIZE.x + MARGIN_PIXEL_SIZE.x), 0); + + // Final position in pixel space + int twoTriID = gl_VertexID - iconNum * NUM_VERTICES; + vec4 pos = UNIT_QUAD[twoTriID]; + vec2 quadPixelPos = offset.xy + pos.xy * 0.5 * iconScale; vec4 viewport; <$transformCameraViewport(cam, viewport)$>; - vec2 clipIconSize = vec2(ICON_PIXEL_SIZE.x / viewport.z, ICON_PIXEL_SIZE.y / viewport.w); - - //Offset size in pixels - float offset = 3.5f; - pos.x += offset * notifNum; - - gl_Position = anchorPoint + (anchorPoint.w * vec4(pos.xy * clipIconSize, 0.0, 0.0)); + vec2 pixelToClip = vec2(2.0 / viewport.z, 2.0 / viewport.w); + gl_Position = anchorPoint + (anchorPoint.w * vec4(quadPixelPos * pixelToClip, 0.0, 0.0)); } \ No newline at end of file From bf052162bba15f0ec98eddc2595e0e2d02f1f3b0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 15:53:02 -0700 Subject: [PATCH 17/39] improvment ? --- .../src/RenderableModelEntityItem.cpp | 36 ++++++++----------- .../render/src/render/drawItemStatus.slv | 4 +-- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3a8857eaa3..5945511584 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -167,6 +167,17 @@ namespace render { } } +void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item::Status::Getters& statusGetters) { + statusGetters.push_back([entity] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); + return render::Item::Status::Value((delta / (0.01f * USECS_PER_SECOND)), 1.0f); + }); + statusGetters.push_back([entity] () -> render::Item::Status::Value { + quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); + return render::Item::Status::Value((delta / (0.02f * USECS_PER_SECOND)), 0.5f); + }); +} + bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { _myMetaItem = scene->allocateID(); @@ -177,20 +188,9 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p pendingChanges.resetItem(_myMetaItem, renderPayload); if (_model) { - // return _model->addToScene(scene, pendingChanges); - render::Item::Status::Getters statusGetters; - statusGetters.push_back([this] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - this->getLastEditedFromRemote(); - return render::Item::Status::Value((delta < 0.1f * USECS_PER_SECOND), 1.0f); - }); - statusGetters.push_back([this] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - this->getLastBroadcast(); - return render::Item::Status::Value((delta < 0.2f * USECS_PER_SECOND), 0.5f); - }); - + makeEntityItemStatusGetters(this, statusGetters); return _model->addToScene(scene, pendingChanges, statusGetters); - } return true; @@ -227,17 +227,9 @@ void RenderableModelEntityItem::render(RenderArgs* args) { render::PendingChanges pendingChanges; if (_model->needsFixupInScene()) { _model->removeFromScene(scene, pendingChanges); - - render::Item::Status::Getters statusGetters; - statusGetters.push_back([this] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - this->getLastEditedFromRemote(); - return render::Item::Status::Value((delta < 0.1f * USECS_PER_SECOND), 1.0f); - }); - statusGetters.push_back([this] () -> render::Item::Status::Value { - quint64 delta = usecTimestampNow() - this->getLastBroadcast(); - return render::Item::Status::Value((delta < 0.2f * USECS_PER_SECOND), 0.5f); - }); + render::Item::Status::Getters statusGetters; + makeEntityItemStatusGetters(this, statusGetters); _model->addToScene(scene, pendingChanges, statusGetters); } scene->enqueuePendingChanges(pendingChanges); diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index dda528bc51..58637ae909 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -40,7 +40,7 @@ vec3 paintRainbow(float nv) { return vec3(1.f, 1.f, 1.f); } -vec2 unpackStatus(uint v) { +vec2 unpackStatus(int v) { // return unpackSnorm2x16(uint(packed)); return vec2(clamp((float(v & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0), clamp((float((v >> 16) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0)); @@ -76,7 +76,7 @@ void main(void) { } // unpack to get x and y satus - vec2 iconStatus = unpackStatus(uint(inStatus[iconNum])); + vec2 iconStatus = unpackStatus(inStatus[iconNum]); // Use the status for showing a color varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0); From 79be37f78fd8487d5a02b62be7e9287ee91ead21 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 16:00:56 -0700 Subject: [PATCH 18/39] improvment ? --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 3 ++- libraries/render/src/render/drawItemStatus.slv | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5945511584..3b801fd9f6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -174,7 +174,8 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item }); statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); - return render::Item::Status::Value((delta / (0.02f * USECS_PER_SECOND)), 0.5f); + // return render::Item::Status::Value((delta / (0.02f * USECS_PER_SECOND)), 0.5f); + return render::Item::Status::Value(1.0f, 0.5f); }); } diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 58637ae909..4eff5c71d7 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -42,8 +42,8 @@ vec3 paintRainbow(float nv) { vec2 unpackStatus(int v) { // return unpackSnorm2x16(uint(packed)); - return vec2(clamp((float(v & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0), - clamp((float((v >> 16) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0)); + return vec2(clamp((float(uint(v) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0), + clamp((float((uint(v) >> 16) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0)); } void main(void) { From dcd61fd417bb9670c54c0798c8e50152fdd969e8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 16:13:54 -0700 Subject: [PATCH 19/39] improvment ? --- libraries/render/src/render/drawItemStatus.slv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index 4eff5c71d7..eb56095d13 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -42,8 +42,8 @@ vec3 paintRainbow(float nv) { vec2 unpackStatus(int v) { // return unpackSnorm2x16(uint(packed)); - return vec2(clamp((float(uint(v) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0), - clamp((float((uint(v) >> 16) & 0xFFFF) - 32727.0) / 32727.0, -1.0, 1.0)); + return vec2(clamp(float((v & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), + clamp(float(((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); } void main(void) { From 0c0b8dbbc15c0255abc06453a596ca1b9e17b8f1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 16:19:13 -0700 Subject: [PATCH 20/39] add stats for elements and entities per incoming packet --- interface/src/ui/OctreeStatsDialog.cpp | 28 ++++++++++++++++---- interface/src/ui/OctreeStatsDialog.h | 2 ++ libraries/entities/src/EntityItem.cpp | 2 ++ libraries/entities/src/EntityTreeElement.cpp | 2 ++ libraries/octree/src/Octree.h | 2 ++ libraries/octree/src/OctreeRenderer.cpp | 15 +++++++++-- libraries/octree/src/OctreeRenderer.h | 7 +++++ 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index c8784f69b8..12ed3cf36f 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -52,6 +52,8 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _localElements = AddStatItem("Local Elements"); _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); + + _entityPackets = AddStatItem("Entity Packets"); _entityUpdateTime = AddStatItem("Entity Update Time"); _entityUpdates = AddStatItem("Entity Updates"); @@ -207,11 +209,27 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); + // Entity Edits update time + label = _labels[_entityPackets]; + auto entities = Application::getInstance()->getEntities(); + auto entitiesTree = entities->getTree(); + auto averageElementsPerPacket = entities->getAverageElementsPerPacket(); + auto averageEntitiesPerPacket = entities->getAverageEntitiesPerPacket(); + + QString averageElementsPerPacketString = locale.toString(averageElementsPerPacket); + QString averageEntitiesPerPacketString = locale.toString(averageEntitiesPerPacket); + + statsValue.str(""); + statsValue << + "Elements: " << qPrintable(averageEntitiesPerPacketString) << " per packet / " << + "Entities: " << qPrintable(averageEntitiesPerPacketString) << " per packet"; + + label->setText(statsValue.str().c_str()); + // Entity Edits update time label = _labels[_entityUpdateTime]; - auto entities = Application::getInstance()->getEntities()->getTree(); - auto averageEditDelta = entities->getAverageEditDeltas(); - auto maxEditDelta = entities->getMaxEditDelta(); + auto averageEditDelta = entitiesTree->getAverageEditDeltas(); + auto maxEditDelta = entitiesTree->getMaxEditDelta(); QString averageEditDeltaString = locale.toString((uint)averageEditDelta); QString maxEditDeltaString = locale.toString((uint)maxEditDelta); @@ -225,8 +243,8 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Entity Edits label = _labels[_entityUpdates]; - auto totalTrackedEdits = entities->getTotalTrackedEdits(); - auto bytesPerEdit = entities->getAverageEditBytes(); + auto totalTrackedEdits = entitiesTree->getTotalTrackedEdits(); + auto bytesPerEdit = entitiesTree->getAverageEditBytes(); // track our updated per second const quint64 SAMPLING_WINDOW = USECS_PER_SECOND / SAMPLES_PER_SECOND; diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index acbf766510..4c59744af2 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -66,6 +66,8 @@ private: int _entityUpdateTime; int _entityUpdates; + int _entityPackets; + const int SAMPLES_PER_SECOND = 10; SimpleMovingAverage _averageUpdatesPerSecond; quint64 _lastWindowAt = 0; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 511238efca..5e129365fe 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -346,6 +346,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef return 0; } + args.entitiesPerPacket++; + // Header bytes // object ID [16 bytes] // ByteCountCoded(type code) [~1 byte] diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 4bc81e1da6..41c0529b80 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -702,6 +702,8 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int int bytesRead = 0; uint16_t numberOfEntities = 0; int expectedBytesPerEntity = EntityItem::expectedBytes(); + + args.elementsPerPacket++; if (bytesLeftToRead >= (int)sizeof(numberOfEntities)) { // read our entities in.... diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 6eeb423ddd..f1d32aa390 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -195,6 +195,8 @@ public: SharedNodePointer sourceNode; bool wantImportProgress; PacketVersion bitstreamVersion; + int elementsPerPacket = 0; + int entitiesPerPacket = 0; ReadBitstreamToTreeParams( bool includeColor = WANT_COLOR, diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 7852f1d4b4..f4c5491678 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -101,6 +101,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar sequence, flightTime, packetLength, dataBytes); } + int elementsPerPacket = 0; + int entitiesPerPacket = 0; + int subsection = 1; while (dataBytes > 0) { if (packetIsCompressed) { @@ -139,13 +142,21 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar qCDebug(octree) << "OctreeRenderer::processDatagram() ******* END _tree->readBitstreamToTree()..."; } _tree->unlock(); - + dataBytes -= sectionLength; dataAt += sectionLength; + + elementsPerPacket += args.elementsPerPacket; + entitiesPerPacket += args.entitiesPerPacket; + } + subsection++; } - subsection++; + _elementsPerPacket.updateAverage(elementsPerPacket); + _entitiesPerPacket.updateAverage(entitiesPerPacket); } + + } bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 98026b732c..9a70e0923e 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -61,12 +61,19 @@ public: /// clears the tree virtual void clear(); + float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); } + float getAverageEntitiesPerPacket() const { return _entitiesPerPacket.getAverage(); } + protected: virtual Octree* createTree() = 0; Octree* _tree; bool _managedTree; ViewFrustum* _viewFrustum; + + SimpleMovingAverage _elementsPerPacket; + SimpleMovingAverage _entitiesPerPacket; + }; #endif // hifi_OctreeRenderer_h From 8916dd205664761e2052a09562eade21c2e0f889 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 17:00:35 -0700 Subject: [PATCH 21/39] add stats for elements and entities per second --- interface/src/ui/OctreeStatsDialog.cpp | 25 ++++++++++++++++++++----- interface/src/ui/OctreeStatsDialog.h | 3 ++- libraries/octree/src/OctreeRenderer.cpp | 23 +++++++++++++++++++++-- libraries/octree/src/OctreeRenderer.h | 9 +++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 12ed3cf36f..ce9034ce2d 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -53,7 +53,8 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); - _entityPackets = AddStatItem("Entity Packets"); + _processedPacketsElements = AddStatItem("Processed Packets Elements"); + _processedPacketsEntities = AddStatItem("Processed Packets Entities"); _entityUpdateTime = AddStatItem("Entity Update Time"); _entityUpdates = AddStatItem("Entity Updates"); @@ -209,20 +210,34 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); - // Entity Edits update time - label = _labels[_entityPackets]; + // Processed Entities Related stats auto entities = Application::getInstance()->getEntities(); auto entitiesTree = entities->getTree(); + + // Processed Packets Elements auto averageElementsPerPacket = entities->getAverageElementsPerPacket(); auto averageEntitiesPerPacket = entities->getAverageEntitiesPerPacket(); + auto averageElementsPerSecond = entities->getAverageElementsPerSecond(); + auto averageEntitiesPerSecond = entities->getAverageEntitiesPerSecond(); QString averageElementsPerPacketString = locale.toString(averageElementsPerPacket); QString averageEntitiesPerPacketString = locale.toString(averageEntitiesPerPacket); + QString averageElementsPerSecondString = locale.toString(averageElementsPerSecond); + QString averageEntitiesPerSecondString = locale.toString(averageEntitiesPerSecond); + label = _labels[_processedPacketsElements]; statsValue.str(""); statsValue << - "Elements: " << qPrintable(averageEntitiesPerPacketString) << " per packet / " << - "Entities: " << qPrintable(averageEntitiesPerPacketString) << " per packet"; + "" << qPrintable(averageElementsPerPacketString) << " per packet / " << + "" << qPrintable(averageElementsPerSecondString) << " per second"; + + label->setText(statsValue.str().c_str()); + + label = _labels[_processedPacketsEntities]; + statsValue.str(""); + statsValue << + "" << qPrintable(averageEntitiesPerPacketString) << " per packet / " << + "" << qPrintable(averageEntitiesPerSecondString) << " per second"; label->setText(statsValue.str().c_str()); diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 4c59744af2..9b0b1ad90a 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -66,7 +66,8 @@ private: int _entityUpdateTime; int _entityUpdates; - int _entityPackets; + int _processedPacketsElements; + int _processedPacketsEntities; const int SAMPLES_PER_SECOND = 10; SimpleMovingAverage _averageUpdatesPerSecond; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index f4c5491678..e77f652932 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -149,14 +149,33 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar elementsPerPacket += args.elementsPerPacket; entitiesPerPacket += args.entitiesPerPacket; + _elementsInLastWindow += args.elementsPerPacket; + _entitiesInLastWindow += args.entitiesPerPacket; + } subsection++; } _elementsPerPacket.updateAverage(elementsPerPacket); _entitiesPerPacket.updateAverage(entitiesPerPacket); + + quint64 now = usecTimestampNow(); + if (_lastWindowAt == 0) { + _lastWindowAt = now; + } + quint64 sinceLastWindow = now - _lastWindowAt; + + const quint64 USECS_PER_SECOND = 1000 * 1000; + if (sinceLastWindow > USECS_PER_SECOND) { + float elementsPerSecondInWindow = (float)_elementsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); + float entitiesPerSecondInWindow = (float)_entitiesInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); + _elementsPerSecond.updateAverage(elementsPerSecondInWindow); + _entitiesPerSecond.updateAverage(entitiesPerSecondInWindow); + + _lastWindowAt = now; + _elementsInLastWindow = 0; + _entitiesInLastWindow = 0; + } } - - } bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 9a70e0923e..de0f4dc1bb 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -63,6 +63,9 @@ public: float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); } float getAverageEntitiesPerPacket() const { return _entitiesPerPacket.getAverage(); } + + float getAverageElementsPerSecond() const { return _elementsPerSecond.getAverage(); } + float getAverageEntitiesPerSecond() const { return _entitiesPerSecond.getAverage(); } protected: virtual Octree* createTree() = 0; @@ -73,6 +76,12 @@ protected: SimpleMovingAverage _elementsPerPacket; SimpleMovingAverage _entitiesPerPacket; + SimpleMovingAverage _elementsPerSecond; + SimpleMovingAverage _entitiesPerSecond; + + quint64 _lastWindowAt = 0; + int _elementsInLastWindow = 0; + int _entitiesInLastWindow = 0; }; From a54cf6706470b28b10e7feb539cc5a254bd055d4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 17:28:53 -0700 Subject: [PATCH 22/39] add stats for processing time per packet --- interface/src/ui/OctreeStatsDialog.cpp | 19 +++++++++++++++++++ interface/src/ui/OctreeStatsDialog.h | 1 + libraries/octree/src/OctreeRenderer.cpp | 16 ++++++++++++++++ libraries/octree/src/OctreeRenderer.h | 8 ++++++++ 4 files changed, 44 insertions(+) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index ce9034ce2d..4c95e7a68a 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -55,6 +55,8 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _processedPacketsElements = AddStatItem("Processed Packets Elements"); _processedPacketsEntities = AddStatItem("Processed Packets Entities"); + _processedPacketsTiming = AddStatItem("Processed Packets Timing"); + _entityUpdateTime = AddStatItem("Entity Update Time"); _entityUpdates = AddStatItem("Entity Updates"); @@ -220,11 +222,19 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { auto averageElementsPerSecond = entities->getAverageElementsPerSecond(); auto averageEntitiesPerSecond = entities->getAverageEntitiesPerSecond(); + auto averageWaitLockPerPacket = entities->getAverageWaitLockPerPacket(); + auto averageUncompressPerPacket = entities->getAverageUncompressPerPacket(); + auto averageReadBitstreamPerPacket = entities->getAverageReadBitstreamPerPacket(); + QString averageElementsPerPacketString = locale.toString(averageElementsPerPacket); QString averageEntitiesPerPacketString = locale.toString(averageEntitiesPerPacket); QString averageElementsPerSecondString = locale.toString(averageElementsPerSecond); QString averageEntitiesPerSecondString = locale.toString(averageEntitiesPerSecond); + QString averageWaitLockPerPacketString = locale.toString(averageWaitLockPerPacket); + QString averageUncompressPerPacketString = locale.toString(averageUncompressPerPacket); + QString averageReadBitstreamPerPacketString = locale.toString(averageReadBitstreamPerPacket); + label = _labels[_processedPacketsElements]; statsValue.str(""); statsValue << @@ -241,6 +251,15 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { label->setText(statsValue.str().c_str()); + label = _labels[_processedPacketsTiming]; + statsValue.str(""); + statsValue << + "Lock Wait:" << qPrintable(averageWaitLockPerPacketString) << " (usecs) / " << + "Uncompress:" << qPrintable(averageUncompressPerPacketString) << " (usecs) / " << + "Process:" << qPrintable(averageReadBitstreamPerPacketString) << " (usecs)"; + + label->setText(statsValue.str().c_str()); + // Entity Edits update time label = _labels[_entityUpdateTime]; auto averageEditDelta = entitiesTree->getAverageEditDeltas(); diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 9b0b1ad90a..986080de56 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -68,6 +68,7 @@ private: int _entityUpdates; int _processedPacketsElements; int _processedPacketsEntities; + int _processedPacketsTiming; const int SAMPLES_PER_SECOND = 10; SimpleMovingAverage _averageUpdatesPerSecond; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index e77f652932..5ffc22d5ee 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -104,6 +104,10 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar int elementsPerPacket = 0; int entitiesPerPacket = 0; + quint64 totalWaitingForLock = 0; + quint64 totalUncompress = 0; + quint64 totalReadBitsteam = 0; + int subsection = 1; while (dataBytes > 0) { if (packetIsCompressed) { @@ -123,7 +127,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar // ask the VoxelTree to read the bitstream into the tree ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, sourceUUID, sourceNode, false, packetVersion); + quint64 startLock = usecTimestampNow(); _tree->lockForWrite(); + quint64 startUncompress = usecTimestampNow(); OctreePacketData packetData(packetIsCompressed); packetData.loadFinalizedContent(dataAt, sectionLength); if (extraDebugging) { @@ -137,7 +143,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar if (extraDebugging) { qCDebug(octree) << "OctreeRenderer::processDatagram() ******* START _tree->readBitstreamToTree()..."; } + quint64 startReadBitsteam = usecTimestampNow(); _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); + quint64 endReadBitsteam = usecTimestampNow(); if (extraDebugging) { qCDebug(octree) << "OctreeRenderer::processDatagram() ******* END _tree->readBitstreamToTree()..."; } @@ -152,11 +160,19 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar _elementsInLastWindow += args.elementsPerPacket; _entitiesInLastWindow += args.entitiesPerPacket; + totalWaitingForLock += (startUncompress - startLock); + totalUncompress += (startReadBitsteam - startUncompress); + totalReadBitsteam += (endReadBitsteam - startReadBitsteam); + } subsection++; } _elementsPerPacket.updateAverage(elementsPerPacket); _entitiesPerPacket.updateAverage(entitiesPerPacket); + + _waitLockPerPacket.updateAverage(totalWaitingForLock); + _uncompressPerPacket.updateAverage(totalUncompress); + _readBitstreamPerPacket.updateAverage(totalReadBitsteam); quint64 now = usecTimestampNow(); if (_lastWindowAt == 0) { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index de0f4dc1bb..894e5c2355 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -66,6 +66,10 @@ public: float getAverageElementsPerSecond() const { return _elementsPerSecond.getAverage(); } float getAverageEntitiesPerSecond() const { return _entitiesPerSecond.getAverage(); } + + float getAverageWaitLockPerPacket() const { return _waitLockPerPacket.getAverage(); } + float getAverageUncompressPerPacket() const { return _uncompressPerPacket.getAverage(); } + float getAverageReadBitstreamPerPacket() const { return _readBitstreamPerPacket.getAverage(); } protected: virtual Octree* createTree() = 0; @@ -79,6 +83,10 @@ protected: SimpleMovingAverage _elementsPerSecond; SimpleMovingAverage _entitiesPerSecond; + SimpleMovingAverage _waitLockPerPacket; + SimpleMovingAverage _uncompressPerPacket; + SimpleMovingAverage _readBitstreamPerPacket; + quint64 _lastWindowAt = 0; int _elementsInLastWindow = 0; int _entitiesInLastWindow = 0; From 0c55130548f2d0dbdb28135d23f26d9e92808c41 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 2 Jul 2015 17:31:29 -0700 Subject: [PATCH 23/39] maybe i have solved the passing of the status --- examples/utilities/tools/renderEngineDebug.js | 2 +- .../src/RenderableModelEntityItem.cpp | 7 +- libraries/render/src/render/Scene.cpp | 2 +- libraries/render/src/render/Scene.h | 10 +-- .../render/src/render/drawItemStatus.slv | 68 ++++++++++--------- 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index d337290927..d50a9c545c 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -10,7 +10,7 @@ Script.include("cookies.js"); -var panel = new Panel(10, 800); +var panel = new Panel(10, 100); panel.newSlider("Num Feed Opaques", 0, 1000, function(value) { }, diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3b801fd9f6..5870b22a04 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -170,12 +170,13 @@ namespace render { void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item::Status::Getters& statusGetters) { statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); - return render::Item::Status::Value((delta / (0.01f * USECS_PER_SECOND)), 1.0f); + float ndelta = (delta / (0.2f * USECS_PER_SECOND)); + return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.01f : 0.5f)); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); - // return render::Item::Status::Value((delta / (0.02f * USECS_PER_SECOND)), 0.5f); - return render::Item::Status::Value(1.0f, 0.5f); + float ndelta = (delta / (0.4f * USECS_PER_SECOND)); + return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.01f : 0.5f)); }); } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index ca56f00960..1ed66e4912 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -53,7 +53,7 @@ void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { (*this)[ItemFilter::Builder::transparentShape().withLayered()]; } -const Item::Status::Value Item::Status::Value::INVALID{ std::numeric_limits::min(), std::numeric_limits::min() }; +const Item::Status::Value Item::Status::Value::INVALID = Item::Status::Value(); void Item::Status::getCompressedValues(glm::ivec4& values) { for (int i = 0; i < values.length(); i++) { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 5b66f8fcf9..b846c60cfe 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -202,15 +202,15 @@ public: class Status { public: class Value { - short _x = 0; - short _y = 0; - Value(short x, short y) : _x(x), _y(y) {} + unsigned short _x = 0xFFFF; + unsigned short _y = 0xFFFF; + Value() {} public: const static Value INVALID; // Invlaid value meanss the status won't show Value(float x, float y = 1.0f) { setX(x); setY(y); } - void setX(float x) { _x = std::numeric_limits::max() * std::max(std::min(x, 1.0f), -1.0f); } - void setY(float y) { _y = std::numeric_limits::max() * std::max(std::min(y, 1.0f), -1.0f); } + void setX(float x) { _x = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(x, 1.0f), -1.0f)); } + void setY(float y) { _y = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(y, 1.0f), -1.0f)); } int getRaw() const { return *((const int*) this); } }; diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index eb56095d13..f99bf006a4 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -1,27 +1,27 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// drawItemStatus.slv -// vertex shader -// -// Created by Sam Gateau on 6/30/2015. -// 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 gpu/Transform.slh@> - -<$declareStandardTransform()$> - -varying vec4 varColor; - -uniform vec3 inBoundPos; -uniform vec3 inBoundDim; -uniform ivec4 inStatus; - +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemStatus.slv +// vertex shader +// +// Created by Sam Gateau on 6/30/2015. +// 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 gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec4 varColor; + +uniform vec3 inBoundPos; +uniform vec3 inBoundDim; +uniform ivec4 inStatus; + vec3 paintRainbow(float nv) { float v = nv * 5.f; if ( v < 0.f ) @@ -38,14 +38,16 @@ vec3 paintRainbow(float nv) { return vec3((v-4.f), 0.f, 1.f ); else return vec3(1.f, 1.f, 1.f); -} - -vec2 unpackStatus(int v) { - // return unpackSnorm2x16(uint(packed)); - return vec2(clamp(float((v & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), - clamp(float(((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); -} - +} + +vec2 unpackStatus(int v) { + // return unpackSnorm2x16(uint(packed)); + // return vec2(clamp(float((v & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), + // clamp(float(((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); + return vec2(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), + clamp(float(int((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); +} + void main(void) { const vec2 ICON_PIXEL_SIZE = vec2(10, 10); const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2); @@ -69,7 +71,7 @@ void main(void) { int iconNum = gl_VertexID / NUM_VERTICES; // if invalid, just kill - if (inStatus[iconNum] == 0x80008000) { + if (inStatus[iconNum] == 0xFFFFFFFF) { gl_Position = anchorPoint; varColor = vec4(1.0); return; From 76ca093e052dd58c164d37cc45f21dce7b4a4317 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 18:12:03 -0700 Subject: [PATCH 24/39] something working ? --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5870b22a04..dc90a676fb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -176,7 +176,7 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); float ndelta = (delta / (0.4f * USECS_PER_SECOND)); - return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.01f : 0.5f)); + return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.3f : 0.9f)); }); } From e1530b3ce942fa2f19b730089d81fe5de02309ac Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 Jul 2015 18:15:24 -0700 Subject: [PATCH 25/39] added a FIXME STUTTER note --- libraries/octree/src/OctreeRenderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 5ffc22d5ee..6fa3f47120 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -128,6 +128,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, sourceUUID, sourceNode, false, packetVersion); quint64 startLock = usecTimestampNow(); + + // FIXME STUTTER - there may be an opportunity to bump this lock outside of the + // loop to reduce the amount of locking/unlocking we're doing _tree->lockForWrite(); quint64 startUncompress = usecTimestampNow(); OctreePacketData packetData(packetIsCompressed); From e3c06a30a11f0a841c54539aae8ddcff46ad2624 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 2 Jul 2015 19:29:09 -0700 Subject: [PATCH 26/39] removing dead code --- libraries/render/src/render/DrawStatus.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index b73df702be..3c92e8f0b2 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -143,13 +143,6 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); -/* if (!_drawItemFormat) { - _drawItemFormat.reset(new gpu::Stream::Format()); - _drawItemFormat->setAttribute(0, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0, gpu::Stream::PER_INSTANCE); - _drawItemFormat->setAttribute(1, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), sizeof(glm::vec3), gpu::Stream::PER_INSTANCE); - } -*/ - // bind the one gpu::Pipeline we need batch.setPipeline(getDrawItemBoundsPipeline()); From 29a7584ee6af7c5a1d6981eab2aeee651b306652 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Jul 2015 11:29:59 -0700 Subject: [PATCH 27/39] remove dead code --- assignment-client/src/octree/OctreeServer.cpp | 41 - interface/src/ui/ApplicationCompositor.cpp | 5 - interface/src/ui/ApplicationOverlay.cpp | 3 - libraries/entities/src/EntityItem.cpp | 3 - libraries/entities/src/EntityTree.cpp | 3 - libraries/octree/src/Octree.cpp | 10 - libraries/octree/src/OctreeElement.cpp | 770 ------------------ libraries/octree/src/OctreeElement.h | 48 -- .../render-utils/src/RenderDeferredTask.cpp | 1 - libraries/render/src/render/DrawTask.cpp | 2 - 10 files changed, 886 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 06fb5c4f47..72f2567809 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -760,47 +760,6 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url statsString += QString(" Total: %1 nodes\r\n") .arg(locale.toString((uint)checkSum).rightJustified(16, ' ')); -#ifdef BLENDED_UNION_CHILDREN - statsString += "\r\n"; - statsString += "OctreeElement Children Encoding Statistics...\r\n"; - - statsString += QString().sprintf(" Single or No Children: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getSingleChildrenCount(), - ((float)OctreeElement::getSingleChildrenCount() / (float)nodeCount) * AS_PERCENT)); - statsString += QString().sprintf(" Two Children as Offset: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getTwoChildrenOffsetCount(), - ((float)OctreeElement::getTwoChildrenOffsetCount() / (float)nodeCount) * AS_PERCENT)); - statsString += QString().sprintf(" Two Children as External: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getTwoChildrenExternalCount(), - ((float)OctreeElement::getTwoChildrenExternalCount() / (float)nodeCount) * AS_PERCENT); - statsString += QString().sprintf(" Three Children as Offset: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getThreeChildrenOffsetCount(), - ((float)OctreeElement::getThreeChildrenOffsetCount() / (float)nodeCount) * AS_PERCENT); - statsString += QString().sprintf(" Three Children as External: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getThreeChildrenExternalCount(), - ((float)OctreeElement::getThreeChildrenExternalCount() / (float)nodeCount) * AS_PERCENT); - statsString += QString().sprintf(" Children as External Array: %10.llu nodes (%5.2f%%)\r\n", - OctreeElement::getExternalChildrenCount(), - ((float)OctreeElement::getExternalChildrenCount() / (float)nodeCount) * AS_PERCENT); - - checkSum = OctreeElement::getSingleChildrenCount() + - OctreeElement::getTwoChildrenOffsetCount() + OctreeElement::getTwoChildrenExternalCount() + - OctreeElement::getThreeChildrenOffsetCount() + OctreeElement::getThreeChildrenExternalCount() + - OctreeElement::getExternalChildrenCount(); - - statsString += " ----------------\r\n"; - statsString += QString().sprintf(" Total: %10.llu nodes\r\n", checkSum); - statsString += QString().sprintf(" Expected: %10.lu nodes\r\n", nodeCount); - - statsString += "\r\n"; - statsString += "In other news....\r\n"; - - statsString += QString().sprintf("could store 4 children internally: %10.llu nodes\r\n", - OctreeElement::getCouldStoreFourChildrenInternally()); - statsString += QString().sprintf("could NOT store 4 children internally: %10.llu nodes\r\n", - OctreeElement::getCouldNotStoreFourChildrenInternally()); -#endif - statsString += "\r\n\r\n"; statsString += "\r\n"; statsString += ""; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 4c3a2a44c1..dafa332d53 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -25,18 +25,13 @@ // Used to animate the magnification windows -static const float MAG_SPEED = 0.08f; static const quint64 MSECS_TO_USECS = 1000ULL; static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; -static const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; static const float reticleSize = TWO_PI / 100.0f; -static const float CONNECTION_STATUS_BORDER_COLOR[] = { 1.0f, 0.0f, 0.0f }; -static const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; - static const float CURSOR_PIXEL_SIZE = 32.0f; static const float MOUSE_PITCH_RANGE = 1.0f * PI; static const float MOUSE_YAW_RANGE = 0.5f * TWO_PI; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 63f68b86ce..e7d220893f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -36,9 +36,6 @@ #include "ui/Stats.h" #include "ui/AvatarInputs.h" -const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; -const int AUDIO_METER_GAP = 5; -const int MUTE_ICON_PADDING = 10; const vec4 CONNECTION_STATUS_BORDER_COLOR{ 1.0f, 0.0f, 0.0f, 0.8f }; const float CONNECTION_STATUS_BORDER_LINE_WIDTH = 4.0f; static const float ORTHO_NEAR_CLIP = -10000; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 6559289e33..d63a7243e7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -30,9 +30,6 @@ #include "EntityActionFactoryInterface.h" -const quint64 DEFAULT_SIMULATOR_CHANGE_LOCKOUT_PERIOD = (quint64)(0.2f * USECS_PER_SECOND); -const quint64 MAX_SIMULATOR_CHANGE_LOCKOUT_PERIOD = 2 * USECS_PER_SECOND; - bool EntityItem::_sendPhysicsUpdates = true; int EntityItem::_maxActionsDataSize = 800; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a341051986..d6f71ebd56 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -26,9 +26,6 @@ #include "LogHandler.h" -const quint64 SIMULATOR_CHANGE_LOCKOUT_PERIOD = (quint64)(0.2f * USECS_PER_SECOND); - - EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _fbxService(NULL), diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index adc2040b8a..7f421368d8 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -667,11 +667,6 @@ OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) co element = NULL; } delete[] octalCode; // cleanup memory -#ifdef HAS_AUDIT_CHILDREN - if (element) { - element->auditChildren("Octree::getOctreeElementAt()"); - } -#endif // def HAS_AUDIT_CHILDREN return element; } @@ -680,11 +675,6 @@ OctreeElement* Octree::getOctreeEnclosingElementAt(float x, float y, float z, fl OctreeElement* element = nodeForOctalCode(_rootElement, octalCode, NULL); delete[] octalCode; // cleanup memory -#ifdef HAS_AUDIT_CHILDREN - if (element) { - element->auditChildren("Octree::getOctreeElementAt()"); - } -#endif // def HAS_AUDIT_CHILDREN return element; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e09d5fb910..e11a11fc8e 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -71,19 +71,9 @@ void OctreeElement::init(unsigned char * octalCode) { _childrenExternal = false; -#ifdef BLENDED_UNION_CHILDREN - _children.external = NULL; - _singleChildrenCount++; -#endif _childrenCount[0]++; // default pointers to child nodes to NULL -#ifdef HAS_AUDIT_CHILDREN - for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { - _childrenArray[i] = NULL; - } -#endif // def HAS_AUDIT_CHILDREN - #ifdef SIMPLE_CHILD_ARRAY for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { _simpleChildArray[i] = NULL; @@ -218,9 +208,6 @@ void OctreeElement::deleteChildAtIndex(int childIndex) { _voxelNodeLeafCount++; } } -#ifdef HAS_AUDIT_CHILDREN - auditChildren("deleteChildAtIndex()"); -#endif // def HAS_AUDIT_CHILDREN } // does not delete the node! @@ -236,10 +223,6 @@ OctreeElement* OctreeElement::removeChildAtIndex(int childIndex) { _voxelNodeLeafCount++; } } - -#ifdef HAS_AUDIT_CHILDREN - auditChildren("removeChildAtIndex()"); -#endif // def HAS_AUDIT_CHILDREN return returnedChild; } @@ -255,60 +238,11 @@ bool OctreeElement::isParentOf(OctreeElement* possibleChild) const { return false; } - -#ifdef HAS_AUDIT_CHILDREN -void OctreeElement::auditChildren(const char* label) const { - bool auditFailed = false; - for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) { - OctreeElement* testChildNew = getChildAtIndex(childIndex); - OctreeElement* testChildOld = _childrenArray[childIndex]; - - if (testChildNew != testChildOld) { - auditFailed = true; - } - } - - const bool alwaysReport = false; // set this to true to get additional debugging - if (alwaysReport || auditFailed) { - qDebug("%s... auditChildren() %s <<<<", label, (auditFailed ? "FAILED" : "PASSED")); - qDebug(" _childrenExternal=%s", debug::valueOf(_childrenExternal)); - qDebug(" childCount=%d", getChildCount()); - - QDebug bitOutput = qDebug().nospace(); - bitOutput << " _childBitmask="; - outputBits(_childBitmask, bitOutput); - - - for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) { - OctreeElement* testChildNew = getChildAtIndex(childIndex); - OctreeElement* testChildOld = _childrenArray[childIndex]; - - qCebug("child at index %d... testChildOld=%p testChildNew=%p %s", - childIndex, testChildOld, testChildNew , - ((testChildNew != testChildOld) ? " DOES NOT MATCH <<<< BAD <<<<" : " - OK ") - ); - } - qDebug("%s... auditChildren() <<<< DONE <<<<", label); - } -} -#endif // def HAS_AUDIT_CHILDREN - - quint64 OctreeElement::_getChildAtIndexTime = 0; quint64 OctreeElement::_getChildAtIndexCalls = 0; quint64 OctreeElement::_setChildAtIndexTime = 0; quint64 OctreeElement::_setChildAtIndexCalls = 0; -#ifdef BLENDED_UNION_CHILDREN -quint64 OctreeElement::_singleChildrenCount = 0; -quint64 OctreeElement::_twoChildrenOffsetCount = 0; -quint64 OctreeElement::_twoChildrenExternalCount = 0; -quint64 OctreeElement::_threeChildrenOffsetCount = 0; -quint64 OctreeElement::_threeChildrenExternalCount = 0; -quint64 OctreeElement::_couldStoreFourChildrenInternally = 0; -quint64 OctreeElement::_couldNotStoreFourChildrenInternally = 0; -#endif - quint64 OctreeElement::_externalChildrenCount = 0; quint64 OctreeElement::_childrenCount[NUMBER_OF_CHILDREN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -341,319 +275,8 @@ OctreeElement* OctreeElement::getChildAtIndex(int childIndex) const { } break; } #endif // def SIMPLE_EXTERNAL_CHILDREN - -#ifdef BLENDED_UNION_CHILDREN - PerformanceWarning warn(false,"getChildAtIndex",false,&_getChildAtIndexTime,&_getChildAtIndexCalls); - OctreeElement* result = NULL; - int childCount = getChildCount(); - -#ifdef HAS_AUDIT_CHILDREN - const char* caseStr = NULL; -#endif - - switch (childCount) { - case 0: -#ifdef HAS_AUDIT_CHILDREN - caseStr = "0 child case"; -#endif - break; - case 1: { -#ifdef HAS_AUDIT_CHILDREN - caseStr = "1 child case"; -#endif - int indexOne = getNthBit(_childBitmask, 1); - if (indexOne == childIndex) { - result = _children.single; - } - } break; - case 2: { -#ifdef HAS_AUDIT_CHILDREN - caseStr = "2 child case"; -#endif - int indexOne = getNthBit(_childBitmask, 1); - int indexTwo = getNthBit(_childBitmask, 2); - - if (_childrenExternal) { - //assert(_children.external); - if (indexOne == childIndex) { - result = _children.external[0]; - } else if (indexTwo == childIndex) { - result = _children.external[1]; - } - } else { - if (indexOne == childIndex) { - int32_t offset = _children.offsetsTwoChildren[0]; - result = (OctreeElement*)((uint8_t*)this + offset); - } else if (indexTwo == childIndex) { - int32_t offset = _children.offsetsTwoChildren[1]; - result = (OctreeElement*)((uint8_t*)this + offset); - } - } - } break; - case 3: { -#ifdef HAS_AUDIT_CHILDREN - caseStr = "3 child case"; -#endif - int indexOne = getNthBit(_childBitmask, 1); - int indexTwo = getNthBit(_childBitmask, 2); - int indexThree = getNthBit(_childBitmask, 3); - - if (_childrenExternal) { - //assert(_children.external); - if (indexOne == childIndex) { - result = _children.external[0]; - } else if (indexTwo == childIndex) { - result = _children.external[1]; - } else if (indexThree == childIndex) { - result = _children.external[2]; - } else { - } - } else { - int64_t offsetOne, offsetTwo, offsetThree; - decodeThreeOffsets(offsetOne, offsetTwo, offsetThree); - - if (indexOne == childIndex) { - result = (OctreeElement*)((uint8_t*)this + offsetOne); - } else if (indexTwo == childIndex) { - result = (OctreeElement*)((uint8_t*)this + offsetTwo); - } else if (indexThree == childIndex) { - result = (OctreeElement*)((uint8_t*)this + offsetThree); - } - } - } break; - default: { -#ifdef HAS_AUDIT_CHILDREN - caseStr = "default"; -#endif - // if we have 4 or more, we know we're in external mode, so we just need to figure out which - // slot in our external array this child is. - if (oneAtBit(_childBitmask, childIndex)) { - childCount = getChildCount(); - for (int ordinal = 1; ordinal <= childCount; ordinal++) { - int index = getNthBit(_childBitmask, ordinal); - if (index == childIndex) { - int externalIndex = ordinal-1; - if (externalIndex < childCount && externalIndex >= 0) { - result = _children.external[externalIndex]; - } else { - qCDebug(octree, "getChildAtIndex() attempt to access external client out of " - "bounds externalIndex=%d <<<<<<<<<< WARNING!!!", externalIndex); - } - break; - } - } - } - } break; - } -#ifdef HAS_AUDIT_CHILDREN - if (result != _childrenArray[childIndex]) { - qCDebug(octree, "getChildAtIndex() case:%s result<%p> != _childrenArray[childIndex]<%p> <<<<<<<<<< WARNING!!!", - caseStr, result,_childrenArray[childIndex]); - } -#endif // def HAS_AUDIT_CHILDREN - return result; -#endif } -#ifdef BLENDED_UNION_CHILDREN -void OctreeElement::storeTwoChildren(OctreeElement* childOne, OctreeElement* childTwo) { - int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this; - int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this; - - const int64_t minOffset = std::numeric_limits::min(); - const int64_t maxOffset = std::numeric_limits::max(); - - bool forceExternal = true; - if (!forceExternal && isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) { - // if previously external, then clean it up... - if (_childrenExternal) { - //assert(_children.external); - const int previousChildCount = 2; - _externalChildrenMemoryUsage -= previousChildCount * sizeof(OctreeElement*); - delete[] _children.external; - _children.external = NULL; // probably not needed! - _childrenExternal = false; - } - - // encode in union - _children.offsetsTwoChildren[0] = offsetOne; - _children.offsetsTwoChildren[1] = offsetTwo; - - _twoChildrenOffsetCount++; - } else { - // encode in array - - // if not previously external, then allocate appropriately - if (!_childrenExternal) { - _childrenExternal = true; - const int newChildCount = 2; - _externalChildrenMemoryUsage += newChildCount * sizeof(OctreeElement*); - _children.external = new OctreeElement*[newChildCount]; - memset(_children.external, 0, sizeof(OctreeElement*) * newChildCount); - } - _children.external[0] = childOne; - _children.external[1] = childTwo; - _twoChildrenExternalCount++; - } -} - -void OctreeElement::retrieveTwoChildren(OctreeElement*& childOne, OctreeElement*& childTwo) { - // If we previously had an external array, then get the - if (_childrenExternal) { - childOne = _children.external[0]; - childTwo = _children.external[1]; - delete[] _children.external; - _children.external = NULL; // probably not needed! - _childrenExternal = false; - _twoChildrenExternalCount--; - const int newChildCount = 2; - _externalChildrenMemoryUsage -= newChildCount * sizeof(OctreeElement*); - } else { - int64_t offsetOne = _children.offsetsTwoChildren[0]; - int64_t offsetTwo = _children.offsetsTwoChildren[1]; - childOne = (OctreeElement*)((uint8_t*)this + offsetOne); - childTwo = (OctreeElement*)((uint8_t*)this + offsetTwo); - _twoChildrenOffsetCount--; - } -} - -void OctreeElement::decodeThreeOffsets(int64_t& offsetOne, int64_t& offsetTwo, int64_t& offsetThree) const { - const quint64 ENCODE_BITS = 21; - const quint64 ENCODE_MASK = 0xFFFFF; - const quint64 ENCODE_MASK_SIGN = 0x100000; - - quint64 offsetEncodedOne = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 2)) & ENCODE_MASK; - quint64 offsetEncodedTwo = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 1)) & ENCODE_MASK; - quint64 offsetEncodedThree = (_children.offsetsThreeChildrenEncoded & ENCODE_MASK); - - quint64 signEncodedOne = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 2)) & ENCODE_MASK_SIGN; - quint64 signEncodedTwo = (_children.offsetsThreeChildrenEncoded >> (ENCODE_BITS * 1)) & ENCODE_MASK_SIGN; - quint64 signEncodedThree = (_children.offsetsThreeChildrenEncoded & ENCODE_MASK_SIGN); - - bool oneNegative = signEncodedOne == ENCODE_MASK_SIGN; - bool twoNegative = signEncodedTwo == ENCODE_MASK_SIGN; - bool threeNegative = signEncodedThree == ENCODE_MASK_SIGN; - - offsetOne = oneNegative ? -offsetEncodedOne : offsetEncodedOne; - offsetTwo = twoNegative ? -offsetEncodedTwo : offsetEncodedTwo; - offsetThree = threeNegative ? -offsetEncodedThree : offsetEncodedThree; -} - -void OctreeElement::encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree) { - const quint64 ENCODE_BITS = 21; - const quint64 ENCODE_MASK = 0xFFFFF; - const quint64 ENCODE_MASK_SIGN = 0x100000; - - quint64 offsetEncodedOne, offsetEncodedTwo, offsetEncodedThree; - if (offsetOne < 0) { - offsetEncodedOne = ((-offsetOne & ENCODE_MASK) | ENCODE_MASK_SIGN); - } else { - offsetEncodedOne = offsetOne & ENCODE_MASK; - } - offsetEncodedOne = offsetEncodedOne << (ENCODE_BITS * 2); - - if (offsetTwo < 0) { - offsetEncodedTwo = ((-offsetTwo & ENCODE_MASK) | ENCODE_MASK_SIGN); - } else { - offsetEncodedTwo = offsetTwo & ENCODE_MASK; - } - offsetEncodedTwo = offsetEncodedTwo << ENCODE_BITS; - - if (offsetThree < 0) { - offsetEncodedThree = ((-offsetThree & ENCODE_MASK) | ENCODE_MASK_SIGN); - } else { - offsetEncodedThree = offsetThree & ENCODE_MASK; - } - _children.offsetsThreeChildrenEncoded = offsetEncodedOne | offsetEncodedTwo | offsetEncodedThree; -} - -void OctreeElement::storeThreeChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree) { - int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this; - int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this; - int64_t offsetThree = (uint8_t*)childThree - (uint8_t*)this; - - const int64_t minOffset = -1048576; // what can fit in 20 bits // std::numeric_limits::min(); - const int64_t maxOffset = 1048576; // what can fit in 20 bits // std::numeric_limits::max(); - - bool forceExternal = true; - if (!forceExternal && - isBetween(offsetOne, maxOffset, minOffset) && - isBetween(offsetTwo, maxOffset, minOffset) && - isBetween(offsetThree, maxOffset, minOffset)) { - // if previously external, then clean it up... - if (_childrenExternal) { - delete[] _children.external; - _children.external = NULL; // probably not needed! - _childrenExternal = false; - const int previousChildCount = 3; - _externalChildrenMemoryUsage -= previousChildCount * sizeof(OctreeElement*); - } - // encode in union - encodeThreeOffsets(offsetOne, offsetTwo, offsetThree); - _threeChildrenOffsetCount++; - } else { - // encode in array - - // if not previously external, then allocate appropriately - if (!_childrenExternal) { - _childrenExternal = true; - const int newChildCount = 3; - _externalChildrenMemoryUsage += newChildCount * sizeof(OctreeElement*); - _children.external = new OctreeElement*[newChildCount]; - memset(_children.external, 0, sizeof(OctreeElement*) * newChildCount); - } - _children.external[0] = childOne; - _children.external[1] = childTwo; - _children.external[2] = childThree; - _threeChildrenExternalCount++; - } -} - -void OctreeElement::retrieveThreeChildren(OctreeElement*& childOne, OctreeElement*& childTwo, OctreeElement*& childThree) { - // If we previously had an external array, then get the - if (_childrenExternal) { - childOne = _children.external[0]; - childTwo = _children.external[1]; - childThree = _children.external[2]; - delete[] _children.external; - _children.external = NULL; // probably not needed! - _childrenExternal = false; - _threeChildrenExternalCount--; - _externalChildrenMemoryUsage -= 3 * sizeof(OctreeElement*); - } else { - int64_t offsetOne, offsetTwo, offsetThree; - decodeThreeOffsets(offsetOne, offsetTwo, offsetThree); - - childOne = (OctreeElement*)((uint8_t*)this + offsetOne); - childTwo = (OctreeElement*)((uint8_t*)this + offsetTwo); - childThree = (OctreeElement*)((uint8_t*)this + offsetThree); - _threeChildrenOffsetCount--; - } -} - -void OctreeElement::checkStoreFourChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree, OctreeElement* childFour) { - int64_t offsetOne = (uint8_t*)childOne - (uint8_t*)this; - int64_t offsetTwo = (uint8_t*)childTwo - (uint8_t*)this; - int64_t offsetThree = (uint8_t*)childThree - (uint8_t*)this; - int64_t offsetFour = (uint8_t*)childFour - (uint8_t*)this; - - const int64_t minOffset = std::numeric_limits::min(); - const int64_t maxOffset = std::numeric_limits::max(); - - bool forceExternal = true; - if (!forceExternal && - isBetween(offsetOne, maxOffset, minOffset) && - isBetween(offsetTwo, maxOffset, minOffset) && - isBetween(offsetThree, maxOffset, minOffset) && - isBetween(offsetFour, maxOffset, minOffset) - ) { - _couldStoreFourChildrenInternally++; - } else { - _couldNotStoreFourChildrenInternally++; - } -} -#endif - void OctreeElement::deleteAllChildren() { // first delete all the OctreeElement objects... for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { @@ -667,52 +290,6 @@ void OctreeElement::deleteAllChildren() { // if the children_t union represents _children.external we need to delete it here delete[] _children.external; } - -#ifdef BLENDED_UNION_CHILDREN - // now, reset our internal state and ANY and all population data - int childCount = getChildCount(); - switch (childCount) { - case 0: { - _singleChildrenCount--; - _childrenCount[0]--; - } break; - case 1: { - _singleChildrenCount--; - _childrenCount[1]--; - } break; - - case 2: { - if (_childrenExternal) { - _twoChildrenExternalCount--; - } else { - _twoChildrenOffsetCount--; - } - _childrenCount[2]--; - } break; - - case 3: { - if (_childrenExternal) { - _threeChildrenExternalCount--; - } else { - _threeChildrenOffsetCount--; - } - _childrenCount[3]--; - } break; - - default: { - _externalChildrenCount--; - _childrenCount[childCount]--; - } break; - - - } - - // If we had externally stored children, clean them too. - if (_childrenExternal && _children.external) { - delete[] _children.external; - } - _children.single = NULL; -#endif // BLENDED_UNION_CHILDREN } void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) { @@ -788,353 +365,6 @@ void OctreeElement::setChildAtIndex(int childIndex, OctreeElement* child) { } #endif // def SIMPLE_EXTERNAL_CHILDREN - -#ifdef BLENDED_UNION_CHILDREN - PerformanceWarning warn(false,"setChildAtIndex",false,&_setChildAtIndexTime,&_setChildAtIndexCalls); - - // Here's how we store things... - // If we have 0 or 1 children, then we just store them in the _children.single; - // If we have 2 children, - // then if we can we store them as 32 bit signed offsets from our own this pointer, - // _children.offsetsTwoChildren[0]-[1] - // these are 32 bit offsets - - unsigned char previousChildMask = _childBitmask; - int previousChildCount = getChildCount(); - if (child) { - setAtBit(_childBitmask, childIndex); - } else { - clearAtBit(_childBitmask, childIndex); - } - int newChildCount = getChildCount(); - - // track our population data - if (previousChildCount != newChildCount) { - _childrenCount[previousChildCount]--; - _childrenCount[newChildCount]++; - } - - // If we had 0 children and we still have 0 children, then there is nothing to do. - if (previousChildCount == 0 && newChildCount == 0) { - // nothing to do... - } else if ((previousChildCount == 0 || previousChildCount == 1) && newChildCount == 1) { - // If we had 0 children, and we're setting our first child or if we had 1 child, or we're resetting the same child, - // then we can just store it in _children.single - _children.single = child; - } else if (previousChildCount == 1 && newChildCount == 0) { - // If we had 1 child, and we've removed our last child, then we can just store NULL in _children.single - _children.single = NULL; - } else if (previousChildCount == 1 && newChildCount == 2) { - // If we had 1 child, and we're adding a second child, then we need to determine - // if we can use offsets to store them - - OctreeElement* childOne; - OctreeElement* childTwo; - - if (getNthBit(previousChildMask, 1) < childIndex) { - childOne = _children.single; - childTwo = child; - } else { - childOne = child; - childTwo = _children.single; - } - - _singleChildrenCount--; - storeTwoChildren(childOne, childTwo); - } else if (previousChildCount == 2 && newChildCount == 1) { - // If we had 2 children, and we're removing one, then we know we can go down to single mode - //assert(child == NULL); // this is the only logical case - - int indexTwo = getNthBit(previousChildMask, 2); - bool keepChildOne = indexTwo == childIndex; - - OctreeElement* childOne; - OctreeElement* childTwo; - - retrieveTwoChildren(childOne, childTwo); - - _singleChildrenCount++; - - if (keepChildOne) { - _children.single = childOne; - } else { - _children.single = childTwo; - } - } else if (previousChildCount == 2 && newChildCount == 2) { - // If we had 2 children, and still have 2, then we know we are resetting one of our existing children - - int indexOne = getNthBit(previousChildMask, 1); - bool replaceChildOne = indexOne == childIndex; - - // Get the existing two children out of their encoding... - OctreeElement* childOne; - OctreeElement* childTwo; - retrieveTwoChildren(childOne, childTwo); - - if (replaceChildOne) { - childOne = child; - } else { - childTwo = child; - } - - storeTwoChildren(childOne, childTwo); - - } else if (previousChildCount == 2 && newChildCount == 3) { - // If we had 2 children, and now have 3, then we know we are going to an external case... - - // First, decode the children... - OctreeElement* childOne; - OctreeElement* childTwo; - OctreeElement* childThree; - - // Get the existing two children out of their encoding... - retrieveTwoChildren(childOne, childTwo); - - // determine order of the existing children - int indexOne = getNthBit(previousChildMask, 1); - int indexTwo = getNthBit(previousChildMask, 2); - - if (childIndex < indexOne) { - childThree = childTwo; - childTwo = childOne; - childOne = child; - } else if (childIndex < indexTwo) { - childThree = childTwo; - childTwo = child; - } else { - childThree = child; - } - storeThreeChildren(childOne, childTwo, childThree); - } else if (previousChildCount == 3 && newChildCount == 2) { - // If we had 3 children, and now have 2, then we know we are going from an external case to a potential internal case - - // We need to determine which children we had, and which one we got rid of... - int indexOne = getNthBit(previousChildMask, 1); - int indexTwo = getNthBit(previousChildMask, 2); - - bool removeChildOne = indexOne == childIndex; - bool removeChildTwo = indexTwo == childIndex; - - OctreeElement* childOne; - OctreeElement* childTwo; - OctreeElement* childThree; - - // Get the existing two children out of their encoding... - retrieveThreeChildren(childOne, childTwo, childThree); - - if (removeChildOne) { - childOne = childTwo; - childTwo = childThree; - } else if (removeChildTwo) { - childTwo = childThree; - } else { - // removing child three, nothing to do. - } - - storeTwoChildren(childOne, childTwo); - } else if (previousChildCount == 3 && newChildCount == 3) { - // If we had 3 children, and now have 3, then we need to determine which item we're replacing... - - // We need to determine which children we had, and which one we got rid of... - int indexOne = getNthBit(previousChildMask, 1); - int indexTwo = getNthBit(previousChildMask, 2); - - bool replaceChildOne = indexOne == childIndex; - bool replaceChildTwo = indexTwo == childIndex; - - OctreeElement* childOne; - OctreeElement* childTwo; - OctreeElement* childThree; - - // Get the existing two children out of their encoding... - retrieveThreeChildren(childOne, childTwo, childThree); - - if (replaceChildOne) { - childOne = child; - } else if (replaceChildTwo) { - childTwo = child; - } else { - childThree = child; - } - - storeThreeChildren(childOne, childTwo, childThree); - } else if (previousChildCount == 3 && newChildCount == 4) { - // If we had 3 children, and now have 4, then we know we are going to an external case... - - // First, decode the children... - OctreeElement* childOne; - OctreeElement* childTwo; - OctreeElement* childThree; - OctreeElement* childFour; - - // Get the existing two children out of their encoding... - retrieveThreeChildren(childOne, childTwo, childThree); - - // determine order of the existing children - int indexOne = getNthBit(previousChildMask, 1); - int indexTwo = getNthBit(previousChildMask, 2); - int indexThree = getNthBit(previousChildMask, 3); - - if (childIndex < indexOne) { - childFour = childThree; - childThree = childTwo; - childTwo = childOne; - childOne = child; - } else if (childIndex < indexTwo) { - childFour = childThree; - childThree = childTwo; - childTwo = child; - } else if (childIndex < indexThree) { - childFour = childThree; - childThree = child; - } else { - childFour = child; - } - - // now, allocate the external... - _childrenExternal = true; - const int newChildCount = 4; - _children.external = new OctreeElement*[newChildCount]; - memset(_children.external, 0, sizeof(OctreeElement*) * newChildCount); - - _externalChildrenMemoryUsage += newChildCount * sizeof(OctreeElement*); - - _children.external[0] = childOne; - _children.external[1] = childTwo; - _children.external[2] = childThree; - _children.external[3] = childFour; - _externalChildrenCount++; - } else if (previousChildCount == 4 && newChildCount == 3) { - // If we had 4 children, and now have 3, then we know we are going from an external case to a potential internal case - //assert(_children.external && _childrenExternal && previousChildCount == 4); - - // We need to determine which children we had, and which one we got rid of... - int indexOne = getNthBit(previousChildMask, 1); - int indexTwo = getNthBit(previousChildMask, 2); - int indexThree = getNthBit(previousChildMask, 3); - - bool removeChildOne = indexOne == childIndex; - bool removeChildTwo = indexTwo == childIndex; - bool removeChildThree = indexThree == childIndex; - - OctreeElement* childOne = _children.external[0]; - OctreeElement* childTwo = _children.external[1]; - OctreeElement* childThree = _children.external[2]; - OctreeElement* childFour = _children.external[3]; - - if (removeChildOne) { - childOne = childTwo; - childTwo = childThree; - childThree = childFour; - } else if (removeChildTwo) { - childTwo = childThree; - childThree = childFour; - } else if (removeChildThree) { - childThree = childFour; - } else { - // removing child four, nothing to do. - } - - // clean up the external children... - _childrenExternal = false; - delete[] _children.external; - _children.external = NULL; - _externalChildrenCount--; - _externalChildrenMemoryUsage -= previousChildCount * sizeof(OctreeElement*); - storeThreeChildren(childOne, childTwo, childThree); - } else if (previousChildCount == newChildCount) { - //assert(_children.external && _childrenExternal && previousChildCount >= 4); - //assert(previousChildCount == newChildCount); - - // 4 or more children, one item being replaced, we know we're stored externally, we just need to find the one - // that needs to be replaced and replace it. - for (int ordinal = 1; ordinal <= 8; ordinal++) { - int index = getNthBit(previousChildMask, ordinal); - if (index == childIndex) { - // this is our child to be replaced - int nthChild = ordinal-1; - _children.external[nthChild] = child; - break; - } - } - } else if (previousChildCount < newChildCount) { - // Growing case... previous must be 4 or greater - //assert(_children.external && _childrenExternal && previousChildCount >= 4); - //assert(previousChildCount == newChildCount-1); - - // 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert - // this child pointer into our external list - OctreeElement** newExternalList = new OctreeElement*[newChildCount]; - memset(newExternalList, 0, sizeof(OctreeElement*) * newChildCount); - - int copiedCount = 0; - for (int ordinal = 1; ordinal <= newChildCount; ordinal++) { - int index = getNthBit(previousChildMask, ordinal); - if (index != -1 && index < childIndex) { - newExternalList[ordinal - 1] = _children.external[ordinal - 1]; - copiedCount++; - } else { - - // insert our new child here... - newExternalList[ordinal - 1] = child; - - // if we didn't copy all of our previous children, then we need to - if (copiedCount < previousChildCount) { - // our child needs to be inserted before this index, and everything else pushed out... - for (int oldOrdinal = ordinal; oldOrdinal <= previousChildCount; oldOrdinal++) { - newExternalList[oldOrdinal] = _children.external[oldOrdinal - 1]; - } - } - break; - } - } - delete[] _children.external; - _children.external = newExternalList; - _externalChildrenMemoryUsage -= previousChildCount * sizeof(OctreeElement*); - _externalChildrenMemoryUsage += newChildCount * sizeof(OctreeElement*); - - } else if (previousChildCount > newChildCount) { - //assert(_children.external && _childrenExternal && previousChildCount >= 4); - //assert(previousChildCount == newChildCount+1); - - // 4 or more children, one item being removed, we know we're stored externally, we just figure out which - // item to remove from our external list - OctreeElement** newExternalList = new OctreeElement*[newChildCount]; - - for (int ordinal = 1; ordinal <= previousChildCount; ordinal++) { - int index = getNthBit(previousChildMask, ordinal); - //assert(index != -1); - if (index < childIndex) { - newExternalList[ordinal - 1] = _children.external[ordinal - 1]; - } else { - // our child needs to be removed from here, and everything else pulled in... - for (int moveOrdinal = ordinal; moveOrdinal <= newChildCount; moveOrdinal++) { - newExternalList[moveOrdinal - 1] = _children.external[moveOrdinal]; - } - break; - } - } - delete[] _children.external; - _children.external = newExternalList; - _externalChildrenMemoryUsage -= previousChildCount * sizeof(OctreeElement*); - _externalChildrenMemoryUsage += newChildCount * sizeof(OctreeElement*); - } else { - //assert(false); - qCDebug(octree, "THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d",previousChildCount, newChildCount); - } - - // check to see if we could store these 4 children locally - if (getChildCount() == 4 && _childrenExternal && _children.external) { - checkStoreFourChildren(_children.external[0], _children.external[1], _children.external[2], _children.external[3]); - } - - -#ifdef HAS_AUDIT_CHILDREN - _childrenArray[childIndex] = child; - auditChildren("setChildAtIndex()"); -#endif // def HAS_AUDIT_CHILDREN - -#endif } diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index e2229b2214..830655242f 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -12,7 +12,6 @@ #ifndef hifi_OctreeElement_h #define hifi_OctreeElement_h -//#define HAS_AUDIT_CHILDREN //#define SIMPLE_CHILD_ARRAY #define SIMPLE_EXTERNAL_CHILDREN @@ -204,25 +203,9 @@ public: static quint64 getSetChildAtIndexTime() { return _setChildAtIndexTime; } static quint64 getSetChildAtIndexCalls() { return _setChildAtIndexCalls; } -#ifdef BLENDED_UNION_CHILDREN - static quint64 getSingleChildrenCount() { return _singleChildrenCount; } - static quint64 getTwoChildrenOffsetCount() { return _twoChildrenOffsetCount; } - static quint64 getTwoChildrenExternalCount() { return _twoChildrenExternalCount; } - static quint64 getThreeChildrenOffsetCount() { return _threeChildrenOffsetCount; } - static quint64 getThreeChildrenExternalCount() { return _threeChildrenExternalCount; } - static quint64 getCouldStoreFourChildrenInternally() { return _couldStoreFourChildrenInternally; } - static quint64 getCouldNotStoreFourChildrenInternally() { return _couldNotStoreFourChildrenInternally; } -#endif - static quint64 getExternalChildrenCount() { return _externalChildrenCount; } static quint64 getChildrenCount(int childCount) { return _childrenCount[childCount]; } -#ifdef BLENDED_UNION_CHILDREN -#ifdef HAS_AUDIT_CHILDREN - void auditChildren(const char* label) const; -#endif // def HAS_AUDIT_CHILDREN -#endif // def BLENDED_UNION_CHILDREN - enum ChildIndex { CHILD_BOTTOM_RIGHT_NEAR = 0, CHILD_BOTTOM_RIGHT_FAR = 1, @@ -261,15 +244,6 @@ protected: void deleteAllChildren(); void setChildAtIndex(int childIndex, OctreeElement* child); -#ifdef BLENDED_UNION_CHILDREN - void storeTwoChildren(OctreeElement* childOne, OctreeElement* childTwo); - void retrieveTwoChildren(OctreeElement*& childOne, OctreeElement*& childTwo); - void storeThreeChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree); - void retrieveThreeChildren(OctreeElement*& childOne, OctreeElement*& childTwo, OctreeElement*& childThree); - void decodeThreeOffsets(int64_t& offsetOne, int64_t& offsetTwo, int64_t& offsetThree) const; - void encodeThreeOffsets(int64_t offsetOne, int64_t offsetTwo, int64_t offsetThree); - void checkStoreFourChildren(OctreeElement* childOne, OctreeElement* childTwo, OctreeElement* childThree, OctreeElement* childFour); -#endif void calculateAACube(); void notifyDeleteHooks(); void notifyUpdateHooks(); @@ -296,19 +270,6 @@ protected: } _children; #endif -#ifdef BLENDED_UNION_CHILDREN - union children_t { - OctreeElement* single; - int32_t offsetsTwoChildren[2]; - quint64 offsetsThreeChildrenEncoded; - OctreeElement** external; - } _children; -#ifdef HAS_AUDIT_CHILDREN - OctreeElement* _childrenArray[8]; /// Only used when HAS_AUDIT_CHILDREN is enabled to help debug children encoding -#endif // def HAS_AUDIT_CHILDREN - -#endif //def BLENDED_UNION_CHILDREN - uint16_t _sourceUUIDKey; /// Client only, stores node id of voxel server that sent his voxel, 2 bytes // Support for _sourceUUID, we use these static member variables to track the UUIDs that are @@ -345,15 +306,6 @@ protected: static quint64 _setChildAtIndexTime; static quint64 _setChildAtIndexCalls; -#ifdef BLENDED_UNION_CHILDREN - static quint64 _singleChildrenCount; - static quint64 _twoChildrenOffsetCount; - static quint64 _twoChildrenExternalCount; - static quint64 _threeChildrenOffsetCount; - static quint64 _threeChildrenExternalCount; - static quint64 _couldStoreFourChildrenInternally; - static quint64 _couldNotStoreFourChildrenInternally; -#endif static quint64 _externalChildrenCount; static quint64 _childrenCount[NUMBER_OF_CHILDREN + 1]; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e0c66eb604..850baf3d06 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -135,7 +135,6 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); - auto& renderDetails = renderContext->args->_details; RenderArgs* args = renderContext->args; gpu::Batch batch; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 6076ec0006..46103f7803 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -59,7 +59,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont assert(renderContext->args); assert(renderContext->args->_viewFrustum); - auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; auto renderDetails = renderContext->args->_details._item; @@ -101,7 +100,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) { auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(_filter); - auto& renderDetails = renderContext->args->_details; outItems.clear(); outItems.reserve(items.size()); From 3d06b011aa2863bb1dc2027c9afbdc5ce1a18ecb Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 3 Jul 2015 13:27:00 -0700 Subject: [PATCH 28/39] adding batch to renderHUD --- .../src/ui/overlays/BillboardOverlay.cpp | 2 -- interface/src/ui/overlays/Grid3DOverlay.cpp | 2 -- interface/src/ui/overlays/Overlays.cpp | 6 ++++ .../src/ui/overlays/Rectangle3DOverlay.cpp | 3 -- interface/src/ui/overlays/Sphere3DOverlay.cpp | 28 ------------------- 5 files changed, 6 insertions(+), 35 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 913eb749a9..988223765a 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -93,8 +93,6 @@ void BillboardOverlay::render(RenderArgs* args) { glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha)); batch->setUniformTexture(0, args->_whiteTexture); // restore default white color after me - } else { - qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 295dc1b2b5..baf7b42ac5 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -89,8 +89,6 @@ void Grid3DOverlay::render(RenderArgs* args) { DependencyManager::get()->renderGrid(*batch, MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS, gridColor); } - } else { - qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index dc49478f38..fb0a095e13 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "BillboardOverlay.h" #include "Circle3DOverlay.h" @@ -96,6 +97,10 @@ void Overlays::cleanupOverlaysToDelete() { void Overlays::renderHUD(RenderArgs* renderArgs) { QReadLocker lock(&_lock); + gpu::Batch batch; + renderArgs->_batch = &batch; + + foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { if (thisOverlay->is3D()) { glEnable(GL_DEPTH_TEST); @@ -109,6 +114,7 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { thisOverlay->render(renderArgs); } } + gpu::GLBackend::renderBatch(batch, true); } unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& properties) { diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 6f35ccb3d0..ddab8040b1 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -87,9 +87,6 @@ void Rectangle3DOverlay::render(RenderArgs* args) { geometryCache->renderVertices(*batch, gpu::LINE_STRIP, _geometryCacheID); } } - } else { - - qDebug() << "NO NAKED GL CALLS ALLOWED HERE! PLEASE USE THE BATCHING SYSTEM NEXT TIME"; } } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index dd60ee4af8..259fe98acf 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -41,34 +41,6 @@ void Sphere3DOverlay::render(RenderArgs* args) { transform.postScale(getDimensions()); batch->setModelTransform(transform); DependencyManager::get()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid); - } else { - glDisable(GL_LIGHTING); - - glm::vec3 position = getPosition(); - glm::vec3 center = getCenter(); - glm::vec3 dimensions = getDimensions(); - glm::quat rotation = getRotation(); - - float glowLevel = getGlowLevel(); - Glower* glower = NULL; - if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); - } - - Transform transform = Transform(); - transform.setTranslation(position); - glm::vec3 axis = glm::axis(rotation); - transform.setRotation(glm::angleAxis(glm::angle(rotation), axis)); - - glm::vec3 positionToCenter = center - position; - transform.setTranslation(positionToCenter); - transform.setScale(dimensions); - DependencyManager::get()->renderSphere(*batch, 1.0f, SLICES, SLICES, sphereColor, _isSolid); - - - if (glower) { - delete glower; - } } } From 40cdd8646e3c727fdbb558fd618ed231a39e274b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 Jul 2015 15:53:53 -0700 Subject: [PATCH 29/39] add packets per second to octree processing stats --- interface/src/ui/OctreeStatsDialog.cpp | 12 ++++++++++++ interface/src/ui/OctreeStatsDialog.h | 1 + libraries/octree/src/OctreeRenderer.cpp | 5 +++++ libraries/octree/src/OctreeRenderer.h | 4 ++++ 4 files changed, 22 insertions(+) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 4c95e7a68a..eea962b412 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -53,6 +53,7 @@ OctreeStatsDialog::OctreeStatsDialog(QWidget* parent, NodeToOctreeSceneStats* mo _localElementsMemory = AddStatItem("Elements Memory"); _sendingMode = AddStatItem("Sending Mode"); + _processedPackets = AddStatItem("Processed Packets"); _processedPacketsElements = AddStatItem("Processed Packets Elements"); _processedPacketsEntities = AddStatItem("Processed Packets Entities"); _processedPacketsTiming = AddStatItem("Processed Packets Timing"); @@ -219,6 +220,8 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Processed Packets Elements auto averageElementsPerPacket = entities->getAverageElementsPerPacket(); auto averageEntitiesPerPacket = entities->getAverageEntitiesPerPacket(); + + auto averagePacketsPerSecond = entities->getAveragePacketsPerSecond(); auto averageElementsPerSecond = entities->getAverageElementsPerSecond(); auto averageEntitiesPerSecond = entities->getAverageEntitiesPerSecond(); @@ -228,6 +231,8 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { QString averageElementsPerPacketString = locale.toString(averageElementsPerPacket); QString averageEntitiesPerPacketString = locale.toString(averageEntitiesPerPacket); + + QString averagePacketsPerSecondString = locale.toString(averagePacketsPerSecond); QString averageElementsPerSecondString = locale.toString(averageElementsPerSecond); QString averageEntitiesPerSecondString = locale.toString(averageEntitiesPerSecond); @@ -235,6 +240,13 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { QString averageUncompressPerPacketString = locale.toString(averageUncompressPerPacket); QString averageReadBitstreamPerPacketString = locale.toString(averageReadBitstreamPerPacket); + label = _labels[_processedPackets]; + statsValue.str(""); + statsValue << + "" << qPrintable(averagePacketsPerSecondString) << " per second"; + + label->setText(statsValue.str().c_str()); + label = _labels[_processedPacketsElements]; statsValue.str(""); statsValue << diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index 986080de56..f56a00bc86 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -66,6 +66,7 @@ private: int _entityUpdateTime; int _entityUpdates; + int _processedPackets; int _processedPacketsElements; int _processedPacketsEntities; int _processedPacketsTiming; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 6fa3f47120..d0aebd216e 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -101,6 +101,8 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar sequence, flightTime, packetLength, dataBytes); } + _packetsInLastWindow++; + int elementsPerPacket = 0; int entitiesPerPacket = 0; @@ -185,12 +187,15 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar const quint64 USECS_PER_SECOND = 1000 * 1000; if (sinceLastWindow > USECS_PER_SECOND) { + float packetsPerSecondInWindow = (float)_packetsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); float elementsPerSecondInWindow = (float)_elementsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); float entitiesPerSecondInWindow = (float)_entitiesInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); + _packetsPerSecond.updateAverage(packetsPerSecondInWindow); _elementsPerSecond.updateAverage(elementsPerSecondInWindow); _entitiesPerSecond.updateAverage(entitiesPerSecondInWindow); _lastWindowAt = now; + _packetsInLastWindow = 0; _elementsInLastWindow = 0; _entitiesInLastWindow = 0; } diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 894e5c2355..cf3b2a2ecd 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -64,6 +64,7 @@ public: float getAverageElementsPerPacket() const { return _elementsPerPacket.getAverage(); } float getAverageEntitiesPerPacket() const { return _entitiesPerPacket.getAverage(); } + float getAveragePacketsPerSecond() const { return _packetsPerSecond.getAverage(); } float getAverageElementsPerSecond() const { return _elementsPerSecond.getAverage(); } float getAverageEntitiesPerSecond() const { return _entitiesPerSecond.getAverage(); } @@ -80,6 +81,8 @@ protected: SimpleMovingAverage _elementsPerPacket; SimpleMovingAverage _entitiesPerPacket; + + SimpleMovingAverage _packetsPerSecond; SimpleMovingAverage _elementsPerSecond; SimpleMovingAverage _entitiesPerSecond; @@ -88,6 +91,7 @@ protected: SimpleMovingAverage _readBitstreamPerPacket; quint64 _lastWindowAt = 0; + int _packetsInLastWindow = 0; int _elementsInLastWindow = 0; int _entitiesInLastWindow = 0; From 74733452da2cdda7ead883bb680983f0ac809df2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 4 Jul 2015 11:25:27 -0700 Subject: [PATCH 30/39] some tweaks to make stats dialog more readable --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/ui/OctreeStatsDialog.cpp | 48 ++++++++++++++++---------- interface/src/ui/OctreeStatsDialog.h | 2 ++ 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c70d11b837..9f49361f79 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -531,6 +531,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::PipelineWarnings); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::LogExtraTimings); addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::SuppressShortTimings); + addCheckableActionToQMenuAndActionHash(timingMenu, MenuOption::ShowRealtimeEntityStats); auto audioIO = DependencyManager::get(); MenuWrapper* audioDebugMenu = developerMenu->addMenu("Audio"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fae7092989..043bb53a7f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -269,6 +269,7 @@ namespace MenuOption { const QString ShowDSConnectTable = "Show Domain Connection Timing"; const QString ShowBordersEntityNodes = "Show Entity Nodes"; const QString ShowIKConstraints = "Show IK Constraints"; + const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; const QString SimpleShadows = "Simple"; const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseMouseInput = "Enable Sixense Mouse Input"; diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index eea962b412..94f91a5ab7 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -129,6 +129,34 @@ OctreeStatsDialog::~OctreeStatsDialog() { void OctreeStatsDialog::paintEvent(QPaintEvent* event) { + // Processed Entities Related stats + auto entities = Application::getInstance()->getEntities(); + auto entitiesTree = entities->getTree(); + + // Do this ever paint event... even if we don't update + auto totalTrackedEdits = entitiesTree->getTotalTrackedEdits(); + + // track our updated per second + const quint64 SAMPLING_WINDOW = USECS_PER_SECOND / SAMPLES_PER_SECOND; + quint64 now = usecTimestampNow(); + quint64 sinceLastWindow = now - _lastWindowAt; + auto editsInLastWindow = totalTrackedEdits - _lastKnownTrackedEdits; + float sinceLastWindowInSeconds = (float)sinceLastWindow / (float)USECS_PER_SECOND; + float recentUpdatesPerSecond = (float)editsInLastWindow / sinceLastWindowInSeconds; + if (sinceLastWindow > SAMPLING_WINDOW) { + _averageUpdatesPerSecond.updateAverage(recentUpdatesPerSecond); + _lastWindowAt = now; + _lastKnownTrackedEdits = totalTrackedEdits; + } + + // Only refresh our stats every once in a while, unless asked for realtime + quint64 REFRESH_AFTER = Menu::getInstance()->isOptionChecked(MenuOption::ShowRealtimeEntityStats) ? 0 : USECS_PER_SECOND; + quint64 sinceLastRefresh = now - _lastRefresh; + if (sinceLastRefresh < REFRESH_AFTER) { + return QDialog::paintEvent(event); + } + _lastRefresh = now; + // Update labels QLabel* label; @@ -213,10 +241,6 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); - // Processed Entities Related stats - auto entities = Application::getInstance()->getEntities(); - auto entitiesTree = entities->getTree(); - // Processed Packets Elements auto averageElementsPerPacket = entities->getAverageElementsPerPacket(); auto averageEntitiesPerPacket = entities->getAverageEntitiesPerPacket(); @@ -289,22 +313,8 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { // Entity Edits label = _labels[_entityUpdates]; - auto totalTrackedEdits = entitiesTree->getTotalTrackedEdits(); auto bytesPerEdit = entitiesTree->getAverageEditBytes(); - // track our updated per second - const quint64 SAMPLING_WINDOW = USECS_PER_SECOND / SAMPLES_PER_SECOND; - quint64 now = usecTimestampNow(); - quint64 sinceLastWindow = now - _lastWindowAt; - auto editsInLastWindow = totalTrackedEdits - _lastKnownTrackedEdits; - float sinceLastWindowInSeconds = (float)sinceLastWindow / (float)USECS_PER_SECOND; - float recentUpdatesPerSecond = (float)editsInLastWindow / sinceLastWindowInSeconds; - if (sinceLastWindow > SAMPLING_WINDOW) { - _averageUpdatesPerSecond.updateAverage(recentUpdatesPerSecond); - _lastWindowAt = now; - _lastKnownTrackedEdits = totalTrackedEdits; - } - auto updatesPerSecond = _averageUpdatesPerSecond.getAverage(); if (updatesPerSecond < 1) { updatesPerSecond = 0; // we don't really care about small updates per second so suppress those @@ -324,7 +334,7 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { showAllOctreeServers(); - this->QDialog::paintEvent(event); + QDialog::paintEvent(event); } void OctreeStatsDialog::showAllOctreeServers() { int serverCount = 0; diff --git a/interface/src/ui/OctreeStatsDialog.h b/interface/src/ui/OctreeStatsDialog.h index f56a00bc86..063c04b295 100644 --- a/interface/src/ui/OctreeStatsDialog.h +++ b/interface/src/ui/OctreeStatsDialog.h @@ -76,6 +76,8 @@ private: quint64 _lastWindowAt = 0; quint64 _lastKnownTrackedEdits = 0; + quint64 _lastRefresh = 0; + int _octreeServerLables[MAX_VOXEL_SERVERS]; int _octreeServerLabelsCount; details _extraServerDetails[MAX_VOXEL_SERVERS]; From c4a5160b890260f75f21e99e88e6f9e8267fc43e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 4 Jul 2015 19:13:35 -0700 Subject: [PATCH 31/39] CR feedback --- libraries/octree/src/OctreeRenderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index d0aebd216e..c4534b2565 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -12,9 +12,11 @@ #include #include -#include +#include #include #include +#include + #include "OctreeLogging.h" #include "OctreeRenderer.h" @@ -185,7 +187,6 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar } quint64 sinceLastWindow = now - _lastWindowAt; - const quint64 USECS_PER_SECOND = 1000 * 1000; if (sinceLastWindow > USECS_PER_SECOND) { float packetsPerSecondInWindow = (float)_packetsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); float elementsPerSecondInWindow = (float)_elementsInLastWindow / (float)(sinceLastWindow / USECS_PER_SECOND); From 2bbffff22f64d59ef536e568a56b7e536e996e98 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Jul 2015 10:22:25 -0700 Subject: [PATCH 32/39] Fixing typos --- libraries/render/src/render/drawItemStatus.slv | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/libraries/render/src/render/drawItemStatus.slv b/libraries/render/src/render/drawItemStatus.slv index f99bf006a4..9e2b4919ff 100644 --- a/libraries/render/src/render/drawItemStatus.slv +++ b/libraries/render/src/render/drawItemStatus.slv @@ -24,26 +24,24 @@ uniform ivec4 inStatus; vec3 paintRainbow(float nv) { float v = nv * 5.f; - if ( v < 0.f ) + if (v < 0.f) { return vec3(0.f, 0.f, 0.f); - else if ( v < 1.f) + } else if (v < 1.f) { return vec3(1.f, v, 0.f); - else if ( v < 2.f) + } else if (v < 2.f) { return vec3(1.f - (v-1.f), 1.f, 0.f); - else if ( v < 3.f) + } else if (v < 3.f) { return vec3(0.f, 1.f, (v-2.f)); - else if ( v < 4.f) + } else if (v < 4.f) { return vec3(0.f, 1.f - (v-3.f), 1.f ); - else if ( v < 5.f) + } else if (v < 5.f) { return vec3((v-4.f), 0.f, 1.f ); - else + } else { return vec3(1.f, 1.f, 1.f); + } } vec2 unpackStatus(int v) { - // return unpackSnorm2x16(uint(packed)); - // return vec2(clamp(float((v & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), - // clamp(float(((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); return vec2(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0), clamp(float(int((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0)); } From 93fbfcbff796f9baeb285ff7d102ab5d2702db1b Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 6 Jul 2015 12:09:08 -0700 Subject: [PATCH 33/39] Added checkbox functionality, double-click to reset panel --- examples/utilities/tools/cookies.js | 1320 ++++++++++++++------------- 1 file changed, 669 insertions(+), 651 deletions(-) mode change 100755 => 100644 examples/utilities/tools/cookies.js diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js old mode 100755 new mode 100644 index 2ec34fcec8..f217b28aae --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -1,651 +1,669 @@ -// -// cookies.js -// -// version 1.0 -// -// Created by Sam Gateau, 4/1/2015 -// A simple ui panel that present a list of porperties and the proper widget to edit it -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// The Slider class -Slider = function(x,y,width,thumbSize) { - this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 125, green: 125, blue: 255 }, - x: x, - y: y, - width: width, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - - - this.thumbSize = thumbSize; - this.thumbHalfSize = 0.5 * thumbSize; - - this.minThumbX = x + this.thumbHalfSize; - this.maxThumbX = x + width - this.thumbHalfSize; - this.thumbX = this.minThumbX; - - this.minValue = 0.0; - this.maxValue = 1.0; - - this.clickOffsetX = 0; - this.isMoving = false; - - this.updateThumb = function() { - thumbTruePos = this.thumbX - 0.5 * this.thumbSize; - Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); - }; - - this.isClickableOverlayItem = function(item) { - return (item == this.thumb) || (item == this.background); - }; - - this.onMouseMoveEvent = function(event) { - if (this.isMoving) { - newThumbX = event.x - this.clickOffsetX; - if (newThumbX < this.minThumbX) { - newThumbX = this.minThumbX; - } - if (newThumbX > this.maxThumbX) { - newThumbX = this.maxThumbX; - } - this.thumbX = newThumbX; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - if (!this.isClickableOverlayItem(clickedOverlay)) { - this.isMoving = false; - return; - } - this.isMoving = true; - var clickOffset = event.x - this.thumbX; - if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { - this.clickOffsetX = clickOffset; - } else { - this.clickOffsetX = 0; - this.thumbX = event.x; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - - }; - - this.onMouseReleaseEvent = function(event) { - this.isMoving = false; - }; - - // Public members: - - this.setNormalizedValue = function(value) { - if (value < 0.0) { - this.thumbX = this.minThumbX; - } else if (value > 1.0) { - this.thumbX = this.maxThumbX; - } else { - this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; - } - this.updateThumb(); - }; - this.getNormalizedValue = function() { - return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); - }; - - this.setValue = function(value) { - var normValue = (value - this.minValue) / (this.maxValue - this.minValue); - this.setNormalizedValue(normValue); - }; - - this.getValue = function() { - return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; - }; - - this.onValueChanged = function(value) {}; - - this.setMaxValue = function(maxValue) { - if (this.maxValue == maxValue) { - return; - } - var currentVal = this.getValue(); - this.maxValue = maxValue; - this.setValue(currentVal); - } - this.setMinValue = function(minValue) { - if (this.minValue == minValue) { - return; - } - var currentVal = this.getValue(); - this.minValue = minValue; - this.setValue(currentVal); - } - - this.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - }; - - this.setThumbColor = function(color) { - Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; - this.setBackgroundColor = function(color) { - Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); - }; -} - -// The Checkbox class -Checkbox = function(x,y,thumbSize) { - - this.thumb = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: thumbSize, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - this.background = Overlays.addOverlay("text", { - backgroundColor: { red: 125, green: 125, blue: 255 }, - x: x, - y: y, - width: thumbSize * 2, - height: thumbSize, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true - }); - - this.thumbSize = thumbSize; - this.thumbHalfSize = 0.5 * thumbSize; - - this.minThumbX = x + this.thumbHalfSize; - this.maxThumbX = x + thumbSize * 2 - this.thumbHalfSize; - this.thumbX = this.minThumbX; - - this.minValue = 0.0; - this.maxValue = 1.0; - - this.clickOffsetX = 0; - this.isMoving = false; - - this.updateThumb = function() { - thumbTruePos = this.thumbX - 0.5 * this.thumbSize; - Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); - }; - - this.isClickableOverlayItem = function(item) { - return item == this.background; - }; - - this.onMouseMoveEvent = function(event) { - if (this.isMoving) { - newThumbX = event.x - this.clickOffsetX; - if (newThumbX < this.minThumbX) { - newThumbX = this.minThumbX; - } - if (newThumbX > this.maxThumbX) { - newThumbX = this.maxThumbX; - } - this.thumbX = newThumbX; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - if (this.background != clickedOverlay) { - this.isMoving = false; - return; - } - this.isMoving = true; - var clickOffset = event.x - this.thumbX; - if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { - this.clickOffsetX = clickOffset; - } else { - this.clickOffsetX = 0; - this.thumbX = event.x; - this.updateThumb(); - this.onValueChanged(this.getValue()); - } - - }; - - this.onMouseReleaseEvent = function(event) { - this.isMoving = false; - }; - - // Public members: - - this.setNormalizedValue = function(value) { - if (value < 0.0) { - this.thumbX = this.minThumbX; - } else if (value > 1.0) { - this.thumbX = this.maxThumbX; - } else { - this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; - } - this.updateThumb(); - }; - this.getNormalizedValue = function() { - return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); - }; - - this.setValue = function(value) { - var normValue = (value - this.minValue) / (this.maxValue - this.minValue); - this.setNormalizedValue(normValue); - }; - - this.getValue = function() { - return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; - }; - - this.onValueChanged = function(value) {}; - - this.destroy = function() { - Overlays.deleteOverlay(this.background); - Overlays.deleteOverlay(this.thumb); - }; -} - -// The ColorBox class -ColorBox = function(x,y,width,thumbSize) { - var self = this; - - var slideHeight = thumbSize / 3; - var sliderWidth = width; - this.red = new Slider(x, y, width, slideHeight); - this.green = new Slider(x, y + slideHeight, width, slideHeight); - this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); - this.red.setBackgroundColor({x: 1, y: 0, z: 0}); - this.green.setBackgroundColor({x: 0, y: 1, z: 0}); - this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); - - this.isClickableOverlayItem = function(item) { - return this.red.isClickableOverlayItem(item) - || this.green.isClickableOverlayItem(item) - || this.blue.isClickableOverlayItem(item); - }; - - this.onMouseMoveEvent = function(event) { - this.red.onMouseMoveEvent(event); - this.green.onMouseMoveEvent(event); - this.blue.onMouseMoveEvent(event); - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - this.red.onMousePressEvent(event, clickedOverlay); - if (this.red.isMoving) { - return; - } - - this.green.onMousePressEvent(event, clickedOverlay); - if (this.green.isMoving) { - return; - } - - this.blue.onMousePressEvent(event, clickedOverlay); - }; - - this.onMouseReleaseEvent = function(event) { - this.red.onMouseReleaseEvent(event); - this.green.onMouseReleaseEvent(event); - this.blue.onMouseReleaseEvent(event); - }; - - this.setterFromWidget = function(value) { - var color = self.getValue(); - self.onValueChanged(color); - self.updateRGBSliders(color); - }; - - this.red.onValueChanged = this.setterFromWidget; - this.green.onValueChanged = this.setterFromWidget; - this.blue.onValueChanged = this.setterFromWidget; - - this.updateRGBSliders = function(color) { - this.red.setThumbColor({x: color.x, y: 0, z: 0}); - this.green.setThumbColor({x: 0, y: color.y, z: 0}); - this.blue.setThumbColor({x: 0, y: 0, z: color.z}); - }; - - // Public members: - this.setValue = function(value) { - this.red.setValue(value.x); - this.green.setValue(value.y); - this.blue.setValue(value.z); - this.updateRGBSliders(value); - }; - - this.getValue = function() { - var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; - return value; - }; - - this.destroy = function() { - this.red.destroy(); - this.green.destroy(); - this.blue.destroy(); - }; - - this.onValueChanged = function(value) {}; -} - -// The DirectionBox class -DirectionBox = function(x,y,width,thumbSize) { - var self = this; - - var slideHeight = thumbSize / 2; - var sliderWidth = width; - this.yaw = new Slider(x, y, width, slideHeight); - this.pitch = new Slider(x, y + slideHeight, width, slideHeight); - - this.yaw.setThumbColor({x: 1, y: 0, z: 0}); - this.yaw.minValue = -180; - this.yaw.maxValue = +180; - - this.pitch.setThumbColor({x: 0, y: 0, z: 1}); - this.pitch.minValue = -1; - this.pitch.maxValue = +1; - - this.isClickableOverlayItem = function(item) { - return this.yaw.isClickableOverlayItem(item) - || this.pitch.isClickableOverlayItem(item); - }; - - this.onMouseMoveEvent = function(event) { - this.yaw.onMouseMoveEvent(event); - this.pitch.onMouseMoveEvent(event); - }; - - this.onMousePressEvent = function(event, clickedOverlay) { - this.yaw.onMousePressEvent(event, clickedOverlay); - if (this.yaw.isMoving) { - return; - } - this.pitch.onMousePressEvent(event, clickedOverlay); - }; - - this.onMouseReleaseEvent = function(event) { - this.yaw.onMouseReleaseEvent(event); - this.pitch.onMouseReleaseEvent(event); - }; - - this.setterFromWidget = function(value) { - var yawPitch = self.getValue(); - self.onValueChanged(yawPitch); - }; - - this.yaw.onValueChanged = this.setterFromWidget; - this.pitch.onValueChanged = this.setterFromWidget; - - // Public members: - this.setValue = function(direction) { - var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); - if (flatXZ > 0.0) { - var flatX = direction.x / flatXZ; - var flatZ = direction.z / flatXZ; - var yaw = Math.acos(flatX) * 180 / Math.PI; - if (flatZ < 0) { - yaw = -yaw; - } - this.yaw.setValue(yaw); - } - this.pitch.setValue(direction.y); - }; - - this.getValue = function() { - var dirZ = this.pitch.getValue(); - var yaw = this.yaw.getValue() * Math.PI / 180; - var cosY = Math.sqrt(1 - dirZ*dirZ); - var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; - return value; - }; - - this.destroy = function() { - this.yaw.destroy(); - this.pitch.destroy(); - }; - - this.onValueChanged = function(value) {}; -} - -var textFontSize = 16; - -function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { - this.name = name; - - - this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { return value.toFixed(2); }; - - var topMargin = (height - textFontSize); - this.title = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x, - y: y, - width: textWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: name, - font: {size: textFontSize}, - topMargin: topMargin, - }); - - this.value = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, - x: x + textWidth, - y: y, - width: valueWidth, - height: height, - alpha: 1.0, - backgroundAlpha: 0.5, - visible: true, - text: this.displayer(getter()), - font: {size: textFontSize}, - topMargin: topMargin - - }); - this.getter = getter; - - this.setter = function(value) { - setter(value); - Overlays.editOverlay(this.value, {text: this.displayer(getter())}); - if (this.widget) { - this.widget.setValue(value); - } - }; - this.setterFromWidget = function(value) { - setter(value); - // ANd loop back the value after the final setter has been called - var value = getter(); - if (this.widget) { - this.widget.setValue(value); - } - Overlays.editOverlay(this.value, {text: this.displayer(value)}); - }; - - - this.widget = null; - - this.destroy = function() { - Overlays.deleteOverlay(this.title); - Overlays.deleteOverlay(this.value); - if (this.widget != null) { - this.widget.destroy(); - } - } -} - -var textWidth = 180; -var valueWidth = 100; -var widgetWidth = 300; -var rawHeight = 20; -var rawYDelta = rawHeight * 1.5; - -Panel = function(x, y) { - - this.x = x; - this.y = y; - this.nextY = y; - - this.widgetX = x + textWidth + valueWidth; - - this.items = new Array(); - this.activeWidget = null; - - this.mouseMoveEvent = function(event) { - if (this.activeWidget) { - this.activeWidget.onMouseMoveEvent(event); - } - }; - - // we also handle click detection in our mousePressEvent() - this.mousePressEvent = function(event) { - // Make sure we quitted previous widget - if (this.activeWidget) { - this.activeWidget.onMouseReleaseEvent(event); - } - this.activeWidget = null; - - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - // If the user clicked any of the slider background then... - for (var i in this.items) { - var widget = this.items[i].widget; - - if (widget.isClickableOverlayItem(clickedOverlay)) { - this.activeWidget = widget; - this.activeWidget.onMousePressEvent(event, clickedOverlay); - // print("clicked... widget=" + i); - break; - } - } - }; - - this.mouseReleaseEvent = function(event) { - if (this.activeWidget) { - this.activeWidget.onMouseReleaseEvent(event); - } - this.activeWidget = null; - }; - - this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { - - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); - slider.minValue = minValue; - slider.maxValue = maxValue; - - - item.widget = slider; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); - this.items[name] = item; - this.nextY += rawYDelta; - // print("created Item... slider=" + name); - }; - - this.newCheckbox = function(name, setValue, getValue, displayValue) { - - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var checkbox = new Checkbox(this.widgetX, this.nextY, rawHeight); - - item.widget = checkbox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); - this.items[name] = item; - this.nextY += rawYDelta; - // print("created Item... slider=" + name); - }; - - this.newColorBox = function(name, setValue, getValue, displayValue) { - - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); - - item.widget = colorBox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); - this.items[name] = item; - this.nextY += rawYDelta; - // print("created Item... colorBox=" + name); - }; - - this.newDirectionBox= function(name, setValue, getValue, displayValue) { - - var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); - - var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); - - item.widget = directionBox; - item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; - item.setter(getValue()); - this.items[name] = item; - this.nextY += rawYDelta; - // print("created Item... directionBox=" + name); - }; - - this.destroy = function() { - for (var i in this.items) { - this.items[i].destroy(); - } - } - - this.set = function(name, value) { - var item = this.items[name]; - if (item != null) { - return item.setter(value); - } - return null; - } - - this.get = function(name) { - var item = this.items[name]; - if (item != null) { - return item.getter(); - } - return null; - } - - this.getWidget = function(name) { - var item = this.items[name]; - if (item != null) { - return item.widget; - } - return null; - } - - this.update = function(name) { - var item = this.items[name]; - if (item != null) { - return item.setter(item.getter()); - } - return null; - } - -}; - - + +// +// cookies.js +// +// version 2.0 +// +// Created by Sam Gateau, 4/1/2015 +// A simple ui panel that present a list of porperties and the proper widget to edit it +// +// Modified by Bridget Went, June 2015 +// Fixed checkBox class functionality, enabled mouseDoublePressEvent to reset panel items +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +// The Slider class +Slider = function(x,y,width,thumbSize) { + this.background = Overlays.addOverlay("text", { + backgroundColor: { red: 200, green: 200, blue: 255 }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + + this.thumbSize = thumbSize; + this.thumbHalfSize = 0.5 * thumbSize; + + this.minThumbX = x + this.thumbHalfSize; + this.maxThumbX = x + width - this.thumbHalfSize; + this.thumbX = this.minThumbX; + + this.minValue = 0.0; + this.maxValue = 1.0; + + this.clickOffsetX = 0; + this.isMoving = false; + + this.updateThumb = function() { + thumbTruePos = this.thumbX - 0.5 * this.thumbSize; + Overlays.editOverlay(this.thumb, { x: thumbTruePos } ); + }; + + this.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == this.background); + }; + + this.onMouseMoveEvent = function(event) { + if (this.isMoving) { + newThumbX = event.x - this.clickOffsetX; + if (newThumbX < this.minThumbX) { + newThumbX = this.minThumbX; + } + if (newThumbX > this.maxThumbX) { + newThumbX = this.maxThumbX; + } + this.thumbX = newThumbX; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { + this.isMoving = false; + return; + } + this.isMoving = true; + var clickOffset = event.x - this.thumbX; + if ((clickOffset > -this.thumbHalfSize) && (clickOffset < this.thumbHalfSize)) { + this.clickOffsetX = clickOffset; + } else { + this.clickOffsetX = 0; + this.thumbX = event.x; + this.updateThumb(); + this.onValueChanged(this.getValue()); + } + + }; + + this.onMouseReleaseEvent = function(event) { + this.isMoving = false; + }; + + + // Public members: + this.setNormalizedValue = function(value) { + if (value < 0.0) { + this.thumbX = this.minThumbX; + } else if (value > 1.0) { + this.thumbX = this.maxThumbX; + } else { + this.thumbX = value * (this.maxThumbX - this.minThumbX) + this.minThumbX; + } + this.updateThumb(); + }; + this.getNormalizedValue = function() { + return (this.thumbX - this.minThumbX) / (this.maxThumbX - this.minThumbX); + }; + + this.setValue = function(value) { + var normValue = (value - this.minValue) / (this.maxValue - this.minValue); + this.setNormalizedValue(normValue); + }; + + this.getValue = function() { + return this.getNormalizedValue() * (this.maxValue - this.minValue) + this.minValue; + }; + + this.onValueChanged = function(value) {}; + + this.destroy = function() { + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + }; + + this.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; + this.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, {backgroundColor: { red: color.x*255, green: color.y*255, blue: color.z*255 }}); + }; +} + +// The Checkbox class +Checkbox = function(x,y,width,thumbSize) { + + this.background = Overlays.addOverlay("text", { + backgroundColor: { red: 125, green: 125, blue: 255 }, + x: x, + y: y, + width: width, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true + }); + + this.thumb = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + textFontSize: 10, + x: x, + y: y, + width: thumbSize, + height: thumbSize, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + + + this.thumbSize = thumbSize; + var checkX = x + (0.25 * thumbSize); + var checkY = y + (0.25 * thumbSize); + + + var checkMark = Overlays.addOverlay("text", { + backgroundColor: { red: 0, green: 255, blue: 0 }, + x: checkX, + y: checkY, + width: thumbSize / 2.0, + height: thumbSize / 2.0, + alpha: 1.0, + visible: true + }); + + var unCheckMark = Overlays.addOverlay("image", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: checkX + 1.0, + y: checkY + 1.0, + width: thumbSize / 2.5, + height: thumbSize / 2.5, + alpha: 1.0, + visible: boxCheckStatus + }); + + + var boxCheckStatus; + var clickedBox = false; + + this.updateThumb = function() { + if (clickedBox) { + boxCheckStatus = !boxCheckStatus; + if (boxCheckStatus) { + Overlays.editOverlay(unCheckMark, { visible: false }); + } else { + Overlays.editOverlay(unCheckMark, { visible: true }); + } + } + }; + + this.isClickableOverlayItem = function(item) { + return (item == this.thumb) || (item == checkMark) || (item == unCheckMark); + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + if (!this.isClickableOverlayItem(clickedOverlay)) { + this.isMoving = false; + clickedBox = false; + return; + } + + clickedBox = true; + this.updateThumb(); + this.onValueChanged(this.getValue()); + }; + + this.onMouseReleaseEvent = function(event) { + this.clickedBox = false; + }; + + // Public members: + this.setNormalizedValue = function(value) { + boxCheckStatus = value; + }; + + this.getNormalizedValue = function() { + return boxCheckStatus; + }; + + this.setValue = function(value) { + this.setNormalizedValue(value); + }; + + this.getValue = function() { + return boxCheckStatus; + }; + + this.onValueChanged = function(value) {}; + + this.destroy = function() { + Overlays.deleteOverlay(this.background); + Overlays.deleteOverlay(this.thumb); + Overlays.deleteOverlay(checkMark); + Overlays.deleteOverlay(unCheckMark); + }; + + this.setThumbColor = function(color) { + Overlays.editOverlay(this.thumb, { red: 255, green: 255, blue: 255 } ); + }; + this.setBackgroundColor = function(color) { + Overlays.editOverlay(this.background, { red: 125, green: 125, blue: 255 }); + }; + +} + +// The ColorBox class +ColorBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 3; + var sliderWidth = width; + this.red = new Slider(x, y, width, slideHeight); + this.green = new Slider(x, y + slideHeight, width, slideHeight); + this.blue = new Slider(x, y + 2 * slideHeight, width, slideHeight); + this.red.setBackgroundColor({x: 1, y: 0, z: 0}); + this.green.setBackgroundColor({x: 0, y: 1, z: 0}); + this.blue.setBackgroundColor({x: 0, y: 0, z: 1}); + + this.isClickableOverlayItem = function(item) { + return this.red.isClickableOverlayItem(item) + || this.green.isClickableOverlayItem(item) + || this.blue.isClickableOverlayItem(item); + }; + + this.onMouseMoveEvent = function(event) { + this.red.onMouseMoveEvent(event); + this.green.onMouseMoveEvent(event); + this.blue.onMouseMoveEvent(event); + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + this.red.onMousePressEvent(event, clickedOverlay); + if (this.red.isMoving) { + return; + } + + this.green.onMousePressEvent(event, clickedOverlay); + if (this.green.isMoving) { + return; + } + + this.blue.onMousePressEvent(event, clickedOverlay); + }; + + this.onMouseReleaseEvent = function(event) { + this.red.onMouseReleaseEvent(event); + this.green.onMouseReleaseEvent(event); + this.blue.onMouseReleaseEvent(event); + }; + + this.setterFromWidget = function(value) { + var color = self.getValue(); + self.onValueChanged(color); + self.updateRGBSliders(color); + }; + + this.red.onValueChanged = this.setterFromWidget; + this.green.onValueChanged = this.setterFromWidget; + this.blue.onValueChanged = this.setterFromWidget; + + this.updateRGBSliders = function(color) { + this.red.setThumbColor({x: color.x, y: 0, z: 0}); + this.green.setThumbColor({x: 0, y: color.y, z: 0}); + this.blue.setThumbColor({x: 0, y: 0, z: color.z}); + }; + + // Public members: + this.setValue = function(value) { + this.red.setValue(value.x); + this.green.setValue(value.y); + this.blue.setValue(value.z); + this.updateRGBSliders(value); + }; + + this.getValue = function() { + var value = {x:this.red.getValue(), y:this.green.getValue(),z:this.blue.getValue()}; + return value; + }; + + this.destroy = function() { + this.red.destroy(); + this.green.destroy(); + this.blue.destroy(); + }; + + this.onValueChanged = function(value) {}; +} + +// The DirectionBox class +DirectionBox = function(x,y,width,thumbSize) { + var self = this; + + var slideHeight = thumbSize / 2; + var sliderWidth = width; + this.yaw = new Slider(x, y, width, slideHeight); + this.pitch = new Slider(x, y + slideHeight, width, slideHeight); + + this.yaw.setThumbColor({x: 1, y: 0, z: 0}); + this.yaw.minValue = -180; + this.yaw.maxValue = +180; + + this.pitch.setThumbColor({x: 0, y: 0, z: 1}); + this.pitch.minValue = -1; + this.pitch.maxValue = +1; + + this.isClickableOverlayItem = function(item) { + return this.yaw.isClickableOverlayItem(item) + || this.pitch.isClickableOverlayItem(item); + }; + + this.onMouseMoveEvent = function(event) { + this.yaw.onMouseMoveEvent(event); + this.pitch.onMouseMoveEvent(event); + }; + + this.onMousePressEvent = function(event, clickedOverlay) { + this.yaw.onMousePressEvent(event, clickedOverlay); + if (this.yaw.isMoving) { + return; + } + this.pitch.onMousePressEvent(event, clickedOverlay); + }; + + this.onMouseReleaseEvent = function(event) { + this.yaw.onMouseReleaseEvent(event); + this.pitch.onMouseReleaseEvent(event); + }; + + this.setterFromWidget = function(value) { + var yawPitch = self.getValue(); + self.onValueChanged(yawPitch); + }; + + this.yaw.onValueChanged = this.setterFromWidget; + this.pitch.onValueChanged = this.setterFromWidget; + + // Public members: + this.setValue = function(direction) { + var flatXZ = Math.sqrt(direction.x * direction.x + direction.z * direction.z); + if (flatXZ > 0.0) { + var flatX = direction.x / flatXZ; + var flatZ = direction.z / flatXZ; + var yaw = Math.acos(flatX) * 180 / Math.PI; + if (flatZ < 0) { + yaw = -yaw; + } + this.yaw.setValue(yaw); + } + this.pitch.setValue(direction.y); + }; + + this.getValue = function() { + var dirZ = this.pitch.getValue(); + var yaw = this.yaw.getValue() * Math.PI / 180; + var cosY = Math.sqrt(1 - dirZ*dirZ); + var value = {x:cosY * Math.cos(yaw), y:dirZ, z: cosY * Math.sin(yaw)}; + return value; + }; + + this.destroy = function() { + this.yaw.destroy(); + this.pitch.destroy(); + }; + + this.onValueChanged = function(value) {}; +} + +var textFontSize = 12; + +function PanelItem(name, setter, getter, displayer, x, y, textWidth, valueWidth, height) { + //print("creating panel item: " + name); + + this.name = name; + + this.displayer = typeof displayer !== 'undefined' ? displayer : function(value) { + if(value == true) { + return "On"; + } else if (value == false) { + return "Off"; + } + return value.toFixed(2); + }; + + var topMargin = (height - textFontSize); + this.title = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x, + y: y, + width: textWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: name, + font: {size: textFontSize}, + topMargin: topMargin, + }); + + this.value = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: x + textWidth, + y: y, + width: valueWidth, + height: height, + alpha: 1.0, + backgroundAlpha: 0.5, + visible: true, + text: this.displayer(getter()), + font: {size: textFontSize}, + topMargin: topMargin + }); + + this.getter = getter; + this.resetValue = getter(); + + this.setter = function(value) { + + setter(value); + + Overlays.editOverlay(this.value, {text: this.displayer(getter())}); + + if (this.widget) { + this.widget.setValue(value); + } + + //print("successfully set value of widget to " + value); + }; + this.setterFromWidget = function(value) { + setter(value); + // ANd loop back the value after the final setter has been called + var value = getter(); + + if (this.widget) { + this.widget.setValue(value); + } + Overlays.editOverlay(this.value, {text: this.displayer(value)}); + }; + + + this.widget = null; + + this.destroy = function() { + Overlays.deleteOverlay(this.title); + Overlays.deleteOverlay(this.value); + if (this.widget != null) { + this.widget.destroy(); + } + } +} + +var textWidth = 180; +var valueWidth = 100; +var widgetWidth = 300; +var rawHeight = 20; +var rawYDelta = rawHeight * 1.5; + +Panel = function(x, y) { + + this.x = x; + this.y = y; + this.nextY = y; + + this.widgetX = x + textWidth + valueWidth; + + this.items = new Array(); + this.activeWidget = null; + + this.mouseMoveEvent = function(event) { + if (this.activeWidget) { + this.activeWidget.onMouseMoveEvent(event); + } + }; + + this.mousePressEvent = function(event) { + // Make sure we quitted previous widget + if (this.activeWidget) { + this.activeWidget.onMouseReleaseEvent(event); + } + this.activeWidget = null; + + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + // If the user clicked any of the slider background then... + for (var i in this.items) { + var widget = this.items[i].widget; + + if (widget.isClickableOverlayItem(clickedOverlay)) { + this.activeWidget = widget; + this.activeWidget.onMousePressEvent(event, clickedOverlay); + + break; + } + } + }; + + // Reset panel item upon double-clicking + this.mouseDoublePressEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + for (var i in this.items) { + + var item = this.items[i]; + var widget = item.widget; + + if (item.title == clickedOverlay || item.value == clickedOverlay) { + widget.updateThumb(); + widget.onValueChanged(item.resetValue); + break; + } + } + } + + this.mouseReleaseEvent = function(event) { + if (this.activeWidget) { + this.activeWidget.onMouseReleaseEvent(event); + } + this.activeWidget = null; + }; + + this.newSlider = function(name, minValue, maxValue, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var slider = new Slider(this.widgetX, this.nextY, widgetWidth, rawHeight); + slider.minValue = minValue; + slider.maxValue = maxValue; + + item.widget = slider; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + }; + + this.newCheckbox = function(name, setValue, getValue, displayValue) { + var display; + if (displayValue == true) { + display = function() {return "On";}; + } else if (displayValue == false) { + display = function() {return "Off";}; + } + + var item = new PanelItem(name, setValue, getValue, display, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var checkbox = new Checkbox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = checkbox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + //print("created Item... checkbox=" + name); + }; + + this.newColorBox = function(name, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var colorBox = new ColorBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = colorBox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + // print("created Item... colorBox=" + name); + }; + + this.newDirectionBox= function(name, setValue, getValue, displayValue) { + + var item = new PanelItem(name, setValue, getValue, displayValue, this.x, this.nextY, textWidth, valueWidth, rawHeight); + + var directionBox = new DirectionBox(this.widgetX, this.nextY, widgetWidth, rawHeight); + + item.widget = directionBox; + item.widget.onValueChanged = function(value) { item.setterFromWidget(value); }; + item.setter(getValue()); + this.items[name] = item; + this.nextY += rawYDelta; + // print("created Item... directionBox=" + name); + }; + + this.destroy = function() { + for (var i in this.items) { + this.items[i].destroy(); + } + } + + this.set = function(name, value) { + var item = this.items[name]; + if (item != null) { + return item.setter(value); + } + return null; + } + + this.get = function(name) { + var item = this.items[name]; + if (item != null) { + return item.getter(); + } + return null; + } + + this.update = function(name) { + var item = this.items[name]; + if (item != null) { + return item.setter(item.getter()); + } + return null; + } + +}; + + From e63be582518cf024e4cca5d5d313754db7dcfc7b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Jul 2015 12:23:57 -0700 Subject: [PATCH 34/39] CLenaing the interface of Item::Status to be more explicit --- libraries/render/src/render/DrawStatus.cpp | 2 +- libraries/render/src/render/Scene.cpp | 44 +++++++++++++++++++-- libraries/render/src/render/Scene.h | 45 +++++++++++----------- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 3c92e8f0b2..27ad0adb72 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -116,7 +116,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex (*itemAABox).setBox(item.bounds.getCorner(), 0.1f); } auto& itemScene = scene->getItem(item.id); - (*itemStatus) = itemScene.getStatusCompressedValues(); + (*itemStatus) = itemScene.getStatusPackedValues(); nbItems++; itemAABox++; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 1ed66e4912..dca32a7828 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -10,6 +10,8 @@ // #include "Scene.h" +#include + using namespace render; void ItemBucketMap::insert(const ItemID& id, const ItemKey& key) { @@ -55,16 +57,41 @@ void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { const Item::Status::Value Item::Status::Value::INVALID = Item::Status::Value(); -void Item::Status::getCompressedValues(glm::ivec4& values) { - for (int i = 0; i < values.length(); i++) { + +void Item::Status::Value::setScale(float scale) { + _scale = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), -1.0f)); + } + +void Item::Status::Value::setColor(float hue) { + _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, 1.0f), -1.0f)); +} + +void Item::Status::getPackedValues(glm::ivec4& values) const { + for (unsigned int i = 0; i < values.length(); i++) { if (i < _values.size()) { - values[i] = _values[i]().getRaw(); + values[i] = _values[i]().getPackedData(); } else { - values[i] = Value::INVALID.getRaw(); + values[i] = Value::INVALID.getPackedData(); } } } +void Item::PayloadInterface::addStatusGetter(const Status::Getter& getter) { + if (!_status) { + _status.reset(new Status()); + } + _status->addGetter(getter); +} + +void Item::PayloadInterface::addStatusGetters(const Status::Getters& getters) { + if (!_status) { + _status.reset(new Status()); + } + for (auto& g : getters) { + _status->addGetter(g); + } +} + void Item::resetPayload(const PayloadPointer& payload) { if (!payload) { kill(); @@ -74,6 +101,15 @@ void Item::resetPayload(const PayloadPointer& payload) { } } +glm::ivec4 Item::getStatusPackedValues() const { + glm::ivec4 values(Status::Value::INVALID.getPackedData()); + auto& status = getStatus(); + if (status) { + status->getPackedValues(values); + }; + return values; +} + void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { _resetItems.push_back(id); _resetPayloads.push_back(payload); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index b846c60cfe..4a6265990d 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -201,18 +200,24 @@ public: // This is Used for monitoring and dynamically adjust the quality class Status { public: - class Value { - unsigned short _x = 0xFFFF; - unsigned short _y = 0xFFFF; - Value() {} - public: - const static Value INVALID; // Invlaid value meanss the status won't show - Value(float x, float y = 1.0f) { setX(x); setY(y); } - void setX(float x) { _x = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(x, 1.0f), -1.0f)); } - void setY(float y) { _y = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(y, 1.0f), -1.0f)); } - - int getRaw() const { return *((const int*) this); } + // Status::Value class is the data used to represent the transient information of a status as a square icon + // The "icon" is a square displayed in the 3D scene over the render::Item AABB center. + // It can be scaled in the range [0, 1] and the color hue can + class Value { + unsigned short _scale = 0xFFFF; + unsigned short _color = 0xFFFF; + public: + const static Value INVALID; // Invalid value meanss the status won't show + + Value() {} + Value(float scale, float hue) { setScale(scale); setColor(hue); } + + void setScale(float scale); + void setColor(float hue); + + // Retreive the Value data tightely packed as an int + int getPackedData() const { return *((const int*) this); } }; typedef std::function Getter; @@ -221,7 +226,8 @@ public: Getters _values; void addGetter(const Getter& getter) { _values.push_back(getter); } - void getCompressedValues(glm::ivec4& values); + + void getPackedValues(glm::ivec4& values) const; }; typedef std::shared_ptr StatusPointer; @@ -247,15 +253,8 @@ public: // Status interface is local to the base class const StatusPointer& getStatus() const { return _status; } - void addStatusGetter(const Status::Getter& getter) { if (!_status) { _status.reset(new Status());} _status->addGetter(getter); } - void addStatusGetters(const Status::Getters& getters) { - if (!_status) { - _status.reset(new Status()); - } - for (auto& g : getters) { - _status->addGetter(g); - } - } + void addStatusGetter(const Status::Getter& getter); + void addStatusGetters(const Status::Getters& getters); protected: StatusPointer _status; @@ -292,7 +291,7 @@ public: // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } - glm::ivec4 getStatusCompressedValues() const { glm::ivec4 values(Status::Value::INVALID.getRaw()); auto& status = getStatus(); if (status) { status->getCompressedValues(values); }; return values; } + glm::ivec4 getStatusPackedValues() const; protected: PayloadPointer _payload; From 95f5b14d45041830b96a23a4f2e6d5da1b733ea2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Jul 2015 12:47:35 -0700 Subject: [PATCH 35/39] CLenaing the interface of Item::Status to be more explicit and removing magic numbers --- .../src/RenderableModelEntityItem.cpp | 14 ++++++++++---- libraries/render/src/render/DrawStatus.cpp | 6 ++++-- libraries/render/src/render/Scene.cpp | 5 +++-- libraries/render/src/render/Scene.h | 4 +++- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index dc90a676fb..fb8006c60f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -170,13 +170,19 @@ namespace render { void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item::Status::Getters& statusGetters) { statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote(); - float ndelta = (delta / (0.2f * USECS_PER_SECOND)); - return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.01f : 0.5f)); + const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); + float normalizedDelta = delta * WAIT_THRESHOLD_INV; + // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD + // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? 0.0f : 120.0f)); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); - float ndelta = (delta / (0.4f * USECS_PER_SECOND)); - return render::Item::Status::Value(1.0f - ndelta, (ndelta > 1.0f ? 0.3f : 0.9f)); + const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND); + float normalizedDelta = delta * WAIT_THRESHOLD_INV; + // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD + // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? 300.0f : 180.0f)); }); } diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 27ad0adb72..90d167cc2a 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -149,9 +149,11 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex AABox* itemAABox = reinterpret_cast (_itemBounds->editData()); glm::ivec4* itemStatus = reinterpret_cast (_itemStatus->editData()); + const unsigned int VEC3_ADRESS_OFFSET = 3; + for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const GLfloat*) (itemAABox + i)); - batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); batch.draw(gpu::LINES, 24, 0); } @@ -159,7 +161,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex batch.setPipeline(getDrawItemStatusPipeline()); for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const GLfloat*) (itemAABox + i)); - batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + 3); + batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const GLfloat*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const GLint*) (itemStatus + i)); batch.draw(gpu::TRIANGLES, 24, 0); diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index dca32a7828..d593eeb2bb 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -59,11 +59,12 @@ const Item::Status::Value Item::Status::Value::INVALID = Item::Status::Value(); void Item::Status::Value::setScale(float scale) { - _scale = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), -1.0f)); + _scale = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f)); } void Item::Status::Value::setColor(float hue) { - _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, 1.0f), -1.0f)); + // Convert the HUe from range [0, 360] to signed normalized value + _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, 360.0f), 0.0f)); } void Item::Status::getPackedValues(glm::ivec4& values) const { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 4a6265990d..8fc27b529a 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -203,7 +203,7 @@ public: // Status::Value class is the data used to represent the transient information of a status as a square icon // The "icon" is a square displayed in the 3D scene over the render::Item AABB center. - // It can be scaled in the range [0, 1] and the color hue can + // It can be scaled in the range [0, 1] and the color hue in the range [0, 360] representing the color wheel hue class Value { unsigned short _scale = 0xFFFF; unsigned short _color = 0xFFFF; @@ -213,7 +213,9 @@ public: Value() {} Value(float scale, float hue) { setScale(scale); setColor(hue); } + // It can be scaled in the range [0, 1] void setScale(float scale); + // the color hue in the range [0, 360] representing the color wheel hue void setColor(float hue); // Retreive the Value data tightely packed as an int From 5d91f1be834ce46555a1831847623df0e5df7fa0 Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 6 Jul 2015 13:26:16 -0700 Subject: [PATCH 36/39] Removed header comments --- examples/utilities/tools/cookies.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index f217b28aae..7433475cdb 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -7,8 +7,6 @@ // Created by Sam Gateau, 4/1/2015 // A simple ui panel that present a list of porperties and the proper widget to edit it // -// Modified by Bridget Went, June 2015 -// Fixed checkBox class functionality, enabled mouseDoublePressEvent to reset panel items // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From 4d48b983647929a245fd07d590656c5569c8456c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Jul 2015 14:22:09 -0700 Subject: [PATCH 37/39] For a fistfull of magic numbers --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- libraries/render/src/render/Scene.cpp | 9 ++++++++- libraries/render/src/render/Scene.h | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index fb8006c60f..ae1c97f07f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -174,7 +174,7 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? 0.0f : 120.0f)); + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::GREEN : render::Item::Status::Value::RED)); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { quint64 delta = usecTimestampNow() - entity->getLastBroadcast(); @@ -182,7 +182,7 @@ void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) - return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? 300.0f : 180.0f)); + return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::MAGENTA : render::Item::Status::Value::CYAN)); }); } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index d593eeb2bb..a7145af4b5 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -57,6 +57,12 @@ void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { const Item::Status::Value Item::Status::Value::INVALID = Item::Status::Value(); +const float Item::Status::Value::RED = 0.0f; +const float Item::Status::Value::YELLOW = 60.0f; +const float Item::Status::Value::GREEN = 120.0f; +const float Item::Status::Value::CYAN = 180.0f; +const float Item::Status::Value::BLUE = 240.0f; +const float Item::Status::Value::MAGENTA = 300.0f; void Item::Status::Value::setScale(float scale) { _scale = (std::numeric_limits::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f)); @@ -64,7 +70,8 @@ void Item::Status::Value::setScale(float scale) { void Item::Status::Value::setColor(float hue) { // Convert the HUe from range [0, 360] to signed normalized value - _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, 360.0f), 0.0f)); + const float HUE_MAX = 360.0f; + _color = (std::numeric_limits::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, HUE_MAX), 0.0f) / HUE_MAX); } void Item::Status::getPackedValues(glm::ivec4& values) const { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 8fc27b529a..934b460e52 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -218,6 +218,14 @@ public: // the color hue in the range [0, 360] representing the color wheel hue void setColor(float hue); + // Standard color Hue + static const float RED; // 0.0f; + static const float YELLOW; // 60.0f; + static const float GREEN; // 120.0f; + static const float CYAN; // 180.0f; + static const float BLUE; // 240.0f; + static const float MAGENTA; // 300.0f; + // Retreive the Value data tightely packed as an int int getPackedData() const { return *((const int*) this); } }; From 2bdd2b8c2cc3e7c264ae2d15cbb8fa0683c57b09 Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 6 Jul 2015 15:02:51 -0700 Subject: [PATCH 38/39] Update cookies.js --- examples/utilities/tools/cookies.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index 7433475cdb..c3930e18c5 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -1,4 +1,3 @@ - // // cookies.js // @@ -7,7 +6,6 @@ // Created by Sam Gateau, 4/1/2015 // A simple ui panel that present a list of porperties and the proper widget to edit it // -// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From 8b4398cd5a626067346a96e8aded574b67489653 Mon Sep 17 00:00:00 2001 From: bwent Date: Mon, 6 Jul 2015 15:03:21 -0700 Subject: [PATCH 39/39] Update cookies.js --- examples/utilities/tools/cookies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/utilities/tools/cookies.js b/examples/utilities/tools/cookies.js index c3930e18c5..0fdae01c5e 100644 --- a/examples/utilities/tools/cookies.js +++ b/examples/utilities/tools/cookies.js @@ -8,7 +8,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - +// // The Slider class Slider = function(x,y,width,thumbSize) { this.background = Overlays.addOverlay("text", {