From 671f27e5bc3950cc75884a5b8b0e6b6221011cb5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 28 Jan 2016 12:05:59 -0800 Subject: [PATCH 01/27] Move DrawStencil to use ShapePlumber --- .../render-utils/src/RenderDeferredTask.cpp | 33 ++++++++----------- .../render-utils/src/RenderDeferredTask.h | 4 +-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d76d0a77de..9ae76bfe02 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -256,25 +256,19 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon } } -gpu::PipelinePointer DrawStencilDeferred::_opaquePipeline; -const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { - if (!_opaquePipeline) { - const gpu::int8 STENCIL_OPAQUE = 1; - auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - +DrawStencilDeferred::DrawStencilDeferred() : _shapePlumber{ std::make_shared() } { + const gpu::int8 STENCIL_OPAQUE = 1; + auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram((*program)); - gpu::Shader::makeProgram((*program)); + auto state = std::make_shared(); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); + state->setColorWriteMask(0); - auto state = std::make_shared(); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); - state->setColorWriteMask(0); - - _opaquePipeline = gpu::Pipeline::create(program, state); - } - return _opaquePipeline; + _shapePlumber->addPipeline(ShapeKey::Filter::Builder(), program, state); } void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -294,11 +288,12 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - batch.setPipeline(getOpaquePipeline()); + // We only need to fetch this once + static const auto& pipeline = _shapePlumber->pickPipeline(args, ShapeKey()); + batch.setPipeline(pipeline->pipeline); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, nullptr); - }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 8d773a9b21..2ebb2e4e12 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -68,14 +68,14 @@ protected: class DrawStencilDeferred { public: - static const gpu::PipelinePointer& getOpaquePipeline(); + DrawStencilDeferred(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); using JobModel = render::Job::Model; protected: - static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable + render::ShapePlumberPointer _shapePlumber; }; class DrawBackgroundDeferred { From df894d364a032fcc31837838e802621c96a7dbb6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 28 Jan 2016 12:25:31 -0800 Subject: [PATCH 02/27] Move DrawOverlay3D to use ShapePlumber --- .../render-utils/src/RenderDeferredTask.cpp | 39 ++++++++++--------- .../render-utils/src/RenderDeferredTask.h | 5 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 9ae76bfe02..15a37998ca 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -128,7 +128,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); } - addJob("DrawOverlay3D", shapePlumber); + addJob("DrawOverlay3D"); addJob("HitEffect"); @@ -180,22 +180,26 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont }); } -// TODO: Move this to the shapePlumber -gpu::PipelinePointer DrawOverlay3D::_opaquePipeline; -const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { - if (!_opaquePipeline) { - auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); - auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - - auto state = std::make_shared(); - state->setDepthTest(false); - // additive blending - state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); +DrawOverlay3D::DrawOverlay3D() : _shapePlumber{ std::make_shared() } { + auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); + auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); + auto program = gpu::Shader::createProgram(vs, ps); - _opaquePipeline = gpu::Pipeline::create(program, state); - } - return _opaquePipeline; + auto opaqueState = std::make_shared(); + opaqueState->setDepthTest(false); + opaqueState->setBlendFunction(true, + // Additive blending + gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + auto transparentState = std::make_shared(); + transparentState->setDepthTest(false); + transparentState->setBlendFunction(true, + // For transparency, keep the highlight intensity + gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + _shapePlumber->addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState); + _shapePlumber->addPipeline(ShapeKey::Filter::Builder().withTranslucent(), program, transparentState); } void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -246,9 +250,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setViewTransform(viewMat); batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - - batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); }); args->_batch = nullptr; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2ebb2e4e12..894a91cdc3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -106,15 +106,12 @@ public: using Config = DrawOverlay3DConfig; using JobModel = render::Job::Model; - DrawOverlay3D(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawOverlay3D(); void configure(const Config& config) { _maxDrawn = config.maxDrawn; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - static const gpu::PipelinePointer& getOpaquePipeline(); - protected: - static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable render::ShapePlumberPointer _shapePlumber; int _maxDrawn; // initialized by Config }; From 5d49eacf83c3e4e850acffd38c6a8292293f786d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 28 Jan 2016 15:51:56 -0800 Subject: [PATCH 03/27] Move pipeline init to separate file --- .../render-utils/src/RenderDeferredTask.cpp | 228 +---------------- .../render-utils/src/RenderPipelines.cpp | 234 ++++++++++++++++++ 2 files changed, 240 insertions(+), 222 deletions(-) create mode 100644 libraries/render-utils/src/RenderPipelines.cpp diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 15a37998ca..8a47280526 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -4,7 +4,7 @@ // render-utils/src/ // // Created by Sam Gateau on 5/29/15. -// Copyright 20154 High Fidelity, Inc. +// Copyright 2016 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 @@ -15,7 +15,6 @@ #include #include #include -#include #include "DebugDeferredBuffer.h" #include "DeferredLightingEffect.h" @@ -31,34 +30,11 @@ #include "RenderDeferredTask.h" -#include "model_vert.h" -#include "model_shadow_vert.h" -#include "model_normal_map_vert.h" -#include "model_lightmap_vert.h" -#include "model_lightmap_normal_map_vert.h" -#include "skin_model_vert.h" -#include "skin_model_shadow_vert.h" -#include "skin_model_normal_map_vert.h" - -#include "model_frag.h" -#include "model_shadow_frag.h" -#include "model_normal_map_frag.h" -#include "model_normal_specular_map_frag.h" -#include "model_specular_map_frag.h" -#include "model_lightmap_frag.h" -#include "model_lightmap_normal_map_frag.h" -#include "model_lightmap_normal_specular_map_frag.h" -#include "model_lightmap_specular_map_frag.h" -#include "model_translucent_frag.h" - -#include "overlay3D_vert.h" -#include "overlay3D_frag.h" - -#include "drawOpaqueStencil_frag.h" - using namespace render; -void initDeferredPipelines(render::ShapePlumber& plumber); +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initStencilPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber); void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { DependencyManager::get()->prepare(renderContext->args); @@ -181,25 +157,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont } DrawOverlay3D::DrawOverlay3D() : _shapePlumber{ std::make_shared() } { - auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); - auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - - auto opaqueState = std::make_shared(); - opaqueState->setDepthTest(false); - opaqueState->setBlendFunction(true, - // Additive blending - gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - auto transparentState = std::make_shared(); - transparentState->setDepthTest(false); - transparentState->setBlendFunction(true, - // For transparency, keep the highlight intensity - gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - _shapePlumber->addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState); - _shapePlumber->addPipeline(ShapeKey::Filter::Builder().withTranslucent(), program, transparentState); + initOverlay3DPipelines(*_shapePlumber); } void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -260,18 +218,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon } DrawStencilDeferred::DrawStencilDeferred() : _shapePlumber{ std::make_shared() } { - const gpu::int8 STENCIL_OPAQUE = 1; - auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); - auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - gpu::Shader::makeProgram((*program)); - - auto state = std::make_shared(); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); - state->setColorWriteMask(0); - - _shapePlumber->addPipeline(ShapeKey::Filter::Builder(), program, state); + initStencilPipelines(*_shapePlumber); } void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -411,166 +358,3 @@ void Blit::run(const SceneContextPointer& sceneContext, const RenderContextPoint } }); } - -void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { - if (pipeline.locations->normalFittingMapUnit > -1) { - batch.setResourceTexture(pipeline.locations->normalFittingMapUnit, - DependencyManager::get()->getNormalFittingTexture()); - } -} - -void initDeferredPipelines(render::ShapePlumber& plumber) { - using Key = render::ShapeKey; - using ShaderPointer = gpu::ShaderPointer; - - auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) { - auto state = std::make_shared(); - - // Cull backface - state->setCullMode(gpu::State::CULL_BACK); - - // Z test depends on transparency - state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); - - // Blend if transparent - state->setBlendFunction(key.isTranslucent(), - // For transparency, keep the highlight intensity - gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); - plumber.addPipeline(key, program, state, &pipelineBatchSetter); - - // Add a wireframe version - if (!key.isWireFrame()) { - auto wireFrameKey = Key::Builder(key).withWireframe(); - auto wireFrameState = std::make_shared(state->getValues()); - - wireFrameState->setFillMode(gpu::State::FILL_LINE); - - plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter); - } - }; - - // Vertex shaders - auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); - auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); - auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); - auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); - auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); - auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); - auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); - auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); - - // Pixel shaders - auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); - auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); - auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); - auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); - auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); - auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); - auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); - auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); - auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); - auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); - - // Fill the pipelineLib - addPipeline( - Key::Builder(), - modelVertex, modelPixel); - - addPipeline( - Key::Builder().withTangents(), - modelNormalMapVertex, modelNormalMapPixel); - - addPipeline( - Key::Builder().withSpecular(), - modelVertex, modelSpecularMapPixel); - - addPipeline( - Key::Builder().withTangents().withSpecular(), - modelNormalMapVertex, modelNormalSpecularMapPixel); - - - addPipeline( - Key::Builder().withTranslucent(), - modelVertex, modelTranslucentPixel); - // FIXME Ignore lightmap for translucents meshpart - addPipeline( - Key::Builder().withTranslucent().withLightmap(), - modelVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withTangents().withTranslucent(), - modelNormalMapVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withSpecular().withTranslucent(), - modelVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withTangents().withSpecular().withTranslucent(), - modelNormalMapVertex, modelTranslucentPixel); - - - addPipeline( - Key::Builder().withLightmap(), - modelLightmapVertex, modelLightmapPixel); - - addPipeline( - Key::Builder().withLightmap().withTangents(), - modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - - addPipeline( - Key::Builder().withLightmap().withSpecular(), - modelLightmapVertex, modelLightmapSpecularMapPixel); - - addPipeline( - Key::Builder().withLightmap().withTangents().withSpecular(), - modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - - - addPipeline( - Key::Builder().withSkinned(), - skinModelVertex, modelPixel); - - addPipeline( - Key::Builder().withSkinned().withTangents(), - skinModelNormalMapVertex, modelNormalMapPixel); - - addPipeline( - Key::Builder().withSkinned().withSpecular(), - skinModelVertex, modelSpecularMapPixel); - - addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), - skinModelNormalMapVertex, modelNormalSpecularMapPixel); - - - addPipeline( - Key::Builder().withSkinned().withTranslucent(), - skinModelVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withSkinned().withTangents().withTranslucent(), - skinModelNormalMapVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withSkinned().withSpecular().withTranslucent(), - skinModelVertex, modelTranslucentPixel); - - addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), - skinModelNormalMapVertex, modelTranslucentPixel); - - - addPipeline( - Key::Builder().withDepthOnly(), - modelShadowVertex, modelShadowPixel); - - - addPipeline( - Key::Builder().withSkinned().withDepthOnly(), - skinModelShadowVertex, modelShadowPixel); -} - diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp new file mode 100644 index 0000000000..a7e9081d9a --- /dev/null +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -0,0 +1,234 @@ + +// +// RenderPipelines.cpp +// render-utils/src/ +// +// Created by Zach Pomerantz on 1/28/2016. +// Copyright 2016 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 "TextureCache.h" +#include "render/DrawTask.h" + +#include "model_vert.h" +#include "model_shadow_vert.h" +#include "model_normal_map_vert.h" +#include "model_lightmap_vert.h" +#include "model_lightmap_normal_map_vert.h" +#include "skin_model_vert.h" +#include "skin_model_shadow_vert.h" +#include "skin_model_normal_map_vert.h" + +#include "model_frag.h" +#include "model_shadow_frag.h" +#include "model_normal_map_frag.h" +#include "model_normal_specular_map_frag.h" +#include "model_specular_map_frag.h" +#include "model_lightmap_frag.h" +#include "model_lightmap_normal_map_frag.h" +#include "model_lightmap_normal_specular_map_frag.h" +#include "model_lightmap_specular_map_frag.h" +#include "model_translucent_frag.h" + +#include "overlay3D_vert.h" +#include "overlay3D_frag.h" + +#include "drawOpaqueStencil_frag.h" + +using namespace render; + +void initOverlay3DPipelines(ShapePlumber& plumber) { + auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); + auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + + auto opaqueState = std::make_shared(); + opaqueState->setDepthTest(false); + opaqueState->setBlendFunction(false); + + plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState); +} + +void initStencilPipelines(ShapePlumber& plumber) { + const gpu::int8 STENCIL_OPAQUE = 1; + auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram((*program)); + + auto state = std::make_shared(); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); + state->setColorWriteMask(0); + + plumber.addPipeline(ShapeKey::Filter::Builder(), program, state); +} + +void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { + if (pipeline.locations->normalFittingMapUnit > -1) { + batch.setResourceTexture(pipeline.locations->normalFittingMapUnit, + DependencyManager::get()->getNormalFittingTexture()); + } +} + +void initDeferredPipelines(render::ShapePlumber& plumber) { + using Key = render::ShapeKey; + using ShaderPointer = gpu::ShaderPointer; + + auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) { + auto state = std::make_shared(); + + // Cull backface + state->setCullMode(gpu::State::CULL_BACK); + + // Z test depends on transparency + state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); + + // Blend if transparent + state->setBlendFunction(key.isTranslucent(), + // For transparency, keep the highlight intensity + gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); + plumber.addPipeline(key, program, state, &pipelineBatchSetter); + + // Add a wireframe version + if (!key.isWireFrame()) { + auto wireFrameKey = Key::Builder(key).withWireframe(); + auto wireFrameState = std::make_shared(state->getValues()); + + wireFrameState->setFillMode(gpu::State::FILL_LINE); + + plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter); + } + }; + + // Vertex shaders + auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); + auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); + auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); + auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); + auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); + auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); + auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + + // Pixel shaders + auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); + auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); + auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); + auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); + auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); + auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); + auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); + auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); + auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + + // Fill the pipelineLib + addPipeline( + Key::Builder(), + modelVertex, modelPixel); + + addPipeline( + Key::Builder().withTangents(), + modelNormalMapVertex, modelNormalMapPixel); + + addPipeline( + Key::Builder().withSpecular(), + modelVertex, modelSpecularMapPixel); + + addPipeline( + Key::Builder().withTangents().withSpecular(), + modelNormalMapVertex, modelNormalSpecularMapPixel); + + + addPipeline( + Key::Builder().withTranslucent(), + modelVertex, modelTranslucentPixel); + // FIXME Ignore lightmap for translucents meshpart + addPipeline( + Key::Builder().withTranslucent().withLightmap(), + modelVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withTangents().withTranslucent(), + modelNormalMapVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withSpecular().withTranslucent(), + modelVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withTangents().withSpecular().withTranslucent(), + modelNormalMapVertex, modelTranslucentPixel); + + + addPipeline( + Key::Builder().withLightmap(), + modelLightmapVertex, modelLightmapPixel); + + addPipeline( + Key::Builder().withLightmap().withTangents(), + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); + + addPipeline( + Key::Builder().withLightmap().withSpecular(), + modelLightmapVertex, modelLightmapSpecularMapPixel); + + addPipeline( + Key::Builder().withLightmap().withTangents().withSpecular(), + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + + + addPipeline( + Key::Builder().withSkinned(), + skinModelVertex, modelPixel); + + addPipeline( + Key::Builder().withSkinned().withTangents(), + skinModelNormalMapVertex, modelNormalMapPixel); + + addPipeline( + Key::Builder().withSkinned().withSpecular(), + skinModelVertex, modelSpecularMapPixel); + + addPipeline( + Key::Builder().withSkinned().withTangents().withSpecular(), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); + + + addPipeline( + Key::Builder().withSkinned().withTranslucent(), + skinModelVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withSkinned().withTangents().withTranslucent(), + skinModelNormalMapVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withSkinned().withSpecular().withTranslucent(), + skinModelVertex, modelTranslucentPixel); + + addPipeline( + Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), + skinModelNormalMapVertex, modelTranslucentPixel); + + + addPipeline( + Key::Builder().withDepthOnly(), + modelShadowVertex, modelShadowPixel); + + + addPipeline( + Key::Builder().withSkinned().withDepthOnly(), + skinModelShadowVertex, modelShadowPixel); +} + From 095f0b93490633524f2ea2a68f802371cb5b61ac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Feb 2016 16:46:11 -0800 Subject: [PATCH 04/27] rename canAdjustLocks to isAllowedEditor for multi-purpose --- assignment-client/src/audio/AudioMixer.cpp | 2 +- domain-server/src/DomainGatekeeper.cpp | 14 +++++++------- domain-server/src/DomainServer.cpp | 2 +- .../entities/src/EntityScriptingInterface.cpp | 4 ++-- libraries/entities/src/EntityTree.cpp | 4 ++-- libraries/networking/src/LimitedNodeList.cpp | 15 +++++++-------- libraries/networking/src/LimitedNodeList.h | 10 +++++----- libraries/networking/src/Node.cpp | 8 ++++---- libraries/networking/src/Node.h | 8 ++++---- libraries/networking/src/NodeList.cpp | 12 ++++++------ 10 files changed, 39 insertions(+), 40 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d85e1d137b..8967436e2d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -551,7 +551,7 @@ void AudioMixer::handleNodeAudioPacket(QSharedPointer message, void AudioMixer::handleMuteEnvironmentPacket(QSharedPointer message, SharedNodePointer sendingNode) { auto nodeList = DependencyManager::get(); - if (sendingNode->getCanAdjustLocks()) { + if (sendingNode->isAllowedEditor()) { auto newPacket = NLPacket::create(PacketType::MuteEnvironment, message->getSize()); // Copy payload newPacket->write(message->getRawMessage(), message->getSize()); diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index fb67744d6e..3e4ee7b758 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -155,7 +155,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo _pendingAssignedNodes.erase(it); // always allow assignment clients to create and destroy entities - newNode->setCanAdjustLocks(true); + newNode->setIsAllowedEditor(true); newNode->setCanRez(true); return newNode; @@ -219,13 +219,13 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect } } - // if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true + // if this user is in the editors list (or if the editors list is empty) set the user's node's isAllowedEditor to true const QVariant* allowedEditorsVariant = valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); // if the allowed editors list is empty then everyone can adjust locks - bool canAdjustLocks = allowedEditors.empty(); + bool isAllowedEditor = allowedEditors.empty(); if (allowedEditors.contains(username, Qt::CaseInsensitive)) { // we have a non-empty allowed editors list - check if this user is verified to be in it @@ -238,10 +238,10 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect << "will be given edit rights to avoid a thrasing of public key requests and connect requests."; } - canAdjustLocks = true; + isAllowedEditor = true; } else { // already verified this user and they are in the allowed editors list - canAdjustLocks = true; + isAllowedEditor = true; } } @@ -256,14 +256,14 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect bool canRez = true; if (onlyEditorsAreRezzers) { - canRez = canAdjustLocks; + canRez = isAllowedEditor; } // add the new node SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); // set the edit rights for this user - newNode->setCanAdjustLocks(canAdjustLocks); + newNode->setIsAllowedEditor(isAllowedEditor); newNode->setCanRez(canRez); // grab the linked data for our new node so we can set the username diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index db3c2df408..64b4f123f5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -744,7 +744,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif extendedHeaderStream << limitedNodeList->getSessionUUID(); extendedHeaderStream << node->getUUID(); - extendedHeaderStream << (quint8) node->getCanAdjustLocks(); + extendedHeaderStream << (quint8) node->isAllowedEditor(); extendedHeaderStream << (quint8) node->getCanRez(); auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8fd7be912e..be9010cba5 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -29,7 +29,7 @@ EntityScriptingInterface::EntityScriptingInterface() : _entityTree(NULL) { auto nodeList = DependencyManager::get(); - connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged); + connect(nodeList.data(), &NodeList::isAllowedEditorChanged, this, &EntityScriptingInterface::canAdjustLocksChanged); connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged); } @@ -40,7 +40,7 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType, bool EntityScriptingInterface::canAdjustLocks() { auto nodeList = DependencyManager::get(); - return nodeList->getThisNodeCanAdjustLocks(); + return nodeList->isAllowedEditor(); } bool EntityScriptingInterface::canRez() { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 34dd809510..3c638fd1a2 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -124,10 +124,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI QUuid senderID; if (senderNode.isNull()) { auto nodeList = DependencyManager::get(); - allowLockChange = nodeList->getThisNodeCanAdjustLocks(); + allowLockChange = nodeList->isAllowedEditor(); senderID = nodeList->getSessionUUID(); } else { - allowLockChange = senderNode->getCanAdjustLocks(); + allowLockChange = senderNode->isAllowedEditor(); senderID = senderNode->getUUID(); } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 3ea3175390..67237ee269 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -52,7 +52,6 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short _numCollectedPackets(0), _numCollectedBytes(0), _packetStatTimer(), - _thisNodeCanAdjustLocks(false), _thisNodeCanRez(true) { static bool firstCall = true; @@ -131,10 +130,10 @@ void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) { } } -void LimitedNodeList::setThisNodeCanAdjustLocks(bool canAdjustLocks) { - if (_thisNodeCanAdjustLocks != canAdjustLocks) { - _thisNodeCanAdjustLocks = canAdjustLocks; - emit canAdjustLocksChanged(canAdjustLocks); +void LimitedNodeList::setIsAllowedEditor(bool isAllowedEditor) { + if (_isAllowedEditor != isAllowedEditor) { + _isAllowedEditor = isAllowedEditor; + emit isAllowedEditorChanged(isAllowedEditor); } } @@ -515,7 +514,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) { SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - bool canAdjustLocks, bool canRez, + bool isAllowedEditor, bool canRez, const QUuid& connectionSecret) { NodeHash::const_iterator it = _nodeHash.find(uuid); @@ -524,14 +523,14 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t matchingNode->setPublicSocket(publicSocket); matchingNode->setLocalSocket(localSocket); - matchingNode->setCanAdjustLocks(canAdjustLocks); + matchingNode->setIsAllowedEditor(isAllowedEditor); matchingNode->setCanRez(canRez); matchingNode->setConnectionSecret(connectionSecret); return matchingNode; } else { // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks, canRez, connectionSecret, this); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, isAllowedEditor, canRez, connectionSecret, this); if (nodeType == NodeType::AudioMixer) { LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index c9785d240b..fcad23da8f 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -104,8 +104,8 @@ public: const QUuid& getSessionUUID() const { return _sessionUUID; } void setSessionUUID(const QUuid& sessionUUID); - bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; } - void setThisNodeCanAdjustLocks(bool canAdjustLocks); + bool isAllowedEditor() const { return _isAllowedEditor; } + void setIsAllowedEditor(bool isAllowedEditor); bool getThisNodeCanRez() const { return _thisNodeCanRez; } void setThisNodeCanRez(bool canRez); @@ -137,7 +137,7 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - bool canAdjustLocks = false, bool canRez = false, + bool isAllowedEditor = false, bool canRez = false, const QUuid& connectionSecret = QUuid()); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } @@ -244,7 +244,7 @@ signals: void localSockAddrChanged(const HifiSockAddr& localSockAddr); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); - void canAdjustLocksChanged(bool canAdjustLocks); + void isAllowedEditorChanged(bool isAllowedEditor); void canRezChanged(bool canRez); protected: @@ -289,7 +289,7 @@ protected: int _numCollectedBytes; QElapsedTimer _packetStatTimer; - bool _thisNodeCanAdjustLocks; + bool _isAllowedEditor { false }; bool _thisNodeCanRez; QPointer _initialSTUNTimer; diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index b28d0a6cb1..7e9bf60ea4 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -47,7 +47,7 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) { } Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez, const QUuid& connectionSecret, + const HifiSockAddr& localSocket, bool isAllowedEditor, bool canRez, const QUuid& connectionSecret, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), @@ -57,7 +57,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, _clockSkewUsec(0), _mutex(), _clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples - _canAdjustLocks(canAdjustLocks), + _isAllowedEditor(isAllowedEditor), _canRez(canRez) { // Update socket's object name @@ -84,7 +84,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) { out << node._uuid; out << node._publicSocket; out << node._localSocket; - out << node._canAdjustLocks; + out << node._isAllowedEditor; out << node._canRez; return out; @@ -95,7 +95,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { in >> node._uuid; in >> node._publicSocket; in >> node._localSocket; - in >> node._canAdjustLocks; + in >> node._isAllowedEditor; in >> node._canRez; return in; diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 865e885add..ca05e5b84d 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -33,7 +33,7 @@ class Node : public NetworkPeer { public: Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - bool canAdjustLocks, bool canRez, const QUuid& connectionSecret = QUuid(), + bool isAllowedEditor, bool canRez, const QUuid& connectionSecret = QUuid(), QObject* parent = 0); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } @@ -58,8 +58,8 @@ public: void updateClockSkewUsec(int clockSkewSample); QMutex& getMutex() { return _mutex; } - void setCanAdjustLocks(bool canAdjustLocks) { _canAdjustLocks = canAdjustLocks; } - bool getCanAdjustLocks() { return _canAdjustLocks; } + void setIsAllowedEditor(bool isAllowedEditor) { _isAllowedEditor = isAllowedEditor; } + bool isAllowedEditor() { return _isAllowedEditor; } void setCanRez(bool canRez) { _canRez = canRez; } bool getCanRez() { return _canRez; } @@ -81,7 +81,7 @@ private: int _clockSkewUsec; QMutex _mutex; MovingPercentile _clockSkewMovingPercentile; - bool _canAdjustLocks; + bool _isAllowedEditor; bool _canRez; }; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 16277caace..677a1ad1e6 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -512,9 +512,9 @@ void NodeList::processDomainServerList(QSharedPointer message) packetStream >> newUUID; setSessionUUID(newUUID); - quint8 thisNodeCanAdjustLocks; - packetStream >> thisNodeCanAdjustLocks; - setThisNodeCanAdjustLocks((bool) thisNodeCanAdjustLocks); + quint8 isAllowedEditor; + packetStream >> isAllowedEditor; + setIsAllowedEditor((bool) isAllowedEditor); quint8 thisNodeCanRez; packetStream >> thisNodeCanRez; @@ -546,10 +546,10 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { qint8 nodeType; QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket, nodeLocalSocket; - bool canAdjustLocks; + bool isAllowedEditor; bool canRez; - packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks >> canRez; + packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> isAllowedEditor >> canRez; // if the public socket address is 0 then it's reachable at the same IP // as the domain server @@ -560,7 +560,7 @@ void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { packetStream >> connectionUUID; SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, - nodeLocalSocket, canAdjustLocks, canRez, + nodeLocalSocket, isAllowedEditor, canRez, connectionUUID); } From b038e4b7e7b10e82b23a4b9f0b29a08ad174ed42 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 1 Feb 2016 16:48:00 -0800 Subject: [PATCH 05/27] calibrate using either the 1 or 2 button on each hand --- plugins/hifiSixense/src/SixenseManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 3377aac14c..b23982f948 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -282,8 +282,8 @@ void SixenseManager::InputDevice::setDebugDrawCalibrated(bool flag) { // the calibration sequence is: // (1) reach arm straight out to the sides (xAxis is to the left) -// (2) press BUTTON_FWD on both hands and hold for one second -// (3) release both BUTTON_FWDs +// (2) press either BUTTON_1 or BUTTON_2 on both hands and hold for one second +// (3) release both buttons // // The code will: // (4) assume that the orb is on a flat surface (yAxis is UP) @@ -294,7 +294,8 @@ static const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters static const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired static bool calibrationRequested(SixenseControllerData* controllers) { - return (controllers[0].buttons == BUTTON_FWD && controllers[1].buttons == BUTTON_FWD); + return (((controllers[0].buttons == BUTTON_1) || (controllers[0].buttons == BUTTON_2)) && + ((controllers[1].buttons == BUTTON_1) || (controllers[1].buttons == BUTTON_2))); } void SixenseManager::InputDevice::updateCalibration(SixenseControllerData* controllers) { From 0b6cfbe50aef5461ac6b60b478ef812468947da7 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 1 Feb 2016 17:48:31 -0800 Subject: [PATCH 06/27] Only connect render config if dirty signal present --- libraries/render/src/render/Task.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 148117eed6..93f3681c1c 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -257,7 +257,13 @@ public: QConfigPointer config = _jobs.back().getConfiguration(); config->setParent(_config.get()); config->setObjectName(name.c_str()); - QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); + + // Connect dirty->refresh if defined + static const char* DIRTY_SIGNAL = "dirty()"; + if (config->metaObject()->indexOfSignal(DIRTY_SIGNAL) != -1) { + QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); + } + return _jobs.back().getOutput(); } template const Varying addJob(std::string name, A&&... args) { From dad36b73fc3edaea1ea271403be8b44583dbdc63 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Feb 2016 09:57:52 -0800 Subject: [PATCH 07/27] Disable gridTool in edit.js --- examples/edit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 286542a91f..29f16a5633 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -336,7 +336,7 @@ var toolBar = (function() { isActive = active; if (!isActive) { entityListTool.setVisible(false); - gridTool.setVisible(false); + // gridTool.setVisible(false); grid.setEnabled(false); propertiesTool.setVisible(false); selectionManager.clearSelections(); @@ -344,7 +344,7 @@ var toolBar = (function() { } else { hasShownPropertiesTool = false; entityListTool.setVisible(true); - gridTool.setVisible(true); + // gridTool.setVisible(true); grid.setEnabled(true); propertiesTool.setVisible(true); Window.setFocus(); From 57d92bcfa6faaa11beafdae07ff914a6b53014b1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 2 Feb 2016 10:13:24 -0800 Subject: [PATCH 08/27] Stop creation of GridTool altogether in edit.js --- examples/edit.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 29f16a5633..cc5921efd1 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -39,10 +39,10 @@ var lightOverlayManager = new LightOverlayManager(); var cameraManager = new CameraManager(); var grid = Grid(); -gridTool = GridTool({ - horizontalGrid: grid -}); -gridTool.setVisible(false); +// gridTool = GridTool({ +// horizontalGrid: grid +// }); +// gridTool.setVisible(false); var entityListTool = EntityListTool(); From e9fd439ffd0210b0720b084bcecf9a1b91c07eb3 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 28 Jan 2016 18:27:49 -0800 Subject: [PATCH 09/27] Added inAir animations --- .../defaultAvatar_full/avatar-animation.json | 80 +++++++++++++++++-- interface/src/avatar/SkeletonModel.cpp | 9 ++- libraries/animation/src/Rig.cpp | 38 ++++++++- libraries/animation/src/Rig.h | 11 ++- libraries/physics/src/CharacterController.h | 1 + 5 files changed, 125 insertions(+), 14 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 42ff64abc6..46912120db 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -247,7 +247,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -263,7 +264,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -278,7 +280,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -293,7 +296,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -308,7 +312,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -323,7 +328,8 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -338,7 +344,8 @@ { "var": "isMovingLeft", "state": "strafeLeft" }, { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -353,7 +360,8 @@ { "var": "isMovingLeft", "state": "strafeLeft" }, { "var": "isTurningRight", "state": "turnRight" }, { "var": "isAway", "state": "awayIntro" }, - { "var": "isFlying", "state": "fly" } + { "var": "isFlying", "state": "fly" }, + { "var": "isInAir", "state": "inAir" } ] }, { @@ -385,8 +393,18 @@ "interpTarget": 6, "interpDuration": 6, "transitions": [ + { "var": "isAway", "state": "awayIntro" }, { "var": "isNotFlying", "state": "idle" } ] + }, + { + "id": "inAir", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "isAway", "state": "awayIntro" }, + { "var": "isNotInAir", "state": "idle" } + ] } ] }, @@ -685,6 +703,52 @@ "loopFlag": true }, "children": [] + }, + { + "id": "inAir", + "type": "blendLinear", + "data": { + "alpha": 0.0, + "alphaVar": "inAirAlpha" + }, + "children": [ + { + "id": "inAirPreApex", + "type": "clip", + "data": { + "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx", + "startFrame": 0.0, + "endFrame": 0.0, + "timeScale": 0.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "inAirApex", + "type": "clip", + "data": { + "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx", + "startFrame": 6.0, + "endFrame": 6.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "inAirPostApex", + "type": "clip", + "data": { + "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_in_air.fbx", + "startFrame": 11.0, + "endFrame": 11.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] } ] } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 6198a1b0a0..50cbbbbb00 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -133,7 +133,14 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromHandParameters(handParams, deltaTime); - _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation(), myAvatar->isHovering()); + Rig::CharacterControllerState ccState = Rig::CharacterControllerState::Ground; + if (myAvatar->getCharacterController()->isHovering()) { + ccState = Rig::CharacterControllerState::Hover; + } else if (myAvatar->getCharacterController()->isJumping()) { + ccState = Rig::CharacterControllerState::Jump; + } + + _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation(), ccState); // evaluate AnimGraph animation and update jointStates. Model::updateRig(deltaTime, parentTransform); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 4d72bfbaea..94bc23cf06 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -504,7 +504,7 @@ static const std::vector FORWARD_SPEEDS = { 0.4f, 1.4f, 4.5f }; // m/s static const std::vector BACKWARD_SPEEDS = { 0.6f, 1.45f }; // m/s static const std::vector LATERAL_SPEEDS = { 0.2f, 0.65f }; // m/s -void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, bool isHovering) { +void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState) { glm::vec3 front = worldRotation * IDENTITY_FRONT; @@ -572,11 +572,16 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos const float TURN_ENTER_SPEED_THRESHOLD = 0.5f; // rad/sec const float TURN_EXIT_SPEED_THRESHOLD = 0.2f; // rad/sec - if (isHovering) { + if (ccState == CharacterControllerState::Hover) { if (_desiredState != RigRole::Hover) { _desiredStateAge = 0.0f; } _desiredState = RigRole::Hover; + } else if (ccState == CharacterControllerState::Jump) { + if (_desiredState != RigRole::Jump) { + _desiredStateAge = 0.0f; + } + _desiredState = RigRole::Jump; } else { float moveThresh; if (_state != RigRole::Move) { @@ -662,6 +667,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isInAir", false); + _animVars.set("isNotInAir", true); } } else if (_state == RigRole::Turn) { if (turningSpeed > 0.0f) { @@ -682,6 +689,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotMoving", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isInAir", false); + _animVars.set("isNotInAir", true); } else if (_state == RigRole::Idle ) { // default anim vars to notMoving and notTurning _animVars.set("isMovingForward", false); @@ -694,7 +703,9 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); - } else { + _animVars.set("isInAir", false); + _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Hover) { // flying. _animVars.set("isMovingForward", false); _animVars.set("isMovingBackward", false); @@ -706,6 +717,27 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", true); _animVars.set("isNotFlying", false); + _animVars.set("isInAir", false); + _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Jump) { + // jumping in-air + _animVars.set("isMovingForward", false); + _animVars.set("isMovingBackward", false); + _animVars.set("isMovingLeft", false); + _animVars.set("isMovingRight", false); + _animVars.set("isNotMoving", true); + _animVars.set("isTurningLeft", false); + _animVars.set("isTurningRight", false); + _animVars.set("isNotTurning", true); + _animVars.set("isFlying", false); + _animVars.set("isNotFlying", true); + _animVars.set("isInAir", true); + _animVars.set("isNotInAir", false); + + // compute blend based on velocity + const float JUMP_SPEED = 3.5f; + float alpha = glm::clamp(-worldVelocity.y / JUMP_SPEED, -1.0f, 1.0f) + 1.0f; + _animVars.set("inAirAlpha", alpha); } t += deltaTime; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index cf96c6dc16..50d775d7f5 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -73,6 +73,12 @@ public: glm::quat rightOrientation = glm::quat(); // rig space (z forward) }; + enum class CharacterControllerState { + Ground = 0, + Jump, + Hover + }; + virtual ~Rig() {} void destroyAnimGraph(); @@ -141,7 +147,7 @@ public: glm::mat4 getJointTransform(int jointIndex) const; // Start or stop animations as needed. - void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, bool isHovering); + void computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation, CharacterControllerState ccState); // Regardless of who started the animations or how many, update the joints. void updateAnimations(float deltaTime, glm::mat4 rootTransform); @@ -271,7 +277,8 @@ public: Idle = 0, Turn, Move, - Hover + Hover, + Jump }; RigRole _state { RigRole::Idle }; RigRole _desiredState { RigRole::Idle }; diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index c1c64a1a02..3c9fc476ca 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -75,6 +75,7 @@ public: glm::vec3 getLinearVelocity() const; + bool isJumping() const { return _isJumping; } bool isHovering() const { return _isHovering; } void setHovering(bool enabled); From 61c55ebf6c96857559280116a830dec7aa5c410a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 29 Jan 2016 11:57:14 -0800 Subject: [PATCH 10/27] Updated character controller with a state enumeration Also, adjusted checkForSupport logic such that very slanted walls are not considered support. --- interface/src/avatar/MyAvatar.cpp | 7 +-- interface/src/avatar/MyAvatar.h | 2 - .../src/avatar/MyCharacterController.cpp | 2 +- interface/src/avatar/SkeletonModel.cpp | 20 ++++--- libraries/animation/src/Rig.cpp | 8 +-- libraries/animation/src/Rig.h | 4 +- libraries/physics/src/CharacterController.cpp | 60 +++++++++---------- libraries/physics/src/CharacterController.h | 17 +++--- 8 files changed, 62 insertions(+), 58 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0c0b51bda2..0aadaed150 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1510,7 +1510,8 @@ void MyAvatar::updatePosition(float deltaTime) { // rotate velocity into camera frame glm::quat rotation = getHead()->getCameraOrientation(); glm::vec3 localVelocity = glm::inverse(rotation) * _targetVelocity; - glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, isHovering()); + bool isHovering = _characterController.getState() == CharacterController::State::Hover; + glm::vec3 newLocalVelocity = applyKeyboardMotor(deltaTime, localVelocity, isHovering); newLocalVelocity = applyScriptedMotor(deltaTime, newLocalVelocity); // rotate back into world-frame @@ -1579,10 +1580,6 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float return false; } -bool MyAvatar::isHovering() const { - return _characterController.isHovering(); -} - void MyAvatar::increaseSize() { if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) { _targetScale *= (1.0f + SCALING_RATIO); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 760f390de9..ac77784077 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -239,8 +239,6 @@ public: glm::quat getCustomListenOrientation() { return _customListenOrientation; } void setCustomListenOrientation(glm::quat customListenOrientation) { _customListenOrientation = customListenOrientation; } - bool isHovering() const; - public slots: void increaseSize(); void decreaseSize(); diff --git a/interface/src/avatar/MyCharacterController.cpp b/interface/src/avatar/MyCharacterController.cpp index c7f2945757..07156e9294 100644 --- a/interface/src/avatar/MyCharacterController.cpp +++ b/interface/src/avatar/MyCharacterController.cpp @@ -67,7 +67,7 @@ void MyCharacterController::updateShapeIfNecessary() { _rigidBody->setAngularFactor(0.0f); _rigidBody->setWorldTransform(btTransform(glmToBullet(_avatar->getOrientation()), glmToBullet(_avatar->getPosition()))); - if (_isHovering) { + if (_state == State::Hover) { _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); } else { _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 50cbbbbb00..c8f14578b4 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -72,6 +72,18 @@ void SkeletonModel::initJointStates() { emit skeletonLoaded(); } +Rig::CharacterControllerState convertCharacterControllerState(CharacterController::State state) { + switch (state) { + default: + case CharacterController::State::Ground: + return Rig::CharacterControllerState::Ground; + case CharacterController::State::InAir: + return Rig::CharacterControllerState::InAir; + case CharacterController::State::Hover: + return Rig::CharacterControllerState::Hover; + }; +} + // Called within Model::simulate call, below. void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Head* head = _owningAvatar->getHead(); @@ -133,13 +145,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromHandParameters(handParams, deltaTime); - Rig::CharacterControllerState ccState = Rig::CharacterControllerState::Ground; - if (myAvatar->getCharacterController()->isHovering()) { - ccState = Rig::CharacterControllerState::Hover; - } else if (myAvatar->getCharacterController()->isJumping()) { - ccState = Rig::CharacterControllerState::Jump; - } - + Rig::CharacterControllerState ccState = convertCharacterControllerState(myAvatar->getCharacterController()->getState()); _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation(), ccState); // evaluate AnimGraph animation and update jointStates. diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 94bc23cf06..33c8f33ac8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -577,11 +577,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _desiredStateAge = 0.0f; } _desiredState = RigRole::Hover; - } else if (ccState == CharacterControllerState::Jump) { - if (_desiredState != RigRole::Jump) { + } else if (ccState == CharacterControllerState::InAir) { + if (_desiredState != RigRole::InAir) { _desiredStateAge = 0.0f; } - _desiredState = RigRole::Jump; + _desiredState = RigRole::InAir; } else { float moveThresh; if (_state != RigRole::Move) { @@ -719,7 +719,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotFlying", false); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); - } else if (_state == RigRole::Jump) { + } else if (_state == RigRole::InAir) { // jumping in-air _animVars.set("isMovingForward", false); _animVars.set("isMovingBackward", false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 50d775d7f5..dc07a32efd 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -75,7 +75,7 @@ public: enum class CharacterControllerState { Ground = 0, - Jump, + InAir, Hover }; @@ -278,7 +278,7 @@ public: Turn, Move, Hover, - Jump + InAir }; RigRole _state { RigRole::Idle }; RigRole _desiredState { RigRole::Idle }; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index a30feec150..055f846793 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -1,4 +1,4 @@ -// + // // CharacterControllerInterface.cpp // libraries/physcis/src // @@ -51,10 +51,7 @@ CharacterController::CharacterController() { _followDesiredBodyTransform.setIdentity(); _followTimeRemaining = 0.0f; _jumpSpeed = JUMP_SPEED; - _isOnGround = false; - _isJumping = false; - _isFalling = false; - _isHovering = true; + _state = State::Hover; _isPushingUp = false; _jumpToHoverStart = 0; _followTime = 0.0f; @@ -107,6 +104,8 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { } } +static const float COS_PI_OVER_THREE = cosf(PI / 3.0f); + bool CharacterController::checkForSupport(btCollisionWorld* collisionWorld) const { int numManifolds = collisionWorld->getDispatcher()->getNumManifolds(); for (int i = 0; i < numManifolds; i++) { @@ -119,8 +118,10 @@ bool CharacterController::checkForSupport(btCollisionWorld* collisionWorld) cons btManifoldPoint& pt = contactManifold->getContactPoint(j); // check to see if contact point is touching the bottom sphere of the capsule. + // and the contact normal is not slanted too much. float contactPointY = (obA == _rigidBody) ? pt.m_localPointA.getY() : pt.m_localPointB.getY(); - if (contactPointY < -_halfHeight) { + btVector3 normal = (obA == _rigidBody) ? pt.m_normalWorldOnB : -pt.m_normalWorldOnB; + if (contactPointY < -_halfHeight && normal.dot(_currentUp) > COS_PI_OVER_THREE) { return true; } } @@ -165,7 +166,7 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { } const btScalar MIN_SPEED = 0.001f; - if (_isHovering) { + if (_state == State::Hover) { if (desiredSpeed < MIN_SPEED) { if (actualSpeed < MIN_SPEED) { _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); @@ -255,9 +256,9 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { void CharacterController::jump() { // check for case where user is holding down "jump" key... - // we'll eventually tansition to "hover" - if (!_isJumping) { - if (!_isHovering) { + // we'll eventually transition to "hover" + if (_state != State::InAir) { + if (_state != State::Hover) { _jumpToHoverStart = usecTimestampNow(); _pendingFlags |= PENDING_FLAG_JUMP; } @@ -266,7 +267,7 @@ void CharacterController::jump() { const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { _isPushingUp = true; - setHovering(true); + setState(State::Hover); } } } @@ -276,19 +277,19 @@ bool CharacterController::onGround() const { return _floorDistance < FLOOR_PROXIMITY_THRESHOLD || _hasSupport; } -void CharacterController::setHovering(bool hover) { - if (hover != _isHovering) { - _isHovering = hover; - _isJumping = false; - +void CharacterController::setState(State desiredState) { + if (desiredState == State::Hover && _state != State::Hover) { + // hover enter if (_rigidBody) { - if (hover) { - _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); - } + _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); + } + } else if (_state == State::Hover && desiredState != State::Hover) { + // hover exit + if (_rigidBody) { + _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); } } + _state = desiredState; } void CharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) { @@ -335,9 +336,8 @@ void CharacterController::setEnabled(bool enabled) { _pendingFlags |= PENDING_FLAG_REMOVE_FROM_SIMULATION; } _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; - _isOnGround = false; } - setHovering(true); + setState(State::Hover); _enabled = enabled; } } @@ -345,7 +345,7 @@ void CharacterController::setEnabled(bool enabled) { void CharacterController::updateUpAxis(const glm::quat& rotation) { btVector3 oldUp = _currentUp; _currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS); - if (!_isHovering) { + if (_state != State::Hover) { const btScalar MIN_UP_ERROR = 0.01f; if (oldUp.distance(_currentUp) > MIN_UP_ERROR) { _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); @@ -425,23 +425,23 @@ void CharacterController::preSimulation() { if (rayCallback.hasHit()) { _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; const btScalar MIN_HOVER_HEIGHT = 3.0f; - if (_isHovering && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { - setHovering(false); + if (_state == State::Hover && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { + setState(State::InAir); } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_floorDistance < JUMP_PROXIMITY_THRESHOLD) { - _isJumping = false; + if (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport) { + setState(State::Ground); } } else if (!_hasSupport) { _floorDistance = FLT_MAX; - setHovering(true); + setState(State::Hover); } if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; if (onGround()) { - _isJumping = true; + setState(State::InAir); btVector3 velocity = _rigidBody->getLinearVelocity(); velocity += _jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 3c9fc476ca..c8b360237d 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -75,9 +75,13 @@ public: glm::vec3 getLinearVelocity() const; - bool isJumping() const { return _isJumping; } - bool isHovering() const { return _isHovering; } - void setHovering(bool enabled); + enum class State { + Ground = 0, + InAir, + Hover + }; + + State getState() const { return _state; } void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); @@ -87,6 +91,8 @@ public: bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); protected: + void setState(State state); + void updateUpAxis(const glm::quat& rotation); bool checkForSupport(btCollisionWorld* collisionWorld) const; @@ -117,10 +123,7 @@ protected: btQuaternion _followAngularDisplacement; bool _enabled; - bool _isOnGround; - bool _isJumping; - bool _isFalling; - bool _isHovering; + State _state; bool _isPushingUp; btDynamicsWorld* _dynamicsWorld { nullptr }; From 2936811484541b5b6133f8e1560393a70a3a8e56 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 29 Jan 2016 18:05:18 -0800 Subject: [PATCH 11/27] Added takeoff animation, WIP Character controller still has some jump/in-air bugs. --- .../defaultAvatar_full/avatar-animation.json | 39 ++++++++++++++++--- interface/src/avatar/SkeletonModel.cpp | 2 + libraries/animation/src/Rig.cpp | 35 +++++++++++++++++ libraries/animation/src/Rig.h | 2 + libraries/physics/src/CharacterController.cpp | 33 ++++++++++------ libraries/physics/src/CharacterController.h | 2 + 6 files changed, 97 insertions(+), 16 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 46912120db..37da0c37cc 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -248,6 +248,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -265,6 +266,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -281,6 +283,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -297,6 +300,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -313,6 +317,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -329,6 +334,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -345,6 +351,7 @@ { "var": "isTurningLeft", "state": "turnLeft" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -361,6 +368,7 @@ { "var": "isTurningRight", "state": "turnRight" }, { "var": "isAway", "state": "awayIntro" }, { "var": "isFlying", "state": "fly" }, + { "var": "isTakeoff", "state": "takeoff" }, { "var": "isInAir", "state": "inAir" } ] }, @@ -397,10 +405,19 @@ { "var": "isNotFlying", "state": "idle" } ] }, + { + "id": "takeoff", + "interpTarget": 0, + "interpDuration": 6, + "transitions": [ + { "var": "isAway", "state": "awayIntro" }, + { "var": "isNotTakeoff", "state": "inAir" } + ] + }, { "id": "inAir", - "interpTarget": 3, - "interpDuration": 3, + "interpTarget": 0, + "interpDuration": 6, "transitions": [ { "var": "isAway", "state": "awayIntro" }, { "var": "isNotInAir", "state": "idle" } @@ -704,6 +721,18 @@ }, "children": [] }, + { + "id": "takeoff", + "type": "clip", + "data": { + "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/jump_takeoff.fbx", + "startFrame": 1.0, + "endFrame": 2.5, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] + }, { "id": "inAir", "type": "blendLinear", @@ -720,7 +749,7 @@ "startFrame": 0.0, "endFrame": 0.0, "timeScale": 0.0, - "loopFlag": true + "loopFlag": false }, "children": [] }, @@ -732,7 +761,7 @@ "startFrame": 6.0, "endFrame": 6.0, "timeScale": 1.0, - "loopFlag": true + "loopFlag": false }, "children": [] }, @@ -744,7 +773,7 @@ "startFrame": 11.0, "endFrame": 11.0, "timeScale": 1.0, - "loopFlag": true + "loopFlag": false }, "children": [] } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c8f14578b4..92bdef686d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -77,6 +77,8 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle default: case CharacterController::State::Ground: return Rig::CharacterControllerState::Ground; + case CharacterController::State::Takeoff: + return Rig::CharacterControllerState::Takeoff; case CharacterController::State::InAir: return Rig::CharacterControllerState::InAir; case CharacterController::State::Hover: diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 33c8f33ac8..9e811fa358 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -582,6 +582,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _desiredStateAge = 0.0f; } _desiredState = RigRole::InAir; + } else if (ccState == CharacterControllerState::Takeoff) { + if (_desiredState != RigRole::Takeoff) { + _desiredStateAge = 0.0f; + } + _desiredState = RigRole::Takeoff; } else { float moveThresh; if (_state != RigRole::Move) { @@ -667,6 +672,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); } @@ -689,8 +696,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotMoving", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Idle ) { // default anim vars to notMoving and notTurning _animVars.set("isMovingForward", false); @@ -703,8 +713,11 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + } else if (_state == RigRole::Hover) { // flying. _animVars.set("isMovingForward", false); @@ -717,8 +730,28 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", true); _animVars.set("isNotFlying", false); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", false); _animVars.set("isNotInAir", true); + + } else if (_state == RigRole::Takeoff) { + // jumping in-air + _animVars.set("isMovingForward", false); + _animVars.set("isMovingBackward", false); + _animVars.set("isMovingLeft", false); + _animVars.set("isMovingRight", false); + _animVars.set("isNotMoving", true); + _animVars.set("isTurningLeft", false); + _animVars.set("isTurningRight", false); + _animVars.set("isNotTurning", true); + _animVars.set("isFlying", false); + _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", true); + _animVars.set("isNotTakeoff", false); + _animVars.set("isInAir", true); + _animVars.set("isNotInAir", false); + } else if (_state == RigRole::InAir) { // jumping in-air _animVars.set("isMovingForward", false); @@ -731,6 +764,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("isNotTurning", true); _animVars.set("isFlying", false); _animVars.set("isNotFlying", true); + _animVars.set("isTakeoff", false); + _animVars.set("isNotTakeoff", true); _animVars.set("isInAir", true); _animVars.set("isNotInAir", false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index dc07a32efd..e12af16e41 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -75,6 +75,7 @@ public: enum class CharacterControllerState { Ground = 0, + Takeoff, InAir, Hover }; @@ -278,6 +279,7 @@ public: Turn, Move, Hover, + Takeoff, InAir }; RigRole _state { RigRole::Idle }; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 055f846793..93b924d9bc 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -54,6 +54,7 @@ CharacterController::CharacterController() { _state = State::Hover; _isPushingUp = false; _jumpToHoverStart = 0; + _takeoffToInAirStart = 0; _followTime = 0.0f; _followLinearDisplacement = btVector3(0, 0, 0); _followAngularDisplacement = btQuaternion::getIdentity(); @@ -257,18 +258,18 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { void CharacterController::jump() { // check for case where user is holding down "jump" key... // we'll eventually transition to "hover" - if (_state != State::InAir) { - if (_state != State::Hover) { - _jumpToHoverStart = usecTimestampNow(); - _pendingFlags |= PENDING_FLAG_JUMP; - } - } else { + if (_state == State::Hover) { quint64 now = usecTimestampNow(); const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { _isPushingUp = true; setState(State::Hover); } + } else { + if (_state != State::Takeoff) { + _jumpToHoverStart = usecTimestampNow(); + _pendingFlags |= PENDING_FLAG_JUMP; + } } } @@ -430,7 +431,7 @@ void CharacterController::preSimulation() { } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport) { + if (_state != State::Takeoff && (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport)) { setState(State::Ground); } } else if (!_hasSupport) { @@ -438,15 +439,25 @@ void CharacterController::preSimulation() { setState(State::Hover); } + quint64 now = usecTimestampNow(); + if (_pendingFlags & PENDING_FLAG_JUMP) { _pendingFlags &= ~ PENDING_FLAG_JUMP; if (onGround()) { - setState(State::InAir); - btVector3 velocity = _rigidBody->getLinearVelocity(); - velocity += _jumpSpeed * _currentUp; - _rigidBody->setLinearVelocity(velocity); + setState(State::Takeoff); + _takeoffToInAirStart = now; } } + + const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; + if (_state == State::Takeoff && (now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) { + setState(State::InAir); + + _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; + btVector3 velocity = _rigidBody->getLinearVelocity(); + velocity += _jumpSpeed * _currentUp; + _rigidBody->setLinearVelocity(velocity); + } } _followTime = 0.0f; diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index c8b360237d..5470104a1a 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -77,6 +77,7 @@ public: enum class State { Ground = 0, + Takeoff, InAir, Hover }; @@ -107,6 +108,7 @@ protected: glm::vec3 _boxScale; // used to compute capsule shape + quint64 _takeoffToInAirStart; quint64 _jumpToHoverStart; btScalar _halfHeight; From 47f3ce3786e97f744d7338bd5cc694511df05891 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 1 Feb 2016 14:18:30 -0800 Subject: [PATCH 12/27] CharacterController jump is more reliable. --- libraries/animation/src/Rig.cpp | 7 ++ libraries/physics/src/CharacterController.cpp | 80 +++++++++++++------ 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 9e811fa358..64935691c8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -624,6 +624,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos const float STATE_CHANGE_HYSTERESIS_TIMER = 0.1f; + // Skip hystersis timer for jump transitions. + if (_desiredState == RigRole::Takeoff) { + _desiredStateAge = STATE_CHANGE_HYSTERESIS_TIMER; + } else if (_state == RigRole::InAir && _desiredState != RigRole::InAir) { + _desiredStateAge = STATE_CHANGE_HYSTERESIS_TIMER; + } + if ((_desiredStateAge >= STATE_CHANGE_HYSTERESIS_TIMER) && _desiredState != _state) { _state = _desiredState; _desiredStateAge = 0.0f; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 93b924d9bc..ad6c9545d2 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -1,4 +1,4 @@ - // +// // CharacterControllerInterface.cpp // libraries/physcis/src // @@ -15,11 +15,14 @@ #include "PhysicsCollisionGroups.h" #include "ObjectMotionState.h" +#include "PhysicsLogging.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float JUMP_SPEED = 3.5f; const float MAX_FALL_HEIGHT = 20.0f; +#define DEBUG_STATE_CHANGE + // helper class for simple ray-traces from character class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback { public: @@ -220,7 +223,7 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { // Dynamicaly compute a follow velocity to move this body toward the _followDesiredBodyTransform. // Rather then add this velocity to velocity the RigidBody, we explicitly teleport the RigidBody towards its goal. // This mirrors the computation done in MyAvatar::FollowHelper::postPhysicsUpdate(). - // These two computations must be kept in sync. + const float MINIMUM_TIME_REMAINING = 0.005f; const float MAX_DISPLACEMENT = 0.5f * _radius; _followTimeRemaining -= dt; @@ -258,18 +261,21 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { void CharacterController::jump() { // check for case where user is holding down "jump" key... // we'll eventually transition to "hover" - if (_state == State::Hover) { - quint64 now = usecTimestampNow(); - const quint64 JUMP_TO_HOVER_PERIOD = 75 * (USECS_PER_SECOND / 100); - if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { - _isPushingUp = true; - setState(State::Hover); - } - } else { - if (_state != State::Takeoff) { - _jumpToHoverStart = usecTimestampNow(); + if (_state != State::Takeoff) { + if (_state == State::InAir) { + quint64 now = usecTimestampNow(); + if (!_isPushingUp) { + _isPushingUp = true; + _jumpToHoverStart = now; + } + const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND; + if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { + setState(State::Hover); + } + } else { _pendingFlags |= PENDING_FLAG_JUMP; } + } } @@ -278,19 +284,41 @@ bool CharacterController::onGround() const { return _floorDistance < FLOOR_PROXIMITY_THRESHOLD || _hasSupport; } -void CharacterController::setState(State desiredState) { - if (desiredState == State::Hover && _state != State::Hover) { - // hover enter - if (_rigidBody) { - _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); - } - } else if (_state == State::Hover && desiredState != State::Hover) { - // hover exit - if (_rigidBody) { - _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); - } +#ifdef DEBUG_STATE_CHANGE +static const char* stateToStr(CharacterController::State state) { + switch (state) { + case CharacterController::State::Ground: + return "Ground"; + case CharacterController::State::Takeoff: + return "Takeoff"; + case CharacterController::State::InAir: + return "InAir"; + case CharacterController::State::Hover: + return "Hover"; + default: + return "Unknown"; + } +} +#endif // #ifdef DEBUG_STATE_CHANGE + +void CharacterController::setState(State desiredState) { + if (desiredState != _state) { +#ifdef DEBUG_STATE_CHANGE + qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "<-" << stateToStr(_state); +#endif + if (desiredState == State::Hover && _state != State::Hover) { + // hover enter + if (_rigidBody) { + _rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f)); + } + } else if (_state == State::Hover && desiredState != State::Hover) { + // hover exit + if (_rigidBody) { + _rigidBody->setGravity(DEFAULT_CHARACTER_GRAVITY * _currentUp); + } + } + _state = desiredState; } - _state = desiredState; } void CharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) { @@ -411,6 +439,7 @@ void CharacterController::preSimulation() { if (_enabled && _dynamicsWorld) { // slam body to where it is supposed to be _rigidBody->setWorldTransform(_characterBodyTransform); + btVector3 velocity = _rigidBody->getLinearVelocity(); // scan for distant floor // rayStart is at center of bottom sphere @@ -431,7 +460,7 @@ void CharacterController::preSimulation() { } // TODO: use collision events rather than ray-trace test to disable jumping const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_state != State::Takeoff && (_floorDistance < JUMP_PROXIMITY_THRESHOLD || _hasSupport)) { + if (_state != State::Takeoff && (velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) { setState(State::Ground); } } else if (!_hasSupport) { @@ -454,7 +483,6 @@ void CharacterController::preSimulation() { setState(State::InAir); _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; - btVector3 velocity = _rigidBody->getLinearVelocity(); velocity += _jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); } From 8b5cf3e49abbd8f4d6f32edb1f1f06cbd8989b4b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 1 Feb 2016 20:43:41 -0800 Subject: [PATCH 13/27] CharacterController: refined state machine. --- libraries/physics/src/CharacterController.cpp | 201 +++++++++--------- libraries/physics/src/CharacterController.h | 6 +- 2 files changed, 109 insertions(+), 98 deletions(-) diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index ad6c9545d2..f241be8b35 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -56,7 +56,8 @@ CharacterController::CharacterController() { _jumpSpeed = JUMP_SPEED; _state = State::Hover; _isPushingUp = false; - _jumpToHoverStart = 0; + _jumpButtonDownStart = 0; + _jumpButtonDownCount = 0; _takeoffToInAirStart = 0; _followTime = 0.0f; _followLinearDisplacement = btVector3(0, 0, 0); @@ -158,68 +159,57 @@ void CharacterController::preStep(btCollisionWorld* collisionWorld) { } void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { - btVector3 actualVelocity = _rigidBody->getLinearVelocity(); - btScalar actualSpeed = actualVelocity.length(); - - btVector3 desiredVelocity = _walkVelocity; - btScalar desiredSpeed = desiredVelocity.length(); - - const btScalar MIN_UP_PUSH = 0.1f; - if (desiredVelocity.dot(_currentUp) < MIN_UP_PUSH) { - _isPushingUp = false; - } const btScalar MIN_SPEED = 0.001f; - if (_state == State::Hover) { - if (desiredSpeed < MIN_SPEED) { - if (actualSpeed < MIN_SPEED) { - _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; - btScalar tau = glm::max(dt / HOVER_BRAKING_TIMESCALE, 1.0f); - _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); - } - } else { - const btScalar HOVER_ACCELERATION_TIMESCALE = 0.1f; - btScalar tau = dt / HOVER_ACCELERATION_TIMESCALE; - _rigidBody->setLinearVelocity(actualVelocity - tau * (actualVelocity - desiredVelocity)); + + btVector3 actualVelocity = _rigidBody->getLinearVelocity(); + if (actualVelocity.length() < MIN_SPEED) { + actualVelocity = btVector3(0.0f, 0.0f, 0.0f); + } + + btVector3 desiredVelocity = _walkVelocity; + if (desiredVelocity.length() < MIN_SPEED) { + desiredVelocity = btVector3(0.0f, 0.0f, 0.0f); + } + + // decompose into horizontal and vertical components. + btVector3 actualVertVelocity = actualVelocity.dot(_currentUp) * _currentUp; + btVector3 actualHorizVelocity = actualVelocity - actualVertVelocity; + btVector3 desiredVertVelocity = desiredVelocity.dot(_currentUp) * _currentUp; + btVector3 desiredHorizVelocity = desiredVelocity - desiredVertVelocity; + + btVector3 finalVelocity; + + switch (_state) { + case State::Ground: + case State::Takeoff: + { + // horizontal ground control + const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f; + btScalar tau = dt / WALK_ACCELERATION_TIMESCALE; + finalVelocity = tau * desiredHorizVelocity + (1.0f - tau) * actualHorizVelocity + actualVertVelocity; } - } else { - if (onGround()) { - // walking on ground - if (desiredSpeed < MIN_SPEED) { - if (actualSpeed < MIN_SPEED) { - _rigidBody->setLinearVelocity(btVector3(0.0f, 0.0f, 0.0f)); - } else { - const btScalar HOVER_BRAKING_TIMESCALE = 0.1f; - btScalar tau = dt / HOVER_BRAKING_TIMESCALE; - _rigidBody->setLinearVelocity((1.0f - tau) * actualVelocity); - } - } else { - // TODO: modify desiredVelocity using floor normal - const btScalar WALK_ACCELERATION_TIMESCALE = 0.1f; - btScalar tau = dt / WALK_ACCELERATION_TIMESCALE; - btVector3 velocityCorrection = tau * (desiredVelocity - actualVelocity); - // subtract vertical component - velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; - _rigidBody->setLinearVelocity(actualVelocity + velocityCorrection); - } - } else { - // transitioning to flying - btVector3 velocityCorrection = desiredVelocity - actualVelocity; + break; + case State::InAir: + { + // horizontal air control + const btScalar IN_AIR_ACCELERATION_TIMESCALE = 2.0f; + btScalar tau = dt / IN_AIR_ACCELERATION_TIMESCALE; + finalVelocity = tau * desiredHorizVelocity + (1.0f - tau) * actualHorizVelocity + actualVertVelocity; + } + break; + case State::Hover: + { + // vertical and horizontal air control const btScalar FLY_ACCELERATION_TIMESCALE = 0.2f; btScalar tau = dt / FLY_ACCELERATION_TIMESCALE; - if (!_isPushingUp) { - // actually falling --> compute a different velocity attenuation factor - const btScalar FALL_ACCELERATION_TIMESCALE = 2.0f; - tau = dt / FALL_ACCELERATION_TIMESCALE; - // zero vertical component - velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; - } - _rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection); + finalVelocity = tau * desiredVelocity + (1.0f - tau) * actualVelocity; } + break; } + _rigidBody->setLinearVelocity(finalVelocity); + // Dynamicaly compute a follow velocity to move this body toward the _followDesiredBodyTransform. // Rather then add this velocity to velocity the RigidBody, we explicitly teleport the RigidBody towards its goal. // This mirrors the computation done in MyAvatar::FollowHelper::postPhysicsUpdate(). @@ -259,24 +249,7 @@ void CharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) { } void CharacterController::jump() { - // check for case where user is holding down "jump" key... - // we'll eventually transition to "hover" - if (_state != State::Takeoff) { - if (_state == State::InAir) { - quint64 now = usecTimestampNow(); - if (!_isPushingUp) { - _isPushingUp = true; - _jumpToHoverStart = now; - } - const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND; - if (now - _jumpToHoverStart > JUMP_TO_HOVER_PERIOD) { - setState(State::Hover); - } - } else { - _pendingFlags |= PENDING_FLAG_JUMP; - } - - } + _pendingFlags |= PENDING_FLAG_JUMP; } bool CharacterController::onGround() const { @@ -441,6 +414,9 @@ void CharacterController::preSimulation() { _rigidBody->setWorldTransform(_characterBodyTransform); btVector3 velocity = _rigidBody->getLinearVelocity(); + btVector3 actualVertVelocity = velocity.dot(_currentUp) * _currentUp; + btVector3 actualHorizVelocity = velocity - actualVertVelocity; + // scan for distant floor // rayStart is at center of bottom sphere btVector3 rayStart = _characterBodyTransform.getOrigin() - _halfHeight * _currentUp; @@ -454,41 +430,74 @@ void CharacterController::preSimulation() { _dynamicsWorld->rayTest(rayStart, rayEnd, rayCallback); if (rayCallback.hasHit()) { _floorDistance = rayLength * rayCallback.m_closestHitFraction - _radius; - const btScalar MIN_HOVER_HEIGHT = 3.0f; - if (_state == State::Hover && _floorDistance < MIN_HOVER_HEIGHT && !_isPushingUp) { - setState(State::InAir); - } - // TODO: use collision events rather than ray-trace test to disable jumping - const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; - if (_state != State::Takeoff && (velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) { - setState(State::Ground); - } - } else if (!_hasSupport) { + } else { _floorDistance = FLT_MAX; - setState(State::Hover); } + const btScalar JUMP_PROXIMITY_THRESHOLD = 0.1f * _radius; + const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; + const btScalar MIN_HOVER_HEIGHT = 2.5f; + const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND; + const btScalar UPWARD_VELOCITY_THRESHOLD = 0.05f; + const btScalar MAX_FLYING_SPEED = 30.0f; + quint64 now = usecTimestampNow(); - if (_pendingFlags & PENDING_FLAG_JUMP) { - _pendingFlags &= ~ PENDING_FLAG_JUMP; - if (onGround()) { - setState(State::Takeoff); - _takeoffToInAirStart = now; + // record a time stamp when the jump button was first pressed. + if ((_previousFlags & PENDING_FLAG_JUMP) != (_pendingFlags & PENDING_FLAG_JUMP)) { + if (_pendingFlags & PENDING_FLAG_JUMP) { + _jumpButtonDownStart = now; + _jumpButtonDownCount++; } } - const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; - if (_state == State::Takeoff && (now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) { - setState(State::InAir); + bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP; + bool wantsToGoUp = !jumpButtonHeld && _walkVelocity.dot(_currentUp) > UPWARD_VELOCITY_THRESHOLD; + bool tooFast = actualHorizVelocity.length() > (MAX_FLYING_SPEED / 2.0f); - _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; - velocity += _jumpSpeed * _currentUp; - _rigidBody->setLinearVelocity(velocity); + switch (_state) { + case State::Ground: + if (!rayCallback.hasHit() && !_hasSupport) { + setState(State::Hover); + } else if (_pendingFlags & PENDING_FLAG_JUMP) { + _takeOffJumpButtonID = _jumpButtonDownCount; + setState(State::Takeoff); + } + break; + case State::Takeoff: + if (!rayCallback.hasHit() && !_hasSupport) { + setState(State::Hover); + } else if ((now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) { + setState(State::InAir); + _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; + velocity += _jumpSpeed * _currentUp; + _rigidBody->setLinearVelocity(velocity); + } + break; + case State::InAir: { + if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) { + setState(State::Ground); + } else if ((jumpButtonHeld && ((_takeOffJumpButtonID != _jumpButtonDownCount) || (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD)) || wantsToGoUp) { + setState(State::Hover); + } + break; + } + case State::Hover: + if (!jumpButtonHeld && !wantsToGoUp && _floorDistance < MIN_HOVER_HEIGHT && !tooFast) { + setState(State::InAir); + } else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !tooFast) { + setState(State::Ground); + } + break; } } - _followTime = 0.0f; + /// _walkVelocity.dot(_currentUp) > UPWARD_VELOCITY_THRESHOLD + + _previousFlags = _pendingFlags; + _pendingFlags &= ~PENDING_FLAG_JUMP; + + _followTime = 0.0f; _followLinearDisplacement = btVector3(0, 0, 0); _followAngularDisplacement = btQuaternion::getIdentity(); } diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 5470104a1a..97bda5c5d5 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -109,7 +109,9 @@ protected: glm::vec3 _boxScale; // used to compute capsule shape quint64 _takeoffToInAirStart; - quint64 _jumpToHoverStart; + quint64 _jumpButtonDownStart; + quint32 _jumpButtonDownCount; + quint32 _takeOffJumpButtonID; btScalar _halfHeight; btScalar _radius; @@ -131,7 +133,7 @@ protected: btDynamicsWorld* _dynamicsWorld { nullptr }; btRigidBody* _rigidBody { nullptr }; uint32_t _pendingFlags { 0 }; - + uint32_t _previousFlags { 0 }; }; #endif // hifi_CharacterControllerInterface_h From c4e1509aa214948bbe2428714d71c9f5133f5186 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 2 Feb 2016 11:19:17 -0800 Subject: [PATCH 14/27] CharacterController: better debug support of internal state machine Head is no longer visible when flying fast, in first-person HMD mode. --- interface/src/avatar/MyAvatar.cpp | 12 +++-- libraries/physics/src/CharacterController.cpp | 46 +++++++++++-------- libraries/physics/src/CharacterController.h | 6 +++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0aadaed150..4253091533 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1311,21 +1311,23 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { _prevShouldDrawHead = shouldDrawHead; } -const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; +const float RENDER_HEAD_CUTOFF_DISTANCE = 0.5f; bool MyAvatar::cameraInsideHead() const { const Head* head = getHead(); const glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); - return glm::length(cameraPosition - head->getEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); + return glm::length(cameraPosition - getDefaultEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); } bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const { - return ((renderArgs->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) || - (qApp->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || - !cameraInsideHead()); + bool defaultMode = renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE; + bool firstPerson = qApp->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON; + bool insideHead = cameraInsideHead(); + return !defaultMode || !firstPerson || !insideHead; } void MyAvatar::updateOrientation(float deltaTime) { + // Smoothly rotate body with arrow keys float targetSpeed = _driveKeys[YAW] * _yawSpeed; if (targetSpeed != 0.0f) { diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index f241be8b35..160b227127 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -21,7 +21,11 @@ const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float JUMP_SPEED = 3.5f; const float MAX_FALL_HEIGHT = 20.0f; -#define DEBUG_STATE_CHANGE +#ifdef DEBUG_STATE_CHANGE +#define SET_STATE(desiredState, reason) setState(desiredState, reason) +#else +#define SET_STATE(desiredState, reason) setState(desiredState) +#endif // helper class for simple ray-traces from character class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback { @@ -65,7 +69,6 @@ CharacterController::CharacterController() { _hasSupport = false; _pendingFlags = PENDING_FLAG_UPDATE_SHAPE; - } bool CharacterController::needsRemoval() const { @@ -274,10 +277,14 @@ static const char* stateToStr(CharacterController::State state) { } #endif // #ifdef DEBUG_STATE_CHANGE +#ifdef DEBUG_STATE_CHANGE +void CharacterController::setState(State desiredState, const char* reason) { +#else void CharacterController::setState(State desiredState) { +#endif if (desiredState != _state) { #ifdef DEBUG_STATE_CHANGE - qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "<-" << stateToStr(_state); + qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "from" << stateToStr(_state) << "," << reason; #endif if (desiredState == State::Hover && _state != State::Hover) { // hover enter @@ -339,7 +346,7 @@ void CharacterController::setEnabled(bool enabled) { } _pendingFlags &= ~ PENDING_FLAG_ADD_TO_SIMULATION; } - setState(State::Hover); + SET_STATE(State::Hover, "setEnabled"); _enabled = enabled; } } @@ -438,8 +445,8 @@ void CharacterController::preSimulation() { const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; const btScalar MIN_HOVER_HEIGHT = 2.5f; const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND; - const btScalar UPWARD_VELOCITY_THRESHOLD = 0.05f; - const btScalar MAX_FLYING_SPEED = 30.0f; + const btScalar UPWARD_VELOCITY_THRESHOLD = 0.1f; + const btScalar MAX_WALKING_SPEED = 2.5f; quint64 now = usecTimestampNow(); @@ -452,23 +459,22 @@ void CharacterController::preSimulation() { } bool jumpButtonHeld = _pendingFlags & PENDING_FLAG_JUMP; - bool wantsToGoUp = !jumpButtonHeld && _walkVelocity.dot(_currentUp) > UPWARD_VELOCITY_THRESHOLD; - bool tooFast = actualHorizVelocity.length() > (MAX_FLYING_SPEED / 2.0f); + bool flyingFast = _state == State::Hover && actualHorizVelocity.length() > (MAX_WALKING_SPEED * 0.75f); switch (_state) { case State::Ground: if (!rayCallback.hasHit() && !_hasSupport) { - setState(State::Hover); + SET_STATE(State::Hover, "no ground"); } else if (_pendingFlags & PENDING_FLAG_JUMP) { _takeOffJumpButtonID = _jumpButtonDownCount; - setState(State::Takeoff); + SET_STATE(State::Takeoff, "jump pressed"); } break; case State::Takeoff: if (!rayCallback.hasHit() && !_hasSupport) { - setState(State::Hover); + SET_STATE(State::Hover, "no ground"); } else if ((now - _takeoffToInAirStart) > TAKE_OFF_TO_IN_AIR_PERIOD) { - setState(State::InAir); + SET_STATE(State::InAir, "takeoff done"); _takeoffToInAirStart = now + USECS_PER_SECOND * 86500.0f; velocity += _jumpSpeed * _currentUp; _rigidBody->setLinearVelocity(velocity); @@ -476,17 +482,19 @@ void CharacterController::preSimulation() { break; case State::InAir: { if ((velocity.dot(_currentUp) <= (JUMP_SPEED / 2.0f)) && ((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport)) { - setState(State::Ground); - } else if ((jumpButtonHeld && ((_takeOffJumpButtonID != _jumpButtonDownCount) || (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD)) || wantsToGoUp) { - setState(State::Hover); + SET_STATE(State::Ground, "hit ground"); + } else if (jumpButtonHeld && (_takeOffJumpButtonID != _jumpButtonDownCount)) { + SET_STATE(State::Hover, "double jump button"); + } else if (jumpButtonHeld && (now - _jumpButtonDownStart) > JUMP_TO_HOVER_PERIOD) { + SET_STATE(State::Hover, "jump button held"); } break; } case State::Hover: - if (!jumpButtonHeld && !wantsToGoUp && _floorDistance < MIN_HOVER_HEIGHT && !tooFast) { - setState(State::InAir); - } else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !tooFast) { - setState(State::Ground); + if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) { + SET_STATE(State::InAir, "near ground"); + } else if (((_floorDistance < JUMP_PROXIMITY_THRESHOLD) || _hasSupport) && !flyingFast) { + SET_STATE(State::Ground, "touching ground"); } break; } diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 97bda5c5d5..bb4a135ca3 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -31,6 +31,8 @@ class btRigidBody; class btCollisionWorld; class btDynamicsWorld; +//#define DEBUG_STATE_CHANGE + class CharacterController : public btCharacterControllerInterface { public: CharacterController(); @@ -92,7 +94,11 @@ public: bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); protected: +#ifdef DEBUG_STATE_CHANGE + void setState(State state, const char* reason); +#else void setState(State state); +#endif void updateUpAxis(const glm::quat& rotation); bool checkForSupport(btCollisionWorld* collisionWorld) const; From 79dc2d5d5502f5aeaa98a0f55e6d0a6b012a7544 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 2 Feb 2016 11:40:15 -0800 Subject: [PATCH 15/27] add some debug for mute environment crash --- assignment-client/src/audio/AudioMixer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 8967436e2d..54032e993f 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -552,6 +552,8 @@ void AudioMixer::handleMuteEnvironmentPacket(QSharedPointer mes auto nodeList = DependencyManager::get(); if (sendingNode->isAllowedEditor()) { + qDebug() << "Received a mute environment packet of" << message->getSize() << "bytes"; + auto newPacket = NLPacket::create(PacketType::MuteEnvironment, message->getSize()); // Copy payload newPacket->write(message->getRawMessage(), message->getSize()); From 5adf9adb0e8321e21e50cba65764f7e5fd0d8a78 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 2 Feb 2016 12:00:17 -0800 Subject: [PATCH 16/27] Make mirror rectaqngle move with mirror controls --- interface/src/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ab5edec527..883b082d0e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1362,6 +1362,9 @@ void Application::paintGL() { renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; renderArgs._blitFramebuffer = DependencyManager::get()->getSelfieFramebuffer(); + auto inputs = AvatarInputs::getInstance(); + _mirrorViewRect.moveTo(inputs->x(), inputs->y()); + renderRearViewMirror(&renderArgs, _mirrorViewRect); renderArgs._blitFramebuffer.reset(); From 2c26b32341fa53453aa6bacf4aed4557c53e960f Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 2 Feb 2016 12:00:58 -0800 Subject: [PATCH 17/27] Make QML based tool-windows close properly --- libraries/ui/src/QmlWindowClass.cpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index 3874b85a12..0e834fa379 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -220,18 +220,7 @@ QmlWindowClass::QmlWindowClass(QObject* qmlWindow) } QmlWindowClass::~QmlWindowClass() { - if (_qmlWindow) { - if (_toolWindow) { - auto offscreenUi = DependencyManager::get(); - auto toolWindow = offscreenUi->getToolWindow(); - auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::QueuedConnection, - Q_ARG(QVariant, _source)); - Q_ASSERT(invokeResult); - } else { - _qmlWindow->deleteLater(); - } - _qmlWindow = nullptr; - } + close(); } void QmlWindowClass::registerObject(const QString& name, QObject* object) { @@ -331,14 +320,18 @@ void QmlWindowClass::setTitle(const QString& title) { } void QmlWindowClass::close() { - DependencyManager::get()->executeOnUiThread([this] { - if (_qmlWindow) { - _qmlWindow->setProperty("destroyOnInvisible", true); - _qmlWindow->setProperty("visible", false); + if (_qmlWindow) { + if (_toolWindow) { + auto offscreenUi = DependencyManager::get(); + auto toolWindow = offscreenUi->getToolWindow(); + auto invokeResult = QMetaObject::invokeMethod(toolWindow, "removeTabForUrl", Qt::QueuedConnection, + Q_ARG(QVariant, _source)); + Q_ASSERT(invokeResult); + } else { _qmlWindow->deleteLater(); - _qmlWindow = nullptr; } - }); + _qmlWindow = nullptr; + } } void QmlWindowClass::hasClosed() { From 656608e2ffaff0f21effbe461b8f36437addd6d1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 2 Feb 2016 12:08:52 -0800 Subject: [PATCH 18/27] Fixes for away.js --- .../meshes/defaultAvatar_full/avatar-animation.json | 1 + libraries/animation/src/Rig.cpp | 11 +++++++---- libraries/animation/src/Rig.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 37da0c37cc..a4e39969b4 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -377,6 +377,7 @@ "interpTarget": 30, "interpDuration": 30, "transitions": [ + { "var": "isNotAway", "state": "awayOutro" }, { "var": "awayIntroOnDone", "state": "away"} ] }, diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 64935691c8..2ea9d782d5 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -784,11 +784,14 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos t += deltaTime; - if (_enableInverseKinematics) { - _animVars.set("ikOverlayAlpha", 1.0f); - } else { - _animVars.set("ikOverlayAlpha", 0.0f); + if (_enableInverseKinematics != _lastEnableInverseKinematics) { + if (_enableInverseKinematics) { + _animVars.set("ikOverlayAlpha", 1.0f); + } else { + _animVars.set("ikOverlayAlpha", 0.0f); + } } + _lastEnableInverseKinematics = _enableInverseKinematics; } _lastFront = front; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index e12af16e41..a360140b16 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -301,6 +301,7 @@ public: std::map _origRoleAnimations; std::vector _prefetchedAnimations; + bool _lastEnableInverseKinematics { false }; bool _enableInverseKinematics { true }; private: From cede14fdc6bfacbac590a504698342c250f19cd8 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 2 Feb 2016 14:01:44 -0800 Subject: [PATCH 19/27] Don't cut off title of windows without close icons --- interface/resources/qml/windows/DefaultFrame.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows/DefaultFrame.qml b/interface/resources/qml/windows/DefaultFrame.qml index a082db5a92..c58f9ca545 100644 --- a/interface/resources/qml/windows/DefaultFrame.qml +++ b/interface/resources/qml/windows/DefaultFrame.qml @@ -6,8 +6,10 @@ import "../controls" Frame { id: frame + property bool wideTopMargin: (window && (window.closable || window.title)); + Rectangle { - anchors { margins: -iconSize; topMargin: -iconSize * ((window && window.closable) ? 2 : 1); } + anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } anchors.fill: parent; color: "#7f7f7f7f"; radius: 3; From 6cc3b2b47f82022ea00925887fa6ffbb9029e200 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 2 Feb 2016 15:04:28 -0800 Subject: [PATCH 20/27] Fixed unused variable warnings on OSX and Linux --- interface/src/avatar/MyAvatar.cpp | 1 - libraries/physics/src/CharacterController.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4253091533..b99430cae3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1314,7 +1314,6 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { const float RENDER_HEAD_CUTOFF_DISTANCE = 0.5f; bool MyAvatar::cameraInsideHead() const { - const Head* head = getHead(); const glm::vec3 cameraPosition = qApp->getCamera()->getPosition(); return glm::length(cameraPosition - getDefaultEyePosition()) < (RENDER_HEAD_CUTOFF_DISTANCE * getUniformScale()); } diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 160b227127..941428f03a 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -445,7 +445,6 @@ void CharacterController::preSimulation() { const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 200 * MSECS_PER_SECOND; const btScalar MIN_HOVER_HEIGHT = 2.5f; const quint64 JUMP_TO_HOVER_PERIOD = 750 * MSECS_PER_SECOND; - const btScalar UPWARD_VELOCITY_THRESHOLD = 0.1f; const btScalar MAX_WALKING_SPEED = 2.5f; quint64 now = usecTimestampNow(); From f24f2749e14b41e7a8f942c52ebaa36c36d0af72 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 2 Feb 2016 15:19:12 -0800 Subject: [PATCH 21/27] Make users.js show QML window for edit friends --- examples/users.js | 17 ++++++++++- interface/src/Application.cpp | 16 ---------- interface/src/Application.h | 2 -- .../GlobalServicesScriptingInterface.cpp | 3 -- .../GlobalServicesScriptingInterface.h | 3 +- libraries/ui/src/OffscreenUi.cpp | 29 ++++++++++--------- libraries/ui/src/QmlWebWindowClass.cpp | 5 +++- 7 files changed, 36 insertions(+), 39 deletions(-) diff --git a/examples/users.js b/examples/users.js index f63184625d..0f9be42835 100644 --- a/examples/users.js +++ b/examples/users.js @@ -235,7 +235,12 @@ var usersWindow = (function () { FRIENDS_BUTTON_HEIGHT = FRIENDS_BUTTON_SVG_HEIGHT, FRIENDS_BUTTON_COLOR = { red: 225, green: 225, blue: 225 }, FRIENDS_BUTTON_ALPHA = 0.95, + FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends", + FRIENDS_WINDOW_WIDTH = 290, + FRIENDS_WINDOW_HEIGHT = 500, + FRIENDS_WINDOW_TITLE = "Add/Remove Friends", friendsButton, + friendsWindow, OPTION_BACKGROUND_COLOR = { red: 60, green: 60, blue: 60 }, OPTION_BACKGROUND_ALPHA = 0.1, @@ -643,7 +648,17 @@ var usersWindow = (function () { } if (clickedOverlay === friendsButton) { - GlobalServices.editFriends(); + if (!friendsWindow) { + friendsWindow = new OverlayWebWindow({ + title: FRIENDS_WINDOW_TITLE, + width: FRIENDS_WINDOW_WIDTH, + height: FRIENDS_WINDOW_HEIGHT, + visible: false + }); + } + friendsWindow.setURL(FRIENDS_WINDOW_URL); + friendsWindow.setVisible(true); + friendsWindow.raise(); } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 883b082d0e..d05440b2e6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4615,22 +4615,6 @@ void Application::activeChanged(Qt::ApplicationState state) { break; } } -void Application::showFriendsWindow() { - const QString FRIENDS_WINDOW_OBJECT_NAME = "FriendsWindow"; - const QString FRIENDS_WINDOW_TITLE = "Add/Remove Friends"; - const QString FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends"; - const int FRIENDS_WINDOW_WIDTH = 290; - const int FRIENDS_WINDOW_HEIGHT = 500; - auto webWindowClass = _window->findChildren(FRIENDS_WINDOW_OBJECT_NAME); - if (webWindowClass.empty()) { - auto friendsWindow = new WebWindowClass(FRIENDS_WINDOW_TITLE, FRIENDS_WINDOW_URL, FRIENDS_WINDOW_WIDTH, - FRIENDS_WINDOW_HEIGHT); - friendsWindow->setParent(_window); - friendsWindow->setObjectName(FRIENDS_WINDOW_OBJECT_NAME); - connect(friendsWindow, &WebWindowClass::closed, &WebWindowClass::deleteLater); - friendsWindow->setVisible(true); - } -} void Application::postLambdaEvent(std::function f) { if (this->thread() == QThread::currentThread()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 4b32d8879b..ef8a5377fd 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -245,8 +245,6 @@ public slots: void handleLocalServerConnection(); void readArgumentsFromLocalSocket(); - void showFriendsWindow(); - void packageModel(); void openUrl(const QUrl& url); diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index e764473107..7dac0247bd 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -144,6 +144,3 @@ void GlobalServicesScriptingInterface::updateDownloadInfo() { emit downloadInfoChanged(getDownloadInfo()); } -void GlobalServicesScriptingInterface::editFriends() { - QMetaObject::invokeMethod(qApp, "showFriendsWindow"); -} diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index e38bfc0eb6..11d8735187 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -45,8 +45,7 @@ public: public slots: DownloadInfoResult getDownloadInfo(); void updateDownloadInfo(); - void editFriends(); - + private slots: void loggedOut(); void checkDownloadInfo(); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 8e52507243..1d471d5419 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -45,6 +45,20 @@ private: bool _navigationFocused { false }; }; +QString fixupHifiUrl(const QString& urlString) { + static const QString ACCESS_TOKEN_PARAMETER = "access_token"; + static const QString ALLOWED_HOST = "metaverse.highfidelity.com"; + QUrl url(urlString); + QUrlQuery query(url); + if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { + AccountManager& accountManager = AccountManager::getInstance(); + query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token); + url.setQuery(query.query()); + return url.toString(); + } + return urlString; +} + class UrlHandler : public QObject { Q_OBJECT public: @@ -60,20 +74,7 @@ public: // FIXME hack for authentication, remove when we migrate to Qt 5.6 Q_INVOKABLE QString fixupUrl(const QString& originalUrl) { - static const QString ACCESS_TOKEN_PARAMETER = "access_token"; - static const QString ALLOWED_HOST = "metaverse.highfidelity.com"; - QString result = originalUrl; - QUrl url(originalUrl); - QUrlQuery query(url); - if (url.host() == ALLOWED_HOST && query.allQueryItemValues(ACCESS_TOKEN_PARAMETER).empty()) { - qDebug() << "Updating URL with auth token"; - AccountManager& accountManager = AccountManager::getInstance(); - query.addQueryItem(ACCESS_TOKEN_PARAMETER, accountManager.getAccountInfo().getAccessToken().token); - url.setQuery(query.query()); - result = url.toString(); - } - - return result; + return fixupHifiUrl(originalUrl); } }; diff --git a/libraries/ui/src/QmlWebWindowClass.cpp b/libraries/ui/src/QmlWebWindowClass.cpp index 96e99654c8..f12fb51b19 100644 --- a/libraries/ui/src/QmlWebWindowClass.cpp +++ b/libraries/ui/src/QmlWebWindowClass.cpp @@ -49,8 +49,11 @@ QString QmlWebWindowClass::getURL() const { return result.toString(); } +// HACK find a good place to declare and store this +extern QString fixupHifiUrl(const QString& urlString); + void QmlWebWindowClass::setURL(const QString& urlString) { DependencyManager::get()->executeOnUiThread([=] { - _qmlWindow->setProperty(URL_PROPERTY, urlString); + _qmlWindow->setProperty(URL_PROPERTY, fixupHifiUrl(urlString)); }); } From bc7fda0ae9c69f6153d1fc6b56a19009a01fe440 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 2 Feb 2016 15:19:47 -0800 Subject: [PATCH 22/27] Set desirable global settings for QML web views --- interface/resources/qml/hifi/Desktop.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 9d527c697a..5951101194 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -1,5 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 +import QtWebEngine 1.1; import "../desktop" import ".." @@ -7,6 +8,13 @@ import ".." Desktop { id: desktop + Component.onCompleted: { + WebEngine.settings.javascriptCanOpenWindows = false; + WebEngine.settings.javascriptCanAccessClipboard = false; + WebEngine.settings.spatialNavigationEnabled = true; + WebEngine.settings.localContentCanAccessRemoteUrls = true; + } + // The tool window, one instance property alias toolWindow: toolWindow ToolWindow { id: toolWindow } From 30e97c2a76bcdafa30d2f2cef9866917de680fc6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 2 Feb 2016 16:34:06 -0800 Subject: [PATCH 23/27] run attachedEntitiesManager.js by default, but without a UI --- examples/attachedEntitiesManager.js | 75 ++++++++++++++++------------- examples/defaultScripts.js | 1 + 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/examples/attachedEntitiesManager.js b/examples/attachedEntitiesManager.js index 01f8f861c9..c44ac66a44 100644 --- a/examples/attachedEntitiesManager.js +++ b/examples/attachedEntitiesManager.js @@ -22,41 +22,44 @@ var MINIMUM_DROP_DISTANCE_FROM_JOINT = 0.4; var ATTACHED_ENTITY_SEARCH_DISTANCE = 10.0; var ATTACHED_ENTITIES_SETTINGS_KEY = "ATTACHED_ENTITIES"; var DRESSING_ROOM_DISTANCE = 2.0; +var SHOW_TOOL_BAR = false; // tool bar -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -var BUTTON_SIZE = 32; -var PADDING = 3; -Script.include(["libraries/toolBars.js"]); -var toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.attachedEntities.toolbar", function(screenSize) { - return { - x: (BUTTON_SIZE + PADDING), - y: (screenSize.y / 2 - BUTTON_SIZE * 2 + PADDING) - }; -}); -var saveButton = toolBar.addOverlay("image", { - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: "http://headache.hungry.com/~seth/hifi/save.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1 -}); -var loadButton = toolBar.addOverlay("image", { - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: "http://headache.hungry.com/~seth/hifi/load.png", - color: { - red: 255, - green: 255, - blue: 255 - }, - alpha: 1 -}); +if (SHOW_TOOL_BAR) { + HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + var BUTTON_SIZE = 32; + var PADDING = 3; + Script.include(["libraries/toolBars.js"]); + var toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.attachedEntities.toolbar", function(screenSize) { + return { + x: (BUTTON_SIZE + PADDING), + y: (screenSize.y / 2 - BUTTON_SIZE * 2 + PADDING) + }; + }); + var saveButton = toolBar.addOverlay("image", { + width: BUTTON_SIZE, + height: BUTTON_SIZE, + imageURL: "http://headache.hungry.com/~seth/hifi/save.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1 + }); + var loadButton = toolBar.addOverlay("image", { + width: BUTTON_SIZE, + height: BUTTON_SIZE, + imageURL: "http://headache.hungry.com/~seth/hifi/load.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1 + }); +} function mousePressEvent(event) { @@ -73,10 +76,14 @@ function mousePressEvent(event) { } function scriptEnding() { - toolBar.cleanup(); + if (SHOW_TOOL_BAR) { + toolBar.cleanup(); + } } -Controller.mousePressEvent.connect(mousePressEvent); +if (SHOW_TOOL_BAR) { + Controller.mousePressEvent.connect(mousePressEvent); +} Script.scriptEnding.connect(scriptEnding); diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 5ca62470ee..35af5f4eae 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -21,3 +21,4 @@ Script.load("controllers/squeezeHands.js"); Script.load("grab.js"); Script.load("directory.js"); Script.load("dialTone.js"); +Script.load("attachedEntitiesManager.js"); From aa10af2851f25284dd1ed4c8ee0ceed4f517add1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 2 Feb 2016 17:10:21 -0800 Subject: [PATCH 24/27] Revert "Move DrawStencil to use ShapePlumber" This reverts commit 671f27e5bc3950cc75884a5b8b0e6b6221011cb5. --- .../render-utils/src/RenderDeferredTask.cpp | 15 ++++++---- .../render-utils/src/RenderDeferredTask.h | 9 +++--- .../render-utils/src/RenderPipelines.cpp | 28 +++++++++---------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 8a47280526..e21b8ce799 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -32,8 +32,8 @@ using namespace render; +extern void initStencilPipeline(gpu::PipelinePointer& pipeline); extern void initOverlay3DPipelines(render::ShapePlumber& plumber); -extern void initStencilPipelines(render::ShapePlumber& plumber); extern void initDeferredPipelines(render::ShapePlumber& plumber); void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -217,8 +217,12 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon } } -DrawStencilDeferred::DrawStencilDeferred() : _shapePlumber{ std::make_shared() } { - initStencilPipelines(*_shapePlumber); +gpu::PipelinePointer DrawStencilDeferred::_opaquePipeline; +const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { + if (!_opaquePipeline) { + initStencilPipeline(_opaquePipeline); + } + return _opaquePipeline; } void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -238,12 +242,11 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - // We only need to fetch this once - static const auto& pipeline = _shapePlumber->pickPipeline(args, ShapeKey()); + batch.setPipeline(getOpaquePipeline()); - batch.setPipeline(pipeline->pipeline); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, nullptr); + }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 894a91cdc3..0be2e0e808 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -68,14 +68,13 @@ protected: class DrawStencilDeferred { public: - DrawStencilDeferred(); - - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Job::Model; + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + static const gpu::PipelinePointer& getOpaquePipeline(); + protected: - render::ShapePlumberPointer _shapePlumber; + static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable }; class DrawBackgroundDeferred { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index a7e9081d9a..d2e880aea3 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -43,19 +43,7 @@ using namespace render; -void initOverlay3DPipelines(ShapePlumber& plumber) { - auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); - auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - - auto opaqueState = std::make_shared(); - opaqueState->setDepthTest(false); - opaqueState->setBlendFunction(false); - - plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState); -} - -void initStencilPipelines(ShapePlumber& plumber) { +void initStencilPipeline(gpu::PipelinePointer& pipeline) { const gpu::int8 STENCIL_OPAQUE = 1; auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); auto ps = gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)); @@ -67,7 +55,19 @@ void initStencilPipelines(ShapePlumber& plumber) { state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE)); state->setColorWriteMask(0); - plumber.addPipeline(ShapeKey::Filter::Builder(), program, state); + pipeline = gpu::Pipeline::create(program, state); +} + +void initOverlay3DPipelines(ShapePlumber& plumber) { + auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert)); + auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + + auto opaqueState = std::make_shared(); + opaqueState->setDepthTest(false); + opaqueState->setBlendFunction(false); + + plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState); } void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { From fff603e4e2f5a48567f7fb390cebdcb0c07a019d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 3 Feb 2016 10:21:27 -0800 Subject: [PATCH 25/27] Removed comment --- libraries/physics/src/CharacterController.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 941428f03a..d16c406658 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -499,8 +499,6 @@ void CharacterController::preSimulation() { } } - /// _walkVelocity.dot(_currentUp) > UPWARD_VELOCITY_THRESHOLD - _previousFlags = _pendingFlags; _pendingFlags &= ~PENDING_FLAG_JUMP; From ad2a7bfc3c4048bae461a0de08244ab0108c92fc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 3 Feb 2016 10:54:08 -0800 Subject: [PATCH 26/27] code review --- examples/attachedEntitiesManager.js | 4 ++-- examples/controllers/handControllerGrab.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/attachedEntitiesManager.js b/examples/attachedEntitiesManager.js index c44ac66a44..1cdd61ad39 100644 --- a/examples/attachedEntitiesManager.js +++ b/examples/attachedEntitiesManager.js @@ -40,7 +40,7 @@ if (SHOW_TOOL_BAR) { var saveButton = toolBar.addOverlay("image", { width: BUTTON_SIZE, height: BUTTON_SIZE, - imageURL: "http://headache.hungry.com/~seth/hifi/save.png", + imageURL: ".../save.png", color: { red: 255, green: 255, @@ -51,7 +51,7 @@ if (SHOW_TOOL_BAR) { var loadButton = toolBar.addOverlay("image", { width: BUTTON_SIZE, height: BUTTON_SIZE, - imageURL: "http://headache.hungry.com/~seth/hifi/load.png", + imageURL: ".../load.png", color: { red: 255, green: 255, diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 842c54b86d..ee3184d78f 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -1224,6 +1224,7 @@ function MyController(hand) { return true; } } + return false; } this.getPresetPosition = function() { From 93530fca72fa36ff5422cc5d8d97f4f25c034d6c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 1 Feb 2016 16:20:59 -0800 Subject: [PATCH 27/27] fix the last of the current override warnings for OS X --- interface/src/Application.h | 10 +++++----- interface/src/avatar/Avatar.h | 8 ++++---- interface/src/avatar/AvatarMotionState.h | 4 ++-- interface/src/ui/overlays/ImageOverlay.h | 2 +- interface/src/ui/overlays/TextOverlay.h | 2 +- libraries/animation/src/SwingTwistConstraint.h | 2 +- .../src/RenderableBoxEntityItem.h | 4 ++-- .../src/RenderableLightEntityItem.h | 6 +++--- .../src/RenderableLineEntityItem.h | 2 +- .../src/RenderableSphereEntityItem.h | 4 ++-- .../src/RenderableTextEntityItem.h | 2 +- .../src/RenderableWebEntityItem.h | 4 ++-- libraries/physics/src/EntityMotionState.h | 16 ++++++++-------- 13 files changed, 33 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 4b32d8879b..3d2cb6f351 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -167,11 +167,11 @@ public: virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; - virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } - virtual QThread* getMainThread() { return thread(); } - virtual PickRay computePickRay(float x, float y) const; - virtual glm::vec3 getAvatarPosition() const; - virtual qreal getDevicePixelRatio(); + virtual ViewFrustum* getCurrentViewFrustum() override { return getDisplayViewFrustum(); } + virtual QThread* getMainThread() override { return thread(); } + virtual PickRay computePickRay(float x, float y) const override; + virtual glm::vec3 getAvatarPosition() const override; + virtual qreal getDevicePixelRatio() override; void setActiveDisplayPlugin(const QString& pluginName); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index db247f3e85..b23b64b384 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -164,10 +164,10 @@ public: virtual void setOrientation(const glm::quat& orientation) override; // these call through to the SpatiallyNestable versions, but they are here to expose these to javascript. - Q_INVOKABLE virtual const QUuid getParentID() const { return SpatiallyNestable::getParentID(); } - Q_INVOKABLE virtual void setParentID(const QUuid& parentID); - Q_INVOKABLE virtual quint16 getParentJointIndex() const { return SpatiallyNestable::getParentJointIndex(); } - Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex); + Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); } + Q_INVOKABLE virtual void setParentID(const QUuid& parentID) override; + Q_INVOKABLE virtual quint16 getParentJointIndex() const override { return SpatiallyNestable::getParentJointIndex(); } + Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override; // NOT thread safe, must be called on main thread. glm::vec3 getUncachedLeftPalmPosition() const; diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 715c38186b..04aa5ea57c 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -61,7 +61,7 @@ public: void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } - virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const; + virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; friend class AvatarManager; friend class Avatar; @@ -72,7 +72,7 @@ protected: ~AvatarMotionState(); virtual bool isReadyToComputeShape() const override { return true; } - virtual btCollisionShape* computeNewShape(); + virtual btCollisionShape* computeNewShape() override; // The AvatarMotionState keeps a RAW backpointer to its Avatar because all AvatarMotionState // instances are "owned" by their corresponding Avatar instance and are deleted in the Avatar dtor. diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index 224cb42045..40da461822 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -20,7 +20,7 @@ class ImageOverlay : public QmlOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + virtual QString getType() const override { return TYPE; } static QUrl const URL; ImageOverlay(); diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 7c6e133ebd..53c1805345 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -30,7 +30,7 @@ public: void setText(const QString& text); - TextOverlay* createClone() const; + TextOverlay* createClone() const override; QSizeF textSize(const QString& text) const; // Pixels }; diff --git a/libraries/animation/src/SwingTwistConstraint.h b/libraries/animation/src/SwingTwistConstraint.h index f36dc851ea..f73bbfb233 100644 --- a/libraries/animation/src/SwingTwistConstraint.h +++ b/libraries/animation/src/SwingTwistConstraint.h @@ -51,7 +51,7 @@ public: virtual bool apply(glm::quat& rotation) const override; void setLowerSpine(bool lowerSpine) { _lowerSpine = lowerSpine; } - virtual bool isLowerSpine() const { return _lowerSpine; } + virtual bool isLowerSpine() const override { return _lowerSpine; } // SwingLimitFunction is an implementation of the constraint check described in the paper: // "The Parameterization of Joint Rotation with the Unit Quaternion" by Quang Liu and Edmond C. Prakash diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.h b/libraries/entities-renderer/src/RenderableBoxEntityItem.h index 9addfd813a..67f881dbd8 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.h @@ -22,8 +22,8 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableBoxEntityItem(const EntityItemID& entityItemID) : BoxEntityItem(entityItemID) { } - virtual void render(RenderArgs* args); - virtual void setUserData(const QString& value); + virtual void render(RenderArgs* args) override; + virtual void setUserData(const QString& value) override; SIMPLE_RENDERABLE() private: diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index aac1a4a998..2db913db0d 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -20,12 +20,12 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableLightEntityItem(const EntityItemID& entityItemID) : LightEntityItem(entityItemID) { } - virtual void render(RenderArgs* args); - virtual bool supportsDetailedRayIntersection() const { return true; } + virtual void render(RenderArgs* args) override; + virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, - void** intersectedObject, bool precisionPicking) const; + void** intersectedObject, bool precisionPicking) const override; SIMPLE_RENDERABLE(); }; diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.h b/libraries/entities-renderer/src/RenderableLineEntityItem.h index 9af8c0c8ba..1227c6e63d 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.h @@ -24,7 +24,7 @@ public: _lineVerticesID(GeometryCache::UNKNOWN_ID) { } - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderableSphereEntityItem.h b/libraries/entities-renderer/src/RenderableSphereEntityItem.h index 737bee3134..5efe49854a 100644 --- a/libraries/entities-renderer/src/RenderableSphereEntityItem.h +++ b/libraries/entities-renderer/src/RenderableSphereEntityItem.h @@ -22,8 +22,8 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); RenderableSphereEntityItem(const EntityItemID& entityItemID) : SphereEntityItem(entityItemID) { } - virtual void render(RenderArgs* args); - virtual void setUserData(const QString& value); + virtual void render(RenderArgs* args) override; + virtual void setUserData(const QString& value) override; SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 149df946f7..cbe2b11c27 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -25,7 +25,7 @@ public: RenderableTextEntityItem(const EntityItemID& entityItemID) : TextEntityItem(entityItemID) { } ~RenderableTextEntityItem() { delete _textRenderer; } - virtual void render(RenderArgs* args); + virtual void render(RenderArgs* args) override; SIMPLE_RENDERABLE(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 799a414151..da1ddbf1a1 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -25,8 +25,8 @@ public: RenderableWebEntityItem(const EntityItemID& entityItemID); ~RenderableWebEntityItem(); - virtual void render(RenderArgs* args); - virtual void setSourceUrl(const QString& value); + virtual void render(RenderArgs* args) override; + virtual void setSourceUrl(const QString& value) override; void setProxyWindow(QWindow* proxyWindow); QObject* getEventHandler(); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 152ae7be23..2c999d0aca 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -29,13 +29,13 @@ public: virtual ~EntityMotionState(); void updateServerPhysicsVariables(); - virtual bool handleEasyChanges(uint32_t& flags); - virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine); + virtual bool handleEasyChanges(uint32_t& flags) override; + virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override; /// \return PhysicsMotionType based on params set in EntityItem - virtual PhysicsMotionType computePhysicsMotionType() const; + virtual PhysicsMotionType computePhysicsMotionType() const override; - virtual bool isMoving() const; + virtual bool isMoving() const override; // this relays incoming position/rotation to the RigidBody virtual void getWorldTransform(btTransform& worldTrans) const override; @@ -48,8 +48,8 @@ public: bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID); void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step); - virtual uint32_t getIncomingDirtyFlags(); - virtual void clearIncomingDirtyFlags(); + virtual uint32_t getIncomingDirtyFlags() override; + virtual void clearIncomingDirtyFlags() override; void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; } void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; } @@ -80,7 +80,7 @@ public: virtual QString getName() const override; - virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const; + virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; // eternal logic can suggest a simuator priority bid for the next outgoing update void setOutgoingPriority(quint8 priority); @@ -93,7 +93,7 @@ protected: #endif virtual bool isReadyToComputeShape() const override; - virtual btCollisionShape* computeNewShape(); + virtual btCollisionShape* computeNewShape() override; virtual void setMotionType(PhysicsMotionType motionType); // In the glorious future (when entities lib depends on physics lib) the EntityMotionState will be