From e2e61c64b11dc8ec5b30c6f8a730dfdb51faf648 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 13 Feb 2015 01:30:04 -0800 Subject: [PATCH 001/341] Support include path to shaders from the hifi libraries to cmake --- cmake/macros/AutoScribeShader.cmake | 22 ++++++- libraries/gpu/CMakeLists.txt | 2 + .../src => gpu/src/gpu}/Config.slh | 4 +- libraries/gpu/src/gpu/Transform.slh | 60 +++++++++++++++++++ libraries/model/CMakeLists.txt | 2 + .../src => model/src/model}/Light.slh | 4 +- .../src => model/src/model}/Material.slh | 4 +- libraries/render-utils/CMakeLists.txt | 2 +- .../render-utils/src/DeferredGlobalLight.slh | 2 +- libraries/render-utils/src/deferred_light.slv | 2 +- .../src/deferred_light_limited.slv | 2 +- .../src/directional_ambient_light.slf | 2 +- ...onal_ambient_light_cascaded_shadow_map.slf | 2 +- .../directional_ambient_light_shadow_map.slf | 2 +- .../render-utils/src/directional_light.slf | 2 +- .../directional_light_cascaded_shadow_map.slf | 2 +- .../src/directional_light_shadow_map.slf | 2 +- libraries/render-utils/src/model.slf | 4 +- libraries/render-utils/src/model.slv | 3 +- libraries/render-utils/src/model_lightmap.slf | 4 +- libraries/render-utils/src/model_lightmap.slv | 2 +- .../src/model_lightmap_normal_map.slf | 4 +- .../src/model_lightmap_normal_map.slv | 2 +- .../model_lightmap_normal_specular_map.slf | 4 +- .../src/model_lightmap_specular_map.slf | 4 +- .../render-utils/src/model_normal_map.slf | 4 +- .../render-utils/src/model_normal_map.slv | 2 +- .../src/model_normal_specular_map.slf | 4 +- libraries/render-utils/src/model_shadow.slf | 2 +- libraries/render-utils/src/model_shadow.slv | 2 +- .../render-utils/src/model_specular_map.slf | 4 +- .../render-utils/src/model_translucent.slf | 4 +- libraries/render-utils/src/point_light.slf | 4 +- libraries/render-utils/src/sdf_text.slf | 2 +- libraries/render-utils/src/sdf_text.slv | 2 +- libraries/render-utils/src/simple.slf | 2 +- libraries/render-utils/src/simple.slv | 2 +- libraries/render-utils/src/skin_model.slv | 2 +- .../src/skin_model_normal_map.slv | 2 +- .../render-utils/src/skin_model_shadow.slv | 2 +- libraries/render-utils/src/spot_light.slf | 4 +- 41 files changed, 137 insertions(+), 52 deletions(-) rename libraries/{render-utils/src => gpu/src/gpu}/Config.slh (90%) mode change 100755 => 100644 create mode 100644 libraries/gpu/src/gpu/Transform.slh rename libraries/{render-utils/src => model/src/model}/Light.slh (93%) mode change 100755 => 100644 rename libraries/{render-utils/src => model/src/model}/Material.slh (91%) mode change 100755 => 100644 diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake index 8b221c8c59..51b6b205e8 100755 --- a/cmake/macros/AutoScribeShader.cmake +++ b/cmake/macros/AutoScribeShader.cmake @@ -15,12 +15,21 @@ function(AUTOSCRIBE_SHADER SHADER_FILE) list(APPEND SHADER_INCLUDE_FILES ${includeFile}) endforeach() - #Extract the unique include shader paths foreach(SHADER_INCLUDE ${SHADER_INCLUDE_FILES}) get_filename_component(INCLUDE_DIR ${SHADER_INCLUDE} PATH) list(APPEND SHADER_INCLUDES_PATHS ${INCLUDE_DIR}) endforeach() + + + #Extract the unique include shader paths + set(INCLUDES ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES}) + #message(Hifi for includes ${INCLUDES}) + foreach(EXTRA_SHADER_INCLUDE ${INCLUDES}) + list(APPEND SHADER_INCLUDES_PATHS ${EXTRA_SHADER_INCLUDE}) + endforeach() + list(REMOVE_DUPLICATES SHADER_INCLUDES_PATHS) + #message(ready for includes ${SHADER_INCLUDES_PATHS}) # make the scribe include arguments set(SCRIBE_INCLUDES) @@ -64,6 +73,17 @@ endfunction() macro(AUTOSCRIBE_SHADER_LIB) + + file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}") + foreach(HIFI_LIBRARY ${ARGN}) + #if (NOT TARGET ${HIFI_LIBRARY}) + # file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}/src/) + #endif () + + #file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src/*.slh) + list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src) + endforeach() + #message(${HIFI_LIBRARIES_SHADER_INCLUDE_FILES}) file(GLOB_RECURSE SHADER_INCLUDE_FILES src/*.slh) file(GLOB_RECURSE SHADER_SOURCE_FILES src/*.slv src/*.slf) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index b6bbba1c0f..9965657073 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -1,5 +1,7 @@ set(TARGET_NAME gpu) +AUTOSCRIBE_SHADER_LIB(gpu) + # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/render-utils/src/Config.slh b/libraries/gpu/src/gpu/Config.slh old mode 100755 new mode 100644 similarity index 90% rename from libraries/render-utils/src/Config.slh rename to libraries/gpu/src/gpu/Config.slh index b431b671a6..b17bd7b2b8 --- a/libraries/render-utils/src/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -8,8 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html !> -<@if not CONFIG_SLH@> -<@def CONFIG_SLH@> +<@if not GPU_CONFIG_SLH@> +<@def GPU_CONFIG_SLH@> <@if GLPROFILE == PC_GL @> <@def VERSION_HEADER #version 330 compatibility@> diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh new file mode 100644 index 0000000000..56bea01e02 --- /dev/null +++ b/libraries/gpu/src/gpu/Transform.slh @@ -0,0 +1,60 @@ + +<@if not GPU_TRANSFORM_STATE_SLH@> +<@def GPU_TRANSFORM_STATE_SLH@> + +struct TransformObject { + mat4 _model; + mat4 _modelInverseTranspose; +}; + +struct TransformCamera { + mat4 _view; + mat4 _viewInverseTranspose; + mat4 _proj; + mat4 _projInverseTranspose; + mat4 _viewProj; + mat4 _viewProjInverseTranspose; +}; + +vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { + return camera._proj * (camera._view * (object._model * pos))); +} + + + +<@if GLPROFILE == PC_GL@> +uniform transformStateBuffer { + TransformState xform; +}; +TransformState getTransformState() { + return xform; +} +<@elif GLPROFILE == MAC_GL@> +uniform vec4 transformStateBuffer[2]; +TransformState getTransformState() { + TransformState xform; + xform._diffuse = transformStateBuffer[0]; + xform._specular = transformStateBuffer[1]; + return xform; +} +<@else@> +uniform vec4 transformStateBuffer[2]; +TransformState getMaterial() { + TransformState xform; + xform._diffuse = transformStateBuffer[0]; + xform._specular = transformStateBuffer[1]; + return xform; +} +<@endif@> + + + +<@endif@> diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index 309f6c3e6d..af3b270287 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -1,4 +1,6 @@ set(TARGET_NAME model) + +AUTOSCRIBE_SHADER_LIB(gpu) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/render-utils/src/Light.slh b/libraries/model/src/model/Light.slh old mode 100755 new mode 100644 similarity index 93% rename from libraries/render-utils/src/Light.slh rename to libraries/model/src/model/Light.slh index abb9fb6c2a..fc17e94050 --- a/libraries/render-utils/src/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -8,8 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html !> -<@if not LIGHT_SLH@> -<@def LIGHT_SLH@> +<@if not MODEL_LIGHT_SLH@> +<@def MODEL_LIGHT_SLH@> struct Light { vec4 _position; diff --git a/libraries/render-utils/src/Material.slh b/libraries/model/src/model/Material.slh old mode 100755 new mode 100644 similarity index 91% rename from libraries/render-utils/src/Material.slh rename to libraries/model/src/model/Material.slh index 86c6049ec6..403a4161e8 --- a/libraries/render-utils/src/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -8,8 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html !> -<@if not MATERIAL_SLH@> -<@def MATERIAL_SLH@> +<@if not MODEL_MATERIAL_SLH@> +<@def MODEL_MATERIAL_SLH@> struct Material { vec4 _diffuse; diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index ed2dcce858..188073819e 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME render-utils) -AUTOSCRIBE_SHADER_LIB() +AUTOSCRIBE_SHADER_LIB(gpu model) # pull in the resources.qrc file qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 6868b96c24..5aa42cf3aa 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -49,7 +49,7 @@ vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { uniform SphericalHarmonics ambientSphere; // Everything about light -<@include Light.slh@> +<@include model/Light.slh@> // The view Matrix uniform mat4 invViewMat; diff --git a/libraries/render-utils/src/deferred_light.slv b/libraries/render-utils/src/deferred_light.slv index f26539fe69..1427dd0f52 100644 --- a/libraries/render-utils/src/deferred_light.slv +++ b/libraries/render-utils/src/deferred_light.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index fdfb88d806..e3051d43f7 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 308a8a73a7..114c5615b8 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf index db017cf5ac..d52363a26b 100755 --- a/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_cascaded_shadow_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf index 43d3e91dbe..7f098eac2e 100755 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 3e708f849e..0299b2a229 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf index 90b3bf1d2b..71464fb916 100644 --- a/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_cascaded_shadow_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/directional_light_shadow_map.slf b/libraries/render-utils/src/directional_light_shadow_map.slf index 5029b57020..2c53a02348 100644 --- a/libraries/render-utils/src/directional_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_light_shadow_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index bc6f127a77..be465ed908 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // model.frag @@ -13,7 +13,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 1c3b03a304..260dd8f0f9 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // model.vert @@ -11,6 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index 59836e9737..9db31bf1ad 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 1ea5b7b68a..53da84de73 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 6310ab0086..a7b6494ee5 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index 14e1d52779..f4f5e72167 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf index ab555ea0c0..e5daae4160 100755 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index 2973882e8a..820ded5cad 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index c6baa6f797..5ad0bfb50d 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index a27cd49171..582f1b1abb 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index 8e7c9d3293..5c272d0c6b 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf index 1fbb44140b..e8bdb01f30 100755 --- a/libraries/render-utils/src/model_shadow.slf +++ b/libraries/render-utils/src/model_shadow.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv index 6ff8c23f5a..b05a92b155 100755 --- a/libraries/render-utils/src/model_shadow.slv +++ b/libraries/render-utils/src/model_shadow.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index bfcc69287d..e50d2c452d 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 4d1bf7bdec..91592e07de 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -<@include Material.slh@> +<@include model/Material.slh@> // the diffuse texture uniform sampler2D diffuseMap; diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index abe904ecce..78d3d1e458 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -19,7 +19,7 @@ <@include DeferredLighting.slh@> // Everything about light -<@include Light.slh@> +<@include model/Light.slh@> // The view Matrix uniform mat4 invViewMat; diff --git a/libraries/render-utils/src/sdf_text.slf b/libraries/render-utils/src/sdf_text.slf index 0e89ce4f47..1affbe4c57 100644 --- a/libraries/render-utils/src/sdf_text.slf +++ b/libraries/render-utils/src/sdf_text.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // sdf_text.frag diff --git a/libraries/render-utils/src/sdf_text.slv b/libraries/render-utils/src/sdf_text.slv index 7fb6dd42e8..27db1c4985 100644 --- a/libraries/render-utils/src/sdf_text.slv +++ b/libraries/render-utils/src/sdf_text.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // sdf_text.vert diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index faa4af4573..3e70674e33 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index e874a6d8a9..61338b440d 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index 4cef8fddab..737fa85bf0 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index c39f9cc0dd..3db63f9d98 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv index 9a594ac26c..3625d4006a 100755 --- a/libraries/render-utils/src/skin_model_shadow.slv +++ b/libraries/render-utils/src/skin_model_shadow.slv @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 95fabae3ed..e6c3938b71 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -1,4 +1,4 @@ -<@include Config.slh@> +<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // @@ -19,7 +19,7 @@ <@include DeferredLighting.slh@> // Everything about light -<@include Light.slh@> +<@include model/Light.slh@> // The view Matrix uniform mat4 invViewMat; From 8944bdd1e54132d3bc04df79290bbf3f29cae5c9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 13 Feb 2015 02:17:08 -0800 Subject: [PATCH 002/341] COmment out problems --- libraries/gpu/src/gpu/Transform.slh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 56bea01e02..04ed408b03 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -29,7 +29,7 @@ vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { } - + uniform transformStateBuffer { TransformState xform; @@ -54,7 +54,7 @@ TransformState getMaterial() { return xform; } <@endif@> - +!> <@endif@> From cc3cc4f96f045d73e675a2a7d6db1d3c773f4e09 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 16 Feb 2015 09:31:29 -0800 Subject: [PATCH 003/341] replacing the glTransform pipeline for model rendering --- libraries/gpu/src/gpu/Batch.cpp | 4 +- libraries/gpu/src/gpu/Batch.h | 2 +- libraries/gpu/src/gpu/Config.slh | 17 ++++++ libraries/gpu/src/gpu/Context.h | 15 ++++++ libraries/gpu/src/gpu/Format.h | 7 +++ libraries/gpu/src/gpu/GLBackend.cpp | 77 ++++++++++++++++++++++++++-- libraries/gpu/src/gpu/GLBackend.h | 10 +++- libraries/gpu/src/gpu/Transform.slh | 12 ++--- libraries/octree/src/ViewFrustum.cpp | 7 +++ libraries/octree/src/ViewFrustum.h | 1 + libraries/render-utils/src/Model.cpp | 15 ++++++ libraries/render-utils/src/model.slv | 24 ++++++++- libraries/shared/src/Transform.h | 8 +++ 13 files changed, 185 insertions(+), 14 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index b15ee4fe29..cd4f4d7d2c 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -153,10 +153,10 @@ void Batch::setViewTransform(const Transform& view) { _params.push_back(_transforms.cache(view)); } -void Batch::setProjectionTransform(const Transform& proj) { +void Batch::setProjectionTransform(const Mat4& proj) { ADD_COMMAND(setProjectionTransform); - _params.push_back(_transforms.cache(proj)); + _params.push_back(cacheData(sizeof(Mat4), &proj); } void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 0657eacd6e..b9467f7fdc 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -89,7 +89,7 @@ public: // with the ModelTransformu to create the equivalent of the glModelViewMatrix void setModelTransform(const Transform& model); void setViewTransform(const Transform& view); - void setProjectionTransform(const Transform& proj); + void setProjectionTransform(const Mat4& proj); // Shader Stage void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index b17bd7b2b8..0ef68c9fd0 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -13,6 +13,23 @@ <@if GLPROFILE == PC_GL @> <@def VERSION_HEADER #version 330 compatibility@> + +<@func inputPosition name@> +layout(location = 0) in vec3 <$name$>; +<@endfunc@> + +<@func inputNormal name@> +layout(location = 1) in vec3 <$name$>; +<@endfunc@> + +<@func inputTexcoord name@> +layout(location = 4) in vec2 <$name$>; +<@endfunc@> + +<@func inputColor name@> +layout(location = 4) vec3 <$name$>; +<@endfunc@> + <@elif GLPROFILE == MAC_GL @> <@def VERSION_HEADER #version 120@> <@else@> diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index b8cba3ded1..2bbf9ea032 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -29,6 +29,21 @@ class Batch; class Backend { public: + class TransformObject { + public: + Mat4 _model; + Mat4 _modelInverse; + Mat4 _modelView; + Mat4 _modelViewInverseTranspose; + }; + + class TransformCamera { + public: + Mat4 _view; + Mat4 _viewInverse; + Mat4 _projection; + }; + template< typename T > static void setGPUObject(const Buffer& buffer, T* bo) { buffer.setGPUObject(reinterpret_cast(bo)); diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 6274c294ec..cbf90384ce 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -11,6 +11,7 @@ #ifndef hifi_gpu_Format_h #define hifi_gpu_Format_h +#include #include namespace gpu { @@ -24,6 +25,12 @@ typedef char int8; typedef uint32 Offset; +typedef glm::mat4 Mat4; +typedef glm::mat3 Mat3; +typedef glm::vec4 Vec4; +typedef glm::vec3 Vec3; +typedef glm::vec2 Vec2; + // Description of a scalar type enum Type { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 34ca47f300..7cc3958497 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -386,18 +386,49 @@ void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { } void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { - _transform._projection = batch._transforms.get(batch._params[paramOffset]._uint); + memcpy(&_transform._projection, batch.editData(batch._params[paramOffset]._uint), sizeof(Mat4)); _transform._invalidProj = true; } +void GLBackend::initTransform() { +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glGenBuffers(1, &_transform._transformObjectBuffer); + glGenBuffers(1, &_transform._transformCameraBuffer); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); + + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); + + + glBindBuffer(GL_UNIFORM_BUFFER, 0); +#else +#endif +} + +void GLBackend::killTransform() { +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glDeleteBuffers(1, &_transform._transformObjectBuffer); + glDeleteBuffers(1, &_transform._transformCameraBuffer); +#else +#endif +} + void GLBackend::updateTransform() { +#define LEGACY_TRANSFORM_PIPELINE +#ifdef LEGACY_TRANSFORM_PIPELINE if (_transform._invalidProj) { // TODO: implement the projection matrix assignment to gl state - /* if (_transform._lastMode != GL_PROJECTION) { + if (_transform._lastMode != GL_PROJECTION) { glMatrixMode(GL_PROJECTION); _transform._lastMode = GL_PROJECTION; } - CHECK_GL_ERROR();*/ + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); + + CHECK_GL_ERROR(); } if (_transform._invalidModel || _transform._invalidView) { @@ -434,6 +465,46 @@ void GLBackend::updateTransform() { _transform._invalidModel = false; _transform._invalidView = false; } +#else + + if (_transform._invalidProj) { + _transform._transformCamera._projection = _transform._projection; + } + + if (_transform._invalidView) { + _transform._view.getInverseMatrix(_transform._transformCamera._view); + _transform._view.getMatrix(_transform._transformCamera._viewInverse); + } + + if (_transform._invalidModel) { + _transform._model.getMatrix(_transform._transformObject._model); + _transform._model.getInverseMatrix(_transform._transformObject._modelInverse); + } + + if (_transform._invalidView || _transform._invalidModel) { + Transform mvx; + Transform::inverseMult(mvx, _transform._view, _transform._model); + mvx.getMatrix(_transform._transformObject._modelView); + mvx.getInverseTransposeMatrix(_transform._transformObject._modelViewInverseTranspose); + } + + if (_transform._invalidView || _transform._invalidProj) { + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + if (_transform._invalidView || _transform._invalidModel) { + glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + glBindBufferRange(GL_UNIFORM_BUFFER, 0, _transform._transformCameraBuffer, 0, sizeof(TransformCamera)); + glBindBufferRange(GL_UNIFORM_BUFFER, 1, _transform._transformObjectBuffer, 0, sizeof(TransformObject)); + + _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; +#endif } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3450ae71a..1c5906525b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -113,11 +113,17 @@ protected: void do_setViewTransform(Batch& batch, uint32 paramOffset); void do_setProjectionTransform(Batch& batch, uint32 paramOffset); + void initTransform(); + void killTransform(); void updateTransform(); struct TransformStageState { + TransformObject _transformObject; + TransformCamera _transformCamera; + GLuint _transformObjectBuffer; + GLuint _transformCameraBuffer; Transform _model; Transform _view; - Transform _projection; + Mat4 _projection; bool _invalidModel; bool _invalidView; bool _invalidProj; @@ -125,6 +131,8 @@ protected: GLenum _lastMode; TransformStageState() : + _transformObjectBuffer(0), + _transformCameraBuffer(0), _model(), _view(), _projection(), diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 04ed408b03..1ae422cd08 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -13,19 +13,19 @@ struct TransformObject { mat4 _model; mat4 _modelInverseTranspose; + mat4 _modelView; + mat4 _modelViewInverseTranspose; }; struct TransformCamera { mat4 _view; - mat4 _viewInverseTranspose; - mat4 _proj; - mat4 _projInverseTranspose; - mat4 _viewProj; - mat4 _viewProjInverseTranspose; + mat4 _viewInverse; + mat4 _projection; + }; vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { - return camera._proj * (camera._view * (object._model * pos))); + return camera._projection * (object._modelView * pos); } diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 81ce31d767..8181a1098b 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -866,4 +866,11 @@ float ViewFrustum::distanceToCamera(const glm::vec3& point) const { return distanceToPoint; } +void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { + if (isOrthographic()) { + proj = glm::ortho(getWidth() * -0.5, getWidth() * +0.5, getHeight() * -0.5, getHeight() * 0.5); + } else { + proj = glm::perspective(getFieldOfView(), getAspectRatio(), getNearClip(), getFarClip()); + } +} diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index c40bc37652..a74140b94f 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -124,6 +124,7 @@ public: float distanceToCamera(const glm::vec3& point) const; + void evalProjectionMatrix(glm::mat4& proj) const; private: // Used for keyhole calculations ViewFrustum::location pointInKeyhole(const glm::vec3& point) const; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f166aecae9..edbce6b814 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1659,11 +1659,26 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + RenderArgs::RenderSide renderSide = RenderArgs::MONO; if (args) { renderSide = args->_renderSide; } + if (args) { + glm::mat4 proj; + args->_viewFrustum->evalProjectionMatrix(proj); + gpu::Batch batch; + batch.setProjectionTransform(proj); + ::gpu::GLBackend::renderBatch(batch); + + } + + _viewState->getViewTransform(); + // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) + _transforms[0].preTranslate(-_translation); + + // Do the rendering batch creation for mono or left eye, not for right eye if (renderSide != RenderArgs::STEREO_RIGHT) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 260dd8f0f9..1da88a3876 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -14,6 +14,11 @@ <@include gpu/Transform.slh@> const int MAX_TEXCOORDS = 2; +<$inputPosition(vin_position)$> +<$inputNormal(vin_normal)$> +<$inputTexcoord(vin_texcoord)$> +<$inputColor(vin_color)$> + uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal @@ -30,6 +35,23 @@ void main(void) { gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * vec4(vin_position, 1.0); } + + +/* +void main(void) { + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // pass along the diffuse color + gl_FrontColor = gl_Color; + + // and the texture coordinates + gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + + // use standard pipeline transform + gl_Position = ftransform(); +} +*/ diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 346a82a3b0..4f5f441170 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -90,6 +90,7 @@ public: Mat4& getMatrix(Mat4& result) const; Mat4& getInverseMatrix(Mat4& result) const; + Mat4& getInverseTransposeMatrix(Mat4& result) const; Transform& evalInverse(Transform& result) const; @@ -329,6 +330,13 @@ inline Transform::Mat4& Transform::getInverseMatrix(Transform::Mat4& result) con return inverse.getMatrix(result); } +inline Transform::Mat4& Transform::getInverseTransposeMatrix(Transform::Mat4& result) const { + getInverseMatrix(result); + result = glm::transpose(result); + return result; +} + + inline void Transform::evalFromRawMatrix(const Mat4& matrix) { // for now works only in the case of TRS transformation if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.0f)) { From 23354da828b04b6c606a280ba13885a7998ee64c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 16 Feb 2015 22:08:21 -0800 Subject: [PATCH 004/341] replacing the glTransform pipeline for model rendering --- libraries/gpu/src/gpu/Batch.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 16 +++++--- libraries/gpu/src/gpu/GLBackend.h | 5 ++- libraries/octree/src/ViewFrustum.cpp | 6 ++- .../render-utils/src/DeferredGlobalLight.slh | 5 ++- libraries/render-utils/src/Model.cpp | 40 ++++++++++--------- libraries/render-utils/src/model.slv | 13 ++---- 7 files changed, 48 insertions(+), 39 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index cd4f4d7d2c..ddbc76fce6 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -156,7 +156,7 @@ void Batch::setViewTransform(const Transform& view) { void Batch::setProjectionTransform(const Mat4& proj) { ADD_COMMAND(setProjectionTransform); - _params.push_back(cacheData(sizeof(Mat4), &proj); + _params.push_back(cacheData(sizeof(Mat4), &proj)); } void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 7cc3958497..4473b00341 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -80,21 +80,25 @@ GLBackend::~GLBackend() { } -void GLBackend::renderBatch(Batch& batch) { +void GLBackend::render(Batch& batch) { + uint32 numCommands = batch.getCommands().size(); const Batch::Commands::value_type* command = batch.getCommands().data(); const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data(); - GLBackend backend; - for (unsigned int i = 0; i < numCommands; i++) { CommandCall call = _commandCalls[(*command)]; - (backend.*(call))(batch, *offset); + (this->*(call))(batch, *offset); command++; offset++; } } +void GLBackend::renderBatch(Batch& batch) { + GLBackend backend; + backend.render(batch); +} + void GLBackend::checkGLError() { GLenum error = glGetError(); if (!error) { @@ -416,9 +420,9 @@ void GLBackend::killTransform() { #else #endif } - +#define LEGACY_TRANSFORM_PIPELINE 1 void GLBackend::updateTransform() { -#define LEGACY_TRANSFORM_PIPELINE + #ifdef LEGACY_TRANSFORM_PIPELINE if (_transform._invalidProj) { // TODO: implement the projection matrix assignment to gl state diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 1c5906525b..249a2fb8f9 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -27,10 +27,13 @@ public: GLBackend(); ~GLBackend(); + void render(Batch& batch); + static void renderBatch(Batch& batch); static void checkGLError(); + class GLBuffer { public: @@ -138,7 +141,7 @@ protected: _projection(), _invalidModel(true), _invalidView(true), - _invalidProj(true), + _invalidProj(false), _lastMode(GL_TEXTURE) {} } _transform; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 8181a1098b..61324861e8 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -870,7 +870,11 @@ void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { if (isOrthographic()) { proj = glm::ortho(getWidth() * -0.5, getWidth() * +0.5, getHeight() * -0.5, getHeight() * 0.5); } else { - proj = glm::perspective(getFieldOfView(), getAspectRatio(), getNearClip(), getFarClip()); + float left, right, bottom, top, near, far; + glm::vec4 clip0, clip1; + computeOffAxisFrustum(left, right, bottom, top, near, far, clip0, clip1); + proj = glm::perspective(glm::radians(getFieldOfView()), getAspectRatio(), getNearClip(), getFarClip()); + // proj = glm::perspective(getFieldOfView() * 0.5f, getAspectRatio(), getNearClip(), getFarClip()); } } diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 5aa42cf3aa..6657100e6f 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -95,7 +95,10 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); - float diffuseDot = dot(normal, getLightDirection(light)); + + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + + float diffuseDot = dot(fragNormal, getLightDirection(light)); // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index edbce6b814..05ae810f6c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -687,6 +687,12 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { _renderBatch.clear(); gpu::Batch& batch = _renderBatch; + if (args) { + glm::mat4 proj; + args->_viewFrustum->evalProjectionMatrix(proj); + batch.setProjectionTransform(proj); + } + // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { _transforms.push_back(Transform()); @@ -1659,26 +1665,26 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); - + #if defined(ANDROID) + #else + glPushMatrix(); + #endif + RenderArgs::RenderSide renderSide = RenderArgs::MONO; if (args) { renderSide = args->_renderSide; } + gpu::GLBackend backend; + if (args) { glm::mat4 proj; args->_viewFrustum->evalProjectionMatrix(proj); gpu::Batch batch; batch.setProjectionTransform(proj); - ::gpu::GLBackend::renderBatch(batch); - + backend.render(batch); } - _viewState->getViewTransform(); - // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) - _transforms[0].preTranslate(-_translation); - - // Do the rendering batch creation for mono or left eye, not for right eye if (renderSide != RenderArgs::STEREO_RIGHT) { // Let's introduce a gpu::Batch to capture all the calls to the graphics api @@ -1833,19 +1839,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { // Render! { PROFILE_RANGE("render Batch"); - #if defined(ANDROID) - #else - glPushMatrix(); - #endif - - ::gpu::GLBackend::renderBatch(_sceneRenderBatch); - - #if defined(ANDROID) - #else - glPopMatrix(); - #endif + backend.render(_sceneRenderBatch); } + + #if defined(ANDROID) + #else + glPopMatrix(); + #endif + // restore all the default material settings _viewState->setupWorldLight(); diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 1da88a3876..f3f52ad990 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -11,19 +11,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> +//include gpu/Transform.slh const int MAX_TEXCOORDS = 2; -<$inputPosition(vin_position)$> -<$inputNormal(vin_normal)$> -<$inputTexcoord(vin_texcoord)$> -<$inputColor(vin_color)$> - uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal varying vec4 normal; - +/* void main(void) { // transform and store the normal for interpolation normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); @@ -37,10 +32,9 @@ void main(void) { // use standard pipeline transform gl_Position = gl_ModelViewProjectionMatrix * vec4(vin_position, 1.0); } +*/ - -/* void main(void) { // transform and store the normal for interpolation normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); @@ -54,4 +48,3 @@ void main(void) { // use standard pipeline transform gl_Position = ftransform(); } -*/ From d8aa0e01381399eb9a547d1b5fc4f63cb4fea8cb Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 17 Feb 2015 09:44:03 -0800 Subject: [PATCH 005/341] replacing the glTransform pipeline for model rendering --- libraries/gpu/src/gpu/Config.slh | 3 +- libraries/gpu/src/gpu/Context.h | 2 +- libraries/gpu/src/gpu/GLBackend.cpp | 55 +++++++++++++++++-- libraries/gpu/src/gpu/GLBackendShared.h | 4 +- libraries/gpu/src/gpu/Transform.slh | 21 ++++--- .../render-utils/src/DeferredGlobalLight.slh | 7 ++- libraries/render-utils/src/Model.cpp | 13 +++++ libraries/render-utils/src/model.slv | 13 ++++- 8 files changed, 95 insertions(+), 23 deletions(-) diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 0ef68c9fd0..89be6a4f54 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -12,7 +12,8 @@ <@def GPU_CONFIG_SLH@> <@if GLPROFILE == PC_GL @> - <@def VERSION_HEADER #version 330 compatibility@> + <@def VERSION_HEADER #version 410 compatibility +#@> <@func inputPosition name@> layout(location = 0) in vec3 <$name$>; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 2bbf9ea032..c426a28d90 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -39,9 +39,9 @@ public: class TransformCamera { public: + Mat4 _projection; Mat4 _view; Mat4 _viewInverse; - Mat4 _projection; }; template< typename T > diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 4473b00341..6b73782798 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -73,11 +73,11 @@ GLBackend::GLBackend() : _input(), _transform() { - + initTransform(); } GLBackend::~GLBackend() { - + killTransform(); } void GLBackend::render(Batch& batch) { @@ -420,7 +420,6 @@ void GLBackend::killTransform() { #else #endif } -#define LEGACY_TRANSFORM_PIPELINE 1 void GLBackend::updateTransform() { #ifdef LEGACY_TRANSFORM_PIPELINE @@ -496,16 +495,62 @@ void GLBackend::updateTransform() { glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera); glBindBuffer(GL_UNIFORM_BUFFER, 0); + CHECK_GL_ERROR(); } if (_transform._invalidView || _transform._invalidModel) { glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject); glBindBuffer(GL_UNIFORM_BUFFER, 0); + CHECK_GL_ERROR(); } - glBindBufferRange(GL_UNIFORM_BUFFER, 0, _transform._transformCameraBuffer, 0, sizeof(TransformCamera)); - glBindBufferRange(GL_UNIFORM_BUFFER, 1, _transform._transformObjectBuffer, 0, sizeof(TransformObject)); + glBindBufferRange(GL_UNIFORM_BUFFER, 6, _transform._transformObjectBuffer, 0, sizeof(TransformObject)); + glBindBufferRange(GL_UNIFORM_BUFFER, 7, _transform._transformCameraBuffer, 0, sizeof(TransformCamera)); + CHECK_GL_ERROR(); + + // Do it again for fixed pipeline unitl we can get rid of it + if (_transform._invalidProj) { + if (_transform._lastMode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + _transform._lastMode = GL_PROJECTION; + } + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); + + CHECK_GL_ERROR(); + } + + if (_transform._invalidModel || _transform._invalidView) { + if (!_transform._model.isIdentity()) { + if (_transform._lastMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + _transform._lastMode = GL_MODELVIEW; + } + Transform::Mat4 modelView; + if (!_transform._view.isIdentity()) { + Transform mvx; + Transform::inverseMult(mvx, _transform._view, _transform._model); + mvx.getMatrix(modelView); + } else { + _transform._model.getMatrix(modelView); + } + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); + } else { + if (!_transform._view.isIdentity()) { + if (_transform._lastMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + _transform._lastMode = GL_MODELVIEW; + } + Transform::Mat4 modelView; + _transform._view.getInverseMatrix(modelView); + glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); + } else { + // TODO: eventually do something about the matrix when neither view nor model is specified? + // glLoadIdentity(); + } + } + CHECK_GL_ERROR(); + } _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; #endif diff --git a/libraries/gpu/src/gpu/GLBackendShared.h b/libraries/gpu/src/gpu/GLBackendShared.h index f0f691f708..1853573522 100644 --- a/libraries/gpu/src/gpu/GLBackendShared.h +++ b/libraries/gpu/src/gpu/GLBackendShared.h @@ -49,7 +49,7 @@ static const GLenum _elementTypeToGLType[NUM_TYPES]= { GL_UNSIGNED_BYTE }; -//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -#define CHECK_GL_ERROR() +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() #endif diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 1ae422cd08..9666a4f258 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -18,10 +18,9 @@ struct TransformObject { }; struct TransformCamera { + mat4 _projection; mat4 _view; mat4 _viewInverse; - mat4 _projection; - }; vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { @@ -29,13 +28,20 @@ vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { } - -uniform transformStateBuffer { - TransformState xform; +uniform transformObjectBuffer { + TransformObject object; }; -TransformState getTransformState() { - return xform; +TransformObject getTransformObject() { + return object; +} + +uniform transformCameraBuffer { + TransformCamera camera; +}; +TransformCamera getTransformCamera() { + return camera; } <@elif GLPROFILE == MAC_GL@> uniform vec4 transformStateBuffer[2]; @@ -54,7 +60,6 @@ TransformState getMaterial() { return xform; } <@endif@> -!> <@endif@> diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 6657100e6f..7f2190d3f1 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -96,10 +96,11 @@ vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, ve Light light = getLight(); - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + //vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + + // float diffuseDot = dot(fragNormal, getLightDirection(light)); + float diffuseDot = dot(normal, getLightDirection(light)); - float diffuseDot = dot(fragNormal, getLightDirection(light)); - // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot const float PERPENDICULAR_THRESHOLD = -0.005; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 05ae810f6c..fb64a8410a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -223,6 +223,19 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo } #endif + loc = glGetUniformBlockIndex(program.programId(), "transformObjectBuffer"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, 6); + // locations.materialBufferUnit = 1; + } + + loc = glGetUniformBlockIndex(program.programId(), "transformCameraBuffer"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, 7); + // locations.materialBufferUnit = 1; + } + + program.link(); if (!program.isLinked()) { program.release(); } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index f3f52ad990..1191dbed39 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -11,14 +11,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -//include gpu/Transform.slh +<@include gpu/Transform.slh@> const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal varying vec4 normal; -/* +/* void main(void) { // transform and store the normal for interpolation normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); @@ -46,5 +46,12 @@ void main(void) { gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // use standard pipeline transform - gl_Position = ftransform(); + //gl_Position = ftransform(); + //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + // TransformObject obj = getTransformObject(); + TransformCamera cam = getTransformCamera(); + // gl_Position = transform(cam, obj, gl_Vertex); + + vec4 vPos = gl_ModelViewMatrix * gl_Vertex; + gl_Position = cam._projection * vPos; } From e99012efbb13e8e0132f8e808d46d63e946ce3f1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 10:33:12 -0800 Subject: [PATCH 006/341] updates to build guides to remove soxr --- BUILD.md | 3 +- BUILD_OSX.md | 2 +- BUILD_WIN.md | 14 --------- assignment-client/CMakeLists.txt | 2 +- cmake/externals/soxr/CMakeLists.txt | 21 ++++++++++++++ .../macros/AddDependencyExternalProject.cmake | 25 ---------------- .../AddDependencyExternalProjects.cmake | 29 +++++++++++++++++++ gvr-interface/CMakeLists.txt | 2 +- interface/CMakeLists.txt | 2 +- libraries/audio-client/CMakeLists.txt | 4 +-- libraries/audio/CMakeLists.txt | 2 +- libraries/avatars/CMakeLists.txt | 2 +- libraries/entities-renderer/CMakeLists.txt | 2 +- libraries/entities/CMakeLists.txt | 2 +- libraries/environment/CMakeLists.txt | 2 +- libraries/fbx/CMakeLists.txt | 2 +- libraries/metavoxels/CMakeLists.txt | 2 +- libraries/model/CMakeLists.txt | 2 +- libraries/octree/CMakeLists.txt | 2 +- libraries/physics/CMakeLists.txt | 2 +- libraries/render-utils/CMakeLists.txt | 2 +- libraries/script-engine/CMakeLists.txt | 2 +- libraries/shared/CMakeLists.txt | 2 +- tests/physics/CMakeLists.txt | 2 +- 24 files changed, 71 insertions(+), 61 deletions(-) create mode 100644 cmake/externals/soxr/CMakeLists.txt delete mode 100644 cmake/macros/AddDependencyExternalProject.cmake create mode 100644 cmake/macros/AddDependencyExternalProjects.cmake diff --git a/BUILD.md b/BUILD.md index f7dc22882a..6bf8df2510 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,9 +5,7 @@ * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 -* [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 -* [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version) #### CMake External Project Dependencies @@ -15,6 +13,7 @@ The following dependencies will be downloaded, built, linked and included automa * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [gverb](https://github.com/highfidelity/gverb) +* [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 ### OS Specific Build Guides * [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 2d5460d39d..563fd38c1c 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -4,7 +4,7 @@ Please read the [general build guide](BUILD.md) for information on dependencies [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. brew tap highfidelity/homebrew-formulas - brew install cmake openssl tbb libsoxr + brew install cmake openssl tbb brew install highfidelity/formulas/qt5 brew link qt5 --force diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 6f26e8c809..219192b360 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -155,20 +155,6 @@ You now have Bullet libraries compiled, now you need to put them in the right pl _Note that the INSTALL target should handle the copying of files into an install directory automatically, however, without modifications to Cmake, the install target didn't work right for me, please update this instructions if you get that working right - Leo <leo@highfidelity.io>_ -###Soxr - -Download the zip from the [soxr sourceforge page](http://sourceforge.net/projects/soxr/). - -We recommend you install it to %HIFI_LIB_DIR%\soxr. This will help our FindSoxr cmake module find what it needs. You can place it wherever you like on your machine if you specify SOXR_ROOT_DIR as an environment variable or a variable passed when cmake is run. - -Extract the soxr archive wherever you like. Then, inside the extracted folder, create a directory called `build`. From that build directory, the following commands will build and then install soxr to `%HIFI_LIB_DIR%`. - -``` -cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=%HIFI_LIB_DIR%/soxr -nmake -nmake install -``` - ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index b16314811b..5475b0fc14 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME assignment-client) setup_hifi_project(Core Gui Network Script Widgets) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt new file mode 100644 index 0000000000..bb6f510eb6 --- /dev/null +++ b/cmake/externals/soxr/CMakeLists.txt @@ -0,0 +1,21 @@ +set(EXTERNAL_NAME soxr) + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + PREFIX ${EXTERNAL_NAME} + URL http://pkgs.fedoraproject.org/repo/pkgs/soxr/soxr-0.1.1-Source.tar.xz/805651a245ead381c82fad6247af5968/soxr-0.1.1-Source.tar.xz + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS=N + LOG_DOWNLOAD ON +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING) + +if (WIN32) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.lib CACHE TYPE STRING) +else () + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.a CACHE TYPE STRING) +endif () \ No newline at end of file diff --git a/cmake/macros/AddDependencyExternalProject.cmake b/cmake/macros/AddDependencyExternalProject.cmake deleted file mode 100644 index ff0ced411e..0000000000 --- a/cmake/macros/AddDependencyExternalProject.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# -# SetupExternalProject.cmake -# cmake/macros -# -# Copyright 2015 High Fidelity, Inc. -# Created by Stephen Birarda on February 13, 2014 -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -macro(ADD_DEPENDENCY_EXTERNAL_PROJECT _PROJ_NAME) - - string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) - - if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) - if (NOT TARGET ${_PROJ_NAME}) - add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${CMAKE_BINARY_DIR}/externals/${_PROJ_NAME}) - endif () - - add_dependencies(${TARGET_NAME} ${_PROJ_NAME}) - - endif () - -endmacro() \ No newline at end of file diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake new file mode 100644 index 0000000000..e739e9994a --- /dev/null +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -0,0 +1,29 @@ +# +# SetupExternalProject.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 13, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS _PROJECTS) + + foreach(_PROJ_NAME ${_PROJECTS}) + + string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) + + if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) + if (NOT TARGET ${_PROJ_NAME}) + add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${CMAKE_BINARY_DIR}/externals/${_PROJ_NAME}) + endif () + + add_dependencies(${TARGET_NAME} ${_PROJ_NAME}) + + endif () + + endforeach() + +endmacro() \ No newline at end of file diff --git a/gvr-interface/CMakeLists.txt b/gvr-interface/CMakeLists.txt index de0b66165b..bdffb1fbd3 100644 --- a/gvr-interface/CMakeLists.txt +++ b/gvr-interface/CMakeLists.txt @@ -24,7 +24,7 @@ endif () include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 7d581284e5..c1e8b7d618 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -108,7 +108,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # set up the external glm library -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) diff --git a/libraries/audio-client/CMakeLists.txt b/libraries/audio-client/CMakeLists.txt index 1cd76cf2f5..7067e2ed81 100644 --- a/libraries/audio-client/CMakeLists.txt +++ b/libraries/audio-client/CMakeLists.txt @@ -8,8 +8,8 @@ link_hifi_libraries(audio) # append audio includes to our list of includes to bubble list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${HIFI_LIBRARY_DIR}/audio/src") -# have CMake grab Gverb from git and then set up linking and directory include -add_dependency_external_project(gverb) +# have CMake grab externals for us +add_dependency_external_projects(gverb soxr) find_package(Gverb REQUIRED) diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index 6ec35e00fc..b9dfc06cad 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME audio) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index bb4b8fdde0..ad06b4adfa 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME avatars) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index e706b07538..b807428203 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME entities-renderer) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Widgets OpenGL Network Script) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index d0c39cac84..5317f97b85 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME entities) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/environment/CMakeLists.txt b/libraries/environment/CMakeLists.txt index e5e7b80701..1c4daa1a6f 100644 --- a/libraries/environment/CMakeLists.txt +++ b/libraries/environment/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME environment) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index da6d471c72..b43e88bb3d 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME fbx) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/metavoxels/CMakeLists.txt b/libraries/metavoxels/CMakeLists.txt index 593ee800a7..f748971311 100644 --- a/libraries/metavoxels/CMakeLists.txt +++ b/libraries/metavoxels/CMakeLists.txt @@ -8,7 +8,7 @@ setup_hifi_library(Network Script Widgets) # link in the networking library link_hifi_libraries(shared networking) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index 0f71a25047..e3eeae7137 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME model) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index 3c7e8e7749..ad6f32f0ff 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME octree) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 7fc3f82496..775d5fcb0f 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME physics) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 054b30d7fb..d6e419fa49 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -8,7 +8,7 @@ qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Widgets OpenGL Network Script) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 4e13ddf513..99ac9da87c 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME script-engine) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Gui Network Script Widgets) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 54cd91deaf..ab4b853b6d 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -4,7 +4,7 @@ set(TARGET_NAME shared) # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) setup_hifi_library(Gui Network Script Widgets) -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index e20f323392..0f15f596c0 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME physics-tests) setup_hifi_project() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) From 2d1ad4977fbdd990fd9f2e51b1d1b5f8cbd60d73 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 10:46:19 -0800 Subject: [PATCH 007/341] handle soxr build for android --- cmake/externals/soxr/CMakeLists.txt | 10 +++++++++- cmake/macros/AddDependencyExternalProjects.cmake | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index bb6f510eb6..0c21780cbc 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -1,11 +1,17 @@ set(EXTERNAL_NAME soxr) +if (ANDROID) + set(PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19" "-DHAVE_WORDS_BIGENDIAN_EXITCODE=1") +else () + set(PLATFORM_CMAKE_ARGS "-DBUILD_SHARED_LIBS=0") +endif () + include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} PREFIX ${EXTERNAL_NAME} URL http://pkgs.fedoraproject.org/repo/pkgs/soxr/soxr-0.1.1-Source.tar.xz/805651a245ead381c82fad6247af5968/soxr-0.1.1-Source.tar.xz - CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS=N + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) @@ -16,6 +22,8 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING if (WIN32) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.lib CACHE TYPE STRING) +elseif (ANDROID) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE STRING) else () set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.a CACHE TYPE STRING) endif () \ No newline at end of file diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index e739e9994a..3ae59dd18e 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -9,9 +9,9 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS _PROJECTS) +macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) - foreach(_PROJ_NAME ${_PROJECTS}) + foreach(_PROJ_NAME ${ARGN}) string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) From f31199863408758a1011a5cb1e3474df438ad340 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 10:47:42 -0800 Subject: [PATCH 008/341] remove soxr from the android build dir --- BUILD_ANDROID.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md index 6ff3160775..9fe286744d 100644 --- a/BUILD_ANDROID.md +++ b/BUILD_ANDROID.md @@ -88,22 +88,6 @@ mkdir lib cp `find . -name "*.so"` lib/ ``` -####Soxr - -Download the [Soxr source](http://sourceforge.net/projects/soxr/) and extract the tarball inside your `ANDROID_LIB_DIR`. Rename the extracted folder to `soxr`. - -From the soxr directory, use cmake, along with the `android.toolchain.cmake` file (included in this repository under cmake/android) to cross-compile soxr for Android. Note that you will need ANDROID_NDK set in your environment before using the toolchain file. - -The full set of commands to build soxr for Android is shown below. It is a long command, make sure you copy the entire command (up to `-DBUILD_TESTS=0`). - -``` -cmake -DCMAKE_TOOLCHAIN_FILE=$FULL_PATH_TO_TOOLCHAIN -DCMAKE_INSTALL_PREFIX=. -DHAVE_WORDS_BIGENDIAN_EXITCODE=1 -DBUILD_TESTS=0 -make -make install -``` - -This will create the `lib` and `include` folders inside `ANDROID_LIB_DIR/soxr` that FindSoxr will look for. - ####Oculus Mobile SDK The Oculus Mobile SDK is optional, for Gear VR support. It is not required to compile gvr-interface. From c82f5b7c0dbe507d8f4701e9dcb10f73a6d0f17d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 10:50:43 -0800 Subject: [PATCH 009/341] use hifi-public as host for libsoxr --- cmake/externals/soxr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 0c21780cbc..ed173f4402 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -10,7 +10,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} PREFIX ${EXTERNAL_NAME} - URL http://pkgs.fedoraproject.org/repo/pkgs/soxr/soxr-0.1.1-Source.tar.xz/805651a245ead381c82fad6247af5968/soxr-0.1.1-Source.tar.xz + URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.tar.xz CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) From c53465e55019bf4db6dae7ed2c6a9ad3169c5b5c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 10:52:31 -0800 Subject: [PATCH 010/341] fix archive type for soxr external project --- cmake/externals/soxr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index ed173f4402..e65b171cfb 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -10,7 +10,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} PREFIX ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.tar.xz + URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.tar.gz CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) From a5bd9be51075a7860d24ba687caf7822e072e56d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 11:00:23 -0800 Subject: [PATCH 011/341] put externals in build-externals to avoid clean build removal --- CMakeLists.txt | 7 +++++++ cmake/macros/AddDependencyExternalProjects.cmake | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6eb3b935e..10d7998454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,13 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/mo set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros") set(EXTERNAL_PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/externals") +set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") +if (ANDROID) + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR}") +else () + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR}") +endif () + file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake") foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS}) include(${CUSTOM_MACRO}) diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index 3ae59dd18e..c039d09987 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -16,8 +16,8 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) - if (NOT TARGET ${_PROJ_NAME}) - add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${CMAKE_BINARY_DIR}/externals/${_PROJ_NAME}) + if (NOT TARGET ${_PROJ_NAME}) + add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME}) endif () add_dependencies(${TARGET_NAME} ${_PROJ_NAME}) From 013bb0433cf5f4d22127c8924077f5a47496ff0b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 11:01:00 -0800 Subject: [PATCH 012/341] clarify build guide for sep externals build dir --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 6bf8df2510..e4bf1f2718 100644 --- a/BUILD.md +++ b/BUILD.md @@ -9,7 +9,7 @@ #### CMake External Project Dependencies -The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. +The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [gverb](https://github.com/highfidelity/gverb) From 19cd24fb059f92962b0c15004d0f731ae7d954fa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 11:02:20 -0800 Subject: [PATCH 013/341] more clarification to BUILD guide for externals --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index e4bf1f2718..9501f7ad0a 100644 --- a/BUILD.md +++ b/BUILD.md @@ -9,7 +9,7 @@ #### CMake External Project Dependencies -The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. +The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-externals`. Should you want to force a re-download and re-compile of all externals, just remove the `build-externals` folder. * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [gverb](https://github.com/highfidelity/gverb) From c7befe8018dad8e2f8349a4a746430ddba3235b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 11:56:30 -0800 Subject: [PATCH 014/341] build the dynamic soxr to reduce manual linking --- cmake/externals/soxr/CMakeLists.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index e65b171cfb..1c74a6904a 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -2,8 +2,6 @@ set(EXTERNAL_NAME soxr) if (ANDROID) set(PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19" "-DHAVE_WORDS_BIGENDIAN_EXITCODE=1") -else () - set(PLATFORM_CMAKE_ARGS "-DBUILD_SHARED_LIBS=0") endif () include(ExternalProject) @@ -22,8 +20,8 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING if (WIN32) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.lib CACHE TYPE STRING) -elseif (ANDROID) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE STRING) +elseif (APPLE) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE STRING) else () - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.a CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE STRING) endif () \ No newline at end of file From 26b4340417c5e0c11cd750fc1c1d6f65361b61aa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 12:07:57 -0800 Subject: [PATCH 015/341] change soxr source to friendly zip --- cmake/externals/soxr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 1c74a6904a..bcb06e4e25 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -8,7 +8,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} PREFIX ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.tar.gz + URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.zip CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) From 66756308a45f58c29274daf85839dcba42d760fa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 12:21:19 -0800 Subject: [PATCH 016/341] force soxr to be shared lib, use new zip --- cmake/externals/soxr/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index bcb06e4e25..2c967d5761 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -8,8 +8,8 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} PREFIX ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1-Source.zip - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= + URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1.zip + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_SHARED_LIBS=1 -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) From 016ef2b2430f3a5d54b925a307209ba7ec738408 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 12:36:26 -0800 Subject: [PATCH 017/341] fix name of soxr lib for windows --- cmake/externals/soxr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 2c967d5761..03b49bd7d1 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -19,7 +19,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING) if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.lib CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE STRING) elseif (APPLE) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE STRING) else () From bc899eaa581da85157ff1601c6499485fe52f653 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 13:17:23 -0800 Subject: [PATCH 018/341] add fixup_bundle step for WIN32 interface --- CMakeLists.txt | 5 +++-- cmake/macros/AddDependencyExternalProjects.cmake | 2 +- cmake/scripts/FixupBundlePostBuild.cmake | 13 +++++++++++++ interface/CMakeLists.txt | 9 +++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 cmake/scripts/FixupBundlePostBuild.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 10d7998454..6ebf5ea5e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,8 +103,9 @@ set(HIFI_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries") # setup for find modules set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") -set(MACRO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros") -set(EXTERNAL_PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/externals") +set(HIFI_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(MACRO_DIR "${HIFI_CMAKE_DIR}/macros") +set(EXTERNAL_PROJECT_DIR "${HIFI_CMAKE_DIR}/externals") set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") if (ANDROID) diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index c039d09987..72dbad6639 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -1,5 +1,5 @@ # -# SetupExternalProject.cmake +# AddDependencyExternalProjects.cmake # cmake/macros # # Copyright 2015 High Fidelity, Inc. diff --git a/cmake/scripts/FixupBundlePostBuild.cmake b/cmake/scripts/FixupBundlePostBuild.cmake new file mode 100644 index 0000000000..7a74089bfa --- /dev/null +++ b/cmake/scripts/FixupBundlePostBuild.cmake @@ -0,0 +1,13 @@ +# +# FixupBundlePostBuild.cmake.in +# cmake/templates +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 13, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +include(BundleUtilities) +fixup_bundle("${BUNDLE_EXECUTABLE}" "" "") \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c1e8b7d618..459a47a1ce 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -239,5 +239,14 @@ else (APPLE) endif() endif (APPLE) +if (WIN32) + # add a post-build command to copy DLLs beside the interface executable + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake + ) +endif () + # link any dependencies bubbled up from our linked dependencies include_dependency_includes() From 250b25154cfe5b81d5979138e3d6070de8f0da0f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 13:41:37 -0800 Subject: [PATCH 019/341] test for recursive dll dir search --- cmake/scripts/FixupBundlePostBuild.cmake | 2 +- interface/CMakeLists.txt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/scripts/FixupBundlePostBuild.cmake b/cmake/scripts/FixupBundlePostBuild.cmake index 7a74089bfa..e41d5cbc45 100644 --- a/cmake/scripts/FixupBundlePostBuild.cmake +++ b/cmake/scripts/FixupBundlePostBuild.cmake @@ -10,4 +10,4 @@ # include(BundleUtilities) -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "") \ No newline at end of file +fixup_bundle("${BUNDLE_EXECUTABLE}" "" "${LIB_SEARCH_DIRS}") \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 459a47a1ce..746f08e0d6 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -240,11 +240,15 @@ else (APPLE) endif (APPLE) if (WIN32) + list(APPEND LIB_SEARCH_DIRS ${EXTERNALS_BINARY_DIR}) # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake + COMMAND ${CMAKE_COMMAND} + -DBUNDLE_EXECUTABLE=$ + -DLIB_SEARCH_DIRS=${LIB_SEARCH_DIRS} + -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake ) endif () From 767601de4fdb0e156cb669e6f60749997dac7474 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:09:26 -0800 Subject: [PATCH 020/341] use a cache variable to pass around lib paths --- cmake/macros/AddPathToLibPaths.cmake | 16 ++++++++++++++++ cmake/modules/FindSoxr.cmake | 5 +++++ cmake/scripts/FixupBundlePostBuild.cmake | 2 +- interface/CMakeLists.txt | 3 +-- 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 cmake/macros/AddPathToLibPaths.cmake diff --git a/cmake/macros/AddPathToLibPaths.cmake b/cmake/macros/AddPathToLibPaths.cmake new file mode 100644 index 0000000000..397680a237 --- /dev/null +++ b/cmake/macros/AddPathToLibPaths.cmake @@ -0,0 +1,16 @@ +# +# AddPathToLibPaths.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 13, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(ADD_PATH_TO_LIB_PATHS _PATH) + set(TEMP_LIB_PATHS ${LIB_PATHS}) + list(APPEND TEMP_LIB_PATHS ${_PATH}) + set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) +endmacro() \ No newline at end of file diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index 367022e9ec..cfe0428ebc 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -24,6 +24,11 @@ hifi_library_search_hints("soxr") find_path(SOXR_INCLUDE_DIRS soxr.h PATH_SUFFIXES include HINTS ${SOXR_SEARCH_DIRS}) find_library(SOXR_LIBRARIES NAMES soxr PATH_SUFFIXES lib HINTS ${SOXR_SEARCH_DIRS}) +if (NOT DEFINED SOXR_LIB_PATH) + get_filename_component(SOXR_LIB_PATH ${SOXR_LIBRARIES} DIRECTORY CACHE) + add_path_to_lib_paths(${SOXR_LIB_PATH}) +endif () + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SOXR DEFAULT_MSG SOXR_INCLUDE_DIRS SOXR_LIBRARIES) diff --git a/cmake/scripts/FixupBundlePostBuild.cmake b/cmake/scripts/FixupBundlePostBuild.cmake index e41d5cbc45..826033d791 100644 --- a/cmake/scripts/FixupBundlePostBuild.cmake +++ b/cmake/scripts/FixupBundlePostBuild.cmake @@ -10,4 +10,4 @@ # include(BundleUtilities) -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "${LIB_SEARCH_DIRS}") \ No newline at end of file +fixup_bundle("${BUNDLE_EXECUTABLE}" "" "${LIB_PATHS}") \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 746f08e0d6..fd13aa7092 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -240,14 +240,13 @@ else (APPLE) endif (APPLE) if (WIN32) - list(APPEND LIB_SEARCH_DIRS ${EXTERNALS_BINARY_DIR}) # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ - -DLIB_SEARCH_DIRS=${LIB_SEARCH_DIRS} + -DLIB_PATHS=${LIB_PATHS} -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake ) endif () From 07e3064cc44791aae65fcea48a5fd1647df2d322 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:18:10 -0800 Subject: [PATCH 021/341] add an output message to verify LIB_PATHS --- cmake/scripts/FixupBundlePostBuild.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/scripts/FixupBundlePostBuild.cmake b/cmake/scripts/FixupBundlePostBuild.cmake index 826033d791..c6d0b42aea 100644 --- a/cmake/scripts/FixupBundlePostBuild.cmake +++ b/cmake/scripts/FixupBundlePostBuild.cmake @@ -10,4 +10,5 @@ # include(BundleUtilities) +message(STATUS "LIB_PATHS for fixup_bundle bundle ${BUNDLE_EXECUTABLE} are ${LIB_PATHS}") fixup_bundle("${BUNDLE_EXECUTABLE}" "" "${LIB_PATHS}") \ No newline at end of file From 801ab0e2b99efe95bff60185360a64169bfaefda Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:30:20 -0800 Subject: [PATCH 022/341] windows unhelpfully puts soxr dll in bin, not lib --- cmake/externals/soxr/CMakeLists.txt | 1 + cmake/modules/FindSoxr.cmake | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 03b49bd7d1..fcd28d4db5 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -20,6 +20,7 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING if (WIN32) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE STRING) elseif (APPLE) set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE STRING) else () diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index cfe0428ebc..b980b4ea1f 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -24,10 +24,10 @@ hifi_library_search_hints("soxr") find_path(SOXR_INCLUDE_DIRS soxr.h PATH_SUFFIXES include HINTS ${SOXR_SEARCH_DIRS}) find_library(SOXR_LIBRARIES NAMES soxr PATH_SUFFIXES lib HINTS ${SOXR_SEARCH_DIRS}) -if (NOT DEFINED SOXR_LIB_PATH) - get_filename_component(SOXR_LIB_PATH ${SOXR_LIBRARIES} DIRECTORY CACHE) - add_path_to_lib_paths(${SOXR_LIB_PATH}) -endif () +if (WIN32) + find_path(SOXR_DLL_PATH soxr.dll PATH_SUFFIXES bin HINTS ${SOXR_SEARCH_DIRS}) + add_path_to_lib_paths(${SOXR_DLL_PATH}) +endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SOXR DEFAULT_MSG SOXR_INCLUDE_DIRS SOXR_LIBRARIES) From 97fa1412e27e9417fd546ed88f6730618da166be Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:45:26 -0800 Subject: [PATCH 023/341] copy dlls beside windows executable for all executables --- cmake/macros/AddPathToLibPaths.cmake | 2 +- .../CopyDllsBesideWindowsExecutable.cmake | 24 +++++++++++++++++++ cmake/macros/SetupHifiProject.cmake | 2 ++ interface/CMakeLists.txt | 12 +--------- 4 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 cmake/macros/CopyDllsBesideWindowsExecutable.cmake diff --git a/cmake/macros/AddPathToLibPaths.cmake b/cmake/macros/AddPathToLibPaths.cmake index 397680a237..f1f7c46a1c 100644 --- a/cmake/macros/AddPathToLibPaths.cmake +++ b/cmake/macros/AddPathToLibPaths.cmake @@ -3,7 +3,7 @@ # cmake/macros # # Copyright 2015 High Fidelity, Inc. -# Created by Stephen Birarda on February 13, 2014 +# Created by Stephen Birarda on February 17, 2014 # # Distributed under the Apache License, Version 2.0. # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake new file mode 100644 index 0000000000..b0379e4764 --- /dev/null +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -0,0 +1,24 @@ +# +# CopyDllsBesideWindowsExecutable.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 17, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) + if (WIN32) + # add a post-build command to copy DLLs beside the interface executable + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} + -DBUNDLE_EXECUTABLE=$ + -DLIB_PATHS=${LIB_PATHS} + -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake + ) + endif () +endmacro() \ No newline at end of file diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 3f9787faa1..8b3bc43101 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -34,4 +34,6 @@ macro(SETUP_HIFI_PROJECT) foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) endforeach() + + copy_dlls_beside_windows_executable() endmacro() \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index fd13aa7092..200d7a72e6 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -239,17 +239,7 @@ else (APPLE) endif() endif (APPLE) -if (WIN32) - # add a post-build command to copy DLLs beside the interface executable - add_custom_command( - TARGET ${TARGET_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} - -DBUNDLE_EXECUTABLE=$ - -DLIB_PATHS=${LIB_PATHS} - -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake - ) -endif () +copy_dlls_beside_windows_executable() # link any dependencies bubbled up from our linked dependencies include_dependency_includes() From 18f293b59b727147acecd7fb1b6841b7c12bc9a5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:53:22 -0800 Subject: [PATCH 024/341] disable bundle fixup on Release build --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index b0379e4764..e0558f7a44 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -10,7 +10,7 @@ # macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) - if (WIN32) + if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} From 6fc74eb83003da6c8716b2fd55a894a5dc18336b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 14:56:34 -0800 Subject: [PATCH 025/341] fix cmake build type check for interface icon --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 200d7a72e6..31d8f3df45 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -78,7 +78,7 @@ if (APPLE) set(MACOSX_BUNDLE_BUNDLE_NAME Interface) set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.Interface) - if (${CMAKE_BUILD_TYPE} MATCHES "RELEASE") + if (CMAKE_BUILD_TYPE STREQUAL "Release") set(ICON_FILENAME "interface.icns") else () set(ICON_FILENAME "interface-beta.icns") From 34cf7bb1f1c0d258d8d3d95cfc6ed9f400bff889 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:04:57 -0800 Subject: [PATCH 026/341] add leap motion dll path for fixup_bundle --- cmake/modules/FindLeapMotion.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index cb49ceb597..8813956696 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -20,6 +20,9 @@ find_path(LEAPMOTION_INCLUDE_DIRS Leap.h PATH_SUFFIXES include HINTS ${LEAPMOTIO if (WIN32) find_library(LEAPMOTION_LIBRARY_DEBUG Leapd PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) + + find_path(LEAPMOTION_DLL_PATH Leapd.dll PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) + add_path_to_lib_paths(${LEAPMOTION_DLL_PATH}) elseif (APPLE) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib HINTS ${LEAPMOTION_SEARCH_DIRS}) endif () From b682cd03f3f573a3bc91ad38f0412a61556efc4d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:08:30 -0800 Subject: [PATCH 027/341] cleanup leap dll path for win --- cmake/modules/FindLeapMotion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index 8813956696..baed00ef50 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -21,7 +21,7 @@ if (WIN32) find_library(LEAPMOTION_LIBRARY_DEBUG Leapd PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) - find_path(LEAPMOTION_DLL_PATH Leapd.dll PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) + get_filename_component(LEAPMOTION_DLL_PATH ${LEAPMOTION_LIBRARY_RELEASE} DIRECTORY CACHE) add_path_to_lib_paths(${LEAPMOTION_DLL_PATH}) elseif (APPLE) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib HINTS ${LEAPMOTION_SEARCH_DIRS}) From c233dc7b57136c05b6f978e2711f5d4c1c9cbbad Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:08:41 -0800 Subject: [PATCH 028/341] get sdl2 dll path for win32 fixup_bundle --- cmake/modules/FindSDL2.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index 6ef9ffa52a..25d61899a1 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -254,3 +254,8 @@ ENDIF(SDL2_LIBRARY_TEMP) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) + +if (WIN32) + get_filename_component(SDL2_DLL_PATH ${SDL2_LIBRARY} DIRECTORY CACHE) + add_path_to_lib_paths(${SDL2_DLL_PATH}) +endif () From e7b4746c160efca7ab367ab8dc4cba90e00f393d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:12:13 -0800 Subject: [PATCH 029/341] add TBB dll path to lib paths --- cmake/modules/FindTBB.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index 03ac99b73c..596cd3ccca 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -56,6 +56,9 @@ elseif (WIN32) endif() set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/vc12") + + find_path(TBB_DLL_PATH tbb_debug.dll PATH_SUFFIXES "bin/${_TBB_ARCH_DIR}/vc12" HINTS ${TBB_SEARCH_DIRS}) + add_path_to_lib_paths(${TBB_DLL_PATH}) elseif (ANDROID) set(_TBB_DEFAULT_INSTALL_DIR "/tbb") set(_TBB_LIB_NAME "tbb") From b727c910d11f004391d0184ac0c76b5de0015967 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:19:17 -0800 Subject: [PATCH 030/341] handle multiple dll paths, add sixense --- cmake/macros/AddPathToLibPaths.cmake | 10 ++++++---- cmake/modules/FindLeapMotion.cmake | 2 +- cmake/modules/FindSDL2.cmake | 2 +- cmake/modules/FindSixense.cmake | 14 +++++++++++++- cmake/modules/FindSoxr.cmake | 2 +- cmake/modules/FindTBB.cmake | 13 +++++++++++-- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/cmake/macros/AddPathToLibPaths.cmake b/cmake/macros/AddPathToLibPaths.cmake index f1f7c46a1c..abdc65c9be 100644 --- a/cmake/macros/AddPathToLibPaths.cmake +++ b/cmake/macros/AddPathToLibPaths.cmake @@ -9,8 +9,10 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -macro(ADD_PATH_TO_LIB_PATHS _PATH) - set(TEMP_LIB_PATHS ${LIB_PATHS}) - list(APPEND TEMP_LIB_PATHS ${_PATH}) - set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) +macro(ADD_PATHS_TO_LIB_PATHS) + foreach(_PATH in ${ARGN}) + set(TEMP_LIB_PATHS ${LIB_PATHS}) + list(APPEND TEMP_LIB_PATHS ${_PATH}) + set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) + endforeach() endmacro() \ No newline at end of file diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index baed00ef50..6ccba0ea66 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -22,7 +22,7 @@ if (WIN32) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) get_filename_component(LEAPMOTION_DLL_PATH ${LEAPMOTION_LIBRARY_RELEASE} DIRECTORY CACHE) - add_path_to_lib_paths(${LEAPMOTION_DLL_PATH}) + add_paths_to_lib_paths(${LEAPMOTION_DLL_PATH}) elseif (APPLE) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib HINTS ${LEAPMOTION_SEARCH_DIRS}) endif () diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index 25d61899a1..d9fa3c3c37 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -257,5 +257,5 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_D if (WIN32) get_filename_component(SDL2_DLL_PATH ${SDL2_LIBRARY} DIRECTORY CACHE) - add_path_to_lib_paths(${SDL2_DLL_PATH}) + add_paths_to_lib_paths(${SDL2_DLL_PATH} ${SDL2_RELEASE_PATH}) endif () diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index f772c42e41..7e6581ffd0 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -32,14 +32,26 @@ elseif (UNIX) elseif (WIN32) find_library(SIXENSE_LIBRARY_RELEASE lib/win32/release_dll/sixense.lib HINTS ${SIXENSE_SEARCH_DIRS}) find_library(SIXENSE_LIBRARY_DEBUG lib/win32/debug_dll/sixensed.lib HINTS ${SIXENSE_SEARCH_DIRS}) + + find_path(SIXENSE_DEBUG_DLL_PATH sixensed.dll PATH_SUFFIXES bin/win32/debug_dll HINTS ${SIXENSE_SEARCH_DIRS}) + find_path(SIXENSE_RELEASE_DLL_PATH sixense.dll PATH_SUFFIXES bin/win32/release_dll HINTS ${SIXENSE_SEARCH_DIRS}) endif () include(SelectLibraryConfigurations) select_library_configurations(SIXENSE) +set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) +if (WIN32) + list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH) +endif () + set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}") include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) +find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_REQUIREMENTS) + +if (WIN32) + add_paths_to_lib_paths(${SIXSENSE_DEBUG_DLL_PATH}) +endif () mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS) diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index b980b4ea1f..fba6158f14 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -26,7 +26,7 @@ find_library(SOXR_LIBRARIES NAMES soxr PATH_SUFFIXES lib HINTS ${SOXR_SEARCH_DIR if (WIN32) find_path(SOXR_DLL_PATH soxr.dll PATH_SUFFIXES bin HINTS ${SOXR_SEARCH_DIRS}) - add_path_to_lib_paths(${SOXR_DLL_PATH}) + add_paths_to_lib_paths(${SOXR_DLL_PATH}) endif() include(FindPackageHandleStandardArgs) diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index 596cd3ccca..c18d619612 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -58,7 +58,7 @@ elseif (WIN32) set(_TBB_LIB_DIR "lib/${_TBB_ARCH_DIR}/vc12") find_path(TBB_DLL_PATH tbb_debug.dll PATH_SUFFIXES "bin/${_TBB_ARCH_DIR}/vc12" HINTS ${TBB_SEARCH_DIRS}) - add_path_to_lib_paths(${TBB_DLL_PATH}) + elseif (ANDROID) set(_TBB_DEFAULT_INSTALL_DIR "/tbb") set(_TBB_LIB_NAME "tbb") @@ -80,6 +80,15 @@ include(FindPackageHandleStandardArgs) select_library_configurations(TBB) select_library_configurations(TBB_MALLOC) -find_package_handle_standard_args(TBB DEFAULT_MSG TBB_LIBRARY TBB_MALLOC_LIBRARY TBB_INCLUDE_DIRS) +set(TBB_REQUIREMENTS TBB_LIBRARY TBB_MALLOC_LIBRARY TBB_INCLUDE_DIRS) +if (WIN32) + list(APPEND TBB_REQUIREMENTS TBB_DLL_PATH) +endif () + +find_package_handle_standard_args(TBB DEFAULT_MSG TBB_REQUIREMENTS) + +if (WIN32) + add_paths_to_lib_paths(${TBB_DLL_PATH}) +endif () set(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY}) From bc0ddd8c1cb6d69dbb2a6d6eb94c4d77e9565c6b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:19:57 -0800 Subject: [PATCH 031/341] rename AddPathToLibPaths file so it is findable --- .../{AddPathToLibPaths.cmake => AddPathsToLibPaths.cmake} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename cmake/macros/{AddPathToLibPaths.cmake => AddPathsToLibPaths.cmake} (94%) diff --git a/cmake/macros/AddPathToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake similarity index 94% rename from cmake/macros/AddPathToLibPaths.cmake rename to cmake/macros/AddPathsToLibPaths.cmake index abdc65c9be..93e3287b5a 100644 --- a/cmake/macros/AddPathToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -1,5 +1,5 @@ # -# AddPathToLibPaths.cmake +# AddPathsToLibPaths.cmake # cmake/macros # # Copyright 2015 High Fidelity, Inc. From e582709185a192fb41853e58977befceb022578e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:22:22 -0800 Subject: [PATCH 032/341] ensure leapmotion dll path is found --- cmake/modules/FindLeapMotion.cmake | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index 6ccba0ea66..6b9d4355f7 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -21,8 +21,7 @@ if (WIN32) find_library(LEAPMOTION_LIBRARY_DEBUG Leapd PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) - get_filename_component(LEAPMOTION_DLL_PATH ${LEAPMOTION_LIBRARY_RELEASE} DIRECTORY CACHE) - add_paths_to_lib_paths(${LEAPMOTION_DLL_PATH}) + find_path(LEAPMOTION_DLL_PATH Leap.dll PATH_SUFFIXES lib/x86 HINTS ${LEAPMOTION_SEARCH_DIRS}) elseif (APPLE) find_library(LEAPMOTION_LIBRARY_RELEASE Leap PATH_SUFFIXES lib HINTS ${LEAPMOTION_SEARCH_DIRS}) endif () @@ -32,7 +31,16 @@ select_library_configurations(LEAPMOTION) set(LEAPMOTION_LIBRARIES "${LEAPMOTION_LIBRARY}") +set(LEAPMOTION_REQUIREMENTS LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES) +if (WIN32) + list(APPEND LEAPMOTION_REQUIREMENTS LEAPMOTION_DLL_PATH) +endif () + include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LeapMotion DEFAULT_MSG LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES) +find_package_handle_standard_args(LeapMotion DEFAULT_MSG LEAPMOTION_REQUIREMENTS) + +if (WIN32) + add_paths_to_lib_paths(${LEAPMOTION_DLL_PATH}) +endif () mark_as_advanced(LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES LEAPMOTION_SEARCH_DIRS) From ecbbb481d01329be9c9d684ebe508ad56d3d05b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:27:12 -0800 Subject: [PATCH 033/341] ensure dll path is found for sdl2 --- cmake/modules/FindSDL2.cmake | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index d9fa3c3c37..b42cacb16a 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -138,6 +138,10 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/csw /opt ) + + if (WIN32) + find_path(SDL2_DLL_PATH SDL2.dll PATH_SUFFIXES lib/x64 HINTS ${SDL2_SEARCH_DIRS}) + endif () # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) FIND_LIBRARY(SDL2_LIBRARY_TEMP SDL2 @@ -153,6 +157,10 @@ ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/csw /opt ) + + if (WIN32) + find_path(SDL2_DLL_PATH SDL2.dll PATH_SUFFIXES lib/x86 HINTS ${SDL2_SEARCH_DIRS}) + endif () ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) IF(NOT SDL2_BUILDING_LIBRARY) @@ -253,9 +261,13 @@ ENDIF(SDL2_LIBRARY_TEMP) INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) +set(SDL2_REQUIREMENTS SDL2_LIBRARY SDL2_INCLUDE_DIR) +if (WIN32) + list(APPEND SDL2_REQUIREMENTS SDL2_DLL_PATH) +endif () + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_REQUIREMENTS) if (WIN32) - get_filename_component(SDL2_DLL_PATH ${SDL2_LIBRARY} DIRECTORY CACHE) - add_paths_to_lib_paths(${SDL2_DLL_PATH} ${SDL2_RELEASE_PATH}) + add_paths_to_lib_paths(${SDL2_DLL_PATH}) endif () From 10cdbc4fa08ecada6991911aaf930876830b10c0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:33:26 -0800 Subject: [PATCH 034/341] fix dynamic requirements in find modules --- cmake/modules/FindLeapMotion.cmake | 4 ++-- cmake/modules/FindSDL2.cmake | 2 +- cmake/modules/FindSixense.cmake | 2 +- cmake/modules/FindTBB.cmake | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index 6b9d4355f7..6f177cd3d7 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -29,7 +29,7 @@ endif () include(SelectLibraryConfigurations) select_library_configurations(LEAPMOTION) -set(LEAPMOTION_LIBRARIES "${LEAPMOTION_LIBRARY}") +set(LEAPMOTION_LIBRARIES ${LEAPMOTION_LIBRARY}) set(LEAPMOTION_REQUIREMENTS LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES) if (WIN32) @@ -37,7 +37,7 @@ if (WIN32) endif () include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LeapMotion DEFAULT_MSG LEAPMOTION_REQUIREMENTS) +find_package_handle_standard_args(LeapMotion DEFAULT_MSG ${LEAPMOTION_REQUIREMENTS}) if (WIN32) add_paths_to_lib_paths(${LEAPMOTION_DLL_PATH}) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index b42cacb16a..55dae82f82 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -266,7 +266,7 @@ if (WIN32) list(APPEND SDL2_REQUIREMENTS SDL2_DLL_PATH) endif () -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_REQUIREMENTS) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS ${SDL2_REQUIREMENTS}) if (WIN32) add_paths_to_lib_paths(${SDL2_DLL_PATH}) diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 7e6581ffd0..11ca704407 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -48,7 +48,7 @@ endif () set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}") include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Sixense DEFAULT_MSG SIXENSE_REQUIREMENTS) +find_package_handle_standard_args(Sixense DEFAULT_MSG ${SIXENSE_REQUIREMENTS}) if (WIN32) add_paths_to_lib_paths(${SIXSENSE_DEBUG_DLL_PATH}) diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index c18d619612..9781154c1a 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -85,7 +85,7 @@ if (WIN32) list(APPEND TBB_REQUIREMENTS TBB_DLL_PATH) endif () -find_package_handle_standard_args(TBB DEFAULT_MSG TBB_REQUIREMENTS) +find_package_handle_standard_args(TBB DEFAULT_MSG ${TBB_REQUIREMENTS}) if (WIN32) add_paths_to_lib_paths(${TBB_DLL_PATH}) From d0d4eaec868d1691cc897596764269accec1991a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:44:03 -0800 Subject: [PATCH 035/341] fix AddPathsToLibPaths foreach, soxr requirements --- cmake/macros/AddPathsToLibPaths.cmake | 2 +- cmake/modules/FindSoxr.cmake | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index 93e3287b5a..e88fd06f95 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -10,7 +10,7 @@ # macro(ADD_PATHS_TO_LIB_PATHS) - foreach(_PATH in ${ARGN}) + foreach(_PATH ${ARGN}) set(TEMP_LIB_PATHS ${LIB_PATHS}) list(APPEND TEMP_LIB_PATHS ${_PATH}) set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index fba6158f14..b36c9465b7 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -25,11 +25,19 @@ find_path(SOXR_INCLUDE_DIRS soxr.h PATH_SUFFIXES include HINTS ${SOXR_SEARCH_DIR find_library(SOXR_LIBRARIES NAMES soxr PATH_SUFFIXES lib HINTS ${SOXR_SEARCH_DIRS}) if (WIN32) - find_path(SOXR_DLL_PATH soxr.dll PATH_SUFFIXES bin HINTS ${SOXR_SEARCH_DIRS}) - add_paths_to_lib_paths(${SOXR_DLL_PATH}) + find_path(SOXR_DLL_PATH soxr.dll PATH_SUFFIXES bin HINTS ${SOXR_SEARCH_DIRS}) endif() +set(SOXR_REQUIREMENTS SOXR_INCLUDE_DIRS SOXR_LIBRARIES) +if (WIN32) + list(APPEND SOXR_REQUIREMENTS SOXR_DLL_PATH) +endif () + include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SOXR DEFAULT_MSG SOXR_INCLUDE_DIRS SOXR_LIBRARIES) +find_package_handle_standard_args(SOXR DEFAULT_MSG ${SOXR_REQUIREMENTS}) + +if (WIN32) + add_paths_to_lib_paths(${SOXR_DLL_PATH}) +endif () mark_as_advanced(SOXR_INCLUDE_DIRS SOXR_LIBRARIES SOXR_SEARCH_DIRS) \ No newline at end of file From c3b71196c7b3541c4daf63b866ce569af5816f92 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 15:58:08 -0800 Subject: [PATCH 036/341] add debug to catch LIB_PATHS override --- cmake/macros/AddPathsToLibPaths.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index e88fd06f95..bc066304bc 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -10,9 +10,14 @@ # macro(ADD_PATHS_TO_LIB_PATHS) + message(STATUS "ADD_PATHS called with ${ARGN}") foreach(_PATH ${ARGN}) + message(STATUS "ADDING ${_PATH}") + message(STATUS "CURRENT LIB_PATHS is ${LIB_PATHS}") set(TEMP_LIB_PATHS ${LIB_PATHS}) list(APPEND TEMP_LIB_PATHS ${_PATH}) + set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) + message(STATUS "LIB PATHS IS NOW ${LIB_PATHS}") endforeach() endmacro() \ No newline at end of file From b14110f596f78d0c4539c87b0b5906d73e71e519 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:01:41 -0800 Subject: [PATCH 037/341] ensure fixup bundle post build step called with list --- cmake/macros/AddPathsToLibPaths.cmake | 4 ---- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index bc066304bc..d86d054615 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -10,14 +10,10 @@ # macro(ADD_PATHS_TO_LIB_PATHS) - message(STATUS "ADD_PATHS called with ${ARGN}") foreach(_PATH ${ARGN}) - message(STATUS "ADDING ${_PATH}") - message(STATUS "CURRENT LIB_PATHS is ${LIB_PATHS}") set(TEMP_LIB_PATHS ${LIB_PATHS}) list(APPEND TEMP_LIB_PATHS ${_PATH}) set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) - message(STATUS "LIB PATHS IS NOW ${LIB_PATHS}") endforeach() endmacro() \ No newline at end of file diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index e0558f7a44..d6a8147ed4 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -17,7 +17,7 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) POST_BUILD COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ - -DLIB_PATHS=${LIB_PATHS} + -DLIB_PATHS="${LIB_PATHS}" -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake ) endif () From 1a0a4d0e208b8705dd1167063807dac68c4587e8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:05:32 -0800 Subject: [PATCH 038/341] use seperate_arguments to allow cmake path escape --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index d6a8147ed4..2d42e3eff4 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -11,13 +11,14 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") + seperate_arguments(LIB_PATHS_ARG WINDOWS_COMMAND ${LIB_PATHS}) # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ - -DLIB_PATHS="${LIB_PATHS}" + -DLIB_PATHS=${LIB_PATHS_ARG} -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake ) endif () From 7920f7afa324e73bf40f7debb25aaf13711c6fe3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:13:53 -0800 Subject: [PATCH 039/341] spell things correctly so cmake knows what you want --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 2d42e3eff4..827c542b18 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -11,7 +11,7 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") - seperate_arguments(LIB_PATHS_ARG WINDOWS_COMMAND ${LIB_PATHS}) + separate_arguments(LIB_PATHS_ARG WINDOWS_COMMAND ${LIB_PATHS}) # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} From 73891b61b09e0046c031d0a3d42d329ecaac05b4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:18:35 -0800 Subject: [PATCH 040/341] use separate arugments to get colon separated list of paths --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 827c542b18..8c04e3183a 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -11,7 +11,7 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") - separate_arguments(LIB_PATHS_ARG WINDOWS_COMMAND ${LIB_PATHS}) + separate_arguments(LIB_PATHS_ARG ${LIB_PATHS}) # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} From bc9481051b2fc6d4c880f43f569763a23da1b17d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:30:39 -0800 Subject: [PATCH 041/341] use configure_file to pass lib_paths to fixup_bundle --- cmake/macros/AddPathsToLibPaths.cmake | 2 ++ .../macros/CopyDllsBesideWindowsExecutable.cmake | 15 ++++++++++----- .../FixupBundlePostBuild.cmake.in} | 4 ++-- 3 files changed, 14 insertions(+), 7 deletions(-) rename cmake/{scripts/FixupBundlePostBuild.cmake => templates/FixupBundlePostBuild.cmake.in} (67%) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index d86d054615..f9556b9363 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -14,6 +14,8 @@ macro(ADD_PATHS_TO_LIB_PATHS) set(TEMP_LIB_PATHS ${LIB_PATHS}) list(APPEND TEMP_LIB_PATHS ${_PATH}) + list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) + set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) endforeach() endmacro() \ No newline at end of file diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 8c04e3183a..2498c0dcf3 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -11,15 +11,20 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") - separate_arguments(LIB_PATHS_ARG ${LIB_PATHS}) + + configure_file( + ${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake + @ONLY + ) + # add a post-build command to copy DLLs beside the interface executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - -DBUNDLE_EXECUTABLE=$ - -DLIB_PATHS=${LIB_PATHS_ARG} - -P ${HIFI_CMAKE_DIR}/scripts/FixupBundlePostBuild.cmake + COMMAND ${CMAKE_COMMAND} + -DBUNDLE_EXECUTABLE=$ + -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) endif () endmacro() \ No newline at end of file diff --git a/cmake/scripts/FixupBundlePostBuild.cmake b/cmake/templates/FixupBundlePostBuild.cmake.in similarity index 67% rename from cmake/scripts/FixupBundlePostBuild.cmake rename to cmake/templates/FixupBundlePostBuild.cmake.in index c6d0b42aea..f72ba577b9 100644 --- a/cmake/scripts/FixupBundlePostBuild.cmake +++ b/cmake/templates/FixupBundlePostBuild.cmake.in @@ -10,5 +10,5 @@ # include(BundleUtilities) -message(STATUS "LIB_PATHS for fixup_bundle bundle ${BUNDLE_EXECUTABLE} are ${LIB_PATHS}") -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "${LIB_PATHS}") \ No newline at end of file +message(STATUS "LIB_PATHS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @LIB_PATHS@") +fixup_bundle("${BUNDLE_EXECUTABLE}" "" "@LIB_PATHS@") \ No newline at end of file From 315ab73900c60a89dc14e90f8cdd10b2de92a1f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:32:52 -0800 Subject: [PATCH 042/341] fix a typo on temporary list --- cmake/macros/AddPathsToLibPaths.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index f9556b9363..a696f5a3e5 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -11,11 +11,11 @@ macro(ADD_PATHS_TO_LIB_PATHS) foreach(_PATH ${ARGN}) - set(TEMP_LIB_PATHS ${LIB_PATHS}) - list(APPEND TEMP_LIB_PATHS ${_PATH}) + set(_TEMP_LIB_PATHS ${LIB_PATHS}) + list(APPEND _TEMP_LIB_PATHS ${_PATH}) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) - set(LIB_PATHS ${TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) + set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) endforeach() endmacro() \ No newline at end of file From df72594afe9501fff06274e70c5507943303b229 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:41:16 -0800 Subject: [PATCH 043/341] fix for docstring of external projects --- cmake/externals/glm/CMakeLists.txt | 2 +- cmake/externals/gverb/CMakeLists.txt | 6 +++--- cmake/externals/soxr/CMakeLists.txt | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index b1aed7dd7f..0ca4aa3cb2 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -12,4 +12,4 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING) \ No newline at end of file +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE) \ No newline at end of file diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index 19a44781b1..463ee26ff0 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -16,10 +16,10 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "Path to gverb include directory") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/gverb.lib CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/gverb.lib CACHE TYPE "List of gverb libraries") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libgverb.a CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libgverb.a CACHE TYPE "List of gverb libraries") endif () \ No newline at end of file diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index fcd28d4db5..2c8dd5de7d 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -16,13 +16,13 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE STRING) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "List of soxr include directories") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE STRING) - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE "List of soxr libraries") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE "Path to soxr dll") elseif (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE "List of soxr libraries") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE STRING) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE "List of soxr libraries") endif () \ No newline at end of file From d8bf8e322bb53c81526301a530c14b0c47556fe2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:42:24 -0800 Subject: [PATCH 044/341] fix a docstring in glm external project --- cmake/externals/glm/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index 0ca4aa3cb2..a9b4ad118d 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -12,4 +12,4 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE) \ No newline at end of file +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "List of glm include directories") \ No newline at end of file From 0ff382e68a1bcf09a32cf800b07abeb915e06fc9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 16:54:59 -0800 Subject: [PATCH 045/341] correct typo in sixense dll path --- cmake/modules/FindSixense.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 11ca704407..f1bfc92bc0 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -51,7 +51,7 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sixense DEFAULT_MSG ${SIXENSE_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${SIXSENSE_DEBUG_DLL_PATH}) + add_paths_to_lib_paths(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH}) endif () mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS) From 5b563e3bc5f8ad37845b823b5887df69c64a2806 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 17:12:14 -0800 Subject: [PATCH 046/341] add LIB_PATHS debugging to catch destruction --- cmake/macros/AddPathsToLibPaths.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index a696f5a3e5..02e3693470 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -12,10 +12,14 @@ macro(ADD_PATHS_TO_LIB_PATHS) foreach(_PATH ${ARGN}) set(_TEMP_LIB_PATHS ${LIB_PATHS}) + message(STATUS "RIGHT NOW LIB_PATHS IS ${LIB_PATHS}") + list(APPEND _TEMP_LIB_PATHS ${_PATH}) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) + + message(STATUS "WE JUST SET LIB_PATHS TO ${LIB_PATHS}") endforeach() endmacro() \ No newline at end of file From 68c19866c426ddfcd308982445868fb0e2cce42b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 17:17:30 -0800 Subject: [PATCH 047/341] call dll copy after project deps are setup --- assignment-client/CMakeLists.txt | 2 ++ cmake/macros/SetupHifiProject.cmake | 2 -- domain-server/CMakeLists.txt | 4 +++- gvr-interface/CMakeLists.txt | 4 +++- ice-server/CMakeLists.txt | 4 +++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 5475b0fc14..e149a8549e 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -18,3 +18,5 @@ if (UNIX) endif (UNIX) include_dependency_includes() + +copy_dlls_beside_windows_executable() diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 8b3bc43101..3f9787faa1 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -34,6 +34,4 @@ macro(SETUP_HIFI_PROJECT) foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES}) target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE}) endforeach() - - copy_dlls_beside_windows_executable() endmacro() \ No newline at end of file diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 421a1da2d4..17d2c9185b 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -52,4 +52,6 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/gvr-interface/CMakeLists.txt b/gvr-interface/CMakeLists.txt index bdffb1fbd3..20d35fb204 100644 --- a/gvr-interface/CMakeLists.txt +++ b/gvr-interface/CMakeLists.txt @@ -87,4 +87,6 @@ if (ANDROID) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/templates/hockeyapp.xml.in" "${ANDROID_APK_BUILD_DIR}/res/values/hockeyapp.xml") qt_create_apk() -endif (ANDROID) \ No newline at end of file +endif (ANDROID) + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/ice-server/CMakeLists.txt b/ice-server/CMakeLists.txt index 6a8ca5bd9f..7224bdc31a 100644 --- a/ice-server/CMakeLists.txt +++ b/ice-server/CMakeLists.txt @@ -6,4 +6,6 @@ setup_hifi_project(Network) # link the shared hifi libraries link_hifi_libraries(embedded-webserver networking shared) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file From 9d7212cdaef5535cb3cb2614f034232ee4469587 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 17:18:24 -0800 Subject: [PATCH 048/341] remove some debug in AddPathsToLibPaths --- cmake/macros/AddPathsToLibPaths.cmake | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index 02e3693470..ab1aef697b 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -12,14 +12,11 @@ macro(ADD_PATHS_TO_LIB_PATHS) foreach(_PATH ${ARGN}) set(_TEMP_LIB_PATHS ${LIB_PATHS}) - message(STATUS "RIGHT NOW LIB_PATHS IS ${LIB_PATHS}") list(APPEND _TEMP_LIB_PATHS ${_PATH}) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) - - message(STATUS "WE JUST SET LIB_PATHS TO ${LIB_PATHS}") endforeach() endmacro() \ No newline at end of file From 7d250136590310b64610fc02ee47aa11537d1f95 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 17:44:58 -0800 Subject: [PATCH 049/341] add DLL copying for all project targets --- tests/audio/CMakeLists.txt | 4 +++- tests/jitter/CMakeLists.txt | 4 +++- tests/metavoxels/CMakeLists.txt | 4 +++- tests/networking/CMakeLists.txt | 4 +++- tests/octree/CMakeLists.txt | 2 ++ tests/physics/CMakeLists.txt | 2 ++ tests/render-utils/CMakeLists.txt | 1 + tests/shared/CMakeLists.txt | 4 +++- tools/bitstream2json/CMakeLists.txt | 4 +++- tools/json2bitstream/CMakeLists.txt | 4 +++- tools/mtc/CMakeLists.txt | 4 +++- tools/scribe/CMakeLists.txt | 4 +++- 12 files changed, 32 insertions(+), 9 deletions(-) diff --git a/tests/audio/CMakeLists.txt b/tests/audio/CMakeLists.txt index 62d0ce5be9..a499ecaf1a 100644 --- a/tests/audio/CMakeLists.txt +++ b/tests/audio/CMakeLists.txt @@ -5,4 +5,6 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared audio networking) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/jitter/CMakeLists.txt b/tests/jitter/CMakeLists.txt index 93f7caefdd..8cfee4b9ad 100644 --- a/tests/jitter/CMakeLists.txt +++ b/tests/jitter/CMakeLists.txt @@ -5,4 +5,6 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/metavoxels/CMakeLists.txt b/tests/metavoxels/CMakeLists.txt index 76f8870b34..1c3cb88328 100644 --- a/tests/metavoxels/CMakeLists.txt +++ b/tests/metavoxels/CMakeLists.txt @@ -7,4 +7,6 @@ setup_hifi_project(Network Script Widgets) # link in the shared libraries link_hifi_libraries(metavoxels networking shared) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/networking/CMakeLists.txt b/tests/networking/CMakeLists.txt index 113a75ab50..0e15965966 100644 --- a/tests/networking/CMakeLists.txt +++ b/tests/networking/CMakeLists.txt @@ -5,4 +5,6 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 99e3516431..7542e40f87 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -6,3 +6,5 @@ setup_hifi_project(Script Network) link_hifi_libraries(shared octree gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index 0f15f596c0..c4107b9bfc 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -11,3 +11,5 @@ include_bullet() link_hifi_libraries(shared physics) include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/render-utils/CMakeLists.txt b/tests/render-utils/CMakeLists.txt index 12a9fe5701..3745f904df 100644 --- a/tests/render-utils/CMakeLists.txt +++ b/tests/render-utils/CMakeLists.txt @@ -15,3 +15,4 @@ endif () #link_libraries(animation fbx shared gpu) include_dependency_includes() +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/shared/CMakeLists.txt b/tests/shared/CMakeLists.txt index 0402d3c74b..8f8d6c425b 100644 --- a/tests/shared/CMakeLists.txt +++ b/tests/shared/CMakeLists.txt @@ -5,4 +5,6 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/bitstream2json/CMakeLists.txt b/tools/bitstream2json/CMakeLists.txt index 64ffbae5bf..b7b2eb198c 100644 --- a/tools/bitstream2json/CMakeLists.txt +++ b/tools/bitstream2json/CMakeLists.txt @@ -3,4 +3,6 @@ setup_hifi_project(Widgets Script) link_hifi_libraries(metavoxels) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/json2bitstream/CMakeLists.txt b/tools/json2bitstream/CMakeLists.txt index d69a8dbe17..a258fbf263 100644 --- a/tools/json2bitstream/CMakeLists.txt +++ b/tools/json2bitstream/CMakeLists.txt @@ -3,4 +3,6 @@ setup_hifi_project(Widgets Script) link_hifi_libraries(metavoxels) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/mtc/CMakeLists.txt b/tools/mtc/CMakeLists.txt index 06b9f86d06..ea21eaf5fc 100644 --- a/tools/mtc/CMakeLists.txt +++ b/tools/mtc/CMakeLists.txt @@ -1,4 +1,6 @@ set(TARGET_NAME mtc) setup_hifi_project() -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt index e67354cffa..3464809b38 100755 --- a/tools/scribe/CMakeLists.txt +++ b/tools/scribe/CMakeLists.txt @@ -2,4 +2,6 @@ set(TARGET_NAME scribe) setup_hifi_project() # call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +include_dependency_includes() + +copy_dlls_beside_windows_executable() \ No newline at end of file From 48d268420957c67d2471863aef00be8588d1780a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Feb 2015 17:51:54 -0800 Subject: [PATCH 050/341] add path to DeviceDLL for sixense --- cmake/modules/FindSixense.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index f1bfc92bc0..f47cfa65ad 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -35,6 +35,7 @@ elseif (WIN32) find_path(SIXENSE_DEBUG_DLL_PATH sixensed.dll PATH_SUFFIXES bin/win32/debug_dll HINTS ${SIXENSE_SEARCH_DIRS}) find_path(SIXENSE_RELEASE_DLL_PATH sixense.dll PATH_SUFFIXES bin/win32/release_dll HINTS ${SIXENSE_SEARCH_DIRS}) + find_path(SIXENSE_DEVICE_DLL_PATH DeviceDLL.dll PATH_SUFFIXES samples/win32/sixense_simple3d HINTS ${SIXENSE_SEARCH_DIRS}) endif () include(SelectLibraryConfigurations) @@ -42,7 +43,7 @@ select_library_configurations(SIXENSE) set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) if (WIN32) - list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH) + list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH SIXENSE_DEVICE_DLL_PATH) endif () set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}") @@ -51,7 +52,7 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sixense DEFAULT_MSG ${SIXENSE_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH}) + add_paths_to_lib_paths(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH} ${SIXENSE_DEVICE_DLL_PATH}) endif () mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS) From cc29297a19eca6a3e9b2996a426a2222d3f9185c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 10:13:23 -0800 Subject: [PATCH 051/341] remove requirement of Qt dlls in path --- BUILD_WIN.md | 20 ++++++++------------ CMakeLists.txt | 4 ++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 219192b360..b3feb19c08 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -6,7 +6,7 @@ Please read the [general build guide](BUILD.md) for information on dependencies * [zLib](http://www.zlib.net/) ~> 1.2.8 * (remember that you need all other dependencies listed in [BUILD.md](BUILD.md)) -####Visual Studio 2013 +###Visual Studio 2013 You can use the Community or Professional editions of Visual Studio 2013. @@ -32,10 +32,8 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit * [Download the offline installer](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe) Once Qt is installed, you need to manually configure the following: -* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.3.2\msvc2013_opengl\bin\`. -* Go to Control Panel > System > Advanced System Settings > Environment Variables > New ... * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory. - + * You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New ###External Libraries As it stands, Hifi/Interface is a 32-bit application, so all libraries should also be 32-bit. @@ -70,9 +68,7 @@ The recommended route for CMake to find the external dependencies is to place al For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. -As with the Qt libraries, you will need to make sure that directories containing DLL'S are in your path. Where possible, you can use static builds of the external dependencies to avoid this requirement. - -###OpenSSL +####OpenSSL Qt will use OpenSSL if it's available, but it doesn't install it, so you must install it separately. @@ -92,13 +88,13 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. -###Intel Threading Building Blocks (TBB) +####Intel Threading Building Blocks (TBB) Download the zip from the [TBB website](https://www.threadingbuildingblocks.org/). We recommend you extract it to %HIFI_LIB_DIR%\tbb. This will help our FindTBB cmake module find what it needs. You can place it wherever you like on your machine if you specify TBB_ROOT_DIR as an environment variable or a variable passed when cmake is run. -###Zlib +####Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. @@ -114,19 +110,19 @@ Add to the PATH: `%HIFI_LIB_DIR%\zlib` Important! This should be added at the beginning of the path, not the end (your system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". -###freeglut +####freeglut Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` -###GLEW +####GLEW Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` -###Bullet +####Bullet Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself. diff --git a/CMakeLists.txt b/CMakeLists.txt index 9731582b59..7a523501d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,10 @@ endif () set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) +if (WIN32) + add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}/bin") +endif () + # set our OS X deployment target to set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) From c9fea9330ef311ccbf176cde48b6f4c46210b4e0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 10:16:45 -0800 Subject: [PATCH 052/341] explain in win guide that fixup_bundle is finding DLLs --- BUILD_WIN.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index b3feb19c08..a3c15eea37 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -34,12 +34,15 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit Once Qt is installed, you need to manually configure the following: * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory. * You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New + ###External Libraries As it stands, Hifi/Interface is a 32-bit application, so all libraries should also be 32-bit. CMake will need to know where the headers and libraries for required external dependencies are. +We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required. + The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir From 5230b805d28328bddeaf781288e5ad40c8e1dac9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 18 Feb 2015 19:24:29 +0100 Subject: [PATCH 053/341] Fix warnings --- interface/src/scripting/HMDScriptingInterface.cpp | 1 - interface/src/ui/ApplicationOverlay.cpp | 2 +- libraries/model/src/model/Light.cpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index fe274b6878..f258fd695c 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -48,7 +48,6 @@ QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* conte QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { glm::vec3 result; - HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance(); if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) { return qScriptValueFromValue(engine, result); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 569ef0cf80..632e76c840 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -136,10 +136,10 @@ ApplicationOverlay::ApplicationOverlay() : _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), _lastMouseMove(0), + _magnifier(true), _alpha(1.0f), _oculusUIRadius(1.0f), _crosshairTexture(0), - _magnifier(true), _previousBorderWidth(-1), _previousBorderHeight(-1), _previousMagnifierBottomLeft(), diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 9616ed2106..a9425bed4b 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -76,7 +76,6 @@ void Light::setSpotAngle(float angle) { if (angle <= 0.f) { angle = 0.0f; } - float cosAngle = cos(angle); editSchema()._spot.x = cos(angle); editSchema()._spot.y = sin(angle); editSchema()._spot.z = angle; From e2d7fb574aa81dae8d0afe05480462edd02f40d5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 11:27:37 -0800 Subject: [PATCH 054/341] move macro call so it is actually loaded --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a523501d2..c821eafe90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,10 +88,6 @@ endif () set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) -if (WIN32) - add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}/bin") -endif () - # set our OS X deployment target to set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) @@ -130,6 +126,10 @@ if (ANDROID) endforeach() endif () +if (WIN32) + add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}/bin") +endif () + # add subdirectories for all targets if (NOT ANDROID) add_subdirectory(assignment-client) From b2ecf990083a3aaba96200b1b87b5ccb2679f931 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 11:36:49 -0800 Subject: [PATCH 055/341] back out of lib cmake dir to get Qt bin --- BUILD_WIN.md | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index a3c15eea37..5f3e4c2228 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -32,7 +32,7 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit * [Download the offline installer](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe) Once Qt is installed, you need to manually configure the following: -* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory. +* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl\lib\cmake` directory. * You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New ###External Libraries diff --git a/CMakeLists.txt b/CMakeLists.txt index c821eafe90..7238cd14a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ if (ANDROID) endif () if (WIN32) - add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}/bin") + add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}\\..\\..\\bin") endif () # add subdirectories for all targets From 84e82f045d7256e81c1c782983b0517a6bb06030 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 11:38:08 -0800 Subject: [PATCH 056/341] find QT_DIR in root CMakeLists --- CMakeLists.txt | 5 ++++- cmake/android/QtCreateAPK.cmake | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7238cd14a1..3dcb3731c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,9 @@ else () endif () endif () +# figure out where the qt dir is +get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) # set our OS X deployment target to @@ -127,7 +130,7 @@ if (ANDROID) endif () if (WIN32) - add_paths_to_lib_paths("${QT_CMAKE_PREFIX_PATH}\\..\\..\\bin") + add_paths_to_lib_paths("${QT_DIR}/bin") endif () # add subdirectories for all targets diff --git a/cmake/android/QtCreateAPK.cmake b/cmake/android/QtCreateAPK.cmake index a8543a5fbc..c3a4a48ac7 100644 --- a/cmake/android/QtCreateAPK.cmake +++ b/cmake/android/QtCreateAPK.cmake @@ -39,9 +39,6 @@ macro(qt_create_apk) # create "strings.xml" configure_file("${ANDROID_THIS_DIRECTORY}/strings.xml.in" "${ANDROID_APK_BUILD_DIR}/res/values/strings.xml") - - # figure out where the qt dir is - get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) # find androiddeployqt find_program(ANDROID_DEPLOY_QT androiddeployqt HINTS "${QT_DIR}/bin") From 0a01a6f566a0af0c7d80e004ac8d20554f2fdd22 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 13:24:59 -0800 Subject: [PATCH 057/341] add TBB as external_project, handle on OS X --- BUILD_OSX.md | 2 +- cmake/externals/tbb/CMakeLists.txt | 41 +++++++++++++++++++++++++++++ libraries/networking/CMakeLists.txt | 6 +++-- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 cmake/externals/tbb/CMakeLists.txt diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 563fd38c1c..c199fe4c73 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -4,7 +4,7 @@ Please read the [general build guide](BUILD.md) for information on dependencies [Homebrew](http://brew.sh/) is an excellent package manager for OS X. It makes install of all hifi dependencies very simple. brew tap highfidelity/homebrew-formulas - brew install cmake openssl tbb + brew install cmake openssl brew install highfidelity/formulas/qt5 brew link qt5 --force diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt new file mode 100644 index 0000000000..52c01227ea --- /dev/null +++ b/cmake/externals/tbb/CMakeLists.txt @@ -0,0 +1,41 @@ +set(EXTERNAL_NAME tbb) + +if (APPLE) + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) +elseif (WIN32) + +elseif (UNIX) + +elseif (ANDROID) + +endif () + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + PREFIX ${EXTERNAL_NAME} + URL ${DOWNLOAD_URL} + BUILD_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" + UPDATE_COMMAND "" + LOG_DOWNLOAD ON +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") + +if (APPLE) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/lib/libc++/libtbb_debug.dylib CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/libc++/libtbb.dylib CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${SOURCE_DIR}/lib/libc++/libtbbmalloc_debug.dylib CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${SOURCE_DIR}/lib/libc++/libtbbmalloc.dylib CACHE TYPE "TBB malloc release library location") +elseif (WIN32) + # set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE "List of soxr libraries") + # set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE "Path to soxr dll") + +else () + # set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE "List of soxr libraries") +endif () \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index bc251a42d4..2236b93d32 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -10,6 +10,8 @@ if (WIN32) target_link_libraries(${TARGET_NAME} ws2_32.lib) endif () +add_dependency_external_projects(tbb) + # find required dependencies find_package(OpenSSL REQUIRED) find_package(TBB REQUIRED) @@ -25,8 +27,8 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) -# append libcuckoo includes to our list of includes to bubble -list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${TBB_INCLUDE_DIRS}") +# append tbb includes to our list of includes to bubble +target_include_directories(${TARGET_NAME} PUBLIC ${TBB_INCLUDE_DIRS}) # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() \ No newline at end of file From 60fc4d2c1c65a8b1c50451559be92c24252cd192 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 13:54:30 -0800 Subject: [PATCH 058/341] attempt to handle android via tbb binaries --- cmake/externals/tbb/CMakeLists.txt | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 52c01227ea..d8b1fa6983 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -3,17 +3,14 @@ set(EXTERNAL_NAME tbb) if (APPLE) set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) elseif (WIN32) - -elseif (UNIX) - -elseif (ANDROID) - + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) +else() + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - PREFIX ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} BUILD_COMMAND "" CONFIGURE_COMMAND "" @@ -36,6 +33,15 @@ elseif (WIN32) # set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE "List of soxr libraries") # set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE "Path to soxr dll") +elseif (ANDROID) + set(_TBB_ANDROID_LIB_PATH "${SOURCE_DIR}/lib/android/x86_64") + + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_PATH}/libtbb_debug.so CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_PATH}/libtbb.so CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_PATH}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_PATH}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") +elseif (UNIX) + else () - # set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE "List of soxr libraries") -endif () \ No newline at end of file + message(STATUS "Your OS is not handled by our TBB external project CMakeLists.txt. Please install TBB yourself and pass -DGET_TBB=0 when running CMake.") +endif () \ No newline at end of file From 973a076f34df20d28e601bef50121c13bfbc0433 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 13:54:39 -0800 Subject: [PATCH 059/341] use default prefix for external project --- cmake/externals/glm/CMakeLists.txt | 1 - cmake/externals/gverb/CMakeLists.txt | 1 - cmake/externals/soxr/CMakeLists.txt | 1 - 3 files changed, 3 deletions(-) diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index a9b4ad118d..1fa393e69e 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -3,7 +3,6 @@ set(EXTERNAL_NAME glm) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - PREFIX ${EXTERNAL_NAME} URL http://pkgs.fedoraproject.org/repo/pkgs/glm/glm-0.9.5.4.zip/fab76fc982b256b46208e5c750ed456a/glm-0.9.5.4.zip CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index 463ee26ff0..972b5b602f 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -7,7 +7,6 @@ endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - PREFIX ${EXTERNAL_NAME} GIT_REPOSITORY https://github.com/birarda/gverb.git CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 2c8dd5de7d..49d7c7598a 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -7,7 +7,6 @@ endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - PREFIX ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1.zip CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_SHARED_LIBS=1 -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON From 71482f6ad73a50f4e9182d4135cdca43d1f0180c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 13:58:20 -0800 Subject: [PATCH 060/341] include tbb as system include, use project as prefix --- CMakeLists.txt | 2 ++ libraries/networking/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dcb3731c3..dbe853dfcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,8 @@ else () set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR}") endif () +set_property(DIRECTORY PROPERTY EP_PREFIX "project") + file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake") foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS}) include(${CUSTOM_MACRO}) diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 2236b93d32..f7dea6c10f 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -28,7 +28,7 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) # append tbb includes to our list of includes to bubble -target_include_directories(${TARGET_NAME} PUBLIC ${TBB_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS}) # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() \ No newline at end of file From b2e587dbbdb85ffc5972cb96e613eddddc91aff3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 14:12:05 -0800 Subject: [PATCH 061/341] remove use of include_dependency_includes and use cmake --- assignment-client/CMakeLists.txt | 2 - cmake/macros/IncludeDependencyIncludes.cmake | 22 ----------- domain-server/CMakeLists.txt | 2 - gvr-interface/CMakeLists.txt | 1 - ice-server/CMakeLists.txt | 2 - interface/CMakeLists.txt | 3 -- libraries/animation/CMakeLists.txt | 5 +-- libraries/audio-client/CMakeLists.txt | 7 +--- libraries/audio/CMakeLists.txt | 5 +-- libraries/avatars/CMakeLists.txt | 3 -- libraries/embedded-webserver/CMakeLists.txt | 5 +-- libraries/entities-renderer/CMakeLists.txt | 5 +-- libraries/entities/CMakeLists.txt | 3 -- libraries/environment/CMakeLists.txt | 5 +-- libraries/fbx/CMakeLists.txt | 5 +-- libraries/gpu/CMakeLists.txt | 9 +---- libraries/metavoxels/CMakeLists.txt | 5 +-- libraries/model/CMakeLists.txt | 5 +-- libraries/networking/CMakeLists.txt | 5 +-- libraries/octree/CMakeLists.txt | 3 -- libraries/physics/CMakeLists.txt | 3 -- libraries/render-utils/CMakeLists.txt | 41 +++++++++----------- libraries/script-engine/CMakeLists.txt | 4 -- libraries/shared/CMakeLists.txt | 5 +-- tests/audio/CMakeLists.txt | 2 - tests/jitter/CMakeLists.txt | 2 - tests/metavoxels/CMakeLists.txt | 2 - tests/networking/CMakeLists.txt | 2 - tests/octree/CMakeLists.txt | 2 - tests/physics/CMakeLists.txt | 2 - tests/render-utils/CMakeLists.txt | 3 -- tests/shared/CMakeLists.txt | 2 - tools/bitstream2json/CMakeLists.txt | 2 - tools/json2bitstream/CMakeLists.txt | 2 - tools/mtc/CMakeLists.txt | 2 - tools/scribe/CMakeLists.txt | 3 -- 36 files changed, 33 insertions(+), 148 deletions(-) delete mode 100644 cmake/macros/IncludeDependencyIncludes.cmake diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index e149a8549e..41343f52d0 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -17,6 +17,4 @@ if (UNIX) target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) -include_dependency_includes() - copy_dlls_beside_windows_executable() diff --git a/cmake/macros/IncludeDependencyIncludes.cmake b/cmake/macros/IncludeDependencyIncludes.cmake deleted file mode 100644 index 4474bdc53a..0000000000 --- a/cmake/macros/IncludeDependencyIncludes.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# IncludeDependencyIncludes.cmake -# cmake/macros -# -# Copyright 2014 High Fidelity, Inc. -# Created by Stephen Birarda on August 8, 2014 -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -macro(INCLUDE_DEPENDENCY_INCLUDES) - if (${TARGET_NAME}_DEPENDENCY_INCLUDES) - list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_INCLUDES) - - # include those in our own target - include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) - - # set the property on this target so it can be retreived by targets linking to us - set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") - endif() -endmacro(INCLUDE_DEPENDENCY_INCLUDES) \ No newline at end of file diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 17d2c9185b..4ff3c1cce1 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -52,6 +52,4 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/gvr-interface/CMakeLists.txt b/gvr-interface/CMakeLists.txt index 20d35fb204..a986fcae0d 100644 --- a/gvr-interface/CMakeLists.txt +++ b/gvr-interface/CMakeLists.txt @@ -29,7 +29,6 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) link_hifi_libraries(shared networking audio-client avatars) -include_dependency_includes() if (ANDROID) find_package(LibOVR) diff --git a/ice-server/CMakeLists.txt b/ice-server/CMakeLists.txt index 7224bdc31a..13d89fc4a2 100644 --- a/ice-server/CMakeLists.txt +++ b/ice-server/CMakeLists.txt @@ -6,6 +6,4 @@ setup_hifi_project(Network) # link the shared hifi libraries link_hifi_libraries(embedded-webserver networking shared) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 31d8f3df45..7458a6c784 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -240,6 +240,3 @@ else (APPLE) endif (APPLE) copy_dlls_beside_windows_executable() - -# link any dependencies bubbled up from our linked dependencies -include_dependency_includes() diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 4024205f81..8c75d5620c 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -3,7 +3,4 @@ set(TARGET_NAME animation) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) -link_hifi_libraries(shared gpu model fbx) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +link_hifi_libraries(shared gpu model fbx) \ No newline at end of file diff --git a/libraries/audio-client/CMakeLists.txt b/libraries/audio-client/CMakeLists.txt index 7067e2ed81..fa7249bee5 100644 --- a/libraries/audio-client/CMakeLists.txt +++ b/libraries/audio-client/CMakeLists.txt @@ -6,7 +6,7 @@ setup_hifi_library(Network Multimedia) link_hifi_libraries(audio) # append audio includes to our list of includes to bubble -list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${HIFI_LIBRARY_DIR}/audio/src") +target_include_directories(${TARGET_NAME} PUBLIC "${HIFI_LIBRARY_DIR}/audio/src") # have CMake grab externals for us add_dependency_external_projects(gverb soxr) @@ -25,7 +25,4 @@ if (APPLE) find_library(CoreAudio CoreAudio) find_library(CoreFoundation CoreFoundation) target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation}) -endif () - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +endif () \ No newline at end of file diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index b9dfc06cad..c2d5c8aca9 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -7,7 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(networking shared) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +link_hifi_libraries(networking shared) \ No newline at end of file diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index ad06b4adfa..acc939b25c 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -8,6 +8,3 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) link_hifi_libraries(audio shared networking) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() diff --git a/libraries/embedded-webserver/CMakeLists.txt b/libraries/embedded-webserver/CMakeLists.txt index ef2cf1054c..955487e540 100644 --- a/libraries/embedded-webserver/CMakeLists.txt +++ b/libraries/embedded-webserver/CMakeLists.txt @@ -1,7 +1,4 @@ set(TARGET_NAME embedded-webserver) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Network) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +setup_hifi_library(Network) \ No newline at end of file diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index b807428203..c0880ed15d 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -7,7 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared gpu script-engine render-utils) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() +link_hifi_libraries(shared gpu script-engine render-utils) \ No newline at end of file diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 5317f97b85..156f3d1f09 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -10,6 +10,3 @@ target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) include_bullet() link_hifi_libraries(avatars shared octree gpu model fbx networking animation) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() diff --git a/libraries/environment/CMakeLists.txt b/libraries/environment/CMakeLists.txt index 1c4daa1a6f..61a8c6b8df 100644 --- a/libraries/environment/CMakeLists.txt +++ b/libraries/environment/CMakeLists.txt @@ -14,7 +14,4 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # add it to our list of libraries to link -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) \ No newline at end of file diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index b43e88bb3d..c1ba5a1c2a 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -11,7 +11,4 @@ link_hifi_libraries(shared gpu model networking octree) find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() +target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) \ No newline at end of file diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 789ffdbfeb..6e7a38f594 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -19,8 +19,7 @@ elseif (WIN32) target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) - # need to bubble up the GLEW_INCLUDE_DIRS - list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${GLEW_INCLUDE_DIRS}") + target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) @@ -40,9 +39,5 @@ else () target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") - # need to bubble up the OPENGL_INCLUDE_DIR - list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${OPENGL_INCLUDE_DIR}") + target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) endif (APPLE) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() diff --git a/libraries/metavoxels/CMakeLists.txt b/libraries/metavoxels/CMakeLists.txt index f748971311..240a2d8853 100644 --- a/libraries/metavoxels/CMakeLists.txt +++ b/libraries/metavoxels/CMakeLists.txt @@ -10,7 +10,4 @@ link_hifi_libraries(shared networking) add_dependency_external_projects(glm) find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) \ No newline at end of file diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index e3eeae7137..c62b29599f 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -7,7 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared gpu) - -# call macro to link our dependencies and bubble them up via a property on our target -include_dependency_includes() +link_hifi_libraries(shared gpu) \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index f7dea6c10f..6b386ace92 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -28,7 +28,4 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) # append tbb includes to our list of includes to bubble -target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS}) \ No newline at end of file diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index ad6f32f0ff..1f44795148 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -16,6 +16,3 @@ include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # append ZLIB and OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 775d5fcb0f..c3dfcafa48 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -14,6 +14,3 @@ endif (BULLET_FOUND) link_hifi_libraries(shared fbx entities) include_hifi_library_headers(fbx) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index d6e419fa49..b266c001e4 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -1,23 +1,20 @@ -set(TARGET_NAME render-utils) - -AUTOSCRIBE_SHADER_LIB() - -# pull in the resources.qrc file -qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") - -# use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Widgets OpenGL Network Script) - -add_dependency_external_projects(glm) +set(TARGET_NAME render-utils) + +AUTOSCRIBE_SHADER_LIB() + +# pull in the resources.qrc file +qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library(Widgets OpenGL Network Script) + +add_dependency_external_projects(glm) find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) - -link_hifi_libraries(animation fbx shared gpu) - -if (WIN32) - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) -endif () - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) + +link_hifi_libraries(animation fbx shared gpu) + +if (WIN32) + # we're using static GLEW, so define GLEW_STATIC + add_definitions(-DGLEW_STATIC) +endif () diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 99ac9da87c..013f43530c 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -8,7 +8,3 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) link_hifi_libraries(shared octree gpu model fbx entities animation audio physics metavoxels) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() - diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index ab4b853b6d..9785994a29 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -6,7 +6,4 @@ setup_hifi_library(Gui Network Script Widgets) add_dependency_external_projects(glm) find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) - -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() \ No newline at end of file +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) \ No newline at end of file diff --git a/tests/audio/CMakeLists.txt b/tests/audio/CMakeLists.txt index a499ecaf1a..a106fc9ea9 100644 --- a/tests/audio/CMakeLists.txt +++ b/tests/audio/CMakeLists.txt @@ -5,6 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared audio networking) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/jitter/CMakeLists.txt b/tests/jitter/CMakeLists.txt index 8cfee4b9ad..377dcc1081 100644 --- a/tests/jitter/CMakeLists.txt +++ b/tests/jitter/CMakeLists.txt @@ -5,6 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/metavoxels/CMakeLists.txt b/tests/metavoxels/CMakeLists.txt index 1c3cb88328..e6a62dc55c 100644 --- a/tests/metavoxels/CMakeLists.txt +++ b/tests/metavoxels/CMakeLists.txt @@ -7,6 +7,4 @@ setup_hifi_project(Network Script Widgets) # link in the shared libraries link_hifi_libraries(metavoxels networking shared) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/networking/CMakeLists.txt b/tests/networking/CMakeLists.txt index 0e15965966..6b9d3738d4 100644 --- a/tests/networking/CMakeLists.txt +++ b/tests/networking/CMakeLists.txt @@ -5,6 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 7542e40f87..70457e220a 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -5,6 +5,4 @@ setup_hifi_project(Script Network) # link in the shared libraries link_hifi_libraries(shared octree gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index c4107b9bfc..12cd9b8531 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -10,6 +10,4 @@ include_bullet() link_hifi_libraries(shared physics) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/render-utils/CMakeLists.txt b/tests/render-utils/CMakeLists.txt index 3745f904df..d55d3c542b 100644 --- a/tests/render-utils/CMakeLists.txt +++ b/tests/render-utils/CMakeLists.txt @@ -12,7 +12,4 @@ if (WIN32) add_definitions(-DGLEW_STATIC) endif () -#link_libraries(animation fbx shared gpu) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/shared/CMakeLists.txt b/tests/shared/CMakeLists.txt index 8f8d6c425b..9ae00756e8 100644 --- a/tests/shared/CMakeLists.txt +++ b/tests/shared/CMakeLists.txt @@ -5,6 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/bitstream2json/CMakeLists.txt b/tools/bitstream2json/CMakeLists.txt index b7b2eb198c..32a5a639ab 100644 --- a/tools/bitstream2json/CMakeLists.txt +++ b/tools/bitstream2json/CMakeLists.txt @@ -3,6 +3,4 @@ setup_hifi_project(Widgets Script) link_hifi_libraries(metavoxels) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/json2bitstream/CMakeLists.txt b/tools/json2bitstream/CMakeLists.txt index a258fbf263..abda40667c 100644 --- a/tools/json2bitstream/CMakeLists.txt +++ b/tools/json2bitstream/CMakeLists.txt @@ -3,6 +3,4 @@ setup_hifi_project(Widgets Script) link_hifi_libraries(metavoxels) -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/mtc/CMakeLists.txt b/tools/mtc/CMakeLists.txt index ea21eaf5fc..5c598eaf0b 100644 --- a/tools/mtc/CMakeLists.txt +++ b/tools/mtc/CMakeLists.txt @@ -1,6 +1,4 @@ set(TARGET_NAME mtc) setup_hifi_project() -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt index 3464809b38..bc07fec230 100755 --- a/tools/scribe/CMakeLists.txt +++ b/tools/scribe/CMakeLists.txt @@ -1,7 +1,4 @@ set(TARGET_NAME scribe) setup_hifi_project() -# call macro to include our dependency includes and bubble them up via a property on our target -include_dependency_includes() - copy_dlls_beside_windows_executable() \ No newline at end of file From b6d660fdd321f3a7eefe8020c80df66ccb4d556a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 15:26:33 -0800 Subject: [PATCH 062/341] setup TBB external project for windows --- cmake/externals/tbb/CMakeLists.txt | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index d8b1fa6983..bc689c2c08 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -4,7 +4,7 @@ if (APPLE) set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) elseif (WIN32) set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) -else() +else () set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) endif () @@ -25,21 +25,26 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") if (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/lib/libc++/libtbb_debug.dylib CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/libc++/libtbb.dylib CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${SOURCE_DIR}/lib/libc++/libtbbmalloc_debug.dylib CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${SOURCE_DIR}/lib/libc++/libtbbmalloc.dylib CACHE TYPE "TBB malloc release library location") + set(_TBB_APPLE_LIB_DIR "${SOURCE_DIR}/lib/libc++") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbb_debug.dylib CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbb.dylib CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbbmalloc_debug.dylib CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbbmalloc.dylib CACHE TYPE "TBB malloc release library location") elseif (WIN32) - # set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE "List of soxr libraries") - # set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE "Path to soxr dll") + set(_TBB_WIN_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbb_debug.lib CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/libtbb.lib CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbbmalloc_debug.lib CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/libtbbmalloc.lib CACHE TYPE "TBB malloc release library location") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE TYPE "Path to TBB DLLs") elseif (ANDROID) - set(_TBB_ANDROID_LIB_PATH "${SOURCE_DIR}/lib/android/x86_64") + set(_TBB_ANDROID_LIB_DIR "${SOURCE_DIR}/lib/android/x86_64") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_PATH}/libtbb_debug.so CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_PATH}/libtbb.so CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_PATH}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_PATH}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") elseif (UNIX) else () From b3b292a45f2cd6ca0da94cd361a6dd92066b346c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 15:40:14 -0800 Subject: [PATCH 063/341] handle linux binary find for tbb external project --- cmake/externals/tbb/CMakeLists.txt | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index bc689c2c08..a31ec09382 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -1,11 +1,11 @@ set(EXTERNAL_NAME tbb) if (APPLE) - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) + set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) elseif (WIN32) - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) + set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) else () - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) + set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) endif () include(ExternalProject) @@ -46,6 +46,29 @@ elseif (ANDROID) set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") elseif (UNIX) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_TBB_ARCH_DIR "intel64") + else() + set(_TBB_ARCH_DIR "ia32") + endif() + + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION + ) + + if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4) + set(_TBB_LINUX_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.4") + elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1) + set(_TBB_LINUX_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.1") + else () + message(FATAL_ERROR "Could not find a compatible version of Threading Building Blocks library for your compiler.") + endif () + + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") else () message(STATUS "Your OS is not handled by our TBB external project CMakeLists.txt. Please install TBB yourself and pass -DGET_TBB=0 when running CMake.") From e665a1b4bb27f63893ccb38c09e1de7e604ac0ba Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 15:47:33 -0800 Subject: [PATCH 064/341] use https for tbb urls since it will redirect --- cmake/externals/tbb/CMakeLists.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index a31ec09382..858cdaeb9f 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -1,11 +1,11 @@ set(EXTERNAL_NAME tbb) if (APPLE) - set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) elseif (WIN32) - set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) else () - set(DOWNLOAD_URL http://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) + set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) endif () include(ExternalProject) @@ -26,12 +26,14 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List o if (APPLE) set(_TBB_APPLE_LIB_DIR "${SOURCE_DIR}/lib/libc++") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbb_debug.dylib CACHE TYPE "TBB debug library location") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbb.dylib CACHE TYPE "TBB release library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbbmalloc_debug.dylib CACHE TYPE "TBB malloc debug library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbbmalloc.dylib CACHE TYPE "TBB malloc release library location") elseif (WIN32) set(_TBB_WIN_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbb_debug.lib CACHE TYPE "TBB debug library location") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/libtbb.lib CACHE TYPE "TBB release library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbbmalloc_debug.lib CACHE TYPE "TBB malloc debug library location") From 11060ed2739d915be6d174217964c0c62922dc42 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 18 Feb 2015 16:00:37 -0800 Subject: [PATCH 065/341] trying to tackle the unenderstood transform value not going through corectly? --- libraries/gpu/src/gpu/GLBackend.cpp | 18 ++++++++++-------- libraries/model/src/model/Material.slh | 4 ++-- libraries/render-utils/src/Model.cpp | 4 ++-- libraries/render-utils/src/model.slv | 9 +++++---- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6b73782798..680ffe64b0 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -492,21 +492,23 @@ void GLBackend::updateTransform() { } if (_transform._invalidView || _transform._invalidProj) { - glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera); - glBindBuffer(GL_UNIFORM_BUFFER, 0); + glBindBufferBase(GL_UNIFORM_BUFFER, 2, 0); + glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR(); } if (_transform._invalidView || _transform._invalidModel) { - glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject); - glBindBuffer(GL_UNIFORM_BUFFER, 0); + glBindBufferBase(GL_UNIFORM_BUFFER, 6, 0); + glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR(); } - glBindBufferRange(GL_UNIFORM_BUFFER, 6, _transform._transformObjectBuffer, 0, sizeof(TransformObject)); - glBindBufferRange(GL_UNIFORM_BUFFER, 7, _transform._transformCameraBuffer, 0, sizeof(TransformCamera)); + glBindBufferBase(GL_UNIFORM_BUFFER, 6, _transform._transformObjectBuffer); + glBindBufferBase(GL_UNIFORM_BUFFER, 2, _transform._transformCameraBuffer); CHECK_GL_ERROR(); // Do it again for fixed pipeline unitl we can get rid of it diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 403a4161e8..9ea269f214 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -26,10 +26,10 @@ float getMaterialShininess(Material m) { return m._specular.a; } <@if GLPROFILE == PC_GL@> uniform materialBuffer { - Material mat; + Material _mat; }; Material getMaterial() { - return mat; + return _mat; } <@elif GLPROFILE == MAC_GL@> uniform vec4 materialBuffer[2]; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index fb64a8410a..fb26f7f9dc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -231,11 +231,11 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo loc = glGetUniformBlockIndex(program.programId(), "transformCameraBuffer"); if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, 7); + glUniformBlockBinding(program.programId(), loc, 2); // locations.materialBufferUnit = 1; } - program.link(); + //program.link(); if (!program.isLinked()) { program.release(); } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 1191dbed39..7f97e429d9 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -48,10 +48,11 @@ void main(void) { // use standard pipeline transform //gl_Position = ftransform(); //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - // TransformObject obj = getTransformObject(); - TransformCamera cam = getTransformCamera(); + //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; + //TransformCamera cam = getTransformCamera(); + /* TransformObject obj = getTransformObject(); // gl_Position = transform(cam, obj, gl_Vertex); - + */ vec4 vPos = gl_ModelViewMatrix * gl_Vertex; - gl_Position = cam._projection * vPos; + gl_Position = camera._projection * vPos; } From 75b193d784c234beb0ebfad9eb9608aa20f1d2b5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 16:03:12 -0800 Subject: [PATCH 066/341] mirror tbb in HF S3 for http link --- cmake/externals/tbb/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 858cdaeb9f..756badf3b0 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -1,11 +1,11 @@ set(EXTERNAL_NAME tbb) if (APPLE) - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_osx.tgz) elseif (WIN32) - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_win.zip) else () - set(DOWNLOAD_URL https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_lin.tgz) endif () include(ExternalProject) From 7ec01c90958d9fe181a01fc945adb42bc5694506 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 17:20:13 -0800 Subject: [PATCH 067/341] handle android build of tbb, don't prefix win with lib --- CMakeLists.txt | 6 ++- cmake/externals/tbb/AndroidTBBLibCopy.cmake | 23 ++++++++ cmake/externals/tbb/CMakeLists.txt | 59 +++++++++++++-------- libraries/audio-client/CMakeLists.txt | 2 +- 4 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 cmake/externals/tbb/AndroidTBBLibCopy.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index dbe853dfcc..924d0367c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,11 +110,13 @@ set(HIFI_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(MACRO_DIR "${HIFI_CMAKE_DIR}/macros") set(EXTERNAL_PROJECT_DIR "${HIFI_CMAKE_DIR}/externals") +STRING(REGEX REPLACE " " "-" CMAKE_GENERATOR_FOLDER_NAME ${CMAKE_GENERATOR}) + set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") if (ANDROID) - set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR}") + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}") else () - set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR}") + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR_FOLDER_NAME}") endif () set_property(DIRECTORY PROPERTY EP_PREFIX "project") diff --git a/cmake/externals/tbb/AndroidTBBLibCopy.cmake b/cmake/externals/tbb/AndroidTBBLibCopy.cmake new file mode 100644 index 0000000000..733ee00124 --- /dev/null +++ b/cmake/externals/tbb/AndroidTBBLibCopy.cmake @@ -0,0 +1,23 @@ +# +# AndroidTBBLibCopy.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 18, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +# first find the so files in the source dir +file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.so") + +# raise an error if we found none +if (NOT _TBB_LIBRARIES) + message(FATAL_ERROR "Did not find any compiled TBB libraries") +endif () + +# make the libs directory and copy the resulting files there +file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib") +message(STATUS "Copying TBB Android libs to ${CMAKE_CURRENT_SOURCE_DIR}/lib") +file(COPY ${_TBB_LIBRARIES} DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/lib") \ No newline at end of file diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 756badf3b0..cbf7d80c68 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -1,23 +1,38 @@ set(EXTERNAL_NAME tbb) -if (APPLE) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_osx.tgz) -elseif (WIN32) - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_win.zip) -else () - set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_lin.tgz) -endif () - include(ExternalProject) -ExternalProject_Add( - ${EXTERNAL_NAME} - URL ${DOWNLOAD_URL} - BUILD_COMMAND "" - CONFIGURE_COMMAND "" - INSTALL_COMMAND "" - UPDATE_COMMAND "" - LOG_DOWNLOAD ON -) + +if (ANDROID) + + find_program(NDK_BUILD_COMMAND NAMES ndk-build DOC "Path to the ndk-build command") + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150209oss_src.tgz + BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake + LOG_DOWNLOAD ON + ) +else () + if (APPLE) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_osx.tgz) + elseif (WIN32) + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_win.zip) + else () + set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_lin.tgz) + endif () + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL ${DOWNLOAD_URL} + BUILD_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) +endif () ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) @@ -34,14 +49,14 @@ if (APPLE) elseif (WIN32) set(_TBB_WIN_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbb_debug.lib CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/libtbb.lib CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/libtbbmalloc_debug.lib CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/libtbbmalloc.lib CACHE TYPE "TBB malloc release library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/tbb_debug.lib CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/tbb.lib CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/tbbmalloc_debug.lib CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/tbbmalloc.lib CACHE TYPE "TBB malloc release library location") set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE TYPE "Path to TBB DLLs") elseif (ANDROID) - set(_TBB_ANDROID_LIB_DIR "${SOURCE_DIR}/lib/android/x86_64") + set(_TBB_ANDROID_LIB_DIR "${SOURCE_DIR}/lib") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") diff --git a/libraries/audio-client/CMakeLists.txt b/libraries/audio-client/CMakeLists.txt index fa7249bee5..43a2016acf 100644 --- a/libraries/audio-client/CMakeLists.txt +++ b/libraries/audio-client/CMakeLists.txt @@ -19,7 +19,7 @@ target_include_directories(${TARGET_NAME} PRIVATE ${GVERB_INCLUDE_DIRS}) # we use libsoxr for resampling find_package(Soxr REQUIRED) target_link_libraries(${TARGET_NAME} ${SOXR_LIBRARIES}) -include_directories(SYSTEM ${SOXR_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${SOXR_INCLUDE_DIRS}) if (APPLE) find_library(CoreAudio CoreAudio) From 6231a9d8da996748226a533132f512d9c22d4907 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 18 Feb 2015 17:29:32 -0800 Subject: [PATCH 068/341] remove TBB from build guides --- BUILD.md | 2 +- BUILD_ANDROID.md | 17 ----------------- BUILD_WIN.md | 6 ------ 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/BUILD.md b/BUILD.md index 9501f7ad0a..f3e9c81b78 100644 --- a/BUILD.md +++ b/BUILD.md @@ -4,13 +4,13 @@ * [Qt](http://qt-project.org/downloads) ~> 5.3.2 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. -* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 #### CMake External Project Dependencies The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-externals`. Should you want to force a re-download and re-compile of all externals, just remove the `build-externals` folder. +* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [gverb](https://github.com/highfidelity/gverb) * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md index 9fe286744d..9f86e7e925 100644 --- a/BUILD_ANDROID.md +++ b/BUILD_ANDROID.md @@ -72,22 +72,6 @@ This should generate libcrypto and libssl in the root of the OpenSSL directory. If you have been building other components it is possible that the OpenSSL compile will fail based on the values other cross-compilations (tbb, bullet) have set. Ensure that you are in a new terminal window to avoid compilation errors from previously set environment variables. -####Intel Threading Building Blocks - -Download the [Intel Threading Building Blocks source](https://www.threadingbuildingblocks.org/download) and extract the tarball inside your `ANDROID_LIB_DIR`. Rename the extracted folder to `tbb`. - -NOTE: BEFORE YOU ATTEMPT TO CROSS-COMPILE TBB, DISCONNECT ANY DEVICES ADB WOULD DETECT. The tbb build process asks adb for a couple of strings, and if a device is plugged in extra characters get added that will cause ndk-build to fail with an error. - -From the tbb directory, execute the following commands. First, we build TBB using `ndk-build`. Then, the compiled libs are copied to a lib folder in the root of tbb directory. - -``` -cd jni -ndk-build target=android tbb tbbmalloc arch=arm -cd ../ -mkdir lib -cp `find . -name "*.so"` lib/ -``` - ####Oculus Mobile SDK The Oculus Mobile SDK is optional, for Gear VR support. It is not required to compile gvr-interface. @@ -111,7 +95,6 @@ To put the Gear VR Service into developer mode you need an application with an O Once the application is on your device, go to `Settings->Application Manager->Gear VR Service->Manage Storage`. Tap on `VR Service Version` six times. It will scan your device to verify that you have an osig file in an application on your device, and then it will let you enable Developer mode. - ###CMake We use CMake to generate the makefiles that compile and deploy the Android APKs to your device. In order to create Makefiles for the Android targets, CMake requires that some environment variables are set, and that other variables are passed to it when it is run. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 5f3e4c2228..88984a7f2d 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -91,12 +91,6 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. -####Intel Threading Building Blocks (TBB) - -Download the zip from the [TBB website](https://www.threadingbuildingblocks.org/). - -We recommend you extract it to %HIFI_LIB_DIR%\tbb. This will help our FindTBB cmake module find what it needs. You can place it wherever you like on your machine if you specify TBB_ROOT_DIR as an environment variable or a variable passed when cmake is run. - ####Zlib Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. From 27c6f80a61e978758fa40dbe9424f31c37827669 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 09:33:22 -0800 Subject: [PATCH 069/341] use md5 hash to verify downloaded externals --- cmake/externals/glm/CMakeLists.txt | 1 + cmake/externals/gverb/CMakeLists.txt | 1 + cmake/externals/soxr/CMakeLists.txt | 1 + cmake/externals/tbb/CMakeLists.txt | 4 ++++ 4 files changed, 7 insertions(+) diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index 1fa393e69e..1afa9a89e8 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -4,6 +4,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} URL http://pkgs.fedoraproject.org/repo/pkgs/glm/glm-0.9.5.4.zip/fab76fc982b256b46208e5c750ed456a/glm-0.9.5.4.zip + URL_MD5 fab76fc982b256b46208e5c750ed456a CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index c62284a133..4173efa073 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -8,6 +8,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/gverb-master.zip + URL_MD5 8b16d586390a2102804e46b87820dfc6 CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 49d7c7598a..2b00db883a 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -8,6 +8,7 @@ include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1.zip + URL_MD5 349b5b2f323a7380bc12186d98c77d1d CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_SHARED_LIBS=1 -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD ON ) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index cbf7d80c68..e5243edf8c 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -9,6 +9,7 @@ if (ANDROID) ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150209oss_src.tgz + URL_MD5 f09c9abe8ec74e6558c1f89cebbe2893 BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" @@ -18,10 +19,13 @@ if (ANDROID) else () if (APPLE) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_osx.tgz) + set(DOWNLOAD_MD5 3e683c19792582b61382e0d760ea5db2) elseif (WIN32) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_win.zip) + set(DOWNLOAD_MD5 e19c184f2bb0e944fc5f397f1e34ca84) else () set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150209oss_lin.tgz) + set(DOWNLOAD_MD5 d9c2a6f7807df364be44a8c3c05e8457) endif () ExternalProject_Add( From 7e04f8a491f487cf33fd431c41fb3cf9c05bb225 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 19 Feb 2015 09:52:58 -0800 Subject: [PATCH 070/341] Model almost working with Transform --- libraries/gpu/src/gpu/Transform.slh | 7 +++++-- libraries/render-utils/src/model.slv | 16 ++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 9666a4f258..3b0feb5ba1 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -12,7 +12,7 @@ struct TransformObject { mat4 _model; - mat4 _modelInverseTranspose; + mat4 _modelInverse; mat4 _modelView; mat4 _modelViewInverseTranspose; }; @@ -24,10 +24,13 @@ struct TransformCamera { }; vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { + return camera._projection * (object._modelView * pos); } - +vec3 transformDir(TransformCamera camera, TransformObject object, vec3 dir) { + return (object._modelViewInverseTranspose * vec4(dir, 0.0)).xyz; +} <@if GLPROFILE == PC_GL@> uniform transformObjectBuffer { diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 7f97e429d9..42fec40e55 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -36,8 +36,6 @@ void main(void) { void main(void) { - // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); // pass along the diffuse color gl_FrontColor = gl_Color; @@ -49,10 +47,12 @@ void main(void) { //gl_Position = ftransform(); //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; - //TransformCamera cam = getTransformCamera(); - /* TransformObject obj = getTransformObject(); - // gl_Position = transform(cam, obj, gl_Vertex); - */ - vec4 vPos = gl_ModelViewMatrix * gl_Vertex; - gl_Position = camera._projection * vPos; + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, gl_Vertex); + + // transform and store the normal for interpolation + normal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); + } From 6f055ca0d7fac78c6bf7cc146773b9b2ba8785cb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:01:40 -0800 Subject: [PATCH 071/341] add an external project to handle bullet --- cmake/externals/bullet/CMakeLists.txt | 36 +++++++++++++++++++++++++++ cmake/externals/glm/CMakeLists.txt | 5 +++- cmake/externals/gverb/CMakeLists.txt | 5 +++- cmake/externals/soxr/CMakeLists.txt | 5 +++- cmake/externals/tbb/CMakeLists.txt | 5 +++- cmake/macros/IncludeBullet.cmake | 16 ------------ interface/CMakeLists.txt | 8 +++--- libraries/entities/CMakeLists.txt | 6 ++++- libraries/physics/CMakeLists.txt | 9 ++++--- tests/physics/CMakeLists.txt | 6 ++++- 10 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 cmake/externals/bullet/CMakeLists.txt delete mode 100644 cmake/macros/IncludeBullet.cmake diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt new file mode 100644 index 0000000000..91a6a486b7 --- /dev/null +++ b/cmake/externals/bullet/CMakeLists.txt @@ -0,0 +1,36 @@ +set(EXTERNAL_NAME bullet) + +if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +endif () + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz + URL_MD5 70b3c8d202dee91a0854b4cbc88173e8 + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE TYPE "Path to bullet include directory") + +set(BULLET_LIB_DIR "${INSTALL_DIR}/lib") + +set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletDynamics.dylib CACHE TYPE "Bullet dynamics release library location") +set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") + +set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletCollision.dylib CACHE TYPE "Bullet collision release library location") +set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") + +set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libLinearMath.dylib CACHE TYPE "Bullet math release library location") +set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") + +set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftbody.dylib CACHE TYPE "Bullet softbody release library location") +set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") \ No newline at end of file diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index 1afa9a89e8..e1874f66e4 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -6,7 +6,10 @@ ExternalProject_Add( URL http://pkgs.fedoraproject.org/repo/pkgs/glm/glm-0.9.5.4.zip/fab76fc982b256b46208e5c750ed456a/glm-0.9.5.4.zip URL_MD5 fab76fc982b256b46208e5c750ed456a CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= - LOG_DOWNLOAD ON + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index 4173efa073..1e6cc8a567 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -10,7 +10,10 @@ ExternalProject_Add( URL http://hifi-public.s3.amazonaws.com/dependencies/gverb-master.zip URL_MD5 8b16d586390a2102804e46b87820dfc6 CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= - LOG_DOWNLOAD ON + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 2b00db883a..9ca540f49d 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -10,7 +10,10 @@ ExternalProject_Add( URL http://hifi-public.s3.amazonaws.com/dependencies/soxr-0.1.1.zip URL_MD5 349b5b2f323a7380bc12186d98c77d1d CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DBUILD_SHARED_LIBS=1 -DBUILD_TESTS=0 -DCMAKE_INSTALL_PREFIX:PATH= - LOG_DOWNLOAD ON + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index e5243edf8c..9bfb682128 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -14,7 +14,10 @@ if (ANDROID) BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake - LOG_DOWNLOAD ON + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 ) else () if (APPLE) diff --git a/cmake/macros/IncludeBullet.cmake b/cmake/macros/IncludeBullet.cmake deleted file mode 100644 index 186e84d1ab..0000000000 --- a/cmake/macros/IncludeBullet.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -# IncludeBullet.cmake -# -# Copyright 2014 High Fidelity, Inc. -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -macro(INCLUDE_BULLET) - find_package(Bullet REQUIRED) - include_directories("${BULLET_INCLUDE_DIRS}") - if (APPLE OR UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${BULLET_INCLUDE_DIRS}") - endif() -endmacro(INCLUDE_BULLET) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 7458a6c784..69beddaaaf 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -32,8 +32,6 @@ elseif (WIN32) set(GL_HEADERS "#include \n#include \n#include ") endif () -include_bullet() - # create the InterfaceConfig.h file based on GL_HEADERS above configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h") configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h") @@ -108,10 +106,14 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # set up the external glm library -add_dependency_external_projects(glm) +add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) +find_package(Bullet REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) + # link required hifi libraries link_hifi_libraries(shared octree environment gpu model fbx metavoxels networking entities avatars audio audio-client animation script-engine physics diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 156f3d1f09..944929dba6 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -7,6 +7,10 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -include_bullet() +add_dependency_external_projects(bullet) + +find_package(Bullet REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(avatars shared octree gpu model fbx networking animation) diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index c3dfcafa48..8929ab4fec 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -7,10 +7,11 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -include_bullet() -if (BULLET_FOUND) - target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) -endif (BULLET_FOUND) +add_dependency_external_projects(bullet) + +find_package(Bullet REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(shared fbx entities) include_hifi_library_headers(fbx) diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index 12cd9b8531..5dd1e270b8 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -6,7 +6,11 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -include_bullet() +add_dependency_external_projects(bullet) + +find_package(Bullet REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(shared physics) From 70a89680f5ae3694c0854796f0f884a6a74f13d7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:04:41 -0800 Subject: [PATCH 072/341] fix bullet include to match previous format --- cmake/externals/bullet/CMakeLists.txt | 2 +- libraries/physics/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 91a6a486b7..dd293da059 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -19,7 +19,7 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include CACHE TYPE "Path to bullet include directory") +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE TYPE "Path to bullet include directory") set(BULLET_LIB_DIR "${INSTALL_DIR}/lib") diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 8929ab4fec..9229bbeca7 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) add_dependency_external_projects(bullet) find_package(Bullet REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} PUBLIC SYSTEM ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(shared fbx entities) From d563c80ca095e14cec39aeaadaebf0d3f70423ea Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:12:41 -0800 Subject: [PATCH 073/341] handle bullet external project on unix/android --- cmake/externals/bullet/CMakeLists.txt | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index dd293da059..479d921bf4 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -9,7 +9,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz URL_MD5 70b3c8d202dee91a0854b4cbc88173e8 - CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 @@ -23,14 +23,24 @@ set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE TYPE set(BULLET_LIB_DIR "${INSTALL_DIR}/lib") -set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletDynamics.dylib CACHE TYPE "Bullet dynamics release library location") -set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") +if (APPLE OR UNIX OR ANDROID) + if (APPLE) + set(SHARED_LIB_EXT "dylib") + else () + set(SHARED_LIB_EXT "so") + endif () + + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletDynamics.${SHARED_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") -set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletCollision.dylib CACHE TYPE "Bullet collision release library location") -set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletCollision.${SHARED_LIB_EXT} CACHE TYPE "Bullet collision release library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") -set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libLinearMath.dylib CACHE TYPE "Bullet math release library location") -set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libLinearMath.${SHARED_LIB_EXT} CACHE TYPE "Bullet math release library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") -set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftbody.dylib CACHE TYPE "Bullet softbody release library location") -set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") \ No newline at end of file + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftbody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") +elseif (WIN32) + +endif () \ No newline at end of file From 03809131a4f7017935fe9973f0ed890efa942e8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:39:48 -0800 Subject: [PATCH 074/341] log install to be able to confirm installed files --- cmake/externals/bullet/CMakeLists.txt | 1 - cmake/externals/gverb/CMakeLists.txt | 1 - cmake/externals/soxr/CMakeLists.txt | 1 - cmake/externals/tbb/CMakeLists.txt | 1 - 4 files changed, 4 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 479d921bf4..32d4d884b4 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -13,7 +13,6 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 - LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index 1e6cc8a567..cc7be74c2f 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -13,7 +13,6 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 - LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 9ca540f49d..03b43074c6 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -13,7 +13,6 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 - LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 9bfb682128..b26adc559c 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -17,7 +17,6 @@ if (ANDROID) LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 - LOG_INSTALL 1 ) else () if (APPLE) From 71b273ceecfdf65d6ab91608c030cb01e85610dc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:42:28 -0800 Subject: [PATCH 075/341] fix order for found result in bullet find module --- cmake/modules/FindBullet.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/modules/FindBullet.cmake b/cmake/modules/FindBullet.cmake index c4f63860f2..9ef25f7e1e 100644 --- a/cmake/modules/FindBullet.cmake +++ b/cmake/modules/FindBullet.cmake @@ -85,9 +85,7 @@ set(BULLET_INCLUDE_DIRS ${BULLET_INCLUDE_DIR}) set(BULLET_LIBRARIES ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${BULLET_SOFTBODY_LIBRARY}) find_package_handle_standard_args(Bullet "Could NOT find Bullet, try to set the path to Bullet root folder in the system variable BULLET_ROOT_DIR" - BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY BULLET_INCLUDE_DIRS + BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY BULLET_SOFTBODY_LIBRARY BULLET_LIBRARIES -) - - +) \ No newline at end of file From 2cdb8edbbf18019c4a688b85d9ed525aaf00acf7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 12:44:49 -0800 Subject: [PATCH 076/341] fix casing for libBulletSoftBody --- cmake/externals/bullet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 32d4d884b4..dfd84ecda2 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -38,7 +38,7 @@ if (APPLE OR UNIX OR ANDROID) set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libLinearMath.${SHARED_LIB_EXT} CACHE TYPE "Bullet math release library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftbody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftBody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") elseif (WIN32) From 6b08b2993ae2bdef6a995db29cf2d0b3ec1f1f6f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:03:16 -0800 Subject: [PATCH 077/341] fix for bullet system include to silence warnings --- interface/CMakeLists.txt | 2 +- libraries/entities/CMakeLists.txt | 2 +- libraries/physics/CMakeLists.txt | 2 +- tests/physics/CMakeLists.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 69beddaaaf..ad42dd97cf 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -111,7 +111,7 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) find_package(Bullet REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) # link required hifi libraries diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 944929dba6..e57bcf67fa 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) add_dependency_external_projects(bullet) find_package(Bullet REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(avatars shared octree gpu model fbx networking animation) diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 9229bbeca7..5e94513da4 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -10,7 +10,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) add_dependency_external_projects(bullet) find_package(Bullet REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC SYSTEM ${BULLET_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(shared fbx entities) diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index 5dd1e270b8..888b158035 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) add_dependency_external_projects(bullet) find_package(Bullet REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE SYSTEM ${BULLET_INCLUDE_DIRS}) +target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) link_hifi_libraries(shared physics) From d185c775a43a6bd08c4dee0e39ba0b49d30900d2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:17:39 -0800 Subject: [PATCH 078/341] fix install step for OS X bullet --- cmake/externals/bullet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index dfd84ecda2..3166c7b2f3 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -9,7 +9,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz URL_MD5 70b3c8d202dee91a0854b4cbc88173e8 - CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From cbc6ae98d87a1f7040d178919a4f2439b0782f7a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:22:33 -0800 Subject: [PATCH 079/341] groundwork for windows support in bullet external project --- cmake/externals/bullet/CMakeLists.txt | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 3166c7b2f3..d82cbd5fad 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -1,15 +1,25 @@ set(EXTERNAL_NAME bullet) if (ANDROID) - set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + set(PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +elseif (WIN32) + set(PLATFORM_CMAKE_ARGS "-DUSE_MSVC_RUNTIME_LIBRARY_DLL=1") +endif () + +if (WIN32) + set(DOWNLOAD_URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip) + set(DOWNLOAD_MD5 f5e8914fc9064ad32e0d62d19d33d977) +else () + set(DOWNLOAD_URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz) + set(DOWNLOAD_MD5 70b3c8d202dee91a0854b4cbc88173e8) endif () include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz - URL_MD5 70b3c8d202dee91a0854b4cbc88173e8 - CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + URL ${DOWNLOAD_URL} + URL_MD5 ${DOWNLOAD_MD5} + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 721be462f57e8d1767e0d31e22a6b179661600b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:40:17 -0800 Subject: [PATCH 080/341] attempt to handle windows in bullet external project --- cmake/externals/bullet/CMakeLists.txt | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index d82cbd5fad..de17c71322 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -19,7 +19,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} URL_MD5 ${DOWNLOAD_MD5} - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 @@ -39,17 +39,23 @@ if (APPLE OR UNIX OR ANDROID) set(SHARED_LIB_EXT "so") endif () - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletDynamics.${SHARED_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") + set(LIB_PREFIX "lib") +elseif (WIN32) + set(SHARED_LIB_EXT "lib") +else () + message(STATUS "Your OS is not handled by our Bullet external project CMakeLists.txt. Please install Bullet yourself and pass -DGET_BULLET=0 when running CMake.") +endif () + +if (DEFINED SHARED_LIB_EXT) + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${SHARED_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletCollision.${SHARED_LIB_EXT} CACHE TYPE "Bullet collision release library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${SHARED_LIB_EXT} CACHE TYPE "Bullet collision release library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libLinearMath.${SHARED_LIB_EXT} CACHE TYPE "Bullet math release library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${SHARED_LIB_EXT} CACHE TYPE "Bullet math release library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/libBulletSoftBody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") -elseif (WIN32) - endif () \ No newline at end of file From 01c92ba94dc7da68afd5de2540ad9ecc2b204225 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:53:48 -0800 Subject: [PATCH 081/341] don't attempt to build shared bullet libs on windows --- cmake/externals/bullet/CMakeLists.txt | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index de17c71322..12ad076b7b 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -1,9 +1,13 @@ set(EXTERNAL_NAME bullet) -if (ANDROID) - set(PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") -elseif (WIN32) +if (WIN32) set(PLATFORM_CMAKE_ARGS "-DUSE_MSVC_RUNTIME_LIBRARY_DLL=1") +else () + set(PLATFORM_CMAKE_ARGS "-DBUILD_SHARED_LIBS=1") + + if (ANDROID) + set(PLATFORM_CMAKE_ARGS "${PLATFORM_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + endif() endif () if (WIN32) @@ -34,28 +38,28 @@ set(BULLET_LIB_DIR "${INSTALL_DIR}/lib") if (APPLE OR UNIX OR ANDROID) if (APPLE) - set(SHARED_LIB_EXT "dylib") + set(BULLET_LIB_EXT "dylib") else () - set(SHARED_LIB_EXT "so") + set(BULLET_LIB_EXT "so") endif () set(LIB_PREFIX "lib") elseif (WIN32) - set(SHARED_LIB_EXT "lib") + set(BULLET_LIB_EXT "lib") else () message(STATUS "Your OS is not handled by our Bullet external project CMakeLists.txt. Please install Bullet yourself and pass -DGET_BULLET=0 when running CMake.") endif () if (DEFINED SHARED_LIB_EXT) - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${SHARED_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${SHARED_LIB_EXT} CACHE TYPE "Bullet collision release library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE TYPE "Bullet collision release library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${SHARED_LIB_EXT} CACHE TYPE "Bullet math release library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE TYPE "Bullet math release library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${SHARED_LIB_EXT} CACHE TYPE "Bullet softbody release library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE TYPE "Bullet softbody release library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") endif () \ No newline at end of file From d47a114f23f01b19d77c5ff6df0679314ea52872 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 13:57:31 -0800 Subject: [PATCH 082/341] actually remove BUILD_SHARED_LIBS from combo command --- cmake/externals/bullet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 12ad076b7b..8738212450 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -23,7 +23,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} URL_MD5 ${DOWNLOAD_MD5} - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DBUILD_SHARED_LIBS=1 -DUSE_GLM=0 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLM=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From a0a4882ed66c251e0d6a93f313114530fad55e49 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 14:18:05 -0800 Subject: [PATCH 083/341] shorten externals binary dir path --- CMakeLists.txt | 14 +++------- cmake/macros/SetupExternalsBinaryDir.cmake | 30 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 cmake/macros/SetupExternalsBinaryDir.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 924d0367c2..e216d304c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,17 +110,6 @@ set(HIFI_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(MACRO_DIR "${HIFI_CMAKE_DIR}/macros") set(EXTERNAL_PROJECT_DIR "${HIFI_CMAKE_DIR}/externals") -STRING(REGEX REPLACE " " "-" CMAKE_GENERATOR_FOLDER_NAME ${CMAKE_GENERATOR}) - -set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") -if (ANDROID) - set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}") -else () - set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR_FOLDER_NAME}") -endif () - -set_property(DIRECTORY PROPERTY EP_PREFIX "project") - file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake") foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS}) include(${CUSTOM_MACRO}) @@ -133,6 +122,9 @@ if (ANDROID) endforeach() endif () +set_property(DIRECTORY PROPERTY EP_PREFIX "project") +setup_externals_binary_dir() + if (WIN32) add_paths_to_lib_paths("${QT_DIR}/bin") endif () diff --git a/cmake/macros/SetupExternalsBinaryDir.cmake b/cmake/macros/SetupExternalsBinaryDir.cmake new file mode 100644 index 0000000000..0e59328a23 --- /dev/null +++ b/cmake/macros/SetupExternalsBinaryDir.cmake @@ -0,0 +1,30 @@ +# +# SetupExternalsBinaryDir.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 19, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(SETUP_EXTERNALS_BINARY_DIR) + + # get a short name for the generator to use in the path + STRING(REGEX REPLACE " " "-" CMAKE_GENERATOR_FOLDER_NAME ${CMAKE_GENERATOR}) + + if (CMAKE_GENERATOR_FOLDER_NAME STREQUAL "Unix-Makefiles") + set(CMAKE_GENERATOR_FOLDER_NAME "makefiles") + elseif (CMAKE_GENERATOR_FOLDER_NAME STREQUAL "Visual-Studio-12") + set(CMAKE_GENERATOR_FOLDER_NAME "vs12") + endif () + + set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") + if (ANDROID) + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}") + else () + set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/${CMAKE_GENERATOR_FOLDER_NAME}") + endif () + +endmacro() \ No newline at end of file From a3d370f01f9e3bdb911efa6e4cb1bdc3d03b9ddd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 14:33:31 -0800 Subject: [PATCH 084/341] more path shortening for build of external projects --- CMakeLists.txt | 3 ++- cmake/externals/bullet/CMakeLists.txt | 1 + cmake/externals/glm/CMakeLists.txt | 1 + cmake/externals/gverb/CMakeLists.txt | 1 + cmake/externals/soxr/CMakeLists.txt | 1 + cmake/macros/SetupExternalsBinaryDir.cmake | 2 +- 6 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e216d304c8..563ece524f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,7 +122,8 @@ if (ANDROID) endforeach() endif () -set_property(DIRECTORY PROPERTY EP_PREFIX "project") +set(EXTERNAL_PROJECT_PREFIX "project") +set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX}) setup_externals_binary_dir() if (WIN32) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 8738212450..1cf82032bf 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -27,6 +27,7 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index e1874f66e4..a6f74b52fe 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -5,6 +5,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL http://pkgs.fedoraproject.org/repo/pkgs/glm/glm-0.9.5.4.zip/fab76fc982b256b46208e5c750ed456a/glm-0.9.5.4.zip URL_MD5 fab76fc982b256b46208e5c750ed456a + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= LOG_DOWNLOAD 1 LOG_CONFIGURE 1 diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index cc7be74c2f..c7791c2424 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -10,6 +10,7 @@ ExternalProject_Add( URL http://hifi-public.s3.amazonaws.com/dependencies/gverb-master.zip URL_MD5 8b16d586390a2102804e46b87820dfc6 CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index 03b43074c6..c2f5163f94 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -13,6 +13,7 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) diff --git a/cmake/macros/SetupExternalsBinaryDir.cmake b/cmake/macros/SetupExternalsBinaryDir.cmake index 0e59328a23..c066363455 100644 --- a/cmake/macros/SetupExternalsBinaryDir.cmake +++ b/cmake/macros/SetupExternalsBinaryDir.cmake @@ -20,7 +20,7 @@ macro(SETUP_EXTERNALS_BINARY_DIR) set(CMAKE_GENERATOR_FOLDER_NAME "vs12") endif () - set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-externals") + set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-ext") if (ANDROID) set(EXTERNALS_BINARY_DIR "${EXTERNALS_BINARY_ROOT_DIR}/android/${CMAKE_GENERATOR_FOLDER_NAME}") else () From afae7297e760c859202260391c9077c5a666eaa4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 14:41:23 -0800 Subject: [PATCH 085/341] adjustements to build guides to remove bullet --- BUILD.md | 2 +- BUILD_WIN.md | 29 ----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/BUILD.md b/BUILD.md index f3e9c81b78..dd2b65fb3b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -4,12 +4,12 @@ * [Qt](http://qt-project.org/downloads) ~> 5.3.2 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. -* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 #### CMake External Project Dependencies The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-externals`. Should you want to force a re-download and re-compile of all externals, just remove the `build-externals` folder. +* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 * [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [gverb](https://github.com/highfidelity/gverb) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 88984a7f2d..a2d87623a2 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -119,35 +119,6 @@ Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\ Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` -####Bullet - -Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself. - -* Download the zip file and extract into a temporary folder -* Create a directory named cmakebuild. Bullet comes with a build\ directory by default, however, that directory is intended for use with premake, and considering premake doesn't support VS2013, we prefer to run the cmake build on its own directory. -* Make the following modifications to Bullet's source: - 1. In file: Extras\HACD\hacdICHull.cpp --- in line: 17 --- insert: #include <algorithm> - 2. In file: src\MiniCL\cl_MiniCL_Defs.h --- comment lines 364 to 372 - 3. In file: CMakeLists.txt set to ON the option USE_MSVC_RUNTIME_LIBRARY_DLL in line 27 - -Then create the Visual Studio solution and build the libraries - run the following commands from a Visual Studio 2013 command prompt, from within the cmakebuild directory created before: - -```shell -cmake .. -G "Visual Studio 12" -msbuild BULLET_PHYSICS.sln /p:Configuration=Debug -``` - -This will create Debug libraries in cmakebuild\lib\Debug. You can replace Debug with Release in the msbuild command and that will generate Release libraries in cmakebuild\lib\Release. - -You now have Bullet libraries compiled, now you need to put them in the right place for hifi to find them: - -* Create a directory named bullet\ inside your %HIFI_LIB_DIR% -* Create two directores named lib\ and include\ inside bullet\ -* Copy all the contents inside src\ from the bullet unzip path into %HIFI_LIB_DIR%\bullet\include\ -* Copy all the contents inside cmakebuild\lib\ into %HIFI_LIB_DIR\bullet\lib - -_Note that the INSTALL target should handle the copying of files into an install directory automatically, however, without modifications to Cmake, the install target didn't work right for me, please update this instructions if you get that working right - Leo <leo@highfidelity.io>_ - ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. From 799cee32aa074f71b82ac04115be24373a873dd7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 14:43:34 -0800 Subject: [PATCH 086/341] remove freeglut from build guides, no longer needed --- BUILD_WIN.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index a2d87623a2..ae71970466 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -2,7 +2,6 @@ Please read the [general build guide](BUILD.md) for information on dependencies ###Windows Specific Dependencies * [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 -* [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1 * [zLib](http://www.zlib.net/) ~> 1.2.8 * (remember that you need all other dependencies listed in [BUILD.md](BUILD.md)) @@ -46,13 +45,6 @@ We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets req The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir - -> bullet - -> include - -> lib - -> freeglut - -> bin - -> include - -> lib -> glew -> bin -> include @@ -61,9 +53,6 @@ The recommended route for CMake to find the external dependencies is to place al -> bin -> include -> lib - -> tbb - -> include - -> lib -> zlib -> include -> lib @@ -107,12 +96,6 @@ Add to the PATH: `%HIFI_LIB_DIR%\zlib` Important! This should be added at the beginning of the path, not the end (your system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". -####freeglut - -Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. - -Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` - ####GLEW Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). From d08142d37dfa2be09310b40e8db0fc0abda280a4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 19 Feb 2015 15:12:13 -0800 Subject: [PATCH 087/341] replacing glTRansform by gpu/Transform features --- libraries/gpu/src/gpu/Context.h | 3 +-- libraries/gpu/src/gpu/GLBackend.cpp | 11 ++++---- libraries/gpu/src/gpu/Transform.slh | 25 +++++++++++++++---- libraries/render-utils/src/model.slv | 21 +--------------- libraries/render-utils/src/model_lightmap.slv | 15 +++++++---- .../src/model_lightmap_normal_map.slv | 15 ++++++++--- .../render-utils/src/model_normal_map.slv | 17 ++++++++++--- libraries/render-utils/src/model_shadow.slv | 7 ++++-- libraries/render-utils/src/skin_model.slv | 15 ++++++++--- .../src/skin_model_normal_map.slv | 15 +++++++++-- .../render-utils/src/skin_model_shadow.slv | 9 ++++++- libraries/shared/src/Transform.h | 14 +++++++++++ 12 files changed, 113 insertions(+), 54 deletions(-) diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index c426a28d90..bd5da57504 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -33,8 +33,6 @@ public: public: Mat4 _model; Mat4 _modelInverse; - Mat4 _modelView; - Mat4 _modelViewInverseTranspose; }; class TransformCamera { @@ -42,6 +40,7 @@ public: Mat4 _projection; Mat4 _view; Mat4 _viewInverse; + Mat4 _projectionViewUntranslated; }; template< typename T > diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 680ffe64b0..f4f73abb45 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -484,11 +484,10 @@ void GLBackend::updateTransform() { _transform._model.getInverseMatrix(_transform._transformObject._modelInverse); } - if (_transform._invalidView || _transform._invalidModel) { - Transform mvx; - Transform::inverseMult(mvx, _transform._view, _transform._model); - mvx.getMatrix(_transform._transformObject._modelView); - mvx.getInverseTransposeMatrix(_transform._transformObject._modelViewInverseTranspose); + if (_transform._invalidView || _transform._invalidProj) { + Mat4 viewUntranslated = _transform._transformCamera._view; + // viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; } if (_transform._invalidView || _transform._invalidProj) { @@ -499,7 +498,7 @@ void GLBackend::updateTransform() { CHECK_GL_ERROR(); } - if (_transform._invalidView || _transform._invalidModel) { + if (_transform._invalidModel) { glBindBufferBase(GL_UNIFORM_BUFFER, 6, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 3b0feb5ba1..d2c1390294 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -13,23 +13,38 @@ struct TransformObject { mat4 _model; mat4 _modelInverse; - mat4 _modelView; - mat4 _modelViewInverseTranspose; }; struct TransformCamera { mat4 _projection; mat4 _view; mat4 _viewInverse; + mat4 _projectionViewUntranslated; }; vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { - - return camera._projection * (object._modelView * pos); + /* vec4 res = object._model * pos; + res += pos.w * camera._viewInverse[3]; + return camera._projectionViewUntranslated * res; +*/ + return camera._projectionViewUntranslated * object._model * pos; + // return camera._projection * camera._view * object._model * pos; } vec3 transformDir(TransformCamera camera, TransformObject object, vec3 dir) { - return (object._modelViewInverseTranspose * vec4(dir, 0.0)).xyz; + vec3 mIr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); + vec3 mIr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); + vec3 mIr2 = vec3(object._modelInverse[0].z, object._modelInverse[1].z, object._modelInverse[2].z); + + vec3 mvIc0 = vec3(dot(camera._viewInverse[0].xyz, mIr0), dot(camera._viewInverse[0].xyz, mIr1), dot(camera._viewInverse[0].xyz, mIr2)); + vec3 mvIc1 = vec3(dot(camera._viewInverse[1].xyz, mIr0), dot(camera._viewInverse[1].xyz, mIr1), dot(camera._viewInverse[1].xyz, mIr2)); + vec3 mvIc2 = vec3(dot(camera._viewInverse[2].xyz, mIr0), dot(camera._viewInverse[2].xyz, mIr1), dot(camera._viewInverse[2].xyz, mIr2)); + + vec3 result = vec3(dot(mvIc0, dir), + dot(mvIc1, dir), + dot(mvIc2, dir)); + + return result; } <@if GLPROFILE == PC_GL@> diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 42fec40e55..5f2bfe5f9d 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -18,22 +18,6 @@ uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal varying vec4 normal; -/* -void main(void) { - // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - - // pass along the diffuse color - gl_FrontColor = gl_Color; - - // and the texture coordinates - gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - - // use standard pipeline transform - gl_Position = gl_ModelViewProjectionMatrix * vec4(vin_position, 1.0); -} -*/ - void main(void) { @@ -42,11 +26,8 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - + // use standard pipeline transform - //gl_Position = ftransform(); - //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 53da84de73..3adca397c2 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; @@ -25,9 +27,6 @@ varying vec4 normal; varying vec2 interpolatedTexcoord1; void main(void) { - // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - // pass along the diffuse color gl_FrontColor = gl_Color; @@ -35,8 +34,14 @@ void main(void) { gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); // interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0)).xy; interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; - + // use standard pipeline transform - gl_Position = ftransform(); + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, gl_Vertex); + + // transform and store the normal for interpolation + normal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index f4f5e72167..be86655f75 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; @@ -32,8 +34,8 @@ varying vec2 interpolatedTexcoord1; void main(void) { // transform and store the normal and tangent for interpolation - interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); - interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); + //interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); + //interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); // pass along the diffuse color gl_FrontColor = gl_Color; @@ -43,5 +45,12 @@ void main(void) { interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy; // use standard pipeline transform - gl_Position = ftransform(); + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, gl_Vertex); + + // transform and store the normal for interpolation + interpolatedNormal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); + interpolatedTangent = vec4(normalize(transformDir(cam, obj, tangent)), 0.0); } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index 582f1b1abb..dbb87473b8 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; @@ -27,8 +29,8 @@ varying vec4 interpolatedTangent; void main(void) { // transform and store the normal and tangent for interpolation - interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); - interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); + //interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0); + //interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0); // pass along the diffuse color gl_FrontColor = gl_Color; @@ -36,6 +38,13 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - // use standard pipeline transform - gl_Position = ftransform(); + // use standard pipeline transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, gl_Vertex); + + // transform and store the normal for interpolation + interpolatedNormal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); + interpolatedTangent = vec4(normalize(transformDir(cam, obj, tangent)), 0.0); } diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv index b05a92b155..5d386d4d4c 100755 --- a/libraries/render-utils/src/model_shadow.slv +++ b/libraries/render-utils/src/model_shadow.slv @@ -11,8 +11,11 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> void main(void) { - // just use standard pipeline transform - gl_Position = ftransform(); + // use standard pipeline transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + gl_Position = transform(cam, obj, gl_Vertex); } diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index 737fa85bf0..08aff5724b 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; @@ -34,14 +36,19 @@ void main(void) { position += clusterMatrix * gl_Vertex * clusterWeight; normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; } - - normal = normalize(gl_ModelViewMatrix * normal); - + // pass along the diffuse color gl_FrontColor = gl_Color; // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - gl_Position = gl_ModelViewProjectionMatrix * position; + // use standard pipeline transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, position); + + // transform and store the normal for interpolation + normal = vec4(normalize(transformDir(cam, obj, normal.xyz)), 0.0); } diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 3db63f9d98..404e9c625d 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; @@ -42,8 +44,8 @@ void main(void) { interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; interpolatedTangent += clusterMatrix * vec4(tangent, 0.0) * clusterWeight; } - interpolatedNormal = gl_ModelViewMatrix * interpolatedNormal; - interpolatedTangent = gl_ModelViewMatrix * interpolatedTangent; + // interpolatedNormal = gl_ModelViewMatrix * interpolatedNormal; + // interpolatedTangent = gl_ModelViewMatrix * interpolatedTangent; // pass along the diffuse color gl_FrontColor = gl_Color; @@ -52,4 +54,13 @@ void main(void) { gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition; + + // use standard pipeline transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, interpolatedPosition); + + interpolatedNormal = vec4(normalize(transformDir(cam, obj, interpolatedNormal.xyz)), 0.0); + interpolatedTangent = vec4(normalize(transformDir(cam, obj, interpolatedTangent.xyz)), 0.0); } diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv index 3625d4006a..ee21f96f45 100755 --- a/libraries/render-utils/src/skin_model_shadow.slv +++ b/libraries/render-utils/src/skin_model_shadow.slv @@ -12,6 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Transform.slh@> + const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; @@ -27,5 +29,10 @@ void main(void) { float clusterWeight = clusterWeights[i]; position += clusterMatrix * gl_Vertex * clusterWeight; } - gl_Position = gl_ModelViewProjectionMatrix * position; + + // use standard pipeline transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + + gl_Position = transform(cam, obj, position); } diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 4f5f441170..ec4513e51c 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -92,6 +92,9 @@ public: Mat4& getInverseMatrix(Mat4& result) const; Mat4& getInverseTransposeMatrix(Mat4& result) const; + Mat4& getRotationScaleMatrix(Mat4& result) const; + Mat4& getRotationScaleMatrixInverse(Mat4& result) const; + Transform& evalInverse(Transform& result) const; static void evalRotationScale(Quat& rotation, Vec3& scale, const Mat3& rotationScaleMatrix); @@ -336,6 +339,17 @@ inline Transform::Mat4& Transform::getInverseTransposeMatrix(Transform::Mat4& re return result; } +inline Transform::Mat4& Transform::getRotationScaleMatrix(Mat4& result) const { + getMatrix(result); + result[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + return result; +} + +inline Transform::Mat4& Transform::getRotationScaleMatrixInverse(Mat4& result) const { + getInverseMatrix(result); + result[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + return result; +} inline void Transform::evalFromRawMatrix(const Mat4& matrix) { // for now works only in the case of TRS transformation From c3b9198ec393265e9b6d343a75ef9f0ec63ce1a1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 15:19:52 -0800 Subject: [PATCH 088/341] cleanup handling of external projects if OS not handled --- cmake/externals/bullet/CMakeLists.txt | 7 +- cmake/externals/tbb/CMakeLists.txt | 23 +-- cmake/externals/zlib/CMakeLists.txt | 22 +++ .../AddDependencyExternalProjects.cmake | 31 +++- cmake/modules/FindZLIB.cmake | 162 ++++++++++++++++++ interface/CMakeLists.txt | 2 +- 6 files changed, 226 insertions(+), 21 deletions(-) create mode 100644 cmake/externals/zlib/CMakeLists.txt create mode 100644 cmake/modules/FindZLIB.cmake diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 1cf82032bf..38bf031387 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -33,7 +33,6 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE TYPE "Path to bullet include directory") set(BULLET_LIB_DIR "${INSTALL_DIR}/lib") @@ -47,8 +46,6 @@ if (APPLE OR UNIX OR ANDROID) set(LIB_PREFIX "lib") elseif (WIN32) set(BULLET_LIB_EXT "lib") -else () - message(STATUS "Your OS is not handled by our Bullet external project CMakeLists.txt. Please install Bullet yourself and pass -DGET_BULLET=0 when running CMake.") endif () if (DEFINED SHARED_LIB_EXT) @@ -63,4 +60,8 @@ if (DEFINED SHARED_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE TYPE "Bullet softbody release library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") +endif () + +if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE TYPE "Path to bullet include directory") endif () \ No newline at end of file diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index b26adc559c..39ec4aa8f2 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -43,7 +43,6 @@ endif () ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") if (APPLE) set(_TBB_APPLE_LIB_DIR "${SOURCE_DIR}/lib/libc++") @@ -85,14 +84,18 @@ elseif (UNIX) elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1) set(_TBB_LINUX_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.1") else () - message(FATAL_ERROR "Could not find a compatible version of Threading Building Blocks library for your compiler.") + message(STATUS "Could not find a compatible version of Threading Building Blocks library for your compiler.") endif () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") - -else () - message(STATUS "Your OS is not handled by our TBB external project CMakeLists.txt. Please install TBB yourself and pass -DGET_TBB=0 when running CMake.") -endif () \ No newline at end of file + if (DEFINED _TBB_LINUX_LIB_DIR) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") + endif () +endif () + +if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE) + + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") +endif () \ No newline at end of file diff --git a/cmake/externals/zlib/CMakeLists.txt b/cmake/externals/zlib/CMakeLists.txt new file mode 100644 index 0000000000..af980484be --- /dev/null +++ b/cmake/externals/zlib/CMakeLists.txt @@ -0,0 +1,22 @@ +set(EXTERNAL_NAME zlib) + +include(ExternalProject) + +if (WIN32) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://zlib.net/zlib128-dll.zip + URL_MD5 42eccc2af5bac6b7a1188d7817d03549 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + + set(${EXTERNAL_NAME_UPPER}_LIBRARY ${SOURCE_DIR}/lib/zdll.lib CACHE TYPE "Location of zlib library") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE TYPE "Location of zlib includes") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR} CACHE TYPE "Location of zlib DLL") +endif () + diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index 72dbad6639..816036fc81 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -14,14 +14,31 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) foreach(_PROJ_NAME ${ARGN}) string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) - - if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) - if (NOT TARGET ${_PROJ_NAME}) - add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME}) - endif () - - add_dependencies(${TARGET_NAME} ${_PROJ_NAME}) + # has the user told us they specific don't want this as an external project? + if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) + # have we already detected we can't have this as external project on this OS? + if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${EXTERNAL_NAME_UPPER}_EXTERNAL_PROJECT) + # have we already setup the target? + if (NOT TARGET ${_PROJ_NAME}) + add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME}) + + # did we end up adding an external project target? + if (NOT TARGET ${_PROJ_NAME}) + set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT FALSE CACHE TYPE "Presence of ${_PROJ_NAME} as external target") + + message(STATUS "${_PROJ_NAME} was not added as an external project target for your OS." + " Either your system should already have the external library or you will need to install it separately.") + else () + set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT TRUE CACHE TYPE "Presence of ${_PROJ_NAME} as external target") + endif () + endif () + + if (TARGET ${_PROJ_NAME}) + add_dependencies(${TARGET_NAME} ${_PROJ_NAME}) + endif () + + endif () endif () endforeach() diff --git a/cmake/modules/FindZLIB.cmake b/cmake/modules/FindZLIB.cmake new file mode 100644 index 0000000000..f052939d04 --- /dev/null +++ b/cmake/modules/FindZLIB.cmake @@ -0,0 +1,162 @@ +#.rst: +# FindZLIB +# -------- +# +# Find the native ZLIB includes and library. +# +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines :prop_tgt:`IMPORTED` target ``ZLIB::ZLIB``, if +# ZLIB has been found. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# :: +# +# ZLIB_INCLUDE_DIRS - where to find zlib.h, etc. +# ZLIB_LIBRARIES - List of libraries when using zlib. +# ZLIB_FOUND - True if zlib found. +# +# :: +# +# ZLIB_VERSION_STRING - The version of zlib found (x.y.z) +# ZLIB_VERSION_MAJOR - The major version of zlib +# ZLIB_VERSION_MINOR - The minor version of zlib +# ZLIB_VERSION_PATCH - The patch version of zlib +# ZLIB_VERSION_TWEAK - The tweak version of zlib +# +# Backward Compatibility +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# The following variable are provided for backward compatibility +# +# :: +# +# ZLIB_MAJOR_VERSION - The major version of zlib +# ZLIB_MINOR_VERSION - The minor version of zlib +# ZLIB_PATCH_VERSION - The patch version of zlib +# +# Hints +# ^^^^^ +# +# A user may set ``ZLIB_ROOT`` to a zlib installation root to tell this +# module where to look. + +#============================================================================= +# Copyright 2000-2014 Kitware, Inc. +# Copyright 2000-2011 Insight Software Consortium +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +# Modified on 2/19/2015 by Stephen Birarda +# The High Fidelity modification adds a ZLIB_DLL_PATH variable for fixup_bundle on windows + +set(_ZLIB_SEARCHES) + +# Search ZLIB_ROOT first if it is set. +if(ZLIB_ROOT) + set(_ZLIB_SEARCH_ROOT PATHS ${ZLIB_ROOT} NO_DEFAULT_PATH) + list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT) +endif() + +# Normal search. +set(_ZLIB_SEARCH_NORMAL + PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]" + "$ENV{PROGRAMFILES}/zlib" + ) +list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL) + +set(ZLIB_NAMES z zlib zdll zlib1 zlibd zlibd1) + +# Try each search configuration. +foreach(search ${_ZLIB_SEARCHES}) + find_path(ZLIB_INCLUDE_DIR NAMES zlib.h ${${search}} PATH_SUFFIXES include) + find_library(ZLIB_LIBRARY NAMES ${ZLIB_NAMES} ${${search}} PATH_SUFFIXES lib) + + if (WIN32) + find_path(ZLIB_DLL_PATH NAMES zlib.dll ${${search}} PATH_SUFFIXES bin) + endif () +endforeach() + +mark_as_advanced(ZLIB_LIBRARY ZLIB_INCLUDE_DIR) + +if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h") + file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$") + + string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}") + string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}") + string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}") + set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}") + + # only append a TWEAK version if it exists: + set(ZLIB_VERSION_TWEAK "") + if( "${ZLIB_H}" MATCHES "ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)") + set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}") + set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}") + endif() + + set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}") + set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}") + set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}") +endif() + +set(ZLIB_REQUIREMENTS ZLIB_LIBRARY ZLIB_INCLUDE_DIR VERSION_VAR ZLIB_VERSION_STRING) +if (WIN32) + list(APPEND ZLIB_REQUIREMENTS ZLIB_DLL_PATH) +endif () + +# handle the QUIETLY and REQUIRED arguments and set ZLIB_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZLIB REQUIRED_VARS ${ZLIB_REQUIREMENTS}) + +if(ZLIB_FOUND) + set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) + set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) + + if(NOT TARGET ZLIB::ZLIB) + add_library(ZLIB::ZLIB UNKNOWN IMPORTED) + set_target_properties(ZLIB::ZLIB PROPERTIES + IMPORTED_LOCATION "${ZLIB_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") + endif() + + if (WIN32) + add_path_to_lib_paths(${ZLIB_DLL_PATH}) + endif () +endif() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ad42dd97cf..c54199dfe8 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -106,7 +106,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # set up the external glm library -add_dependency_external_projects(glm bullet) +add_dependency_external_projects(glm bullet zlib) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) From 63d4538b76ffb0779d82433879c6de6af12df23b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 15:22:37 -0800 Subject: [PATCH 089/341] fix ZLIB dll find, bullet check --- cmake/externals/bullet/CMakeLists.txt | 2 +- cmake/modules/FindZLIB.cmake | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 38bf031387..e46cb093d4 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -48,7 +48,7 @@ elseif (WIN32) set(BULLET_LIB_EXT "lib") endif () -if (DEFINED SHARED_LIB_EXT) +if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") diff --git a/cmake/modules/FindZLIB.cmake b/cmake/modules/FindZLIB.cmake index f052939d04..e6212247b3 100644 --- a/cmake/modules/FindZLIB.cmake +++ b/cmake/modules/FindZLIB.cmake @@ -135,10 +135,11 @@ if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h") set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}") endif() -set(ZLIB_REQUIREMENTS ZLIB_LIBRARY ZLIB_INCLUDE_DIR VERSION_VAR ZLIB_VERSION_STRING) +set(ZLIB_REQUIREMENTS ZLIB_LIBRARY ZLIB_INCLUDE_DIR) if (WIN32) list(APPEND ZLIB_REQUIREMENTS ZLIB_DLL_PATH) endif () +list(APPEND ZLIB_REQUIREMENTS VERSION_VAR ZLIB_VERSION_STRING) # handle the QUIETLY and REQUIRED arguments and set ZLIB_FOUND to TRUE if # all listed variables are TRUE From 44f8e599e2f02c1f8076a95b490808c6170a4d15 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 15:29:28 -0800 Subject: [PATCH 090/341] test the possibility that zlib is no longer required --- interface/CMakeLists.txt | 7 ++----- libraries/environment/CMakeLists.txt | 9 +-------- libraries/fbx/CMakeLists.txt | 6 +----- libraries/octree/CMakeLists.txt | 8 -------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c54199dfe8..fb29667e09 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -106,7 +106,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # set up the external glm library -add_dependency_external_projects(glm bullet zlib) +add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) @@ -119,9 +119,6 @@ link_hifi_libraries(shared octree environment gpu model fbx metavoxels networkin audio audio-client animation script-engine physics render-utils entities-renderer) -# find any optional and required libraries -find_package(ZLIB REQUIRED) - # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) @@ -185,7 +182,7 @@ endif () include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes") target_link_libraries( - ${TARGET_NAME} ${ZLIB_LIBRARIES} + ${TARGET_NAME} Qt5::Gui Qt5::Network Qt5::Multimedia Qt5::OpenGL Qt5::Script Qt5::Svg Qt5::WebKitWidgets ) diff --git a/libraries/environment/CMakeLists.txt b/libraries/environment/CMakeLists.txt index 61a8c6b8df..a2ee9e3f55 100644 --- a/libraries/environment/CMakeLists.txt +++ b/libraries/environment/CMakeLists.txt @@ -7,11 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared networking) - -# find ZLIB -find_package(ZLIB REQUIRED) -include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") - -# add it to our list of libraries to link -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) \ No newline at end of file +link_hifi_libraries(shared networking) \ No newline at end of file diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index c1ba5a1c2a..1ce1c74922 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -7,8 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared gpu model networking octree) - -find_package(ZLIB REQUIRED) -include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) \ No newline at end of file +link_hifi_libraries(shared gpu model networking octree) \ No newline at end of file diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index 1f44795148..cc36aead15 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -8,11 +8,3 @@ find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) link_hifi_libraries(shared networking) - -# find ZLIB -find_package(ZLIB REQUIRED) - -include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") - -# append ZLIB and OpenSSL to our list of libraries to link -target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) From dab524fb0f294525821227c0db2cebfe09cc2eaf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 15:35:38 -0800 Subject: [PATCH 091/341] remove zlib modules and mentions in build guides --- BUILD_LINUX.md | 6 - BUILD_WIN.md | 17 --- cmake/externals/zlib/CMakeLists.txt | 22 ---- cmake/modules/FindZLIB.cmake | 163 ---------------------------- 4 files changed, 208 deletions(-) delete mode 100644 cmake/externals/zlib/CMakeLists.txt delete mode 100644 cmake/modules/FindZLIB.cmake diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 08945716ae..933e73e869 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -1,11 +1,5 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file. -###Linux Specific Dependencies -* [freeglut](http://freeglut.sourceforge.net/) ~> 2.8.0 -* [zLib](http://www.zlib.net/) ~> 1.2.8 - -In general, as long as external dependencies are placed in OS standard locations, CMake will successfully find them during its run. When possible, you may choose to install depencies from your package manager of choice, or from source. - ###Qt5 Dependencies Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: diff --git a/BUILD_WIN.md b/BUILD_WIN.md index ae71970466..f6d484fcd1 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -2,7 +2,6 @@ Please read the [general build guide](BUILD.md) for information on dependencies ###Windows Specific Dependencies * [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 -* [zLib](http://www.zlib.net/) ~> 1.2.8 * (remember that you need all other dependencies listed in [BUILD.md](BUILD.md)) ###Visual Studio 2013 @@ -80,22 +79,6 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. -####Zlib - -Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. - -Add the following environment variables (remember to substitute your own directory for %HIFI_LIB_DIR%): - - ZLIB_LIBRARY=%HIFI_LIB_DIR%\zlib\lib\zdll.lib - ZLIB_INCLUDE_DIR=%HIFI_LIB_DIR%\zlib\include - -Add to the PATH: `%HIFI_LIB_DIR%\zlib` - -(The PATH environment variable is where Windows looks for its DLL's and executables. There's a great tool for editing these variables with ease, [Rapid Environment Editor](http://www.rapidee.com/en/download)) - -Important! This should be added at the beginning of the path, not the end (your -system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". - ####GLEW Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). diff --git a/cmake/externals/zlib/CMakeLists.txt b/cmake/externals/zlib/CMakeLists.txt deleted file mode 100644 index af980484be..0000000000 --- a/cmake/externals/zlib/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -set(EXTERNAL_NAME zlib) - -include(ExternalProject) - -if (WIN32) - ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://zlib.net/zlib128-dll.zip - URL_MD5 42eccc2af5bac6b7a1188d7817d03549 - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 - ) - - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - - set(${EXTERNAL_NAME_UPPER}_LIBRARY ${SOURCE_DIR}/lib/zdll.lib CACHE TYPE "Location of zlib library") - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/include CACHE TYPE "Location of zlib includes") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR} CACHE TYPE "Location of zlib DLL") -endif () - diff --git a/cmake/modules/FindZLIB.cmake b/cmake/modules/FindZLIB.cmake deleted file mode 100644 index e6212247b3..0000000000 --- a/cmake/modules/FindZLIB.cmake +++ /dev/null @@ -1,163 +0,0 @@ -#.rst: -# FindZLIB -# -------- -# -# Find the native ZLIB includes and library. -# -# IMPORTED Targets -# ^^^^^^^^^^^^^^^^ -# -# This module defines :prop_tgt:`IMPORTED` target ``ZLIB::ZLIB``, if -# ZLIB has been found. -# -# Result Variables -# ^^^^^^^^^^^^^^^^ -# -# This module defines the following variables: -# -# :: -# -# ZLIB_INCLUDE_DIRS - where to find zlib.h, etc. -# ZLIB_LIBRARIES - List of libraries when using zlib. -# ZLIB_FOUND - True if zlib found. -# -# :: -# -# ZLIB_VERSION_STRING - The version of zlib found (x.y.z) -# ZLIB_VERSION_MAJOR - The major version of zlib -# ZLIB_VERSION_MINOR - The minor version of zlib -# ZLIB_VERSION_PATCH - The patch version of zlib -# ZLIB_VERSION_TWEAK - The tweak version of zlib -# -# Backward Compatibility -# ^^^^^^^^^^^^^^^^^^^^^^ -# -# The following variable are provided for backward compatibility -# -# :: -# -# ZLIB_MAJOR_VERSION - The major version of zlib -# ZLIB_MINOR_VERSION - The minor version of zlib -# ZLIB_PATCH_VERSION - The patch version of zlib -# -# Hints -# ^^^^^ -# -# A user may set ``ZLIB_ROOT`` to a zlib installation root to tell this -# module where to look. - -#============================================================================= -# Copyright 2000-2014 Kitware, Inc. -# Copyright 2000-2011 Insight Software Consortium -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the names of Kitware, Inc., the Insight Software Consortium, -# nor the names of their contributors may be used to endorse or promote -# products derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - - -# Modified on 2/19/2015 by Stephen Birarda -# The High Fidelity modification adds a ZLIB_DLL_PATH variable for fixup_bundle on windows - -set(_ZLIB_SEARCHES) - -# Search ZLIB_ROOT first if it is set. -if(ZLIB_ROOT) - set(_ZLIB_SEARCH_ROOT PATHS ${ZLIB_ROOT} NO_DEFAULT_PATH) - list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_ROOT) -endif() - -# Normal search. -set(_ZLIB_SEARCH_NORMAL - PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]" - "$ENV{PROGRAMFILES}/zlib" - ) -list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL) - -set(ZLIB_NAMES z zlib zdll zlib1 zlibd zlibd1) - -# Try each search configuration. -foreach(search ${_ZLIB_SEARCHES}) - find_path(ZLIB_INCLUDE_DIR NAMES zlib.h ${${search}} PATH_SUFFIXES include) - find_library(ZLIB_LIBRARY NAMES ${ZLIB_NAMES} ${${search}} PATH_SUFFIXES lib) - - if (WIN32) - find_path(ZLIB_DLL_PATH NAMES zlib.dll ${${search}} PATH_SUFFIXES bin) - endif () -endforeach() - -mark_as_advanced(ZLIB_LIBRARY ZLIB_INCLUDE_DIR) - -if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h") - file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$") - - string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}") - string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}") - string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}") - set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}") - - # only append a TWEAK version if it exists: - set(ZLIB_VERSION_TWEAK "") - if( "${ZLIB_H}" MATCHES "ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)") - set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}") - set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}") - endif() - - set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}") - set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}") - set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}") -endif() - -set(ZLIB_REQUIREMENTS ZLIB_LIBRARY ZLIB_INCLUDE_DIR) -if (WIN32) - list(APPEND ZLIB_REQUIREMENTS ZLIB_DLL_PATH) -endif () -list(APPEND ZLIB_REQUIREMENTS VERSION_VAR ZLIB_VERSION_STRING) - -# handle the QUIETLY and REQUIRED arguments and set ZLIB_FOUND to TRUE if -# all listed variables are TRUE -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZLIB REQUIRED_VARS ${ZLIB_REQUIREMENTS}) - -if(ZLIB_FOUND) - set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) - set(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) - - if(NOT TARGET ZLIB::ZLIB) - add_library(ZLIB::ZLIB UNKNOWN IMPORTED) - set_target_properties(ZLIB::ZLIB PROPERTIES - IMPORTED_LOCATION "${ZLIB_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIRS}") - endif() - - if (WIN32) - add_path_to_lib_paths(${ZLIB_DLL_PATH}) - endif () -endif() From b7c03c34a8fcd456a90bb8705dab035b2dcf1992 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 16:39:05 -0800 Subject: [PATCH 092/341] use path and filepath where appropriate for cache --- cmake/externals/bullet/CMakeLists.txt | 18 +++---- cmake/externals/glm/CMakeLists.txt | 2 +- cmake/externals/gverb/CMakeLists.txt | 6 +-- cmake/externals/soxr/CMakeLists.txt | 10 ++-- cmake/externals/tbb/CMakeLists.txt | 51 ++++++++----------- .../AddDependencyExternalProjects.cmake | 4 +- cmake/macros/AddPathsToLibPaths.cmake | 2 +- 7 files changed, 43 insertions(+), 50 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index e46cb093d4..661beac212 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -49,19 +49,19 @@ elseif (WIN32) endif () if (DEFINED BULLET_LIB_EXT) - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE TYPE "Bullet dynamics release library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet dynamics debug library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics release library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet dynamics debug library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE TYPE "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet collision debug library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE TYPE "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet math debug library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE TYPE "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE TYPE "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet softbody debug library location") endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE TYPE "Path to bullet include directory") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE PATH "Path to bullet include directory") endif () \ No newline at end of file diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index a6f74b52fe..eda9e0df98 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -16,4 +16,4 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "List of glm include directories") \ No newline at end of file +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glm include directories") \ No newline at end of file diff --git a/cmake/externals/gverb/CMakeLists.txt b/cmake/externals/gverb/CMakeLists.txt index c7791c2424..f5372f6895 100644 --- a/cmake/externals/gverb/CMakeLists.txt +++ b/cmake/externals/gverb/CMakeLists.txt @@ -19,10 +19,10 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "Path to gverb include directory") +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to gverb include directory") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/gverb.lib CACHE TYPE "List of gverb libraries") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/gverb.lib CACHE FILEPATH "List of gverb libraries") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libgverb.a CACHE TYPE "List of gverb libraries") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libgverb.a CACHE FILEPATH "List of gverb libraries") endif () \ No newline at end of file diff --git a/cmake/externals/soxr/CMakeLists.txt b/cmake/externals/soxr/CMakeLists.txt index c2f5163f94..d004cf9ccb 100644 --- a/cmake/externals/soxr/CMakeLists.txt +++ b/cmake/externals/soxr/CMakeLists.txt @@ -19,13 +19,13 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE TYPE "List of soxr include directories") +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of soxr include directories") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE TYPE "List of soxr libraries") - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE TYPE "Path to soxr dll") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/soxr.lib CACHE FILEPATH "List of soxr libraries") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${INSTALL_DIR}/bin CACHE PATH "Path to soxr dll") elseif (APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE TYPE "List of soxr libraries") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.dylib CACHE FILEPATH "List of soxr libraries") else () - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE TYPE "List of soxr libraries") + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${INSTALL_DIR}/lib/libsoxr.so CACHE FILEPATH "List of soxr libraries") endif () \ No newline at end of file diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 39ec4aa8f2..56997db490 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -45,29 +45,21 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (APPLE) - set(_TBB_APPLE_LIB_DIR "${SOURCE_DIR}/lib/libc++") - - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbb_debug.dylib CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbb.dylib CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_APPLE_LIB_DIR}/libtbbmalloc_debug.dylib CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_APPLE_LIB_DIR}/libtbbmalloc.dylib CACHE TYPE "TBB malloc release library location") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/libc++") + set(_LIB_PREFIX "lib") + set(_LIB_EXT "dylib") elseif (WIN32) - set(_TBB_WIN_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") - - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/tbb_debug.lib CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/tbb.lib CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_WIN_LIB_DIR}/tbbmalloc_debug.lib CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_WIN_LIB_DIR}/tbbmalloc.lib CACHE TYPE "TBB malloc release library location") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE TYPE "Path to TBB DLLs") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") + set(_LIB_EXT "lib") + set(${EXTERNAL_NAME_UPPER}_DLL_PATH "${SOURCE_DIR}/bin/ia32/vc12" CACHE PATH "Path to TBB DLLs") elseif (ANDROID) - set(_TBB_ANDROID_LIB_DIR "${SOURCE_DIR}/lib") - - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_ANDROID_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib") + set(_LIB_PREFIX "lib") + set(_LIB_EXT "so") elseif (UNIX) + set(_LIB_PREFIX "lib") + set(_LIB_EXT "so") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_TBB_ARCH_DIR "intel64") else() @@ -80,22 +72,23 @@ elseif (UNIX) ) if (GCC_VERSION VERSION_GREATER 4.4 OR GCC_VERSION VERSION_EQUAL 4.4) - set(_TBB_LINUX_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.4") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.4") elseif (GCC_VERSION VERSION_GREATER 4.1 OR GCC_VERSION VERSION_EQUAL 4.1) - set(_TBB_LINUX_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.1") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/${_TBB_ARCH_DIR}/gcc4.1") else () message(STATUS "Could not find a compatible version of Threading Building Blocks library for your compiler.") endif () - if (DEFINED _TBB_LINUX_LIB_DIR) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbb_debug.so CACHE TYPE "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbb.so CACHE TYPE "TBB release library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LINUX_LIB_DIR}/libtbbmalloc_debug.so CACHE TYPE "TBB malloc debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LINUX_LIB_DIR}/libtbbmalloc.so CACHE TYPE "TBB malloc release library location") - endif () + endif () -if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE) +if (DEFINED _TBB_LIB_DIR) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb.${_LIB_EXT} CACHE FILEPATH "TBB release library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc.${_LIB_EXT} CACHE FILEPATH "TBB malloc release library location") +endif () +if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") endif () \ No newline at end of file diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index 816036fc81..f9ba91e1cb 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -25,12 +25,12 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) # did we end up adding an external project target? if (NOT TARGET ${_PROJ_NAME}) - set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT FALSE CACHE TYPE "Presence of ${_PROJ_NAME} as external target") + set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT FALSE CACHE BOOL "Presence of ${_PROJ_NAME} as external target") message(STATUS "${_PROJ_NAME} was not added as an external project target for your OS." " Either your system should already have the external library or you will need to install it separately.") else () - set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT TRUE CACHE TYPE "Presence of ${_PROJ_NAME} as external target") + set(${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT TRUE CACHE BOOL "Presence of ${_PROJ_NAME} as external target") endif () endif () diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index ab1aef697b..d92a339ba7 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -17,6 +17,6 @@ macro(ADD_PATHS_TO_LIB_PATHS) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) - set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE TYPE LIST FORCE) + set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE LIST FORCE) endforeach() endmacro() \ No newline at end of file From 12f03c560656f7388aa617eb127789000eb0ab26 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 19 Feb 2015 17:39:30 -0800 Subject: [PATCH 093/341] set install name dir for bullet on OS X --- cmake/externals/bullet/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 661beac212..4fb8b0a5d1 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -6,7 +6,9 @@ else () set(PLATFORM_CMAKE_ARGS "-DBUILD_SHARED_LIBS=1") if (ANDROID) - set(PLATFORM_CMAKE_ARGS "${PLATFORM_CMAKE_ARGS} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + list(APPEND PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + elseif (APPLE) + list(APPEND PLATFORM_CMAKE_ARGS "-DCMAKE_INSTALL_NAME_DIR=/lib") endif() endif () @@ -23,7 +25,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} URL_MD5 ${DOWNLOAD_MD5} - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLM=0 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 4b3183d820b5cf9eddcffda9724f0a3c7cba42d3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 19 Feb 2015 17:44:06 -0800 Subject: [PATCH 094/341] AssignmentClients accept an id on the command-line. AssignmentClientMonitor now has a NodeList. It stores its local port in shared memory, like the DomainServer does. As it spawns children, it addes Nodes to the NodeList for each one. The children send status updates to the Monitor. The Monitor will notice if there are no spares and fork another child. --- assignment-client/src/AssignmentClient.cpp | 77 +++++++--- assignment-client/src/AssignmentClient.h | 12 +- assignment-client/src/AssignmentClientApp.cpp | 84 ++++++++++ assignment-client/src/AssignmentClientApp.h | 19 +++ .../src/AssignmentClientMonitor.cpp | 143 +++++++++++++++++- .../src/AssignmentClientMonitor.h | 21 ++- assignment-client/src/main.cpp | 30 +--- domain-server/src/DomainServer.cpp | 16 +- libraries/networking/src/LimitedNodeList.cpp | 38 +++++ libraries/networking/src/LimitedNodeList.h | 10 ++ libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 + libraries/networking/src/PacketHeaders.cpp | 3 + libraries/networking/src/PacketHeaders.h | 4 +- 14 files changed, 389 insertions(+), 77 deletions(-) create mode 100644 assignment-client/src/AssignmentClientApp.cpp create mode 100644 assignment-client/src/AssignmentClientApp.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index bf67d4d597..9098a258e7 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -40,10 +41,11 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv) : +AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL) + _localASPortSharedMem(NULL), + _localACMPortSharedMem(NULL) { LogUtils::init(); @@ -57,6 +59,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); auto avatarHashMap = DependencyManager::set(); + + nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -123,9 +127,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - QTimer* timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -136,6 +139,36 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + + setUpStatsToMonitor(); +} + + +void AssignmentClient::setUpStatsToMonitor() { + // Figure out the address to send out stats to + quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; + auto nodeList = DependencyManager::get(); + + nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); + _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); + + // send a stats packet every 1 seconds + connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); + _statsTimerACM.start(1000); +} + +void AssignmentClient::sendStatsPacketToACM() { + // tell the assignment client monitor what this assignment client is doing (if anything) + QJsonObject statsObject; + auto nodeList = DependencyManager::get(); + + if (_currentAssignment) { + statsObject["assignment_type"] = _currentAssignment->getTypeName(); + } else { + statsObject["assignment_type"] = "none"; + } + nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -145,34 +178,22 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - if (!_localASPortSharedMem) { - _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - - if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY - << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } - } - - if (_localASPortSharedMem->isAttached()) { - _localASPortSharedMem->lock(); - - quint16 localAssignmentServerPort; - memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); - - _localASPortSharedMem->unlock(); - + quint16 localAssignmentServerPort; + if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - + else { + qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } } - + nodeList->sendAssignment(_requestAssignment); } } @@ -227,10 +248,16 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } + } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { + qDebug() << "Network told me to exit"; + quit(); } else { + qDebug() << "punt"; // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); } + } else { + qDebug() << "packetVersionAndHashMatch said no"; } } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 053458f136..7f0f16e6d6 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,7 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv); + AssignmentClient(int &argc, char **argv, QUuid nodeUUID); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: @@ -29,13 +29,21 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); + void sendStatsPacketToACM(); private: + void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; + QSharedMemory* _localASPortSharedMem; // memory shared with domain server + QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor + QTimer _requestTimer; // timer for requesting and assignment + QTimer _statsTimerACM; // timer for sending stats to assignment client monitor + + protected: + HifiSockAddr _assignmentClientMonitorSocket; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp new file mode 100644 index 0000000000..4541732e2c --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -0,0 +1,84 @@ +// +// AssignmentClientapp.cpp +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" + + +AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : + QApplication(argc, argv) +{ +# ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +# endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Assignment Client"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); + parser.addOption(numChildsOption); + + const QCommandLineOption idOption("i", "assignment client id", "uuid"); + parser.addOption(idOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(numChildsOption) && parser.isSet(idOption)) { + qCritical() << "using both -i and -n doesn't make sense."; + parser.showHelp(); + Q_UNREACHABLE(); + } + + unsigned int numForks = 0; + if (parser.isSet(numChildsOption)) { + numForks = parser.value(numChildsOption).toInt(); + } + + QUuid nodeUUID = QUuid::createUuid(); + if (parser.isSet(idOption)) { + nodeUUID = QUuid(parser.value(idOption)); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + monitor.exec(); + } else { + AssignmentClient client(argc, argv, nodeUUID); + client.exec(); + } +} + + +AssignmentClientApp::~AssignmentClientApp() { +} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h new file mode 100644 index 0000000000..6c91fa06a3 --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.h @@ -0,0 +1,19 @@ +// +// AssignmentClientapp.h +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +class AssignmentClientApp : public QApplication { + Q_OBJECT +public: + AssignmentClientApp(int argc, char* argv[]); + ~AssignmentClientApp(); +}; diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 45e1f56d53..831d50c134 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -14,13 +14,18 @@ #include #include + +#include // XXX need this? + + #include "AssignmentClientMonitor.h" +#include "PacketHeaders.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -41,17 +46,38 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); + + + // create a NodeList so we can receive stats from children + DependencyManager::registerInheritance(); + auto addressManager = DependencyManager::set(); + // auto nodeList = DependencyManager::set(NodeType::Unassigned); + auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, + DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); + + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); + + nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } + + connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); + _checkSparesTimer.start(5000); } AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); + + foreach (AssignmentClientChildData* childStatus, _childStatus) { + delete childStatus; + } } + + void AssignmentClientMonitor::stopChildProcesses() { QList >::Iterator it = _childProcesses.begin(); @@ -74,11 +100,18 @@ void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); _childProcesses.append(QPointer(assignmentClient)); + + QUuid childUUID = QUuid::createUuid(); + + // create a Node for this child. this is done so we can idenitfy packets from unknown children + DependencyManager::get()->addOrUpdateNode + (childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false); // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - - assignmentClient->start(applicationFilePath(), _childArguments); + + QStringList idArgs = QStringList() << "-i" << childUUID.toString(); + assignmentClient->start(applicationFilePath(), _childArguments + idArgs); // link the child processes' finished slot to our childProcessFinished slot connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, @@ -96,3 +129,105 @@ void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitS spawnChildClient(); } + + + +void AssignmentClientMonitor::checkSpares() { + qDebug() << "check spares:"; + + QString aSpareId = ""; + unsigned int spareCount = 0; + + QHash::const_iterator i = _childStatus.constBegin(); + while (i != _childStatus.constEnd()) { + qDebug() << " " << i.key() << i.value()->getChildType(); + if (i.value()->getChildType() == "none") { + spareCount ++; + aSpareId = i.key(); + } + ++i; + } + + qDebug() << "spare count is" << spareCount; + + if (spareCount < 1) { + qDebug() << "FORK"; + spawnChildClient(); + } + + if (spareCount > 1) { + qDebug() << "KILL"; + } +} + + + + +void AssignmentClientMonitor::readPendingDatagrams() { + auto nodeList = DependencyManager::get(); + + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + + while (nodeList->getNodeSocket().hasPendingDatagrams()) { + receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); + nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), + senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); + + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { + + QUuid packetUUID = uuidFromPacketHeader(receivedPacket); + // qDebug() << "packetUUID = " << packetUUID; + + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (!matchingNode) { + qDebug() << "got packet from unknown child, id =" << packetUUID.toString(); + // tell unknown assignment-client child to exit. + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } + + if (matchingNode) { + // update our records about how to reach this child + matchingNode->setLocalSocket(senderSockAddr); + + // push past the packet header + QDataStream packetStream(receivedPacket); + packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); + + QVariantMap unpackedVariantMap; + + packetStream >> unpackedVariantMap; + + QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); + + // qDebug() << "ACM got stats packet, id =" << packetUUID.toString() + // << "type =" << unpackedStatsJSON["assignment_type"]; + + QString key(QString(packetUUID.toString())); + if (_childStatus.contains(key)) { + delete _childStatus[ key ]; + } + + QString childType = unpackedStatsJSON["assignment_type"].toString(); + auto childStatus = new AssignmentClientChildData(childType); + _childStatus[ key ] = childStatus; + + } + } else { + // have the NodeList attempt to handle it + nodeList->processNodeData(senderSockAddr, receivedPacket); + } + } + } +} + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) { + _childType = childType; +} + + +AssignmentClientChildData::~AssignmentClientChildData() { +} diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 9a7bca9cb3..75d2296533 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -20,20 +20,39 @@ extern const char* NUM_FORKS_PARAMETER; +class AssignmentClientChildData { + public: + AssignmentClientChildData(QString childType); + ~AssignmentClientChildData(); + + QString getChildType() { return _childType; } + + private: + QString _childType; + // ... timestamp +}; + + class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void readPendingDatagrams(); + void checkSpares(); + private: void spawnChildClient(); QList > _childProcesses; QStringList _childArguments; + QHash _childStatus; + + QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 3bf6990a74..81a12526bf 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,34 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" int main(int argc, char* argv[]) { -#ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -#endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); - - int numForks = 0; - - if (numForksString) { - numForks = atoi(numForksString); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - return monitor.exec(); - } else { - AssignmentClient client(argc, argv); - return client.exec(); - } + AssignmentClientApp app(argc, argv); + return 0; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f84722a438..30d6dd4348 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -244,21 +244,9 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateStaticScriptedAssignmentsFromSettings(); auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); - + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - quint16 localPort = nodeList->getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c8c454ff14..075fd5a44b 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } + +void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { + // save our local port to shared memory so that assignment client children know how to talk to this parent + QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); + quint16 localPort = getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } +} + + +bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, + quint16& localPort) { + if (!sharedMem) { + sharedMem = new QSharedMemory(key, this); + + if (!sharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << key; + } + } + + if (sharedMem->isAttached()) { + sharedMem->lock(); + memcpy(&localPort, sharedMem->data(), sizeof(localPort)); + sharedMem->unlock(); + return true; + } + + return false; +} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 72aefdb2b3..e7ccbe7746 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -49,6 +51,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; +const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; + +const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -168,6 +175,9 @@ public: return SharedNodePointer(); } + + void putLocalPortIntoSharedMemory(const QString key, QObject* parent); + bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f70c2d9b3c..e63f230f6e 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { +qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, destination); +} + +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { + return sendStats(statsObject, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 907fccfcac..1c6de4bb6c 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,6 +47,7 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } + qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..db97e216ee 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; + case PacketTypeStopNode: + return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..32f33c01d9 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - UNUSED_10, + PacketTypeStopNode, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; From 5c3cae471be2e0527abfe8eea8ca8a84193c8a6f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Feb 2015 09:48:04 -0800 Subject: [PATCH 095/341] Fix avatar billboards all rendering as the same billboard --- interface/src/avatar/Avatar.cpp | 21 +++++++++------------ interface/src/avatar/Avatar.h | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d4c10b2b4a..6dc3d4b339 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -537,18 +537,13 @@ void Avatar::renderBillboard() { return; } if (!_billboardTexture) { - QImage image = QImage::fromData(_billboard); - if (image.format() != QImage::Format_ARGB32) { - image = image.convertToFormat(QImage::Format_ARGB32); - } - _billboardTexture.reset(new Texture()); - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, - GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - } else { - glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); + // Using a unique URL ensures we don't get another avatar's texture from TextureCache + QUrl uniqueUrl = QUrl(QUuid::createUuid().toString()); + _billboardTexture = DependencyManager::get()->getTexture( + uniqueUrl, DEFAULT_TEXTURE, false, _billboard); + } + if (!_billboardTexture->isLoaded()) { + return; } glEnable(GL_ALPHA_TEST); @@ -556,6 +551,8 @@ void Avatar::renderBillboard() { glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); + + glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 18e42b7dd7..72b7ecf93a 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -234,7 +234,7 @@ protected: private: bool _initialized; - QScopedPointer _billboardTexture; + NetworkTexturePointer _billboardTexture; bool _shouldRenderBillboard; bool _isLookAtTarget; From ded78816b52e1efafa0d2bde39de78d4a81181a7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 20 Feb 2015 11:26:08 -0800 Subject: [PATCH 096/341] Fixing the remaining issue with the avatar rendering path --- libraries/gpu/src/gpu/Context.h | 3 ++- libraries/gpu/src/gpu/GLBackend.cpp | 2 +- libraries/gpu/src/gpu/Transform.slh | 17 ++++++++--------- libraries/render-utils/src/Model.cpp | 9 ++++----- libraries/render-utils/src/model.slv | 5 ++--- libraries/render-utils/src/model_lightmap.slv | 5 ++--- .../src/model_lightmap_normal_map.slv | 7 +++---- libraries/render-utils/src/model_normal_map.slv | 7 +++---- libraries/render-utils/src/model_shadow.slv | 2 +- libraries/render-utils/src/skin_model.slv | 5 ++--- .../render-utils/src/skin_model_normal_map.slv | 7 +++---- .../render-utils/src/skin_model_shadow.slv | 3 +-- 12 files changed, 32 insertions(+), 40 deletions(-) diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index bd5da57504..d7162c50d7 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -37,10 +37,11 @@ public: class TransformCamera { public: - Mat4 _projection; Mat4 _view; Mat4 _viewInverse; Mat4 _projectionViewUntranslated; + Mat4 _projection; + Vec4 _viewport; }; template< typename T > diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index f4f73abb45..3208b314e9 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -486,7 +486,7 @@ void GLBackend::updateTransform() { if (_transform._invalidView || _transform._invalidProj) { Mat4 viewUntranslated = _transform._transformCamera._view; - // viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); + viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index d2c1390294..b433f8282d 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -16,22 +16,21 @@ struct TransformObject { }; struct TransformCamera { - mat4 _projection; mat4 _view; mat4 _viewInverse; mat4 _projectionViewUntranslated; + mat4 _projection; + vec4 _viewport; }; -vec4 transform(TransformCamera camera, TransformObject object, vec4 pos) { - /* vec4 res = object._model * pos; - res += pos.w * camera._viewInverse[3]; - return camera._projectionViewUntranslated * res; -*/ - return camera._projectionViewUntranslated * object._model * pos; - // return camera._projection * camera._view * object._model * pos; +vec4 transformModelToClipPos(TransformCamera camera, TransformObject object, vec4 pos) { + vec4 epos = (object._model * pos) + vec4(-pos.w * camera._viewInverse[3].xyz, 0.0); + return camera._projectionViewUntranslated * epos; + // Equivalent to the following but hoppefully a bit more accurate + // return camera._projection * camera._view * object._model * pos; } -vec3 transformDir(TransformCamera camera, TransformObject object, vec3 dir) { +vec3 transformModelToEyeDir(TransformCamera camera, TransformObject object, vec3 dir) { vec3 mIr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); vec3 mIr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); vec3 mIr2 = vec3(object._modelInverse[0].z, object._modelInverse[1].z, object._modelInverse[2].z); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index fb26f7f9dc..f64f58cf14 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -700,11 +700,10 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { _renderBatch.clear(); gpu::Batch& batch = _renderBatch; - if (args) { - glm::mat4 proj; - args->_viewFrustum->evalProjectionMatrix(proj); - batch.setProjectionTransform(proj); - } + // Setup the projection matrix + glm::mat4 proj; + _viewState->getCurrentViewFrustum()->evalProjectionMatrix(proj); + batch.setProjectionTransform(proj); // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index 5f2bfe5f9d..4f416e8f1f 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -30,10 +30,9 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, gl_Vertex); + gl_Position = transformModelToClipPos(cam, obj, gl_Vertex); // transform and store the normal for interpolation - normal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); + normal = vec4(normalize(transformModelToEyeDir(cam, obj, gl_Normal)), 0.0); } diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 3adca397c2..afe3c73549 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -38,10 +38,9 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, gl_Vertex); + gl_Position = transformModelToClipPos(cam, obj, gl_Vertex); // transform and store the normal for interpolation - normal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); + normal = vec4(normalize(transformModelToEyeDir(cam, obj, gl_Normal)), 0.0); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index be86655f75..6e66b28e63 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -47,10 +47,9 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, gl_Vertex); + gl_Position = transformModelToClipPos(cam, obj, gl_Vertex); // transform and store the normal for interpolation - interpolatedNormal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); - interpolatedTangent = vec4(normalize(transformDir(cam, obj, tangent)), 0.0); + interpolatedNormal = vec4(normalize(transformModelToEyeDir(cam, obj, gl_Normal)), 0.0); + interpolatedTangent = vec4(normalize(transformModelToEyeDir(cam, obj, tangent)), 0.0); } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index dbb87473b8..4111458464 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -41,10 +41,9 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, gl_Vertex); + gl_Position = transformModelToClipPos(cam, obj, gl_Vertex); // transform and store the normal for interpolation - interpolatedNormal = vec4(normalize(transformDir(cam, obj, gl_Normal)), 0.0); - interpolatedTangent = vec4(normalize(transformDir(cam, obj, tangent)), 0.0); + interpolatedNormal = vec4(normalize(transformModelToEyeDir(cam, obj, gl_Normal)), 0.0); + interpolatedTangent = vec4(normalize(transformModelToEyeDir(cam, obj, tangent)), 0.0); } diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv index 5d386d4d4c..98f6bf5104 100755 --- a/libraries/render-utils/src/model_shadow.slv +++ b/libraries/render-utils/src/model_shadow.slv @@ -17,5 +17,5 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - gl_Position = transform(cam, obj, gl_Vertex); + gl_Position = transformModelToClipPos(cam, obj, gl_Vertex); } diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index 08aff5724b..780b72323c 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -46,9 +46,8 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, position); + gl_Position = transformModelToClipPos(cam, obj, position); // transform and store the normal for interpolation - normal = vec4(normalize(transformDir(cam, obj, normal.xyz)), 0.0); + normal = vec4(normalize(transformModelToEyeDir(cam, obj, normal.xyz)), 0.0); } diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 404e9c625d..43ec9c6a9d 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -58,9 +58,8 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, interpolatedPosition); + gl_Position = transformModelToClipPos(cam, obj, interpolatedPosition); - interpolatedNormal = vec4(normalize(transformDir(cam, obj, interpolatedNormal.xyz)), 0.0); - interpolatedTangent = vec4(normalize(transformDir(cam, obj, interpolatedTangent.xyz)), 0.0); + interpolatedNormal = vec4(normalize(transformModelToEyeDir(cam, obj, interpolatedNormal.xyz)), 0.0); + interpolatedTangent = vec4(normalize(transformModelToEyeDir(cam, obj, interpolatedTangent.xyz)), 0.0); } diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv index ee21f96f45..de7f8f4e9f 100755 --- a/libraries/render-utils/src/skin_model_shadow.slv +++ b/libraries/render-utils/src/skin_model_shadow.slv @@ -33,6 +33,5 @@ void main(void) { // use standard pipeline transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - - gl_Position = transform(cam, obj, position); + gl_Position = transformModelToClipPos(cam, obj, position); } From 4e2d2bc1881556681d31e96897ac866eead1c7ed Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 20 Feb 2015 12:05:06 -0800 Subject: [PATCH 097/341] Fixing the remaining issue with the avatar rendering path --- libraries/gpu/src/gpu/Batch.h | 5 ++ libraries/gpu/src/gpu/GLBackend.cpp | 82 ++++++++-------------------- libraries/render-utils/src/Model.cpp | 4 +- 3 files changed, 30 insertions(+), 61 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index b9467f7fdc..310cd9fe16 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -53,6 +53,11 @@ enum Primitive { NUM_PRIMITIVES, }; +enum ReservedSlot { + TRANSFORM_OBJECT_SLOT = 6, + TRANSFORM_CAMERA_SLOT = 7, +}; + class Batch { public: typedef Stream::Slot Slot; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 3208b314e9..fd91e0df0c 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -421,55 +421,7 @@ void GLBackend::killTransform() { #endif } void GLBackend::updateTransform() { - -#ifdef LEGACY_TRANSFORM_PIPELINE - if (_transform._invalidProj) { - // TODO: implement the projection matrix assignment to gl state - if (_transform._lastMode != GL_PROJECTION) { - glMatrixMode(GL_PROJECTION); - _transform._lastMode = GL_PROJECTION; - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&_transform._projection)); - - CHECK_GL_ERROR(); - } - - if (_transform._invalidModel || _transform._invalidView) { - if (!_transform._model.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - Transform::Mat4 modelView; - if (!_transform._view.isIdentity()) { - Transform mvx; - Transform::inverseMult(mvx, _transform._view, _transform._model); - mvx.getMatrix(modelView); - } else { - _transform._model.getMatrix(modelView); - } - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - if (!_transform._view.isIdentity()) { - if (_transform._lastMode != GL_MODELVIEW) { - glMatrixMode(GL_MODELVIEW); - _transform._lastMode = GL_MODELVIEW; - } - Transform::Mat4 modelView; - _transform._view.getInverseMatrix(modelView); - glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); - } else { - // TODO: eventually do something about the matrix when neither view nor model is specified? - // glLoadIdentity(); - } - } - CHECK_GL_ERROR(); - - _transform._invalidModel = false; - _transform._invalidView = false; - } -#else - + // Check all the dirty flags and update the state accordingly if (_transform._invalidProj) { _transform._transformCamera._projection = _transform._projection; } @@ -489,28 +441,39 @@ void GLBackend::updateTransform() { viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f); _transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated; } - + if (_transform._invalidView || _transform._invalidProj) { - glBindBufferBase(GL_UNIFORM_BUFFER, 2, 0); - glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); + glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR(); +#endif } if (_transform._invalidModel) { - glBindBufferBase(GL_UNIFORM_BUFFER, 6, 0); +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERROR(); +#endif } - glBindBufferBase(GL_UNIFORM_BUFFER, 6, _transform._transformObjectBuffer); - glBindBufferBase(GL_UNIFORM_BUFFER, 2, _transform._transformCameraBuffer); - CHECK_GL_ERROR(); +#if defined(Q_OS_MAC) +#elif defined(Q_OS_WIN) + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer); + glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer); + CHECK_GL_ERROR(); +#endif - // Do it again for fixed pipeline unitl we can get rid of it + +#if defined(Q_OS_MAC) + // Do it again for fixed pipeline until we can get rid of it if (_transform._invalidProj) { if (_transform._lastMode != GL_PROJECTION) { glMatrixMode(GL_PROJECTION); @@ -552,9 +515,10 @@ void GLBackend::updateTransform() { } CHECK_GL_ERROR(); } - - _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; #endif + + // Flags are clean + _transform._invalidView = _transform._invalidProj = _transform._invalidModel = false; } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f64f58cf14..dd4d1ba9e7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -225,13 +225,13 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo loc = glGetUniformBlockIndex(program.programId(), "transformObjectBuffer"); if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, 6); + glUniformBlockBinding(program.programId(), loc, gpu::TRANSFORM_OBJECT_SLOT); // locations.materialBufferUnit = 1; } loc = glGetUniformBlockIndex(program.programId(), "transformCameraBuffer"); if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, 2); + glUniformBlockBinding(program.programId(), loc, gpu::TRANSFORM_CAMERA_SLOT); // locations.materialBufferUnit = 1; } From abfebf51f541e4c2d08b2cb92deb565f8329c76d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 12:17:42 -0800 Subject: [PATCH 098/341] handle install name change on OS X for TBB --- cmake/externals/tbb/AndroidTBBLibCopy.cmake | 2 +- cmake/externals/tbb/CMakeLists.txt | 11 ++++ .../tbb/OSXTBBInstallNameChange.cmake | 59 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 cmake/externals/tbb/OSXTBBInstallNameChange.cmake diff --git a/cmake/externals/tbb/AndroidTBBLibCopy.cmake b/cmake/externals/tbb/AndroidTBBLibCopy.cmake index 733ee00124..1c7697ab54 100644 --- a/cmake/externals/tbb/AndroidTBBLibCopy.cmake +++ b/cmake/externals/tbb/AndroidTBBLibCopy.cmake @@ -1,6 +1,6 @@ # # AndroidTBBLibCopy.cmake -# cmake/macros +# cmake/externals/tbb # # Copyright 2015 High Fidelity, Inc. # Created by Stephen Birarda on February 18, 2014 diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 56997db490..06da60ac04 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -48,6 +48,17 @@ if (APPLE) set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/libc++") set(_LIB_PREFIX "lib") set(_LIB_EXT "dylib") + + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + change-install-name + COMMENT "Calling install_name_tool on TBB libraries to fix install name for dylib linking" + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/OSXTBBInstallNameChange.cmake + DEPENDEES install + WORKING_DIRECTORY + LOG 1 + ) + elseif (WIN32) set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/ia32/vc12") set(_LIB_EXT "lib") diff --git a/cmake/externals/tbb/OSXTBBInstallNameChange.cmake b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake new file mode 100644 index 0000000000..c263ed7d2e --- /dev/null +++ b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake @@ -0,0 +1,59 @@ +# +# OSXTBBInstallNameChange.cmake +# cmake/externals/tbb +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 20, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +# first find the so files in the source dir +set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libc++) +file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib") + +# raise an error if we found none +if (NOT _TBB_LIBRARIES) + message(FATAL_ERROR "Did not find any TBB libraries") +endif () + +# find the install_name_tool command +find_program(INSTALL_NAME_TOOL_COMMAND NAMES install_name_tool DOC "Path to the install_name_tool command") + +# find the lipo command +find_program(LIPO_COMMAND NAMES lipo DOC "Path to the lipo command") + +# enumerate the libraries +foreach(_TBB_LIBRARY ${_TBB_LIBRARIES}) + get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME) + + set(_LIPO_ARGS -remove i386 ${_TBB_LIBRARY_FILENAME} -output ${_TBB_LIBRARY_FILENAME}) + message(STATUS "${LIPO_COMMAND} ${_LIPO_ARGS}") + + # first we use lipo to remove i386 from each dylib + execute_process( + COMMAND ${LIPO_COMMAND} ${_LIPO_ARGS} + WORKING_DIRECTORY ${_TBB_LIBRARY_DIR} + ERROR_VARIABLE _LIPO_ERROR + ) + + if (_LIPO_ERROR) + message(FATAL_ERROR "There was an error removing i386 for ${_TBB_LIBRARY_FILENAME} - ${_LIPO_ERROR}") + endif () + + set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME}) + + message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}") + + execute_process( + COMMAND ${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS} + WORKING_DIRECTORY ${_TBB_LIBRARY_DIR} + ERROR_VARIABLE _INSTALL_NAME_ERROR + ) + + if (_INSTALL_NAME_ERROR) + message(FATAL_ERROR "There was an error changing install name for ${_TBB_LIBRARY_FILENAME} - ${_INSTALL_NAME_ERROR}") + endif () +endforeach() + From 0bad8db1a0f794a1ad9e4c2d0977f2045c95c362 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 12:17:58 -0800 Subject: [PATCH 099/341] fix missing dependencies to external projects --- cmake/macros/AddDependencyExternalProjects.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index f9ba91e1cb..464652a5b7 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -18,7 +18,7 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) # has the user told us they specific don't want this as an external project? if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) # have we already detected we can't have this as external project on this OS? - if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${EXTERNAL_NAME_UPPER}_EXTERNAL_PROJECT) + if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT) # have we already setup the target? if (NOT TARGET ${_PROJ_NAME}) add_subdirectory(${EXTERNAL_PROJECT_DIR}/${_PROJ_NAME} ${EXTERNALS_BINARY_DIR}/${_PROJ_NAME}) From a85cb2eeaade9d4f80e929a96b1fcf75a9b483ab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 12:18:14 -0800 Subject: [PATCH 100/341] don't log glm install so it is shown in log --- assignment-client/CMakeLists.txt | 2 +- cmake/externals/glm/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 41343f52d0..ada534431a 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -17,4 +17,4 @@ if (UNIX) target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) -copy_dlls_beside_windows_executable() +copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index eda9e0df98..6e5b1ef870 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -10,7 +10,6 @@ ExternalProject_Add( LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 - LOG_INSTALL 1 ) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) From b7cc163ca4b6186491c1316641d06f9652c94969 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 12:21:10 -0800 Subject: [PATCH 101/341] lib paths is actually a string --- cmake/macros/AddPathsToLibPaths.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index d92a339ba7..07c143a9dd 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -17,6 +17,6 @@ macro(ADD_PATHS_TO_LIB_PATHS) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) - set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE LIST FORCE) + set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE STRING FORCE) endforeach() endmacro() \ No newline at end of file From 32fa2e8d31370bd9dab586c5665cce645446642a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 12:24:17 -0800 Subject: [PATCH 102/341] add missing docstring to AddPathsToLibPaths --- cmake/macros/AddPathsToLibPaths.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake index 07c143a9dd..7ac31db83f 100644 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ b/cmake/macros/AddPathsToLibPaths.cmake @@ -17,6 +17,6 @@ macro(ADD_PATHS_TO_LIB_PATHS) list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) - set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE STRING FORCE) + set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE STRING "Paths for external libraries passed to fixup_bundle" FORCE) endforeach() endmacro() \ No newline at end of file From feb0e7ac31a7f6c8950278b35163c01e5079ee64 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:26:59 -0800 Subject: [PATCH 103/341] AssignmentClientMonitor doesn't keep a list of its children. Instead it knows about active children due to their entries in the NodeList. Every few seconds, if 2 or more children are idle, the Monitor will ask one to exit --- assignment-client/src/AssignmentClient.cpp | 42 ++++-- assignment-client/src/AssignmentClient.h | 3 +- assignment-client/src/AssignmentClientApp.cpp | 18 +-- assignment-client/src/AssignmentClientApp.h | 2 +- .../src/AssignmentClientMonitor.cpp | 134 +++++++----------- .../src/AssignmentClientMonitor.h | 14 +- libraries/networking/src/AddressManager.cpp | 4 +- 7 files changed, 99 insertions(+), 118 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 9098a258e7..a0304acad9 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +// #include #include #include #include @@ -41,7 +41,7 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : +AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL), @@ -58,8 +58,11 @@ AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - auto avatarHashMap = DependencyManager::set(); + // auto avatarHashMap = DependencyManager::set(); + // make up a uuid for this child so the parent can tell us apart. This id will be changed + // when the domain server hands over an assignment. + QUuid nodeUUID = QUuid::createUuid(); nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us @@ -139,11 +142,37 @@ AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + // DependencyManager::get(); setUpStatsToMonitor(); } +void AssignmentClient::stopAssignmentClient() { + + // QList threads = QObject::findChildren (); + // foreach(QThread *thread, threads) { // or FileUploader* fileuploader, fileUploaders_ ? + // qDebug() << "thread " << thread->currentThreadId(); + // } + + qDebug() << "Exiting."; + + _requestTimer.stop(); + _statsTimerACM.stop(); + + + // DependencyManager::get()->disconnect(); + // DependencyManager::get()->disconnectNotify(); + // DependencyManager::get()->disconnect(); + // DependencyManager::get()->disconnectNotify(); + + // DependencyManager::destroy(); + // DependencyManager::destroy(); + + quit(); +} + + void AssignmentClient::setUpStatsToMonitor() { // Figure out the address to send out stats to quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; @@ -249,15 +278,12 @@ void AssignmentClient::readPendingDatagrams() { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - qDebug() << "Network told me to exit"; - quit(); + qDebug() << "Network told me to exit."; + emit stopAssignmentClient(); } else { - qDebug() << "punt"; // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); } - } else { - qDebug() << "packetVersionAndHashMatch said no"; } } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 7f0f16e6d6..e105309e10 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,7 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv, QUuid nodeUUID); + AssignmentClient(int &argc, char **argv); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: @@ -30,6 +30,7 @@ private slots: void assignmentCompleted(); void handleAuthenticationRequest(); void sendStatsPacketToACM(); + void stopAssignmentClient(); private: void setUpStatsToMonitor(); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 4541732e2c..8848b59c49 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -21,7 +21,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : - QApplication(argc, argv) + QCoreApplication(argc, argv) { # ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); @@ -40,9 +40,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); parser.addOption(numChildsOption); - const QCommandLineOption idOption("i", "assignment client id", "uuid"); - parser.addOption(idOption); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -54,27 +51,16 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : Q_UNREACHABLE(); } - if (parser.isSet(numChildsOption) && parser.isSet(idOption)) { - qCritical() << "using both -i and -n doesn't make sense."; - parser.showHelp(); - Q_UNREACHABLE(); - } - unsigned int numForks = 0; if (parser.isSet(numChildsOption)) { numForks = parser.value(numChildsOption).toInt(); } - QUuid nodeUUID = QUuid::createUuid(); - if (parser.isSet(idOption)) { - nodeUUID = QUuid(parser.value(idOption)); - } - if (numForks) { AssignmentClientMonitor monitor(argc, argv, numForks); monitor.exec(); } else { - AssignmentClient client(argc, argv, nodeUUID); + AssignmentClient client(argc, argv); client.exec(); } } diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index 6c91fa06a3..09952ad19c 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -11,7 +11,7 @@ #include -class AssignmentClientApp : public QApplication { +class AssignmentClientApp : public QCoreApplication { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 831d50c134..94975b0a4d 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -20,6 +20,7 @@ #include "AssignmentClientMonitor.h" #include "PacketHeaders.h" +#include "SharedUtil.h" const char* NUM_FORKS_PARAMETER = "-n"; @@ -70,85 +71,49 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); - - foreach (AssignmentClientChildData* childStatus, _childStatus) { - delete childStatus; - } } - - void AssignmentClientMonitor::stopChildProcesses() { - - QList >::Iterator it = _childProcesses.begin(); - while (it != _childProcesses.end()) { - if (!it->isNull()) { - qDebug() << "Monitor is terminating child process" << it->data(); - - // don't re-spawn this child when it goes down - disconnect(it->data(), 0, this, 0); - - it->data()->terminate(); - it->data()->waitForFinished(); - } - - it = _childProcesses.erase(it); - } + auto nodeList = DependencyManager::get(); + + nodeList->eachNode([&](const SharedNodePointer& node){ + qDebug() << "asking child" << node->getUUID() << "to exit."; + node->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); + }); } void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); - _childProcesses.append(QPointer(assignmentClient)); - - QUuid childUUID = QUuid::createUuid(); - - // create a Node for this child. this is done so we can idenitfy packets from unknown children - DependencyManager::get()->addOrUpdateNode - (childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false); - // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - QStringList idArgs = QStringList() << "-i" << childUUID.toString(); - assignmentClient->start(applicationFilePath(), _childArguments + idArgs); - - // link the child processes' finished slot to our childProcessFinished slot - connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, - SLOT(childProcessFinished(int, QProcess::ExitStatus))); - + assignmentClient->start(applicationFilePath(), _childArguments); qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } -void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { - qDebug("Replacing dead child assignment client with a new one"); - - // remove the old process from our list of child processes - qDebug() << "need to remove" << QPointer(qobject_cast(sender())); - _childProcesses.removeOne(QPointer(qobject_cast(sender()))); - - spawnChildClient(); -} - - void AssignmentClientMonitor::checkSpares() { - qDebug() << "check spares:"; - - QString aSpareId = ""; + auto nodeList = DependencyManager::get(); + QUuid aSpareId = ""; unsigned int spareCount = 0; - QHash::const_iterator i = _childStatus.constBegin(); - while (i != _childStatus.constEnd()) { - qDebug() << " " << i.key() << i.value()->getChildType(); - if (i.value()->getChildType() == "none") { - spareCount ++; - aSpareId = i.key(); - } - ++i; - } + nodeList->removeSilentNodes(); - qDebug() << "spare count is" << spareCount; + qDebug() << "check spares:"; + + nodeList->eachNode([&](const SharedNodePointer& node){ + AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + qDebug() << " " << node->getUUID() << childData->getChildType(); + if (childData->getChildType() == "none") { + spareCount ++; + aSpareId = node->getUUID(); + } + }); + + qDebug() << " spare count is" << spareCount; if (spareCount < 1) { qDebug() << "FORK"; @@ -156,13 +121,16 @@ void AssignmentClientMonitor::checkSpares() { } if (spareCount > 1) { - qDebug() << "KILL"; + // kill aSpareId + qDebug() << "asking child" << aSpareId << "to exit."; + SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); + childNode->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, childNode); } } - - void AssignmentClientMonitor::readPendingDatagrams() { auto nodeList = DependencyManager::get(); @@ -176,16 +144,21 @@ void AssignmentClientMonitor::readPendingDatagrams() { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { - QUuid packetUUID = uuidFromPacketHeader(receivedPacket); - // qDebug() << "packetUUID = " << packetUUID; - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (!matchingNode) { - qDebug() << "got packet from unknown child, id =" << packetUUID.toString(); - // tell unknown assignment-client child to exit. - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + // XXX only do this if from local machine + if (!packetUUID.isNull()) { + matchingNode = DependencyManager::get()->addOrUpdateNode + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); + matchingNode->setLinkedData(childData); + } else { + // tell unknown assignment-client child to exit. + qDebug() << "asking unknown child to exit."; + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } } if (matchingNode) { @@ -195,25 +168,18 @@ void AssignmentClientMonitor::readPendingDatagrams() { // push past the packet header QDataStream packetStream(receivedPacket); packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - + // decode json QVariantMap unpackedVariantMap; - packetStream >> unpackedVariantMap; - QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); - // qDebug() << "ACM got stats packet, id =" << packetUUID.toString() - // << "type =" << unpackedStatsJSON["assignment_type"]; - - QString key(QString(packetUUID.toString())); - if (_childStatus.contains(key)) { - delete _childStatus[ key ]; - } - + // get child's assignment type out of the decoded json QString childType = unpackedStatsJSON["assignment_type"].toString(); - auto childStatus = new AssignmentClientChildData(childType); - _childStatus[ key ] = childStatus; - + AssignmentClientChildData *childData = + static_cast(matchingNode->getLinkedData()); + childData->setChildType(childType); + // note when this child talked + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); } } else { // have the NodeList attempt to handle it diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 75d2296533..a91dfa93cc 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -15,21 +15,25 @@ #include #include #include +#include #include extern const char* NUM_FORKS_PARAMETER; -class AssignmentClientChildData { +class AssignmentClientChildData : public NodeData { public: AssignmentClientChildData(QString childType); ~AssignmentClientChildData(); QString getChildType() { return _childType; } + void setChildType(QString childType) { _childType = childType; } + + // implement parseData to return 0 so we can be a subclass of NodeData + int parseData(const QByteArray& packet) { return 0; } private: QString _childType; - // ... timestamp }; @@ -41,17 +45,15 @@ public: void stopChildProcesses(); private slots: - void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + // void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams(); void checkSpares(); private: void spawnChildClient(); - QList > _childProcesses; + // QList > _childProcesses; QStringList _childArguments; - QHash _childStatus; - QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9bcdcbe9a4..f67abdca2b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { pathString += "/" + orientationString; } else { qDebug() << "Cannot add orientation to path without a getter for position." - << "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; + << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat"; } } @@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { return pathString; } else { qDebug() << "Cannot create address path without a getter for position." - << "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; + << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; return QString(); } } From 56d237ae8bdaa7df60785b7538ddd42e36cfd8e0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:28:24 -0800 Subject: [PATCH 104/341] cleanups --- assignment-client/src/AssignmentClient.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a0304acad9..f0461663a7 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,6 @@ #include #include #include -// #include #include #include #include @@ -149,26 +148,9 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : void AssignmentClient::stopAssignmentClient() { - - // QList threads = QObject::findChildren (); - // foreach(QThread *thread, threads) { // or FileUploader* fileuploader, fileUploaders_ ? - // qDebug() << "thread " << thread->currentThreadId(); - // } - qDebug() << "Exiting."; - _requestTimer.stop(); _statsTimerACM.stop(); - - - // DependencyManager::get()->disconnect(); - // DependencyManager::get()->disconnectNotify(); - // DependencyManager::get()->disconnect(); - // DependencyManager::get()->disconnectNotify(); - - // DependencyManager::destroy(); - // DependencyManager::destroy(); - quit(); } From bd3d7124e299280ef5e2993e7131672873994f67 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:31:58 -0800 Subject: [PATCH 105/341] cleanups --- assignment-client/src/AssignmentClient.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index f0461663a7..b9f6afa5d3 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -57,7 +57,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - // auto avatarHashMap = DependencyManager::set(); // make up a uuid for this child so the parent can tell us apart. This id will be changed // when the domain server hands over an assignment. @@ -141,8 +140,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); - // DependencyManager::get(); + // Hook up a timer to send this child's status to the Monitor once per second setUpStatsToMonitor(); } From 907be67135719e4e6ba01c4f10487db8a083e71f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:34:51 -0800 Subject: [PATCH 106/341] cleanups --- assignment-client/src/AssignmentClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index b9f6afa5d3..465078099f 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -193,7 +193,7 @@ void AssignmentClient::sendAssignmentRequest() { localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); @@ -203,7 +203,7 @@ void AssignmentClient::sendAssignmentRequest() { qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } } - + nodeList->sendAssignment(_requestAssignment); } } From 4bba4fc387ab9c83547d65a4fd2531d3a2334607 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 13:44:37 -0800 Subject: [PATCH 107/341] cleanups --- assignment-client/src/AssignmentClient.cpp | 2 +- assignment-client/src/AssignmentClientMonitor.cpp | 15 +++++---------- assignment-client/src/AssignmentClientMonitor.h | 3 --- domain-server/src/DomainServer.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 3 +-- 5 files changed, 8 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 465078099f..cf4b305bb0 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -203,7 +203,7 @@ void AssignmentClient::sendAssignmentRequest() { qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); } } - + nodeList->sendAssignment(_requestAssignment); } } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 94975b0a4d..32830e2bb3 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -13,10 +13,7 @@ #include #include - - -#include // XXX need this? - +#include #include "AssignmentClientMonitor.h" #include "PacketHeaders.h" @@ -52,7 +49,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); - // auto nodeList = DependencyManager::set(NodeType::Unassigned); auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); @@ -89,7 +85,7 @@ void AssignmentClientMonitor::spawnChildClient() { // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - + assignmentClient->start(applicationFilePath(), _childArguments); qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } @@ -102,8 +98,6 @@ void AssignmentClientMonitor::checkSpares() { nodeList->removeSilentNodes(); - qDebug() << "check spares:"; - nodeList->eachNode([&](const SharedNodePointer& node){ AssignmentClientChildData *childData = static_cast(node->getLinkedData()); qDebug() << " " << node->getUUID() << childData->getChildType(); @@ -113,10 +107,11 @@ void AssignmentClientMonitor::checkSpares() { } }); - qDebug() << " spare count is" << spareCount; + if (spareCount != 1) { + qDebug() << " spare count is" << spareCount; + } if (spareCount < 1) { - qDebug() << "FORK"; spawnChildClient(); } diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index a91dfa93cc..8055b5d81f 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -45,14 +45,11 @@ public: void stopChildProcesses(); private slots: - // void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams(); void checkSpares(); private: void spawnChildClient(); - // QList > _childProcesses; - QStringList _childArguments; QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 30d6dd4348..64e0d335b1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -244,7 +244,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateStaticScriptedAssignmentsFromSettings(); auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); - + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index e7ccbe7746..b53287562b 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -25,9 +25,8 @@ #include #include #include -#include - #include +#include #include From 5e264f8241f7e6e8055def0fc1ae0c6604f18339 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 13:47:38 -0800 Subject: [PATCH 108/341] add GLEW as dependency external project --- BUILD_WIN.md | 20 +------------------- cmake/externals/glew/CMakeLists.txt | 26 ++++++++++++++++++++++++++ cmake/modules/FindGLEW.cmake | 15 +++++++++------ interface/CMakeLists.txt | 8 +++----- libraries/gpu/CMakeLists.txt | 8 ++------ libraries/render-utils/CMakeLists.txt | 7 +------ tests/render-utils/CMakeLists.txt | 5 ----- 7 files changed, 42 insertions(+), 47 deletions(-) create mode 100644 cmake/externals/glew/CMakeLists.txt diff --git a/BUILD_WIN.md b/BUILD_WIN.md index f6d484fcd1..6956abbc5f 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,9 +1,5 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file. -###Windows Specific Dependencies -* [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 -* (remember that you need all other dependencies listed in [BUILD.md](BUILD.md)) - ###Visual Studio 2013 You can use the Community or Professional editions of Visual Studio 2013. @@ -44,18 +40,10 @@ We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets req The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir - -> glew - -> bin - -> include - -> lib -> openssl -> bin -> include -> lib - -> zlib - -> include - -> lib - -> test For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. @@ -79,16 +67,10 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. -####GLEW - -Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). - -Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` - ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. - cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 12" + cmake .. -G "Visual Studio 12" Open %HIFI_DIR%\build\hifi.sln and compile. diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt new file mode 100644 index 0000000000..ca0311cff5 --- /dev/null +++ b/cmake/externals/glew/CMakeLists.txt @@ -0,0 +1,26 @@ +if (WIN32) + set(EXTERNAL_NAME glm) + + include(ExternalProject) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/glew-1.10.0-win32.zip + URL_MD5 37514e4e595a3b3dc587eee8f7e8ec2f + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + + string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of glew include directories") + + set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) + + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32s.lib CACHE FILEPATH "Location of GLEW release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_LIB_DIR}/glew32sd.lib CACHE FILEPATH "Location of GLEW debug library") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") +endif () \ No newline at end of file diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 363f346d09..14ea8e52db 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -27,13 +27,16 @@ if (WIN32) find_library(GLEW_LIBRARY_RELEASE glew32s PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) find_library(GLEW_LIBRARY_DEBUG glew32sd PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) + find_path(GLEW_DLL_PATH glew32.dll PATH_SUFFIXES "bin/Release/Win32" HINTS ${GLEW_SEARCH_DIRS}) + include(SelectLibraryConfigurations) select_library_configurations(GLEW) + + set(GLEW_LIBRARIES ${GLEW_LIBRARY}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES GLEW_DLL_PATH) + + add_paths_to_lib_paths(${GLEW_DLL_PATH}) endif () -set(GLEW_LIBRARIES ${GLEW_LIBRARY}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES) - -mark_as_advanced(GLEW_INCLUDE_DIRS GLEW_LIBRARIES GLEW_SEARCH_DIRS) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index fb29667e09..446a816d1b 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -219,13 +219,11 @@ else (APPLE) # link target to external libraries if (WIN32) + add_dependency_external_projects(glew) find_package(GLEW REQUIRED) - include_directories(${GLEW_INCLUDE_DIRS}) + target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS}) - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) - - target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} "${NSIGHT_LIBRARIES}" wsock32.lib opengl32.lib Winmm.lib) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} ${NSIGHT_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 6e7a38f594..7b1d6e743a 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -11,15 +11,11 @@ if (APPLE) target_link_libraries(${TARGET_NAME} ${OpenGL}) elseif (WIN32) + add_dependency_external_projects(glew) find_package(GLEW REQUIRED) - include_directories(${GLEW_INCLUDE_DIRS}) - - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) + target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) - - target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index b266c001e4..9a08b8c7ed 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -12,9 +12,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(animation fbx shared gpu) - -if (WIN32) - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) -endif () +link_hifi_libraries(animation fbx shared gpu) \ No newline at end of file diff --git a/tests/render-utils/CMakeLists.txt b/tests/render-utils/CMakeLists.txt index d55d3c542b..0452fd629c 100644 --- a/tests/render-utils/CMakeLists.txt +++ b/tests/render-utils/CMakeLists.txt @@ -7,9 +7,4 @@ setup_hifi_project(Quick Gui OpenGL) # link in the shared libraries link_hifi_libraries(render-utils gpu shared) -if (WIN32) - # we're using static GLEW, so define GLEW_STATIC - add_definitions(-DGLEW_STATIC) -endif () - copy_dlls_beside_windows_executable() \ No newline at end of file From ef729201d6e44cff8d6adfc5fdaa350994792e19 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 13:51:12 -0800 Subject: [PATCH 109/341] fix external name for GLEW --- cmake/externals/glew/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index ca0311cff5..dd856cd942 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -1,5 +1,5 @@ if (WIN32) - set(EXTERNAL_NAME glm) + set(EXTERNAL_NAME glew) include(ExternalProject) ExternalProject_Add( From c242b4e834c2fd2f037b387eecff2ddc7831ac6f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 13:55:40 -0800 Subject: [PATCH 110/341] set GLEW debug version to NOTFOUND --- cmake/externals/glew/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index dd856cd942..2e198a08f3 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -20,7 +20,7 @@ if (WIN32) set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32s.lib CACHE FILEPATH "Location of GLEW release library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_LIB_DIR}/glew32sd.lib CACHE FILEPATH "Location of GLEW debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Location of GLEW debug library") set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") endif () \ No newline at end of file From b23dd28b56e9b134969eacb876d12622d2cdf658 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 14:01:01 -0800 Subject: [PATCH 111/341] don't use static version of GLEW --- cmake/externals/glew/CMakeLists.txt | 2 +- cmake/modules/FindGLEW.cmake | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index 2e198a08f3..e960eb8bcb 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -19,7 +19,7 @@ if (WIN32) set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32s.lib CACHE FILEPATH "Location of GLEW release library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32.lib CACHE FILEPATH "Location of GLEW release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Location of GLEW debug library") set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 14ea8e52db..7abbe135cb 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -24,8 +24,8 @@ if (WIN32) find_path(GLEW_INCLUDE_DIRS GL/glew.h PATH_SUFFIXES include HINTS ${GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY_RELEASE glew32s PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) - find_library(GLEW_LIBRARY_DEBUG glew32sd PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) + find_library(GLEW_LIBRARY_RELEASE glew32 PATH_SUFFIXES "lib/Release/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) + find_library(GLEW_LIBRARY_DEBUG glew32d PATH_SUFFIXES "lib/Debug/Win32" "lib" HINTS ${GLEW_SEARCH_DIRS}) find_path(GLEW_DLL_PATH glew32.dll PATH_SUFFIXES "bin/Release/Win32" HINTS ${GLEW_SEARCH_DIRS}) From 175966cce8ec9a25ca0888c5c0e0df0e660542cf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 14:19:08 -0800 Subject: [PATCH 112/341] clarify build guide for external projects --- BUILD.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/BUILD.md b/BUILD.md index dd2b65fb3b..a88d5cd22e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,9 +5,7 @@ * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. -#### CMake External Project Dependencies - -The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-externals` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-externals`. Should you want to force a re-download and re-compile of all externals, just remove the `build-externals` folder. +####CMake External Project Dependencies * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 @@ -15,7 +13,13 @@ The following dependencies will be downloaded, built, linked and included automa * [gverb](https://github.com/highfidelity/gverb) * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 -### OS Specific Build Guides +The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project. + +These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build-ext` folder. + +If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DGET_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project. + +###OS Specific Build Guides * [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. * [BUILD_LINUX.md](BUILD_LINUX.md) - additional instructions for Linux. * [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows. @@ -50,6 +54,9 @@ For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generat cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/lib/cmake ####Finding Dependencies + +The following applies for dependencies we do not grab via CMake ExternalProject (OpenSSL is an example), or for dependencies you have opted not to grab as a CMake ExternalProject (via -DGET_$NAME=0). The list of dependencies we grab by default as external projects can be found in [the CMake External Project Dependencies section](#CMake External Project Dependencies). + You can point our [Cmake find modules](cmake/modules/) to the correct version of dependencies by setting one of the three following variables to the location of the correct version of the dependency. In the examples below the variable $NAME would be replaced by the name of the dependency in uppercase, and $name would be replaced by the name of the dependency in lowercase (ex: OPENSSL_ROOT_DIR, openssl). From d6105e2e8c503a0f9d5e4192040808738831833c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 14:20:44 -0800 Subject: [PATCH 113/341] fix link to external project dependencies section --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index a88d5cd22e..6cfe5229d6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -55,7 +55,7 @@ For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generat ####Finding Dependencies -The following applies for dependencies we do not grab via CMake ExternalProject (OpenSSL is an example), or for dependencies you have opted not to grab as a CMake ExternalProject (via -DGET_$NAME=0). The list of dependencies we grab by default as external projects can be found in [the CMake External Project Dependencies section](#CMake External Project Dependencies). +The following applies for dependencies we do not grab via CMake ExternalProject (OpenSSL is an example), or for dependencies you have opted not to grab as a CMake ExternalProject (via -DGET_$NAME=0). The list of dependencies we grab by default as external projects can be found in [the CMake External Project Dependencies section](#cmake-external-project-dependencies). You can point our [Cmake find modules](cmake/modules/) to the correct version of dependencies by setting one of the three following variables to the location of the correct version of the dependency. From 70c96e496fdec6bb936102165bbcee80f3e177aa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:25:13 -0800 Subject: [PATCH 114/341] don't print ^a to qDebug for unassigned node type --- libraries/networking/src/Node.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2bf792c6ee..2a38799707 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -149,7 +149,12 @@ QDataStream& operator>>(QDataStream& in, Node& node) { } QDebug operator<<(QDebug debug, const Node &node) { - debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; + debug.nospace() << NodeType::getNodeTypeName(node.getType()); + if (node.getType() == NodeType::Unassigned) { + debug.nospace() << " (1)"; + } else { + debug.nospace() << " (" << node.getType() << ")"; + } debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); From 8cee88acb495c3a775276ee579e80a4d616af48b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:25:43 -0800 Subject: [PATCH 115/341] network chatter between Monitor and AssignmentClients is expected to be localhost only --- assignment-client/src/AssignmentClient.cpp | 9 ++++-- .../src/AssignmentClientMonitor.cpp | 28 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index cf4b305bb0..5fcc380962 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -259,8 +259,13 @@ void AssignmentClient::readPendingDatagrams() { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - qDebug() << "Network told me to exit."; - emit stopAssignmentClient(); + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + qDebug() << "Network told me to exit."; + emit stopAssignmentClient(); + } else { + qDebug() << "Got a stop packet from other than localhost."; + } } else { // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 32830e2bb3..d601990759 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -87,10 +87,12 @@ void AssignmentClientMonitor::spawnChildClient() { assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(applicationFilePath(), _childArguments); + qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } + void AssignmentClientMonitor::checkSpares() { auto nodeList = DependencyManager::get(); QUuid aSpareId = ""; @@ -100,7 +102,6 @@ void AssignmentClientMonitor::checkSpares() { nodeList->eachNode([&](const SharedNodePointer& node){ AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - qDebug() << " " << node->getUUID() << childData->getChildType(); if (childData->getChildType() == "none") { spareCount ++; aSpareId = node->getUUID(); @@ -142,17 +143,20 @@ void AssignmentClientMonitor::readPendingDatagrams() { QUuid packetUUID = uuidFromPacketHeader(receivedPacket); SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); if (!matchingNode) { - // XXX only do this if from local machine - if (!packetUUID.isNull()) { - matchingNode = DependencyManager::get()->addOrUpdateNode - (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); - AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); - matchingNode->setLinkedData(childData); - } else { - // tell unknown assignment-client child to exit. - qDebug() << "asking unknown child to exit."; - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + // The parent only expects to be talking with prorams running on this same machine. + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + if (!packetUUID.isNull()) { + matchingNode = DependencyManager::get()->addOrUpdateNode + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); + matchingNode->setLinkedData(childData); + } else { + // tell unknown assignment-client child to exit. + qDebug() << "asking unknown child to exit."; + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } } } From 270d509a1284c3b8fb3ca07e6ea077e9c7f49eb1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 20 Feb 2015 14:29:12 -0800 Subject: [PATCH 116/341] cleanups --- assignment-client/src/AssignmentClientMonitor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index d601990759..2bddab9656 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -62,7 +62,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u } connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); - _checkSparesTimer.start(5000); + _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } AssignmentClientMonitor::~AssignmentClientMonitor() { @@ -109,7 +109,7 @@ void AssignmentClientMonitor::checkSpares() { }); if (spareCount != 1) { - qDebug() << " spare count is" << spareCount; + qDebug() << "spare count is" << spareCount; } if (spareCount < 1) { From 987562976a5c09c703211440e70b57caebb61434 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 20 Feb 2015 14:46:36 -0800 Subject: [PATCH 117/341] Fixing the remaining issue with the avatar rendering path --- libraries/gpu/src/gpu/Transform.slh | 39 ++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index b433f8282d..6f0154a07d 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -24,13 +24,21 @@ struct TransformCamera { }; vec4 transformModelToClipPos(TransformCamera camera, TransformObject object, vec4 pos) { +<@if GLPROFILE == MAC_GL@> + return gl_ModelViewProjectionMatrix * pos; +<@elif GLPROFILE == PC_GL@> vec4 epos = (object._model * pos) + vec4(-pos.w * camera._viewInverse[3].xyz, 0.0); return camera._projectionViewUntranslated * epos; // Equivalent to the following but hoppefully a bit more accurate // return camera._projection * camera._view * object._model * pos; + +<@endif@> } vec3 transformModelToEyeDir(TransformCamera camera, TransformObject object, vec3 dir) { +<@if GLPROFILE == MAC_GL@> + return (gl_NormalMatrix * vec4(dir, 0.0)).xyz; +<@elif GLPROFILE == PC_GL@> vec3 mIr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); vec3 mIr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); vec3 mIr2 = vec3(object._modelInverse[0].z, object._modelInverse[1].z, object._modelInverse[2].z); @@ -44,6 +52,7 @@ vec3 transformModelToEyeDir(TransformCamera camera, TransformObject object, vec3 dot(mvIc2, dir)); return result; +<@endif@> } <@if GLPROFILE == PC_GL@> @@ -61,21 +70,27 @@ TransformCamera getTransformCamera() { return camera; } <@elif GLPROFILE == MAC_GL@> -uniform vec4 transformStateBuffer[2]; -TransformState getTransformState() { - TransformState xform; - xform._diffuse = transformStateBuffer[0]; - xform._specular = transformStateBuffer[1]; - return xform; +TransformObject getTransformObject() { + TransformObject object; + return object; +} + +TransformCamera getTransformCamera() { + TransformCamera camera; + return camera; } <@else@> -uniform vec4 transformStateBuffer[2]; -TransformState getMaterial() { - TransformState xform; - xform._diffuse = transformStateBuffer[0]; - xform._specular = transformStateBuffer[1]; - return xform; + +TransformObject getTransformObject() { + TransformObject object; + return object; } + +TransformCamera getTransformCamera() { + TransformCamera camera; + return camera; +} + <@endif@> From 05ae1b6fe699e795d9e8c9d59575f84804fc2eef Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 20 Feb 2015 15:20:34 -0800 Subject: [PATCH 118/341] fixing the mac osx code path for Transform --- libraries/gpu/src/gpu/Transform.slh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 6f0154a07d..e9c8a7984a 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -37,7 +37,7 @@ vec4 transformModelToClipPos(TransformCamera camera, TransformObject object, vec vec3 transformModelToEyeDir(TransformCamera camera, TransformObject object, vec3 dir) { <@if GLPROFILE == MAC_GL@> - return (gl_NormalMatrix * vec4(dir, 0.0)).xyz; + return gl_NormalMatrix * dir; <@elif GLPROFILE == PC_GL@> vec3 mIr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); vec3 mIr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); From bc0bd462cbe5f4b5ddaa5570137e0328fddc0177 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 15:26:16 -0800 Subject: [PATCH 119/341] add an external project for SDL 2 --- CMakeLists.txt | 3 ++ cmake/externals/sdl2/CMakeLists.txt | 50 +++++++++++++++++++++++++++++ cmake/modules/FindSDL2.cmake | 49 ---------------------------- interface/CMakeLists.txt | 2 ++ 4 files changed, 55 insertions(+), 49 deletions(-) create mode 100644 cmake/externals/sdl2/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 563ece524f..574bf0a344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,9 @@ set(EXTERNAL_PROJECT_PREFIX "project") set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX}) setup_externals_binary_dir() +# setup for optional external project dependencies +option(GET_SDL2 "Download SDL2 as external project" 0) + if (WIN32) add_paths_to_lib_paths("${QT_DIR}/bin") endif () diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt new file mode 100644 index 0000000000..00936a8320 --- /dev/null +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -0,0 +1,50 @@ +set(EXTERNAL_NAME sdl2) + +include(ExternalProject) + +if (WIN32) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip + URL_MD5 30a333bcbe94bc5016e8799c73e86233 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) +else () + if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") + endif () + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://www.libsdl.org/release/SDL2-2.0.3.tar.gz + URL_MD5 fe6c61d2e9df9ef570e7e80c6e822537 + CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + ) +endif () + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +if (WIN32) + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + set(_ROOT_DIR ${SOURCE_DIR}) + set(_LIB_DIR "${SOURCE_DIR}/lib/x86") + set(_LIB_EXT "lib") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of SDL2 DLL") +else () + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + set(_ROOT_DIR ${INSTALL_DIR}) + + set(_LIB_DIR ${INSTALL_DIR}/lib) + set(_LIB_EXT "so") + set(_LIB_PREFIX "lib") +endif () + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${_LIB_DIR}/${_LIB_PREFIX}SDL2.${_LIB_EXT} CACHE FILEPATH "Path to SDL2 library") \ No newline at end of file diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index 55dae82f82..8c7c0c581b 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -163,48 +163,6 @@ ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) endif () ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) -IF(NOT SDL2_BUILDING_LIBRARY) - IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") - # Non-OS X framework versions expect you to also dynamically link to - # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms - # seem to provide SDL2main for compatibility even though they don't - # necessarily need it. - # Lookup the 64 bit libs on x64 - IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - FIND_LIBRARY(SDL2MAIN_LIBRARY - NAMES SDL2main - HINTS - ${SDL2_SEARCH_DIRS} - $ENV{SDL2} - PATH_SUFFIXES lib64 lib - lib/x64 - x86_64-w64-mingw32/lib - PATHS - /sw - /opt/local - /opt/csw - /opt - ) - # On 32bit build find the 32bit libs - ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) - FIND_LIBRARY(SDL2MAIN_LIBRARY - NAMES SDL2main - HINTS - ${SDL2_SEARCH_DIRS} - $ENV{SDL2} - PATH_SUFFIXES lib - lib/x86 - i686-w64-mingw32/lib - PATHS - /sw - /opt/local - /opt/csw - /opt - ) - ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) - ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") -ENDIF(NOT SDL2_BUILDING_LIBRARY) - # SDL2 may require threads on your system. # The Apple build may not need an explicit flag because one of the # frameworks may already provide it. @@ -222,13 +180,6 @@ ENDIF(MINGW) SET(SDL2_FOUND "NO") IF(SDL2_LIBRARY_TEMP) - # For SDL2main - IF(NOT SDL2_BUILDING_LIBRARY) - IF(SDL2MAIN_LIBRARY) - SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) - ENDIF(SDL2MAIN_LIBRARY) - ENDIF(NOT SDL2_BUILDING_LIBRARY) - # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. # CMake doesn't display the -framework Cocoa string in the UI even # though it actually is there if I modify a pre-used variable. diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 446a816d1b..0cff232f26 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -119,6 +119,8 @@ link_hifi_libraries(shared octree environment gpu model fbx metavoxels networkin audio audio-client animation script-engine physics render-utils entities-renderer) +add_dependency_external_projects(sdl2) + # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) From 0b607fa390462ff08e3142df2ac5d5d10523c385 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 20 Feb 2015 15:28:25 -0800 Subject: [PATCH 120/341] first cut at shutting down scripts ahead of other cleanup --- interface/src/Application.cpp | 18 +- .../src/EntityTreeRenderer.cpp | 329 ++++++++++-------- .../src/EntityTreeRenderer.h | 3 + libraries/script-engine/src/ScriptEngine.cpp | 58 ++- libraries/script-engine/src/ScriptEngine.h | 10 + 5 files changed, 270 insertions(+), 148 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1211df3727..ecb74392a6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -527,12 +527,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : } void Application::aboutToQuit() { +qDebug() << "Application::aboutToQuit()"; _aboutToQuit = true; cleanupBeforeQuit(); } void Application::cleanupBeforeQuit() { + qDebug() << "Application::cleanupBeforeQuit() ------------ START -----------------"; + + // stop entities running scripts + _entities.shutdown(); + + // stop all running scripts + ScriptEngine::gracefullyStopAllScripts(); + + // first stop all timers directly or by invokeMethod // depending on what thread they run in locationUpdateTimer->stop(); @@ -572,6 +582,8 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); + + qDebug() << "Application::cleanupBeforeQuit() ------------ DONE -----------------"; } Application::~Application() { @@ -3432,6 +3444,7 @@ void Application::clearScriptsBeforeRunning() { } void Application::saveScripts() { +qDebug() << "Application::saveScripts()"; // Saves all currently running user-loaded scripts Settings settings; settings.beginWriteArray(SETTINGS_KEY); @@ -3525,7 +3538,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri #endif QThread* workerThread = new QThread(this); - workerThread->setObjectName("Script Engine Thread"); + QString scriptEngineName = QString("Script Thread:") + scriptEngine->getFilename(); + workerThread->setObjectName(scriptEngineName); // when the worker thread is started, call our engine's run.. connect(workerThread, &QThread::started, scriptEngine, &ScriptEngine::run); @@ -3599,6 +3613,7 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { } void Application::scriptFinished(const QString& scriptName) { + qDebug() << "Application::scriptFinished(), scriptName:" << scriptName; const QString& scriptURLString = QUrl(scriptName).toString(); QHash::iterator it = _scriptEnginesHash.find(scriptURLString); if (it != _scriptEnginesHash.end()) { @@ -3609,6 +3624,7 @@ void Application::scriptFinished(const QString& scriptName) { } void Application::stopAllScripts(bool restart) { + qDebug() << "Application::stopAllScripts()... restart:" << restart; // stops all current running scripts for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 975d0f515d..b0396f32d6 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -97,6 +97,27 @@ void EntityTreeRenderer::init() { connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID); } +void EntityTreeRenderer::shutdown() { + _shuttingDown = true; + + /* + if (_entitiesScriptEngine) { + _entitiesScriptEngine->stop(); + + QEventLoop loop; + QObject::connect(_entitiesScriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); + + _entitiesScriptEngine->stop(); + + qDebug() << "waiting on Entities sandbox script to stop... "; + loop.exec(); + qDebug() << "done waiting... "; + + } + */ +} + + QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItemID) { EntityItem* entity = static_cast(_tree)->findEntityByEntityItemID(entityItemID); return loadEntityScript(entity); @@ -156,6 +177,10 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { + if (_shuttingDown) { + return QScriptValue(); // no entity... + } + if (!entity) { return QScriptValue(); // no entity... } @@ -235,7 +260,7 @@ void EntityTreeRenderer::setTree(Octree* newTree) { } void EntityTreeRenderer::update() { - if (_tree) { + if (_tree && !_shuttingDown) { EntityTree* tree = static_cast(_tree); tree->update(); @@ -258,7 +283,7 @@ void EntityTreeRenderer::update() { } void EntityTreeRenderer::checkEnterLeaveEntities() { - if (_tree) { + if (_tree && !_shuttingDown) { _tree->lockForWrite(); // so that our scripts can do edits if they want glm::vec3 avatarPosition = _viewState->getAvatarPosition() / (float) TREE_SCALE; @@ -309,7 +334,7 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { } void EntityTreeRenderer::leaveAllEntities() { - if (_tree) { + if (_tree && !_shuttingDown) { _tree->lockForWrite(); // so that our scripts can do edits if they want // for all of our previous containing entities, if they are no longer containing then send them a leave event @@ -330,7 +355,7 @@ void EntityTreeRenderer::leaveAllEntities() { } } void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { - if (_tree) { + if (_tree && !_shuttingDown) { Model::startScene(renderSide); RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -700,179 +725,193 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity } void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { - PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); - PickRay ray = _viewState->computePickRay(event->x(), event->y()); + if (_tree && !_shuttingDown) { + PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); - bool precisionPicking = !_dontDoPrecisionPicking; - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); - if (rayPickResult.intersects) { - //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; - emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + bool precisionPicking = !_dontDoPrecisionPicking; + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); + if (rayPickResult.intersects) { + //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; + emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mousePressOnEntity").isValid()) { - entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs); - } + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mousePressOnEntity").isValid()) { + entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs); + } - _currentClickingOnEntityID = rayPickResult.entityID; - emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - if (entityScript.property("clickDownOnEntity").isValid()) { - entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs); + _currentClickingOnEntityID = rayPickResult.entityID; + emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + if (entityScript.property("clickDownOnEntity").isValid()) { + entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs); + } } + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; } - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; } void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { - PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); - PickRay ray = _viewState->computePickRay(event->x(), event->y()); - bool precisionPicking = !_dontDoPrecisionPicking; - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); - if (rayPickResult.intersects) { - //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; - emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (_tree && !_shuttingDown) { + PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); + bool precisionPicking = !_dontDoPrecisionPicking; + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); + if (rayPickResult.intersects) { + //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; + emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mouseReleaseOnEntity").isValid()) { - entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs); + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mouseReleaseOnEntity").isValid()) { + entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs); + } } - } - // Even if we're no longer intersecting with an entity, if we started clicking on it, and now - // we're releasing the button, then this is considered a clickOn event - if (!_currentClickingOnEntityID.isInvalidID()) { - emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + // Even if we're no longer intersecting with an entity, if we started clicking on it, and now + // we're releasing the button, then this is considered a clickOn event + if (!_currentClickingOnEntityID.isInvalidID()) { + emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); - QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); - if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) { - currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); + QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); + if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) { + currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + } } - } - // makes it the unknown ID, we just released so we can't be clicking on anything - _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; + // makes it the unknown ID, we just released so we can't be clicking on anything + _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; + } } void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); + if (_tree && !_shuttingDown) { + PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); - PickRay ray = _viewState->computePickRay(event->x(), event->y()); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); - bool precisionPicking = false; // for mouse moves we do not do precision picking - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); - if (rayPickResult.intersects) { - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + bool precisionPicking = false; // for mouse moves we do not do precision picking + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); + if (rayPickResult.intersects) { + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - // load the entity script if needed... - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mouseMoveEvent").isValid()) { - entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs); - } + // load the entity script if needed... + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mouseMoveEvent").isValid()) { + entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs); + } - //qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID; - emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("mouseMoveOnEntity").isValid()) { - entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs); - } + //qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID; + emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("mouseMoveOnEntity").isValid()) { + entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs); + } - // handle the hover logic... + // handle the hover logic... - // if we were previously hovering over an entity, and this new entity is not the same as our previous entity - // then we need to send the hover leave. - if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); + // if we were previously hovering over an entity, and this new entity is not the same as our previous entity + // then we need to send the hover leave. + if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); + QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); - QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); - if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { - currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); - } - } - - // If the new hover entity does not match the previous hover entity then we are entering the new one - // this is true if the _currentHoverOverEntityID is known or unknown - if (rayPickResult.entityID != _currentHoverOverEntityID) { - emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("hoverEnterEntity").isValid()) { - entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs); - } - } - - // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and - // we should send our hover over event - emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("hoverOverEntity").isValid()) { - entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs); - } - - // remember what we're hovering over - _currentHoverOverEntityID = rayPickResult.entityID; - - } else { - // handle the hover logic... - // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to - // send the hover leave for our previous entity - if (!_currentHoverOverEntityID.isInvalidID()) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - - QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); - - QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); - if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { - currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); + QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); + if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { + currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); + } } - _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID + // If the new hover entity does not match the previous hover entity then we are entering the new one + // this is true if the _currentHoverOverEntityID is known or unknown + if (rayPickResult.entityID != _currentHoverOverEntityID) { + emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("hoverEnterEntity").isValid()) { + entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs); + } + } + + // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and + // we should send our hover over event + emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("hoverOverEntity").isValid()) { + entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs); + } + + // remember what we're hovering over + _currentHoverOverEntityID = rayPickResult.entityID; + + } else { + // handle the hover logic... + // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to + // send the hover leave for our previous entity + if (!_currentHoverOverEntityID.isInvalidID()) { + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); + + QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); + + QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); + if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { + currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); + } + + _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID + } } - } - // Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have - // not yet released the hold then this is still considered a holdingClickOnEntity event - if (!_currentClickingOnEntityID.isInvalidID()) { - emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + // Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have + // not yet released the hold then this is still considered a holdingClickOnEntity event + if (!_currentClickingOnEntityID.isInvalidID()) { + emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); + QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); - QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); - if (currentClickingEntity.property("holdingClickOnEntity").isValid()) { - currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); + if (currentClickingEntity.property("holdingClickOnEntity").isValid()) { + currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + } } + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; } - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; } void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { - checkAndCallUnload(entityID); + if (_tree && !_shuttingDown) { + checkAndCallUnload(entityID); + } _entityScripts.remove(entityID); } void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) { - checkAndCallUnload(entityID); + if (_tree && !_shuttingDown) { + checkAndCallUnload(entityID); + } checkAndCallPreload(entityID); } void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) { - // load the entity script if needed... - QScriptValue entityScript = loadEntityScript(entityID); - if (entityScript.property("preload").isValid()) { - QScriptValueList entityArgs = createEntityArgs(entityID); - entityScript.property("preload").call(entityScript, entityArgs); + if (_tree && !_shuttingDown) { + // load the entity script if needed... + QScriptValue entityScript = loadEntityScript(entityID); + if (entityScript.property("preload").isValid()) { + QScriptValueList entityArgs = createEntityArgs(entityID); + entityScript.property("preload").call(entityScript, entityArgs); + } } } void EntityTreeRenderer::checkAndCallUnload(const EntityItemID& entityID) { - QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID); - if (entityScript.property("unload").isValid()) { - QScriptValueList entityArgs = createEntityArgs(entityID); - entityScript.property("unload").call(entityScript, entityArgs); + if (_tree && !_shuttingDown) { + QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID); + if (entityScript.property("unload").isValid()) { + QScriptValueList entityArgs = createEntityArgs(entityID); + entityScript.property("unload").call(entityScript, entityArgs); + } } } @@ -887,22 +926,24 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { - QScriptValue entityScriptA = loadEntityScript(idA); - if (entityScriptA.property("collisionWithEntity").isValid()) { - QScriptValueList args; - args << idA.toScriptValue(_entitiesScriptEngine); - args << idB.toScriptValue(_entitiesScriptEngine); - args << collisionToScriptValue(_entitiesScriptEngine, collision); - entityScriptA.property("collisionWithEntity").call(entityScriptA, args); - } + if (_tree && !_shuttingDown) { + QScriptValue entityScriptA = loadEntityScript(idA); + if (entityScriptA.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idA.toScriptValue(_entitiesScriptEngine); + args << idB.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptA.property("collisionWithEntity").call(entityScriptA, args); + } - QScriptValue entityScriptB = loadEntityScript(idB); - if (entityScriptB.property("collisionWithEntity").isValid()) { - QScriptValueList args; - args << idB.toScriptValue(_entitiesScriptEngine); - args << idA.toScriptValue(_entitiesScriptEngine); - args << collisionToScriptValue(_entitiesScriptEngine, collision); - entityScriptB.property("collisionWithEntity").call(entityScriptA, args); + QScriptValue entityScriptB = loadEntityScript(idB); + if (entityScriptB.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idB.toScriptValue(_entitiesScriptEngine); + args << idA.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptB.property("collisionWithEntity").call(entityScriptA, args); + } } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 3826a80238..0da85f360b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -46,6 +46,7 @@ public: virtual int getBoundaryLevelAdjust() const; virtual void setTree(Octree* newTree); + void shutdown(); void update(); EntityTree* getTree() { return static_cast(_tree); } @@ -154,6 +155,8 @@ private: bool _displayModelElementProxy; bool _dontDoPrecisionPicking; + bool _shuttingDown = false; + }; #endif // hifi_EntityTreeRenderer_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0956374238..63ecea4254 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,8 +94,45 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { + _allKnownScriptEngines.insert(this); } +ScriptEngine::~ScriptEngine() { + qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::~ScriptEngine() " << getFilename(); + _allKnownScriptEngines.remove(this); +} + +QSet ScriptEngine::_allKnownScriptEngines; + +void ScriptEngine::gracefullyStopAllScripts() { + qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------"; + foreach(ScriptEngine* scriptEngine, _allKnownScriptEngines) { + if (scriptEngine->isRunning()) { + qDebug() << "scriptEngine still alive:" << scriptEngine->getFilename() << "[" << scriptEngine << "]"; + + QEventLoop loop; + QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); + + scriptEngine->stop(); + + qDebug() << "waiting on script to stop... "; + loop.exec(); + qDebug() << "done waiting... "; + } + } + qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- DONE ------------------"; +} + +QString ScriptEngine::getFilename() const { + QStringList fileNameParts = _fileNameString.split("/"); + QString lastPart; + if (!fileNameParts.isEmpty()) { + lastPart = fileNameParts.last(); + } + return lastPart; +} + + void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; @@ -364,16 +401,18 @@ void ScriptEngine::run() { } if (_isFinished) { + qDebug() << "ScriptEngine::run()... while() about to break " << getFilename(); break; } QCoreApplication::processEvents(); if (_isFinished) { + qDebug() << "ScriptEngine::run()... while() about to break " << getFilename(); break; } - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { + if (!_isFinished && _entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); @@ -383,7 +422,7 @@ void ScriptEngine::run() { } } - if (_isAvatar && _avatarData) { + if (!_isFinished && _isAvatar && _avatarData) { const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE) / (1000 * 1000)) + 0.5); @@ -493,9 +532,13 @@ void ScriptEngine::run() { clearExceptions(); } - emit update(deltaTime); + if (!_isFinished) { + //qDebug() << "ScriptEngine::run()... about to emit update() _scriptName:" << _scriptName << "_fileNameString:" << _fileNameString << "_isFinished:" << _isFinished; + emit update(deltaTime); + } lastUpdate = now; } + qDebug() << "ScriptEngine::run()... about to emit scriptEnding() " << getFilename(); emit scriptEnding(); // kill the avatar identity timer @@ -513,16 +556,25 @@ void ScriptEngine::run() { // If we were on a thread, then wait till it's done if (thread()) { + qDebug() << "ScriptEngine::run()... about to call thread()->quit() " << getFilename(); thread()->quit(); } + qDebug() << "ScriptEngine::run()... about to emit finished() " << getFilename(); emit finished(_fileNameString); _isRunning = false; + + qDebug() << "ScriptEngine::run()... about to emit runningStateChanged() " << getFilename(); emit runningStateChanged(); + + qDebug() << "ScriptEngine::run()... about to emit doneRunning() " << getFilename(); + emit doneRunning(); + qDebug() << "ScriptEngine::run()... DONE WITH run()... " << getFilename(); } void ScriptEngine::stop() { + qDebug() << "ScriptEngine::stop()... " << getFilename(); _isFinished = true; emit runningStateChanged(); } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index f2911842e6..f3289a8c70 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -43,6 +43,8 @@ public: const QString& fileNameString = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); + ~ScriptEngine(); + /// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; } @@ -88,6 +90,10 @@ public: bool isUserLoaded() const { return _isUserLoaded; } void setParentURL(const QString& parentURL) { _parentURL = parentURL; } + + QString getFilename() const; + + static void gracefullyStopAllScripts(); public slots: void loadURL(const QUrl& scriptURL); @@ -118,6 +124,7 @@ signals: void runningStateChanged(); void evaluationFinished(QScriptValue result, bool isException); void loadScript(const QString& scriptName, bool isUserLoaded); + void doneRunning(); protected: QString _scriptContents; @@ -156,6 +163,9 @@ private: QHash _outgoingScriptAudioSequenceNumbers; private slots: void handleScriptDownload(); + +private: + static QSet _allKnownScriptEngines; }; #endif // hifi_ScriptEngine_h From dc9c4ea43ce1a04b7cdeef0d17f8b710e4c00216 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 15:34:41 -0800 Subject: [PATCH 121/341] add options with default for get of external projects --- CMakeLists.txt | 14 ++++++++++++-- cmake/macros/AddDependencyExternalProjects.cmake | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 574bf0a344..22062caa6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,8 +126,18 @@ set(EXTERNAL_PROJECT_PREFIX "project") set_property(DIRECTORY PROPERTY EP_PREFIX ${EXTERNAL_PROJECT_PREFIX}) setup_externals_binary_dir() -# setup for optional external project dependencies -option(GET_SDL2 "Download SDL2 as external project" 0) +# setup options to grab external project dependencies +option(GET_BULLET "Get Bullet library automatically as external project" 1) +option(GET_GLM "Get GLM library automatically as external project" 1) +option(GET_GVERB "Get Gverb library automatically as external project" 1) +option(GET_SOXR "Get Soxr library automatically as external project" 1) +option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1) + +if (WIN32) + option(GET_GLEW "Get GLEW library automatically as external project" 1) +endif () + +option(GET_SDL2 "Get SDL2 library automatically as external project" 0) if (WIN32) add_paths_to_lib_paths("${QT_DIR}/bin") diff --git a/cmake/macros/AddDependencyExternalProjects.cmake b/cmake/macros/AddDependencyExternalProjects.cmake index 464652a5b7..e859ef2db5 100644 --- a/cmake/macros/AddDependencyExternalProjects.cmake +++ b/cmake/macros/AddDependencyExternalProjects.cmake @@ -16,7 +16,7 @@ macro(ADD_DEPENDENCY_EXTERNAL_PROJECTS) string(TOUPPER ${_PROJ_NAME} _PROJ_NAME_UPPER) # has the user told us they specific don't want this as an external project? - if (NOT DEFINED GET_${_PROJ_NAME_UPPER} OR GET_${_PROJ_NAME_UPPER}) + if (GET_${_PROJ_NAME_UPPER}) # have we already detected we can't have this as external project on this OS? if (NOT DEFINED ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT OR ${_PROJ_NAME_UPPER}_EXTERNAL_PROJECT) # have we already setup the target? From fd8e9bad20d45c646e613478bda811b74cc91dad Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 15:36:59 -0800 Subject: [PATCH 122/341] fix casing in find modules for gverb and soxr --- cmake/modules/FindGverb.cmake | 2 +- cmake/modules/FindSoxr.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/modules/FindGverb.cmake b/cmake/modules/FindGverb.cmake index e54fba8083..0c149a7ca1 100644 --- a/cmake/modules/FindGverb.cmake +++ b/cmake/modules/FindGverb.cmake @@ -22,4 +22,4 @@ find_path(GVERB_INCLUDE_DIRS gverb.h PATH_SUFFIXES include HINTS ${GVERB_SEARCH_ find_library(GVERB_LIBRARIES gverb PATH_SUFFIXES lib HINTS ${GVERB_SEARCH_DIRS}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GVERB DEFAULT_MSG GVERB_INCLUDE_DIRS GVERB_LIBRARIES) \ No newline at end of file +find_package_handle_standard_args(Gverb DEFAULT_MSG GVERB_INCLUDE_DIRS GVERB_LIBRARIES) \ No newline at end of file diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index b36c9465b7..1c67650496 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -34,7 +34,7 @@ if (WIN32) endif () include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SOXR DEFAULT_MSG ${SOXR_REQUIREMENTS}) +find_package_handle_standard_args(Soxr DEFAULT_MSG ${SOXR_REQUIREMENTS}) if (WIN32) add_paths_to_lib_paths(${SOXR_DLL_PATH}) From b219937902d30e706eeb40463a02f5f203b592c8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 20 Feb 2015 15:46:11 -0800 Subject: [PATCH 123/341] switch known scripts iterator --- libraries/script-engine/src/ScriptEngine.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 63ecea4254..e4401bd4b4 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -106,7 +106,12 @@ QSet ScriptEngine::_allKnownScriptEngines; void ScriptEngine::gracefullyStopAllScripts() { qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------"; - foreach(ScriptEngine* scriptEngine, _allKnownScriptEngines) { + + QSet::const_iterator i = _allKnownScriptEngines.constBegin(); + while (i != _allKnownScriptEngines.constEnd()) { + ScriptEngine* scriptEngine = *i; + qDebug() << scriptEngine; + if (scriptEngine->isRunning()) { qDebug() << "scriptEngine still alive:" << scriptEngine->getFilename() << "[" << scriptEngine << "]"; @@ -119,6 +124,8 @@ void ScriptEngine::gracefullyStopAllScripts() { loop.exec(); qDebug() << "done waiting... "; } + + ++i; } qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- DONE ------------------"; } From c64f172311997aedd81cdd97cc307a147b5b32bd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 20 Feb 2015 16:06:37 -0800 Subject: [PATCH 124/341] add qxmpp as external project --- CMakeLists.txt | 1 + cmake/externals/qxmpp/CMakeLists.txt | 47 ++++++++++++++++++++++++++++ cmake/externals/qxmpp/qxmpp.patch | 13 ++++++++ interface/CMakeLists.txt | 2 +- 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 cmake/externals/qxmpp/CMakeLists.txt create mode 100644 cmake/externals/qxmpp/qxmpp.patch diff --git a/CMakeLists.txt b/CMakeLists.txt index 22062caa6c..a79476f17f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,7 @@ if (WIN32) endif () option(GET_SDL2 "Get SDL2 library automatically as external project" 0) +option(GET_QXMPP "GET Qxmpp library automatically as external project" 0) if (WIN32) add_paths_to_lib_paths("${QT_DIR}/bin") diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt new file mode 100644 index 0000000000..ddac75569b --- /dev/null +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -0,0 +1,47 @@ +set(EXTERNAL_NAME qxmpp) + +# we need to find qmake inside QT_DIR +find_program(QMAKE_COMMAND NAME qmake PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + +if (NOT QMAKE_COMMAND) + message(FATAL_ERROR "Could not find qmake. Qxmpp cannot be compiled without qmake.") +endif () + +if (ANDROID) + set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") +endif () + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://qxmpp.googlecode.com/files/qxmpp-0.7.6.tar.gz + URL_MD5 ee45a97313306ded2ff0f6618a3ed1e1 + BUILD_IN_SOURCE 1 + PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch + CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") + +if (WIN32) + set(_LIB_EXT "lib") + + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of QXmpp DLL") +else () + if (APPLE) + set(_LIB_EXT "dylib") + else () + set(_LIB_EXT "so") + endif () + + set(_LIB_PREFIX "lib") +endif () + +set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_PREFIX}qxmpp.${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Path to QXmpp debug library") diff --git a/cmake/externals/qxmpp/qxmpp.patch b/cmake/externals/qxmpp/qxmpp.patch new file mode 100644 index 0000000000..ca2f455817 --- /dev/null +++ b/cmake/externals/qxmpp/qxmpp.patch @@ -0,0 +1,13 @@ +diff --git a/qxmpp-0.7.6/src/src.pro b/qxmpp-0.7.6-patch/src/src.pro +index 954738c..8404c8c 100644 +--- a/qxmpp-0.7.6/src/src.pro ++++ b/qxmpp-0.7.6-patch/src/src.pro +@@ -4,7 +4,7 @@ QT -= gui + + TEMPLATE = lib + +-CONFIG += $$QXMPP_LIBRARY_TYPE ++CONFIG += $$QXMPP_LIBRARY_TYPE c++11 + DEFINES += QXMPP_BUILD + DEFINES += $$QXMPP_INTERNAL_DEFINES + INCLUDEPATH += $$QXMPP_INCLUDEPATH $$QXMPP_INTERNAL_INCLUDES diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0cff232f26..2e0120dfc8 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -119,7 +119,7 @@ link_hifi_libraries(shared octree environment gpu model fbx metavoxels networkin audio audio-client animation script-engine physics render-utils entities-renderer) -add_dependency_external_projects(sdl2) +add_dependency_external_projects(sdl2 qxmpp) # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) From 8c4474b2d0a88d083e330f50856b2306d15f6be7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 20 Feb 2015 17:55:04 -0800 Subject: [PATCH 125/341] more hacking --- interface/src/Application.cpp | 4 ++-- libraries/script-engine/src/ScriptEngine.cpp | 18 +++++++++++------- libraries/script-engine/src/ScriptEngine.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ecb74392a6..e7b71afd93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -540,7 +540,7 @@ void Application::cleanupBeforeQuit() { _entities.shutdown(); // stop all running scripts - ScriptEngine::gracefullyStopAllScripts(); + ScriptEngine::gracefullyStopAllScripts(this); // first stop all timers directly or by invokeMethod @@ -3545,7 +3545,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(workerThread, &QThread::started, scriptEngine, &ScriptEngine::run); // when the thread is terminated, add both scriptEngine and thread to the deleteLater queue - connect(scriptEngine, SIGNAL(finished(const QString&)), scriptEngine, SLOT(deleteLater())); + connect(scriptEngine, SIGNAL(doneRunning()), scriptEngine, SLOT(deleteLater())); connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); // when the application is about to quit, stop our script engine so it unwinds properly diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e4401bd4b4..5cbf0b1149 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,6 +94,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { + qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::ScriptEngine() " << getFilename() << "[" << this << "]"; _allKnownScriptEngines.insert(this); } @@ -104,28 +105,31 @@ ScriptEngine::~ScriptEngine() { QSet ScriptEngine::_allKnownScriptEngines; -void ScriptEngine::gracefullyStopAllScripts() { +void ScriptEngine::gracefullyStopAllScripts(QObject* application) { qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------"; - QSet::const_iterator i = _allKnownScriptEngines.constBegin(); - while (i != _allKnownScriptEngines.constEnd()) { - ScriptEngine* scriptEngine = *i; - qDebug() << scriptEngine; + + QSetIterator i(_allKnownScriptEngines); + while (i.hasNext()) { + ScriptEngine* scriptEngine = i.next(); + qDebug() << (void*)scriptEngine; if (scriptEngine->isRunning()) { qDebug() << "scriptEngine still alive:" << scriptEngine->getFilename() << "[" << scriptEngine << "]"; QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); + + scriptEngine->disconnect(application); scriptEngine->stop(); qDebug() << "waiting on script to stop... "; loop.exec(); qDebug() << "done waiting... "; + } else { + qDebug() << "WARNING! scriptEngine [" << (void*)scriptEngine << "] still in _allKnownScriptEngines but not running??? <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"; } - - ++i; } qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- DONE ------------------"; } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index f3289a8c70..1bd07ba220 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -93,7 +93,7 @@ public: QString getFilename() const; - static void gracefullyStopAllScripts(); + static void gracefullyStopAllScripts(QObject* application); public slots: void loadURL(const QUrl& scriptURL); From e3de994c4ad9276413a205bbcc55d499e5b2b264 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 20 Feb 2015 18:42:02 -0800 Subject: [PATCH 126/341] more hacking --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 8 ++++++-- libraries/script-engine/src/ScriptEngine.cpp | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index b0396f32d6..c81599dd33 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -61,8 +61,12 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf EntityTreeRenderer::~EntityTreeRenderer() { // NOTE: we don't need to delete _entitiesScriptEngine because it's owned by the application and gets cleaned up // automatically but we do need to delete our sandbox script engine. - delete _sandboxScriptEngine; - _sandboxScriptEngine = NULL; + + if (_sandboxScriptEngine) { + qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() delete _sandboxScriptEngine!!!!!"; + delete _sandboxScriptEngine; + _sandboxScriptEngine = NULL; + } } void EntityTreeRenderer::clear() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 5cbf0b1149..9ec76e38b2 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -109,7 +109,7 @@ void ScriptEngine::gracefullyStopAllScripts(QObject* application) { qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------"; - QSetIterator i(_allKnownScriptEngines); + QMutableSetIterator i(_allKnownScriptEngines); while (i.hasNext()) { ScriptEngine* scriptEngine = i.next(); qDebug() << (void*)scriptEngine; @@ -121,7 +121,6 @@ void ScriptEngine::gracefullyStopAllScripts(QObject* application) { QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); scriptEngine->disconnect(application); - scriptEngine->stop(); qDebug() << "waiting on script to stop... "; From 2e7a43a7fb73ee46163083702697a07f880b10fb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 20 Feb 2015 18:47:47 -0800 Subject: [PATCH 127/341] more hacking --- interface/src/Application.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e7b71afd93..2fe11608a5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -587,27 +587,51 @@ void Application::cleanupBeforeQuit() { } Application::~Application() { - EntityTree* tree = _entities.getTree(); - tree->lockForWrite(); - _entities.getTree()->setSimulation(NULL); - tree->unlock(); + qDebug() << "Application::~Application() ------------ START -----------------"; + + qDebug() << "Application::~Application() line:" << __LINE__; + EntityTree* tree = _entities.getTree(); + qDebug() << "Application::~Application() line:" << __LINE__; + tree->lockForWrite(); + qDebug() << "Application::~Application() line:" << __LINE__; + _entities.getTree()->setSimulation(NULL); + qDebug() << "Application::~Application() line:" << __LINE__; + tree->unlock(); + qDebug() << "Application::~Application() line:" << __LINE__; + + qDebug() << "Application::~Application() line:" << __LINE__; qInstallMessageHandler(NULL); + qDebug() << "Application::~Application() line:" << __LINE__; // ask the datagram processing thread to quit and wait until it is done + qDebug() << "Application::~Application() line:" << __LINE__; _nodeThread->quit(); + qDebug() << "Application::~Application() line:" << __LINE__; _nodeThread->wait(); + qDebug() << "Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() line:" << __LINE__; _octreeProcessor.terminate(); + qDebug() << "Application::~Application() line:" << __LINE__; _entityEditSender.terminate(); + qDebug() << "Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() line:" << __LINE__; Menu::getInstance()->deleteLater(); + qDebug() << "Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() line:" << __LINE__; _myAvatar = NULL; + qDebug() << "Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() line:" << __LINE__; ModelEntityItem::cleanupLoadedAnimations() ; + qDebug() << "Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() line:" << __LINE__; DependencyManager::destroy(); + qDebug() << "Application::~Application() line:" << __LINE__; qDebug() << "start destroying ResourceCaches Application::~Application() line:" << __LINE__; DependencyManager::destroy(); @@ -616,6 +640,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); qDebug() << "done destroying ResourceCaches Application::~Application() line:" << __LINE__; + qDebug() << "Application::~Application() ------------ DONE -----------------"; } void Application::initializeGL() { From 36b323c6f302e359ec34235b69f53e38b190c245 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Sat, 21 Feb 2015 15:37:09 +0530 Subject: [PATCH 128/341] Added VHACD dependency Provide link to github source. The source tree has necessary cmke changes to allow 32 bit build specific to hifi --- BUILD.md | 2 +- BUILD_WIN.md | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index f7dc22882a..b956f0e70b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -8,7 +8,7 @@ * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 * [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version) - +* [VHACD](https://github.com/virneo/v-hacd) #### CMake External Project Dependencies The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index f5bc3e09b5..0f806f3bf7 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -67,6 +67,9 @@ The recommended route for CMake to find the external dependencies is to place al -> include -> lib -> test + -> vhacd + -> include + -> lib For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. @@ -114,6 +117,15 @@ Add to the PATH: `%HIFI_LIB_DIR%\zlib` Important! This should be added at the beginning of the path, not the end (your system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". +###vhacd +Download it directly from https://github.com/virneo/v-hacd +cd src\ +mkdir build +cd build +cmake .. +Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug. This create a output folder with include and lib directory. +Either copy that folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory. + ###freeglut Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. From b9befc208bd494abf266b3d1a4e29326b48d6ddd Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Sat, 21 Feb 2015 15:38:16 +0530 Subject: [PATCH 129/341] Cmake module to find VHACD library FindVHACD will look for VHACD_ROOT_DIR env variable or HIFI_LIB_DIR/vhacd folder --- cmake/modules/FindVHACD.cmake | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 cmake/modules/FindVHACD.cmake diff --git a/cmake/modules/FindVHACD.cmake b/cmake/modules/FindVHACD.cmake new file mode 100644 index 0000000000..d84ab30dff --- /dev/null +++ b/cmake/modules/FindVHACD.cmake @@ -0,0 +1,55 @@ +# +# FindVHACD.cmake +# +# Try to find the V-HACD library that decomposes a 3D surface into a set of "near" convex parts. +# +# Once done this will define +# +# VHACD_FOUND - system found V-HACD +# VHACD_INCLUDE_DIRS - the V-HACD include directory +# VHACD_LIBRARIES - link to this to use V-HACD +# +# Created on 2/20/2015 by Virendra Singh +# Copyright 2015 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("vhacd") + +macro(_FIND_VHACD_LIBRARY _var) + set(_${_var}_NAMES ${ARGN}) + find_library(${_var}_LIBRARY_RELEASE + NAMES ${_${_var}_NAMES} + HINTS + ${VHACD_SEARCH_DIRS} + $ENV{VHACD_ROOT_DIR} + PATH_SUFFIXES lib lib/Release + ) + + find_library(${_var}_LIBRARY_DEBUG + NAMES ${_${_var}_NAMES} + HINTS + ${VHACD_SEARCH_DIRS} + $ENV{VHACD_ROOT_DIR} + PATH_SUFFIXES lib lib/Debug + ) + + select_library_configurations(${_var}) + + mark_as_advanced(${_var}_LIBRARY) + mark_as_advanced(${_var}_LIBRARY) +endmacro() + + +find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS} $ENV{VHACD_ROOT_DIR}) +_FIND_VHACD_LIBRARY(VHACD VHACD_LIB) +set(VHACD_LIBRARIES ${VHACD_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(VHACD "Could NOT find VHACD, try to set the path to VHACD root folder in the system variable VHACD_ROOT_DIR or create a directory vhacd in HIFI_LIB_DIR and paste the necessary files there" + VHACD_INCLUDE_DIRS VHACD_LIBRARIES) + +mark_as_advanced(VHACD_INCLUDE_DIRS VHACD_LIBRARIES VHACD_SEARCH_DIRS) \ No newline at end of file From ddd137ed60ff96800531a17adee0dc4a8c2921e7 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Sat, 21 Feb 2015 15:39:16 +0530 Subject: [PATCH 130/341] cmake changes for vhacd cmake changes to create a new project vhacd as a seperate executable in tools directory --- tools/CMakeLists.txt | 1 + tools/vhacd/CMakeLists.txt | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tools/vhacd/CMakeLists.txt diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a13933ba5e..57fe18c53f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory(bitstream2json) add_subdirectory(json2bitstream) add_subdirectory(mtc) add_subdirectory(scribe) +add_subdirectory(vhacd) diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt new file mode 100644 index 0000000000..ee82cd599d --- /dev/null +++ b/tools/vhacd/CMakeLists.txt @@ -0,0 +1,13 @@ +set(TARGET_NAME vhacd) +setup_hifi_project() +link_hifi_libraries(shared model fbx gpu networking octree) + +find_package(VHACD REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) + +add_dependency_external_project(glm) +find_package(GLM REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) + +include_dependency_includes() \ No newline at end of file From ce04b1accb2690edcf43cfa1676c34e8fd519e80 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Sat, 21 Feb 2015 15:40:39 +0530 Subject: [PATCH 131/341] vhacd tool this tool is as per joblist #20305. Its provides an executable to test VHACD computation on simple fbx models. --- tools/vhacd/src/VHACDUtil.cpp | 130 ++++++++++++++++++++++++++++++++++ tools/vhacd/src/VHACDUtil.h | 55 ++++++++++++++ tools/vhacd/src/main.cpp | 102 ++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 tools/vhacd/src/VHACDUtil.cpp create mode 100644 tools/vhacd/src/VHACDUtil.h create mode 100644 tools/vhacd/src/main.cpp diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp new file mode 100644 index 0000000000..bfcdb74634 --- /dev/null +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -0,0 +1,130 @@ +// +// VHACDUtil.cpp +// tools/vhacd/src +// +// Created by Virendra Singh on 2/20/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include "VHACDUtil.h" + + +//Read all the meshes from provided FBX file +bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results) +{ + + // open the fbx file + QFile fbx(filename); + if (!fbx.open(QIODevice::ReadOnly)) { + return false; + } + std::cout << "Reading FBX.....\n"; + + QByteArray fbxContents = fbx.readAll(); + FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); + //results->meshCount = geometry.meshes.count(); + + int count = 0; + foreach(FBXMesh mesh, geometry.meshes) + { + //get vertices for each mesh + QVector vertices = mesh.vertices; + + //get the triangle indices for each mesh + QVector triangles; + foreach(FBXMeshPart part, mesh.parts) + { + QVector indices = part.triangleIndices; + triangles += indices; + } + + //only read meshes with triangles + if (triangles.count() <= 0) + continue; + results->perMeshVertices.append(vertices); + results->perMeshTriangleIndices.append(triangles); + count++; + } + + results->meshCount = count; + return true; +} + +bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const +{ + VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); + int meshCount = meshes->meshCount; + int count = 0; + std::cout << "Performing V-HACD computation on " << meshCount <<" meshes ..... " << std::endl; + + for (int i = 0; i < meshCount; i++) + { + + std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); + std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); + int nPoints = (unsigned int)vertices.size(); + int nTriangles = (unsigned int)triangles.size() / 3; + std::cout << "Mesh " << i + 1 << " : "; + // compute approximate convex decomposition + bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, nTriangles, params); + if (!res) + { + std::cout << "V-HACD computation failed for Mesh : " << i + 1 << std::endl; + continue; + } + count++; //For counting number of successfull computations + + //Number of hulls for the mesh + unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); + results->convexHullsCountList.append(nConvexHulls); + + //get all the convex hulls for this mesh + QVector convexHulls; + for (unsigned int j = 0; j < nConvexHulls; j++) + { + VHACD::IVHACD::ConvexHull hull; + interfaceVHACD->GetConvexHull(j, hull); + convexHulls.append(hull); + } + results->convexHullList.append(convexHulls); + } //end of for loop + + results->meshCount = count; + + //release memory + interfaceVHACD->Clean(); + interfaceVHACD->Release(); + + if (count > 0) + return true; + else + return false; +} + +vhacd::VHACDUtil:: ~VHACDUtil() +{ + //nothing to be cleaned +} + +//ProgressClaback implementation +void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation) +{ + int progress = (int)(overallProgress + 0.5); + + if (progress < 10) + std::cout << "\b\b"; + else + std::cout << "\b\b\b"; + std::cout << progress << "%"; + + if (progress >= 100) + std::cout << std::endl; + +} + +vhacd::ProgressCallback::ProgressCallback(void){} +vhacd::ProgressCallback::~ProgressCallback(){} \ No newline at end of file diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h new file mode 100644 index 0000000000..a9df5d7f2a --- /dev/null +++ b/tools/vhacd/src/VHACDUtil.h @@ -0,0 +1,55 @@ +// +// VHACDUtil.h +// tools/vhacd/src +// +// Created by Virendra Singh on 2/20/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_VHACDUtil_h +#define hifi_VHACDUtil_h + +#include +#include +#include +#include + +#include +#include +#include + +namespace vhacd{ + + typedef struct{ + int meshCount; + QVector convexHullsCountList; + QVector> convexHullList; + }ComputeResults; + + typedef struct{ + int meshCount; + QVector> perMeshVertices; + QVector> perMeshTriangleIndices; + }LoadFBXResults; + + class VHACDUtil{ + public: + bool loadFBX(const QString filename, vhacd::LoadFBXResults *results); + bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const; + ~VHACDUtil(); + }; + + class ProgressCallback : public VHACD::IVHACD::IUserCallback + { + public: + ProgressCallback(void); + ~ProgressCallback(); + + //Couldn't follow coding guideline here due to virtual function declared in IUserCallback + void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation); + }; +} +#endif //hifi_VHACDUtil_h \ No newline at end of file diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp new file mode 100644 index 0000000000..55a152c179 --- /dev/null +++ b/tools/vhacd/src/main.cpp @@ -0,0 +1,102 @@ +// +// main.cpp +// tools/vhacd/src +// +// Created by Virendra Singh on 2/20/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include +#include +#include +#include "VHACDUtil.h" + +using namespace std; +using namespace VHACD; + +int main(int argc, char * argv[]) +{ + vector triangles; // array of indexes + vector points; // array of coordinates + vhacd::VHACDUtil vUtil; + vhacd::LoadFBXResults fbx; //mesh data from loaded fbx file + vhacd::ComputeResults results; // results after computing vhacd + VHACD::IVHACD::Parameters params; + vhacd::ProgressCallback pCallBack; + + + QString fname = "F:/models/ship/Sample_Ship.fbx"; + + //set parameters for V-HACD + params.m_callback = &pCallBack; //progress callback + params.m_resolution = 50000; + params.m_depth = 10; + params.m_concavity = 0.003; + params.m_alpha = 0.05; // controls the bias toward clipping along symmetry planes + params.m_pca = 1; // enable/disable normalizing the mesh before applying the convex decomposition + params.m_mode = 1; // 0: voxel - based approximate convex decomposition, 1 : tetrahedron - based approximate convex decomposition + params.m_maxNumVerticesPerCH = 128; + params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls + + // load the mesh + if (!vUtil.loadFBX(fname, &fbx)) + { + cout << "Error in opening FBX file...."; + return 1; + } + + if (!vUtil.computeVHACD(&fbx, params, &results)) + { + cout << "Compute Failed..."; + return 1; + } + + int totalVertices = 0; + for (int i = 0; i < fbx.meshCount; i++) + { + totalVertices += fbx.perMeshVertices.at(i).count(); + } + + int totalTriangles = 0; + for (int i = 0; i < fbx.meshCount; i++) + { + totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); + } + + int totalHulls = 0; + QVector hullCounts = results.convexHullsCountList; + for (int i = 0; i < results.meshCount; i++) + { + totalHulls += hullCounts.at(i); + } + cout << endl << "Summary of V-HACD Computation..................." << endl; + cout << "File Path : " << fname.toStdString() << endl; + cout << "Number Of Meshes : " << fbx.meshCount << endl; + cout << "Processed Meshes : " << results.meshCount << endl; + cout << "Total vertices : " << totalVertices << endl; + cout << "Total Triangles : " << totalTriangles << endl; + cout << "Total Convex Hulls : " << totalHulls << endl; + cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); + cout << "\t" << "Number Of Hulls : " << chList.count() << endl; + + for (int j = 0; j < results.convexHullList.at(i).count(); j++) + { + + cout << "\tHUll : " << j + 1 << endl; + cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; + cout << "\t\tNumber Of Triangles : " << chList.at(j).m_nTriangles << endl; + } + } + + getchar(); + return 0; +} \ No newline at end of file From 90bff36fd3d3d810b1807562955a66054ecaa79a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 22 Feb 2015 18:48:48 -0800 Subject: [PATCH 132/341] trying to ge the shadow to render correctly --- interface/src/avatar/Avatar.cpp | 10 ++++++---- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/Head.cpp | 6 ++++-- interface/src/avatar/Head.h | 2 +- interface/src/avatar/MyAvatar.cpp | 8 +++++--- interface/src/avatar/MyAvatar.h | 2 +- libraries/gpu/src/gpu/Transform.slh | 18 ++++++++---------- libraries/octree/src/ViewFrustum.cpp | 7 ++++++- libraries/render-utils/src/Model.cpp | 8 +++++--- 9 files changed, 37 insertions(+), 26 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index d4c10b2b4a..9806098745 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -366,7 +366,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool // render body if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - renderBody(renderMode, postLighting, glowLevel); + renderBody(frustum, renderMode, postLighting, glowLevel); } if (!postLighting && renderMode != SHADOW_RENDER_MODE) { @@ -472,7 +472,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLevel) { +void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) { Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; { @@ -489,11 +489,13 @@ void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLeve if (postLighting) { getHand()->render(false, modelRenderMode); } else { - _skeletonModel.render(1.0f, modelRenderMode); + RenderArgs args; + args._viewFrustum = renderFrustum; + _skeletonModel.render(1.0f, modelRenderMode, &args); renderAttachments(renderMode); } } - getHead()->render(1.0f, modelRenderMode, postLighting); + getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); } bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 18e42b7dd7..ee7a2a1736 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -223,7 +223,7 @@ protected: float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD); void renderDisplayName(); - virtual void renderBody(RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); + virtual void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; void simulateAttachments(float deltaTime); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index afc1346ad8..49b9c7bbe1 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -249,13 +249,15 @@ void Head::relaxLean(float deltaTime) { _deltaLeanForward *= relaxationFactor; } -void Head::render(float alpha, Model::RenderMode mode, bool postLighting) { +void Head::render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mode, bool postLighting) { if (postLighting) { if (_renderLookatVectors) { renderLookatVectors(_leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); } } else { - _faceModel.render(alpha, mode); + RenderArgs args; + args._viewFrustum = renderFrustum; + _faceModel.render(alpha, mode, &args); } } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 89eea35903..4454f063b4 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -40,7 +40,7 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); - void render(float alpha, Model::RenderMode mode, bool postLighting); + void render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mode, bool postLighting); void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ba628ea0d4..f029f54b2a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1085,7 +1085,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved); } -void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLevel) { +void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) { if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } @@ -1094,7 +1094,9 @@ void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLe Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; if (!postLighting) { - _skeletonModel.render(1.0f, modelRenderMode); + RenderArgs args; + args._viewFrustum = renderFrustum; + _skeletonModel.render(1.0f, modelRenderMode, &args); renderAttachments(renderMode); } @@ -1102,7 +1104,7 @@ void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLe const Camera *camera = Application::getInstance()->getCamera(); const glm::vec3 cameraPos = camera->getPosition(); if (shouldRenderHead(cameraPos, renderMode)) { - getHead()->render(1.0f, modelRenderMode, postLighting); + getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); } if (postLighting) { getHand()->render(true, modelRenderMode); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ae392268f0..63b4cd8a77 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -38,7 +38,7 @@ public: void updateFromTrackers(float deltaTime); void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE, bool postLighting = false); - void renderBody(RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); + void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; void renderDebugBodyPoints(); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index e9c8a7984a..9578177826 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -39,18 +39,16 @@ vec3 transformModelToEyeDir(TransformCamera camera, TransformObject object, vec3 <@if GLPROFILE == MAC_GL@> return gl_NormalMatrix * dir; <@elif GLPROFILE == PC_GL@> - vec3 mIr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); - vec3 mIr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); - vec3 mIr2 = vec3(object._modelInverse[0].z, object._modelInverse[1].z, object._modelInverse[2].z); + vec3 mr0 = vec3(object._modelInverse[0].x, object._modelInverse[1].x, object._modelInverse[2].x); + vec3 mr1 = vec3(object._modelInverse[0].y, object._modelInverse[1].y, object._modelInverse[2].y); + vec3 mr2 = vec3(object._modelInverse[0].z, object._modelInverse[1].z, object._modelInverse[2].z); - vec3 mvIc0 = vec3(dot(camera._viewInverse[0].xyz, mIr0), dot(camera._viewInverse[0].xyz, mIr1), dot(camera._viewInverse[0].xyz, mIr2)); - vec3 mvIc1 = vec3(dot(camera._viewInverse[1].xyz, mIr0), dot(camera._viewInverse[1].xyz, mIr1), dot(camera._viewInverse[1].xyz, mIr2)); - vec3 mvIc2 = vec3(dot(camera._viewInverse[2].xyz, mIr0), dot(camera._viewInverse[2].xyz, mIr1), dot(camera._viewInverse[2].xyz, mIr2)); + vec3 mvc0 = vec3(dot(camera._viewInverse[0].xyz, mr0), dot(camera._viewInverse[0].xyz, mr1), dot(camera._viewInverse[0].xyz, mr2)); + vec3 mvc1 = vec3(dot(camera._viewInverse[1].xyz, mr0), dot(camera._viewInverse[1].xyz, mr1), dot(camera._viewInverse[1].xyz, mr2)); + vec3 mvc2 = vec3(dot(camera._viewInverse[2].xyz, mr0), dot(camera._viewInverse[2].xyz, mr1), dot(camera._viewInverse[2].xyz, mr2)); + + vec3 result = vec3(dot(mvc0, dir), dot(mvc1, dir), dot(mvc2, dir)); - vec3 result = vec3(dot(mvIc0, dir), - dot(mvIc1, dir), - dot(mvIc2, dir)); - return result; <@endif@> } diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 61324861e8..f92ba0a742 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -868,7 +868,12 @@ float ViewFrustum::distanceToCamera(const glm::vec3& point) const { void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { if (isOrthographic()) { - proj = glm::ortho(getWidth() * -0.5, getWidth() * +0.5, getHeight() * -0.5, getHeight() * 0.5); + float left, right, bottom, top, near, far; + glm::vec4 clip0, clip1; + computeOffAxisFrustum(left, right, bottom, top, near, far, clip0, clip1); + + proj = glm::ortho(left, right, bottom, top); + proj = glm::ortho(-0.5f * getWidth(), +0.5f * getWidth(), -0.5f * getWidth(), +0.5f * getWidth()); } else { float left, right, bottom, top, near, far; glm::vec4 clip0, clip1; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index dd4d1ba9e7..f8cd363a5b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -701,9 +701,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { gpu::Batch& batch = _renderBatch; // Setup the projection matrix - glm::mat4 proj; - _viewState->getCurrentViewFrustum()->evalProjectionMatrix(proj); - batch.setProjectionTransform(proj); + if (args && args->_viewFrustum) { + glm::mat4 proj; + args->_viewFrustum->evalProjectionMatrix(proj); + batch.setProjectionTransform(proj); + } // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { From 8212f86bfb614fb8fe507dc7bbce18fed98fe4ce Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Mon, 23 Feb 2015 12:19:45 +0530 Subject: [PATCH 133/341] Minor grammar corrections Corrected line breaks. --- BUILD.md | 3 ++- BUILD_WIN.md | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/BUILD.md b/BUILD.md index b956f0e70b..b94ab1ff50 100644 --- a/BUILD.md +++ b/BUILD.md @@ -8,7 +8,8 @@ * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 * [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version) -* [VHACD](https://github.com/virneo/v-hacd) +* [VHACD](https://github.com/virneo/v-hacd)(clone this repository) + #### CMake External Project Dependencies The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 0f806f3bf7..f735936d0a 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -119,11 +119,17 @@ system likely has many copies of zlib1.dll, and you want High Fidelity to use th ###vhacd Download it directly from https://github.com/virneo/v-hacd -cd src\ -mkdir build -cd build -cmake .. -Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug. This create a output folder with include and lib directory. + +To build it run the following commands + 1. cd src\ + 2. mkdir build + 3. cd build + 4. cmake .. + +Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug. + +This will create an output folder with include and lib directory inside it. + Either copy that folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory. ###freeglut From ffaea071308887993b175b51097d01aeedafff7f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Feb 2015 07:04:14 -0800 Subject: [PATCH 134/341] trying to ge the shadow to render correctly --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 8 +++++++- libraries/render-utils/src/AbstractViewStateInterface.h | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 975d0f515d..ec048cb6eb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -332,8 +332,14 @@ void EntityTreeRenderer::leaveAllEntities() { void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { if (_tree) { Model::startScene(renderSide); - RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, + + ViewFrustum* frustum = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? + _viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum(); + + RenderArgs args = { this, frustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + _tree->lockForRead(); _tree->recurseTreeWithOperation(renderOperation, &args); diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 50a75c769a..0d73614e7c 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -32,6 +32,9 @@ public: /// gets the current view frustum for rendering the view state virtual ViewFrustum* getCurrentViewFrustum() = 0; + + /// gets the shadow view frustum for rendering the view state + virtual ViewFrustum* getShadowViewFrustum() = 0; virtual bool getShadowsEnabled() = 0; virtual bool getCascadeShadowsEnabled() = 0; From d08f7d6255cebe54696e7ae715b955b68d88729e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 08:24:52 -0800 Subject: [PATCH 135/341] check if QXmpp is dynamic or static --- cmake/modules/FindQxmpp.cmake | 8 +++++++- interface/CMakeLists.txt | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cmake/modules/FindQxmpp.cmake b/cmake/modules/FindQxmpp.cmake index 8fbc63e9dc..7c1579835d 100644 --- a/cmake/modules/FindQxmpp.cmake +++ b/cmake/modules/FindQxmpp.cmake @@ -26,6 +26,10 @@ find_path(QXMPP_INCLUDE_DIRS QXmppClient.h PATH_SUFFIXES include/qxmpp HINTS ${Q find_library(QXMPP_LIBRARY_RELEASE NAMES qxmpp PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) find_library(QXMPP_LIBRARY_DEBUG NAMES qxmpp_d PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) +if (WIN32) + find_path(QXMPP_DLL_PATH NAMES qxmpp.dll PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) +endif () + find_package(Qt5 COMPONENTS Xml REQUIRED) include(SelectLibraryConfigurations) @@ -36,4 +40,6 @@ set(QXMPP_LIBRARIES "${QXMPP_LIBRARY}" Qt5::Xml) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(QXmpp DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_LIBRARY) -mark_as_advanced(QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_SEARCH_DIRS) \ No newline at end of file +if (QXMPP_DLL_PATH) + add_paths_to_lib_paths(${QXMPP_DLL_PATH}) +endif () \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 2e0120dfc8..1c27d8f9db 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -175,8 +175,8 @@ if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE) target_link_libraries(${TARGET_NAME} ${CoreMIDI}) endif () -if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32) - # assume we're linking a static Qt on windows +if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32 AND NOT QXMPP_DLL_PATH) + # if we have no QXmpp DLL path, assume we're linking a static QXmpp on windows add_definitions(-DQXMPP_STATIC) endif () From 28bcc0a95277ce4b68de862999cb0a5a360ec9ab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 08:43:18 -0800 Subject: [PATCH 136/341] use nmake on win for QXmpp build --- cmake/externals/qxmpp/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index ddac75569b..e605e2b253 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -11,6 +11,12 @@ if (ANDROID) set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") endif () +if (WIN32) + find_program(PLATFORM_BUILD_COMMAND NAME nmake) +else () + find_program(PLATFORM_BUILD_COMMAND NAME make) +endif () + include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} @@ -19,6 +25,7 @@ ExternalProject_Add( BUILD_IN_SOURCE 1 PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= + BUILD_COMMAND PLATFORM_BUILD_COMMAND LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 1c707059c58af89bbff47f727ce84199ef6ac586 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 08:46:16 -0800 Subject: [PATCH 137/341] fix for quoted PLATFORM_BUILD_COMMAND for QXmpp --- cmake/externals/qxmpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index e605e2b253..d5ccd0c020 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -25,7 +25,7 @@ ExternalProject_Add( BUILD_IN_SOURCE 1 PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= - BUILD_COMMAND PLATFORM_BUILD_COMMAND + BUILD_COMMAND ${PLATFORM_BUILD_COMMAND} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 1b8d421fb3c8fa48b2d5cdf4d031c3964ebff841 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:06:39 -0800 Subject: [PATCH 138/341] add a fatal error if nmake not found --- cmake/externals/qxmpp/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index d5ccd0c020..0273344b30 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -12,9 +12,12 @@ if (ANDROID) endif () if (WIN32) - find_program(PLATFORM_BUILD_COMMAND NAME nmake) + find_program(PLATFORM_BUILD_COMMAND nmake) + if (NOT PLATFORM_BUILD_COMMAND) + message(FATAL_ERROR "You asked us to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") + endif () else () - find_program(PLATFORM_BUILD_COMMAND NAME make) + find_program(PLATFORM_BUILD_COMMAND make) endif () include(ExternalProject) From d32fc645e80933634ce7a774f5cc68d8b05b165d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 09:10:15 -0800 Subject: [PATCH 139/341] remove some dead code, added a debugging notes comment --- .../src/EntityTreeRenderer.cpp | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c81599dd33..7a089eee5f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -63,6 +63,11 @@ EntityTreeRenderer::~EntityTreeRenderer() { // automatically but we do need to delete our sandbox script engine. if (_sandboxScriptEngine) { + // NOTE: is it possible this is a problem? I think that we hook the script engine object up to a deleteLater() + // call inside of registerScriptEngineWithApplicationServices() but do we not call that for _sandboxScriptEngine??? + // this _sandboxScriptEngine implementation is confusing and potentially error prone because it's not a full fledged + // ScriptEngine that has been fully connected. We did this so that scripts that were ill-formed could be evaluated + // but not execute against the application. qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() delete _sandboxScriptEngine!!!!!"; delete _sandboxScriptEngine; _sandboxScriptEngine = NULL; @@ -103,22 +108,6 @@ void EntityTreeRenderer::init() { void EntityTreeRenderer::shutdown() { _shuttingDown = true; - - /* - if (_entitiesScriptEngine) { - _entitiesScriptEngine->stop(); - - QEventLoop loop; - QObject::connect(_entitiesScriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - - _entitiesScriptEngine->stop(); - - qDebug() << "waiting on Entities sandbox script to stop... "; - loop.exec(); - qDebug() << "done waiting... "; - - } - */ } From 9e5fb9532bc2d6fb51f660cc2ba7f9ecef4d6613 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:11:06 -0800 Subject: [PATCH 140/341] clear up BUILD guide for optional external projects --- BUILD.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/BUILD.md b/BUILD.md index 6cfe5229d6..98b8cffab1 100644 --- a/BUILD.md +++ b/BUILD.md @@ -13,6 +13,13 @@ * [gverb](https://github.com/highfidelity/gverb) * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 +The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile QXmpp you would pass -DGET_QXMPP=1. + +* [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3 + * Enables game controller support in Interface +* [QXmpp](https://github.com/qxmpp-project/qxmpp) ~> 0.7.6 + * Enables text chat support in Interface + The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build-ext` folder. @@ -67,12 +74,6 @@ In the examples below the variable $NAME would be replaced by the name of the de ###Optional Components -####QXmpp - -You can [find QXmpp here](https://github.com/qxmpp-project/qxmpp), 0.7.6 is the version you want. The inclusion of the QXmpp enables text chat in the Interface client. - -OS X users who tap our [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) can install QXmpp via homebrew - `brew install highfidelity/formulas/qxmpp`. - ####Devices You can support external input/output devices such as Oculus Rift, Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. From e53221e2977f2a4d5b9e2d8840c8eae9efd65588 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:11:17 -0800 Subject: [PATCH 141/341] remove an extra space --- BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 98b8cffab1..b8d7df0d0c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -43,7 +43,7 @@ For example, a Qt5 5.3.2 installation to /usr/local/qt5 would require that QT_CM The path it needs to be set to will depend on where and how Qt5 was installed. e.g. export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/clang_64/lib/cmake/ - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.2/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/localCellar/qt5/5.3.2/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake ####Generating build files From c3d98b12899d19d3236056897c641cad615a54f3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:11:52 -0800 Subject: [PATCH 142/341] use nmake for install of QXmpp on windows --- cmake/externals/qxmpp/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index 0273344b30..c35708daa6 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -14,7 +14,7 @@ endif () if (WIN32) find_program(PLATFORM_BUILD_COMMAND nmake) if (NOT PLATFORM_BUILD_COMMAND) - message(FATAL_ERROR "You asked us to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") + message(FATAL_ERROR "You asked CMake to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") endif () else () find_program(PLATFORM_BUILD_COMMAND make) @@ -29,6 +29,7 @@ ExternalProject_Add( PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= BUILD_COMMAND ${PLATFORM_BUILD_COMMAND} + INSTALL_COMMAND ${PLATFORM_BUILD_COMMAND} install LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 9a069f56ab5a97c9537fa110c85d1b75ab517ed1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:13:59 -0800 Subject: [PATCH 143/341] indicate in win build guide that nmake should be in path --- BUILD_WIN.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 6956abbc5f..290a8b8be6 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -10,10 +10,16 @@ Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" -#####Windows SDK 8.1 +####Windows SDK 8.1 If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. +####nmake + +Some of the external projects may require nmake to build and install. Please ensure that nmake is in your PATH so CMake can find it if required. For a typical Visual Studio installation, nmake.exe is located at the following path. + + C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin + ###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. From e5ef61e27ee15b0cd7ad3d0409b374bf7ba3122b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 09:23:15 -0800 Subject: [PATCH 144/341] simplifying the change --- .../src/EntityTreeRenderer.cpp | 334 +++++++++--------- 1 file changed, 173 insertions(+), 161 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 7a089eee5f..18813de519 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -718,159 +718,168 @@ QScriptValueList EntityTreeRenderer::createEntityArgs(const EntityItemID& entity } void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { - if (_tree && !_shuttingDown) { - PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); - PickRay ray = _viewState->computePickRay(event->x(), event->y()); - - bool precisionPicking = !_dontDoPrecisionPicking; - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); - if (rayPickResult.intersects) { - //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; - emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mousePressOnEntity").isValid()) { - entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs); - } - - _currentClickingOnEntityID = rayPickResult.entityID; - emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - if (entityScript.property("clickDownOnEntity").isValid()) { - entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs); - } - } - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; + // If we don't have a tree, or we're in the process of shutting down, then don't + // process these events. + if (!_tree || _shuttingDown) { + return; } + PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); + + bool precisionPicking = !_dontDoPrecisionPicking; + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); + if (rayPickResult.intersects) { + //qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID; + emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mousePressOnEntity").isValid()) { + entityScript.property("mousePressOnEntity").call(entityScript, entityScriptArgs); + } + + _currentClickingOnEntityID = rayPickResult.entityID; + emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + if (entityScript.property("clickDownOnEntity").isValid()) { + entityScript.property("clickDownOnEntity").call(entityScript, entityScriptArgs); + } + } + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; } void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { - if (_tree && !_shuttingDown) { - PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); - PickRay ray = _viewState->computePickRay(event->x(), event->y()); - bool precisionPicking = !_dontDoPrecisionPicking; - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); - if (rayPickResult.intersects) { - //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; - emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mouseReleaseOnEntity").isValid()) { - entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs); - } - } - - // Even if we're no longer intersecting with an entity, if we started clicking on it, and now - // we're releasing the button, then this is considered a clickOn event - if (!_currentClickingOnEntityID.isInvalidID()) { - emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - - QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); - QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); - if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) { - currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs); - } - } - - // makes it the unknown ID, we just released so we can't be clicking on anything - _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; + // If we don't have a tree, or we're in the process of shutting down, then don't + // process these events. + if (!_tree || _shuttingDown) { + return; } + PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent"); + PickRay ray = _viewState->computePickRay(event->x(), event->y()); + bool precisionPicking = !_dontDoPrecisionPicking; + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking); + if (rayPickResult.intersects) { + //qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID; + emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mouseReleaseOnEntity").isValid()) { + entityScript.property("mouseReleaseOnEntity").call(entityScript, entityScriptArgs); + } + } + + // Even if we're no longer intersecting with an entity, if we started clicking on it, and now + // we're releasing the button, then this is considered a clickOn event + if (!_currentClickingOnEntityID.isInvalidID()) { + emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + + QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); + QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); + if (currentClickingEntity.property("clickReleaseOnEntity").isValid()) { + currentClickingEntity.property("clickReleaseOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + } + } + + // makes it the unknown ID, we just released so we can't be clicking on anything + _currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; } void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - if (_tree && !_shuttingDown) { - PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); - - PickRay ray = _viewState->computePickRay(event->x(), event->y()); - - bool precisionPicking = false; // for mouse moves we do not do precision picking - RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); - if (rayPickResult.intersects) { - QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); - - // load the entity script if needed... - QScriptValue entityScript = loadEntityScript(rayPickResult.entity); - if (entityScript.property("mouseMoveEvent").isValid()) { - entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs); - } - - //qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID; - emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("mouseMoveOnEntity").isValid()) { - entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs); - } - - // handle the hover logic... - - // if we were previously hovering over an entity, and this new entity is not the same as our previous entity - // then we need to send the hover leave. - if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - - QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); - - QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); - if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { - currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); - } - } - - // If the new hover entity does not match the previous hover entity then we are entering the new one - // this is true if the _currentHoverOverEntityID is known or unknown - if (rayPickResult.entityID != _currentHoverOverEntityID) { - emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("hoverEnterEntity").isValid()) { - entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs); - } - } - - // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and - // we should send our hover over event - emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); - if (entityScript.property("hoverOverEntity").isValid()) { - entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs); - } - - // remember what we're hovering over - _currentHoverOverEntityID = rayPickResult.entityID; - - } else { - // handle the hover logic... - // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to - // send the hover leave for our previous entity - if (!_currentHoverOverEntityID.isInvalidID()) { - emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); - - QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); - - QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); - if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { - currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); - } - - _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID - } - } - - // Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have - // not yet released the hold then this is still considered a holdingClickOnEntity event - if (!_currentClickingOnEntityID.isInvalidID()) { - emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); - - QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); - - QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); - if (currentClickingEntity.property("holdingClickOnEntity").isValid()) { - currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs); - } - } - _lastMouseEvent = MouseEvent(*event, deviceID); - _lastMouseEventValid = true; + // If we don't have a tree, or we're in the process of shutting down, then don't + // process these events. + if (!_tree || _shuttingDown) { + return; } + PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent"); + + PickRay ray = _viewState->computePickRay(event->x(), event->y()); + + bool precisionPicking = false; // for mouse moves we do not do precision picking + RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock, precisionPicking); + if (rayPickResult.intersects) { + QScriptValueList entityScriptArgs = createMouseEventArgs(rayPickResult.entityID, event, deviceID); + + // load the entity script if needed... + QScriptValue entityScript = loadEntityScript(rayPickResult.entity); + if (entityScript.property("mouseMoveEvent").isValid()) { + entityScript.property("mouseMoveEvent").call(entityScript, entityScriptArgs); + } + + //qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID; + emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("mouseMoveOnEntity").isValid()) { + entityScript.property("mouseMoveOnEntity").call(entityScript, entityScriptArgs); + } + + // handle the hover logic... + + // if we were previously hovering over an entity, and this new entity is not the same as our previous entity + // then we need to send the hover leave. + if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) { + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); + + QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); + + QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); + if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { + currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); + } + } + + // If the new hover entity does not match the previous hover entity then we are entering the new one + // this is true if the _currentHoverOverEntityID is known or unknown + if (rayPickResult.entityID != _currentHoverOverEntityID) { + emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("hoverEnterEntity").isValid()) { + entityScript.property("hoverEnterEntity").call(entityScript, entityScriptArgs); + } + } + + // and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and + // we should send our hover over event + emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID)); + if (entityScript.property("hoverOverEntity").isValid()) { + entityScript.property("hoverOverEntity").call(entityScript, entityScriptArgs); + } + + // remember what we're hovering over + _currentHoverOverEntityID = rayPickResult.entityID; + + } else { + // handle the hover logic... + // if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to + // send the hover leave for our previous entity + if (!_currentHoverOverEntityID.isInvalidID()) { + emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID)); + + QScriptValueList currentHoverEntityArgs = createMouseEventArgs(_currentHoverOverEntityID, event, deviceID); + + QScriptValue currentHoverEntity = loadEntityScript(_currentHoverOverEntityID); + if (currentHoverEntity.property("hoverLeaveEntity").isValid()) { + currentHoverEntity.property("hoverLeaveEntity").call(currentHoverEntity, currentHoverEntityArgs); + } + + _currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID + } + } + + // Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have + // not yet released the hold then this is still considered a holdingClickOnEntity event + if (!_currentClickingOnEntityID.isInvalidID()) { + emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID)); + + QScriptValueList currentClickingEntityArgs = createMouseEventArgs(_currentClickingOnEntityID, event, deviceID); + + QScriptValue currentClickingEntity = loadEntityScript(_currentClickingOnEntityID); + if (currentClickingEntity.property("holdingClickOnEntity").isValid()) { + currentClickingEntity.property("holdingClickOnEntity").call(currentClickingEntity, currentClickingEntityArgs); + } + } + _lastMouseEvent = MouseEvent(*event, deviceID); + _lastMouseEventValid = true; } void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { @@ -919,24 +928,27 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision) { - if (_tree && !_shuttingDown) { - QScriptValue entityScriptA = loadEntityScript(idA); - if (entityScriptA.property("collisionWithEntity").isValid()) { - QScriptValueList args; - args << idA.toScriptValue(_entitiesScriptEngine); - args << idB.toScriptValue(_entitiesScriptEngine); - args << collisionToScriptValue(_entitiesScriptEngine, collision); - entityScriptA.property("collisionWithEntity").call(entityScriptA, args); - } + // If we don't have a tree, or we're in the process of shutting down, then don't + // process these events. + if (!_tree || _shuttingDown) { + return; + } + QScriptValue entityScriptA = loadEntityScript(idA); + if (entityScriptA.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idA.toScriptValue(_entitiesScriptEngine); + args << idB.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptA.property("collisionWithEntity").call(entityScriptA, args); + } - QScriptValue entityScriptB = loadEntityScript(idB); - if (entityScriptB.property("collisionWithEntity").isValid()) { - QScriptValueList args; - args << idB.toScriptValue(_entitiesScriptEngine); - args << idA.toScriptValue(_entitiesScriptEngine); - args << collisionToScriptValue(_entitiesScriptEngine, collision); - entityScriptB.property("collisionWithEntity").call(entityScriptA, args); - } + QScriptValue entityScriptB = loadEntityScript(idB); + if (entityScriptB.property("collisionWithEntity").isValid()) { + QScriptValueList args; + args << idB.toScriptValue(_entitiesScriptEngine); + args << idA.toScriptValue(_entitiesScriptEngine); + args << collisionToScriptValue(_entitiesScriptEngine, collision); + entityScriptB.property("collisionWithEntity").call(entityScriptA, args); } } From 437d5c7bdf57febff22cd039c5102c8e5fdbde69 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:26:35 -0800 Subject: [PATCH 145/341] repairs to include locations for QXmpp and SDL2 --- cmake/externals/sdl2/CMakeLists.txt | 4 +++- cmake/modules/FindQxmpp.cmake | 2 +- interface/src/XmppClient.h | 4 ++-- interface/src/scripting/GlobalServicesScriptingInterface.h | 4 ++-- interface/src/ui/ChatWindow.h | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 00936a8320..5b60e60af1 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -33,6 +33,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(_ROOT_DIR ${SOURCE_DIR}) + set(_INCLUDE_DIR ${_ROOT_DIR}/include) set(_LIB_DIR "${SOURCE_DIR}/lib/x86") set(_LIB_EXT "lib") @@ -40,11 +41,12 @@ if (WIN32) else () ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) set(_ROOT_DIR ${INSTALL_DIR}) + set(_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2) set(_LIB_DIR ${INSTALL_DIR}/lib) set(_LIB_EXT "so") set(_LIB_PREFIX "lib") endif () -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2 CACHE PATH "Location of SDL2 include directory") +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_INCLUDE_DIR} CACHE PATH "Location of SDL2 include directory") set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${_LIB_DIR}/${_LIB_PREFIX}SDL2.${_LIB_EXT} CACHE FILEPATH "Path to SDL2 library") \ No newline at end of file diff --git a/cmake/modules/FindQxmpp.cmake b/cmake/modules/FindQxmpp.cmake index 7c1579835d..489936688e 100644 --- a/cmake/modules/FindQxmpp.cmake +++ b/cmake/modules/FindQxmpp.cmake @@ -21,7 +21,7 @@ include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") hifi_library_search_hints("qxmpp") -find_path(QXMPP_INCLUDE_DIRS QXmppClient.h PATH_SUFFIXES include/qxmpp HINTS ${QXMPP_SEARCH_DIRS}) +find_path(QXMPP_INCLUDE_DIRS qxmpp/QXmppClient.h PATH_SUFFIXES include HINTS ${QXMPP_SEARCH_DIRS}) find_library(QXMPP_LIBRARY_RELEASE NAMES qxmpp PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) find_library(QXMPP_LIBRARY_DEBUG NAMES qxmpp_d PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) diff --git a/interface/src/XmppClient.h b/interface/src/XmppClient.h index 91c10c4055..2b7a831ff3 100644 --- a/interface/src/XmppClient.h +++ b/interface/src/XmppClient.h @@ -15,8 +15,8 @@ #include #ifdef HAVE_QXMPP -#include -#include +#include +#include #endif /// Generalized threaded processor for handling received inbound packets. diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index 657cb945c5..d8b436a6e6 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -21,8 +21,8 @@ #ifdef HAVE_QXMPP -#include -#include +#include +#include #endif // HAVE_QXMPP diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 2338ab280d..b2ee113637 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -25,8 +25,8 @@ #ifdef HAVE_QXMPP -#include -#include +#include +#include #endif From a8d48e592f596ca116daa9ead613838fe65fb727 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 09:44:18 -0800 Subject: [PATCH 146/341] removing debug messages --- .../src/EntityTreeRenderer.cpp | 3 +- libraries/script-engine/src/ScriptEngine.cpp | 39 +++++-------------- libraries/script-engine/src/ScriptEngine.h | 2 +- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 18813de519..fdaaa6422b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -68,7 +68,6 @@ EntityTreeRenderer::~EntityTreeRenderer() { // this _sandboxScriptEngine implementation is confusing and potentially error prone because it's not a full fledged // ScriptEngine that has been fully connected. We did this so that scripts that were ill-formed could be evaluated // but not execute against the application. - qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() delete _sandboxScriptEngine!!!!!"; delete _sandboxScriptEngine; _sandboxScriptEngine = NULL; } @@ -171,7 +170,7 @@ QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorTe QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { if (_shuttingDown) { - return QScriptValue(); // no entity... + return QScriptValue(); // since we're shutting down, we don't load any more scripts } if (!entity) { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9ec76e38b2..6cae9fcfa4 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,43 +94,33 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { - qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::ScriptEngine() " << getFilename() << "[" << this << "]"; _allKnownScriptEngines.insert(this); } ScriptEngine::~ScriptEngine() { - qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::~ScriptEngine() " << getFilename(); _allKnownScriptEngines.remove(this); } QSet ScriptEngine::_allKnownScriptEngines; -void ScriptEngine::gracefullyStopAllScripts(QObject* application) { - qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- START ------------------"; - - +void ScriptEngine::stopAllScripts(QObject* application) { QMutableSetIterator i(_allKnownScriptEngines); while (i.hasNext()) { ScriptEngine* scriptEngine = i.next(); - qDebug() << (void*)scriptEngine; - - if (scriptEngine->isRunning()) { - qDebug() << "scriptEngine still alive:" << scriptEngine->getFilename() << "[" << scriptEngine << "]"; + // NOTE: typically all script engines are running. But there's at least one known exception to this, the + // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using + // them. We don't need to stop scripts that aren't running. + if (scriptEngine->isRunning()) { QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); scriptEngine->disconnect(application); scriptEngine->stop(); - qDebug() << "waiting on script to stop... "; loop.exec(); - qDebug() << "done waiting... "; - } else { - qDebug() << "WARNING! scriptEngine [" << (void*)scriptEngine << "] still in _allKnownScriptEngines but not running??? <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"; } } - qDebug() << "[" << QThread::currentThread() << "]" << "ScriptEngine::gracefullyStopAllScripts() ----------- DONE ------------------"; } QString ScriptEngine::getFilename() const { @@ -411,14 +401,12 @@ void ScriptEngine::run() { } if (_isFinished) { - qDebug() << "ScriptEngine::run()... while() about to break " << getFilename(); break; } QCoreApplication::processEvents(); if (_isFinished) { - qDebug() << "ScriptEngine::run()... while() about to break " << getFilename(); break; } @@ -548,7 +536,6 @@ void ScriptEngine::run() { } lastUpdate = now; } - qDebug() << "ScriptEngine::run()... about to emit scriptEnding() " << getFilename(); emit scriptEnding(); // kill the avatar identity timer @@ -566,25 +553,19 @@ void ScriptEngine::run() { // If we were on a thread, then wait till it's done if (thread()) { - qDebug() << "ScriptEngine::run()... about to call thread()->quit() " << getFilename(); thread()->quit(); } - qDebug() << "ScriptEngine::run()... about to emit finished() " << getFilename(); emit finished(_fileNameString); _isRunning = false; - qDebug() << "ScriptEngine::run()... about to emit runningStateChanged() " << getFilename(); emit runningStateChanged(); - qDebug() << "ScriptEngine::run()... about to emit doneRunning() " << getFilename(); emit doneRunning(); - qDebug() << "ScriptEngine::run()... DONE WITH run()... " << getFilename(); } void ScriptEngine::stop() { - qDebug() << "ScriptEngine::stop()... " << getFilename(); _isFinished = true; emit runningStateChanged(); } @@ -666,12 +647,10 @@ void ScriptEngine::print(const QString& message) { emit printedMessage(message); } -/** - * If a callback is specified, the included files will be loaded asynchronously and the callback will be called - * when all of the files have finished loading. - * If no callback is specified, the included files will be loaded synchronously and will block execution until - * all of the files have finished loading. - */ +// If a callback is specified, the included files will be loaded asynchronously and the callback will be called +// when all of the files have finished loading. +// If no callback is specified, the included files will be loaded synchronously and will block execution until +// all of the files have finished loading. void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) { QList urls; for (QString file : includeFiles) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 1bd07ba220..ab32f2c0a5 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -93,7 +93,7 @@ public: QString getFilename() const; - static void gracefullyStopAllScripts(QObject* application); + static void stopAllScripts(QObject* application); public slots: void loadURL(const QUrl& scriptURL); From 85cec79ff5566125a1721ac61420e7ba142c0a23 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 09:44:22 -0800 Subject: [PATCH 147/341] removing debug messages --- interface/src/Application.cpp | 44 +++-------------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2fe11608a5..25ee53f187 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -527,21 +527,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : } void Application::aboutToQuit() { -qDebug() << "Application::aboutToQuit()"; _aboutToQuit = true; cleanupBeforeQuit(); } void Application::cleanupBeforeQuit() { - qDebug() << "Application::cleanupBeforeQuit() ------------ START -----------------"; - - // stop entities running scripts - _entities.shutdown(); - - // stop all running scripts - ScriptEngine::gracefullyStopAllScripts(this); - + + _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + ScriptEngine::stopAllScripts(this); // stop all currently running global scripts // first stop all timers directly or by invokeMethod // depending on what thread they run in @@ -582,65 +576,36 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); - - qDebug() << "Application::cleanupBeforeQuit() ------------ DONE -----------------"; } Application::~Application() { - qDebug() << "Application::~Application() ------------ START -----------------"; - - - qDebug() << "Application::~Application() line:" << __LINE__; EntityTree* tree = _entities.getTree(); - qDebug() << "Application::~Application() line:" << __LINE__; tree->lockForWrite(); - qDebug() << "Application::~Application() line:" << __LINE__; _entities.getTree()->setSimulation(NULL); - qDebug() << "Application::~Application() line:" << __LINE__; tree->unlock(); - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; qInstallMessageHandler(NULL); - qDebug() << "Application::~Application() line:" << __LINE__; // ask the datagram processing thread to quit and wait until it is done - qDebug() << "Application::~Application() line:" << __LINE__; _nodeThread->quit(); - qDebug() << "Application::~Application() line:" << __LINE__; _nodeThread->wait(); - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; _octreeProcessor.terminate(); - qDebug() << "Application::~Application() line:" << __LINE__; _entityEditSender.terminate(); - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; Menu::getInstance()->deleteLater(); - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; _myAvatar = NULL; - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; ModelEntityItem::cleanupLoadedAnimations() ; - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() line:" << __LINE__; DependencyManager::destroy(); - qDebug() << "Application::~Application() line:" << __LINE__; - qDebug() << "start destroying ResourceCaches Application::~Application() line:" << __LINE__; DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - qDebug() << "done destroying ResourceCaches Application::~Application() line:" << __LINE__; - qDebug() << "Application::~Application() ------------ DONE -----------------"; } void Application::initializeGL() { @@ -3469,7 +3434,6 @@ void Application::clearScriptsBeforeRunning() { } void Application::saveScripts() { -qDebug() << "Application::saveScripts()"; // Saves all currently running user-loaded scripts Settings settings; settings.beginWriteArray(SETTINGS_KEY); @@ -3638,7 +3602,6 @@ void Application::handleScriptLoadError(const QString& scriptFilename) { } void Application::scriptFinished(const QString& scriptName) { - qDebug() << "Application::scriptFinished(), scriptName:" << scriptName; const QString& scriptURLString = QUrl(scriptName).toString(); QHash::iterator it = _scriptEnginesHash.find(scriptURLString); if (it != _scriptEnginesHash.end()) { @@ -3649,7 +3612,6 @@ void Application::scriptFinished(const QString& scriptName) { } void Application::stopAllScripts(bool restart) { - qDebug() << "Application::stopAllScripts()... restart:" << restart; // stops all current running scripts for (QHash::const_iterator it = _scriptEnginesHash.constBegin(); it != _scriptEnginesHash.constEnd(); it++) { From 82a798ef15e7e71cc8f1b7de426b4cb163bc296f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:47:35 -0800 Subject: [PATCH 148/341] use SDL2 framework on OS X --- cmake/externals/sdl2/CMakeLists.txt | 48 +++++++++++++++++++---------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 5b60e60af1..49bb68891d 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -12,6 +12,16 @@ if (WIN32) INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) +elseif (APPLE) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-2.0.3-OSX.tar.gz + URL_MD5 64f888886268bdf1656ef1b4b7d7756d + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) else () if (ANDROID) set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") @@ -30,23 +40,29 @@ endif () string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -if (WIN32) +if (APPLE) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - set(_ROOT_DIR ${SOURCE_DIR}) - set(_INCLUDE_DIR ${_ROOT_DIR}/include) - set(_LIB_DIR "${SOURCE_DIR}/lib/x86") - set(_LIB_EXT "lib") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of SDL2 DLL") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/SDL2.framework/Headers CACHE PATH "Location of SDL2 include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/SDL2.framework CACHE PATH "Location of SDL2 framework") else () - ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - set(_ROOT_DIR ${INSTALL_DIR}) - set(_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2) + if (WIN32) + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + set(_ROOT_DIR ${SOURCE_DIR}) + set(_INCLUDE_DIR ${_ROOT_DIR}/include) + set(_LIB_DIR "${SOURCE_DIR}/lib/x86") + set(_LIB_EXT "lib") - set(_LIB_DIR ${INSTALL_DIR}/lib) - set(_LIB_EXT "so") - set(_LIB_PREFIX "lib") -endif () + set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of SDL2 DLL") + else () + ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) + set(_ROOT_DIR ${INSTALL_DIR}) + set(_INCLUDE_DIR ${_ROOT_DIR}/include/SDL2) + + set(_LIB_DIR ${INSTALL_DIR}/lib) + set(_LIB_EXT "so") + set(_LIB_PREFIX "lib") + endif () -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_INCLUDE_DIR} CACHE PATH "Location of SDL2 include directory") -set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${_LIB_DIR}/${_LIB_PREFIX}SDL2.${_LIB_EXT} CACHE FILEPATH "Path to SDL2 library") \ No newline at end of file + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${_INCLUDE_DIR} CACHE PATH "Location of SDL2 include directory") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${_LIB_DIR}/${_LIB_PREFIX}SDL2.${_LIB_EXT} CACHE FILEPATH "Path to SDL2 library") +endif () \ No newline at end of file From e71a8258d6a7ec9e3e4cb2ef1b551bb0a7cc34fb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 09:52:35 -0800 Subject: [PATCH 149/341] fix SDL2 framework link on OS X --- cmake/externals/sdl2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 49bb68891d..3d59af4c06 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -43,7 +43,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (APPLE) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/SDL2.framework/Headers CACHE PATH "Location of SDL2 include directory") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/SDL2.framework CACHE PATH "Location of SDL2 framework") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP "-framework ${SOURCE_DIR}/SDL2.framework" CACHE STRING "Link string for SDL2 framework") else () if (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) From 24632923391c5a497d15f161b7b4ca4361c0bfd9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 10:00:44 -0800 Subject: [PATCH 150/341] link SDL2 as a downloaded framework on OS X --- cmake/externals/sdl2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/sdl2/CMakeLists.txt b/cmake/externals/sdl2/CMakeLists.txt index 3d59af4c06..d2a021e833 100644 --- a/cmake/externals/sdl2/CMakeLists.txt +++ b/cmake/externals/sdl2/CMakeLists.txt @@ -43,7 +43,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (APPLE) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${SOURCE_DIR}/SDL2.framework/Headers CACHE PATH "Location of SDL2 include directory") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP "-framework ${SOURCE_DIR}/SDL2.framework" CACHE STRING "Link string for SDL2 framework") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_TEMP ${SOURCE_DIR}/SDL2.framework/SDL2 CACHE STRING "Path to SDL2 library") else () if (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) From 1efa7b28b06643da311212dcd059fcddf88bc573 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 10:04:14 -0800 Subject: [PATCH 151/341] removed dead code --- libraries/script-engine/src/ScriptEngine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 6cae9fcfa4..17237d7843 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -531,7 +531,6 @@ void ScriptEngine::run() { } if (!_isFinished) { - //qDebug() << "ScriptEngine::run()... about to emit update() _scriptName:" << _scriptName << "_fileNameString:" << _fileNameString << "_isFinished:" << _isFinished; emit update(deltaTime); } lastUpdate = now; From 16c557a9c7a947d0fce6af9e1db9c5f81f882989 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 10:32:06 -0800 Subject: [PATCH 152/341] copy over /tmp/hifi.dst dir for xcode qxmpp install --- cmake/externals/qxmpp/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index c35708daa6..06b215845a 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -37,6 +37,19 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) +if (CMAKE_GENERATOR STREQUAL Xcode) + find_program(DITTO_COMMAND ditto) + + ExternalProject_Add_Step( + ${EXTERNAL_NAME} + copy-from-xcode-install + COMMENT "Copying from /tmp/hifi.dst${INSTALL_DIR} to move install to proper location" + COMMAND ${DITTO_COMMAND} /tmp/hifi.dst${INSTALL_DIR} ${INSTALL_DIR} + DEPENDEES install + LOG 1 + ) +endif () + string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") From 6042ba6cf21b3a31fa7c2cddb4569524cab2c5e4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 10:36:20 -0800 Subject: [PATCH 153/341] fix for qxmpp name on win and lib location --- cmake/externals/qxmpp/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index 06b215845a..4d76c6901f 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -54,18 +54,18 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") if (WIN32) - set(_LIB_EXT "lib") + set(_LIB_EXT "0.lib") set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of QXmpp DLL") else () if (APPLE) set(_LIB_EXT "dylib") else () - set(_LIB_EXT "so") + set(_LIB_EXT ".so") endif () set(_LIB_PREFIX "lib") endif () -set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_PREFIX}qxmpp.${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Path to QXmpp debug library") From 0990910ed2c24949431a88adb83d21e2f48afcba Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 10:41:48 -0800 Subject: [PATCH 154/341] add a missing period for apple qxmpp ext --- cmake/externals/qxmpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index 4d76c6901f..25ec409efb 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -59,7 +59,7 @@ if (WIN32) set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of QXmpp DLL") else () if (APPLE) - set(_LIB_EXT "dylib") + set(_LIB_EXT ".dylib") else () set(_LIB_EXT ".so") endif () From 353f7e2f96d1f2fb1bc67d8d430f4bb110932032 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 10:59:54 -0800 Subject: [PATCH 155/341] set qxmpp debug library to empty string --- cmake/externals/qxmpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index 25ec409efb..451ee19be4 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -68,4 +68,4 @@ else () endif () set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") -set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Path to QXmpp debug library") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QXmpp debug library") From 80da0a17029e973e9ffe20c44da7c4af9b486d51 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:11:35 -0800 Subject: [PATCH 156/341] use empty string for not present debug libraries --- cmake/externals/bullet/CMakeLists.txt | 8 ++++---- cmake/externals/glew/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 4fb8b0a5d1..3c83b84fcd 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -52,16 +52,16 @@ endif () if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics release library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet dynamics debug library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet dynamics debug library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet collision debug library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet math debug library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet softbody debug library location") endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) diff --git a/cmake/externals/glew/CMakeLists.txt b/cmake/externals/glew/CMakeLists.txt index e960eb8bcb..0d80e7a789 100644 --- a/cmake/externals/glew/CMakeLists.txt +++ b/cmake/externals/glew/CMakeLists.txt @@ -20,7 +20,7 @@ if (WIN32) set(_LIB_DIR ${SOURCE_DIR}/lib/Release/Win32) set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/glew32.lib CACHE FILEPATH "Location of GLEW release library") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG NOTFOUND CACHE FILEPATH "Location of GLEW debug library") + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Location of GLEW debug library") set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${SOURCE_DIR}/bin/Release/Win32 CACHE FILEPATH "Location of GLEW DLL") endif () \ No newline at end of file From 0b9b7f06cc8088b530b3b99d9d23d0f74322ed93 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 23 Feb 2015 11:12:19 -0800 Subject: [PATCH 157/341] address various comments from code review --- assignment-client/src/AssignmentClient.cpp | 8 ++--- assignment-client/src/AssignmentClientApp.cpp | 4 --- assignment-client/src/AssignmentClientApp.h | 1 - .../src/AssignmentClientChildData.cpp | 8 +++++ .../src/AssignmentClientChildData.h | 32 +++++++++++++++++ .../src/AssignmentClientMonitor.cpp | 34 ++++++++----------- .../src/AssignmentClientMonitor.h | 17 ++-------- libraries/networking/src/LimitedNodeList.cpp | 4 +-- libraries/networking/src/LimitedNodeList.h | 2 +- 9 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 assignment-client/src/AssignmentClientChildData.cpp create mode 100644 assignment-client/src/AssignmentClientChildData.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 5fcc380962..2dfc3787de 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -159,8 +159,8 @@ void AssignmentClient::setUpStatsToMonitor() { quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; auto nodeList = DependencyManager::get(); - nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, - _localACMPortSharedMem, localMonitorServerPort); + nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); // send a stats packet every 1 seconds @@ -189,8 +189,8 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted quint16 localAssignmentServerPort; - if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, - localAssignmentServerPort)) { + if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 8848b59c49..477f1a2cf8 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -64,7 +64,3 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : client.exec(); } } - - -AssignmentClientApp::~AssignmentClientApp() { -} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index 09952ad19c..c5099ff25c 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -15,5 +15,4 @@ class AssignmentClientApp : public QCoreApplication { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); - ~AssignmentClientApp(); }; diff --git a/assignment-client/src/AssignmentClientChildData.cpp b/assignment-client/src/AssignmentClientChildData.cpp new file mode 100644 index 0000000000..de34613ec9 --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.cpp @@ -0,0 +1,8 @@ + +#include "AssignmentClientChildData.h" + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) : + _childType(childType) +{ +} diff --git a/assignment-client/src/AssignmentClientChildData.h b/assignment-client/src/AssignmentClientChildData.h new file mode 100644 index 0000000000..6fd5f72f7f --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.h @@ -0,0 +1,32 @@ +// +// AssignmentClientChildData.h +// assignment-client/src +// +// Created by Seth Alves on 2/23/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AssignmentClientChildData_h +#define hifi_AssignmentClientChildData_h + +#include + + +class AssignmentClientChildData : public NodeData { + public: + AssignmentClientChildData(QString childType); + + QString getChildType() { return _childType; } + void setChildType(QString childType) { _childType = childType; } + + // implement parseData to return 0 so we can be a subclass of NodeData + int parseData(const QByteArray& packet) { return 0; } + + private: + QString _childType; +}; + +#endif // hifi_AssignmentClientChildData_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 2bddab9656..803c7fd5c7 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -16,6 +16,7 @@ #include #include "AssignmentClientMonitor.h" +#include "AssignmentClientChildData.h" #include "PacketHeaders.h" #include "SharedUtil.h" @@ -72,12 +73,12 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { void AssignmentClientMonitor::stopChildProcesses() { auto nodeList = DependencyManager::get(); - nodeList->eachNode([&](const SharedNodePointer& node){ - qDebug() << "asking child" << node->getUUID() << "to exit."; - node->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); - }); + nodeList->eachNode([&](const SharedNodePointer& node) { + qDebug() << "asking child" << node->getUUID() << "to exit."; + node->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); + }); } void AssignmentClientMonitor::spawnChildClient() { @@ -100,13 +101,13 @@ void AssignmentClientMonitor::checkSpares() { nodeList->removeSilentNodes(); - nodeList->eachNode([&](const SharedNodePointer& node){ - AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - if (childData->getChildType() == "none") { - spareCount ++; - aSpareId = node->getUUID(); - } - }); + nodeList->eachNode([&](const SharedNodePointer& node) { + AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + if (childData->getChildType() == "none") { + spareCount ++; + aSpareId = node->getUUID(); + } + }); if (spareCount != 1) { qDebug() << "spare count is" << spareCount; @@ -189,10 +190,3 @@ void AssignmentClientMonitor::readPendingDatagrams() { } -AssignmentClientChildData::AssignmentClientChildData(QString childType) { - _childType = childType; -} - - -AssignmentClientChildData::~AssignmentClientChildData() { -} diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 8055b5d81f..71ae34bc8c 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -19,23 +19,10 @@ #include +#include "AssignmentClientChildData.h" + extern const char* NUM_FORKS_PARAMETER; -class AssignmentClientChildData : public NodeData { - public: - AssignmentClientChildData(QString childType); - ~AssignmentClientChildData(); - - QString getChildType() { return _childType; } - void setChildType(QString childType) { _childType = childType; } - - // implement parseData to return 0 so we can be a subclass of NodeData - int parseData(const QByteArray& packet) { return 0; } - - private: - QString _childType; -}; - class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 075fd5a44b..4fc0648c4d 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,8 +688,8 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, - quint16& localPort) { +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, + quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index b53287562b..27cddb4b24 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); public slots: void reset(); From 9878a9333866c3dcd52dbb95bf22d7e8e4b4d49b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:13:10 -0800 Subject: [PATCH 158/341] add a definition for shared QXmpp on win --- interface/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1c27d8f9db..92d34972d5 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -175,9 +175,14 @@ if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE) target_link_libraries(${TARGET_NAME} ${CoreMIDI}) endif () -if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32 AND NOT QXMPP_DLL_PATH) - # if we have no QXmpp DLL path, assume we're linking a static QXmpp on windows - add_definitions(-DQXMPP_STATIC) +if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32) + if (NOT QXMPP_DLL_PATH) + # if we have no QXmpp DLL path, assume we're linking a static QXmpp on windows + add_definitions(-DQXMPP_STATIC) + else () + # otherwise assume we are linking a dynamic QXmpp + add_definitions(-DQXMPP_SHARED) + endif () endif () # include headers for interface and InterfaceConfig. From 1372436e6340f39b23352efececce29c3bdeec5c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:20:50 -0800 Subject: [PATCH 159/341] handle possibility that bullet builds debug libraries --- cmake/externals/bullet/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 3c83b84fcd..bdc7740020 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -52,16 +52,16 @@ endif () if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics release library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet dynamics debug library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics debug library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision debug library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math debug library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody debug library location") endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) From 6803aa8d913bc6b4670544c46b8e1ed536a05afc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:22:21 -0800 Subject: [PATCH 160/341] fix copy paste typos --- cmake/externals/bullet/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index bdc7740020..3680bf459f 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -55,13 +55,13 @@ if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics debug library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision debug library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math debug library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody debug library location") endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) From 5983a94c7f7773bd000a4d556d4348a50622961f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:29:42 -0800 Subject: [PATCH 161/341] force bullet cmake build to be RelWithDebInfo --- cmake/externals/bullet/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 3680bf459f..f9e812b119 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -25,7 +25,7 @@ ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} URL_MD5 ${DOWNLOAD_MD5} - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 @@ -52,16 +52,16 @@ endif () if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics release library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics debug library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet dynamics debug library location") set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet collision debug library location") set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet math debug library location") set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet softbody debug library location") endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) From 7e2d355b56b2cc0cc594151b210e9f4bdfb7d410 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 11:40:30 -0800 Subject: [PATCH 162/341] first cut at properly shutting down timers while shutting down scripts --- libraries/script-engine/src/ScriptEngine.cpp | 14 ++++++++++++++ libraries/script-engine/src/ScriptEngine.h | 1 + 2 files changed, 15 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 17237d7843..0919dc5d59 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -535,6 +535,9 @@ void ScriptEngine::run() { } lastUpdate = now; } + + stopAllTimers(); // make sure all our timers are stopped if the script is ending + emit scriptEnding(); // kill the avatar identity timer @@ -564,6 +567,17 @@ void ScriptEngine::run() { emit doneRunning(); } +// NOTE: This is private because it must be called on the same thread that created the timers, which is why +// we want to only call it in our own run "shutdown" processing. +void ScriptEngine::stopAllTimers() { + QMutableHashIterator i(_timerFunctionMap); + while (i.hasNext()) { + i.next(); + QTimer* timer = i.key(); + stopTimer(timer); + } +} + void ScriptEngine::stop() { _isFinished = true; emit runningStateChanged(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index ab32f2c0a5..8963a1e0f6 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -141,6 +141,7 @@ protected: int _numAvatarSoundSentBytes; private: + void stopAllTimers(); void sendAvatarIdentityPacket(); void sendAvatarBillboardPacket(); From 2f4adbc2f7981fcd362252cd393c671bb37b79cf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 11:40:38 -0800 Subject: [PATCH 163/341] also use release icon for RelWithDebInfo --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 92d34972d5..37887f5e14 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -76,7 +76,7 @@ if (APPLE) set(MACOSX_BUNDLE_BUNDLE_NAME Interface) set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.Interface) - if (CMAKE_BUILD_TYPE STREQUAL "Release") + if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") set(ICON_FILENAME "interface.icns") else () set(ICON_FILENAME "interface-beta.icns") From e60d91e4cee8f101f639cc0dfca83f3166f6c053 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:00:19 -0800 Subject: [PATCH 164/341] fix for bullet debug or release build on windows --- cmake/externals/bullet/CMakeLists.txt | 51 +++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index f9e812b119..efcb2f99bc 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -12,25 +12,40 @@ else () endif() endif () -if (WIN32) - set(DOWNLOAD_URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip) - set(DOWNLOAD_MD5 f5e8914fc9064ad32e0d62d19d33d977) -else () - set(DOWNLOAD_URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz) - set(DOWNLOAD_MD5 70b3c8d202dee91a0854b4cbc88173e8) -endif () - include(ExternalProject) -ExternalProject_Add( - ${EXTERNAL_NAME} - URL ${DOWNLOAD_URL} - URL_MD5 ${DOWNLOAD_MD5} - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 - BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build -) + +if (WIN32) + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(MSBUILD_CONFIGURATION Debug) + else () + set(MSBUILD_CONFIGURATION Release) + endif () + + find_program(MSBUILD_COMMAND msbuild) + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip + URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + BUILD_COMMAND ${MSBUILD_COMMAND} bullet.vcxproj /t:Build /p:Configuration=${MSBUILD_CONFIGURATION} + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + ) +else () + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz + URL_MD5 70b3c8d202dee91a0854b4cbc88173e8 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build + ) +endif () ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) From 793116b90cff736102f74f0a90137faaad4fe463 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 23 Feb 2015 21:00:26 +0100 Subject: [PATCH 165/341] ability to mute all notifications or just certain types --- examples/notifications.js | 135 ++++++++++++++++++++++++++++---------- 1 file changed, 102 insertions(+), 33 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index f9d2ba83ed..27192ed789 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -38,11 +38,13 @@ // function onIncomingMessage(user, message) { // //do stuff here; // var text = "This is a notification"; -// wordWrap(text); +// var wrappedText = wordWrap(text); +// createNotification(wrappedText, NotificationType.SNAPSHOT); // } // // This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. -// wordWrap() will format the text to fit the notifications overlay and send it to createNotification(text). +// wordWrap() will format the text to fit the notifications overlay and return it +// after that we will send it to createNotification(text). // If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly. @@ -50,12 +52,12 @@ // // 1. Add a key to the keyPressEvent(key). // 2. Declare a text string. -// 3. Call createNotifications(text) parsing the text. +// 3. Call createNotifications(text, NotificationType) parsing the text. // example: // var welcome; // if (key.text == "q") { //queries number of users online // var welcome = "There are " + GlobalServices.onlineUsers.length + " users online now."; -// createNotification(welcome); +// createNotification(welcome, NotificationType.USERS_ONLINE); // } Script.include("./libraries/globals.js"); Script.include("./libraries/soundArray.js"); @@ -83,6 +85,46 @@ var last_users = GlobalServices.onlineUsers; var users = []; var ctrlIsPressed = false; var ready = true; +var MENU_NAME = 'Tools > Notifications'; +var PLAY_NOTIFICATION_SOUNDS_MENU_ITEM = "Play Notification Sounds"; +var NOTIFICATION_MENU_ITEM_POST = " Notifications"; +var PLAY_NOTIFICATION_SOUNDS_SETTING = "play_notification_sounds"; +var PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE = "play_notification_sounds_type_"; + +var NotificationType = { + UNKNOWN: 0, + USER_JOINS: 1, + USER_LEAVES: 2, + MUTE_TOGGLE: 3, + CHAT_MENTION: 4, + USERS_ONLINE: 5, + SNAPSHOT: 6, + WINDOW_RESIZE: 7, + properties: [ + { text: "User Join" }, + { text: "User Leave" }, + { text: "Mute Toggle" }, + { text: "Chat Mention" }, + { text: "Users Online" }, + { text: "Snapshot" }, + { text: "Window Resize" } + ], + getTypeFromMenuItem: function(menuItemName) { + if (menuItemName.substr(menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length) !== NOTIFICATION_MENU_ITEM_POST) { + return NotificationType.UNKNOWN; + } + var preMenuItemName = menuItemName.substr(0, menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length); + for (type in this.properties) { + if (this.properties[type].text === preMenuItemName) { + return parseInt(type) + 1; + } + } + return NotificationType.UNKNOWN; + }, + getMenuString: function(type) { + return this.properties[type - 1].text + NOTIFICATION_MENU_ITEM_POST; + } +}; var randomSounds = new SoundArray({ localOnly: true }, true); var numberOfSounds = 2; @@ -90,15 +132,6 @@ for (var i = 1; i <= numberOfSounds; i++) { randomSounds.addSound(HIFI_PUBLIC_BUCKET + "sounds/UI/notification-general" + i + ".raw"); } -// When our script shuts down, we should clean up all of our overlays -function scriptEnding() { - for (i = 0; i < notifications.length; i++) { - Overlays.deleteOverlay(notifications[i]); - Overlays.deleteOverlay(buttons[i]); - } -} -Script.scriptEnding.connect(scriptEnding); - var notifications = []; var buttons = []; var times = []; @@ -211,8 +244,6 @@ function notify(notice, button, height) { positions, last; - randomSounds.playRandom(); - if (isOnHMD) { // Calculate 3D values from 2D overlay properties. @@ -257,7 +288,7 @@ function notify(notice, button, height) { } // This function creates and sizes the overlays -function createNotification(text) { +function createNotification(text, notificationType) { var count = (text.match(/\n/g) || []).length, breakPoint = 43.0, // length when new line is added extraLine = 0, @@ -307,6 +338,12 @@ function createNotification(text) { alpha: backgroundAlpha }; + if (Menu.isOptionChecked(PLAY_NOTIFICATION_SOUNDS_MENU_ITEM) && + Menu.isOptionChecked(NotificationType.getMenuString(notificationType))) + { + randomSounds.playRandom(); + } + notify(noticeProperties, buttonProperties, height); } @@ -345,8 +382,7 @@ function stringDivider(str, slotWidth, spaceReplacer) { // formats string to add newline every 43 chars function wordWrap(str) { - var result = stringDivider(str, 43.0, "\n"); - createNotification(result); + return stringDivider(str, 43.0, "\n"); } // This fires a notification on window resize @@ -358,7 +394,7 @@ function checkSize() { windowDimensions = Controller.getViewportDimensions(); overlayLocationX = (windowDimensions.x - (width + 60.0)); buttonLocationX = overlayLocationX + (width - 35.0); - createNotification(windowResize); + createNotification(windowResize, NotificationType.WINDOW_RESIZE); } } @@ -442,10 +478,7 @@ var STARTUP_TIMEOUT = 500, // ms // This reports the number of users online at startup function reportUsers() { - var welcome; - - welcome = "Welcome! There are " + GlobalServices.onlineUsers.length + " users online now."; - createNotification(welcome); + createNotification("Welcome! There are " + GlobalServices.onlineUsers.length + " users online now.", NotificationType.USERS_ONLINE); } function finishStartup() { @@ -472,13 +505,13 @@ function onOnlineUsersChanged(users) { if (!isStartingUp()) { // Skip user notifications at startup. for (i = 0; i < users.length; i += 1) { if (last_users.indexOf(users[i]) === -1.0) { - createNotification(users[i] + " has joined"); + createNotification(users[i] + " has joined", NotificationType.USER_JOINS); } } for (i = 0; i < last_users.length; i += 1) { if (users.indexOf(last_users[i]) === -1.0) { - createNotification(last_users[i] + " has left"); + createNotification(last_users[i] + " has left", NotificationType.USER_LEAVES); } } } @@ -497,7 +530,7 @@ function onIncomingMessage(user, message) { thisAlert = user + ": " + myMessage; if (myMessage.indexOf(alertMe) > -1.0) { - wordWrap(thisAlert); + CreateNotification(wordWrap(thisAlert), NotificationType.CHAT_MENTION); } } @@ -506,9 +539,9 @@ function onMuteStateChanged() { var muteState, muteString; - muteState = AudioDevice.getMuted() ? "muted" : "unmuted"; + muteState = AudioDevice.getMuted() ? "muted" : "unmuted"; muteString = "Microphone is now " + muteState; - createNotification(muteString); + createNotification(muteString, NotificationType.MUTE_TOGGLE); } // handles mouse clicks on buttons @@ -551,25 +584,58 @@ function keyPressEvent(key) { if (key.text === "q") { //queries number of users online numUsers = GlobalServices.onlineUsers.length; welcome = "There are " + numUsers + " users online now."; - createNotification(welcome); + createNotification(welcome, NotificationType.USERS_ONLINE); } if (key.text === "s") { if (ctrlIsPressed === true) { noteString = "Snapshot taken."; - createNotification(noteString); + createNotification(noteString, NotificationType.SNAPSHOT); } } } +function setup() { + Menu.addMenu(MENU_NAME); + var checked = Settings.getValue(PLAY_NOTIFICATION_SOUNDS_SETTING); + checked = checked === '' ? true : checked; + Menu.addMenuItem({ + menuName: MENU_NAME, + menuItemName: PLAY_NOTIFICATION_SOUNDS_MENU_ITEM, + isCheckable: true, + isChecked: Settings.getValue(PLAY_NOTIFICATION_SOUNDS_SETTING) + }); + Menu.addSeparator(MENU_NAME, "Play sounds for:"); + for (type in NotificationType.properties) { + checked = Settings.getValue(PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE + (parseInt(type) + 1)); + checked = checked === '' ? true : checked; + Menu.addMenuItem({ + menuName: MENU_NAME, + menuItemName: NotificationType.properties[type].text + NOTIFICATION_MENU_ITEM_POST, + isCheckable: true, + isChecked: checked + }); + } +} + // When our script shuts down, we should clean up all of our overlays function scriptEnding() { - var i; - - for (i = 0; i < notifications.length; i += 1) { + for (var i = 0; i < notifications.length; i++) { Overlays.deleteOverlay(notifications[i]); Overlays.deleteOverlay(buttons[i]); } + Menu.removeMenu(MENU_NAME); +} + +function menuItemEvent(menuItem) { + if (menuItem === PLAY_NOTIFICATION_SOUNDS_MENU_ITEM) { + Settings.setValue(PLAY_NOTIFICATION_SOUNDS_SETTING, Menu.isOptionChecked(PLAY_NOTIFICATION_SOUNDS_MENU_ITEM)); + return; + } + var notificationType = NotificationType.getTypeFromMenuItem(menuItem); + if (notificationType !== notificationType.UNKNOWN) { + Settings.setValue(PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE + notificationType, Menu.isOptionChecked(menuItem)); + } } AudioDevice.muteToggled.connect(onMuteStateChanged); @@ -580,3 +646,6 @@ GlobalServices.incomingMessage.connect(onIncomingMessage); Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); +Menu.menuItemEvent.connect(menuItemEvent); + +setup(); From ded0b1461b6427207272afb39317ff2315e5477d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:04:35 -0800 Subject: [PATCH 166/341] help cmake find msbuild --- cmake/externals/bullet/CMakeLists.txt | 2 +- cmake/externals/qxmpp/CMakeLists.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index efcb2f99bc..71bb6c7a83 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -21,7 +21,7 @@ if (WIN32) set(MSBUILD_CONFIGURATION Release) endif () - find_program(MSBUILD_COMMAND msbuild) + find_program(MSBUILD_COMMAND msbuild PATHS "C:/Program Files (x86)/MSBUILD/12.0/Bin") ExternalProject_Add( ${EXTERNAL_NAME} diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index 451ee19be4..f3f92be71e 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -12,7 +12,8 @@ if (ANDROID) endif () if (WIN32) - find_program(PLATFORM_BUILD_COMMAND nmake) + find_program(PLATFORM_BUILD_COMMAND nmake PATHS "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin") + if (NOT PLATFORM_BUILD_COMMAND) message(FATAL_ERROR "You asked CMake to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") endif () From 9e1a890ff293ad24f009b943e48d9072aa117f18 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:09:00 -0800 Subject: [PATCH 167/341] fix for msbuild target command --- cmake/externals/bullet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 71bb6c7a83..ff39716512 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -28,7 +28,7 @@ if (WIN32) URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - BUILD_COMMAND ${MSBUILD_COMMAND} bullet.vcxproj /t:Build /p:Configuration=${MSBUILD_CONFIGURATION} + BUILD_COMMAND ${MSBUILD_COMMAND} bullet.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 8d97107acf258cecda7f2e3021decf4dca934621 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:12:36 -0800 Subject: [PATCH 168/341] use ALL_BUILD for bullet msbuild --- cmake/externals/bullet/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index ff39716512..7c5c7967d3 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -27,8 +27,8 @@ if (WIN32) ${EXTERNAL_NAME} URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - BUILD_COMMAND ${MSBUILD_COMMAND} bullet.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 88130feb11016c27d46b8698a85c732c08a5b8b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:19:54 -0800 Subject: [PATCH 169/341] force release build of bullet on win32 --- cmake/externals/bullet/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 7c5c7967d3..3e1b932a4f 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -27,8 +27,8 @@ if (WIN32) ${EXTERNAL_NAME} URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=Release LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From b32fa0f33d4570e0ce4db1bf6a85623d77768678 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:27:30 -0800 Subject: [PATCH 170/341] pass correct configuration to bullet install target --- cmake/externals/bullet/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 3e1b932a4f..9d8da889c6 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -29,6 +29,7 @@ if (WIN32) URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=Release + INSTALL_COMMAND ${MSBUILD_COMMAND} INSTALL.vcxproj /p:Configuration=Release LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 2ad8ac866df3c82fa24e88e1430d846075ada5ce Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 12:50:53 -0800 Subject: [PATCH 171/341] make correct version of bullet for windows --- CMakeLists.txt | 6 ++++ cmake/android/QtCreateAPK.cmake | 2 +- cmake/externals/bullet/CMakeLists.txt | 34 ++++++++++++------- .../CopyDllsBesideWindowsExecutable.cmake | 2 +- interface/CMakeLists.txt | 2 +- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a79476f17f..25c18fc058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,12 @@ set(HIFI_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries") # setup for find modules set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") +if (CMAKE_BUILD_TYPE) + string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_CMAKE_BUILD_TYPE) +else () + set(UPPER_CMAKE_BUILD_TYPE DEBUG) +endif () + set(HIFI_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(MACRO_DIR "${HIFI_CMAKE_DIR}/macros") set(EXTERNAL_PROJECT_DIR "${HIFI_CMAKE_DIR}/externals") diff --git a/cmake/android/QtCreateAPK.cmake b/cmake/android/QtCreateAPK.cmake index c3a4a48ac7..30ee2f57bd 100644 --- a/cmake/android/QtCreateAPK.cmake +++ b/cmake/android/QtCreateAPK.cmake @@ -26,7 +26,7 @@ macro(qt_create_apk) set(ANDROID_APK_THEME "") endif() - if (CMAKE_BUILD_TYPE MATCHES RELEASE) + if (UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE) set(ANDROID_APK_DEBUGGABLE "false") set(ANDROID_APK_RELEASE_LOCAL ${ANDROID_APK_RELEASE}) else () diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 9d8da889c6..d08ceb11b9 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -15,7 +15,7 @@ endif () include(ExternalProject) if (WIN32) - if (CMAKE_BUILD_TYPE STREQUAL "Debug") + if (UPPER_CMAKE_BUILD_TYPE MATCHES DEBUG) set(MSBUILD_CONFIGURATION Debug) else () set(MSBUILD_CONFIGURATION Release) @@ -27,9 +27,8 @@ if (WIN32) ${EXTERNAL_NAME} URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=Release - INSTALL_COMMAND ${MSBUILD_COMMAND} INSTALL.vcxproj /p:Configuration=Release + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 @@ -67,19 +66,28 @@ elseif (WIN32) endif () if (DEFINED BULLET_LIB_EXT) - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics release library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet dynamics debug library location") + if (NOT WIN32 OR UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE) + set(_PRESENT_LIB_TYPE RELEASE) + set(_MISSING_LIB_TYPE DEBUG) + else () + set(_PRESENT_LIB_TYPE DEBUG) + set(_MISSING_LIB_TYPE RELEASE) + set(_LIB_NAME_SUFFIX _Debug) + endif () + + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics ${_PRESENT_LIB_TYPE} library location") + set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet dynamics ${_MISSING_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision release library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet collision debug library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision ${_PRESENT_LIB_TYPE} library location") + set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet collision ${_MISSING_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math release library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet math debug library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math ${_PRESENT_LIB_TYPE} library location") + set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet math ${_MISSING_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody release library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_DEBUG "" CACHE FILEPATH "Bullet softbody debug library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody ${_PRESENT_LIB_TYPE} library location") + set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet softbody ${_MISSING_LIB_TYPE} library location") endif () -if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) +if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_PRESENT_LIB_TYPE}) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE PATH "Path to bullet include directory") endif () \ No newline at end of file diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 2498c0dcf3..0ec7b50fd8 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -10,7 +10,7 @@ # macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) - if (WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") + if (WIN32 AND NOT UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE) configure_file( ${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 37887f5e14..ee41648758 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -76,7 +76,7 @@ if (APPLE) set(MACOSX_BUNDLE_BUNDLE_NAME Interface) set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.Interface) - if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + if (UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE OR UPPER_CMAKE_BUILD_TYPE MATCHES RELWITHDEBINFO) set(ICON_FILENAME "interface.icns") else () set(ICON_FILENAME "interface-beta.icns") From 954a298dc4632889f44d42d0666b7049e782ee2b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 13:04:12 -0800 Subject: [PATCH 172/341] correct QXmpp DLL path for windows --- cmake/externals/qxmpp/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index f3f92be71e..c8bbdba6ba 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -54,6 +54,8 @@ endif () string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") +set(_LIB_DIR ${INSTALL_DIR}/lib) + if (WIN32) set(_LIB_EXT "0.lib") @@ -68,5 +70,5 @@ else () set(_LIB_PREFIX "lib") endif () -set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") +set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QXmpp debug library") From 687c76a6f8ae0aff1cf1554a9d929cee01109035 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Feb 2015 13:12:29 -0800 Subject: [PATCH 173/341] trying to ge the shadow to render correctly --- interface/src/Application.cpp | 6 +++++- libraries/octree/src/ViewFrustum.cpp | 16 ++++++++++------ libraries/render-utils/src/Shadow.slh | 2 ++ .../src/directional_ambient_light_shadow_map.slf | 2 ++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1211df3727..f533765644 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2564,7 +2564,9 @@ void Application::updateShadowMap() { glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation)); // update the shadow view frustum - _shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f)); + // glm::vec3 shadowFrustumCenter = glm::vec3((minima.x + maxima.x) * 0.5f, (minima.y + maxima.y) * 0.5f, (minima.z + maxima.z) * 0.5f); + glm::vec3 shadowFrustumCenter = rotation * ((minima + maxima) * 0.5f); + _shadowViewFrustum.setPosition(shadowFrustumCenter); _shadowViewFrustum.setOrientation(rotation); _shadowViewFrustum.setOrthographic(true); _shadowViewFrustum.setWidth(maxima.x - minima.x); @@ -2594,8 +2596,10 @@ void Application::updateShadowMap() { // this is what is used for rendering the Entities and avatars Transform viewTransform; viewTransform.setRotation(rotation); + // viewTransform.postTranslate(shadowFrustumCenter); setViewTransform(viewTransform); + glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index f92ba0a742..fac017218d 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -577,6 +577,10 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom // compute our dimensions the usual way float hheight = _nearClip * tanf(_fieldOfView * 0.5f * RADIANS_PER_DEGREE); float hwidth = _aspectRatio * hheight; + if (isOrthographic()) { + hheight = getHeight(); + hwidth = getWidth(); + } // get our frustum corners in view space glm::mat4 eyeMatrix = glm::mat4_cast(glm::inverse(_eyeOffsetOrientation)) * glm::translate(-_eyeOffsetPosition); @@ -868,18 +872,18 @@ float ViewFrustum::distanceToCamera(const glm::vec3& point) const { void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { if (isOrthographic()) { - float left, right, bottom, top, near, far; - glm::vec4 clip0, clip1; - computeOffAxisFrustum(left, right, bottom, top, near, far, clip0, clip1); + glm::vec3 frustumCenter = glm::inverse( _orientation) * _position; - proj = glm::ortho(left, right, bottom, top); - proj = glm::ortho(-0.5f * getWidth(), +0.5f * getWidth(), -0.5f * getWidth(), +0.5f * getWidth()); + proj = glm::ortho(frustumCenter.x -0.5f * getWidth(), + frustumCenter.x +0.5f * getWidth(), + frustumCenter.y -0.5f * getHeight(), + frustumCenter.y +0.5f * getHeight(), + -getFarClip(), -getNearClip()); } else { float left, right, bottom, top, near, far; glm::vec4 clip0, clip1; computeOffAxisFrustum(left, right, bottom, top, near, far, clip0, clip1); proj = glm::perspective(glm::radians(getFieldOfView()), getAspectRatio(), getNearClip(), getFarClip()); - // proj = glm::perspective(getFieldOfView() * 0.5f, getAspectRatio(), getNearClip(), getFarClip()); } } diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index a8d0ce457a..d4c19915ff 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -31,6 +31,8 @@ uniform vec3 shadowDistances; // the inverse of the size of the shadow map uniform float shadowScale; +uniform mat4 shadowMatrices[4]; + vec2 samples[8] = vec2[8]( vec2(-2.0, -2.0), vec2(2.0, -2.0), diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf index 7f098eac2e..3407cb03e3 100755 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf @@ -46,4 +46,6 @@ void main(void) { gl_FragColor = vec4(color, frag.normalVal.a); } + + gl_FragColor = vec4(vec3(shadowAttenuation), 1.0); } From bae5d987f91bff9086d0136bb90654266391d5cb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 13:21:45 -0800 Subject: [PATCH 174/341] add OpenSSL lib path to paths for fixup --- cmake/modules/FindOpenSSL.cmake | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake index 8298cc75b4..1d749a910c 100644 --- a/cmake/modules/FindOpenSSL.cmake +++ b/cmake/modules/FindOpenSSL.cmake @@ -98,6 +98,9 @@ if (WIN32 AND NOT CYGWIN) select_library_configurations(SSL_EAY) set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY}) + + find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS}) + elseif (MINGW) # same player, for MinGW set(LIB_EAY_NAMES libeay32) @@ -218,11 +221,15 @@ endif () include(FindPackageHandleStandardArgs) +set(OPENSSL_REQUIREMENTS OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIR) +if (WIN32) + list(APPEND OPENSSL_REQUIREMENTS OPENSSL_DLL_PATH) +endif () + if (OPENSSL_VERSION) find_package_handle_standard_args(OpenSSL REQUIRED_VARS - OPENSSL_LIBRARIES - OPENSSL_INCLUDE_DIR + ${OPENSSL_REQUIREMENTS} VERSION_VAR OPENSSL_VERSION FAIL_MESSAGE @@ -230,9 +237,12 @@ if (OPENSSL_VERSION) ) else () find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR" - OPENSSL_LIBRARIES - OPENSSL_INCLUDE_DIR + ${OPENSSL_REQUIREMENTS} ) endif () +if (WIN32) + add_paths_to_lib_paths(${OPENSSL_DLL_PATH}) +endif () + mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS) From 8be707f63f62482158abaa5864d36f2334e4c61a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 13:24:17 -0800 Subject: [PATCH 175/341] rename add paths macro for fixup_bundle --- CMakeLists.txt | 2 +- cmake/macros/AddPathsToLibPaths.cmake | 22 ------------------- cmake/modules/FindGLEW.cmake | 2 +- cmake/modules/FindLeapMotion.cmake | 2 +- cmake/modules/FindOpenSSL.cmake | 2 +- cmake/modules/FindQxmpp.cmake | 2 +- cmake/modules/FindSDL2.cmake | 2 +- cmake/modules/FindSixense.cmake | 2 +- cmake/modules/FindSoxr.cmake | 2 +- cmake/modules/FindTBB.cmake | 2 +- cmake/templates/FixupBundlePostBuild.cmake.in | 4 ++-- 11 files changed, 11 insertions(+), 33 deletions(-) delete mode 100644 cmake/macros/AddPathsToLibPaths.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 25c18fc058..f036a9c91f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,7 @@ option(GET_SDL2 "Get SDL2 library automatically as external project" 0) option(GET_QXMPP "GET Qxmpp library automatically as external project" 0) if (WIN32) - add_paths_to_lib_paths("${QT_DIR}/bin") + add_paths_to_fixup_libs("${QT_DIR}/bin") endif () # add subdirectories for all targets diff --git a/cmake/macros/AddPathsToLibPaths.cmake b/cmake/macros/AddPathsToLibPaths.cmake deleted file mode 100644 index 7ac31db83f..0000000000 --- a/cmake/macros/AddPathsToLibPaths.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# AddPathsToLibPaths.cmake -# cmake/macros -# -# Copyright 2015 High Fidelity, Inc. -# Created by Stephen Birarda on February 17, 2014 -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -macro(ADD_PATHS_TO_LIB_PATHS) - foreach(_PATH ${ARGN}) - set(_TEMP_LIB_PATHS ${LIB_PATHS}) - - list(APPEND _TEMP_LIB_PATHS ${_PATH}) - - list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) - - set(LIB_PATHS ${_TEMP_LIB_PATHS} CACHE STRING "Paths for external libraries passed to fixup_bundle" FORCE) - endforeach() -endmacro() \ No newline at end of file diff --git a/cmake/modules/FindGLEW.cmake b/cmake/modules/FindGLEW.cmake index 7abbe135cb..e86db3fdac 100644 --- a/cmake/modules/FindGLEW.cmake +++ b/cmake/modules/FindGLEW.cmake @@ -37,6 +37,6 @@ if (WIN32) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_INCLUDE_DIRS GLEW_LIBRARIES GLEW_DLL_PATH) - add_paths_to_lib_paths(${GLEW_DLL_PATH}) + add_paths_to_fixup_libs(${GLEW_DLL_PATH}) endif () diff --git a/cmake/modules/FindLeapMotion.cmake b/cmake/modules/FindLeapMotion.cmake index 6f177cd3d7..eafb031a07 100644 --- a/cmake/modules/FindLeapMotion.cmake +++ b/cmake/modules/FindLeapMotion.cmake @@ -40,7 +40,7 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LeapMotion DEFAULT_MSG ${LEAPMOTION_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${LEAPMOTION_DLL_PATH}) + add_paths_to_fixup_libs(${LEAPMOTION_DLL_PATH}) endif () mark_as_advanced(LEAPMOTION_INCLUDE_DIRS LEAPMOTION_LIBRARIES LEAPMOTION_SEARCH_DIRS) diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake index 1d749a910c..db3b2ba477 100644 --- a/cmake/modules/FindOpenSSL.cmake +++ b/cmake/modules/FindOpenSSL.cmake @@ -242,7 +242,7 @@ else () endif () if (WIN32) - add_paths_to_lib_paths(${OPENSSL_DLL_PATH}) + add_paths_to_fixup_libs(${OPENSSL_DLL_PATH}) endif () mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES OPENSSL_SEARCH_DIRS) diff --git a/cmake/modules/FindQxmpp.cmake b/cmake/modules/FindQxmpp.cmake index 489936688e..5caa929427 100644 --- a/cmake/modules/FindQxmpp.cmake +++ b/cmake/modules/FindQxmpp.cmake @@ -41,5 +41,5 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(QXmpp DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_LIBRARY) if (QXMPP_DLL_PATH) - add_paths_to_lib_paths(${QXMPP_DLL_PATH}) + add_paths_to_fixup_libs(${QXMPP_DLL_PATH}) endif () \ No newline at end of file diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index 8c7c0c581b..1a089bcb60 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -220,5 +220,5 @@ endif () FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS ${SDL2_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${SDL2_DLL_PATH}) + add_paths_to_fixup_libs(${SDL2_DLL_PATH}) endif () diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index f47cfa65ad..0f4346c53d 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -52,7 +52,7 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sixense DEFAULT_MSG ${SIXENSE_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH} ${SIXENSE_DEVICE_DLL_PATH}) + add_paths_to_fixup_libs(${SIXENSE_DEBUG_DLL_PATH} ${SIXENSE_RELEASE_DLL_PATH} ${SIXENSE_DEVICE_DLL_PATH}) endif () mark_as_advanced(SIXENSE_LIBRARIES SIXENSE_INCLUDE_DIRS SIXENSE_SEARCH_DIRS) diff --git a/cmake/modules/FindSoxr.cmake b/cmake/modules/FindSoxr.cmake index 1c67650496..df6ad8050e 100644 --- a/cmake/modules/FindSoxr.cmake +++ b/cmake/modules/FindSoxr.cmake @@ -37,7 +37,7 @@ include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Soxr DEFAULT_MSG ${SOXR_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${SOXR_DLL_PATH}) + add_paths_to_fixup_libs(${SOXR_DLL_PATH}) endif () mark_as_advanced(SOXR_INCLUDE_DIRS SOXR_LIBRARIES SOXR_SEARCH_DIRS) \ No newline at end of file diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index 9781154c1a..4d4b3ca504 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -88,7 +88,7 @@ endif () find_package_handle_standard_args(TBB DEFAULT_MSG ${TBB_REQUIREMENTS}) if (WIN32) - add_paths_to_lib_paths(${TBB_DLL_PATH}) + add_paths_to_fixup_libs(${TBB_DLL_PATH}) endif () set(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY}) diff --git a/cmake/templates/FixupBundlePostBuild.cmake.in b/cmake/templates/FixupBundlePostBuild.cmake.in index f72ba577b9..7d98e9796c 100644 --- a/cmake/templates/FixupBundlePostBuild.cmake.in +++ b/cmake/templates/FixupBundlePostBuild.cmake.in @@ -10,5 +10,5 @@ # include(BundleUtilities) -message(STATUS "LIB_PATHS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @LIB_PATHS@") -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "@LIB_PATHS@") \ No newline at end of file +message(STATUS "FIXUP_LIBS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @FIXUP_LIBS@") +fixup_bundle("${BUNDLE_EXECUTABLE}" "" "@FIXUP_LIBS@") \ No newline at end of file From 87ce55cc42b218cce7497b4a0f12b6693d7879d6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 13:24:53 -0800 Subject: [PATCH 176/341] add new macro file for fixup libs --- cmake/macros/AddPathsToFixupLibs.cmake | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 cmake/macros/AddPathsToFixupLibs.cmake diff --git a/cmake/macros/AddPathsToFixupLibs.cmake b/cmake/macros/AddPathsToFixupLibs.cmake new file mode 100644 index 0000000000..913fcb7ee7 --- /dev/null +++ b/cmake/macros/AddPathsToFixupLibs.cmake @@ -0,0 +1,22 @@ +# +# AddPathsToFixupLibs.cmake +# cmake/macros +# +# Copyright 2015 High Fidelity, Inc. +# Created by Stephen Birarda on February 17, 2014 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(add_paths_to_fixup_libs) + foreach(_PATH ${ARGN}) + set(_TEMP_LIB_PATHS ${FIXUP_LIBS}) + + list(APPEND _TEMP_LIB_PATHS ${_PATH}) + + list(REMOVE_DUPLICATES _TEMP_LIB_PATHS) + + set(FIXUP_LIBS ${_TEMP_LIB_PATHS} CACHE STRING "Paths for external libraries passed to fixup_bundle" FORCE) + endforeach() +endmacro() \ No newline at end of file From 71dd443ae291732c6e5a8ccd4ff80bcdf6d44c6d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 15:29:43 -0800 Subject: [PATCH 177/341] also call fixup_bundle for release builds on win --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 0ec7b50fd8..4a1bc35fb7 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -10,7 +10,7 @@ # macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) - if (WIN32 AND NOT UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE) + if (WIN32) configure_file( ${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in From 086960f8aff112a938f2fd4b12f4898751f16535 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 23 Feb 2015 16:10:42 -0800 Subject: [PATCH 178/341] clarify the build guide for nmake and msbuild --- BUILD_WIN.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 290a8b8be6..212dd31f98 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -14,12 +14,18 @@ Or you can start a regular command prompt and then run: If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. -####nmake +####nmake & msbuild -Some of the external projects may require nmake to build and install. Please ensure that nmake is in your PATH so CMake can find it if required. For a typical Visual Studio installation, nmake.exe is located at the following path. +Some of the external projects may require nmake and msbuild to compile and install. If they are not installed at the locations listed below, please ensure that both are in your PATH so CMake can find them when required. + +We expect nmake.exe to be located at the following path. C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin +We exepect msbuild.exe to be located at the following path. + + C:\Program Files (x86)\MSBUILD\12.0\Bin + ###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. From 04a39275efa2562cfa17d034ad6a6344b2950f51 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Feb 2015 16:47:43 -0800 Subject: [PATCH 179/341] Trying to setup correctly the projection matrix for all the different cases... --- interface/src/avatar/Avatar.cpp | 6 +++--- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 8 ++++---- interface/src/avatar/MyAvatar.h | 2 +- libraries/render-utils/src/DeferredGlobalLight.slh | 7 ++++--- libraries/render-utils/src/Model.cpp | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9806098745..98db07a25b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -492,7 +492,7 @@ void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool RenderArgs args; args._viewFrustum = renderFrustum; _skeletonModel.render(1.0f, modelRenderMode, &args); - renderAttachments(renderMode); + renderAttachments(renderMode, &args); } } getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); @@ -522,11 +522,11 @@ void Avatar::simulateAttachments(float deltaTime) { } } -void Avatar::renderAttachments(RenderMode renderMode) { +void Avatar::renderAttachments(RenderMode renderMode, RenderArgs* args) { Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; foreach (Model* model, _attachmentModels) { - model->render(1.0f, modelRenderMode); + model->render(1.0f, modelRenderMode, args); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ee7a2a1736..93b8d811d5 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -227,7 +227,7 @@ protected: virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; void simulateAttachments(float deltaTime); - virtual void renderAttachments(RenderMode renderMode); + virtual void renderAttachments(RenderMode renderMode, RenderArgs* args); virtual void updateJointMappings(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f029f54b2a..c3ecd23a3f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1097,7 +1097,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo RenderArgs args; args._viewFrustum = renderFrustum; _skeletonModel.render(1.0f, modelRenderMode, &args); - renderAttachments(renderMode); + renderAttachments(renderMode, &args); } // Render head so long as the camera isn't inside it @@ -1902,9 +1902,9 @@ void MyAvatar::onToggleRagdoll() { } } -void MyAvatar::renderAttachments(RenderMode renderMode) { +void MyAvatar::renderAttachments(RenderMode renderMode, RenderArgs* args) { if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == MIRROR_RENDER_MODE) { - Avatar::renderAttachments(renderMode); + Avatar::renderAttachments(renderMode, args); return; } const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry(); @@ -1914,7 +1914,7 @@ void MyAvatar::renderAttachments(RenderMode renderMode) { for (int i = 0; i < _attachmentData.size(); i++) { const QString& jointName = _attachmentData.at(i).jointName; if (jointName != headJointName && jointName != "Head") { - _attachmentModels.at(i)->render(1.0f, modelRenderMode); + _attachmentModels.at(i)->render(1.0f, modelRenderMode, args); } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 63b4cd8a77..4255f40712 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -187,7 +187,7 @@ signals: void transformChanged(); protected: - virtual void renderAttachments(RenderMode renderMode); + virtual void renderAttachments(RenderMode renderMode, RenderArgs* args); private: float _turningKeyPressTime; diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 7f2190d3f1..966e69f7ff 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -96,15 +96,16 @@ vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, ve Light light = getLight(); - //vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); - // float diffuseDot = dot(fragNormal, getLightDirection(light)); - float diffuseDot = dot(normal, getLightDirection(light)); + float diffuseDot = dot(fragNormal, -getLightDirection(light)); + // float diffuseDot = dot(normal, getLightDirection(light)); // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot const float PERPENDICULAR_THRESHOLD = -0.005; float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); + //float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); // evaluate the shadow test but only relevant for light facing fragments float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f8cd363a5b..c632afa084 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -680,7 +680,7 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { // render the attachments foreach (Model* attachment, _attachments) { - attachment->render(alpha, mode); + attachment->render(alpha, mode, args); } if (_meshStates.isEmpty()) { return false; From 65a3e3618a0a8697687413a4e67c511ac0493794 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Feb 2015 17:06:46 -0800 Subject: [PATCH 180/341] Trying to setup correctly the projection matrix for all the different cases... --- libraries/gpu/src/gpu/Config.slh | 20 +------------------ .../directional_ambient_light_shadow_map.slf | 2 -- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/libraries/gpu/src/gpu/Config.slh b/libraries/gpu/src/gpu/Config.slh index 89be6a4f54..b17bd7b2b8 100644 --- a/libraries/gpu/src/gpu/Config.slh +++ b/libraries/gpu/src/gpu/Config.slh @@ -12,25 +12,7 @@ <@def GPU_CONFIG_SLH@> <@if GLPROFILE == PC_GL @> - <@def VERSION_HEADER #version 410 compatibility -#@> - -<@func inputPosition name@> -layout(location = 0) in vec3 <$name$>; -<@endfunc@> - -<@func inputNormal name@> -layout(location = 1) in vec3 <$name$>; -<@endfunc@> - -<@func inputTexcoord name@> -layout(location = 4) in vec2 <$name$>; -<@endfunc@> - -<@func inputColor name@> -layout(location = 4) vec3 <$name$>; -<@endfunc@> - + <@def VERSION_HEADER #version 330 compatibility@> <@elif GLPROFILE == MAC_GL @> <@def VERSION_HEADER #version 120@> <@else@> diff --git a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf index 3407cb03e3..7f098eac2e 100755 --- a/libraries/render-utils/src/directional_ambient_light_shadow_map.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow_map.slf @@ -46,6 +46,4 @@ void main(void) { gl_FragColor = vec4(color, frag.normalVal.a); } - - gl_FragColor = vec4(vec3(shadowAttenuation), 1.0); } From 6be8f4c0ec8dcffe07e99f22ecec501e1f07d7a0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 23 Feb 2015 17:32:31 -0800 Subject: [PATCH 181/341] more work on improving shutdown behavior --- interface/src/Application.cpp | 11 ++- .../src/EntityTreeRenderer.cpp | 2 + libraries/script-engine/src/ScriptEngine.cpp | 81 ++++++++++++++++--- libraries/script-engine/src/ScriptEngine.h | 4 + 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 25ee53f187..32854a1781 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3538,7 +3538,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); // when the application is about to quit, stop our script engine so it unwinds properly - connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); + //connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); auto nodeList = DependencyManager::get(); connect(nodeList.data(), &NodeList::nodeKilled, scriptEngine, &ScriptEngine::nodeKilled); @@ -3550,7 +3550,14 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri } ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded, - bool loadScriptFromEditor, bool activateMainWindow) { + bool loadScriptFromEditor, bool activateMainWindow) { + + qDebug() << "Application::loadScript() " << scriptFilename << "line:" << __LINE__; + if (isAboutToQuit()) { + qDebug() << "Application::loadScript() WHILE QUITTING.... what to do????" << scriptFilename << "line:" << __LINE__; + return NULL; + } + QUrl scriptUrl(scriptFilename); const QString& scriptURLString = scriptUrl.toString(); if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index fdaaa6422b..9deafe17da 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -59,6 +59,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf } EntityTreeRenderer::~EntityTreeRenderer() { + qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- BEGIN -----------"; // NOTE: we don't need to delete _entitiesScriptEngine because it's owned by the application and gets cleaned up // automatically but we do need to delete our sandbox script engine. @@ -71,6 +72,7 @@ EntityTreeRenderer::~EntityTreeRenderer() { delete _sandboxScriptEngine; _sandboxScriptEngine = NULL; } + qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- DONE -----------"; } void EntityTreeRenderer::clear() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0919dc5d59..fe568ab077 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,33 +94,78 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { + qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------"; + _allScriptsMutex.lock(); _allKnownScriptEngines.insert(this); + _allScriptsMutex.unlock(); + qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << " -------- DONE -----------"; } ScriptEngine::~ScriptEngine() { - _allKnownScriptEngines.remove(this); + qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------"; + if (!_stoppingAllScripts) { + _allScriptsMutex.lock(); + qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " removing from list of scripts"; + _allKnownScriptEngines.remove(this); + _allScriptsMutex.unlock(); + } else { + qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " NOT removing from list of scripts here..."; + } + qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " -------- DONE -----------"; } QSet ScriptEngine::_allKnownScriptEngines; +QMutex ScriptEngine::_allScriptsMutex; +bool ScriptEngine::_stoppingAllScripts = false; void ScriptEngine::stopAllScripts(QObject* application) { + + qDebug() << "ScriptEngine::stopAllScripts() -------- BEGIN -----------"; + _allScriptsMutex.lock(); + _stoppingAllScripts = true; + QMutableSetIterator i(_allKnownScriptEngines); while (i.hasNext()) { ScriptEngine* scriptEngine = i.next(); + qDebug() << "ScriptEngine::stopAllScripts() scriptEngine: " << (void*)scriptEngine; + + QString scriptName = scriptEngine->getFilename(); + + qDebug() << "ScriptEngine::stopAllScripts() considering script: " << scriptName << "evaluatePending:" << scriptEngine->evaluatePending(); + // NOTE: typically all script engines are running. But there's at least one known exception to this, the // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using // them. We don't need to stop scripts that aren't running. if (scriptEngine->isRunning()) { + if (scriptEngine->evaluatePending()) { + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "waiting for evaluation to complete...."; + QEventLoop loop; + QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); + loop.exec(); + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "evaluation complete...."; + } + + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; + QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - - scriptEngine->disconnect(application); - scriptEngine->stop(); + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; + scriptEngine->disconnect(application); + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; + scriptEngine->stop(); + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; loop.exec(); + qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; + i.remove(); + } else { + qDebug() << "ScriptEngine::stopAllScripts() script: " << scriptName << " was not running... skipping it's stop() call."; } } + _stoppingAllScripts = false; + _allScriptsMutex.unlock(); + qDebug() << "ScriptEngine::stopAllScripts() -------- DONE -----------"; } QString ScriptEngine::getFilename() const { @@ -347,6 +392,8 @@ void ScriptEngine::evaluate() { } QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { + qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__; + _evaluatePending = true; QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber); if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); @@ -354,6 +401,8 @@ QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileN } emit evaluationFinished(result, hasUncaughtException()); clearExceptions(); + _evaluatePending = false; + qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__; return result; } @@ -370,30 +419,36 @@ void ScriptEngine::sendAvatarBillboardPacket() { } void ScriptEngine::run() { + qDebug() << "ScriptEngine::run() " << getFilename() << " -------- BEGIN -----------"; + if (!_isInitialized) { + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; init(); + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; } + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; _isRunning = true; _isFinished = false; + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; emit runningStateChanged(); + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; QScriptValue result = evaluate(_scriptContents); - if (hasUncaughtException()) { - int line = uncaughtExceptionLineNumber(); - qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString(); - emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + result.toString()); - clearExceptions(); - } + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; QElapsedTimer startTime; startTime.start(); int thisFrame = 0; + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; auto nodeList = DependencyManager::get(); qint64 lastUpdate = usecTimestampNow(); + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; while (!_isFinished) { int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { @@ -535,6 +590,7 @@ void ScriptEngine::run() { } lastUpdate = now; } + qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; stopAllTimers(); // make sure all our timers are stopped if the script is ending @@ -565,6 +621,7 @@ void ScriptEngine::run() { emit runningStateChanged(); emit doneRunning(); + qDebug() << "ScriptEngine::run() " << getFilename() << " -------- DONE -----------" << " line:" << __LINE__; } // NOTE: This is private because it must be called on the same thread that created the timers, which is why @@ -579,6 +636,7 @@ void ScriptEngine::stopAllTimers() { } void ScriptEngine::stop() { + qDebug() << "ScriptEngine::stop() " << getFilename() << "[" << ((void*)this) << "]"; _isFinished = true; emit runningStateChanged(); } @@ -710,8 +768,11 @@ void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { } void ScriptEngine::load(const QString& loadFile) { + qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; QUrl url = resolvePath(loadFile); + qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; emit loadScript(url.toString(), false); + qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; } void ScriptEngine::nodeKilled(SharedNodePointer node) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 8963a1e0f6..a672646c79 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -85,6 +85,7 @@ public: bool isFinished() const { return _isFinished; } bool isRunning() const { return _isRunning; } + bool evaluatePending() const { return _evaluatePending; } void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } @@ -131,6 +132,7 @@ protected: QString _parentURL; bool _isFinished; bool _isRunning; + bool _evaluatePending = false; bool _isInitialized; bool _isAvatar; QTimer* _avatarIdentityTimer; @@ -167,6 +169,8 @@ private slots: private: static QSet _allKnownScriptEngines; + static QMutex _allScriptsMutex; + static bool _stoppingAllScripts; }; #endif // hifi_ScriptEngine_h From ab590440be3f3fa70e99a762579b2d43cc6da19e Mon Sep 17 00:00:00 2001 From: Seefo Date: Mon, 23 Feb 2015 22:15:24 -0500 Subject: [PATCH 182/341] Cleaned up warnings on Windows --- libraries/metavoxels/src/Spanner.cpp | 12 ++++++------ tests/jitter/src/main.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index fbd0d311f5..fd5a59fdfb 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1959,7 +1959,7 @@ HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const } else { colorWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; colorHeight = innerHeightHeight + HeightfieldData::SHARED_EDGE; - newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF); + newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); } int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; @@ -2185,7 +2185,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons } else { colorWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; colorHeight = innerHeightHeight + HeightfieldData::SHARED_EDGE; - newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF); + newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); } int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; @@ -2428,7 +2428,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons } } } - bool nextAlphaY = stackDest->getEntryAlpha(y + 1, voxelHeight); + int nextAlphaY = stackDest->getEntryAlpha(y + 1, voxelHeight); if (nextAlphaY == currentAlpha) { entryDest->hermiteY = 0; @@ -2447,7 +2447,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons } int nextStackZ = (int)stackZ + 1; if (nextStackZ <= innerStackHeight) { - bool nextAlphaZ = newStackContents.at(nextStackZ * stackWidth + (int)stackX).getEntryAlpha( + int nextAlphaZ = newStackContents.at(nextStackZ * stackWidth + (int)stackX).getEntryAlpha( y, nextVoxelHeightZ); if (nextAlphaZ == currentAlpha) { entryDest->hermiteZ = 0; @@ -2828,7 +2828,7 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { _height.reset(); } if (colorWidth > 0 && colorMaterial) { - QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF); + QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); for (int i = 0; i < CHILD_COUNT; i++) { HeightfieldColorPointer childColor = _children[i]->getColor(); if (!childColor) { @@ -3266,7 +3266,7 @@ HeightfieldNode* HeightfieldNode::subdivide(const QVector& heightConten } for (int i = 0; i < CHILD_COUNT; i++) { QVector childHeightContents(heightWidth * heightHeight); - QByteArray childColorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF); + QByteArray childColorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); QByteArray childMaterialContents(materialWidth * materialHeight, 0); QVector childStackContents(stackWidth * stackHeight); diff --git a/tests/jitter/src/main.cpp b/tests/jitter/src/main.cpp index baaa2d08d6..788ae89c6f 100644 --- a/tests/jitter/src/main.cpp +++ b/tests/jitter/src/main.cpp @@ -8,7 +8,7 @@ #include #ifdef _WINDOWS -#include +#include #else #include #include @@ -76,7 +76,7 @@ void runSend(const char* addressOption, int port, int gap, int size, int report) memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = inet_addr(addressOption); + inet_pton(AF_INET, addressOption, &servaddr.sin_addr); servaddr.sin_port = htons(port); const int SAMPLES_FOR_SECOND = 1000000 / gap; From f5a7a19bc3f239e04836f98d7c8fc0d24cfe78de Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 10:41:20 -0800 Subject: [PATCH 183/341] coding convention --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4fc0648c4d..b240f0df9e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,7 +688,7 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 27cddb4b24..02234ee4f7 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); From 5f9af610c268eab27c303a229743d48b974a1306 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 10:41:58 -0800 Subject: [PATCH 184/341] coding convention --- libraries/networking/src/LimitedNodeList.cpp | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 4fc0648c4d..b240f0df9e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -688,7 +688,7 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p } -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort) { if (!sharedMem) { sharedMem = new QSharedMemory(key, this); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 27cddb4b24..02234ee4f7 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -176,7 +176,7 @@ public: } void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); From 4641bd0cd99176192ec03e5a7a3facb8a41cdd24 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 10:47:37 -0800 Subject: [PATCH 185/341] Add Window.domainChanged signal for scripting --- interface/src/scripting/WindowScriptingInterface.cpp | 3 +++ interface/src/scripting/WindowScriptingInterface.h | 1 + 2 files changed, 4 insertions(+) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index c4b288347d..fc3eefe260 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -18,6 +18,7 @@ #include #include "Application.h" +#include "DomainHandler.h" #include "MainWindow.h" #include "Menu.h" #include "ui/ModelsBrowser.h" @@ -34,6 +35,8 @@ WindowScriptingInterface::WindowScriptingInterface() : _nonBlockingFormActive(false), _formResult(QDialog::Rejected) { + const DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + connect(&domainHandler, &DomainHandler::hostnameChanged, this, &WindowScriptingInterface::domainChanged); } WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 66d0ab9306..5c0aa4f0a8 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -57,6 +57,7 @@ public slots: QScriptValue peekNonBlockingFormResult(QScriptValue array); signals: + void domainChanged(const QString& domainHostname); void inlineButtonClicked(const QString& name); void nonBlockingFormClosed(); From c9818c184a41fb9835e28d58d141c85c8e03b0d5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 10:47:55 -0800 Subject: [PATCH 186/341] Update editEntities to turn off when switching domains --- examples/editEntities.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/editEntities.js b/examples/editEntities.js index 61100b4556..9b13b167e7 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -396,6 +396,10 @@ var toolBar = (function () { return handled; } + Window.domainChanged.connect(function() { + that.setActive(false); + }); + that.cleanup = function () { toolBar.cleanup(); }; From d74856e01b50737a44d900299974187b901ab925 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:21:04 -0800 Subject: [PATCH 187/341] add angularVelocity to controller --- interface/src/devices/SixenseManager.cpp | 12 ++++++++++++ .../scripting/ControllerScriptingInterface.cpp | 15 +++++++++++++++ .../src/scripting/ControllerScriptingInterface.h | 1 + libraries/avatars/src/HandData.cpp | 2 +- libraries/avatars/src/HandData.h | 4 +++- 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index ffaa5260db..609ac7b349 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -260,6 +260,18 @@ void SixenseManager::update(float deltaTime) { float sign = (i == 0) ? -1.0f : 1.0f; rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); + // Angular Velocity of Palm + glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation()); + glm::vec3 angularVelocity(0.0f); + float rotationAngle = glm::angle(deltaRotation); + if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) { + angularVelocity = glm::normalize(glm::axis(deltaRotation)); + angularVelocity *= (rotationAngle / deltaTime); + palm->setRawAngularVelocity(angularVelocity); + } else { + palm->setRawAngularVelocity(glm::vec3(0.0f)); + } + if (_lowVelocityFilter) { // Use a velocity sensitive filter to damp small motions and preserve large ones with // no latency. diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 929a763e70..2188f45374 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -208,6 +208,21 @@ glm::quat ControllerScriptingInterface::getSpatialControlRawRotation(int control } return glm::quat(); // bad index } + +glm::vec3 ControllerScriptingInterface::getSpatialControlRawAngularVelocity(int controlIndex) const { + int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; + int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; + const PalmData* palmData = getActivePalm(palmIndex); + if (palmData) { + switch (controlOfPalm) { + case PALM_SPATIALCONTROL: + return palmData->getRawAngularVelocity(); + case TIP_SPATIALCONTROL: + return palmData->getRawAngularVelocity(); // Tip = palm angular velocity + } + } + return glm::vec3(0); // bad index +} glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index d56d159c06..c088dd6c9a 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -96,6 +96,7 @@ public slots: virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; + virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const; virtual void captureKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 5d850d06d0..9a9b51c1c8 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -67,7 +67,7 @@ PalmData::PalmData(HandData* owningHandData) : _rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawPosition(0.0f), _rawVelocity(0.0f), -_rotationalVelocity(0.0f), +_rawAngularVelocity(0.0f), _totalPenetration(0.0f), _controllerButtons(0), _isActive(false), diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 534ea67726..a5e2b2907e 100644 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -98,6 +98,8 @@ public: void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; } + void setRawAngularVelocity(const glm::vec3& angularVelocity) { _rawAngularVelocity = angularVelocity; } + const glm::vec3& getRawAngularVelocity() const { return _rawAngularVelocity; } void addToPosition(const glm::vec3& delta); void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; } @@ -148,7 +150,7 @@ private: glm::quat _rawRotation; glm::vec3 _rawPosition; glm::vec3 _rawVelocity; - glm::vec3 _rotationalVelocity; + glm::vec3 _rawAngularVelocity; glm::quat _lastRotation; glm::vec3 _tipPosition; From 7489b468f3a4f473ed6825ac5c81d12242330c01 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:48:35 -0800 Subject: [PATCH 188/341] give angular velocity to the thrown ball --- examples/controllers/hydra/toyball.js | 72 +++++++++++++++++++-------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/examples/controllers/hydra/toyball.js b/examples/controllers/hydra/toyball.js index b2ce6c1463..06e7f5a2e7 100644 --- a/examples/controllers/hydra/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -29,15 +29,21 @@ var RIGHT_BUTTON_FWD = 11; var RIGHT_BUTTON_3 = 9; var BALL_RADIUS = 0.08; -var GRAVITY_STRENGTH = 1.0; +var GRAVITY_STRENGTH = 3.0; var HELD_COLOR = { red: 240, green: 0, blue: 0 }; var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; +var averageLinearVelocity = [ { x: 0, y: 0, z : 0 }, { x: 0, y: 0, z : 0 } ]; + +var LIFETIME_SECONDS = 600; + +var BALL_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ryan/baseball4.fbx"; + var leftBallAlreadyInHand = false; var rightBallAlreadyInHand = false; -var leftHandEntity; -var rightHandEntity; +var leftHandEntity = false; +var rightHandEntity = false; var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw"); var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw"); @@ -67,31 +73,55 @@ function checkControllerSide(whichSide) { var BUTTON_3; var TRIGGER; var palmPosition; + var palmRotation; var ballAlreadyInHand; var handMessage; + var linearVelocity; + var angularVelocity; + var AVERAGE_FACTOR = 0.33; if (whichSide == LEFT_PALM) { BUTTON_FWD = LEFT_BUTTON_FWD; BUTTON_3 = LEFT_BUTTON_3; TRIGGER = 0; palmPosition = Controller.getSpatialControlPosition(LEFT_PALM); + palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(LEFT_PALM)); ballAlreadyInHand = leftBallAlreadyInHand; handMessage = "LEFT"; + averageLinearVelocity[0] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(LEFT_TIP)), + Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[0])); + linearVelocity = averageLinearVelocity[0]; + angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(LEFT_TIP)); + angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); } else { BUTTON_FWD = RIGHT_BUTTON_FWD; BUTTON_3 = RIGHT_BUTTON_3; TRIGGER = 1; palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM); + palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(RIGHT_PALM)); ballAlreadyInHand = rightBallAlreadyInHand; + averageLinearVelocity[1] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(RIGHT_TIP)), + Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[1])); + linearVelocity = averageLinearVelocity[1]; + angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(RIGHT_TIP)); + angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity); handMessage = "RIGHT"; } var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5)); // If I don't currently have a ball in my hand, then try to catch closest one + if (leftHandEntity && !leftHandEntity.isKnownID) { + leftHandEntity = Entities.identifyEntity(leftHandEntity); + } + if (rightHandEntity && !rightHandEntity.isKnownID) { + rightHandEntity = Entities.identifyEntity(rightHandEntity); + } + if (!ballAlreadyInHand && grabButtonPressed) { var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); + //if (closestEntity.isKnownID && ((leftHandEntity && (closestEntity.id == leftHandEntity.id)) || (rightHandEntity && (closestEntity.id == rightHandEntity.id)))) { if (closestEntity.isKnownID) { debugPrint(handMessage + " HAND- CAUGHT SOMETHING!!"); @@ -107,13 +137,14 @@ function checkControllerSide(whichSide) { var properties = { position: { x: ballPosition.x, y: ballPosition.y, z: ballPosition.z }, - color: HELD_COLOR, + rotation: palmRotation, + color: HELD_COLOR, velocity : { x: 0, y: 0, z: 0}, - lifetime : 600, - inHand: true }; + gravity: { x: 0, y: 0, z: 0} + }; Entities.editEntity(closestEntity, properties); - Audio.playSound(catchSound, { position: ballPosition }); + Audio.playSound(catchSound, { position: ballPosition }); return; // exit early } @@ -129,18 +160,20 @@ function checkControllerSide(whichSide) { if (grabButtonPressed && !ballAlreadyInHand) { var ballPosition = getBallHoldPosition(whichSide); var properties = { - type: "Sphere", + type: "Model", + modelURL: BALL_MODEL_URL, position: { x: ballPosition.x, y: ballPosition.y, - z: ballPosition.z }, + z: ballPosition.z }, + rotation: palmRotation, velocity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0}, - inHand: true, dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, damping: 0.00001, + shapeType: "sphere", + collisionsWillMove: false, color: HELD_COLOR, - - lifetime: 600 // 10 seconds - same as default, not needed but here as an example + lifetime: LIFETIME_SECONDS }; newEntity = Entities.addEntity(properties); @@ -174,21 +207,20 @@ function checkControllerSide(whichSide) { var properties = { position: { x: ballPosition.x, y: ballPosition.y, z: ballPosition.z }, + rotation: palmRotation, + velocity: { x: 0, y: 0, z: 0}, + gravity: { x: 0, y: 0, z: 0}, }; Entities.editEntity(handEntity, properties); } else { debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!"); // If toy ball just released, add velocity to it! - var tipVelocity = Controller.getSpatialControlVelocity(whichTip); - var THROWN_VELOCITY_SCALING = 1.5; var properties = { - velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING, - y: tipVelocity.y * THROWN_VELOCITY_SCALING, - z: tipVelocity.z * THROWN_VELOCITY_SCALING } , + velocity: linearVelocity, + rotation: palmRotation, + angularVelocity: angularVelocity, collisionsWillMove: true, - inHand: false, color: THROWN_COLOR, - lifetime: 10, gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, }; @@ -216,7 +248,7 @@ function checkController(deltaTime) { // this is expected for hydras if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) { - debugPrint("no hydra connected?"); + debugPrint("total buttons = " + numberOfButtons + ", Triggers = " + numberOfTriggers + ", controllers/trigger = " + controllersPerTrigger); return; // bail if no hydra } From 9d021a1a1ee166e65c71ec003791cbb1fca5b5b3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:49:12 -0800 Subject: [PATCH 189/341] remove unused line --- examples/controllers/hydra/toyball.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/controllers/hydra/toyball.js b/examples/controllers/hydra/toyball.js index 06e7f5a2e7..5306769e95 100644 --- a/examples/controllers/hydra/toyball.js +++ b/examples/controllers/hydra/toyball.js @@ -121,7 +121,6 @@ function checkControllerSide(whichSide) { if (!ballAlreadyInHand && grabButtonPressed) { var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); - //if (closestEntity.isKnownID && ((leftHandEntity && (closestEntity.id == leftHandEntity.id)) || (rightHandEntity && (closestEntity.id == rightHandEntity.id)))) { if (closestEntity.isKnownID) { debugPrint(handMessage + " HAND- CAUGHT SOMETHING!!"); From 573390b42960b394adb75cd16b6d48930288354c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 24 Feb 2015 11:55:41 -0800 Subject: [PATCH 190/341] fix dice for collision shapes, add angular velocity --- examples/dice.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/dice.js b/examples/dice.js index d33da576c1..1205f38ee1 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -53,8 +53,10 @@ function shootDice(position, velocity) { position: position, velocity: velocity, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), + angularVelocity: { x: Math.random() * 100, y: Math.random() * 100, z: Math.random() * 100 }, lifetime: LIFETIME, gravity: { x: 0, y: GRAVITY, z: 0 }, + shapeType: "box", collisionsWillMove: true })); position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); From 09ffcbb2e88f35a48ba7e46138cabbe4fa08e2c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Feb 2015 12:30:40 -0800 Subject: [PATCH 191/341] Revert "Merge pull request #4324 from sethalves/assignment-client-keep-a-spare" This reverts commit 087e2babde1329c242484e0e7f4ffbfa3e3206ea, reversing changes made to 5202d2136a0adfb2cf2558847b85a1f7ec94457d. --- assignment-client/src/AssignmentClient.cpp | 87 +++------- assignment-client/src/AssignmentClient.h | 11 +- assignment-client/src/AssignmentClientApp.cpp | 66 -------- assignment-client/src/AssignmentClientApp.h | 18 -- .../src/AssignmentClientChildData.cpp | 8 - .../src/AssignmentClientChildData.h | 32 ---- .../src/AssignmentClientMonitor.cpp | 158 ++++-------------- .../src/AssignmentClientMonitor.h | 13 +- assignment-client/src/main.cpp | 30 +++- domain-server/src/DomainServer.cpp | 14 +- libraries/networking/src/AddressManager.cpp | 4 +- libraries/networking/src/LimitedNodeList.cpp | 38 ----- libraries/networking/src/LimitedNodeList.h | 9 - libraries/networking/src/Node.cpp | 7 +- libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 - libraries/networking/src/PacketHeaders.cpp | 3 - libraries/networking/src/PacketHeaders.h | 4 +- 18 files changed, 108 insertions(+), 403 deletions(-) delete mode 100644 assignment-client/src/AssignmentClientApp.cpp delete mode 100644 assignment-client/src/AssignmentClientApp.h delete mode 100644 assignment-client/src/AssignmentClientChildData.cpp delete mode 100644 assignment-client/src/AssignmentClientChildData.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 2dfc3787de..bf67d4d597 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,10 +18,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -43,8 +43,7 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL), - _localACMPortSharedMem(NULL) + _localASPortSharedMem(NULL) { LogUtils::init(); @@ -57,11 +56,7 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - - // make up a uuid for this child so the parent can tell us apart. This id will be changed - // when the domain server hands over an assignment. - QUuid nodeUUID = QUuid::createUuid(); - nodeList->setSessionUUID(nodeUUID); + auto avatarHashMap = DependencyManager::set(); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -128,8 +123,9 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + QTimer* timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -140,45 +136,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); - - // Hook up a timer to send this child's status to the Monitor once per second - setUpStatsToMonitor(); -} - - -void AssignmentClient::stopAssignmentClient() { - qDebug() << "Exiting."; - _requestTimer.stop(); - _statsTimerACM.stop(); - quit(); -} - - -void AssignmentClient::setUpStatsToMonitor() { - // Figure out the address to send out stats to - quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; - auto nodeList = DependencyManager::get(); - - nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, - _localACMPortSharedMem, localMonitorServerPort); - _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); - - // send a stats packet every 1 seconds - connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); - _statsTimerACM.start(1000); -} - -void AssignmentClient::sendStatsPacketToACM() { - // tell the assignment client monitor what this assignment client is doing (if anything) - QJsonObject statsObject; - auto nodeList = DependencyManager::get(); - - if (_currentAssignment) { - statsObject["assignment_type"] = _currentAssignment->getTypeName(); - } else { - statsObject["assignment_type"] = "none"; - } - nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -188,9 +145,23 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - quint16 localAssignmentServerPort; - if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, - localAssignmentServerPort)) { + if (!_localASPortSharedMem) { + _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + + if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY + << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } + } + + if (_localASPortSharedMem->isAttached()) { + _localASPortSharedMem->lock(); + + quint16 localAssignmentServerPort; + memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); + + _localASPortSharedMem->unlock(); + if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; @@ -199,9 +170,7 @@ void AssignmentClient::sendAssignmentRequest() { nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - else { - qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } + } nodeList->sendAssignment(_requestAssignment); @@ -258,14 +227,6 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } - } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { - if (senderSockAddr.getAddress() == QHostAddress::LocalHost || - senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - qDebug() << "Network told me to exit."; - emit stopAssignmentClient(); - } else { - qDebug() << "Got a stop packet from other than localhost."; - } } else { // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index e105309e10..053458f136 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -29,22 +29,13 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); - void sendStatsPacketToACM(); - void stopAssignmentClient(); private: - void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; // memory shared with domain server - QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor - QTimer _requestTimer; // timer for requesting and assignment - QTimer _statsTimerACM; // timer for sending stats to assignment client monitor - - protected: - HifiSockAddr _assignmentClientMonitorSocket; + QSharedMemory* _localASPortSharedMem; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp deleted file mode 100644 index 477f1a2cf8..0000000000 --- a/assignment-client/src/AssignmentClientApp.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// AssignmentClientapp.cpp -// assignment-client/src -// -// Created by Seth Alves on 2/19/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include - -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" -#include "AssignmentClientApp.h" - - -AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : - QCoreApplication(argc, argv) -{ -# ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -# endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - // parse command-line - QCommandLineParser parser; - parser.setApplicationDescription("High Fidelity Assignment Client"); - parser.addHelpOption(); - - const QCommandLineOption helpOption = parser.addHelpOption(); - - const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); - parser.addOption(numChildsOption); - - if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; - parser.showHelp(); - Q_UNREACHABLE(); - } - - if (parser.isSet(helpOption)) { - parser.showHelp(); - Q_UNREACHABLE(); - } - - unsigned int numForks = 0; - if (parser.isSet(numChildsOption)) { - numForks = parser.value(numChildsOption).toInt(); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - monitor.exec(); - } else { - AssignmentClient client(argc, argv); - client.exec(); - } -} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h deleted file mode 100644 index c5099ff25c..0000000000 --- a/assignment-client/src/AssignmentClientApp.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// AssignmentClientapp.h -// assignment-client/src -// -// Created by Seth Alves on 2/19/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -class AssignmentClientApp : public QCoreApplication { - Q_OBJECT -public: - AssignmentClientApp(int argc, char* argv[]); -}; diff --git a/assignment-client/src/AssignmentClientChildData.cpp b/assignment-client/src/AssignmentClientChildData.cpp deleted file mode 100644 index de34613ec9..0000000000 --- a/assignment-client/src/AssignmentClientChildData.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#include "AssignmentClientChildData.h" - - -AssignmentClientChildData::AssignmentClientChildData(QString childType) : - _childType(childType) -{ -} diff --git a/assignment-client/src/AssignmentClientChildData.h b/assignment-client/src/AssignmentClientChildData.h deleted file mode 100644 index 6fd5f72f7f..0000000000 --- a/assignment-client/src/AssignmentClientChildData.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// AssignmentClientChildData.h -// assignment-client/src -// -// Created by Seth Alves on 2/23/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AssignmentClientChildData_h -#define hifi_AssignmentClientChildData_h - -#include - - -class AssignmentClientChildData : public NodeData { - public: - AssignmentClientChildData(QString childType); - - QString getChildType() { return _childType; } - void setChildType(QString childType) { _childType = childType; } - - // implement parseData to return 0 so we can be a subclass of NodeData - int parseData(const QByteArray& packet) { return 0; } - - private: - QString _childType; -}; - -#endif // hifi_AssignmentClientChildData_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 803c7fd5c7..45e1f56d53 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -13,18 +13,14 @@ #include #include -#include #include "AssignmentClientMonitor.h" -#include "AssignmentClientChildData.h" -#include "PacketHeaders.h" -#include "SharedUtil.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -45,25 +41,11 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); - - - // create a NodeList so we can receive stats from children - DependencyManager::registerInheritance(); - auto addressManager = DependencyManager::set(); - auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, - DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); - - connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); - - nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (unsigned int i = 0; i < numAssignmentClientForks; i++) { + for (int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } - - connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); - _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } AssignmentClientMonitor::~AssignmentClientMonitor() { @@ -71,122 +53,46 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { } void AssignmentClientMonitor::stopChildProcesses() { - auto nodeList = DependencyManager::get(); - - nodeList->eachNode([&](const SharedNodePointer& node) { - qDebug() << "asking child" << node->getUUID() << "to exit."; - node->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); - }); + + QList >::Iterator it = _childProcesses.begin(); + while (it != _childProcesses.end()) { + if (!it->isNull()) { + qDebug() << "Monitor is terminating child process" << it->data(); + + // don't re-spawn this child when it goes down + disconnect(it->data(), 0, this, 0); + + it->data()->terminate(); + it->data()->waitForFinished(); + } + + it = _childProcesses.erase(it); + } } void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); + _childProcesses.append(QPointer(assignmentClient)); + // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(applicationFilePath(), _childArguments); - + + // link the child processes' finished slot to our childProcessFinished slot + connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, + SLOT(childProcessFinished(int, QProcess::ExitStatus))); + qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } - - -void AssignmentClientMonitor::checkSpares() { - auto nodeList = DependencyManager::get(); - QUuid aSpareId = ""; - unsigned int spareCount = 0; - - nodeList->removeSilentNodes(); - - nodeList->eachNode([&](const SharedNodePointer& node) { - AssignmentClientChildData *childData = static_cast(node->getLinkedData()); - if (childData->getChildType() == "none") { - spareCount ++; - aSpareId = node->getUUID(); - } - }); - - if (spareCount != 1) { - qDebug() << "spare count is" << spareCount; - } - - if (spareCount < 1) { - spawnChildClient(); - } - - if (spareCount > 1) { - // kill aSpareId - qDebug() << "asking child" << aSpareId << "to exit."; - SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); - childNode->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, childNode); - } +void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { + qDebug("Replacing dead child assignment client with a new one"); + + // remove the old process from our list of child processes + qDebug() << "need to remove" << QPointer(qobject_cast(sender())); + _childProcesses.removeOne(QPointer(qobject_cast(sender()))); + + spawnChildClient(); } - - -void AssignmentClientMonitor::readPendingDatagrams() { - auto nodeList = DependencyManager::get(); - - QByteArray receivedPacket; - HifiSockAddr senderSockAddr; - - while (nodeList->getNodeSocket().hasPendingDatagrams()) { - receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); - nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), - senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); - - if (nodeList->packetVersionAndHashMatch(receivedPacket)) { - if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { - QUuid packetUUID = uuidFromPacketHeader(receivedPacket); - SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); - if (!matchingNode) { - // The parent only expects to be talking with prorams running on this same machine. - if (senderSockAddr.getAddress() == QHostAddress::LocalHost || - senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { - if (!packetUUID.isNull()) { - matchingNode = DependencyManager::get()->addOrUpdateNode - (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); - AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); - matchingNode->setLinkedData(childData); - } else { - // tell unknown assignment-client child to exit. - qDebug() << "asking unknown child to exit."; - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); - } - } - } - - if (matchingNode) { - // update our records about how to reach this child - matchingNode->setLocalSocket(senderSockAddr); - - // push past the packet header - QDataStream packetStream(receivedPacket); - packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - // decode json - QVariantMap unpackedVariantMap; - packetStream >> unpackedVariantMap; - QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); - - // get child's assignment type out of the decoded json - QString childType = unpackedStatsJSON["assignment_type"].toString(); - AssignmentClientChildData *childData = - static_cast(matchingNode->getLinkedData()); - childData->setChildType(childType); - // note when this child talked - matchingNode->setLastHeardMicrostamp(usecTimestampNow()); - } - } else { - // have the NodeList attempt to handle it - nodeList->processNodeData(senderSockAddr, receivedPacket); - } - } - } -} - - diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 71ae34bc8c..9a7bca9cb3 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -15,30 +15,25 @@ #include #include #include -#include #include -#include "AssignmentClientChildData.h" - extern const char* NUM_FORKS_PARAMETER; - class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: - void readPendingDatagrams(); - void checkSpares(); - + void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); private: void spawnChildClient(); + QList > _childProcesses; + QStringList _childArguments; - QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 81a12526bf..3bf6990a74 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,10 +9,34 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include -#include "AssignmentClientApp.h" +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" int main(int argc, char* argv[]) { - AssignmentClientApp app(argc, argv); - return 0; +#ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +#endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); + + int numForks = 0; + + if (numForksString) { + numForks = atoi(numForksString); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + return monitor.exec(); + } else { + AssignmentClient client(argc, argv); + return client.exec(); + } } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 64e0d335b1..f84722a438 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -246,7 +246,19 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + quint16 localPort = nodeList->getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f67abdca2b..9bcdcbe9a4 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { pathString += "/" + orientationString; } else { qDebug() << "Cannot add orientation to path without a getter for position." - << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat"; + << "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; } } @@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { return pathString; } else { qDebug() << "Cannot create address path without a getter for position." - << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; + << "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; return QString(); } } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b240f0df9e..c8c454ff14 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,41 +669,3 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } - -void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { - // save our local port to shared memory so that assignment client children know how to talk to this parent - QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); - quint16 localPort = getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } -} - - -bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, - quint16& localPort) { - if (!sharedMem) { - sharedMem = new QSharedMemory(key, this); - - if (!sharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << key; - } - } - - if (sharedMem->isAttached()) { - sharedMem->lock(); - memcpy(&localPort, sharedMem->data(), sizeof(localPort)); - sharedMem->unlock(); - return true; - } - - return false; -} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 02234ee4f7..72aefdb2b3 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -26,7 +26,6 @@ #include #include #include -#include #include @@ -50,11 +49,6 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; -const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; - -const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; -const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; -const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -174,9 +168,6 @@ public: return SharedNodePointer(); } - - void putLocalPortIntoSharedMemory(const QString key, QObject* parent); - bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2a38799707..2bf792c6ee 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -149,12 +149,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { } QDebug operator<<(QDebug debug, const Node &node) { - debug.nospace() << NodeType::getNodeTypeName(node.getType()); - if (node.getType() == NodeType::Unassigned) { - debug.nospace() << " (1)"; - } else { - debug.nospace() << " (" << node.getType() << ")"; - } + debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e63f230f6e..f70c2d9b3c 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,17 +62,13 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, destination); -} - -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { - return sendStats(statsObject, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 1c6de4bb6c..907fccfcac 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,7 +47,6 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } - qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index db97e216ee..2eee540fff 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,8 +70,6 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; - case PacketTypeStopNode: - return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -126,7 +124,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); - PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 32f33c01d9..e593955b51 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - PacketTypeStopNode, + UNUSED_10, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; From d52ba5e95870f07cd6b4e3e23024b222cc0576d4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Feb 2015 13:20:17 -0800 Subject: [PATCH 192/341] call windeployqt after fixup_bundle for qt plugins --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 4a1bc35fb7..4f144c4315 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -18,7 +18,7 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) @ONLY ) - # add a post-build command to copy DLLs beside the interface executable + # add a post-build command to copy DLLs beside the executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD @@ -26,5 +26,15 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) -DBUNDLE_EXECUTABLE=$ -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) + + find_program(${WINDEPLOYQT_COMMAND} windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + + # add a post-build command to call windeployqt to copy Qt plugins + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND SET PATH=%PATH%;${QT_DIR}/bin + COMMAND ${WINDEPLOYQT_COMMAND} --no-libraries --force $ + ) endif () endmacro() \ No newline at end of file From fd93b99f03fc3e8a8ccb0b19b93377ab8c98122e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 14:02:46 -0800 Subject: [PATCH 193/341] more hacking on script shutdown behavior --- interface/src/Application.cpp | 12 +- .../src/EntityTreeRenderer.cpp | 3 - libraries/script-engine/src/ScriptEngine.cpp | 264 ++++++++++++++---- libraries/script-engine/src/ScriptEngine.h | 9 +- 4 files changed, 231 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 32854a1781..7184021239 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3552,9 +3552,11 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow) { - qDebug() << "Application::loadScript() " << scriptFilename << "line:" << __LINE__; + qDebug() << "Application::loadScript() ---- BEGIN ---- Script:" << scriptFilename; + if (isAboutToQuit()) { - qDebug() << "Application::loadScript() WHILE QUITTING.... what to do????" << scriptFilename << "line:" << __LINE__; + qDebug() << "Requests to load scripts while quitting are ignored. Script:" << scriptFilename; + qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; return NULL; } @@ -3563,6 +3565,8 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { + qDebug() << "Application::loadScript() from _scriptEnginesHash[scriptURLString].... Script:" << scriptFilename; + qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; return _scriptEnginesHash[scriptURLString]; } @@ -3581,6 +3585,7 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); // get the script engine object to load the script at the designated script URL + qDebug() << "Application::loadScript() about to call loadURL() scriptUrl:" << scriptUrl; scriptEngine->loadURL(scriptUrl); } @@ -3589,6 +3594,9 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser _window->activateWindow(); } + qDebug() << "Application::loadScript() newly created scriptEngine.... Script:" << scriptFilename; + qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; + return scriptEngine; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 9deafe17da..8648cea285 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -59,10 +59,8 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf } EntityTreeRenderer::~EntityTreeRenderer() { - qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- BEGIN -----------"; // NOTE: we don't need to delete _entitiesScriptEngine because it's owned by the application and gets cleaned up // automatically but we do need to delete our sandbox script engine. - if (_sandboxScriptEngine) { // NOTE: is it possible this is a problem? I think that we hook the script engine object up to a deleteLater() // call inside of registerScriptEngineWithApplicationServices() but do we not call that for _sandboxScriptEngine??? @@ -72,7 +70,6 @@ EntityTreeRenderer::~EntityTreeRenderer() { delete _sandboxScriptEngine; _sandboxScriptEngine = NULL; } - qDebug() << "EntityTreeRenderer::~EntityTreeRenderer() -------- DONE -----------"; } void EntityTreeRenderer::clear() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fe568ab077..e99cbea0e5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -94,33 +94,32 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { - qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------"; _allScriptsMutex.lock(); _allKnownScriptEngines.insert(this); _allScriptsMutex.unlock(); - qDebug() << "ScriptEngine::ScriptEngine() " << getFilename() << " -------- DONE -----------"; } ScriptEngine::~ScriptEngine() { - qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << "[" << ((void*)this) << "]" << " -------- BEGIN -----------"; + qDebug() << "ScriptEngine::~ScriptEngine() ------- BEGIN ------- script:" << getFilename(); + // If we're not already in the middle of stopping all scripts, then we should remove ourselves + // from the list of running scripts. We don't do this if we're in the process of stopping all scripts + // because that method removes scripts from its list as it iterates them if (!_stoppingAllScripts) { _allScriptsMutex.lock(); - qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " removing from list of scripts"; _allKnownScriptEngines.remove(this); _allScriptsMutex.unlock(); - } else { - qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " NOT removing from list of scripts here..."; } - qDebug() << "ScriptEngine::~ScriptEngine() " << getFilename() << " -------- DONE -----------"; + qDebug() << "ScriptEngine::~ScriptEngine() ------- END ------- script:" << getFilename(); } QSet ScriptEngine::_allKnownScriptEngines; QMutex ScriptEngine::_allScriptsMutex; bool ScriptEngine::_stoppingAllScripts = false; +bool ScriptEngine::_doneRunningThisScript = false; void ScriptEngine::stopAllScripts(QObject* application) { + qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------"; - qDebug() << "ScriptEngine::stopAllScripts() -------- BEGIN -----------"; _allScriptsMutex.lock(); _stoppingAllScripts = true; @@ -128,44 +127,92 @@ void ScriptEngine::stopAllScripts(QObject* application) { while (i.hasNext()) { ScriptEngine* scriptEngine = i.next(); - qDebug() << "ScriptEngine::stopAllScripts() scriptEngine: " << (void*)scriptEngine; - QString scriptName = scriptEngine->getFilename(); - qDebug() << "ScriptEngine::stopAllScripts() considering script: " << scriptName << "evaluatePending:" << scriptEngine->evaluatePending(); + qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName + << "isRunning():" << scriptEngine->isRunning() + << "evaluatePending():" << scriptEngine->evaluatePending(); // NOTE: typically all script engines are running. But there's at least one known exception to this, the // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using // them. We don't need to stop scripts that aren't running. if (scriptEngine->isRunning()) { + + // If the script is running, but still evaluating then we need to wait for its evaluation step to + // complete. After that we can handle the stop process appropriately if (scriptEngine->evaluatePending()) { - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "waiting for evaluation to complete...."; - QEventLoop loop; - QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); - loop.exec(); - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__ << "evaluation complete...."; + while (scriptEngine->evaluatePending()) { + QEventLoop loop; + QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); + qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) STARTING loop.exec() script:" << scriptName; + loop.exec(); + qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) AFTER loop.exec() script:" << scriptName; + } } - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; - - QEventLoop loop; - QObject::connect(scriptEngine, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; scriptEngine->disconnect(application); - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; scriptEngine->stop(); - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; - loop.exec(); - qDebug() << "ScriptEngine::stopAllScripts() handling script: " << scriptName << "line:" << __LINE__; + + qDebug() << "ScriptEngine::stopAllScripts() -- WAITING for waitTillDoneRunning() script:" << scriptName; + scriptEngine->waitTillDoneRunning(); + qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName; i.remove(); } else { - qDebug() << "ScriptEngine::stopAllScripts() script: " << scriptName << " was not running... skipping it's stop() call."; } } _stoppingAllScripts = false; _allScriptsMutex.unlock(); - qDebug() << "ScriptEngine::stopAllScripts() -------- DONE -----------"; + qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------"; +} + + +void ScriptEngine::waitTillDoneRunning() { + QString scriptName = getFilename(); + qDebug() << "ScriptEngine::waitTillDoneRunning() ------- BEGIN ------- script:" << scriptName; + qDebug() << " _isFinished:" << _isFinished; + qDebug() << " _isRunning:" << _isRunning; + qDebug() << " _isInitialized:" << _isInitialized; + qDebug() << " _evaluatesPending:" << _evaluatesPending; + + if (_isRunning) { + qDebug() << "ScriptEngine::waitTillDoneRunning() SETTING _doneRunningThisScript = false ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + _doneRunningThisScript = false; + _isWaitingForDoneRunning = true; + + // What can we do here??? + // we will be calling this on the main Application thread, inside of stopAllScripts() + // we want the application thread to continue to process events, because the script will + // likely need to marshall messages across to the main thread. + while (!_doneRunningThisScript && _isRunning) { + + // and run a QEventLoop??? + QEventLoop loop; + QObject::connect(this, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); + qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING loop.exec() script:" << scriptName; + qDebug() << " _doneRunningThisScript:" << _doneRunningThisScript; + qDebug() << " _isRunning:" << _isRunning; + qDebug() << " _isWaitingForDoneRunning:" << _isWaitingForDoneRunning; + qDebug() << " _isFinished:" << _isFinished; + qDebug() << " _isInitialized:" << _isInitialized; + qDebug() << " _evaluatesPending:" << _evaluatesPending; + loop.exec(); + qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER loop.exec() script:" << scriptName; + + // process events + qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING QCoreApplication::processEvents() script:" << scriptName; + QCoreApplication::processEvents(); + qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER QCoreApplication::processEvents() script:" << scriptName; + + if (_doneRunningThisScript) { + qDebug() << "ScriptEngine::waitTillDoneRunning() _doneRunningThisScript after processEvents... breaking!!! script:" << scriptName; + break; + } + } + + _isWaitingForDoneRunning = false; + } + + qDebug() << "ScriptEngine::waitTillDoneRunning() ------- DONE ------- script:" << scriptName; } QString ScriptEngine::getFilename() const { @@ -377,12 +424,23 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func } void ScriptEngine::evaluate() { + if (_stoppingAllScripts) { + qDebug() << "ScriptEngine::evaluate() while shutting down is ignored..."; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return; // bail early + } + + qDebug() << "ScriptEngine::evaluate() -- BEGIN script:" << getFilename() << "[" << this << "]"; if (!_isInitialized) { init(); } + qDebug() << "ScriptEngine::evaluate() -- about to call own evaluate(program) script:" << getFilename() << "[" << this << "]"; QScriptValue result = evaluate(_scriptContents); + qDebug() << "ScriptEngine::evaluate() -- AFTER own evaluate(program) script:" << getFilename() << "[" << this << "]"; + // TODO: why do we check this twice? It seems like the call to clearExcpetions() in the lower level evaluate call + // will cause this code to never actually run... if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString(); @@ -392,17 +450,30 @@ void ScriptEngine::evaluate() { } QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { - qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__; - _evaluatePending = true; + if (_stoppingAllScripts) { + qDebug() << "ScriptEngine::evaluate(program) while shutting down is ignored..."; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return QScriptValue(); // bail early + } + + qDebug() << "ScriptEngine::evaluate(program) -- BEGIN script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + _evaluatesPending++; + qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending++ script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + qDebug() << "ScriptEngine::evaluate(program) -- BEFORE QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber); + qDebug() << "ScriptEngine::evaluate(program) -- AFTER QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString(); } + _evaluatesPending--; + qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending-- script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + + qDebug() << "ScriptEngine::evaluate(program) -- ABOUT TO emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; emit evaluationFinished(result, hasUncaughtException()); + qDebug() << "ScriptEngine::evaluate(program) -- AFTER emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; clearExceptions(); - _evaluatePending = false; - qDebug() << "ScriptEngine::evaluate() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::evaluate(program) -- DONE script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; return result; } @@ -419,49 +490,60 @@ void ScriptEngine::sendAvatarBillboardPacket() { } void ScriptEngine::run() { - qDebug() << "ScriptEngine::run() " << getFilename() << " -------- BEGIN -----------"; + // TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if + // we're in the process of stopping? + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; if (!_isInitialized) { - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; init(); - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; } - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; _isRunning = true; _isFinished = false; - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; emit runningStateChanged(); - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; QScriptValue result = evaluate(_scriptContents); - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; QElapsedTimer startTime; startTime.start(); int thisFrame = 0; - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; auto nodeList = DependencyManager::get(); qint64 lastUpdate = usecTimestampNow(); - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + while (!_isFinished) { + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { usleep(usecToSleep); } if (_isFinished) { + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; break; } + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + QCoreApplication::processEvents(); + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + if (_isFinished) { + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; break; } @@ -589,16 +671,38 @@ void ScriptEngine::run() { emit update(deltaTime); } lastUpdate = now; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + } - qDebug() << "ScriptEngine::run() " << getFilename() << " line:" << __LINE__; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; stopAllTimers(); // make sure all our timers are stopped if the script is ending + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename(); + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } emit scriptEnding(); + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; // kill the avatar identity timer delete _avatarIdentityTimer; + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); @@ -609,19 +713,44 @@ void ScriptEngine::run() { } } + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + // If we were on a thread, then wait till it's done if (thread()) { + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; thread()->quit(); + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + + qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; } emit finished(_fileNameString); - _isRunning = false; + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + _isRunning = false; emit runningStateChanged(); + qDebug() << "ABOUT TO emit doneRunning() script:" << getFilename() << "[" << this << "]"; emit doneRunning(); - qDebug() << "ScriptEngine::run() " << getFilename() << " -------- DONE -----------" << " line:" << __LINE__; + qDebug() << "AFTER emit doneRunning() script:" << getFilename() << "[" << this << "]"; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } + + qDebug() << "ScriptEngine::run() SETTING _doneRunningThisScript = true ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + _doneRunningThisScript = true; + + if (_isWaitingForDoneRunning) { + qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + } } // NOTE: This is private because it must be called on the same thread that created the timers, which is why @@ -636,9 +765,10 @@ void ScriptEngine::stopAllTimers() { } void ScriptEngine::stop() { - qDebug() << "ScriptEngine::stop() " << getFilename() << "[" << ((void*)this) << "]"; + qDebug() << "ScriptEngine::stop() -- START -- line:" << __LINE__ << " script:" << getFilename(); _isFinished = true; emit runningStateChanged(); + qDebug() << "ScriptEngine::stop() -- DONE -- line:" << __LINE__ << " script:" << getFilename(); } void ScriptEngine::timerFired() { @@ -674,10 +804,22 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int } QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { + if (_stoppingAllScripts) { + qDebug() << "Script.setInterval() while shutting down is ignored..."; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return NULL; // bail early + } + return setupTimerWithInterval(function, intervalMS, false); } QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { + if (_stoppingAllScripts) { + qDebug() << "Script.setTimeout() while shutting down is ignored..."; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return NULL; // bail early + } + return setupTimerWithInterval(function, timeoutMS, true); } @@ -723,6 +865,12 @@ void ScriptEngine::print(const QString& message) { // If no callback is specified, the included files will be loaded synchronously and will block execution until // all of the files have finished loading. void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) { + if (_stoppingAllScripts) { + qDebug() << "Script.include() while shutting down is ignored..."; + qDebug() << " includeFiles:" << includeFiles; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return; // bail early + } QList urls; for (QString file : includeFiles) { urls.append(resolvePath(file)); @@ -736,7 +884,9 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac if (contents.isNull()) { qDebug() << "Error loading file: " << url; } else { + qDebug() << "ScriptEngine::include() BEFORE evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending; QScriptValue result = evaluate(contents, url.toString()); + qDebug() << "ScriptEngine::include() AFTER evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending; } } @@ -762,17 +912,31 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac } void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { + if (_stoppingAllScripts) { + qDebug() << "Script.include() while shutting down is ignored..."; + qDebug() << " includeFile:" << includeFile; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return; // bail early + } + QStringList urls; urls.append(includeFile); include(urls, callback); } +// NOTE: The load() command is similar to the include() command except that it loads the script +// as a stand-alone script. To accomplish this, the ScriptEngine class just emits a signal which +// the Application or other context will connect to in order to know to actually load the script void ScriptEngine::load(const QString& loadFile) { - qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; + if (_stoppingAllScripts) { + qDebug() << "Script.load() while shutting down is ignored..."; + qDebug() << " loadFile:" << loadFile; + qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + return; // bail early + } + QUrl url = resolvePath(loadFile); - qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; emit loadScript(url.toString(), false); - qDebug() << "ScriptEngine::load() " << getFilename() << "[" << ((void*)this) << "]" << "line:" << __LINE__; } void ScriptEngine::nodeKilled(SharedNodePointer node) { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index a672646c79..51cacd5e58 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -85,7 +86,7 @@ public: bool isFinished() const { return _isFinished; } bool isRunning() const { return _isRunning; } - bool evaluatePending() const { return _evaluatePending; } + bool evaluatePending() const { return _evaluatesPending > 0; } void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } @@ -95,6 +96,8 @@ public: QString getFilename() const; static void stopAllScripts(QObject* application); + + void waitTillDoneRunning(); public slots: void loadURL(const QUrl& scriptURL); @@ -132,7 +135,8 @@ protected: QString _parentURL; bool _isFinished; bool _isRunning; - bool _evaluatePending = false; + int _evaluatesPending = 0; + bool _isWaitingForDoneRunning = false; bool _isInitialized; bool _isAvatar; QTimer* _avatarIdentityTimer; @@ -171,6 +175,7 @@ private: static QSet _allKnownScriptEngines; static QMutex _allScriptsMutex; static bool _stoppingAllScripts; + static bool _doneRunningThisScript; }; #endif // hifi_ScriptEngine_h From e91a28a0a4650fa01780001071e20f99df6966ce Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 24 Feb 2015 14:33:55 -0800 Subject: [PATCH 194/341] Rework DDE blendshape derivation and remove scaling and smoothing --- interface/src/devices/DdeFaceTracker.cpp | 121 ++++++++++------------- interface/src/devices/DdeFaceTracker.h | 4 - 2 files changed, 50 insertions(+), 75 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 87a180bd1e..4026b581d7 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -151,37 +151,6 @@ float DdeFaceTracker::getBlendshapeCoefficient(int index) const { return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f; } -static const float DDE_MIN_RANGE = -0.2f; -static const float DDE_MAX_RANGE = 1.5f; -float rescaleCoef(float ddeCoef) { - return (ddeCoef - DDE_MIN_RANGE) / (DDE_MAX_RANGE - DDE_MIN_RANGE); -} - -const int MIN = 0; -const int AVG = 1; -const int MAX = 2; -const float LONG_TERM_AVERAGE = 0.999f; - - -void resetCoefficient(float * coefficient, float currentValue) { - coefficient[MIN] = coefficient[MAX] = coefficient[AVG] = currentValue; -} - -float updateAndGetCoefficient(float * coefficient, float currentValue, bool scaleToRange = false) { - coefficient[MIN] = (currentValue < coefficient[MIN]) ? currentValue : coefficient[MIN]; - coefficient[MAX] = (currentValue > coefficient[MAX]) ? currentValue : coefficient[MAX]; - coefficient[AVG] = LONG_TERM_AVERAGE * coefficient[AVG] + (1.0f - LONG_TERM_AVERAGE) * currentValue; - if (coefficient[MAX] > coefficient[MIN]) { - if (scaleToRange) { - return glm::clamp((currentValue - coefficient[AVG]) / (coefficient[MAX] - coefficient[MIN]), 0.0f, 1.0f); - } else { - return glm::clamp(currentValue - coefficient[AVG], 0.0f, 1.0f); - } - } else { - return 0.0f; - } -} - void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if(buffer.size() > MIN_PACKET_SIZE) { Packet packet; @@ -196,9 +165,6 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { if (_reset || (_lastReceiveTimestamp == 0)) { memcpy(&_referenceTranslation, &translation, sizeof(glm::vec3)); memcpy(&_referenceRotation, &rotation, sizeof(glm::quat)); - - resetCoefficient(_rightEye, packet.expressions[0]); - resetCoefficient(_leftEye, packet.expressions[1]); _reset = false; } @@ -207,51 +173,64 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { translation -= _referenceTranslation; translation /= LEAN_DAMPING_FACTOR; translation.x *= -1; - + _headTranslation = translation; + // Compute relative rotation rotation = glm::inverse(_referenceRotation) * rotation; - - // copy values - _headTranslation = translation; _headRotation = rotation; - - if (_lastReceiveTimestamp == 0) { - // On first packet, reset coefficients - } - - // Set blendshapes - float EYE_MAGNIFIER = 4.0f; - float rightEye = glm::clamp((updateAndGetCoefficient(_rightEye, packet.expressions[0])) * EYE_MAGNIFIER, 0.0f, 1.0f); - _blendshapeCoefficients[_rightBlinkIndex] = rightEye; - float leftEye = glm::clamp((updateAndGetCoefficient(_leftEye, packet.expressions[1])) * EYE_MAGNIFIER, 0.0f, 1.0f); - _blendshapeCoefficients[_leftBlinkIndex] = leftEye; - - float leftBrow = 1.0f - rescaleCoef(packet.expressions[14]); - if (leftBrow < 0.5f) { - _blendshapeCoefficients[_browDownLeftIndex] = 1.0f - 2.0f * leftBrow; - _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; + // The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much + // less than this. + + // Eye blendshapes + static const float RELAXED_EYE_VALUE = 0.1f; + float leftEye = packet.expressions[1] - RELAXED_EYE_VALUE; + float rightEye = packet.expressions[0] - RELAXED_EYE_VALUE; + if (leftEye > 0.0f) { + _blendshapeCoefficients[_leftBlinkIndex] = leftEye; + _blendshapeCoefficients[_leftEyeOpenIndex] = 0.0f; } else { + _blendshapeCoefficients[_leftBlinkIndex] = 0.0f; + _blendshapeCoefficients[_leftEyeOpenIndex] = -leftEye; + } + if (rightEye > 0.0f) { + _blendshapeCoefficients[_rightBlinkIndex] = rightEye; + _blendshapeCoefficients[_rightEyeOpenIndex] = 0.0f; + } else { + _blendshapeCoefficients[_rightBlinkIndex] = 0.0f; + _blendshapeCoefficients[_rightEyeOpenIndex] = -rightEye; + } + + // Eyebrow blendshapes + float browCenter = packet.expressions[17]; + float browDelta = packet.expressions[24] - packet.expressions[23]; + float browLeft = browCenter - browDelta; + float browRight = browCenter + browDelta; + if (browLeft > 0) { + _blendshapeCoefficients[_browUpLeftIndex] = browLeft; _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; - _blendshapeCoefficients[_browUpLeftIndex] = 2.0f * (leftBrow - 0.5f); - } - float rightBrow = 1.0f - rescaleCoef(packet.expressions[15]); - if (rightBrow < 0.5f) { - _blendshapeCoefficients[_browDownRightIndex] = 1.0f - 2.0f * rightBrow; - _blendshapeCoefficients[_browUpRightIndex] = 0.0f; } else { - _blendshapeCoefficients[_browDownRightIndex] = 0.0f; - _blendshapeCoefficients[_browUpRightIndex] = 2.0f * (rightBrow - 0.5f); + _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; + _blendshapeCoefficients[_browDownLeftIndex] = -browLeft; } - - float JAW_OPEN_MAGNIFIER = 1.4f; - _blendshapeCoefficients[_jawOpenIndex] = rescaleCoef(packet.expressions[21]) * JAW_OPEN_MAGNIFIER; - - float SMILE_MULTIPLIER = 2.0f; - _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(packet.expressions[24] * SMILE_MULTIPLIER, 0.0f, 1.0f); - _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(packet.expressions[23] * SMILE_MULTIPLIER, 0.0f, 1.0f); - - + if (browRight > 0) { + _blendshapeCoefficients[_browUpRightIndex] = browRight; + _blendshapeCoefficients[_browDownRightIndex] = 0.0f; + } else { + _blendshapeCoefficients[_browUpRightIndex] = 0.0f; + _blendshapeCoefficients[_browDownRightIndex] = -browRight; + } + if (browLeft + browRight > 0) { + _blendshapeCoefficients[_browUpCenterIndex] = (browLeft + browRight) / 2.0f; + } else { + _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; + } + + // Mouth blendshapes + _blendshapeCoefficients[_jawOpenIndex] = packet.expressions[21]; + _blendshapeCoefficients[_mouthSmileLeftIndex] = packet.expressions[24]; + _blendshapeCoefficients[_mouthSmileRightIndex] = packet.expressions[23]; + } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; } diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index bd5d066732..162e2b145f 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -90,10 +90,6 @@ private: int _mouthSmileRightIndex; int _jawOpenIndex; - - float _leftEye[3]; - float _rightEye[3]; - }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file From 89c10ca2ece60d44f330a4b4d410f8f92a7eafef Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 14:36:24 -0800 Subject: [PATCH 195/341] Fix BillboardOverlay::findRayIntersection --- .../src/ui/overlays/BillboardOverlay.cpp | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 27bd0c9102..4ea0e55710 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -12,6 +12,7 @@ #include "Application.h" #include "BillboardOverlay.h" +#include BillboardOverlay::BillboardOverlay() : _fromImage(), @@ -191,18 +192,51 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float& distance, BoxFace& face) { if (_texture) { + // This is taken from Planar3DOverlay. Although it probably makes more sense for this + // overlay type to extend from Planar3DOverlay, the interfaces are different enough (scale vs. dimensions) + // that it would break existing scripts and would require other changes to make up for unique + // features like `isFacingAvatar`. + + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + bool isNull = _fromImage.isNull(); float width = isNull ? _texture->getWidth() : _fromImage.width(); float height = isNull ? _texture->getHeight() : _fromImage.height(); - float maxSize = glm::max(width, height); - float x = width / (2.0f * maxSize); - float y = -height / (2.0f * maxSize); - float maxDimension = glm::max(x,y); - float scaledDimension = maxDimension * _scale; - glm::vec3 corner = getCenter() - glm::vec3(scaledDimension, scaledDimension, scaledDimension) ; - AACube myCube(corner, scaledDimension * 2.0f); - return myCube.findRayIntersection(origin, direction, distance, face); + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::quat rotation; + if (_isFacingAvatar) { + // rotate about vertical to face the camera + rotation = Application::getInstance()->getCamera()->getRotation(); + rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + } else { + rotation = _rotation; + } + glm::vec3 normal = rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + distance = rayInfo._hitDistance; + + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - _position); + + // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. + float maxSize = glm::max(width, height); + glm::vec2 halfDimensions = 0.5f * _scale * glm::vec2(width / maxSize, height / maxSize); + + intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x + && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; + } + return intersects; } return false; } From e7e7323ff01684262c9ea9fd09913f558dace2e0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 24 Feb 2015 15:00:41 -0800 Subject: [PATCH 196/341] pass 10.9 SDK as CMAKE_OSX_SYSROOT --- CMakeLists.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc67d622de..5deecb4be5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,8 +88,17 @@ endif () set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) -# set our OS X deployment target to -set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) +if (APPLE) + # set our OS X deployment target + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) + + # find the 10.9 SDK path + execute_process(COMMAND xcodebuild -sdk -version OUTPUT_VARIABLE XCODE_SDK_VERSIONS) + string(REGEX MATCH \\/.+MacOSX10.9.sdk OSX_SDK_PATH ${XCODE_SDK_VERSIONS}) + + # set that as the SDK to use + set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH}) +endif () # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) From 8757600a5eeac4199f607992770b118f79b079ee Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 15:57:13 -0800 Subject: [PATCH 197/341] ifdef around massive debug output --- libraries/script-engine/src/ScriptEngine.cpp | 149 ++++++++++--------- 1 file changed, 76 insertions(+), 73 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e99cbea0e5..cbdd59146b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -41,6 +41,13 @@ #include "MIDIEvent.h" + +#ifdef WANT_DEBUG_SCRIPT_ENDING +#define DEBUG_SCRIPT_ENDING(X) X +#else +#define DEBUG_SCRIPT_ENDING(x) +#endif + EntityScriptingInterface ScriptEngine::_entityScriptingInterface; static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ @@ -100,7 +107,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam } ScriptEngine::~ScriptEngine() { - qDebug() << "ScriptEngine::~ScriptEngine() ------- BEGIN ------- script:" << getFilename(); + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::~ScriptEngine() ------- BEGIN ------- script:" << getFilename();) // If we're not already in the middle of stopping all scripts, then we should remove ourselves // from the list of running scripts. We don't do this if we're in the process of stopping all scripts // because that method removes scripts from its list as it iterates them @@ -109,7 +116,7 @@ ScriptEngine::~ScriptEngine() { _allKnownScriptEngines.remove(this); _allScriptsMutex.unlock(); } - qDebug() << "ScriptEngine::~ScriptEngine() ------- END ------- script:" << getFilename(); + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::~ScriptEngine() ------- END ------- script:" << getFilename();) } QSet ScriptEngine::_allKnownScriptEngines; @@ -118,7 +125,7 @@ bool ScriptEngine::_stoppingAllScripts = false; bool ScriptEngine::_doneRunningThisScript = false; void ScriptEngine::stopAllScripts(QObject* application) { - qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------";) _allScriptsMutex.lock(); _stoppingAllScripts = true; @@ -129,9 +136,9 @@ void ScriptEngine::stopAllScripts(QObject* application) { QString scriptName = scriptEngine->getFilename(); - qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName << "isRunning():" << scriptEngine->isRunning() - << "evaluatePending():" << scriptEngine->evaluatePending(); + << "evaluatePending():" << scriptEngine->evaluatePending();) // NOTE: typically all script engines are running. But there's at least one known exception to this, the // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using @@ -144,38 +151,34 @@ void ScriptEngine::stopAllScripts(QObject* application) { while (scriptEngine->evaluatePending()) { QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); - qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) STARTING loop.exec() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) STARTING loop.exec() script:" << scriptName;) loop.exec(); - qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) AFTER loop.exec() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) AFTER loop.exec() script:" << scriptName;) } } scriptEngine->disconnect(application); scriptEngine->stop(); - qDebug() << "ScriptEngine::stopAllScripts() -- WAITING for waitTillDoneRunning() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() -- WAITING for waitTillDoneRunning() script:" << scriptName;) scriptEngine->waitTillDoneRunning(); - qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName;) i.remove(); } else { } } _stoppingAllScripts = false; _allScriptsMutex.unlock(); - qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------";) } void ScriptEngine::waitTillDoneRunning() { QString scriptName = getFilename(); - qDebug() << "ScriptEngine::waitTillDoneRunning() ------- BEGIN ------- script:" << scriptName; - qDebug() << " _isFinished:" << _isFinished; - qDebug() << " _isRunning:" << _isRunning; - qDebug() << " _isInitialized:" << _isInitialized; - qDebug() << " _evaluatesPending:" << _evaluatesPending; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() ------- BEGIN ------- script:" << scriptName;) if (_isRunning) { - qDebug() << "ScriptEngine::waitTillDoneRunning() SETTING _doneRunningThisScript = false ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() SETTING _doneRunningThisScript = false ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _doneRunningThisScript = false; _isWaitingForDoneRunning = true; @@ -188,23 +191,23 @@ void ScriptEngine::waitTillDoneRunning() { // and run a QEventLoop??? QEventLoop loop; QObject::connect(this, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING loop.exec() script:" << scriptName; - qDebug() << " _doneRunningThisScript:" << _doneRunningThisScript; - qDebug() << " _isRunning:" << _isRunning; - qDebug() << " _isWaitingForDoneRunning:" << _isWaitingForDoneRunning; - qDebug() << " _isFinished:" << _isFinished; - qDebug() << " _isInitialized:" << _isInitialized; - qDebug() << " _evaluatesPending:" << _evaluatesPending; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING loop.exec() script:" << scriptName;) + DEBUG_SCRIPT_ENDING(qDebug() << " _doneRunningThisScript:" << _doneRunningThisScript;) + DEBUG_SCRIPT_ENDING(qDebug() << " _isRunning:" << _isRunning;) + DEBUG_SCRIPT_ENDING(qDebug() << " _isWaitingForDoneRunning:" << _isWaitingForDoneRunning;) + DEBUG_SCRIPT_ENDING(qDebug() << " _isFinished:" << _isFinished;) + DEBUG_SCRIPT_ENDING(qDebug() << " _isInitialized:" << _isInitialized;) + DEBUG_SCRIPT_ENDING(qDebug() << " _evaluatesPending:" << _evaluatesPending;) loop.exec(); - qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER loop.exec() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER loop.exec() script:" << scriptName;) // process events - qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING QCoreApplication::processEvents() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING QCoreApplication::processEvents() script:" << scriptName;) QCoreApplication::processEvents(); - qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER QCoreApplication::processEvents() script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER QCoreApplication::processEvents() script:" << scriptName;) if (_doneRunningThisScript) { - qDebug() << "ScriptEngine::waitTillDoneRunning() _doneRunningThisScript after processEvents... breaking!!! script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() _doneRunningThisScript after processEvents... breaking!!! script:" << scriptName;) break; } } @@ -212,7 +215,7 @@ void ScriptEngine::waitTillDoneRunning() { _isWaitingForDoneRunning = false; } - qDebug() << "ScriptEngine::waitTillDoneRunning() ------- DONE ------- script:" << scriptName; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() ------- DONE ------- script:" << scriptName;) } QString ScriptEngine::getFilename() const { @@ -430,20 +433,20 @@ void ScriptEngine::evaluate() { return; // bail early } - qDebug() << "ScriptEngine::evaluate() -- BEGIN script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- BEGIN script:" << getFilename() << "[" << this << "]";) if (!_isInitialized) { init(); } - qDebug() << "ScriptEngine::evaluate() -- about to call own evaluate(program) script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- about to call own evaluate(program) script:" << getFilename() << "[" << this << "]";) QScriptValue result = evaluate(_scriptContents); - qDebug() << "ScriptEngine::evaluate() -- AFTER own evaluate(program) script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- AFTER own evaluate(program) script:" << getFilename() << "[" << this << "]";) // TODO: why do we check this twice? It seems like the call to clearExcpetions() in the lower level evaluate call // will cause this code to never actually run... if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); - qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString(); + DEBUG_SCRIPT_ENDING(qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString();) emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + result.toString()); clearExceptions(); } @@ -456,24 +459,24 @@ QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileN return QScriptValue(); // bail early } - qDebug() << "ScriptEngine::evaluate(program) -- BEGIN script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- BEGIN script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) _evaluatesPending++; - qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending++ script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; - qDebug() << "ScriptEngine::evaluate(program) -- BEFORE QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending++ script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- BEFORE QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber); - qDebug() << "ScriptEngine::evaluate(program) -- AFTER QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- AFTER QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString(); } _evaluatesPending--; - qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending-- script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending-- script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) - qDebug() << "ScriptEngine::evaluate(program) -- ABOUT TO emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- ABOUT TO emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) emit evaluationFinished(result, hasUncaughtException()); - qDebug() << "ScriptEngine::evaluate(program) -- AFTER emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- AFTER emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) clearExceptions(); - qDebug() << "ScriptEngine::evaluate(program) -- DONE script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- DONE script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) return result; } @@ -493,18 +496,18 @@ void ScriptEngine::run() { // TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if // we're in the process of stopping? - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) if (!_isInitialized) { init(); } - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _isRunning = true; _isFinished = false; emit runningStateChanged(); - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) QScriptValue result = evaluate(_scriptContents); - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) QElapsedTimer startTime; startTime.start(); @@ -515,11 +518,11 @@ void ScriptEngine::run() { qint64 lastUpdate = usecTimestampNow(); - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) while (!_isFinished) { if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec @@ -528,22 +531,22 @@ void ScriptEngine::run() { } if (_isFinished) { - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) break; } if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } QCoreApplication::processEvents(); if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } if (_isFinished) { - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) break; } @@ -673,34 +676,34 @@ void ScriptEngine::run() { lastUpdate = now; if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } } if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) stopAllTimers(); // make sure all our timers are stopped if the script is ending - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename(); + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename();) if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } emit scriptEnding(); - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) // kill the avatar identity timer delete _avatarIdentityTimer; - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { @@ -713,43 +716,43 @@ void ScriptEngine::run() { } } - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) // If we were on a thread, then wait till it's done if (thread()) { - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) thread()->quit(); - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } - qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } emit finished(_fileNameString); if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } _isRunning = false; emit runningStateChanged(); - qDebug() << "ABOUT TO emit doneRunning() script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ABOUT TO emit doneRunning() script:" << getFilename() << "[" << this << "]";) emit doneRunning(); - qDebug() << "AFTER emit doneRunning() script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "AFTER emit doneRunning() script:" << getFilename() << "[" << this << "]";) if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } - qDebug() << "ScriptEngine::run() SETTING _doneRunningThisScript = true ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() SETTING _doneRunningThisScript = true ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _doneRunningThisScript = true; if (_isWaitingForDoneRunning) { - qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } } @@ -765,10 +768,10 @@ void ScriptEngine::stopAllTimers() { } void ScriptEngine::stop() { - qDebug() << "ScriptEngine::stop() -- START -- line:" << __LINE__ << " script:" << getFilename(); + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stop() -- START -- line:" << __LINE__ << " script:" << getFilename();) _isFinished = true; emit runningStateChanged(); - qDebug() << "ScriptEngine::stop() -- DONE -- line:" << __LINE__ << " script:" << getFilename(); + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stop() -- DONE -- line:" << __LINE__ << " script:" << getFilename();) } void ScriptEngine::timerFired() { @@ -884,9 +887,9 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac if (contents.isNull()) { qDebug() << "Error loading file: " << url; } else { - qDebug() << "ScriptEngine::include() BEFORE evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::include() BEFORE evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;) QScriptValue result = evaluate(contents, url.toString()); - qDebug() << "ScriptEngine::include() AFTER evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::include() AFTER evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;) } } From 89f7f2da2e93df6469d425ff01d7dd38b05043c8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 15:57:34 -0800 Subject: [PATCH 198/341] don't do idle process and painting if we're shutting down the application --- interface/src/Application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 998e2065dc..537d3d2a75 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1471,6 +1471,10 @@ void Application::checkFPS() { void Application::idle() { PerformanceTimer perfTimer("idle"); + + if (_aboutToQuit) { + return; // bail early, nothing to do here. + } // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing From 9dcea38b2b661bf38255e6a133a4929deb07db90 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 16:23:39 -0800 Subject: [PATCH 199/341] tweak some debugging --- libraries/script-engine/src/ScriptEngine.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cbdd59146b..a6b0b8dc1f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -125,7 +125,7 @@ bool ScriptEngine::_stoppingAllScripts = false; bool ScriptEngine::_doneRunningThisScript = false; void ScriptEngine::stopAllScripts(QObject* application) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------";) + qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------"; _allScriptsMutex.lock(); _stoppingAllScripts = true; @@ -136,9 +136,7 @@ void ScriptEngine::stopAllScripts(QObject* application) { QString scriptName = scriptEngine->getFilename(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName - << "isRunning():" << scriptEngine->isRunning() - << "evaluatePending():" << scriptEngine->evaluatePending();) + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName << "isRunning():" << scriptEngine->isRunning() << "evaluatePending():" << scriptEngine->evaluatePending();) // NOTE: typically all script engines are running. But there's at least one known exception to this, the // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using @@ -165,11 +163,13 @@ void ScriptEngine::stopAllScripts(QObject* application) { DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName;) i.remove(); } else { + qDebug() << "ScriptEngine::stopAllScripts() " << scriptName << " - will be freed on it's own."; } } _stoppingAllScripts = false; _allScriptsMutex.unlock(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------";) + qDebug() << "ScriptEngine::stopAllScripts() _allKnownScriptEngines.count:" << _allKnownScriptEngines.count(); + qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------"; } @@ -428,8 +428,8 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func void ScriptEngine::evaluate() { if (_stoppingAllScripts) { - qDebug() << "ScriptEngine::evaluate() while shutting down is ignored..."; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() while shutting down is ignored...";) + DEBUG_SCRIPT_ENDING(qDebug() << " parent script:" << getFilename() << "[" << this << "]";) return; // bail early } @@ -454,8 +454,8 @@ void ScriptEngine::evaluate() { QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { if (_stoppingAllScripts) { - qDebug() << "ScriptEngine::evaluate(program) while shutting down is ignored..."; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) while shutting down is ignored...";) + DEBUG_SCRIPT_ENDING(qDebug() << " parent script:" << getFilename() << "[" << this << "]";) return QScriptValue(); // bail early } From c9d6a44c3a5cc399d115738404e1e7acad332415 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 16:56:13 -0800 Subject: [PATCH 200/341] fix up command-line parsing --- assignment-client/src/AssignmentClient.cpp | 49 ++------ assignment-client/src/AssignmentClient.h | 4 +- assignment-client/src/AssignmentClientApp.cpp | 118 +++++++++++++++++- assignment-client/src/AssignmentClientApp.h | 16 +++ .../src/AssignmentClientMonitor.cpp | 60 ++++++--- .../src/AssignmentClientMonitor.h | 15 ++- 6 files changed, 196 insertions(+), 66 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 2dfc3787de..cb2da51031 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -40,7 +39,9 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv) : +AssignmentClient::AssignmentClient(int &argc, char **argv, + Assignment::Type requestAssignmentType, QString assignmentPool, QUuid walletUUID, + QString assignmentServerHostname, quint16 assignmentServerPort) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL), @@ -73,51 +74,20 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // set the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); - const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments()); - - const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "t"; - const QString ASSIGNMENT_POOL_OPTION = "pool"; - const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "wallet"; - const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "a"; - const QString CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION = "p"; - - Assignment::Type requestAssignmentType = Assignment::AllTypes; - - // check for an assignment type passed on the command line or in the config - if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) { - requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt(); - } - - QString assignmentPool; - - // check for an assignment pool passed on the command line or in the config - if (argumentVariantMap.contains(ASSIGNMENT_POOL_OPTION)) { - assignmentPool = argumentVariantMap.value(ASSIGNMENT_POOL_OPTION).toString(); - } - // setup our _requestAssignment member variable from the passed arguments _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); // check for a wallet UUID on the command line or in the config // this would represent where the user running AC wants funds sent to - if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { - QUuid walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString(); + if (!walletUUID.isNull()) { qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } - quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; - // check for an overriden assignment server hostname - if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) { + if (assignmentServerHostname != "") { // change the hostname for our assignment server - _assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); - } - - // check for an overriden assignment server port - if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION)) { - assignmentServerPort = - argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); + _assignmentServerHostname = assignmentServerHostname; } _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); @@ -128,6 +98,10 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; + if (_assignmentServerHostname != "localhost") { + qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } + connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); @@ -199,9 +173,6 @@ void AssignmentClient::sendAssignmentRequest() { nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - else { - qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } } nodeList->sendAssignment(_requestAssignment); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index e105309e10..67a5dc89a7 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,9 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv); + + AssignmentClient(int &argc, char **argv, Assignment::Type requestAssignmentType, QString assignmentPool, + QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 477f1a2cf8..7f174f0833 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "Assignment.h" #include "AssignmentClient.h" @@ -37,9 +38,35 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : const QCommandLineOption helpOption = parser.addHelpOption(); - const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); + const QCommandLineOption clientTypeOption(ASSIGNMENT_TYPE_OVERRIDE_OPTION, + "run single assignment client of given type", "type"); + parser.addOption(clientTypeOption); + + const QCommandLineOption poolOption(ASSIGNMENT_POOL_OPTION, "set assignment pool", "pool-name"); + parser.addOption(poolOption); + + const QCommandLineOption walletDestinationOption(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION, + "set wallet destination", "wallet-uuid"); + parser.addOption(walletDestinationOption); + + const QCommandLineOption assignmentServerHostnameOption(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION, + "set assignment-server hostname", "hostname"); + parser.addOption(assignmentServerHostnameOption); + + const QCommandLineOption assignmentServerPortOption(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION, + "set assignment-server port", "port"); + parser.addOption(assignmentServerPortOption); + + const QCommandLineOption numChildsOption(ASSIGNMENT_NUM_FORKS_OPTION, "number of children to fork", "child-count"); parser.addOption(numChildsOption); + const QCommandLineOption minChildsOption(ASSIGNMENT_MIN_FORKS_OPTION, "minimum number of children", "child-count"); + parser.addOption(minChildsOption); + + const QCommandLineOption maxChildsOption(ASSIGNMENT_MAX_FORKS_OPTION, "maximum number of children", "child-count"); + parser.addOption(maxChildsOption); + + if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -51,16 +78,99 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : Q_UNREACHABLE(); } + + const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments()); + + unsigned int numForks = 0; if (parser.isSet(numChildsOption)) { numForks = parser.value(numChildsOption).toInt(); } - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); + unsigned int minForks = 0; + if (parser.isSet(minChildsOption)) { + minForks = parser.value(minChildsOption).toInt(); + } + + unsigned int maxForks = 0; + if (parser.isSet(maxChildsOption)) { + maxForks = parser.value(maxChildsOption).toInt(); + } + + + Assignment::Type requestAssignmentType = Assignment::AllTypes; + if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) { + requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt(); + } + if (parser.isSet(clientTypeOption)) { + if (numForks || minForks || maxForks) { + qCritical() << "don't use -t with forking mode."; + parser.showHelp(); + Q_UNREACHABLE(); + } + requestAssignmentType = (Assignment::Type) parser.value(clientTypeOption).toInt(); + } + + QString assignmentPool; + // check for an assignment pool passed on the command line or in the config + if (argumentVariantMap.contains(ASSIGNMENT_POOL_OPTION)) { + assignmentPool = argumentVariantMap.value(ASSIGNMENT_POOL_OPTION).toString(); + } + if (parser.isSet(poolOption)) { + assignmentPool = parser.value(poolOption); + } + + + QUuid walletUUID; + if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { + walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString(); + } + if (parser.isSet(walletDestinationOption)) { + walletUUID = parser.value(walletDestinationOption); + } + + + QString assignmentServerHostname; + if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { + assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); + } + if (parser.isSet(assignmentServerHostnameOption)) { + assignmentServerHostname = parser.value(assignmentServerHostnameOption); + } + + + // check for an overriden assignment server port + quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; + if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { + assignmentServerPort = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION).toString().toUInt(); + } + if (parser.isSet(assignmentServerPortOption)) { + assignmentServerPort = parser.value(assignmentServerPortOption).toInt(); + } + + + + if (parser.isSet(numChildsOption)) { + if (minForks && minForks > numForks) { + qCritical() << "--min can't be more than -n"; + parser.showHelp(); + Q_UNREACHABLE(); + } + if (maxForks && maxForks < numForks) { + qCritical() << "--max can't be less than -n"; + parser.showHelp(); + Q_UNREACHABLE(); + } + } + + + if (numForks || minForks || maxForks) { + AssignmentClientMonitor monitor(argc, argv, numForks, minForks, maxForks, assignmentPool, + walletUUID, assignmentServerHostname, assignmentServerPort); monitor.exec(); } else { - AssignmentClient client(argc, argv); + AssignmentClient client(argc, argv, requestAssignmentType, assignmentPool, + walletUUID, assignmentServerHostname, assignmentServerPort); client.exec(); } } diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h index c5099ff25c..531035ef0e 100644 --- a/assignment-client/src/AssignmentClientApp.h +++ b/assignment-client/src/AssignmentClientApp.h @@ -9,10 +9,26 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#ifndef hifi_AssignmentClientApp_h +#define hifi_AssignmentClientApp_h + + #include +const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "t"; +const QString ASSIGNMENT_POOL_OPTION = "pool"; +const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "wallet"; +const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "a"; +const QString CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION = "p"; +const QString ASSIGNMENT_NUM_FORKS_OPTION = "n"; +const QString ASSIGNMENT_MIN_FORKS_OPTION = "min"; +const QString ASSIGNMENT_MAX_FORKS_OPTION = "max"; + + class AssignmentClientApp : public QCoreApplication { Q_OBJECT public: AssignmentClientApp(int argc, char* argv[]); }; + +#endif // hifi_AssignmentClientApp_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 803c7fd5c7..0f8e7adc17 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -16,6 +16,7 @@ #include #include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" #include "AssignmentClientChildData.h" #include "PacketHeaders.h" #include "SharedUtil.h" @@ -24,8 +25,20 @@ const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : - QCoreApplication(argc, argv) +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, + const unsigned int numAssignmentClientForks, + const unsigned int minAssignmentClientForks, + const unsigned int maxAssignmentClientForks, + QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, + quint16 assignmentServerPort) : + QCoreApplication(argc, argv), + _numAssignmentClientForks(numAssignmentClientForks), + _minAssignmentClientForks(minAssignmentClientForks), + _maxAssignmentClientForks(maxAssignmentClientForks), + _assignmentPool(assignmentPool), + _walletUUID(walletUUID), + _assignmentServerHostname(assignmentServerHostname), + _assignmentServerPort(assignmentServerPort) { // start the Logging class with the parent's target name LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); @@ -36,16 +49,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u #else ShutdownEventListener::getInstance(); #endif - - _childArguments = arguments(); - - // remove the parameter for the number of forks so it isn't passed to the child forked processes - int forksParameterIndex = _childArguments.indexOf(NUM_FORKS_PARAMETER); - - // this removes both the "-n" parameter and the number of forks passed - _childArguments.removeAt(forksParameterIndex); - _childArguments.removeAt(forksParameterIndex); - // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); @@ -58,7 +61,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const u nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (unsigned int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < _numAssignmentClientForks; i++) { spawnChildClient(); } @@ -83,7 +86,26 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); - + + // unparse the parts of the command-line that the child cares about + QStringList _childArguments; + if (_assignmentPool != "") { + _childArguments.append("--" + ASSIGNMENT_POOL_OPTION); + _childArguments.append(_assignmentPool); + } + if (!_walletUUID.isNull()) { + _childArguments.append("--" + ASSIGNMENT_WALLET_DESTINATION_ID_OPTION); + _childArguments.append(_walletUUID.toString()); + } + if (_assignmentServerHostname != "") { + _childArguments.append("--" + CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION); + _childArguments.append(_assignmentServerHostname); + } + if (_assignmentServerPort != DEFAULT_DOMAIN_SERVER_PORT) { + _childArguments.append("--" + CUSTOM_ASSIGNMENT_SERVER_PORT_OPTION); + _childArguments.append(QString::number(_assignmentServerPort)); + } + // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); @@ -98,26 +120,24 @@ void AssignmentClientMonitor::checkSpares() { auto nodeList = DependencyManager::get(); QUuid aSpareId = ""; unsigned int spareCount = 0; + unsigned int totalCount = 0; nodeList->removeSilentNodes(); nodeList->eachNode([&](const SharedNodePointer& node) { AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + totalCount ++; if (childData->getChildType() == "none") { spareCount ++; aSpareId = node->getUUID(); } }); - if (spareCount != 1) { - qDebug() << "spare count is" << spareCount; - } - - if (spareCount < 1) { + if (spareCount < 1 && totalCount < _maxAssignmentClientForks) { spawnChildClient(); } - if (spareCount > 1) { + if (spareCount > 1 && totalCount > _minAssignmentClientForks) { // kill aSpareId qDebug() << "asking child" << aSpareId << "to exit."; SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 71ae34bc8c..e40a10014b 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -27,7 +27,10 @@ extern const char* NUM_FORKS_PARAMETER; class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks, + const unsigned int minAssignmentClientForks, const unsigned int maxAssignmentClientForks, + QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, + quint16 assignmentServerPort); ~AssignmentClientMonitor(); void stopChildProcesses(); @@ -37,8 +40,16 @@ private slots: private: void spawnChildClient(); - QStringList _childArguments; QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children + + const unsigned int _numAssignmentClientForks; + const unsigned int _minAssignmentClientForks; + const unsigned int _maxAssignmentClientForks; + + QString _assignmentPool; + QUuid _walletUUID; + QString _assignmentServerHostname; + quint16 _assignmentServerPort; }; #endif // hifi_AssignmentClientMonitor_h From 03b10b6cb02fbf281844b02dc3e3b41242e5d0c6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:00:30 -0800 Subject: [PATCH 201/341] Add findRayRectangleIntersection --- libraries/shared/src/GeometryUtil.cpp | 35 ++++++++++++++++++++++++++- libraries/shared/src/GeometryUtil.h | 3 +++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index aaec8b3e4a..cf15830a10 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -12,8 +12,10 @@ #include #include -#include "SharedUtil.h" #include "GeometryUtil.h" +#include "PlaneShape.h" +#include "RayIntersectionInfo.h" +#include "SharedUtil.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector @@ -491,3 +493,34 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len } } } + +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions) { + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::vec3 normal = rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + float distance = rayInfo._hitDistance; + + glm::vec3 hitPosition = origin + (distance * direction); + glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); + + glm::vec2 halfDimensions = 0.5f * dimensions; + + intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x + && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; + } + + return intersects; +} diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index a6889ef73e..e0de536e97 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,6 +76,9 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions); + bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); From be7959bbcddb1f45c8e92989ed7cceee18cc4251 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:00:55 -0800 Subject: [PATCH 202/341] Fix BillboardOverlay findRayIntersection implementation --- .../src/ui/overlays/BillboardOverlay.cpp | 46 ++++--------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index 4ea0e55710..a82da0ee5f 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -10,9 +10,10 @@ // #include "Application.h" +#include "GeometryUtil.h" +#include "PlaneShape.h" #include "BillboardOverlay.h" -#include BillboardOverlay::BillboardOverlay() : _fromImage(), @@ -192,23 +193,6 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float& distance, BoxFace& face) { if (_texture) { - // This is taken from Planar3DOverlay. Although it probably makes more sense for this - // overlay type to extend from Planar3DOverlay, the interfaces are different enough (scale vs. dimensions) - // that it would break existing scripts and would require other changes to make up for unique - // features like `isFacingAvatar`. - - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - bool isNull = _fromImage.isNull(); - float width = isNull ? _texture->getWidth() : _fromImage.width(); - float height = isNull ? _texture->getHeight() : _fromImage.height(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); glm::quat rotation; if (_isFacingAvatar) { // rotate about vertical to face the camera @@ -217,27 +201,17 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v } else { rotation = _rotation; } - glm::vec3 normal = rotation * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(_position); // the position is definitely a point on our plane - bool intersects = plane.findRayIntersection(rayInfo); + // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. + bool isNull = _fromImage.isNull(); + float width = isNull ? _texture->getWidth() : _fromImage.width(); + float height = isNull ? _texture->getHeight() : _fromImage.height(); + float maxSize = glm::max(width, height); + glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize); - if (intersects) { - distance = rayInfo._hitDistance; - - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - _position); - - // Produce the dimensions of the billboard based on the image's aspect ratio and the overlay's scale. - float maxSize = glm::max(width, height); - glm::vec2 halfDimensions = 0.5f * _scale * glm::vec2(width / maxSize, height / maxSize); - - intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x - && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; - } - return intersects; + return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions); } + return false; } From eb21b7443989000e1eb495985c12de686e4120d7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Feb 2015 17:01:24 -0800 Subject: [PATCH 203/341] Replace Planar3DOverlay::findRayIntersection with GeometryUtil::findRayRectangleIntersection --- interface/src/ui/overlays/Planar3DOverlay.cpp | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 508b5c4227..925725d261 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -17,6 +17,8 @@ #include #include +#include "GeometryUtil.h" + #include "Planar3DOverlay.h" const float DEFAULT_SIZE = 1.0f; @@ -93,29 +95,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - RayIntersectionInfo rayInfo; - rayInfo._rayStart = origin; - rayInfo._rayDirection = direction; - rayInfo._rayLength = std::numeric_limits::max(); - - PlaneShape plane; - - const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); - glm::vec3 normal = _rotation * UNROTATED_NORMAL; - plane.setNormal(normal); - plane.setPoint(_position); // the position is definitely a point on our plane - - bool intersects = plane.findRayIntersection(rayInfo); - - if (intersects) { - distance = rayInfo._hitDistance; - - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(_rotation) * (hitPosition - _position); - glm::vec2 halfDimensions = _dimensions / 2.0f; - - intersects = -halfDimensions.x <= localHitPosition.x && localHitPosition.x <= halfDimensions.x - && -halfDimensions.y <= localHitPosition.y && localHitPosition.y <= halfDimensions.y; - } - return intersects; + return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions); } From 25ae001d3b874330d3bd538fffab8e66b8fd23eb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 17:05:44 -0800 Subject: [PATCH 204/341] removed extra debugging --- libraries/script-engine/src/ScriptEngine.cpp | 119 +------------------ 1 file changed, 1 insertion(+), 118 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a6b0b8dc1f..9a88476e8c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -42,12 +42,6 @@ #include "MIDIEvent.h" -#ifdef WANT_DEBUG_SCRIPT_ENDING -#define DEBUG_SCRIPT_ENDING(X) X -#else -#define DEBUG_SCRIPT_ENDING(x) -#endif - EntityScriptingInterface ScriptEngine::_entityScriptingInterface; static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ @@ -107,7 +101,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam } ScriptEngine::~ScriptEngine() { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::~ScriptEngine() ------- BEGIN ------- script:" << getFilename();) // If we're not already in the middle of stopping all scripts, then we should remove ourselves // from the list of running scripts. We don't do this if we're in the process of stopping all scripts // because that method removes scripts from its list as it iterates them @@ -116,7 +109,6 @@ ScriptEngine::~ScriptEngine() { _allKnownScriptEngines.remove(this); _allScriptsMutex.unlock(); } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::~ScriptEngine() ------- END ------- script:" << getFilename();) } QSet ScriptEngine::_allKnownScriptEngines; @@ -136,8 +128,6 @@ void ScriptEngine::stopAllScripts(QObject* application) { QString scriptName = scriptEngine->getFilename(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() considering:" << scriptName << "isRunning():" << scriptEngine->isRunning() << "evaluatePending():" << scriptEngine->evaluatePending();) - // NOTE: typically all script engines are running. But there's at least one known exception to this, the // "entities sandbox" which is only used to evaluate entities scripts to test their validity before using // them. We don't need to stop scripts that aren't running. @@ -149,18 +139,14 @@ void ScriptEngine::stopAllScripts(QObject* application) { while (scriptEngine->evaluatePending()) { QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) STARTING loop.exec() script:" << scriptName;) loop.exec(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() while(evaluatePending()) AFTER loop.exec() script:" << scriptName;) } } scriptEngine->disconnect(application); scriptEngine->stop(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() -- WAITING for waitTillDoneRunning() script:" << scriptName;) scriptEngine->waitTillDoneRunning(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stopAllScripts() -- AFTER waitTillDoneRunning() script:" << scriptName;) i.remove(); } else { qDebug() << "ScriptEngine::stopAllScripts() " << scriptName << " - will be freed on it's own."; @@ -175,10 +161,8 @@ void ScriptEngine::stopAllScripts(QObject* application) { void ScriptEngine::waitTillDoneRunning() { QString scriptName = getFilename(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() ------- BEGIN ------- script:" << scriptName;) if (_isRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() SETTING _doneRunningThisScript = false ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _doneRunningThisScript = false; _isWaitingForDoneRunning = true; @@ -191,31 +175,18 @@ void ScriptEngine::waitTillDoneRunning() { // and run a QEventLoop??? QEventLoop loop; QObject::connect(this, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING loop.exec() script:" << scriptName;) - DEBUG_SCRIPT_ENDING(qDebug() << " _doneRunningThisScript:" << _doneRunningThisScript;) - DEBUG_SCRIPT_ENDING(qDebug() << " _isRunning:" << _isRunning;) - DEBUG_SCRIPT_ENDING(qDebug() << " _isWaitingForDoneRunning:" << _isWaitingForDoneRunning;) - DEBUG_SCRIPT_ENDING(qDebug() << " _isFinished:" << _isFinished;) - DEBUG_SCRIPT_ENDING(qDebug() << " _isInitialized:" << _isInitialized;) - DEBUG_SCRIPT_ENDING(qDebug() << " _evaluatesPending:" << _evaluatesPending;) loop.exec(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER loop.exec() script:" << scriptName;) // process events - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() STARTING QCoreApplication::processEvents() script:" << scriptName;) QCoreApplication::processEvents(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() AFTER QCoreApplication::processEvents() script:" << scriptName;) if (_doneRunningThisScript) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() _doneRunningThisScript after processEvents... breaking!!! script:" << scriptName;) break; } } _isWaitingForDoneRunning = false; } - - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::waitTillDoneRunning() ------- DONE ------- script:" << scriptName;) } QString ScriptEngine::getFilename() const { @@ -428,25 +399,20 @@ void ScriptEngine::registerGetterSetter(const QString& name, QScriptEngine::Func void ScriptEngine::evaluate() { if (_stoppingAllScripts) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() while shutting down is ignored...";) - DEBUG_SCRIPT_ENDING(qDebug() << " parent script:" << getFilename() << "[" << this << "]";) return; // bail early } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- BEGIN script:" << getFilename() << "[" << this << "]";) if (!_isInitialized) { init(); } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- about to call own evaluate(program) script:" << getFilename() << "[" << this << "]";) QScriptValue result = evaluate(_scriptContents); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate() -- AFTER own evaluate(program) script:" << getFilename() << "[" << this << "]";) // TODO: why do we check this twice? It seems like the call to clearExcpetions() in the lower level evaluate call // will cause this code to never actually run... if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); - DEBUG_SCRIPT_ENDING(qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString();) + qDebug() << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + result.toString()); clearExceptions(); } @@ -454,29 +420,18 @@ void ScriptEngine::evaluate() { QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { if (_stoppingAllScripts) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) while shutting down is ignored...";) - DEBUG_SCRIPT_ENDING(qDebug() << " parent script:" << getFilename() << "[" << this << "]";) return QScriptValue(); // bail early } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- BEGIN script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) _evaluatesPending++; - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending++ script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- BEFORE QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) QScriptValue result = QScriptEngine::evaluate(program, fileName, lineNumber); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- AFTER QScriptEngine::evaluate() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at (" << _fileNameString << " : " << fileName << ") line" << line << ": " << result.toString(); } _evaluatesPending--; - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- after _evaluatesPending-- script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) - - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- ABOUT TO emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) emit evaluationFinished(result, hasUncaughtException()); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- AFTER emit evaluationFinished() script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) clearExceptions(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::evaluate(program) -- DONE script:" << getFilename() << "_evaluatesPending:" << _evaluatesPending << "[" << this << "]";) return result; } @@ -496,18 +451,14 @@ void ScriptEngine::run() { // TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if // we're in the process of stopping? - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) if (!_isInitialized) { init(); } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _isRunning = true; _isFinished = false; emit runningStateChanged(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) QScriptValue result = evaluate(_scriptContents); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) QElapsedTimer startTime; startTime.start(); @@ -518,35 +469,19 @@ void ScriptEngine::run() { qint64 lastUpdate = usecTimestampNow(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - while (!_isFinished) { - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { usleep(usecToSleep); } if (_isFinished) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) break; } - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - QCoreApplication::processEvents(); - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - if (_isFinished) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) break; } @@ -675,37 +610,14 @@ void ScriptEngine::run() { } lastUpdate = now; - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - } - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - stopAllTimers(); // make sure all our timers are stopped if the script is ending - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename();) - - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - emit scriptEnding(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) // kill the avatar identity timer delete _avatarIdentityTimer; - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); @@ -716,44 +628,19 @@ void ScriptEngine::run() { } } - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - // If we were on a thread, then wait till it's done if (thread()) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) thread()->quit(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) } emit finished(_fileNameString); - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - _isRunning = false; emit runningStateChanged(); - DEBUG_SCRIPT_ENDING(qDebug() << "ABOUT TO emit doneRunning() script:" << getFilename() << "[" << this << "]";) emit doneRunning(); - DEBUG_SCRIPT_ENDING(qDebug() << "AFTER emit doneRunning() script:" << getFilename() << "[" << this << "]";) - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } - - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() SETTING _doneRunningThisScript = true ################################### line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) _doneRunningThisScript = true; - - if (_isWaitingForDoneRunning) { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::run() ** _isWaitingForDoneRunning == true ** line:" << __LINE__ << " script:" << getFilename() << "[" << this << "]";) - } } // NOTE: This is private because it must be called on the same thread that created the timers, which is why @@ -768,10 +655,8 @@ void ScriptEngine::stopAllTimers() { } void ScriptEngine::stop() { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stop() -- START -- line:" << __LINE__ << " script:" << getFilename();) _isFinished = true; emit runningStateChanged(); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::stop() -- DONE -- line:" << __LINE__ << " script:" << getFilename();) } void ScriptEngine::timerFired() { @@ -887,9 +772,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac if (contents.isNull()) { qDebug() << "Error loading file: " << url; } else { - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::include() BEFORE evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;) QScriptValue result = evaluate(contents, url.toString()); - DEBUG_SCRIPT_ENDING(qDebug() << "ScriptEngine::include() AFTER evaluate() line:" << __LINE__ << " parent script:" << getFilename() << "[" << this << "]" << " url:" << url << "_evaluatesPending:" << _evaluatesPending;) } } From 89ebb45c0390830c84e41c12bf865a84a3792b86 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 17:09:05 -0800 Subject: [PATCH 205/341] Revert "Merge pull request #4332 from birarda/master" This reverts commit 3230857b0d03c603bacb9016740234e781070d44, reversing changes made to 1b669af79df5335ae0e6565c33e06e30a006ca5e. --- assignment-client/src/AssignmentClient.cpp | 87 +++++++--- assignment-client/src/AssignmentClient.h | 11 +- assignment-client/src/AssignmentClientApp.cpp | 66 ++++++++ assignment-client/src/AssignmentClientApp.h | 18 ++ .../src/AssignmentClientChildData.cpp | 8 + .../src/AssignmentClientChildData.h | 32 ++++ .../src/AssignmentClientMonitor.cpp | 158 ++++++++++++++---- .../src/AssignmentClientMonitor.h | 13 +- assignment-client/src/main.cpp | 30 +--- domain-server/src/DomainServer.cpp | 14 +- libraries/networking/src/AddressManager.cpp | 4 +- libraries/networking/src/LimitedNodeList.cpp | 38 +++++ libraries/networking/src/LimitedNodeList.h | 9 + libraries/networking/src/Node.cpp | 7 +- libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 + libraries/networking/src/PacketHeaders.cpp | 3 + libraries/networking/src/PacketHeaders.h | 4 +- 18 files changed, 403 insertions(+), 108 deletions(-) create mode 100644 assignment-client/src/AssignmentClientApp.cpp create mode 100644 assignment-client/src/AssignmentClientApp.h create mode 100644 assignment-client/src/AssignmentClientChildData.cpp create mode 100644 assignment-client/src/AssignmentClientChildData.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index bf67d4d597..2dfc3787de 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,10 +18,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -43,7 +43,8 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL) + _localASPortSharedMem(NULL), + _localACMPortSharedMem(NULL) { LogUtils::init(); @@ -56,7 +57,11 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); - auto avatarHashMap = DependencyManager::set(); + + // make up a uuid for this child so the parent can tell us apart. This id will be changed + // when the domain server hands over an assignment. + QUuid nodeUUID = QUuid::createUuid(); + nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -123,9 +128,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - QTimer* timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -136,6 +140,45 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + + // Hook up a timer to send this child's status to the Monitor once per second + setUpStatsToMonitor(); +} + + +void AssignmentClient::stopAssignmentClient() { + qDebug() << "Exiting."; + _requestTimer.stop(); + _statsTimerACM.stop(); + quit(); +} + + +void AssignmentClient::setUpStatsToMonitor() { + // Figure out the address to send out stats to + quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; + auto nodeList = DependencyManager::get(); + + nodeList->getLocalServerPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); + _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); + + // send a stats packet every 1 seconds + connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); + _statsTimerACM.start(1000); +} + +void AssignmentClient::sendStatsPacketToACM() { + // tell the assignment client monitor what this assignment client is doing (if anything) + QJsonObject statsObject; + auto nodeList = DependencyManager::get(); + + if (_currentAssignment) { + statsObject["assignment_type"] = _currentAssignment->getTypeName(); + } else { + statsObject["assignment_type"] = "none"; + } + nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -145,23 +188,9 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - if (!_localASPortSharedMem) { - _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - - if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY - << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } - } - - if (_localASPortSharedMem->isAttached()) { - _localASPortSharedMem->lock(); - - quint16 localAssignmentServerPort; - memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); - - _localASPortSharedMem->unlock(); - + quint16 localAssignmentServerPort; + if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" << localAssignmentServerPort; @@ -170,7 +199,9 @@ void AssignmentClient::sendAssignmentRequest() { nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - + else { + qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } } nodeList->sendAssignment(_requestAssignment); @@ -227,6 +258,14 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } + } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + qDebug() << "Network told me to exit."; + emit stopAssignmentClient(); + } else { + qDebug() << "Got a stop packet from other than localhost."; + } } else { // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 053458f136..e105309e10 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -29,13 +29,22 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); + void sendStatsPacketToACM(); + void stopAssignmentClient(); private: + void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; + QSharedMemory* _localASPortSharedMem; // memory shared with domain server + QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor + QTimer _requestTimer; // timer for requesting and assignment + QTimer _statsTimerACM; // timer for sending stats to assignment client monitor + + protected: + HifiSockAddr _assignmentClientMonitorSocket; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp new file mode 100644 index 0000000000..477f1a2cf8 --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -0,0 +1,66 @@ +// +// AssignmentClientapp.cpp +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" + + +AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : + QCoreApplication(argc, argv) +{ +# ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +# endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Assignment Client"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); + parser.addOption(numChildsOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + unsigned int numForks = 0; + if (parser.isSet(numChildsOption)) { + numForks = parser.value(numChildsOption).toInt(); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + monitor.exec(); + } else { + AssignmentClient client(argc, argv); + client.exec(); + } +} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h new file mode 100644 index 0000000000..c5099ff25c --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.h @@ -0,0 +1,18 @@ +// +// AssignmentClientapp.h +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +class AssignmentClientApp : public QCoreApplication { + Q_OBJECT +public: + AssignmentClientApp(int argc, char* argv[]); +}; diff --git a/assignment-client/src/AssignmentClientChildData.cpp b/assignment-client/src/AssignmentClientChildData.cpp new file mode 100644 index 0000000000..de34613ec9 --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.cpp @@ -0,0 +1,8 @@ + +#include "AssignmentClientChildData.h" + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) : + _childType(childType) +{ +} diff --git a/assignment-client/src/AssignmentClientChildData.h b/assignment-client/src/AssignmentClientChildData.h new file mode 100644 index 0000000000..6fd5f72f7f --- /dev/null +++ b/assignment-client/src/AssignmentClientChildData.h @@ -0,0 +1,32 @@ +// +// AssignmentClientChildData.h +// assignment-client/src +// +// Created by Seth Alves on 2/23/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AssignmentClientChildData_h +#define hifi_AssignmentClientChildData_h + +#include + + +class AssignmentClientChildData : public NodeData { + public: + AssignmentClientChildData(QString childType); + + QString getChildType() { return _childType; } + void setChildType(QString childType) { _childType = childType; } + + // implement parseData to return 0 so we can be a subclass of NodeData + int parseData(const QByteArray& packet) { return 0; } + + private: + QString _childType; +}; + +#endif // hifi_AssignmentClientChildData_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 45e1f56d53..803c7fd5c7 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -13,14 +13,18 @@ #include #include +#include #include "AssignmentClientMonitor.h" +#include "AssignmentClientChildData.h" +#include "PacketHeaders.h" +#include "SharedUtil.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -41,11 +45,25 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); + + + // create a NodeList so we can receive stats from children + DependencyManager::registerInheritance(); + auto addressManager = DependencyManager::set(); + auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, + DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); + + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); + + nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } + + connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); + _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } AssignmentClientMonitor::~AssignmentClientMonitor() { @@ -53,46 +71,122 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { } void AssignmentClientMonitor::stopChildProcesses() { - - QList >::Iterator it = _childProcesses.begin(); - while (it != _childProcesses.end()) { - if (!it->isNull()) { - qDebug() << "Monitor is terminating child process" << it->data(); - - // don't re-spawn this child when it goes down - disconnect(it->data(), 0, this, 0); - - it->data()->terminate(); - it->data()->waitForFinished(); - } - - it = _childProcesses.erase(it); - } + auto nodeList = DependencyManager::get(); + + nodeList->eachNode([&](const SharedNodePointer& node) { + qDebug() << "asking child" << node->getUUID() << "to exit."; + node->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); + }); } void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); - _childProcesses.append(QPointer(assignmentClient)); - // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(applicationFilePath(), _childArguments); - - // link the child processes' finished slot to our childProcessFinished slot - connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, - SLOT(childProcessFinished(int, QProcess::ExitStatus))); - + qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } -void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { - qDebug("Replacing dead child assignment client with a new one"); - - // remove the old process from our list of child processes - qDebug() << "need to remove" << QPointer(qobject_cast(sender())); - _childProcesses.removeOne(QPointer(qobject_cast(sender()))); - - spawnChildClient(); + + +void AssignmentClientMonitor::checkSpares() { + auto nodeList = DependencyManager::get(); + QUuid aSpareId = ""; + unsigned int spareCount = 0; + + nodeList->removeSilentNodes(); + + nodeList->eachNode([&](const SharedNodePointer& node) { + AssignmentClientChildData *childData = static_cast(node->getLinkedData()); + if (childData->getChildType() == "none") { + spareCount ++; + aSpareId = node->getUUID(); + } + }); + + if (spareCount != 1) { + qDebug() << "spare count is" << spareCount; + } + + if (spareCount < 1) { + spawnChildClient(); + } + + if (spareCount > 1) { + // kill aSpareId + qDebug() << "asking child" << aSpareId << "to exit."; + SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); + childNode->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, childNode); + } } + + +void AssignmentClientMonitor::readPendingDatagrams() { + auto nodeList = DependencyManager::get(); + + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + + while (nodeList->getNodeSocket().hasPendingDatagrams()) { + receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); + nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), + senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); + + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { + QUuid packetUUID = uuidFromPacketHeader(receivedPacket); + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (!matchingNode) { + // The parent only expects to be talking with prorams running on this same machine. + if (senderSockAddr.getAddress() == QHostAddress::LocalHost || + senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { + if (!packetUUID.isNull()) { + matchingNode = DependencyManager::get()->addOrUpdateNode + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); + matchingNode->setLinkedData(childData); + } else { + // tell unknown assignment-client child to exit. + qDebug() << "asking unknown child to exit."; + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } + } + } + + if (matchingNode) { + // update our records about how to reach this child + matchingNode->setLocalSocket(senderSockAddr); + + // push past the packet header + QDataStream packetStream(receivedPacket); + packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); + // decode json + QVariantMap unpackedVariantMap; + packetStream >> unpackedVariantMap; + QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); + + // get child's assignment type out of the decoded json + QString childType = unpackedStatsJSON["assignment_type"].toString(); + AssignmentClientChildData *childData = + static_cast(matchingNode->getLinkedData()); + childData->setChildType(childType); + // note when this child talked + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); + } + } else { + // have the NodeList attempt to handle it + nodeList->processNodeData(senderSockAddr, receivedPacket); + } + } + } +} + + diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 9a7bca9cb3..71ae34bc8c 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -15,25 +15,30 @@ #include #include #include +#include #include +#include "AssignmentClientChildData.h" + extern const char* NUM_FORKS_PARAMETER; + class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: - void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void readPendingDatagrams(); + void checkSpares(); + private: void spawnChildClient(); - QList > _childProcesses; - QStringList _childArguments; + QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 3bf6990a74..81a12526bf 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,34 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" int main(int argc, char* argv[]) { -#ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -#endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); - - int numForks = 0; - - if (numForksString) { - numForks = atoi(numForksString); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - return monitor.exec(); - } else { - AssignmentClient client(argc, argv); - return client.exec(); - } + AssignmentClientApp app(argc, argv); + return 0; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f84722a438..64e0d335b1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -246,19 +246,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - quint16 localPort = nodeList->getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9bcdcbe9a4..f67abdca2b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { pathString += "/" + orientationString; } else { qDebug() << "Cannot add orientation to path without a getter for position." - << "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; + << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat"; } } @@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const { return pathString; } else { qDebug() << "Cannot create address path without a getter for position." - << "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; + << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; return QString(); } } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c8c454ff14..b240f0df9e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } + +void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { + // save our local port to shared memory so that assignment client children know how to talk to this parent + QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); + quint16 localPort = getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } +} + + +bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, + quint16& localPort) { + if (!sharedMem) { + sharedMem = new QSharedMemory(key, this); + + if (!sharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << key; + } + } + + if (sharedMem->isAttached()) { + sharedMem->lock(); + memcpy(&localPort, sharedMem->data(), sizeof(localPort)); + sharedMem->unlock(); + return true; + } + + return false; +} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 72aefdb2b3..02234ee4f7 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -49,6 +50,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; +const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; + +const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -168,6 +174,9 @@ public: return SharedNodePointer(); } + + void putLocalPortIntoSharedMemory(const QString key, QObject* parent); + bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2bf792c6ee..2a38799707 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -149,7 +149,12 @@ QDataStream& operator>>(QDataStream& in, Node& node) { } QDebug operator<<(QDebug debug, const Node &node) { - debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; + debug.nospace() << NodeType::getNodeTypeName(node.getType()); + if (node.getType() == NodeType::Unassigned) { + debug.nospace() << " (1)"; + } else { + debug.nospace() << " (" << node.getType() << ")"; + } debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); return debug.nospace(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f70c2d9b3c..e63f230f6e 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { +qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, destination); +} + +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { + return sendStats(statsObject, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 907fccfcac..1c6de4bb6c 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,6 +47,7 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } + qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..db97e216ee 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; + case PacketTypeStopNode: + return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..32f33c01d9 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - UNUSED_10, + PacketTypeStopNode, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; From eab09eaf2885de695dc9780f95c63d916085f3b4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 17:15:58 -0800 Subject: [PATCH 206/341] removed extra debugging --- interface/src/Application.cpp | 14 ++-------- libraries/script-engine/src/ScriptEngine.cpp | 27 ++++++-------------- 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 537d3d2a75..390b42eaa7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3567,11 +3567,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow) { - qDebug() << "Application::loadScript() ---- BEGIN ---- Script:" << scriptFilename; - if (isAboutToQuit()) { - qDebug() << "Requests to load scripts while quitting are ignored. Script:" << scriptFilename; - qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; return NULL; } @@ -3580,8 +3576,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { - qDebug() << "Application::loadScript() from _scriptEnginesHash[scriptURLString].... Script:" << scriptFilename; - qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; return _scriptEnginesHash[scriptURLString]; } @@ -3600,7 +3594,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); // get the script engine object to load the script at the designated script URL - qDebug() << "Application::loadScript() about to call loadURL() scriptUrl:" << scriptUrl; scriptEngine->loadURL(scriptUrl); } @@ -3609,9 +3602,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser _window->activateWindow(); } - qDebug() << "Application::loadScript() newly created scriptEngine.... Script:" << scriptFilename; - qDebug() << "Application::loadScript() ---- END ---- Script:" << scriptFilename; - return scriptEngine; } @@ -3771,8 +3761,8 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject voxelWalletUUID = QUuid(voxelObject[VOXEL_WALLET_UUID].toString()); } - qDebug() << "Voxel costs are" << satoshisPerVoxel << "per voxel and" << satoshisPerMeterCubed << "per meter cubed"; - qDebug() << "Destination wallet UUID for voxel payments is" << voxelWalletUUID; + qDebug() << "Octree edits costs are" << satoshisPerVoxel << "per octree cell and" << satoshisPerMeterCubed << "per meter cubed"; + qDebug() << "Destination wallet UUID for edit payments is" << voxelWalletUUID; } QString Application::getPreviousScriptLocation() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9a88476e8c..d090fc0ac6 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -117,8 +117,6 @@ bool ScriptEngine::_stoppingAllScripts = false; bool ScriptEngine::_doneRunningThisScript = false; void ScriptEngine::stopAllScripts(QObject* application) { - qDebug() << "ScriptEngine::stopAllScripts() ------- BEGIN -------"; - _allScriptsMutex.lock(); _stoppingAllScripts = true; @@ -148,14 +146,10 @@ void ScriptEngine::stopAllScripts(QObject* application) { scriptEngine->waitTillDoneRunning(); i.remove(); - } else { - qDebug() << "ScriptEngine::stopAllScripts() " << scriptName << " - will be freed on it's own."; } } _stoppingAllScripts = false; _allScriptsMutex.unlock(); - qDebug() << "ScriptEngine::stopAllScripts() _allKnownScriptEngines.count:" << _allKnownScriptEngines.count(); - qDebug() << "ScriptEngine::stopAllScripts() ------- DONE -------"; } @@ -693,8 +687,7 @@ QObject* ScriptEngine::setupTimerWithInterval(const QScriptValue& function, int QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) { if (_stoppingAllScripts) { - qDebug() << "Script.setInterval() while shutting down is ignored..."; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + qDebug() << "Script.setInterval() while shutting down is ignored... parent script:" << getFilename(); return NULL; // bail early } @@ -703,8 +696,7 @@ QObject* ScriptEngine::setInterval(const QScriptValue& function, int intervalMS) QObject* ScriptEngine::setTimeout(const QScriptValue& function, int timeoutMS) { if (_stoppingAllScripts) { - qDebug() << "Script.setTimeout() while shutting down is ignored..."; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + qDebug() << "Script.setTimeout() while shutting down is ignored... parent script:" << getFilename(); return NULL; // bail early } @@ -754,9 +746,8 @@ void ScriptEngine::print(const QString& message) { // all of the files have finished loading. void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callback) { if (_stoppingAllScripts) { - qDebug() << "Script.include() while shutting down is ignored..."; - qDebug() << " includeFiles:" << includeFiles; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + qDebug() << "Script.include() while shutting down is ignored..." + << "includeFiles:" << includeFiles << "parent script:" << getFilename(); return; // bail early } QList urls; @@ -799,9 +790,8 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { if (_stoppingAllScripts) { - qDebug() << "Script.include() while shutting down is ignored..."; - qDebug() << " includeFile:" << includeFile; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + qDebug() << "Script.include() while shutting down is ignored... " + << "includeFile:" << includeFile << "parent script:" << getFilename(); return; // bail early } @@ -815,9 +805,8 @@ void ScriptEngine::include(const QString& includeFile, QScriptValue callback) { // the Application or other context will connect to in order to know to actually load the script void ScriptEngine::load(const QString& loadFile) { if (_stoppingAllScripts) { - qDebug() << "Script.load() while shutting down is ignored..."; - qDebug() << " loadFile:" << loadFile; - qDebug() << " parent script:" << getFilename() << "[" << this << "]"; + qDebug() << "Script.load() while shutting down is ignored... " + << "loadFile:" << loadFile << "parent script:" << getFilename(); return; // bail early } From 0456cb298f35070346e9d9572b9d786f7bda0bac Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 24 Feb 2015 17:16:00 -0800 Subject: [PATCH 207/341] lower threshold for ignoring rotation updates one hundred fold smaller --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 15d46603b5..d6a3aab970 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1002,7 +1002,7 @@ void EntityItem::computeShapeInfo(ShapeInfo& info) const { } const float MIN_POSITION_DELTA = 0.0001f; -const float MIN_ALIGNMENT_DOT = 0.9999f; +const float MIN_ALIGNMENT_DOT = 0.999999f; const float MIN_VELOCITY_DELTA = 0.01f; const float MIN_DAMPING_DELTA = 0.001f; const float MIN_GRAVITY_DELTA = 0.001f; From 310654831c6f663e5745a6f66f7642ebeb3dac9e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 17:34:19 -0800 Subject: [PATCH 208/341] clean up comments remove dead code --- interface/src/Application.cpp | 6 ++--- .../src/EntityTreeRenderer.cpp | 14 ++++++------ libraries/script-engine/src/ScriptEngine.cpp | 22 +++++++++++++++---- libraries/script-engine/src/ScriptEngine.h | 1 - 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 390b42eaa7..d3161ebf51 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3541,6 +3541,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance()); #endif + // TODO: Consider moving some of this functionality into the ScriptEngine class instead. It seems wrong that this + // work is being done in the Application class when really these dependencies are more related to the ScriptEngine's + // implementation QThread* workerThread = new QThread(this); QString scriptEngineName = QString("Script Thread:") + scriptEngine->getFilename(); workerThread->setObjectName(scriptEngineName); @@ -3552,9 +3555,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri connect(scriptEngine, SIGNAL(doneRunning()), scriptEngine, SLOT(deleteLater())); connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); - // when the application is about to quit, stop our script engine so it unwinds properly - //connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); - auto nodeList = DependencyManager::get(); connect(nodeList.data(), &NodeList::nodeKilled, scriptEngine, &ScriptEngine::nodeKilled); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 8648cea285..70e1054c39 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -59,14 +59,14 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf } EntityTreeRenderer::~EntityTreeRenderer() { - // NOTE: we don't need to delete _entitiesScriptEngine because it's owned by the application and gets cleaned up - // automatically but we do need to delete our sandbox script engine. + // NOTE: we don't need to delete _entitiesScriptEngine because it is registered with the application and has a + // signal tied to call it's deleteLater on doneRunning if (_sandboxScriptEngine) { - // NOTE: is it possible this is a problem? I think that we hook the script engine object up to a deleteLater() - // call inside of registerScriptEngineWithApplicationServices() but do we not call that for _sandboxScriptEngine??? - // this _sandboxScriptEngine implementation is confusing and potentially error prone because it's not a full fledged - // ScriptEngine that has been fully connected. We did this so that scripts that were ill-formed could be evaluated - // but not execute against the application. + // TODO: consider reworking how _sandboxScriptEngine is managed. It's treated differently than _entitiesScriptEngine + // because we don't call registerScriptEngineWithApplicationServices() for it. This implementation is confusing and + // potentially error prone because it's not a full fledged ScriptEngine that has been fully connected to the + // application. We did this so that scripts that were ill-formed could be evaluated but not execute against the + // application services. But this means it's shutdown behavior is different from other ScriptEngines delete _sandboxScriptEngine; _sandboxScriptEngine = NULL; } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d090fc0ac6..b41331450b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -135,16 +135,31 @@ void ScriptEngine::stopAllScripts(QObject* application) { // complete. After that we can handle the stop process appropriately if (scriptEngine->evaluatePending()) { while (scriptEngine->evaluatePending()) { + + // This event loop allows any started, but not yet finished evaluate() calls to complete + // we need to let these complete so that we can be guaranteed that the script engine isn't + // in a partially setup state, which can confuse our shutdown unwinding. QEventLoop loop; QObject::connect(scriptEngine, &ScriptEngine::evaluationFinished, &loop, &QEventLoop::quit); loop.exec(); } } + // We disconnect any script engine signals from the application because we don't want to do any + // extra stopScript/loadScript processing that the Application normally does when scripts start + // and stop. We can safely short circuit this because we know we're in the "quitting" process scriptEngine->disconnect(application); + + // Calling stop on the script engine will set it's internal _isFinished state to true, and result + // in the ScriptEngine gracefully ending it's run() method. scriptEngine->stop(); + // We need to wait for the engine to be done running before we proceed, because we don't + // want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing + // any application state after we leave this stopAllScripts() method scriptEngine->waitTillDoneRunning(); + + // If the script is stopped, we can remove it from our set i.remove(); } } @@ -156,10 +171,11 @@ void ScriptEngine::stopAllScripts(QObject* application) { void ScriptEngine::waitTillDoneRunning() { QString scriptName = getFilename(); + // If the script never started running or finished running before we got here, we don't need to wait for it if (_isRunning) { - _doneRunningThisScript = false; - _isWaitingForDoneRunning = true; + _doneRunningThisScript = false; // NOTE: this is static, we serialize our waiting for scripts to finish + // What can we do here??? // we will be calling this on the main Application thread, inside of stopAllScripts() // we want the application thread to continue to process events, because the script will @@ -178,8 +194,6 @@ void ScriptEngine::waitTillDoneRunning() { break; } } - - _isWaitingForDoneRunning = false; } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 51cacd5e58..154fdb88e3 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -136,7 +136,6 @@ protected: bool _isFinished; bool _isRunning; int _evaluatesPending = 0; - bool _isWaitingForDoneRunning = false; bool _isInitialized; bool _isAvatar; QTimer* _avatarIdentityTimer; From 7a95ed2baae9132a695fd4747950169a46911a92 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 24 Feb 2015 17:38:20 -0800 Subject: [PATCH 209/341] Scale and clamp DDE blendshape coefficients --- interface/src/devices/DdeFaceTracker.cpp | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 4026b581d7..b21334e387 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -183,53 +183,59 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // less than this. // Eye blendshapes - static const float RELAXED_EYE_VALUE = 0.1f; + static const float RELAXED_EYE_VALUE = 0.2f; + static const float EYE_OPEN_SCALE = 4.0f; + static const float EYE_BLINK_SCALE = 2.0f; float leftEye = packet.expressions[1] - RELAXED_EYE_VALUE; float rightEye = packet.expressions[0] - RELAXED_EYE_VALUE; if (leftEye > 0.0f) { - _blendshapeCoefficients[_leftBlinkIndex] = leftEye; + _blendshapeCoefficients[_leftBlinkIndex] = glm::clamp(EYE_BLINK_SCALE * leftEye, 0.0f, 1.0f); _blendshapeCoefficients[_leftEyeOpenIndex] = 0.0f; } else { _blendshapeCoefficients[_leftBlinkIndex] = 0.0f; - _blendshapeCoefficients[_leftEyeOpenIndex] = -leftEye; + _blendshapeCoefficients[_leftEyeOpenIndex] = glm::clamp(EYE_OPEN_SCALE * -leftEye, 0.0f, 1.0f); } if (rightEye > 0.0f) { - _blendshapeCoefficients[_rightBlinkIndex] = rightEye; + _blendshapeCoefficients[_rightBlinkIndex] = glm::clamp(EYE_BLINK_SCALE * rightEye, 0.0f, 1.0f); _blendshapeCoefficients[_rightEyeOpenIndex] = 0.0f; } else { _blendshapeCoefficients[_rightBlinkIndex] = 0.0f; - _blendshapeCoefficients[_rightEyeOpenIndex] = -rightEye; + _blendshapeCoefficients[_rightEyeOpenIndex] = glm::clamp(EYE_OPEN_SCALE * -rightEye, 0.0f, 1.0f); } // Eyebrow blendshapes + static const float BROW_UP_SCALE = 3.0f; + static const float BROW_DOWN_SCALE = 3.0f; float browCenter = packet.expressions[17]; float browDelta = packet.expressions[24] - packet.expressions[23]; float browLeft = browCenter - browDelta; float browRight = browCenter + browDelta; if (browLeft > 0) { - _blendshapeCoefficients[_browUpLeftIndex] = browLeft; + _blendshapeCoefficients[_browUpLeftIndex] = glm::clamp(BROW_UP_SCALE * browLeft, 0.0f, 1.0f); _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; } else { _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; - _blendshapeCoefficients[_browDownLeftIndex] = -browLeft; + _blendshapeCoefficients[_browDownLeftIndex] = glm::clamp(BROW_DOWN_SCALE * -browLeft, 0.0f, 1.0f); } if (browRight > 0) { - _blendshapeCoefficients[_browUpRightIndex] = browRight; + _blendshapeCoefficients[_browUpRightIndex] = glm::clamp(BROW_UP_SCALE * browRight, 0.0f, 1.0f); _blendshapeCoefficients[_browDownRightIndex] = 0.0f; } else { _blendshapeCoefficients[_browUpRightIndex] = 0.0f; - _blendshapeCoefficients[_browDownRightIndex] = -browRight; + _blendshapeCoefficients[_browDownRightIndex] = glm::clamp(BROW_DOWN_SCALE * -browRight, 0.0f, 1.0f); } - if (browLeft + browRight > 0) { - _blendshapeCoefficients[_browUpCenterIndex] = (browLeft + browRight) / 2.0f; + if (browCenter > 0) { + _blendshapeCoefficients[_browUpCenterIndex] = glm::clamp(BROW_UP_SCALE * browCenter, 0.0f, 1.0f); } else { _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; } // Mouth blendshapes - _blendshapeCoefficients[_jawOpenIndex] = packet.expressions[21]; - _blendshapeCoefficients[_mouthSmileLeftIndex] = packet.expressions[24]; - _blendshapeCoefficients[_mouthSmileRightIndex] = packet.expressions[23]; + static const float JAW_OPEN_SCALE = 1.4f; + static const float SMILE_SCALE = 2.0f; + _blendshapeCoefficients[_jawOpenIndex] = JAW_OPEN_SCALE * packet.expressions[21]; + _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(SMILE_SCALE * packet.expressions[24], 0.0f, 1.0f); + _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(SMILE_SCALE * packet.expressions[23], 0.0f, 1.0f); } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; From 5c5ffc07ab4830518735f159d9388c74412dadeb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 24 Feb 2015 17:43:08 -0800 Subject: [PATCH 210/341] allow client count to drift as needed if the user doesn't specify --min or --max --- .../src/AssignmentClientMonitor.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 0f8e7adc17..a3eb5170d5 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -133,17 +133,23 @@ void AssignmentClientMonitor::checkSpares() { } }); - if (spareCount < 1 && totalCount < _maxAssignmentClientForks) { - spawnChildClient(); + // Spawn or kill children, as needed. If --min or --max weren't specified, allow the child count + // to drift up or down as far as needed. + if (spareCount < 1) { + if (!_maxAssignmentClientForks || totalCount < _maxAssignmentClientForks) { + spawnChildClient(); + } } - if (spareCount > 1 && totalCount > _minAssignmentClientForks) { - // kill aSpareId - qDebug() << "asking child" << aSpareId << "to exit."; - SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); - childNode->activateLocalSocket(); - QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); - nodeList->writeUnverifiedDatagram(diePacket, childNode); + if (spareCount > 1) { + if (!_minAssignmentClientForks || totalCount > _minAssignmentClientForks) { + // kill aSpareId + qDebug() << "asking child" << aSpareId << "to exit."; + SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId); + childNode->activateLocalSocket(); + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, childNode); + } } } From f1017f8a5d56cbaab111f7609623163b0eb0b69f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Feb 2015 17:45:22 -0800 Subject: [PATCH 211/341] simplify waitTillDoneRunning --- libraries/script-engine/src/ScriptEngine.cpp | 21 ++++++-------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b41331450b..d201c1568c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -176,23 +176,14 @@ void ScriptEngine::waitTillDoneRunning() { _doneRunningThisScript = false; // NOTE: this is static, we serialize our waiting for scripts to finish - // What can we do here??? - // we will be calling this on the main Application thread, inside of stopAllScripts() - // we want the application thread to continue to process events, because the script will - // likely need to marshall messages across to the main thread. - while (!_doneRunningThisScript && _isRunning) { + // NOTE: waitTillDoneRunning() will be called on the main Application thread, inside of stopAllScripts() + // we want the application thread to continue to process events, because the scripts will likely need to + // marshall messages across to the main thread. For example if they access Settings or Meny in any of their + // shutdown code. + while (!_doneRunningThisScript) { - // and run a QEventLoop??? - QEventLoop loop; - QObject::connect(this, &ScriptEngine::doneRunning, &loop, &QEventLoop::quit); - loop.exec(); - - // process events + // process events for the main application thread, allowing invokeMethod calls to pass between threads QCoreApplication::processEvents(); - - if (_doneRunningThisScript) { - break; - } } } } From c15c549881c8e6c5aaace851a37142d361b4effd Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Wed, 25 Feb 2015 07:47:00 +0530 Subject: [PATCH 212/341] Code formatting --- tools/vhacd/src/VHACDUtil.cpp | 29 ++++++++++------------------- tools/vhacd/src/VHACDUtil.h | 3 +-- tools/vhacd/src/main.cpp | 24 ++++++++---------------- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index bfcdb74634..dcfd7e447f 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -9,13 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include #include "VHACDUtil.h" //Read all the meshes from provided FBX file -bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results) -{ +bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results){ // open the fbx file QFile fbx(filename); @@ -29,15 +28,13 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re //results->meshCount = geometry.meshes.count(); int count = 0; - foreach(FBXMesh mesh, geometry.meshes) - { + foreach(FBXMesh mesh, geometry.meshes) { //get vertices for each mesh QVector vertices = mesh.vertices; //get the triangle indices for each mesh QVector triangles; - foreach(FBXMeshPart part, mesh.parts) - { + foreach(FBXMeshPart part, mesh.parts) { QVector indices = part.triangleIndices; triangles += indices; } @@ -54,15 +51,13 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re return true; } -bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const -{ +bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const{ VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); int meshCount = meshes->meshCount; int count = 0; std::cout << "Performing V-HACD computation on " << meshCount <<" meshes ..... " << std::endl; - for (int i = 0; i < meshCount; i++) - { + for (int i = 0; i < meshCount; i++){ std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); @@ -71,8 +66,7 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD std::cout << "Mesh " << i + 1 << " : "; // compute approximate convex decomposition bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, nTriangles, params); - if (!res) - { + if (!res){ std::cout << "V-HACD computation failed for Mesh : " << i + 1 << std::endl; continue; } @@ -84,8 +78,7 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD //get all the convex hulls for this mesh QVector convexHulls; - for (unsigned int j = 0; j < nConvexHulls; j++) - { + for (unsigned int j = 0; j < nConvexHulls; j++){ VHACD::IVHACD::ConvexHull hull; interfaceVHACD->GetConvexHull(j, hull); convexHulls.append(hull); @@ -105,14 +98,12 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD return false; } -vhacd::VHACDUtil:: ~VHACDUtil() -{ +vhacd::VHACDUtil:: ~VHACDUtil(){ //nothing to be cleaned } //ProgressClaback implementation -void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation) -{ +void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation){ int progress = (int)(overallProgress + 0.5); if (progress < 10) diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h index a9df5d7f2a..aaabcdf904 100644 --- a/tools/vhacd/src/VHACDUtil.h +++ b/tools/vhacd/src/VHACDUtil.h @@ -42,8 +42,7 @@ namespace vhacd{ ~VHACDUtil(); }; - class ProgressCallback : public VHACD::IVHACD::IUserCallback - { + class ProgressCallback : public VHACD::IVHACD::IUserCallback{ public: ProgressCallback(void); ~ProgressCallback(); diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp index 55a152c179..a80a57bb3e 100644 --- a/tools/vhacd/src/main.cpp +++ b/tools/vhacd/src/main.cpp @@ -19,8 +19,7 @@ using namespace std; using namespace VHACD; -int main(int argc, char * argv[]) -{ +int main(int argc, char * argv[]){ vector triangles; // array of indexes vector points; // array of coordinates vhacd::VHACDUtil vUtil; @@ -44,34 +43,29 @@ int main(int argc, char * argv[]) params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls // load the mesh - if (!vUtil.loadFBX(fname, &fbx)) - { + if (!vUtil.loadFBX(fname, &fbx)){ cout << "Error in opening FBX file...."; return 1; } - if (!vUtil.computeVHACD(&fbx, params, &results)) - { + if (!vUtil.computeVHACD(&fbx, params, &results)){ cout << "Compute Failed..."; return 1; } int totalVertices = 0; - for (int i = 0; i < fbx.meshCount; i++) - { + for (int i = 0; i < fbx.meshCount; i++){ totalVertices += fbx.perMeshVertices.at(i).count(); } int totalTriangles = 0; - for (int i = 0; i < fbx.meshCount; i++) - { + for (int i = 0; i < fbx.meshCount; i++){ totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); } int totalHulls = 0; QVector hullCounts = results.convexHullsCountList; - for (int i = 0; i < results.meshCount; i++) - { + for (int i = 0; i < results.meshCount; i++){ totalHulls += hullCounts.at(i); } cout << endl << "Summary of V-HACD Computation..................." << endl; @@ -82,14 +76,12 @@ int main(int argc, char * argv[]) cout << "Total Triangles : " << totalTriangles << endl; cout << "Total Convex Hulls : " << totalHulls << endl; cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); cout << "\t" << "Number Of Hulls : " << chList.count() << endl; - for (int j = 0; j < results.convexHullList.at(i).count(); j++) - { + for (int j = 0; j < results.convexHullList.at(i).count(); j++){ cout << "\tHUll : " << j + 1 << endl; cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; From b0ffaaa8b7255a505221033dd2b52a6e880ef262 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 24 Feb 2015 18:53:35 -0800 Subject: [PATCH 213/341] Smooth DDE blendshape coefficients a little --- interface/src/devices/DdeFaceTracker.cpp | 31 ++++++++++++++++-------- interface/src/devices/DdeFaceTracker.h | 5 ++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index b21334e387..cd893d3709 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -65,9 +65,12 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : _mouthSmileRightIndex(29), _jawOpenIndex(21), _host(host), - _port(port) + _port(port), + _previousTranslation(glm::vec3()), + _previousRotation(glm::quat()) { _blendshapeCoefficients.resize(NUM_EXPRESSION); + _previousExpressions.resize(NUM_EXPRESSION); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); @@ -173,21 +176,23 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { translation -= _referenceTranslation; translation /= LEAN_DAMPING_FACTOR; translation.x *= -1; - _headTranslation = translation; + _headTranslation = (translation + _previousTranslation) / 2.0f; + _previousTranslation = translation; // Compute relative rotation rotation = glm::inverse(_referenceRotation) * rotation; - _headRotation = rotation; + _headRotation = (rotation + _previousRotation) / 2.0f; + _previousRotation = rotation; // The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much - // less than this. + // less than this.packet.expressions[1] // Eye blendshapes static const float RELAXED_EYE_VALUE = 0.2f; static const float EYE_OPEN_SCALE = 4.0f; - static const float EYE_BLINK_SCALE = 2.0f; - float leftEye = packet.expressions[1] - RELAXED_EYE_VALUE; - float rightEye = packet.expressions[0] - RELAXED_EYE_VALUE; + static const float EYE_BLINK_SCALE = 2.5f; + float leftEye = (packet.expressions[1] + _previousExpressions[1]) / 2.0f - RELAXED_EYE_VALUE; + float rightEye = (packet.expressions[0] + _previousExpressions[0]) / 2.0f - RELAXED_EYE_VALUE; if (leftEye > 0.0f) { _blendshapeCoefficients[_leftBlinkIndex] = glm::clamp(EYE_BLINK_SCALE * leftEye, 0.0f, 1.0f); _blendshapeCoefficients[_leftEyeOpenIndex] = 0.0f; @@ -202,12 +207,15 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _blendshapeCoefficients[_rightBlinkIndex] = 0.0f; _blendshapeCoefficients[_rightEyeOpenIndex] = glm::clamp(EYE_OPEN_SCALE * -rightEye, 0.0f, 1.0f); } + _previousExpressions[1] = packet.expressions[1]; + _previousExpressions[0] = packet.expressions[0]; // Eyebrow blendshapes static const float BROW_UP_SCALE = 3.0f; static const float BROW_DOWN_SCALE = 3.0f; - float browCenter = packet.expressions[17]; - float browDelta = packet.expressions[24] - packet.expressions[23]; + float browCenter = (packet.expressions[17] + _previousExpressions[17]) / 2.0f; + float browDelta = (packet.expressions[24] + _previousExpressions[24] + - packet.expressions[23] - _previousExpressions[23]) / 2.0f; float browLeft = browCenter - browDelta; float browRight = browCenter + browDelta; if (browLeft > 0) { @@ -229,10 +237,13 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { } else { _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; } + _previousExpressions[17] = packet.expressions[17]; + _previousExpressions[24] = packet.expressions[24]; + _previousExpressions[23] = packet.expressions[23]; // Mouth blendshapes static const float JAW_OPEN_SCALE = 1.4f; - static const float SMILE_SCALE = 2.0f; + static const float SMILE_SCALE = 2.5f; _blendshapeCoefficients[_jawOpenIndex] = JAW_OPEN_SCALE * packet.expressions[21]; _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(SMILE_SCALE * packet.expressions[24], 0.0f, 1.0f); _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(SMILE_SCALE * packet.expressions[23], 0.0f, 1.0f); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 162e2b145f..ba22d31fd1 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -90,6 +90,11 @@ private: int _mouthSmileRightIndex; int _jawOpenIndex; + + // Previous values for simple smoothing + glm::vec3 _previousTranslation; + glm::quat _previousRotation; + QVector _previousExpressions; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file From 9a153a6506cb6a70da655176daaf58a36261b595 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Wed, 25 Feb 2015 08:36:58 +0530 Subject: [PATCH 214/341] Time measurement Used c++11 chrono class to measure elapsed time. --- tools/vhacd/src/VHACDUtil.h | 2 +- tools/vhacd/src/main.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h index aaabcdf904..036d4ce526 100644 --- a/tools/vhacd/src/VHACDUtil.h +++ b/tools/vhacd/src/VHACDUtil.h @@ -16,7 +16,7 @@ #include #include #include - +#include //c++11 feature #include #include #include diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp index a80a57bb3e..31866a7cfc 100644 --- a/tools/vhacd/src/main.cpp +++ b/tools/vhacd/src/main.cpp @@ -27,9 +27,14 @@ int main(int argc, char * argv[]){ vhacd::ComputeResults results; // results after computing vhacd VHACD::IVHACD::Parameters params; vhacd::ProgressCallback pCallBack; - - QString fname = "F:/models/ship/Sample_Ship.fbx"; + string filename(argv[1]); + if (filename.empty()){ + cout << "please provide a FBX file as argument\n "; + return 1; + } + + QString fname = QString::fromStdString(filename); //set parameters for V-HACD params.m_callback = &pCallBack; //progress callback @@ -43,15 +48,23 @@ int main(int argc, char * argv[]){ params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls // load the mesh + + auto begin = std::chrono::high_resolution_clock::now(); if (!vUtil.loadFBX(fname, &fbx)){ cout << "Error in opening FBX file...."; return 1; } + auto end = std::chrono::high_resolution_clock::now(); + auto loadDuration = std::chrono::duration_cast(end - begin).count(); + //perform vhacd computation + begin = std::chrono::high_resolution_clock::now(); if (!vUtil.computeVHACD(&fbx, params, &results)){ cout << "Compute Failed..."; return 1; } + end = std::chrono::high_resolution_clock::now(); + auto computeDuration = std::chrono::duration_cast(end - begin).count(); int totalVertices = 0; for (int i = 0; i < fbx.meshCount; i++){ @@ -75,6 +88,8 @@ int main(int argc, char * argv[]){ cout << "Total vertices : " << totalVertices << endl; cout << "Total Triangles : " << totalTriangles << endl; cout << "Total Convex Hulls : " << totalHulls << endl; + cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl; + cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl; cout << endl << "Summary per convex hull ........................" << endl < Date: Wed, 25 Feb 2015 08:45:00 +0530 Subject: [PATCH 215/341] cmake changes for building on linux --- cmake/modules/FindVHACD.cmake | 4 ++-- tools/vhacd/CMakeLists.txt | 14 +++++++++++++- tools/vhacd/src/VHACDUtil.cpp | 4 ++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindVHACD.cmake b/cmake/modules/FindVHACD.cmake index d84ab30dff..f7eee44737 100644 --- a/cmake/modules/FindVHACD.cmake +++ b/cmake/modules/FindVHACD.cmake @@ -45,11 +45,11 @@ endmacro() find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS} $ENV{VHACD_ROOT_DIR}) -_FIND_VHACD_LIBRARY(VHACD VHACD_LIB) +_FIND_VHACD_LIBRARY(VHACD libVHACD.a) set(VHACD_LIBRARIES ${VHACD_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(VHACD "Could NOT find VHACD, try to set the path to VHACD root folder in the system variable VHACD_ROOT_DIR or create a directory vhacd in HIFI_LIB_DIR and paste the necessary files there" VHACD_INCLUDE_DIRS VHACD_LIBRARIES) -mark_as_advanced(VHACD_INCLUDE_DIRS VHACD_LIBRARIES VHACD_SEARCH_DIRS) \ No newline at end of file +mark_as_advanced(VHACD_INCLUDE_DIRS VHACD_LIBRARIES VHACD_SEARCH_DIRS) diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt index ee82cd599d..51e15c8239 100644 --- a/tools/vhacd/CMakeLists.txt +++ b/tools/vhacd/CMakeLists.txt @@ -6,8 +6,20 @@ find_package(VHACD REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) +if(NOT WIN32) + find_package( Threads) + target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) + + include(FindOpenMP) + if(OPENMP_FOUND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + endif() +endif() + add_dependency_external_project(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -include_dependency_includes() \ No newline at end of file +include_dependency_includes() diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index bfcdb74634..71ee2740c1 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +#include #include "VHACDUtil.h" @@ -127,4 +127,4 @@ void vhacd::ProgressCallback::Update(const double overallProgress, const double } vhacd::ProgressCallback::ProgressCallback(void){} -vhacd::ProgressCallback::~ProgressCallback(){} \ No newline at end of file +vhacd::ProgressCallback::~ProgressCallback(){} From ed09b619d14a50de8c3c741851dad969e80f92e2 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Wed, 25 Feb 2015 09:12:19 +0530 Subject: [PATCH 216/341] OS check check OS for different filenames --- cmake/modules/FindVHACD.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/modules/FindVHACD.cmake b/cmake/modules/FindVHACD.cmake index f7eee44737..03e30b41d4 100644 --- a/cmake/modules/FindVHACD.cmake +++ b/cmake/modules/FindVHACD.cmake @@ -45,7 +45,11 @@ endmacro() find_path(VHACD_INCLUDE_DIRS VHACD.h PATH_SUFFIXES include HINTS ${VHACD_SEARCH_DIRS} $ENV{VHACD_ROOT_DIR}) +if(NOT WIN32) _FIND_VHACD_LIBRARY(VHACD libVHACD.a) +else() +_FIND_VHACD_LIBRARY(VHACD VHACD_LIB) +endif() set(VHACD_LIBRARIES ${VHACD_LIBRARY}) include(FindPackageHandleStandardArgs) From e87df0017a0769ed6d8a4a86ac59cc9c7814e1d3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 08:26:54 -0800 Subject: [PATCH 217/341] code review feedback --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 70e1054c39..46f9ff6f55 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -890,8 +890,8 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) { if (_tree && !_shuttingDown) { checkAndCallUnload(entityID); + checkAndCallPreload(entityID); } - checkAndCallPreload(entityID); } void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID) { From 0ce49888ff70885e200a50161a5b513713c276f0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 25 Feb 2015 09:20:34 -0800 Subject: [PATCH 218/341] AssignmentClientApp is QCoreApplication, other classes aren't. If --min is set and all the assignment clients exit (probably due to domain server restarting), respawn until --min is statisfied. --- assignment-client/src/AssignmentClient.cpp | 9 ++------- assignment-client/src/AssignmentClient.h | 4 ++-- assignment-client/src/AssignmentClientApp.cpp | 16 ++++++++++++---- .../src/AssignmentClientMonitor.cpp | 8 +++----- assignment-client/src/AssignmentClientMonitor.h | 9 ++++----- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index cb2da51031..38f5c7cc55 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -39,19 +39,14 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv, - Assignment::Type requestAssignmentType, QString assignmentPool, QUuid walletUUID, +AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort) : - QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _localASPortSharedMem(NULL), _localACMPortSharedMem(NULL) { LogUtils::init(); - setOrganizationName("High Fidelity"); - setOrganizationDomain("highfidelity.io"); - setApplicationName("assignment-client"); QSettings::setDefaultFormat(QSettings::IniFormat); // create a NodeList as an unassigned client @@ -124,7 +119,7 @@ void AssignmentClient::stopAssignmentClient() { qDebug() << "Exiting."; _requestTimer.stop(); _statsTimerACM.stop(); - quit(); + QCoreApplication::quit(); } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 67a5dc89a7..d1d93c78dc 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -18,11 +18,11 @@ class QSharedMemory; -class AssignmentClient : public QCoreApplication { +class AssignmentClient : public QObject { Q_OBJECT public: - AssignmentClient(int &argc, char **argv, Assignment::Type requestAssignmentType, QString assignmentPool, + AssignmentClient(Assignment::Type requestAssignmentType, QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 7f174f0833..26b6b8675a 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -28,6 +28,10 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setvbuf(stdout, NULL, _IOLBF, 0); # endif + setOrganizationName("High Fidelity"); + setOrganizationDomain("highfidelity.io"); + setApplicationName("assignment-client"); + // use the verbose message handler in Logging qInstallMessageHandler(LogHandler::verboseMessageHandler); @@ -97,6 +101,10 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : maxForks = parser.value(maxChildsOption).toInt(); } + if (!numForks && minForks) { + // if the user specified --min but not -n, set -n to --min + numForks = minForks; + } Assignment::Type requestAssignmentType = Assignment::AllTypes; if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) { @@ -165,12 +173,12 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : if (numForks || minForks || maxForks) { - AssignmentClientMonitor monitor(argc, argv, numForks, minForks, maxForks, assignmentPool, + AssignmentClientMonitor monitor(numForks, minForks, maxForks, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); - monitor.exec(); + exec(); } else { - AssignmentClient client(argc, argv, requestAssignmentType, assignmentPool, + AssignmentClient client(requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); - client.exec(); + exec(); } } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index a3eb5170d5..29fda05ee1 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -25,13 +25,11 @@ const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, - const unsigned int numAssignmentClientForks, +AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmentClientForks, const unsigned int minAssignmentClientForks, const unsigned int maxAssignmentClientForks, QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort) : - QCoreApplication(argc, argv), _numAssignmentClientForks(numAssignmentClientForks), _minAssignmentClientForks(minAssignmentClientForks), _maxAssignmentClientForks(maxAssignmentClientForks), @@ -109,7 +107,7 @@ void AssignmentClientMonitor::spawnChildClient() { // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - assignmentClient->start(applicationFilePath(), _childArguments); + assignmentClient->start(QCoreApplication::applicationFilePath(), _childArguments); qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } @@ -135,7 +133,7 @@ void AssignmentClientMonitor::checkSpares() { // Spawn or kill children, as needed. If --min or --max weren't specified, allow the child count // to drift up or down as far as needed. - if (spareCount < 1) { + if (spareCount < 1 || totalCount < _minAssignmentClientForks) { if (!_maxAssignmentClientForks || totalCount < _maxAssignmentClientForks) { spawnChildClient(); } diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index e40a10014b..dc88bfcd95 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -24,13 +24,12 @@ extern const char* NUM_FORKS_PARAMETER; -class AssignmentClientMonitor : public QCoreApplication { +class AssignmentClientMonitor : public QObject { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks, - const unsigned int minAssignmentClientForks, const unsigned int maxAssignmentClientForks, - QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, - quint16 assignmentServerPort); + AssignmentClientMonitor(const unsigned int numAssignmentClientForks, const unsigned int minAssignmentClientForks, + const unsigned int maxAssignmentClientForks, QString assignmentPool, QUuid walletUUID, + QString assignmentServerHostname, quint16 assignmentServerPort); ~AssignmentClientMonitor(); void stopChildProcesses(); From 14ec9b431e8f0283b08b3b3e535b7f31b7f52b9b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 25 Feb 2015 10:26:44 -0800 Subject: [PATCH 219/341] Update findRayRectangleIntersection to set out variable distance --- libraries/shared/src/GeometryUtil.cpp | 6 +++--- libraries/shared/src/GeometryUtil.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index cf15830a10..13d78ec8b3 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -494,8 +494,8 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len } } -bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions) { +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, + const glm::vec3& position, const glm::vec2& dimensions, float& distance) { RayIntersectionInfo rayInfo; rayInfo._rayStart = origin; rayInfo._rayDirection = direction; @@ -511,7 +511,7 @@ bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& dire bool intersects = plane.findRayIntersection(rayInfo); if (intersects) { - float distance = rayInfo._hitDistance; + distance = rayInfo._hitDistance; glm::vec3 hitPosition = origin + (distance * direction); glm::vec3 localHitPosition = glm::inverse(rotation) * (hitPosition - position); diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index e0de536e97..657a06a604 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -76,8 +76,8 @@ bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& directi bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& start, const glm::vec3& end, float radius, float& distance); -bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, - const glm::quat& rotation, const glm::vec3& position, const glm::vec2& dimensions); +bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, + const glm::vec3& position, const glm::vec2& dimensions, float& distance); bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& v0, const glm::vec3& v1, const glm::vec3& v2, float& distance); From c499352ad8eaded4abe879ec63cfd05c9571042f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 25 Feb 2015 10:27:11 -0800 Subject: [PATCH 220/341] Update billboard and planar overlays to use new findRayRectangleIntersection signature --- interface/src/ui/overlays/BillboardOverlay.cpp | 2 +- interface/src/ui/overlays/Planar3DOverlay.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index a82da0ee5f..88c097575b 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -209,7 +209,7 @@ bool BillboardOverlay::findRayIntersection(const glm::vec3& origin, const glm::v float maxSize = glm::max(width, height); glm::vec2 dimensions = _scale * glm::vec2(width / maxSize, height / maxSize); - return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions); + return findRayRectangleIntersection(origin, direction, rotation, _position, dimensions, distance); } return false; diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 925725d261..aea6585fc4 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -95,5 +95,5 @@ QScriptValue Planar3DOverlay::getProperty(const QString& property) { bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) { - return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions); + return findRayRectangleIntersection(origin, direction, _rotation, _position, _dimensions, distance); } From 660d9ad499ffc372741f281c4e49f1003409c234 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 25 Feb 2015 10:28:45 -0800 Subject: [PATCH 221/341] Make KeyEvent objects equal even if they have differing isAutoRepeat values --- libraries/script-engine/src/KeyEvent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/script-engine/src/KeyEvent.cpp b/libraries/script-engine/src/KeyEvent.cpp index b7564db1b6..febc8fc21f 100644 --- a/libraries/script-engine/src/KeyEvent.cpp +++ b/libraries/script-engine/src/KeyEvent.cpp @@ -121,8 +121,7 @@ bool KeyEvent::operator==(const KeyEvent& other) const { && other.isControl == isControl && other.isMeta == isMeta && other.isAlt == isAlt - && other.isKeypad == isKeypad - && other.isAutoRepeat == isAutoRepeat; + && other.isKeypad == isKeypad; } From fd8240669b52be4e18fff1ce30744e6b4c8a06aa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 10:39:44 -0800 Subject: [PATCH 222/341] fix for windeployqt for executables --- .../CopyDllsBesideWindowsExecutable.cmake | 27 +++++++++++++------ tools/scribe/CMakeLists.txt | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 4f144c4315..61d35d93b1 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -10,6 +10,13 @@ # macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) + + if (NOT ${ARGN}) + set(USES_QT TRUE) + else () + set(USES_QT ${ARGN}) + endif () + if (WIN32) configure_file( @@ -27,14 +34,18 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) - find_program(${WINDEPLOYQT_COMMAND} windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + if (NOT USES_QT) + + find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + + # add a post-build command to call windeployqt to copy Qt plugins + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} --no-libraries $" + ) + + endif () - # add a post-build command to call windeployqt to copy Qt plugins - add_custom_command( - TARGET ${TARGET_NAME} - POST_BUILD - COMMAND SET PATH=%PATH%;${QT_DIR}/bin - COMMAND ${WINDEPLOYQT_COMMAND} --no-libraries --force $ - ) endif () endmacro() \ No newline at end of file diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt index bc07fec230..4196909043 100755 --- a/tools/scribe/CMakeLists.txt +++ b/tools/scribe/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME scribe) setup_hifi_project() -copy_dlls_beside_windows_executable() \ No newline at end of file +copy_dlls_beside_windows_executable(false) \ No newline at end of file From 66ab2ba9f908c489f7448b5959056702bf55adc2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 10:44:02 -0800 Subject: [PATCH 223/341] fix for flipped conditional for dll fixup --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 61d35d93b1..43373d9da0 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -18,7 +18,6 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) endif () if (WIN32) - configure_file( ${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake @@ -34,8 +33,7 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) - if (NOT USES_QT) - + if (USES_QT) find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) # add a post-build command to call windeployqt to copy Qt plugins @@ -46,6 +44,5 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) ) endif () - endif () endmacro() \ No newline at end of file From c5fba3e0ce596e901fe09e851ec1b577cd9efb5b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 25 Feb 2015 10:44:08 -0800 Subject: [PATCH 224/341] Improve mouth resting position and smile --- interface/src/devices/DdeFaceTracker.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index cd893d3709..cd70c1a516 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -242,11 +242,18 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _previousExpressions[23] = packet.expressions[23]; // Mouth blendshapes + static const float JAW_OPEN_THRESHOLD = 0.16f; static const float JAW_OPEN_SCALE = 1.4f; - static const float SMILE_SCALE = 2.5f; - _blendshapeCoefficients[_jawOpenIndex] = JAW_OPEN_SCALE * packet.expressions[21]; - _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(SMILE_SCALE * packet.expressions[24], 0.0f, 1.0f); - _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(SMILE_SCALE * packet.expressions[23], 0.0f, 1.0f); + static const float SMILE_THRESHOLD = 0.18f; + static const float SMILE_SCALE = 1.5f; + float smileLeft = (packet.expressions[24] + _previousExpressions[24]) / 2.0f; + float smileRight = (packet.expressions[23] + _previousExpressions[23]) / 2.0f; + _blendshapeCoefficients[_jawOpenIndex] = glm::clamp(JAW_OPEN_SCALE * (packet.expressions[21] - JAW_OPEN_THRESHOLD), + 0.0f, 1.0f); + _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(SMILE_SCALE * (smileLeft - SMILE_THRESHOLD), 0.0f, 1.0f); + _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(SMILE_SCALE * (smileRight - SMILE_THRESHOLD), 0.0f, 1.0f); + _previousExpressions[24] = packet.expressions[24]; + _previousExpressions[23] = packet.expressions[23]; } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; From 23e172a0a1c73f0ad71231184bb4c77d62594fc7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 25 Feb 2015 10:44:57 -0800 Subject: [PATCH 225/341] Remove attempt at individual eyebrow control --- interface/src/devices/DdeFaceTracker.cpp | 30 ++++++++---------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index cd70c1a516..b973946acb 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -214,32 +214,22 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { static const float BROW_UP_SCALE = 3.0f; static const float BROW_DOWN_SCALE = 3.0f; float browCenter = (packet.expressions[17] + _previousExpressions[17]) / 2.0f; - float browDelta = (packet.expressions[24] + _previousExpressions[24] - - packet.expressions[23] - _previousExpressions[23]) / 2.0f; - float browLeft = browCenter - browDelta; - float browRight = browCenter + browDelta; - if (browLeft > 0) { - _blendshapeCoefficients[_browUpLeftIndex] = glm::clamp(BROW_UP_SCALE * browLeft, 0.0f, 1.0f); + if (browCenter > 0) { + float browUp = glm::clamp(BROW_UP_SCALE * browCenter, 0.0f, 1.0f); + _blendshapeCoefficients[_browUpCenterIndex] = browUp; + _blendshapeCoefficients[_browUpLeftIndex] = browUp; _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; - } else { - _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; - _blendshapeCoefficients[_browDownLeftIndex] = glm::clamp(BROW_DOWN_SCALE * -browLeft, 0.0f, 1.0f); - } - if (browRight > 0) { - _blendshapeCoefficients[_browUpRightIndex] = glm::clamp(BROW_UP_SCALE * browRight, 0.0f, 1.0f); + _blendshapeCoefficients[_browUpRightIndex] = browUp; _blendshapeCoefficients[_browDownRightIndex] = 0.0f; } else { - _blendshapeCoefficients[_browUpRightIndex] = 0.0f; - _blendshapeCoefficients[_browDownRightIndex] = glm::clamp(BROW_DOWN_SCALE * -browRight, 0.0f, 1.0f); - } - if (browCenter > 0) { - _blendshapeCoefficients[_browUpCenterIndex] = glm::clamp(BROW_UP_SCALE * browCenter, 0.0f, 1.0f); - } else { + float browDown = glm::clamp(BROW_DOWN_SCALE * -browCenter, 0.0f, 1.0f); _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; + _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; + _blendshapeCoefficients[_browDownLeftIndex] = browDown; + _blendshapeCoefficients[_browUpRightIndex] = 0.0f; + _blendshapeCoefficients[_browDownRightIndex] = browDown; } _previousExpressions[17] = packet.expressions[17]; - _previousExpressions[24] = packet.expressions[24]; - _previousExpressions[23] = packet.expressions[23]; // Mouth blendshapes static const float JAW_OPEN_THRESHOLD = 0.16f; From e66f12f95873728e773db1be8b46089b6df4735a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 10:56:08 -0800 Subject: [PATCH 226/341] add shutdown short circuiting to datagram processor --- interface/src/Application.cpp | 5 +++-- interface/src/DatagramProcessor.cpp | 4 ++++ interface/src/DatagramProcessor.h | 11 +++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d3161ebf51..eb228f2874 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -534,6 +534,7 @@ void Application::aboutToQuit() { void Application::cleanupBeforeQuit() { + _datagramProcessor.shutdown(); // tell the datagram processor we're shutting down, so it can short circuit _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts @@ -584,8 +585,6 @@ Application::~Application() { _entities.getTree()->setSimulation(NULL); tree->unlock(); - qInstallMessageHandler(NULL); - // ask the datagram processing thread to quit and wait until it is done _nodeThread->quit(); _nodeThread->wait(); @@ -606,6 +605,8 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + + qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages } void Application::initializeGL() { diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 02d3c62765..a491f9444d 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -30,6 +30,10 @@ DatagramProcessor::DatagramProcessor(QObject* parent) : void DatagramProcessor::processDatagrams() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "DatagramProcessor::processDatagrams()"); + + if (_isShuttingDown) { + return; // bail early... we're shutting down. + } HifiSockAddr senderSockAddr; diff --git a/interface/src/DatagramProcessor.h b/interface/src/DatagramProcessor.h index 4ce090e52e..7fc192ee2d 100644 --- a/interface/src/DatagramProcessor.h +++ b/interface/src/DatagramProcessor.h @@ -25,14 +25,17 @@ public: int getOutByteCount() const { return _outByteCount; } void resetCounters() { _inPacketCount = 0; _outPacketCount = 0; _inByteCount = 0; _outByteCount = 0; } + + void shutdown() { _isShuttingDown = true; } public slots: void processDatagrams(); private: - int _inPacketCount; - int _outPacketCount; - int _inByteCount; - int _outByteCount; + int _inPacketCount = 0; + int _outPacketCount = 0; + int _inByteCount = 0; + int _outByteCount = 0; + bool _isShuttingDown = false; }; #endif // hifi_DatagramProcessor_h From 33b0fd24a6a86e4282555da5811aaba8ebf7ba5a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 11:02:05 -0800 Subject: [PATCH 227/341] don't call copy dll step for scribe --- .../CopyDllsBesideWindowsExecutable.cmake | 25 ++++++------------- tools/scribe/CMakeLists.txt | 4 +-- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index 43373d9da0..a97603a6ca 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -11,12 +11,6 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) - if (NOT ${ARGN}) - set(USES_QT TRUE) - else () - set(USES_QT ${ARGN}) - endif () - if (WIN32) configure_file( ${HIFI_CMAKE_DIR}/templates/FixupBundlePostBuild.cmake.in @@ -33,16 +27,13 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) - if (USES_QT) - find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) - - # add a post-build command to call windeployqt to copy Qt plugins - add_custom_command( - TARGET ${TARGET_NAME} - POST_BUILD - COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} --no-libraries $" - ) - - endif () + find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + + # add a post-build command to call windeployqt to copy Qt plugins + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND} --no-libraries $" + ) endif () endmacro() \ No newline at end of file diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt index 4196909043..b71a287e46 100755 --- a/tools/scribe/CMakeLists.txt +++ b/tools/scribe/CMakeLists.txt @@ -1,4 +1,2 @@ set(TARGET_NAME scribe) -setup_hifi_project() - -copy_dlls_beside_windows_executable(false) \ No newline at end of file +setup_hifi_project() \ No newline at end of file From 1a4808857e58873c89b6407ca754ffaa2ea4c984 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 25 Feb 2015 11:30:54 -0800 Subject: [PATCH 228/341] put local domain server's http port into shared memeory --- assignment-client/src/AssignmentClientMonitor.cpp | 3 ++- domain-server/src/DomainServer.cpp | 9 ++++++++- libraries/networking/src/LimitedNodeList.cpp | 3 +-- libraries/networking/src/LimitedNodeList.h | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 29fda05ee1..63b140a701 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -56,7 +56,8 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); - nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); + nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this, + nodeList->getNodeSocket().localPort()); // use QProcess to fork off a process for each of the child assignment clients for (unsigned int i = 0; i < _numAssignmentClientForks; i++) { diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 64e0d335b1..251f7a8702 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -246,7 +246,14 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, nodeList->getNodeSocket().localPort()); + + // store out local http ports in shared memory + quint16 localHttpPort = DOMAIN_SERVER_HTTP_PORT; + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_HTTP_PORT_SMEM_KEY, this, localHttpPort); + quint16 localHttpsPort = DOMAIN_SERVER_HTTPS_PORT; + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY, this, localHttpsPort); + // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b240f0df9e..faa90b79bf 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -670,10 +670,9 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } -void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { +void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent, quint16 localPort) { // save our local port to shared memory so that assignment client children know how to talk to this parent QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); - quint16 localPort = getNodeSocket().localPort(); // attempt to create the shared memory segment if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 02234ee4f7..08f6452fa3 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -50,6 +50,8 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; +const QString DOMAIN_SERVER_LOCAL_HTTP_PORT_SMEM_KEY = "domain-server.local-http-port"; +const QString DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY = "domain-server.local-https-port"; const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; @@ -175,7 +177,7 @@ public: return SharedNodePointer(); } - void putLocalPortIntoSharedMemory(const QString key, QObject* parent); + void putLocalPortIntoSharedMemory(const QString key, QObject* parent, quint16 localPort); bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort); public slots: From 5776df10122322b25bc59f4d9aa527f5eb7bcf1d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 25 Feb 2015 12:07:19 -0800 Subject: [PATCH 229/341] load dynamic obj as inactive when not moving --- libraries/physics/src/EntityMotionState.cpp | 4 ++++ libraries/physics/src/EntityMotionState.h | 26 +++++++++++---------- libraries/physics/src/ObjectMotionState.h | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 4 ++++ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 810bf9a6a8..699b4cc386 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -63,6 +63,10 @@ void EntityMotionState::stepKinematicSimulation(quint64 now) { _entity->simulate(now); } +bool EntityMotionState::isMoving() const { + return _entity->isMoving(); +} + // This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC) diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 5d98e545d9..7214626fc4 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -36,28 +36,30 @@ public: virtual ~EntityMotionState(); /// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem - MotionType computeMotionType() const; + virtual MotionType computeMotionType() const; - void updateKinematicState(uint32_t substep); - void stepKinematicSimulation(quint64 now); + virtual void updateKinematicState(uint32_t substep); + virtual void stepKinematicSimulation(quint64 now); + + virtual bool isMoving() const; // this relays incoming position/rotation to the RigidBody - void getWorldTransform(btTransform& worldTrans) const; + virtual void getWorldTransform(btTransform& worldTrans) const; // this relays outgoing position/rotation to the EntityItem - void setWorldTransform(const btTransform& worldTrans); + virtual void setWorldTransform(const btTransform& worldTrans); // these relay incoming values to the RigidBody - void updateObjectEasy(uint32_t flags, uint32_t frame); - void updateObjectVelocities(); + virtual void updateObjectEasy(uint32_t flags, uint32_t frame); + virtual void updateObjectVelocities(); - void computeShapeInfo(ShapeInfo& shapeInfo); - float computeMass(const ShapeInfo& shapeInfo) const; + virtual void computeShapeInfo(ShapeInfo& shapeInfo); + virtual float computeMass(const ShapeInfo& shapeInfo) const; - void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame); + virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame); - uint32_t getIncomingDirtyFlags() const; - void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); } + virtual uint32_t getIncomingDirtyFlags() const; + virtual void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); } EntityItem* getEntity() const { return _entity; } diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index ceeea219cf..fb402a178d 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -101,6 +101,8 @@ public: void setKinematic(bool kinematic, uint32_t substep); virtual void stepKinematicSimulation(quint64 now) = 0; + virtual bool isMoving() const = 0; + friend class PhysicsEngine; protected: void setRigidBody(btRigidBody* body); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 461d15114c..10c7f42546 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -439,6 +439,10 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec const float DYNAMIC_ANGULAR_VELOCITY_THRESHOLD = 0.087266f; // ~5 deg/sec body->setSleepingThresholds(DYNAMIC_LINEAR_VELOCITY_THRESHOLD, DYNAMIC_ANGULAR_VELOCITY_THRESHOLD); + if (!motionState->isMoving()) { + // try to initialize this object as inactive + body->forceActivationState(ISLAND_SLEEPING); + } break; } case MOTION_TYPE_STATIC: From af341f0ee52d717d8943b4b2d4a727999d2a44d8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 25 Feb 2015 12:11:32 -0800 Subject: [PATCH 230/341] if hifi uri is localhost, extract domain-server port from shared memory --- libraries/networking/src/AddressManager.cpp | 12 ++++++++++-- libraries/networking/src/AddressManager.h | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f67abdca2b..58399a6075 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -34,7 +34,8 @@ AddressManager::AddressManager() : _rootPlaceName(), _rootPlaceID(), _positionGetter(NULL), - _orientationGetter(NULL) + _orientationGetter(NULL), + _localDSPortSharedMem(NULL) { connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress); } @@ -152,8 +153,15 @@ void AddressManager::handleLookupString(const QString& lookupString) { if (!lookupString.startsWith('/')) { const QRegExp HIFI_SCHEME_REGEX = QRegExp(HIFI_URL_SCHEME + ":\\/{1,2}", Qt::CaseInsensitive); sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX); + + quint16 localDomainServerPort = DEFAULT_DOMAIN_SERVER_PORT; + if (sanitizedString == "localhost") { + auto nodeList = DependencyManager::get(); + nodeList->getLocalServerPortFromSharedMemory + (DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localDSPortSharedMem, localDomainServerPort); + } - lookupURL = QUrl(HIFI_URL_SCHEME + "://" + sanitizedString); + lookupURL = QUrl(HIFI_URL_SCHEME + "://" + sanitizedString + ":" + QString::number(localDomainServerPort)); } else { lookupURL = QUrl(lookupString); } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 0c24c12cc9..bfc3ace657 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -13,6 +13,7 @@ #define hifi_AddressManager_h #include +#include #include #include @@ -94,6 +95,8 @@ private: QUuid _rootPlaceID; PositionGetter _positionGetter; OrientationGetter _orientationGetter; + + QSharedMemory* _localDSPortSharedMem; // memory shared with domain server }; -#endif // hifi_AddressManager_h \ No newline at end of file +#endif // hifi_AddressManager_h From a89691fc6652521f03d99c7cb4b6fbf8f7f4f69d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 12:11:35 -0800 Subject: [PATCH 231/341] switch GLCanvas back to being owned by Application --- interface/src/Application.cpp | 77 +++++++++---------- interface/src/Application.h | 13 ++-- interface/src/Camera.cpp | 2 +- interface/src/GLCanvas.h | 18 ++--- interface/src/UIUtil.cpp | 5 +- interface/src/audio/AudioToolBox.cpp | 3 +- interface/src/devices/OculusManager.cpp | 4 +- interface/src/devices/PrioVR.cpp | 2 +- interface/src/devices/SixenseManager.cpp | 2 +- interface/src/devices/TV3DManager.cpp | 4 +- .../ControllerScriptingInterface.cpp | 3 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 30 ++++---- interface/src/ui/MetavoxelEditor.cpp | 2 +- interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/Snapshot.cpp | 3 +- interface/src/ui/Stats.cpp | 8 +- 17 files changed, 93 insertions(+), 87 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eb228f2874..772c314783 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -215,7 +215,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::registerInheritance(); // Set dependencies - auto glCanvas = DependencyManager::set(); + //auto glCanvasGlobal = DependencyManager::set(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); auto geometryCache = DependencyManager::set(); @@ -307,7 +307,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us - auto glCanvas = DependencyManager::get(); auto nodeList = DependencyManager::get(); _myAvatar = DependencyManager::get()->getMyAvatar(); @@ -447,16 +446,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); - _window->setCentralWidget(glCanvas.data()); + _window->setCentralWidget(_glWidget); _window->restoreGeometry(); _window->setVisible(true); - glCanvas->setFocusPolicy(Qt::StrongFocus); - glCanvas->setFocus(); + _glWidget->setFocusPolicy(Qt::StrongFocus); + _glWidget->setFocus(); // enable mouse tracking; otherwise, we only get drag events - glCanvas->setMouseTracking(true); + _glWidget->setMouseTracking(true); _toolWindow = new ToolWindow(); _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); @@ -474,7 +473,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : checkVersion(); - _overlays.init(glCanvas.data()); // do this before scripts load + _overlays.init(_glWidget); // do this before scripts load _runningScriptsWidget->setRunningScripts(getRunningScripts()); connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript); @@ -533,6 +532,7 @@ void Application::aboutToQuit() { } void Application::cleanupBeforeQuit() { + qDebug() << "Application::cleanupBeforeQuit() ------------ BEGIN --------------"; _datagramProcessor.shutdown(); // tell the datagram processor we're shutting down, so it can short circuit _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts @@ -577,9 +577,12 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); + + qDebug() << "Application::cleanupBeforeQuit() ------------ END --------------"; } Application::~Application() { + qDebug() << "Application::~Application() ------------ BEGIN --------------"; EntityTree* tree = _entities.getTree(); tree->lockForWrite(); _entities.getTree()->setSimulation(NULL); @@ -598,15 +601,19 @@ Application::~Application() { ModelEntityItem::cleanupLoadedAnimations() ; - DependencyManager::destroy(); + //DependencyManager::destroy(); + qDebug() << "Application::~Application() ------------ BEGIN CACHE CLEANUP --------------"; DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + qDebug() << "Application::~Application() ------------ END CACHE CLEANUP --------------"; qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages + + qDebug() << "Application::~Application() ------------ END --------------"; } void Application::initializeGL() { @@ -691,7 +698,7 @@ void Application::paintGL() { if (OculusManager::isConnected()) { DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); } else { - QSize fbSize = DependencyManager::get()->getDeviceSize() * getRenderResolutionScale(); + QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); DependencyManager::get()->setFrameBufferSize(fbSize); } @@ -1058,8 +1065,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); if (TV3DManager::isConnected()) { - auto glCanvas = DependencyManager::get(); - TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); @@ -1071,8 +1077,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); if (TV3DManager::isConnected()) { - auto glCanvas = DependencyManager::get(); - TV3DManager::configureCamera(_myCamera, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } } else { @@ -1501,7 +1506,7 @@ void Application::idle() { { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - DependencyManager::get()->updateGL(); + _glWidget->updateGL(); } { PerformanceTimer perfTimer("rest"); @@ -1542,8 +1547,7 @@ void Application::setFullscreen(bool fullscreen) { } void Application::setEnable3DTVMode(bool enable3DTVMode) { - auto glCanvas = DependencyManager::get(); - resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } void Application::setEnableVRMode(bool enableVRMode) { @@ -1568,8 +1572,7 @@ void Application::setEnableVRMode(bool enableVRMode) { _myCamera.setHmdRotation(glm::quat()); } - auto glCanvas = DependencyManager::get(); - resizeGL(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); updateCursorVisibility(); } @@ -1580,9 +1583,8 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { bool Application::mouseOnScreen() const { if (OculusManager::isConnected()) { - auto glCanvas = DependencyManager::get(); - return getMouseX() >= 0 && getMouseX() <= glCanvas->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= glCanvas->getDeviceHeight(); + return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && + getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); } return true; } @@ -1792,8 +1794,7 @@ void Application::init() { _metavoxels.init(); - auto glCanvas = DependencyManager::get(); - _rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect); + _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); @@ -1801,10 +1802,10 @@ void Application::init() { connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); // make sure our texture cache knows about window size changes - DependencyManager::get()->associateWithWidget(glCanvas.data()); + DependencyManager::get()->associateWithWidget(_glWidget); // initialize the GlowEffect with our widget - DependencyManager::get()->init(glCanvas.data(), + DependencyManager::get()->init(_glWidget, Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); } @@ -2058,9 +2059,9 @@ void Application::updateCursor(float deltaTime) { void Application::updateCursorVisibility() { if (!_cursorVisible || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { - DependencyManager::get()->setCursor(Qt::BlankCursor); + _glWidget->setCursor(Qt::BlankCursor); } else { - DependencyManager::get()->unsetCursor(); + _glWidget->unsetCursor(); } } @@ -2650,8 +2651,7 @@ void Application::updateShadowMap() { fbo->release(); - auto glCanvas = DependencyManager::get(); - glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); + glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f }; @@ -2701,7 +2701,7 @@ QImage Application::renderAvatarBillboard() { Glower glower; const int BILLBOARD_SIZE = 64; - renderRearViewMirror(QRect(0, DependencyManager::get()->getDeviceHeight() - BILLBOARD_SIZE, + renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); @@ -2993,9 +2993,8 @@ bool Application::getCascadeShadowsEnabled() { } glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - auto glCanvas = DependencyManager::get(); - float horizontalScale = glCanvas->getDeviceWidth() / 2.0f; - float verticalScale = glCanvas->getDeviceHeight() / 2.0f; + float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; + float verticalScale = _glWidget->getDeviceHeight() / 2.0f; // -1,-1 is 0,windowHeight // 1,1 is windowWidth,0 @@ -3014,7 +3013,7 @@ glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { // -1,-1 1,-1 glm::vec2 screenPoint((projectedPoint.x + 1.0) * horizontalScale, - ((projectedPoint.y + 1.0) * -verticalScale) + glCanvas->getDeviceHeight()); + ((projectedPoint.y + 1.0) * -verticalScale) + _glWidget->getDeviceHeight()); return screenPoint; } @@ -3150,7 +3149,7 @@ void Application::resetSensors() { QScreen* currentScreen = _window->windowHandle()->screen(); QWindow* mainWindow = _window->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); - DependencyManager::get()->cursor().setPos(currentScreen, windowCenter); + _glWidget->cursor().setPos(currentScreen, windowCenter); _myAvatar->reset(); @@ -3786,7 +3785,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio void Application::loadDialog() { - QString fileNameString = QFileDialog::getOpenFileName(DependencyManager::get().data(), + QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); @@ -3827,7 +3826,7 @@ void Application::setScriptsLocation(const QString& scriptsLocation) { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(DependencyManager::get().data(), getLogger()); + _logDialog = new LogDialog(_glWidget, getLogger()); } if (_logDialog->isVisible()) { @@ -3884,7 +3883,7 @@ void Application::parseVersionXml() { } if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(DependencyManager::get().data(), releaseNotes, latestVersion, downloadUrl); + new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); } sender->deleteLater(); } @@ -3917,7 +3916,7 @@ void Application::takeSnapshot() { } if (!_snapshotShareDialog) { - _snapshotShareDialog = new SnapshotShareDialog(fileName, DependencyManager::get().data()); + _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); } _snapshotShareDialog->show(); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 669187138c..9cd19c8259 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -171,7 +171,8 @@ public: bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); - bool isThrottleRendering() const { return DependencyManager::get()->isThrottleRendering(); } + GLCanvas* getGLWidget() { return _glWidget; } + bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } @@ -195,8 +196,8 @@ public: bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; - int getTrueMouseX() const { return DependencyManager::get()->mapFromGlobal(QCursor::pos()).x(); } - int getTrueMouseY() const { return DependencyManager::get()->mapFromGlobal(QCursor::pos()).y(); } + int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); } + int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); } int getMouseDragStartedX() const; int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } @@ -270,8 +271,8 @@ public: FileLogger* getLogger() { return _logger; } - glm::vec2 getViewportDimensions() const { return glm::vec2(DependencyManager::get()->getDeviceWidth(), - DependencyManager::get()->getDeviceHeight()); } + glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), + _glWidget->getDeviceHeight()); } NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } void skipVersion(QString latestVersion); @@ -593,6 +594,8 @@ private: QThread _settingsThread; QTimer _settingsTimer; + + GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features }; #endif // hifi_Application_h diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 5019599641..e334fd7c65 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -122,7 +122,7 @@ void Camera::setFarClip(float f) { } PickRay Camera::computePickRay(float x, float y) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); } diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index ee101743cf..9e75d92b42 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -16,14 +16,18 @@ #include #include -#include +//#include /// customized canvas that simply forwards requests/events to the singleton application -class GLCanvas : public QGLWidget, public Dependency { +class GLCanvas : public QGLWidget { Q_OBJECT - SINGLETON_DEPENDENCY public: + GLCanvas(); + virtual ~GLCanvas() { + qDebug() << "Deleting GLCanvas"; + } + bool isThrottleRendering() const; int getDeviceWidth() const; @@ -60,12 +64,8 @@ private slots: void activeChanged(Qt::ApplicationState state); void throttleRender(); bool eventFilter(QObject*, QEvent* event); - -private: - GLCanvas(); - ~GLCanvas() { - qDebug() << "Deleting GLCanvas"; - } + }; + #endif // hifi_GLCanvas_h diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 19d3a51917..03195c5e75 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -12,7 +12,8 @@ #include #include -#include "DependencyManager.h" +//#include "DependencyManager.h" +#include "Application.h" #include "GLCanvas.h" #include "UIUtil.h" @@ -44,7 +45,7 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) { // this function at all. If you mix both you will end up with inconsistent results // across platforms. void UIUtil::scaleWidgetFontSizes(QWidget* widget) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); // This is the base dpi that we are targetting. This is based on Mac OSXs default DPI, // and is the basis for all font sizes. diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp index 924c8105ea..e12b7bcbb0 100644 --- a/interface/src/audio/AudioToolBox.cpp +++ b/interface/src/audio/AudioToolBox.cpp @@ -16,6 +16,7 @@ #include #include +#include "Application.h" #include "AudioToolBox.h" // Mute icon configration @@ -37,7 +38,7 @@ bool AudioToolBox::mousePressEvent(int x, int y) { void AudioToolBox::render(int x, int y, bool boxed) { glEnable(GL_TEXTURE_2D); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); if (_micTextureId == 0) { _micTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 14d1939198..4d864d8cec 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -566,7 +566,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p } // restore our normal viewport - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); glViewport(0, 0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); glMatrixMode(GL_PROJECTION); @@ -585,7 +585,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); glOrtho(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight(), -1.0, 1.0); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp index b3342ac2bd..428c223eb7 100644 --- a/interface/src/devices/PrioVR.cpp +++ b/interface/src/devices/PrioVR.cpp @@ -216,7 +216,7 @@ void PrioVR::renderCalibrationCountdown() { static TextRenderer* textRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY, 18, QFont::Bold, false, TextRenderer::OUTLINE_EFFECT, 2); QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); textRenderer->draw((glCanvas->width() - textRenderer->computeExtent(text.constData()).x) / 2, glCanvas->height() / 2, text, glm::vec4(1,1,1,1)); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 609ac7b349..ce6ca57c69 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -472,7 +472,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) //Injecting mouse movements and clicks void SixenseManager::emulateMouse(PalmData* palm, int index) { MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); QPoint pos; Qt::MouseButton bumperButton; diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 9af13c461e..205ebfd29d 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -35,7 +35,7 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); int width = glCanvas->getDeviceWidth(); int height = glCanvas->getDeviceHeight(); Camera& camera = *Application::getInstance()->getCamera(); @@ -93,7 +93,7 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); QSize deviceSize = glCanvas->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 2188f45374..35c24346d2 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -15,6 +15,7 @@ #include #include +#include "Application.h" #include "devices/MotionTracker.h" #include "devices/SixenseManager.h" #include "ControllerScriptingInterface.h" @@ -285,7 +286,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); return glm::vec2(glCanvas->width(), glCanvas->height()); } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index fc3eefe260..8ec9fbbb82 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -44,7 +44,7 @@ WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title } QScriptValue WindowScriptingInterface::hasFocus() { - return DependencyManager::get()->hasFocus(); + return Application::getInstance()->getGLWidget()->hasFocus(); } void WindowScriptingInterface::setFocus() { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 632e76c840..0c5941366f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -170,7 +170,7 @@ ApplicationOverlay::~ApplicationOverlay() { void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); _textureFov = glm::radians(_oculusUIAngularSize); _textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight(); @@ -239,7 +239,7 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -401,7 +401,7 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), overlayColor); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); if (_crosshairTexture == 0) { _crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } @@ -451,7 +451,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -528,7 +528,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); //lazily load crosshair texture if (_crosshairTexture == 0) { @@ -575,7 +575,7 @@ void ApplicationOverlay::renderPointers() { } void ApplicationOverlay::renderControllerPointers() { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); //Static variables used for storing controller state @@ -722,7 +722,7 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool if (!_magnifier) { return; } - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); const int widgetWidth = glCanvas->width(); const int widgetHeight = glCanvas->height(); @@ -787,7 +787,7 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool } void ApplicationOverlay::renderAudioMeter() { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); auto audio = DependencyManager::get(); // Audio VU Meter and Mute Icon @@ -905,7 +905,7 @@ void ApplicationOverlay::renderStatsAndLogs() { Application* application = Application::getInstance(); QSharedPointer bandwidthRecorder = DependencyManager::get(); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); @@ -943,7 +943,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); auto geometryCache = DependencyManager::get(); int width = glCanvas->width(); int height = glCanvas->height(); @@ -1087,7 +1087,7 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - QSize size = DependencyManager::get()->getDeviceSize(); + QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); if (_framebufferObject != NULL && size == _framebufferObject->size()) { // Already build return; @@ -1138,7 +1138,7 @@ void ApplicationOverlay::TexturedHemisphere::render() { glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { - QSize screenSize = DependencyManager::get()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE; float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE; @@ -1146,7 +1146,7 @@ glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { } glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { - QSize screenSize = DependencyManager::get()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width(); float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height(); @@ -1154,7 +1154,7 @@ glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { - QSize screenSize = DependencyManager::get()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width(); float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height(); @@ -1162,7 +1162,7 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const { - QSize screenSize = DependencyManager::get()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio; float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp index bead5c743f..34c6ec9a30 100644 --- a/interface/src/ui/MetavoxelEditor.cpp +++ b/interface/src/ui/MetavoxelEditor.cpp @@ -140,7 +140,7 @@ MetavoxelEditor::MetavoxelEditor(QWidget* parent) : connect(Application::getInstance()->getMetavoxels(), &MetavoxelSystem::rendering, this, &MetavoxelEditor::renderPreview); - DependencyManager::get()->installEventFilter(this); + Application::getInstance()->getGLWidget()->installEventFilter(this); show(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 1a3ad541c9..fa63079290 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -235,7 +235,7 @@ void PreferencesDialog::savePreferences() { myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); DependencyManager::get()->getMyAvatar()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 9f8603e2ca..5a3109ff64 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -23,6 +23,7 @@ #include #include +#include "Application.h" #include "Snapshot.h" // filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg @@ -93,7 +94,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); QImage shot = glCanvas->grabFrameBuffer(); Avatar* avatar = DependencyManager::get()->getMyAvatar(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 7617adf01c..a4bb60bf7c 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -62,7 +62,7 @@ Stats::Stats(): _metavoxelReceiveProgress(0), _metavoxelReceiveTotal(0) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); resetWidth(glCanvas->width(), 0); } @@ -73,7 +73,7 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -128,7 +128,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); int extraSpace = glCanvas->width() - horizontalOffset -2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) @@ -202,7 +202,7 @@ void Stats::display( int outKbitsPerSecond, int voxelPacketsToProcess) { - auto glCanvas = DependencyManager::get(); + auto glCanvas = Application::getInstance()->getGLWidget(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; From d1e648b39234084fac6fca18c196778a3fdab181 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 12:34:38 -0800 Subject: [PATCH 232/341] remove unused references to QGLWidget* parent in Overlay and Overlays --- interface/src/Application.cpp | 2 +- interface/src/UIUtil.cpp | 4 ---- interface/src/ui/overlays/Overlay.cpp | 5 +---- interface/src/ui/overlays/Overlay.h | 3 +-- interface/src/ui/overlays/Overlays.cpp | 5 ++--- interface/src/ui/overlays/Overlays.h | 3 +-- 6 files changed, 6 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 772c314783..5c6b370cfb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -473,7 +473,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : checkVersion(); - _overlays.init(_glWidget); // do this before scripts load + _overlays.init(); // do this before scripts load _runningScriptsWidget->setRunningScripts(getRunningScripts()); connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript); diff --git a/interface/src/UIUtil.cpp b/interface/src/UIUtil.cpp index 03195c5e75..8951ada5a6 100644 --- a/interface/src/UIUtil.cpp +++ b/interface/src/UIUtil.cpp @@ -12,8 +12,6 @@ #include #include -//#include "DependencyManager.h" -#include "Application.h" #include "GLCanvas.h" #include "UIUtil.h" @@ -45,8 +43,6 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) { // this function at all. If you mix both you will end up with inconsistent results // across platforms. void UIUtil::scaleWidgetFontSizes(QWidget* widget) { - auto glCanvas = Application::getInstance()->getGLWidget(); - // This is the base dpi that we are targetting. This is based on Mac OSXs default DPI, // and is the basis for all font sizes. const float BASE_DPI = 72.0f; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index fd7aaca717..b7700d8299 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -20,7 +20,6 @@ Overlay::Overlay() : - _parent(NULL), _isLoaded(true), _alpha(DEFAULT_ALPHA), _glowLevel(0.0f), @@ -40,7 +39,6 @@ Overlay::Overlay() : } Overlay::Overlay(const Overlay* overlay) : - _parent(NULL), _isLoaded(overlay->_isLoaded), _alpha(overlay->_alpha), _glowLevel(overlay->_glowLevel), @@ -60,8 +58,7 @@ Overlay::Overlay(const Overlay* overlay) : { } -void Overlay::init(QGLWidget* parent, QScriptEngine* scriptEngine) { - _parent = parent; +void Overlay::init(QScriptEngine* scriptEngine) { _scriptEngine = scriptEngine; } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 99ab588197..b921c2ddbb 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -38,7 +38,7 @@ public: Overlay(); Overlay(const Overlay* overlay); ~Overlay(); - void init(QGLWidget* parent, QScriptEngine* scriptEngine); + void init(QScriptEngine* scriptEngine); virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; @@ -85,7 +85,6 @@ public: protected: float updatePulse(); - QGLWidget* _parent; bool _isLoaded; float _alpha; float _glowLevel; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 8ba7ddea00..c7b350f100 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -58,8 +58,7 @@ Overlays::~Overlays() { } -void Overlays::init(QGLWidget* parent) { - _parent = parent; +void Overlays::init() { _scriptEngine = new QScriptEngine(); } @@ -202,7 +201,7 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope } unsigned int Overlays::addOverlay(Overlay* overlay) { - overlay->init(_parent, _scriptEngine); + overlay->init(_scriptEngine); QWriteLocker lock(&_lock); unsigned int thisID = _nextOverlayID; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 94ac6f98bb..42227d04f6 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -51,7 +51,7 @@ class Overlays : public QObject { public: Overlays(); ~Overlays(); - void init(QGLWidget* parent); + void init(); void update(float deltatime); void renderWorld(bool drawFront, RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::RenderSide renderSide = RenderArgs::MONO); @@ -95,7 +95,6 @@ private: QMap _overlaysWorld; QList _overlaysToDelete; unsigned int _nextOverlayID; - QGLWidget* _parent; QReadWriteLock _lock; QReadWriteLock _deleteLock; QScriptEngine* _scriptEngine; From 912b851eb72c0ee031de3c85c375feb84c8496a8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 12:54:34 -0800 Subject: [PATCH 233/341] remove crufty references to QGLWidget --- interface/src/ui/overlays/Base3DOverlay.cpp | 1 - interface/src/ui/overlays/Circle3DOverlay.cpp | 1 - interface/src/ui/overlays/Cube3DOverlay.cpp | 2 -- interface/src/ui/overlays/Grid3DOverlay.h | 2 -- interface/src/ui/overlays/ImageOverlay.cpp | 1 - interface/src/ui/overlays/ImageOverlay.h | 1 - interface/src/ui/overlays/Overlay.cpp | 3 --- interface/src/ui/overlays/Overlay.h | 1 - interface/src/ui/overlays/Overlay2D.cpp | 3 --- interface/src/ui/overlays/Overlay2D.h | 1 - interface/src/ui/overlays/Planar3DOverlay.cpp | 1 - interface/src/ui/overlays/Planar3DOverlay.h | 1 - interface/src/ui/overlays/Rectangle3DOverlay.cpp | 2 -- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 -- interface/src/ui/overlays/TextOverlay.cpp | 2 -- interface/src/ui/overlays/TextOverlay.h | 4 ---- interface/src/ui/overlays/Volume3DOverlay.cpp | 1 - interface/src/ui/overlays/Volume3DOverlay.h | 1 - 18 files changed, 30 deletions(-) diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 57c7aa791b..f0c49979c8 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -11,7 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include "Application.h" diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index e68f1bfb37..132f58b6f0 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -11,7 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 53d7d4e70b..a9bfbae8dd 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -11,8 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include - #include #include #include diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h index d6c85a10ee..451ce0a498 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ b/interface/src/ui/overlays/Grid3DOverlay.h @@ -17,8 +17,6 @@ #include -#include - #include #include diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 3cc1b54b62..72e47b5e3d 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -11,7 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index e167c4e755..31c6031102 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -14,7 +14,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index b7700d8299..2cb8b3c91d 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -11,9 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include -#include #include #include "Overlay.h" diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index b921c2ddbb..9077605fc4 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -14,7 +14,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index df7df391eb..f60d44a472 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -11,9 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include -#include #include #include "Overlay2D.h" diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 7493add905..20641206c2 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -14,7 +14,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp index 925725d261..265cafa0ec 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ b/interface/src/ui/overlays/Planar3DOverlay.cpp @@ -11,7 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h index 9355265f80..8a02b35bd2 100644 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ b/interface/src/ui/overlays/Planar3DOverlay.h @@ -16,7 +16,6 @@ #include -#include #include #include "Base3DOverlay.h" diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 7a88b327d1..8662030e23 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -11,8 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include - #include #include #include diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 11bd7b97e8..a0e8d06b41 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -11,8 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include - #include #include diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index f3b05b7300..85e5af708c 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -11,8 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include - #include #include #include diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 793d705d3c..6387b42bc3 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -14,13 +14,9 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include -#include #include #include #include -#include #include diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp index 40fea5c8c9..b0310f8155 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ b/interface/src/ui/overlays/Volume3DOverlay.cpp @@ -14,7 +14,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include #include #include #include diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h index 7938641a8f..b7c59b2ace 100644 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ b/interface/src/ui/overlays/Volume3DOverlay.h @@ -16,7 +16,6 @@ #include -#include #include #include "Base3DOverlay.h" From a9fcde62653e6045d6460d8041c6782de1f686fc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:07:52 -0800 Subject: [PATCH 234/341] fix two typos in BUILD guides --- BUILD.md | 2 +- BUILD_WIN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index b8d7df0d0c..98b8cffab1 100644 --- a/BUILD.md +++ b/BUILD.md @@ -43,7 +43,7 @@ For example, a Qt5 5.3.2 installation to /usr/local/qt5 would require that QT_CM The path it needs to be set to will depend on where and how Qt5 was installed. e.g. export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/clang_64/lib/cmake/ - export QT_CMAKE_PREFIX_PATH=/usr/localCellar/qt5/5.3.2/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.3.2/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake ####Generating build files diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 212dd31f98..28d26d9eb4 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -22,7 +22,7 @@ We expect nmake.exe to be located at the following path. C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin -We exepect msbuild.exe to be located at the following path. +We expect msbuild.exe to be located at the following path. C:\Program Files (x86)\MSBUILD\12.0\Bin From 1c2606c6db2bd74e1a45b86c2c5e363d47b0b0a3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:12:37 -0800 Subject: [PATCH 235/341] fail out if windeployqt is not found --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index a97603a6ca..24996fde03 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -28,6 +28,10 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) ) find_program(WINDEPLOYQT_COMMAND windeployqt PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) + + if (NOT WINDEPLOYQT_COMMAND) + message(FATAL_ERROR "Could not find windeployqt at ${QT_DIR}/bin. windeployqt is required.") + endif () # add a post-build command to call windeployqt to copy Qt plugins add_custom_command( From d24287f62762cb56e5d52986dc6e06f2c50743fa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:48:28 -0800 Subject: [PATCH 236/341] look in Xcode application for 10.9 SDK --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7a64fef18..288d669077 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,11 +96,16 @@ if (APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) # find the 10.9 SDK path - execute_process(COMMAND xcodebuild -sdk -version OUTPUT_VARIABLE XCODE_SDK_VERSIONS) - string(REGEX MATCH \\/.+MacOSX10.9.sdk OSX_SDK_PATH ${XCODE_SDK_VERSIONS}) + find_path(_OSX_DESIRED_SDK_PATH NAME MacOSX10.9.sdk HINTS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ ${OSX_SDK_PATH}) + + if (NOT _OSX_DESIRED_SDK_PATH) + message(FATAL_ERROR "Could not find OS X 10.9 SDK. Please pass OSX_SDK_PATH to CMake to point us to your SDKs directory.") + else () + message(STATUS "Found OS X 10.9 SDK at ${_OSX_DESIRED_SDK_PATH}/MacOSX10.9.sdk") + endif () # set that as the SDK to use - set(CMAKE_OSX_SYSROOT ${OSX_SDK_PATH}) + set(CMAKE_OSX_SYSROOT ${_OSX_DESIRED_SDK_PATH}/MacOSX10.9.sdk) endif () # Find includes in corresponding build directories From 994c0386d307d5cc91196db61200e60b4d88b9e7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:50:59 -0800 Subject: [PATCH 237/341] cleanup command that looks for SDK --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 288d669077..b3fc5b2d2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,14 +89,19 @@ endif () # figure out where the qt dir is get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) -set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) -if (APPLE) +if (APPLE) # set our OS X deployment target set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) # find the 10.9 SDK path - find_path(_OSX_DESIRED_SDK_PATH NAME MacOSX10.9.sdk HINTS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ ${OSX_SDK_PATH}) + find_path( + _OSX_DESIRED_SDK_PATH + NAME MacOSX10.9.sdk + HINTS ${OSX_SDK_PATH} + PATHS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + ) if (NOT _OSX_DESIRED_SDK_PATH) message(FATAL_ERROR "Could not find OS X 10.9 SDK. Please pass OSX_SDK_PATH to CMake to point us to your SDKs directory.") From e0d31f6e617fa7dbe2c09f889eb461b2d4e34bc9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:52:14 -0800 Subject: [PATCH 238/341] remove extra added spaces --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3fc5b2d2a..8a9c77bc4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,9 +89,9 @@ endif () # figure out where the qt dir is get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) -set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) -if (APPLE) +if (APPLE) # set our OS X deployment target set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8) From a7a9ede744bc23e0215ac59cc6e98a27e2775d6e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 13:53:57 -0800 Subject: [PATCH 239/341] handle an SDK in Xcode beta --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a9c77bc4f..75282137dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ if (APPLE) NAME MacOSX10.9.sdk HINTS ${OSX_SDK_PATH} PATHS /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ ) if (NOT _OSX_DESIRED_SDK_PATH) From 5eecb6a8377e1407c17f3e1355a0060249924903 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 14:44:10 -0800 Subject: [PATCH 240/341] correctly delete glbuffers --- libraries/gpu/src/gpu/Context.h | 3 ++- libraries/gpu/src/gpu/GLBackend.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index b8cba3ded1..78e58bf721 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -11,6 +11,7 @@ #ifndef hifi_gpu_Context_h #define hifi_gpu_Context_h +#include #include #include "Resource.h" @@ -21,7 +22,7 @@ namespace gpu { class GPUObject { public: GPUObject() {} - ~GPUObject() {} + virtual ~GPUObject() {} }; class Batch; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3450ae71a..49d4bd4c19 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -32,7 +32,7 @@ public: static void checkGLError(); - class GLBuffer { + class GLBuffer : public GPUObject { public: Stamp _stamp; GLuint _buffer; From af43ba34442afa7b844dc920210b3caab3a4eec5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 15:21:24 -0800 Subject: [PATCH 241/341] used a registered quad for the audio box since its color constantly changes --- interface/src/audio/AudioToolBox.cpp | 6 +++++- interface/src/audio/AudioToolBox.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp index e12b7bcbb0..330e7bc194 100644 --- a/interface/src/audio/AudioToolBox.cpp +++ b/interface/src/audio/AudioToolBox.cpp @@ -106,8 +106,12 @@ void AudioToolBox::render(int x, int y, bool boxed) { glm::vec2 bottomRight(_iconBounds.right(), _iconBounds.bottom()); glm::vec2 texCoordTopLeft(1,1); glm::vec2 texCoordBottomRight(0,0); + + if (_boxQuadID == GeometryCache::UNKNOWN_ID) { + _boxQuadID = DependencyManager::get()->allocateID(); + } - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor, _boxQuadID); glDisable(GL_TEXTURE_2D); } \ No newline at end of file diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h index 2c073c1825..526de89b9c 100644 --- a/interface/src/audio/AudioToolBox.h +++ b/interface/src/audio/AudioToolBox.h @@ -13,6 +13,7 @@ #define hifi_AudioToolBox_h #include +#include class AudioToolBox : public Dependency { SINGLETON_DEPENDENCY @@ -26,6 +27,7 @@ private: GLuint _micTextureId = 0; GLuint _muteTextureId = 0; GLuint _boxTextureId = 0; + int _boxQuadID = GeometryCache::UNKNOWN_ID; QRect _iconBounds; qint64 _iconPulseTimeReference = 0; }; From b03928cec7dae8208bb349d55b40a95f9c69e494 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 16:31:43 -0800 Subject: [PATCH 242/341] some cleanup --- interface/src/Application.cpp | 12 ------------ interface/src/GLCanvas.h | 5 ----- 2 files changed, 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5c6b370cfb..0bdd8f8f53 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -215,7 +215,6 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::registerInheritance(); // Set dependencies - //auto glCanvasGlobal = DependencyManager::set(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); auto geometryCache = DependencyManager::set(); @@ -532,8 +531,6 @@ void Application::aboutToQuit() { } void Application::cleanupBeforeQuit() { - qDebug() << "Application::cleanupBeforeQuit() ------------ BEGIN --------------"; - _datagramProcessor.shutdown(); // tell the datagram processor we're shutting down, so it can short circuit _entities.shutdown(); // tell the entities system we're shutting down, so it will stop running scripts ScriptEngine::stopAllScripts(this); // stop all currently running global scripts @@ -577,12 +574,9 @@ void Application::cleanupBeforeQuit() { // destroy the AudioClient so it and its thread have a chance to go down safely DependencyManager::destroy(); - - qDebug() << "Application::cleanupBeforeQuit() ------------ END --------------"; } Application::~Application() { - qDebug() << "Application::~Application() ------------ BEGIN --------------"; EntityTree* tree = _entities.getTree(); tree->lockForWrite(); _entities.getTree()->setSimulation(NULL); @@ -601,19 +595,13 @@ Application::~Application() { ModelEntityItem::cleanupLoadedAnimations() ; - //DependencyManager::destroy(); - - qDebug() << "Application::~Application() ------------ BEGIN CACHE CLEANUP --------------"; DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - qDebug() << "Application::~Application() ------------ END CACHE CLEANUP --------------"; qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages - - qDebug() << "Application::~Application() ------------ END --------------"; } void Application::initializeGL() { diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 9e75d92b42..e2bbf3b841 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -16,17 +16,12 @@ #include #include -//#include - /// customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { Q_OBJECT public: GLCanvas(); - virtual ~GLCanvas() { - qDebug() << "Deleting GLCanvas"; - } bool isThrottleRendering() const; From 05d7d47045b8297057dbe1345dc35e029c74f4d8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 25 Feb 2015 16:32:48 -0800 Subject: [PATCH 243/341] some cleanup --- libraries/gpu/src/gpu/Context.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 78e58bf721..8140c91bf6 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -11,7 +11,6 @@ #ifndef hifi_gpu_Context_h #define hifi_gpu_Context_h -#include #include #include "Resource.h" From 434c0b569f51c10825acd0cbde7299803912a58e Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Thu, 26 Feb 2015 06:28:28 +0530 Subject: [PATCH 244/341] Make vhacd tool optional --- tools/CMakeLists.txt | 4 ++++ tools/vhacd/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 57fe18c53f..003920a442 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -3,4 +3,8 @@ add_subdirectory(bitstream2json) add_subdirectory(json2bitstream) add_subdirectory(mtc) add_subdirectory(scribe) + +find_package(VHACD) +if(VHACD_FOUND) add_subdirectory(vhacd) +endif() diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt index 51e15c8239..db0cc13e67 100644 --- a/tools/vhacd/CMakeLists.txt +++ b/tools/vhacd/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME vhacd) setup_hifi_project() link_hifi_libraries(shared model fbx gpu networking octree) -find_package(VHACD REQUIRED) +#find_package(VHACD REQUIRED) done in CMakeList.txt in parent directory target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) From f8627c823357590f904aa9911b6a16e30b7f6d23 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Feb 2015 17:48:26 -0800 Subject: [PATCH 245/341] fix handling for vc12 externals --- cmake/macros/SetupExternalsBinaryDir.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/macros/SetupExternalsBinaryDir.cmake b/cmake/macros/SetupExternalsBinaryDir.cmake index c066363455..04bd00643c 100644 --- a/cmake/macros/SetupExternalsBinaryDir.cmake +++ b/cmake/macros/SetupExternalsBinaryDir.cmake @@ -14,10 +14,12 @@ macro(SETUP_EXTERNALS_BINARY_DIR) # get a short name for the generator to use in the path STRING(REGEX REPLACE " " "-" CMAKE_GENERATOR_FOLDER_NAME ${CMAKE_GENERATOR}) - if (CMAKE_GENERATOR_FOLDER_NAME STREQUAL "Unix-Makefiles") - set(CMAKE_GENERATOR_FOLDER_NAME "makefiles") - elseif (CMAKE_GENERATOR_FOLDER_NAME STREQUAL "Visual-Studio-12") - set(CMAKE_GENERATOR_FOLDER_NAME "vs12") + if (MSVC12) + set(CMAKE_GENERATOR_FOLDER_NAME "vc12") + else () + if (CMAKE_GENERATOR_FOLDER_NAME STREQUAL "Unix-Makefiles") + set(CMAKE_GENERATOR_FOLDER_NAME "makefiles") + endif () endif () set(EXTERNALS_BINARY_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build-ext") From 6b29e314c20b672cf83a870724f966d2ad250357 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:05:27 -0800 Subject: [PATCH 246/341] Adding the Stage of the Scene and exposing control of the sun light from javascript --- interface/src/Application.cpp | 15 +- libraries/gpu/src/gpu/Context.h | 2 +- libraries/gpu/src/gpu/GLBackend.h | 4 +- libraries/model/src/model/Stage.cpp | 442 ++++++++++++++++++ libraries/model/src/model/Stage.h | 200 ++++++++ .../src/SceneScriptingInterface.cpp | 36 ++ .../src/SceneScriptingInterface.h | 43 ++ libraries/script-engine/src/ScriptEngine.cpp | 5 + 8 files changed, 741 insertions(+), 6 deletions(-) create mode 100644 libraries/model/src/model/Stage.cpp create mode 100644 libraries/model/src/model/Stage.h create mode 100644 libraries/script-engine/src/SceneScriptingInterface.cpp create mode 100644 libraries/script-engine/src/SceneScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7e73da1bd..9b27c6c570 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -82,6 +82,8 @@ #include #include +#include + #include "Application.h" #include "AudioClient.h" #include "InterfaceVersion.h" @@ -2495,7 +2497,10 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin - return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); + // return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); + + auto skyStage = DependencyManager::get()->getSkyStage(); + return skyStage->getSunLight()->getDirection(); } void Application::updateShadowMap() { @@ -2505,7 +2510,7 @@ void Application::updateShadowMap() { glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); - glm::vec3 lightDirection = -getSunDirection(); + glm::vec3 lightDirection = getSunDirection(); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); @@ -2875,7 +2880,11 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); - DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); + // DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); + auto skyStage = DependencyManager::get()->getSkyStage(); +// DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, skyStage->_light->getIntensity()); + DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity()); + PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); DependencyManager::get()->render(); diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index b8cba3ded1..8140c91bf6 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -21,7 +21,7 @@ namespace gpu { class GPUObject { public: GPUObject() {} - ~GPUObject() {} + virtual ~GPUObject() {} }; class Batch; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3450ae71a..806ba0b1eb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -32,7 +32,7 @@ public: static void checkGLError(); - class GLBuffer { + class GLBuffer : public GPUObject { public: Stamp _stamp; GLuint _buffer; @@ -44,7 +44,7 @@ public: static void syncGPUObject(const Buffer& buffer); static GLuint getBufferID(const Buffer& buffer); - class GLTexture { + class GLTexture : public GPUObject { public: Stamp _storageStamp; Stamp _contentStamp; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp new file mode 100644 index 0000000000..64aa504965 --- /dev/null +++ b/libraries/model/src/model/Stage.cpp @@ -0,0 +1,442 @@ +// +// Stage.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Stage.h" + +#include +using namespace model; + + +void EarthSunModel::updateAll() const { + updateWorldToSurface(); + updateSurfaceToEye(); + updateSun(); +} + +Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { + + + // Longitude is along Z axis but - from east to west + Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); + + // latitude is along X axis + from south to north + Mat4d rotLat = glm::rotate(-glm::radians(latitude), Vec3d(1.0, 0.0, 0.0)); + + // translation is movin to the earth surface + altiture at the radius along Y axis + Mat4d surfaceT = glm::translate(Vec3d(0.0, -absAltitude, 0.0)); + + // Mat4d worldScale = glm::scale(Vec3d(scale)); + + Mat4d worldToGeoLocMat = surfaceT * rotLat * rotLon; + + return worldToGeoLocMat; +} + +void EarthSunModel::updateWorldToSurface() const { + // Check if the final position is too close to the earth center ? + double absAltitude = _earthRadius + _altitude; + if ( absAltitude < 0.01) { + absAltitude = 0.01; + } + + // Final world to local Frame + _worldToSurfaceMat = evalWorldToGeoLocationMat(_longitude, _latitude, absAltitude, _scale); + // and the inverse + _surfaceToWorldMat = glm::inverse(_worldToSurfaceMat); + + _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); +} + +void EarthSunModel::updateSurfaceToEye() const +{ + + _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); + _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; + _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; + _eyePos = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0) ); + _eyeDir = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, -1.0, 0.0) ); +} + +void EarthSunModel::updateSun() const { + // Longitude is along Y axis but - from east to west + Mat4d rotSunLon; + + Mat4d rotSun = evalWorldToGeoLocationMat(_sunLongitude, _sunLatitude, _earthRadius, _scale); + rotSun = glm::inverse(rotSun); + + _sunDir = Vec3d(rotSun * Vec4d(0.0, 1.0, 0.0, 0.0)); + + // sun direction is looking up toward Y axis at the specified sun lat, long + Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); + _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); +} + + +float moduloRange(float val, float minVal, float maxVal) { + float range = maxVal - minVal; + float rval = (val - minVal) / range; + float intval; + return modf(rval, &intval) * range + minVal; +} + +void EarthSunModel::setLatitude(float lat) { + _latitude = moduloRange(lat, -90.0f, 90.0f); + invalidate(); +} +void EarthSunModel::setLongitude(float lon) { + _longitude = moduloRange(lon, -180.0f, 180.0f); + invalidate(); +} +void EarthSunModel::setAltitude(float altitude) { + _altitude = moduloRange(altitude, -1000.f, 100000.f); + invalidate(); +} + +void EarthSunModel::setSunLatitude(float lat) { + _sunLatitude = moduloRange(lat, -90.0f, 90.0f); + invalidate(); +} +void EarthSunModel::setSunLongitude(float lon) { + _sunLongitude = moduloRange(lon, -180.0f, 180.0f); + invalidate(); +} + +const int NUM_DAYS_PER_YEAR = 365; +const float NUM_HOURS_PER_DAY = 24.0f; + +SunSkyStage::SunSkyStage() : + _sunLight(new Light()) +{ + _sunLight->setType(Light::SUN); + + setSunIntensity(1.0f); + setSunColor(Vec3(1.0f, 1.0f, 1.0f)); + + // setOriginLocation(45.0f, 20.0f, 1.0f); + setDayTime(18.0f); + setYearTime(60.0f); +} + +SunSkyStage::~SunSkyStage() { +} + +void SunSkyStage::setDayTime(float hour) { + _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); + invalidate(); +} + +void SunSkyStage::setYearTime(unsigned int day) { + _yearTime = day % NUM_DAYS_PER_YEAR; + invalidate(); +} + +void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { + _earthSunModel.setLongitude(longitude); + _earthSunModel.setLatitude(latitude); + _earthSunModel.setAltitude(altitude); + invalidate(); +} + +void SunSkyStage::setSunColor(const Vec3& color) { + _sunLight->setColor(color); +} +void SunSkyStage::setSunIntensity(float intensity) { + _sunLight->setIntensity(intensity); +} + +void SunSkyStage::updateGraphicsObject() const { + // Always update the sunLongitude based on the current dayTIme and the current origin + _earthSunModel.setSunLongitude(_earthSunModel.getLongitude() + (-180.0 + 360.0 * _dayTime / NUM_HOURS_PER_DAY)); + + // And update the sunLAtitude as the declinaison depending of the time of the year + _earthSunModel.setSunLatitude(-(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(_yearTime + 10)))); + + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); +} + + + + + + +// +// Environment.cpp +// interface/src +// +// Created by Andrzej Kapolka on 5/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "InterfaceConfig.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Application.h" +#include "Camera.h" +#include "world.h" + +#include "Environment.h" + +uint qHash(const HifiSockAddr& sockAddr) { + if (sockAddr.getAddress().isNull()) { + return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash + } + quint32 address = sockAddr.getAddress().toIPv4Address(); + return sockAddr.getPort() + qHash(QByteArray::fromRawData((char*) &address, + sizeof(address))); +} + +Environment::Environment() + : _initialized(false) { +} + +Environment::~Environment() { + if (_initialized) { + delete _skyFromAtmosphereProgram; + delete _skyFromSpaceProgram; + } +} + +void Environment::init() { + if (_initialized) { + qDebug("[ERROR] Environment is already initialized."); + return; + } + + _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); + _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); + + // start off with a default-constructed environment data + _data[HifiSockAddr()][0]; + + _initialized = true; +} + +void Environment::resetToDefault() { + _data.clear(); + _data[HifiSockAddr()][0]; +} + +void Environment::renderAtmospheres(Camera& camera) { + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + // TODO: do something about EnvironmentData + foreach (const EnvironmentData& environmentData, serverData) { + renderAtmosphere(camera, environmentData); + } + } +} + +glm::vec3 Environment::getGravity (const glm::vec3& position) { + // + // 'Default' gravity pulls you downward in Y when you are near the X/Z plane + const glm::vec3 DEFAULT_GRAVITY(0.0f, -1.0f, 0.0f); + glm::vec3 gravity(DEFAULT_GRAVITY); + float DEFAULT_SURFACE_RADIUS = 30.0f; + float gravityStrength; + + // Weaken gravity with height + if (position.y > 0.0f) { + gravityStrength = 1.0f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.0f); + gravity *= gravityStrength; + } + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + glm::vec3 vector = environmentData.getAtmosphereCenter(position) - position; + float surfaceRadius = environmentData.getAtmosphereInnerRadius(); + if (glm::length(vector) <= surfaceRadius) { + // At or inside a planet, gravity is as set for the planet + gravity += glm::normalize(vector) * environmentData.getGravity(); + } else { + // Outside a planet, the gravity falls off with distance + gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f); + gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength; + } + } + } + + return gravity; +} + +const EnvironmentData Environment::getClosestData(const glm::vec3& position) { + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + EnvironmentData closest; + float closestDistance = FLT_MAX; + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) - + environmentData.getAtmosphereOuterRadius(); + if (distance < closestDistance) { + closest = environmentData; + closestDistance = distance; + } + } + } + return closest; +} + +bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, + float radius, glm::vec3& penetration) { + // collide with the "floor" + bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration); + + glm::vec3 middle = (start + end) * 0.5f; + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + if (environmentData.getGravity() == 0.0f) { + continue; // don't bother colliding with gravity-less environments + } + glm::vec3 environmentPenetration; + if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(middle), + environmentData.getAtmosphereInnerRadius(), environmentPenetration)) { + penetration = addPenetrations(penetration, environmentPenetration); + found = true; + } + } + } + return found; +} + +int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) { + // push past the packet header + int bytesRead = numBytesForPacketHeader(packet); + + // push past flags, sequence, timestamp + bytesRead += sizeof(OCTREE_PACKET_FLAGS); + bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); + bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + EnvironmentData newData; + while (bytesRead < packet.size()) { + int dataLength = newData.parseData(reinterpret_cast(packet.data()) + bytesRead, + packet.size() - bytesRead); + + // update the mapping by address/ID + _data[senderAddress][newData.getID()] = newData; + + bytesRead += dataLength; + } + + // remove the default mapping, if any + _data.remove(HifiSockAddr()); + + return bytesRead; +} + +ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { + ProgramObject* program = new ProgramObject(); + QByteArray prefix = QString(PathUtils::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); + program->addShaderFromSourceFile(QGLShader::Vertex, prefix + ".vert"); + program->addShaderFromSourceFile(QGLShader::Fragment, prefix + ".frag"); + program->link(); + + locations[CAMERA_POS_LOCATION] = program->uniformLocation("v3CameraPos"); + locations[LIGHT_POS_LOCATION] = program->uniformLocation("v3LightPos"); + locations[INV_WAVELENGTH_LOCATION] = program->uniformLocation("v3InvWavelength"); + locations[CAMERA_HEIGHT2_LOCATION] = program->uniformLocation("fCameraHeight2"); + locations[OUTER_RADIUS_LOCATION] = program->uniformLocation("fOuterRadius"); + locations[OUTER_RADIUS2_LOCATION] = program->uniformLocation("fOuterRadius2"); + locations[INNER_RADIUS_LOCATION] = program->uniformLocation("fInnerRadius"); + locations[KR_ESUN_LOCATION] = program->uniformLocation("fKrESun"); + locations[KM_ESUN_LOCATION] = program->uniformLocation("fKmESun"); + locations[KR_4PI_LOCATION] = program->uniformLocation("fKr4PI"); + locations[KM_4PI_LOCATION] = program->uniformLocation("fKm4PI"); + locations[SCALE_LOCATION] = program->uniformLocation("fScale"); + locations[SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleDepth"); + locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleOverScaleDepth"); + locations[G_LOCATION] = program->uniformLocation("g"); + locations[G2_LOCATION] = program->uniformLocation("g2"); + + return program; +} + +void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { + glm::vec3 center = data.getAtmosphereCenter(camera.getPosition()); + + glPushMatrix(); + glTranslatef(center.x, center.y, center.z); + + glm::vec3 relativeCameraPos = camera.getPosition() - center; + float height = glm::length(relativeCameraPos); + + // use the appropriate shader depending on whether we're inside or outside + ProgramObject* program; + int* locations; + if (height < data.getAtmosphereOuterRadius()) { + program = _skyFromAtmosphereProgram; + locations = _skyFromAtmosphereUniformLocations; + + } else { + program = _skyFromSpaceProgram; + locations = _skyFromSpaceUniformLocations; + } + + // the constants here are from Sean O'Neil's GPU Gems entry + // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp + program->bind(); + program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); + glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); + program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); + program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], + 1 / powf(data.getScatteringWavelengths().r, 4.0f), + 1 / powf(data.getScatteringWavelengths().g, 4.0f), + 1 / powf(data.getScatteringWavelengths().b, 4.0f)); + program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); + program->setUniformValue(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); + program->setUniformValue(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PI); + program->setUniformValue(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PI); + program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); + program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); + program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], + (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); + program->setUniformValue(locations[G_LOCATION], -0.990f); + program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere + glDepthMask(GL_TRUE); + + program->release(); + + glPopMatrix(); +} diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h new file mode 100644 index 0000000000..9b2922e163 --- /dev/null +++ b/libraries/model/src/model/Stage.h @@ -0,0 +1,200 @@ +// +// Stage.h +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Stage_h +#define hifi_model_Stage_h + +#include "Light.h" + +namespace model { + +typedef glm::dvec3 Vec3d; +typedef glm::dvec4 Vec4d; +typedef glm::dmat4 Mat4d; +typedef glm::mat4 Mat4; + +class EarthSunModel { +public: + enum Preset + { + Toulouse = 0, + SanFrancisco, + Sydney, + Num_Presets, + }; + static const std::string PresetNames[Num_Presets]; + //void assignPreset( Preset p); + //Preset preset() const { return mPreset; } + + void setScale(float scale); + float getScale() const { return _scale; } + + void setLatitude(float lat); + float getLatitude() const { return _latitude; } + void setLongitude(float lon); + float getLongitude() const { return _longitude; } + void setAltitude(float altitude); + float getAltitude() const { return _altitude; } + + const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } + + const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } + const Mat4d& getWoldToSurfaceMat() const { valid(); return _worldToSurfaceMat; } + + const Mat4d& getEyeToSurfaceMat() const { valid(); return _eyeToSurfaceMat; } + const Mat4d& getSurfaceToEyeMat() const { valid(); return _surfaceToEyeMat; } + + const Mat4d& getEyeToWorldMat() const { valid(); return _eyeToWorldMat; } + const Mat4d& getWorldToEyeMat() const { valid(); return _worldToEyeMat; } + + + //or set the surfaceToEye mat directly + void setEyeToSurfaceMat( const Mat4d& e2s); + + const Vec3d& getEyePos() const { valid(); return _eyePos; } + const Vec3d& getEyeDir() const { valid(); return _eyeDir; } + + void setSunLongitude(float lon); + float getSunLongitude() const { return _sunLongitude; } + + void setSunLatitude(float lat); + float getSunLatitude() const { return _sunLatitude; } + + const Vec3d& getWorldSunDir() const { valid(); return _sunDir; } + const Vec3d& getSurfaceSunDir() const { valid(); return _surfaceSunDir; } + + + EarthSunModel() { valid(); } + +protected: + double _scale = 1000.0; //Km + double _earthRadius = 6360.0; + + double _longitude = 0.0; + double _latitude = 0.0; + double _altitude = 0.01; + mutable Vec3d _surfacePos; + mutable Mat4d _worldToSurfaceMat; + mutable Mat4d _surfaceToWorldMat; + void updateWorldToSurface() const; + + mutable Mat4d _surfaceToEyeMat; + mutable Mat4d _eyeToSurfaceMat; + mutable Vec3d _eyeDir; + mutable Vec3d _eyePos; + void updateSurfaceToEye() const; + + mutable Mat4d _worldToEyeMat; + mutable Mat4d _eyeToWorldMat; + + double _sunLongitude = 0.0; + double _sunLatitude = 0.0; + mutable Vec3d _sunDir; + mutable Vec3d _surfaceSunDir; + void updateSun() const; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateAll(); _invalid = false; } } + void updateAll() const; + + static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); +}; + +namespace gpu { + class Batch; +}; + +class ProgramObject; + +class Skybox { +public: + void recordBatch(gpu::Batch& batch, const Transform& viewTransform, const Mat4& projection); + + Skybox(); + ~Skybox(); +protected: + ProgramObject* createSkyProgram(const char* from, int* locations); + ProgramObject* _skyFromAtmosphereProgram; + ProgramObject* _skyFromSpaceProgram; + enum { + CAMERA_POS_LOCATION, + LIGHT_POS_LOCATION, + INV_WAVELENGTH_LOCATION, + CAMERA_HEIGHT2_LOCATION, + OUTER_RADIUS_LOCATION, + OUTER_RADIUS2_LOCATION, + INNER_RADIUS_LOCATION, + KR_ESUN_LOCATION, + KM_ESUN_LOCATION, + KR_4PI_LOCATION, + KM_4PI_LOCATION, + SCALE_LOCATION, + SCALE_DEPTH_LOCATION, + SCALE_OVER_SCALE_DEPTH_LOCATION, + G_LOCATION, + G2_LOCATION, + LOCATION_COUNT + }; + + int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; + int _skyFromSpaceUniformLocations[LOCATION_COUNT]; +}; + +// Sun sky stage generates the rendering primitives to display a scene realistically +// at the specified location and time around earth +class SunSkyStage { +public: + + SunSkyStage(); + ~SunSkyStage(); + + // time of the day (local to the position) expressed in decimal hour in the range [0.0, 24.0] + void setDayTime(float hour); + float getDayTime() const { return _dayTime; } + + // time of the year expressed in day in the range [0, 365] + void setYearTime(unsigned int day); + unsigned int getYearTime() const { return _yearTime; } + + // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] + void setOriginLocation(float longitude, float latitude, float surfaceAltitude); + float getOriginLatitude() const { return _earthSunModel.getLatitude(); } + float getOriginLongitude() const { return _earthSunModel.getLongitude(); } + float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); } + + // Sun properties + void setSunColor(const Vec3& color); + const Vec3& getSunColor() const { return getSunLight()->getColor(); } + void setSunIntensity(float intensity); + float getSunIntensity() const { return getSunLight()->getIntensity(); } + + LightPointer getSunLight() const { valid(); return _sunLight; } + +protected: + LightPointer _sunLight; + + // default day is 1st of january at noun + float _dayTime = 12.0f; + int _yearTime = 0; + + mutable EarthSunModel _earthSunModel; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateGraphicsObject(); _invalid = false; } } + void updateGraphicsObject() const; +}; + +typedef QSharedPointer< SunSkyStage > SunSkyStagePointer; + +}; + +#endif diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp new file mode 100644 index 0000000000..ff255a3e5e --- /dev/null +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -0,0 +1,36 @@ +// +// SceneScriptingInterface.cpp +// interface/src/scripting +// +// Created by Sam Gateau on 2/24/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "SceneScriptingInterface.h" + + Q_INVOKABLE void setOriginGeoLocation(float longitude, float latitude, float altitude); +void SceneScriptingInterface::setOriginLocation(float longitude, float latitude, float altitude) { + _skyStage->setOriginLocation(longitude, latitude, altitude); +} +void SceneScriptingInterface::setSunColor(const glm::vec3& color) { + _skyStage->setSunColor(color); +} +void SceneScriptingInterface::setSunIntensity(float intensity) { + _skyStage->setSunIntensity(intensity); +} + +void SceneScriptingInterface::setDayTime(float hour) { + _skyStage->setDayTime(hour); +} +void SceneScriptingInterface::setYearTime(int day) { + _skyStage->setYearTime(day); +} + +model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { + return _skyStage; +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h new file mode 100644 index 0000000000..3fc909f9a0 --- /dev/null +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -0,0 +1,43 @@ +// +// SceneScriptingInterface.h +// interface/src/scripting +// +// Created by Sam Gateau on 2/24/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SceneScriptingInterface_h +#define hifi_SceneScriptingInterface_h + +#include + +#include + +#include "model/Stage.h" + +class SceneScriptingInterface : public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + +public: + Q_INVOKABLE void setOriginLocation(float longitude, float latitude, float altitude); + + Q_INVOKABLE void setSunColor(const glm::vec3& color); + Q_INVOKABLE void setSunIntensity(float intensity); + + Q_INVOKABLE void setDayTime(float hour); + Q_INVOKABLE void setYearTime(int day); + + model::SunSkyStagePointer getSkyStage() const; + +protected: + SceneScriptingInterface() {}; + ~SceneScriptingInterface() {}; + + model::SunSkyStagePointer _skyStage = model::SunSkyStagePointer(new model::SunSkyStage()); +}; + +#endif // hifi_SceneScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0956374238..aed5d91410 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -39,6 +39,8 @@ #include "TypedArrays.h" #include "XMLHttpRequestClass.h" +#include "SceneScriptingInterface.h" + #include "MIDIEvent.h" EntityScriptingInterface ScriptEngine::_entityScriptingInterface; @@ -208,6 +210,8 @@ void ScriptEngine::init() { _isInitialized = true; + auto sceneScriptingInterface = DependencyManager::set(); + _entityScriptingInterface.init(); // register various meta-types @@ -251,6 +255,7 @@ void ScriptEngine::init() { registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("AnimationCache", DependencyManager::get().data()); + registerGlobalObject("Scene", DependencyManager::get().data()); // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); From b4cb5ca9d1e455ec7425a950259bdbc7bb65c9f7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:09:18 -0800 Subject: [PATCH 247/341] add an example script to control the sun light --- examples/example/misc/sunLightExample.js | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 examples/example/misc/sunLightExample.js diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js new file mode 100644 index 0000000000..0bc3b0dfea --- /dev/null +++ b/examples/example/misc/sunLightExample.js @@ -0,0 +1,32 @@ +// +// SunLightExample.js +// examples +// Sam Gateau +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var intensity = 1.0; +var day = 0.0; +var hour = 12.0; +var longitude = 0.0; +var latitude = -45.0; + +Scene.setDayTime(hour); +Scene.setOriginLocation(longitude, latitude, 0.0); + +function ticktack() { + hour += 0.1; + //Scene.setSunIntensity(Math.cos(time)); + if (hour > 24.0) { + hour = 0.0; + day++; + Scene.setYearTime(day); + } + Scene.setDayTime(hour); + +} + +Script.setInterval(ticktack, 41); From 4959e2924e0bd00ab17ed7812763c35cfae5300b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:17:38 -0800 Subject: [PATCH 248/341] add an example script to control the sun light --- libraries/model/src/model/Stage.cpp | 277 ---------------------------- 1 file changed, 277 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 64aa504965..dcd633f35c 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -163,280 +163,3 @@ void SunSkyStage::updateGraphicsObject() const { _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); } - - - - - -// -// Environment.cpp -// interface/src -// -// Created by Andrzej Kapolka on 5/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "Application.h" -#include "Camera.h" -#include "world.h" - -#include "Environment.h" - -uint qHash(const HifiSockAddr& sockAddr) { - if (sockAddr.getAddress().isNull()) { - return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash - } - quint32 address = sockAddr.getAddress().toIPv4Address(); - return sockAddr.getPort() + qHash(QByteArray::fromRawData((char*) &address, - sizeof(address))); -} - -Environment::Environment() - : _initialized(false) { -} - -Environment::~Environment() { - if (_initialized) { - delete _skyFromAtmosphereProgram; - delete _skyFromSpaceProgram; - } -} - -void Environment::init() { - if (_initialized) { - qDebug("[ERROR] Environment is already initialized."); - return; - } - - _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); - _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); - - // start off with a default-constructed environment data - _data[HifiSockAddr()][0]; - - _initialized = true; -} - -void Environment::resetToDefault() { - _data.clear(); - _data[HifiSockAddr()][0]; -} - -void Environment::renderAtmospheres(Camera& camera) { - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - // TODO: do something about EnvironmentData - foreach (const EnvironmentData& environmentData, serverData) { - renderAtmosphere(camera, environmentData); - } - } -} - -glm::vec3 Environment::getGravity (const glm::vec3& position) { - // - // 'Default' gravity pulls you downward in Y when you are near the X/Z plane - const glm::vec3 DEFAULT_GRAVITY(0.0f, -1.0f, 0.0f); - glm::vec3 gravity(DEFAULT_GRAVITY); - float DEFAULT_SURFACE_RADIUS = 30.0f; - float gravityStrength; - - // Weaken gravity with height - if (position.y > 0.0f) { - gravityStrength = 1.0f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.0f); - gravity *= gravityStrength; - } - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - glm::vec3 vector = environmentData.getAtmosphereCenter(position) - position; - float surfaceRadius = environmentData.getAtmosphereInnerRadius(); - if (glm::length(vector) <= surfaceRadius) { - // At or inside a planet, gravity is as set for the planet - gravity += glm::normalize(vector) * environmentData.getGravity(); - } else { - // Outside a planet, the gravity falls off with distance - gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f); - gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength; - } - } - } - - return gravity; -} - -const EnvironmentData Environment::getClosestData(const glm::vec3& position) { - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - EnvironmentData closest; - float closestDistance = FLT_MAX; - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) - - environmentData.getAtmosphereOuterRadius(); - if (distance < closestDistance) { - closest = environmentData; - closestDistance = distance; - } - } - } - return closest; -} - -bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, - float radius, glm::vec3& penetration) { - // collide with the "floor" - bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration); - - glm::vec3 middle = (start + end) * 0.5f; - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - if (environmentData.getGravity() == 0.0f) { - continue; // don't bother colliding with gravity-less environments - } - glm::vec3 environmentPenetration; - if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(middle), - environmentData.getAtmosphereInnerRadius(), environmentPenetration)) { - penetration = addPenetrations(penetration, environmentPenetration); - found = true; - } - } - } - return found; -} - -int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) { - // push past the packet header - int bytesRead = numBytesForPacketHeader(packet); - - // push past flags, sequence, timestamp - bytesRead += sizeof(OCTREE_PACKET_FLAGS); - bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); - bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - EnvironmentData newData; - while (bytesRead < packet.size()) { - int dataLength = newData.parseData(reinterpret_cast(packet.data()) + bytesRead, - packet.size() - bytesRead); - - // update the mapping by address/ID - _data[senderAddress][newData.getID()] = newData; - - bytesRead += dataLength; - } - - // remove the default mapping, if any - _data.remove(HifiSockAddr()); - - return bytesRead; -} - -ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { - ProgramObject* program = new ProgramObject(); - QByteArray prefix = QString(PathUtils::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); - program->addShaderFromSourceFile(QGLShader::Vertex, prefix + ".vert"); - program->addShaderFromSourceFile(QGLShader::Fragment, prefix + ".frag"); - program->link(); - - locations[CAMERA_POS_LOCATION] = program->uniformLocation("v3CameraPos"); - locations[LIGHT_POS_LOCATION] = program->uniformLocation("v3LightPos"); - locations[INV_WAVELENGTH_LOCATION] = program->uniformLocation("v3InvWavelength"); - locations[CAMERA_HEIGHT2_LOCATION] = program->uniformLocation("fCameraHeight2"); - locations[OUTER_RADIUS_LOCATION] = program->uniformLocation("fOuterRadius"); - locations[OUTER_RADIUS2_LOCATION] = program->uniformLocation("fOuterRadius2"); - locations[INNER_RADIUS_LOCATION] = program->uniformLocation("fInnerRadius"); - locations[KR_ESUN_LOCATION] = program->uniformLocation("fKrESun"); - locations[KM_ESUN_LOCATION] = program->uniformLocation("fKmESun"); - locations[KR_4PI_LOCATION] = program->uniformLocation("fKr4PI"); - locations[KM_4PI_LOCATION] = program->uniformLocation("fKm4PI"); - locations[SCALE_LOCATION] = program->uniformLocation("fScale"); - locations[SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleDepth"); - locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleOverScaleDepth"); - locations[G_LOCATION] = program->uniformLocation("g"); - locations[G2_LOCATION] = program->uniformLocation("g2"); - - return program; -} - -void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { - glm::vec3 center = data.getAtmosphereCenter(camera.getPosition()); - - glPushMatrix(); - glTranslatef(center.x, center.y, center.z); - - glm::vec3 relativeCameraPos = camera.getPosition() - center; - float height = glm::length(relativeCameraPos); - - // use the appropriate shader depending on whether we're inside or outside - ProgramObject* program; - int* locations; - if (height < data.getAtmosphereOuterRadius()) { - program = _skyFromAtmosphereProgram; - locations = _skyFromAtmosphereUniformLocations; - - } else { - program = _skyFromSpaceProgram; - locations = _skyFromSpaceUniformLocations; - } - - // the constants here are from Sean O'Neil's GPU Gems entry - // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp - program->bind(); - program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); - glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); - program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); - program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], - 1 / powf(data.getScatteringWavelengths().r, 4.0f), - 1 / powf(data.getScatteringWavelengths().g, 4.0f), - 1 / powf(data.getScatteringWavelengths().b, 4.0f)); - program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); - program->setUniformValue(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); - program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); - program->setUniformValue(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); - program->setUniformValue(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); - program->setUniformValue(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); - program->setUniformValue(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PI); - program->setUniformValue(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PI); - program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); - program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); - program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], - (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); - program->setUniformValue(locations[G_LOCATION], -0.990f); - program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere - glDepthMask(GL_TRUE); - - program->release(); - - glPopMatrix(); -} From ce60bb40d73aa24e4e338ed42dbfe10c5422f739 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Thu, 26 Feb 2015 22:32:47 +0530 Subject: [PATCH 249/341] removed tags for *.md files --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index aee74ebddc..3b44b99e68 100644 --- a/.gitignore +++ b/.gitignore @@ -46,5 +46,4 @@ libraries/audio-client/external/*/* gvr-interface/assets/oculussig* gvr-interface/libs/* -TAGS -*.md \ No newline at end of file +TAGS \ No newline at end of file From bdb79f261952f5c081c1b377ca8fe556bd098cef Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Thu, 26 Feb 2015 22:56:21 +0530 Subject: [PATCH 250/341] Resetting from master --- BUILD.md | 9 +-------- BUILD_WIN.md | 43 +++++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/BUILD.md b/BUILD.md index b94ab1ff50..82cbf6628c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,20 +2,13 @@ * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 * [Qt](http://qt-project.org/downloads) ~> 5.3.2 +* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 * [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version) -* [VHACD](https://github.com/virneo/v-hacd)(clone this repository) - -#### CMake External Project Dependencies - -The following dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build` directory in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. - -* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 -* [gverb](https://github.com/highfidelity/gverb) ### OS Specific Build Guides * [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index f735936d0a..8022fae5b8 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -56,6 +56,9 @@ The recommended route for CMake to find the external dependencies is to place al -> bin -> include -> lib + -> glm + -> glm + -> glm.hpp -> openssl -> bin -> include @@ -67,9 +70,6 @@ The recommended route for CMake to find the external dependencies is to place al -> include -> lib -> test - -> vhacd - -> include - -> lib For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. @@ -117,21 +117,6 @@ Add to the PATH: `%HIFI_LIB_DIR%\zlib` Important! This should be added at the beginning of the path, not the end (your system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". -###vhacd -Download it directly from https://github.com/virneo/v-hacd - -To build it run the following commands - 1. cd src\ - 2. mkdir build - 3. cd build - 4. cmake .. - -Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug. - -This will create an output folder with include and lib directory inside it. - -Either copy that folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory. - ###freeglut Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. @@ -144,6 +129,26 @@ Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\ Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` +###GLM + +This package contains only headers, so there's nothing to add to the PATH. + +Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder. + +###Gverb + +1. Go to https://github.com/highfidelity/gverb + Or download the sources directly via this link: + https://github.com/highfidelity/gverb/archive/master.zip + +2. Extract the archive + +3. Place the directories “include” and “src” in interface/external/gverb + (Normally next to this readme) + +4. Clear your build directory, run cmake, build and you should be all set. + + ###Bullet Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself. @@ -181,8 +186,6 @@ We recommend you install it to %HIFI_LIB_DIR%\soxr. This will help our FindSoxr Extract the soxr archive wherever you like. Then, inside the extracted folder, create a directory called `build`. From that build directory, the following commands will build and then install soxr to `%HIFI_LIB_DIR%`. -(Make sure to run the following inside Visual Studio) - ``` cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=%HIFI_LIB_DIR%/soxr nmake From 621df1f66bdefa7406492367d4aa8fc663fcc949 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 09:50:21 -0800 Subject: [PATCH 251/341] remove win requirement of msbuild for bullet --- BUILD_WIN.md | 6 +----- cmake/externals/bullet/CMakeLists.txt | 13 ++----------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 28d26d9eb4..63648241a4 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -16,16 +16,12 @@ If using Visual Studio 2013 and building as a Visual Studio 2013 project you nee ####nmake & msbuild -Some of the external projects may require nmake and msbuild to compile and install. If they are not installed at the locations listed below, please ensure that both are in your PATH so CMake can find them when required. +Some of the external projects may require nmake to compile and install. If it is not installed at the location listed below, please ensure that it is in your PATH so CMake can find it when required. We expect nmake.exe to be located at the following path. C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin -We expect msbuild.exe to be located at the following path. - - C:\Program Files (x86)\MSBUILD\12.0\Bin - ###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index d08ceb11b9..fb5a4ecf8b 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -14,21 +14,12 @@ endif () include(ExternalProject) -if (WIN32) - if (UPPER_CMAKE_BUILD_TYPE MATCHES DEBUG) - set(MSBUILD_CONFIGURATION Debug) - else () - set(MSBUILD_CONFIGURATION Release) - endif () - - find_program(MSBUILD_COMMAND msbuild PATHS "C:/Program Files (x86)/MSBUILD/12.0/Bin") - +if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 - BUILD_COMMAND ${MSBUILD_COMMAND} ALL_BUILD.vcxproj /p:Configuration=${MSBUILD_CONFIGURATION} + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 From 0918d4989b342f9380e77dc6cd2e00cbaa0483df Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Feb 2015 09:53:23 -0800 Subject: [PATCH 252/341] mv ShutdownEventListener into class which is a child of QCoreApplication --- assignment-client/src/AssignmentClientApp.cpp | 8 ++++++++ assignment-client/src/AssignmentClientMonitor.cpp | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 26b6b8675a..6e269f35b7 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "Assignment.h" #include "AssignmentClient.h" @@ -173,6 +174,13 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : if (numForks || minForks || maxForks) { + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us +# ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +# else + ShutdownEventListener::getInstance(); +# endif + AssignmentClientMonitor monitor(numForks, minForks, maxForks, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); exec(); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 29fda05ee1..ffc402c04d 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include "AssignmentClientMonitor.h" @@ -40,13 +39,6 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen { // start the Logging class with the parent's target name LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME); - - // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us -#ifdef _WIN32 - installNativeEventFilter(&ShutdownEventListener::getInstance()); -#else - ShutdownEventListener::getInstance(); -#endif // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); From ea88518a440ced8cae3a051fc41cb19aa5a38e34 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 09:57:56 -0800 Subject: [PATCH 253/341] handle debug/release for multi-config on WIN32 --- cmake/externals/bullet/CMakeLists.txt | 38 +++++++++++++-------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index fb5a4ecf8b..47f4c16f91 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -57,28 +57,26 @@ elseif (WIN32) endif () if (DEFINED BULLET_LIB_EXT) - if (NOT WIN32 OR UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE) - set(_PRESENT_LIB_TYPE RELEASE) - set(_MISSING_LIB_TYPE DEBUG) - else () - set(_PRESENT_LIB_TYPE DEBUG) - set(_MISSING_LIB_TYPE RELEASE) - set(_LIB_NAME_SUFFIX _Debug) - endif () + set(_BULLET_LIB_PAIRS "DYNAMICS_LIBRARY\;BulletDynamics" "COLLISION_LIBRARY\;BulletCollision" "MATH_LIBRARY\;LinearMath" "SOFTBODY_LIBRARY\;BulletSoftBody") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletDynamics${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet dynamics ${_PRESENT_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet dynamics ${_MISSING_LIB_TYPE} library location") - - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletCollision${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet collision ${_PRESENT_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_COLLISION_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet collision ${_MISSING_LIB_TYPE} library location") - - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}LinearMath${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet math ${_PRESENT_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_MATH_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet math ${_MISSING_LIB_TYPE} library location") - - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_${_PRESENT_LIB_TYPE} ${BULLET_LIB_DIR}/${LIB_PREFIX}BulletSoftBody${_LIB_NAME_SUFFIX}.${BULLET_LIB_EXT} CACHE FILEPATH "Bullet softbody ${_PRESENT_LIB_TYPE} library location") - set(${EXTERNAL_NAME_UPPER}_SOFTBODY_LIBRARY_${_MISSING_LIB_TYPE} "" CACHE FILEPATH "Bullet softbody ${_MISSING_LIB_TYPE} library location") + foreach(_LIB_PAIR ${_BULLET_LIB_PAIRS}) + + list(GET _LIB_PAIR 0 _LIB_VAR_NAME) + list(GET _LIB_PAIR 1 _LIB_NAME) + + message(STATUS ${_LIB_VAR_NAME}) + message(STATUS ${_LIB_NAME}) + + set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} release library location") + + if (WIN32) + set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} debug library location") + else () + set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG "" CACHE FILEPATH "${_LIB_NAME} debug library location") + endif () + endforeach() endif () -if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_${_PRESENT_LIB_TYPE}) +if (DEFINED ${EXTERNAL_NAME_UPPER}_DYNAMICS_LIBRARY_RELEASE) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIR ${INSTALL_DIR}/include/bullet CACHE PATH "Path to bullet include directory") endif () \ No newline at end of file From 5a4a3ce6dd99e054c80c37d0ac7571c9610fc0b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 09:59:15 -0800 Subject: [PATCH 254/341] remove message calls to debug bullet vars --- cmake/externals/bullet/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 47f4c16f91..587b7a12f1 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -60,13 +60,9 @@ if (DEFINED BULLET_LIB_EXT) set(_BULLET_LIB_PAIRS "DYNAMICS_LIBRARY\;BulletDynamics" "COLLISION_LIBRARY\;BulletCollision" "MATH_LIBRARY\;LinearMath" "SOFTBODY_LIBRARY\;BulletSoftBody") foreach(_LIB_PAIR ${_BULLET_LIB_PAIRS}) - list(GET _LIB_PAIR 0 _LIB_VAR_NAME) list(GET _LIB_PAIR 1 _LIB_NAME) - message(STATUS ${_LIB_VAR_NAME}) - message(STATUS ${_LIB_NAME}) - set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} release library location") if (WIN32) From 7c7d727b55a878d4a3610dff083be0067502f5cb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Feb 2015 10:07:48 -0800 Subject: [PATCH 255/341] mv ShutdownEventListener into class which is a child of QCoreApplication --- assignment-client/src/AssignmentClient.cpp | 7 ------- assignment-client/src/AssignmentClientApp.cpp | 15 +++++++++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 38f5c7cc55..86680d2f03 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -58,13 +58,6 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri // when the domain server hands over an assignment. QUuid nodeUUID = QUuid::createUuid(); nodeList->setSessionUUID(nodeUUID); - - // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us -#ifdef _WIN32 - installNativeEventFilter(&ShutdownEventListener::getInstance()); -#else - ShutdownEventListener::getInstance(); -#endif // set the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 6e269f35b7..7c6fb50db2 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -29,6 +29,14 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setvbuf(stdout, NULL, _IOLBF, 0); # endif + +# ifdef _WIN32 + installNativeEventFilter(&ShutdownEventListener::getInstance()); +# else + ShutdownEventListener::getInstance(); +# endif + + setOrganizationName("High Fidelity"); setOrganizationDomain("highfidelity.io"); setApplicationName("assignment-client"); @@ -175,16 +183,11 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : if (numForks || minForks || maxForks) { // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us -# ifdef _WIN32 - installNativeEventFilter(&ShutdownEventListener::getInstance()); -# else - ShutdownEventListener::getInstance(); -# endif - AssignmentClientMonitor monitor(numForks, minForks, maxForks, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); exec(); } else { + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us AssignmentClient client(requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); exec(); From 8eb4abc49cb8c23c344be69a2e50e813b6b32bf2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 19:14:09 +0100 Subject: [PATCH 256/341] Rework FaceTracker --- interface/src/devices/FaceTracker.cpp | 5 ++--- interface/src/devices/FaceTracker.h | 24 +++++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index 52fe04de77..8d61789715 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -11,7 +11,6 @@ #include "FaceTracker.h" -FaceTracker::FaceTracker() : - _estimatedEyePitch(0.0f), - _estimatedEyeYaw(0.0f) { +inline float FaceTracker::getBlendshapeCoefficient(int index) const { + return isValidBlendshapeIndex(index) ? _blendshapeCoefficients[index] : 0.0f; } diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 7c367b7899..07c479e3e3 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -18,13 +18,17 @@ #include #include -/// Base class for face trackers (Faceshift, Visage). +/// Base class for face trackers (Faceshift, Visage, DDE). class FaceTracker : public QObject { Q_OBJECT public: - FaceTracker(); - virtual ~FaceTracker() {} + virtual bool isActive() const { return false; } + virtual bool isTracking() const { return false; } + + virtual void init() {} + virtual void update(float deltaTime) {} + virtual void reset() {} const glm::vec3& getHeadTranslation() const { return _headTranslation; } const glm::quat& getHeadRotation() const { return _headRotation; } @@ -32,15 +36,21 @@ public: float getEstimatedEyePitch() const { return _estimatedEyePitch; } float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } + int getNumBlendshapes() const { return _blendshapeCoefficients.size(); } + bool isValidBlendshapeIndex(int index) const { return index >= 0 && index < getNumBlendshapes(); } const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + float getBlendshapeCoefficient(int index) const; protected: - glm::vec3 _headTranslation; - glm::quat _headRotation; - float _estimatedEyePitch; - float _estimatedEyeYaw; + + glm::vec3 _headTranslation = glm::vec3(0.0f); + glm::quat _headRotation = glm::quat(); + float _estimatedEyePitch = 0.0f; + float _estimatedEyeYaw = 0.0f; QVector _blendshapeCoefficients; + + float _fadeCoefficient = 0.0f; }; #endif // hifi_FaceTracker_h From b6968a6b1538875504b4f90b6d71038b13b75850 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 19:15:49 +0100 Subject: [PATCH 257/341] Update Facetrackers --- interface/src/devices/DdeFaceTracker.cpp | 18 +---- interface/src/devices/DdeFaceTracker.h | 10 ++- interface/src/devices/Faceshift.cpp | 73 ++++++------------- interface/src/devices/Faceshift.h | 89 ++++++++++++------------ interface/src/devices/Visage.cpp | 3 +- interface/src/devices/Visage.h | 10 +-- 6 files changed, 77 insertions(+), 126 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 87a180bd1e..ed0e4057ef 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -50,6 +50,8 @@ DdeFaceTracker::DdeFaceTracker() : } DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : + _host(host), + _port(port), _lastReceiveTimestamp(0), _reset(false), _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes @@ -63,9 +65,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : _browUpRightIndex(18), _mouthSmileLeftIndex(28), _mouthSmileRightIndex(29), - _jawOpenIndex(21), - _host(host), - _port(port) + _jawOpenIndex(21) { _blendshapeCoefficients.resize(NUM_EXPRESSION); @@ -80,18 +80,6 @@ DdeFaceTracker::~DdeFaceTracker() { } } -void DdeFaceTracker::init() { - -} - -void DdeFaceTracker::reset() { - _reset = true; -} - -void DdeFaceTracker::update() { - -} - void DdeFaceTracker::setEnabled(bool enabled) { // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. _udpSocket.close(); diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index bd5d066732..88528370a2 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -23,12 +23,10 @@ class DdeFaceTracker : public FaceTracker, public Dependency { SINGLETON_DEPENDENCY public: - //initialization - void init(); - void reset(); - void update(); - - bool isActive() const; + virtual void reset() { _reset = true; } + + virtual bool isActive() const; + virtual bool isTracking() const { return isActive(); } float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); } diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 2f541c1c4e..87ee0ef31c 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -25,37 +25,11 @@ using namespace fs; using namespace std; +const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; const quint16 FACESHIFT_PORT = 33433; -float STARTING_FACESHIFT_FRAME_TIME = 0.033f; +const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; Faceshift::Faceshift() : - _tcpEnabled(true), - _tcpRetryCount(0), - _lastTrackingStateReceived(0), - _averageFrameTime(STARTING_FACESHIFT_FRAME_TIME), - _headAngularVelocity(0), - _headLinearVelocity(0), - _lastHeadTranslation(0), - _filteredHeadTranslation(0), - _eyeGazeLeftPitch(0.0f), - _eyeGazeLeftYaw(0.0f), - _eyeGazeRightPitch(0.0f), - _eyeGazeRightYaw(0.0f), - _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes - _rightBlinkIndex(1), - _leftEyeOpenIndex(8), - _rightEyeOpenIndex(9), - _browDownLeftIndex(14), - _browDownRightIndex(15), - _browUpCenterIndex(16), - _browUpLeftIndex(17), - _browUpRightIndex(18), - _mouthSmileLeftIndex(28), - _mouthSmileRightIndex(29), - _jawOpenIndex(21), - _longTermAverageEyePitch(0.0f), - _longTermAverageEyeYaw(0.0f), - _longTermAverageInitialized(false), _eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION), _hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME) { @@ -71,31 +45,15 @@ Faceshift::Faceshift() : #endif } +#ifdef HAVE_FACESHIFT void Faceshift::init() { -#ifdef HAVE_FACESHIFT setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift)); -#endif } -bool Faceshift::isConnectedOrConnecting() const { - return _tcpSocket.state() == QAbstractSocket::ConnectedState || - (_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState); -} - -bool Faceshift::isActive() const { -#ifdef HAVE_FACESHIFT - const quint64 ACTIVE_TIMEOUT_USECS = 1000000; - return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS; -#else - return false; -#endif -} - -void Faceshift::update() { +void Faceshift::update(float deltaTime) { if (!isActive()) { return; } - PerformanceTimer perfTimer("faceshift"); // get the euler angles relative to the window glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3( (_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f))))); @@ -116,14 +74,28 @@ void Faceshift::update() { } void Faceshift::reset() { -#ifdef HAVE_FACESHIFT if (_tcpSocket.state() == QAbstractSocket::ConnectedState) { string message; fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral()); send(message); } _longTermAverageInitialized = false; +} + +bool Faceshift::isActive() const { + const quint64 ACTIVE_TIMEOUT_USECS = 1000000; + return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS; +} + +bool Faceshift::isTracking() const { + return isActive() && _tracking; +} #endif + + +bool Faceshift::isConnectedOrConnecting() const { + return _tcpSocket.state() == QAbstractSocket::ConnectedState || + (_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState); } void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float browUp, @@ -148,12 +120,13 @@ void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float } void Faceshift::setTCPEnabled(bool enabled) { +#ifdef HAVE_FACESHIFT if ((_tcpEnabled = enabled)) { connectSocket(); - } else { _tcpSocket.disconnectFromHost(); } +#endif } void Faceshift::connectSocket() { @@ -202,10 +175,6 @@ void Faceshift::readFromSocket() { receive(_tcpSocket.readAll()); } -float Faceshift::getBlendshapeCoefficient(int index) const { - return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f; -} - void Faceshift::send(const std::string& message) { _tcpSocket.write(message.data(), message.size()); } diff --git a/interface/src/devices/Faceshift.h b/interface/src/devices/Faceshift.h index 0cef3d3e13..f224448b8e 100644 --- a/interface/src/devices/Faceshift.h +++ b/interface/src/devices/Faceshift.h @@ -24,8 +24,7 @@ #include "FaceTracker.h" -const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; -const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost"; +const float STARTING_FACESHIFT_FRAME_TIME = 0.033f; /// Handles interaction with the Faceshift software, which provides head position/orientation and facial features. class Faceshift : public FaceTracker, public Dependency { @@ -33,11 +32,17 @@ class Faceshift : public FaceTracker, public Dependency { SINGLETON_DEPENDENCY public: - void init(); +#ifdef HAVE_FACESHIFT + // If we don't have faceshift, use the base class' methods + virtual void init(); + virtual void update(float deltaTime); + virtual void reset(); - bool isConnectedOrConnecting() const; + virtual bool isActive() const; + virtual bool isTracking() const; +#endif - bool isActive() const; + bool isConnectedOrConnecting() const; const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; } @@ -68,9 +73,6 @@ public: QString getHostname() { return _hostname.get(); } void setHostname(const QString& hostname); - - void update(); - void reset(); void updateFakeCoefficients(float leftBlink, float rightBlink, @@ -82,15 +84,12 @@ public: QVector& coefficients) const; signals: - void connectionStateChanged(); public slots: - void setTCPEnabled(bool enabled); private slots: - void connectSocket(); void noteConnected(); void noteError(QAbstractSocket::SocketError error); @@ -101,8 +100,6 @@ private: Faceshift(); virtual ~Faceshift() {} - float getBlendshapeCoefficient(int index) const; - void send(const std::string& message); void receive(const QByteArray& buffer); @@ -113,48 +110,48 @@ private: fs::fsBinaryStream _stream; #endif - bool _tcpEnabled; - int _tcpRetryCount; - bool _tracking; - quint64 _lastTrackingStateReceived; - float _averageFrameTime; + bool _tcpEnabled = true; + int _tcpRetryCount = 0; + bool _tracking = false; + quint64 _lastTrackingStateReceived = 0; + float _averageFrameTime = STARTING_FACESHIFT_FRAME_TIME; - glm::vec3 _headAngularVelocity; - glm::vec3 _headLinearVelocity; - glm::vec3 _lastHeadTranslation; - glm::vec3 _filteredHeadTranslation; + glm::vec3 _headAngularVelocity = glm::vec3(0.0f); + glm::vec3 _headLinearVelocity = glm::vec3(0.0f); + glm::vec3 _lastHeadTranslation = glm::vec3(0.0f); + glm::vec3 _filteredHeadTranslation = glm::vec3(0.0f); // degrees - float _eyeGazeLeftPitch; - float _eyeGazeLeftYaw; - float _eyeGazeRightPitch; - float _eyeGazeRightYaw; - - int _leftBlinkIndex; - int _rightBlinkIndex; - int _leftEyeOpenIndex; - int _rightEyeOpenIndex; - - // Brows - int _browDownLeftIndex; - int _browDownRightIndex; - int _browUpCenterIndex; - int _browUpLeftIndex; - int _browUpRightIndex; - - int _mouthSmileLeftIndex; - int _mouthSmileRightIndex; - - int _jawOpenIndex; + float _eyeGazeLeftPitch = 0.0f; + float _eyeGazeLeftYaw = 0.0f; + float _eyeGazeRightPitch = 0.0f; + float _eyeGazeRightYaw = 0.0f; // degrees - float _longTermAverageEyePitch; - float _longTermAverageEyeYaw; - bool _longTermAverageInitialized; + float _longTermAverageEyePitch = 0.0f; + float _longTermAverageEyeYaw = 0.0f; + bool _longTermAverageInitialized = false; Setting::Handle _eyeDeflection; Setting::Handle _hostname; + // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes + int _leftBlinkIndex = 0; + int _rightBlinkIndex = 1; + int _leftEyeOpenIndex = 8; + int _rightEyeOpenIndex = 9; + + // Brows + int _browDownLeftIndex = 14; + int _browDownRightIndex = 15; + int _browUpCenterIndex = 16; + int _browUpLeftIndex = 17; + int _browUpRightIndex = 18; + + int _mouthSmileLeftIndex = 28; + int _mouthSmileRightIndex = 29; + + int _jawOpenIndex = 21; }; #endif // hifi_Faceshift_h diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 39bda83e61..45c19a6ab3 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -126,13 +126,12 @@ void Visage::init() { updateEnabled(); } -void Visage::update() { +void Visage::update(float deltaTime) { #ifdef HAVE_VISAGE _active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK); if (!_active) { return; } - PerformanceTimer perfTimer("visage"); _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin) * TRANSLATION_SCALE; diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index 690a9f3066..cd2ec3ecad 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -31,12 +31,12 @@ class Visage : public FaceTracker, public Dependency { SINGLETON_DEPENDENCY public: - void init(); + virtual void init(); + virtual void update(float deltaTime); + virtual void reset(); - bool isActive() const { return _active; } - - void update(); - void reset(); + virtual bool isActive() const { return _active; } + virtual bool isTracking() const { return isActive(); } public slots: From f560f97c6b5c1ed0b3381a8be5439843caaeec51 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 19:18:05 +0100 Subject: [PATCH 258/341] Only update active FaceTracker --- interface/src/Application.cpp | 36 ++++------------------------------- interface/src/Application.h | 3 --- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bdd8f8f53..e1b4aa40ea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1859,35 +1859,6 @@ void Application::updateMouseRay() { } } -void Application::updateFaceshift() { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateFaceshift()"); - auto faceshift = DependencyManager::get(); - // Update faceshift - faceshift->update(); - - // Copy angular velocity if measured by faceshift, to the head - if (faceshift->isActive()) { - _myAvatar->getHead()->setAngularVelocity(faceshift->getHeadAngularVelocity()); - } -} - -void Application::updateVisage() { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateVisage()"); - - // Update Visage - DependencyManager::get()->update(); -} - -void Application::updateDDE() { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateDDE()"); - - // Update Cara - DependencyManager::get()->update(); -} - void Application::updateMyAvatarLookAtPosition() { PerformanceTimer perfTimer("lookAt"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -2067,12 +2038,13 @@ void Application::update(float deltaTime) { { PerformanceTimer perfTimer("devices"); DeviceTracker::updateAll(); - updateFaceshift(); - updateVisage(); + FaceTracker* tracker = getActiveFaceTracker(); + if (tracker) { + tracker->update(deltaTime); + } SixenseManager::getInstance().update(deltaTime); JoystickScriptingInterface::getInstance().update(); _prioVR.update(deltaTime); - } // Dispatch input events diff --git a/interface/src/Application.h b/interface/src/Application.h index 9cd19c8259..4a8e712d30 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -421,9 +421,6 @@ private: // Various helper functions called during update() void updateLOD(); void updateMouseRay(); - void updateFaceshift(); - void updateVisage(); - void updateDDE(); void updateMyAvatarLookAtPosition(); void updateThreads(float deltaTime); void updateMetavoxels(float deltaTime); From 682b3f5e61c109a659e8f2ea11a2926b92dc6049 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 19:18:52 +0100 Subject: [PATCH 259/341] Remove unused angular velocity --- interface/src/avatar/Head.cpp | 1 - interface/src/avatar/Head.h | 4 ---- 2 files changed, 5 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 52f1b3ee86..a6458c7a22 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -42,7 +42,6 @@ Head::Head(Avatar* owningAvatar) : _mouth2(0.0f), _mouth3(0.0f), _mouth4(0.0f), - _angularVelocity(0,0,0), _renderLookatVectors(false), _saccade(0.0f, 0.0f, 0.0f), _saccadeTarget(0.0f, 0.0f, 0.0f), diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 89eea35903..6c53c2d7aa 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -55,9 +55,6 @@ public: /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; - - const glm::vec3& getAngularVelocity() const { return _angularVelocity; } - void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); glm::vec3 getCorrectedLookAtPosition(); @@ -130,7 +127,6 @@ private: float _mouth2; float _mouth3; float _mouth4; - glm::vec3 _angularVelocity; bool _renderLookatVectors; glm::vec3 _saccade; glm::vec3 _saccadeTarget; From e37ef226fc6b04378d2d8ce48960dc49d5cd4312 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 19:21:14 +0100 Subject: [PATCH 260/341] Simplify lookForward compute --- interface/src/avatar/MyAvatar.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ba628ea0d4..9cdd38dbc8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -892,13 +892,7 @@ void MyAvatar::updateLookAtTargetAvatar() { _lookAtTargetAvatar.clear(); _targetAvatarPosition = glm::vec3(0.0f); - glm::quat faceRotation = Application::getInstance()->getViewFrustum()->getOrientation(); - FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); - if (tracker) { - // If faceshift or other face tracker in use, add on the actual angle of the head - faceRotation *= tracker->getHeadRotation(); - } - glm::vec3 lookForward = faceRotation * IDENTITY_FRONT; + glm::vec3 lookForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FRONT; glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.0f; From 36c3131524a2005cdc11e76ffaf8434751b8f4fd Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Fri, 27 Feb 2015 00:14:46 +0530 Subject: [PATCH 261/341] Rectifying bad merge in BUILD.md and BUILD_WIN.md --- BUILD.md | 37 ++++++--- BUILD_WIN.md | 153 +++++-------------------------------- tools/vhacd/CMakeLists.txt | 4 +- tools/vhacd/src/main.cpp | 5 +- 4 files changed, 50 insertions(+), 149 deletions(-) diff --git a/BUILD.md b/BUILD.md index 82cbf6628c..98b8cffab1 100644 --- a/BUILD.md +++ b/BUILD.md @@ -2,15 +2,31 @@ * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.12.2 * [Qt](http://qt-project.org/downloads) ~> 5.3.2 -* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. -* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 -* [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 -* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 -* [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version) -### OS Specific Build Guides +####CMake External Project Dependencies + +* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 +* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3 +* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.4 +* [gverb](https://github.com/highfidelity/gverb) +* [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 + +The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile QXmpp you would pass -DGET_QXMPP=1. + +* [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3 + * Enables game controller support in Interface +* [QXmpp](https://github.com/qxmpp-project/qxmpp) ~> 0.7.6 + * Enables text chat support in Interface + +The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project. + +These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build-ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build-ext` folder. + +If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DGET_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project. + +###OS Specific Build Guides * [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X. * [BUILD_LINUX.md](BUILD_LINUX.md) - additional instructions for Linux. * [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows. @@ -45,6 +61,9 @@ For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generat cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.3.2/lib/cmake ####Finding Dependencies + +The following applies for dependencies we do not grab via CMake ExternalProject (OpenSSL is an example), or for dependencies you have opted not to grab as a CMake ExternalProject (via -DGET_$NAME=0). The list of dependencies we grab by default as external projects can be found in [the CMake External Project Dependencies section](#cmake-external-project-dependencies). + You can point our [Cmake find modules](cmake/modules/) to the correct version of dependencies by setting one of the three following variables to the location of the correct version of the dependency. In the examples below the variable $NAME would be replaced by the name of the dependency in uppercase, and $name would be replaced by the name of the dependency in lowercase (ex: OPENSSL_ROOT_DIR, openssl). @@ -55,12 +74,6 @@ In the examples below the variable $NAME would be replaced by the name of the de ###Optional Components -####QXmpp - -You can [find QXmpp here](https://github.com/qxmpp-project/qxmpp), 0.7.6 is the version you want. The inclusion of the QXmpp enables text chat in the Interface client. - -OS X users who tap our [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) can install QXmpp via homebrew - `brew install highfidelity/formulas/qxmpp`. - ####Devices You can support external input/output devices such as Oculus Rift, Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 8022fae5b8..28d26d9eb4 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,12 +1,6 @@ Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file. -###Windows Specific Dependencies -* [GLEW](http://glew.sourceforge.net/) ~> 1.10.0 -* [freeglut MSVC](http://www.transmissionzero.co.uk/software/freeglut-devel/) ~> 2.8.1 -* [zLib](http://www.zlib.net/) ~> 1.2.8 -* (remember that you need all other dependencies listed in [BUILD.md](BUILD.md)) - -####Visual Studio 2013 +###Visual Studio 2013 You can use the Community or Professional editions of Visual Studio 2013. @@ -16,10 +10,22 @@ Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" -#####Windows SDK 8.1 +####Windows SDK 8.1 If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. +####nmake & msbuild + +Some of the external projects may require nmake and msbuild to compile and install. If they are not installed at the locations listed below, please ensure that both are in your PATH so CMake can find them when required. + +We expect nmake.exe to be located at the following path. + + C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin + +We expect msbuild.exe to be located at the following path. + + C:\Program Files (x86)\MSBUILD\12.0\Bin + ###Qt You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version. @@ -32,9 +38,8 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit * [Download the offline installer](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe) Once Qt is installed, you need to manually configure the following: -* Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.3.2\msvc2013_opengl\bin\`. -* Go to Control Panel > System > Advanced System Settings > Environment Variables > New ... -* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl` directory. +* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl\lib\cmake` directory. + * You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New ###External Libraries @@ -42,40 +47,19 @@ As it stands, Hifi/Interface is a 32-bit application, so all libraries should al CMake will need to know where the headers and libraries for required external dependencies are. +We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required. + The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir - -> bullet - -> include - -> lib - -> freeglut - -> bin - -> include - -> lib - -> glew - -> bin - -> include - -> lib - -> glm - -> glm - -> glm.hpp -> openssl -> bin -> include -> lib - -> tbb - -> include - -> lib - -> zlib - -> include - -> lib - -> test For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. From here on, whenever you see %HIFI_LIB_DIR% you should substitute the directory that you chose. -As with the Qt libraries, you will need to make sure that directories containing DLL'S are in your path. Where possible, you can use static builds of the external dependencies to avoid this requirement. - -###OpenSSL +####OpenSSL Qt will use OpenSSL if it's available, but it doesn't install it, so you must install it separately. @@ -95,107 +79,10 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. -###Intel Threading Building Blocks (TBB) - -Download the zip from the [TBB website](https://www.threadingbuildingblocks.org/). - -We recommend you extract it to %HIFI_LIB_DIR%\tbb. This will help our FindTBB cmake module find what it needs. You can place it wherever you like on your machine if you specify TBB_ROOT_DIR as an environment variable or a variable passed when cmake is run. - -###Zlib - -Download the compiled DLL from the [zlib website](http://www.zlib.net/). Extract to %HIFI_LIB_DIR%\zlib. - -Add the following environment variables (remember to substitute your own directory for %HIFI_LIB_DIR%): - - ZLIB_LIBRARY=%HIFI_LIB_DIR%\zlib\lib\zdll.lib - ZLIB_INCLUDE_DIR=%HIFI_LIB_DIR%\zlib\include - -Add to the PATH: `%HIFI_LIB_DIR%\zlib` - -(The PATH environment variable is where Windows looks for its DLL's and executables. There's a great tool for editing these variables with ease, [Rapid Environment Editor](http://www.rapidee.com/en/download)) - -Important! This should be added at the beginning of the path, not the end (your -system likely has many copies of zlib1.dll, and you want High Fidelity to use the correct version). If High Fidelity picks up the wrong zlib1.dll then it might be unable to use it, and that would cause it to fail to start, showing only the cryptic error "The application was unable to start correctly: 0xc0000022". - -###freeglut - -Download the binary package: `freeglut-MSVC-2.8.1-1.mp.zip`. Extract to %HIFI_LIB_DIR%\freeglut. - -Add to the PATH: `%HIFI_LIB_DIR%\freeglut\bin` - -###GLEW - -Download the binary package: `glew-1.10.0-win32.zip`. Extract to %HIFI_LIB_DIR%\glew (you'll need to rename the default directory name). - -Add to the PATH: `%HIFI_LIB_DIR%\glew\bin\Release\Win32` - -###GLM - -This package contains only headers, so there's nothing to add to the PATH. - -Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder. - -###Gverb - -1. Go to https://github.com/highfidelity/gverb - Or download the sources directly via this link: - https://github.com/highfidelity/gverb/archive/master.zip - -2. Extract the archive - -3. Place the directories “include” and “src” in interface/external/gverb - (Normally next to this readme) - -4. Clear your build directory, run cmake, build and you should be all set. - - -###Bullet - -Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself. - -* Download the zip file and extract into a temporary folder -* Create a directory named cmakebuild. Bullet comes with a build\ directory by default, however, that directory is intended for use with premake, and considering premake doesn't support VS2013, we prefer to run the cmake build on its own directory. -* Make the following modifications to Bullet's source: - 1. In file: Extras\HACD\hacdICHull.cpp --- in line: 17 --- insert: #include <algorithm> - 2. In file: src\MiniCL\cl_MiniCL_Defs.h --- comment lines 364 to 372 - 3. In file: CMakeLists.txt set to ON the option USE_MSVC_RUNTIME_LIBRARY_DLL in line 27 - -Then create the Visual Studio solution and build the libraries - run the following commands from a Visual Studio 2013 command prompt, from within the cmakebuild directory created before: - -```shell -cmake .. -G "Visual Studio 12" -msbuild BULLET_PHYSICS.sln /p:Configuration=Debug -``` - -This will create Debug libraries in cmakebuild\lib\Debug. You can replace Debug with Release in the msbuild command and that will generate Release libraries in cmakebuild\lib\Release. - -You now have Bullet libraries compiled, now you need to put them in the right place for hifi to find them: - -* Create a directory named bullet\ inside your %HIFI_LIB_DIR% -* Create two directores named lib\ and include\ inside bullet\ -* Copy all the contents inside src\ from the bullet unzip path into %HIFI_LIB_DIR%\bullet\include\ -* Copy all the contents inside cmakebuild\lib\ into %HIFI_LIB_DIR\bullet\lib - -_Note that the INSTALL target should handle the copying of files into an install directory automatically, however, without modifications to Cmake, the install target didn't work right for me, please update this instructions if you get that working right - Leo <leo@highfidelity.io>_ - -###Soxr - -Download the zip from the [soxr sourceforge page](http://sourceforge.net/projects/soxr/). - -We recommend you install it to %HIFI_LIB_DIR%\soxr. This will help our FindSoxr cmake module find what it needs. You can place it wherever you like on your machine if you specify SOXR_ROOT_DIR as an environment variable or a variable passed when cmake is run. - -Extract the soxr archive wherever you like. Then, inside the extracted folder, create a directory called `build`. From that build directory, the following commands will build and then install soxr to `%HIFI_LIB_DIR%`. - -``` -cmake .. -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=%HIFI_LIB_DIR%/soxr -nmake -nmake install -``` - ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. - cmake .. -DZLIB_LIBRARY=%ZLIB_LIBRARY% -DZLIB_INCLUDE_DIR=%ZLIB_INCLUDE_DIR% -G "Visual Studio 12" + cmake .. -G "Visual Studio 12" Open %HIFI_DIR%\build\hifi.sln and compile. diff --git a/tools/vhacd/CMakeLists.txt b/tools/vhacd/CMakeLists.txt index db0cc13e67..31a7f7c8e2 100644 --- a/tools/vhacd/CMakeLists.txt +++ b/tools/vhacd/CMakeLists.txt @@ -18,8 +18,6 @@ if(NOT WIN32) endif() endif() -add_dependency_external_project(glm) +add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) - -include_dependency_includes() diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp index 31866a7cfc..3d7f2d7504 100644 --- a/tools/vhacd/src/main.cpp +++ b/tools/vhacd/src/main.cpp @@ -27,7 +27,10 @@ int main(int argc, char * argv[]){ vhacd::ComputeResults results; // results after computing vhacd VHACD::IVHACD::Parameters params; vhacd::ProgressCallback pCallBack; - + if (argc < 2){ + cout << "please provide a FBX file as argument\n "; + return 1; + } string filename(argv[1]); if (filename.empty()){ cout << "please provide a FBX file as argument\n "; From fcb293d0b2155d4334610dc6448a2073356bbca7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 10:45:00 -0800 Subject: [PATCH 262/341] CLean up before pr --- examples/example/misc/sunLightExample.js | 1 - interface/src/Application.cpp | 4 -- libraries/model/src/model/Stage.cpp | 56 +++++++++++++++++------- libraries/model/src/model/Stage.h | 55 +---------------------- 4 files changed, 42 insertions(+), 74 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 0bc3b0dfea..7f38211052 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -26,7 +26,6 @@ function ticktack() { Scene.setYearTime(day); } Scene.setDayTime(hour); - } Script.setInterval(ticktack, 41); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 298814f484..46fec006ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2493,8 +2493,6 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin - // return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); - auto skyStage = DependencyManager::get()->getSkyStage(); return skyStage->getSunLight()->getDirection(); } @@ -2875,9 +2873,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); - // DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); auto skyStage = DependencyManager::get()->getSkyStage(); -// DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, skyStage->_light->getIntensity()); DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity()); PROFILE_RANGE("DeferredLighting"); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index dcd633f35c..12ed186cf6 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -21,8 +21,6 @@ void EarthSunModel::updateAll() const { } Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { - - // Longitude is along Z axis but - from east to west Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); @@ -54,9 +52,7 @@ void EarthSunModel::updateWorldToSurface() const { _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); } -void EarthSunModel::updateSurfaceToEye() const -{ - +void EarthSunModel::updateSurfaceToEye() const { _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; @@ -76,8 +72,7 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); -} - +} float moduloRange(float val, float minVal, float maxVal) { float range = maxVal - minVal; @@ -86,30 +81,48 @@ float moduloRange(float val, float minVal, float maxVal) { return modf(rval, &intval) * range + minVal; } +const float MAX_LONGITUDE = 180.0f; +const float MAX_LATITUDE = 90.0f; + +float validateLongitude(float lon) { + return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); +} + +float validateLatitude(float lat) { + return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); +} + +float validateAltitude(float altitude) { + const float MIN_ALTITUDE = -1000.0f; + const float MAX_ALTITUDE = 100000.0f; + return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); +} + void EarthSunModel::setLatitude(float lat) { - _latitude = moduloRange(lat, -90.0f, 90.0f); + _latitude = validateLatitude(lat); invalidate(); } void EarthSunModel::setLongitude(float lon) { - _longitude = moduloRange(lon, -180.0f, 180.0f); + _longitude = validateLongitude(lon); invalidate(); } void EarthSunModel::setAltitude(float altitude) { - _altitude = moduloRange(altitude, -1000.f, 100000.f); + _altitude = validateAltitude(altitude); invalidate(); } void EarthSunModel::setSunLatitude(float lat) { - _sunLatitude = moduloRange(lat, -90.0f, 90.0f); + _sunLatitude = validateLatitude(lat); invalidate(); } void EarthSunModel::setSunLongitude(float lon) { - _sunLongitude = moduloRange(lon, -180.0f, 180.0f); + _sunLongitude = validateLongitude(lon); invalidate(); } const int NUM_DAYS_PER_YEAR = 365; const float NUM_HOURS_PER_DAY = 24.0f; +const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; SunSkyStage::SunSkyStage() : _sunLight(new Light()) @@ -119,8 +132,11 @@ SunSkyStage::SunSkyStage() : setSunIntensity(1.0f); setSunColor(Vec3(1.0f, 1.0f, 1.0f)); - // setOriginLocation(45.0f, 20.0f, 1.0f); + // Default origin location is a special place in the world... + setOriginLocation(122.407f, 37.777f, 0.03f); + // 6pm setDayTime(18.0f); + // Begining of march setYearTime(60.0f); } @@ -151,12 +167,20 @@ void SunSkyStage::setSunIntensity(float intensity) { _sunLight->setIntensity(intensity); } +// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclinaison(double dayNumber) { + return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); +} + void SunSkyStage::updateGraphicsObject() const { - // Always update the sunLongitude based on the current dayTIme and the current origin - _earthSunModel.setSunLongitude(_earthSunModel.getLongitude() + (-180.0 + 360.0 * _dayTime / NUM_HOURS_PER_DAY)); + // Always update the sunLongitude based on the current dayTime and the current origin + // The day time is supposed to be local at the origin + double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; + double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); + _earthSunModel.setSunLongitude(sunLongitude); // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(-(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(_yearTime + 10)))); + _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 9b2922e163..f99d2c1648 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -22,16 +22,6 @@ typedef glm::mat4 Mat4; class EarthSunModel { public: - enum Preset - { - Toulouse = 0, - SanFrancisco, - Sydney, - Num_Presets, - }; - static const std::string PresetNames[Num_Presets]; - //void assignPreset( Preset p); - //Preset preset() const { return mPreset; } void setScale(float scale); float getScale() const { return _scale; } @@ -108,46 +98,6 @@ protected: static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); }; -namespace gpu { - class Batch; -}; - -class ProgramObject; - -class Skybox { -public: - void recordBatch(gpu::Batch& batch, const Transform& viewTransform, const Mat4& projection); - - Skybox(); - ~Skybox(); -protected: - ProgramObject* createSkyProgram(const char* from, int* locations); - ProgramObject* _skyFromAtmosphereProgram; - ProgramObject* _skyFromSpaceProgram; - enum { - CAMERA_POS_LOCATION, - LIGHT_POS_LOCATION, - INV_WAVELENGTH_LOCATION, - CAMERA_HEIGHT2_LOCATION, - OUTER_RADIUS_LOCATION, - OUTER_RADIUS2_LOCATION, - INNER_RADIUS_LOCATION, - KR_ESUN_LOCATION, - KM_ESUN_LOCATION, - KR_4PI_LOCATION, - KM_4PI_LOCATION, - SCALE_LOCATION, - SCALE_DEPTH_LOCATION, - SCALE_OVER_SCALE_DEPTH_LOCATION, - G_LOCATION, - G2_LOCATION, - LOCATION_COUNT - }; - - int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; - int _skyFromSpaceUniformLocations[LOCATION_COUNT]; -}; - // Sun sky stage generates the rendering primitives to display a scene realistically // at the specified location and time around earth class SunSkyStage { @@ -181,9 +131,8 @@ public: protected: LightPointer _sunLight; - // default day is 1st of january at noun - float _dayTime = 12.0f; - int _yearTime = 0; + float _dayTime; + int _yearTime; mutable EarthSunModel _earthSunModel; From 95839dd64e9caec0138efb7f6a308b23bd0da0f3 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Fri, 27 Feb 2015 00:27:18 +0530 Subject: [PATCH 263/341] untabify the source files --- tools/vhacd/src/VHACDUtil.cpp | 155 ++++++++++++++++----------------- tools/vhacd/src/VHACDUtil.h | 47 +++++----- tools/vhacd/src/main.cpp | 157 +++++++++++++++++----------------- 3 files changed, 180 insertions(+), 179 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index 95e78b212d..d4ab9d7c8a 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -16,104 +16,105 @@ //Read all the meshes from provided FBX file bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *results){ - // open the fbx file - QFile fbx(filename); - if (!fbx.open(QIODevice::ReadOnly)) { - return false; - } - std::cout << "Reading FBX.....\n"; + // open the fbx file + QFile fbx(filename); + if (!fbx.open(QIODevice::ReadOnly)) { + return false; + } + std::cout << "Reading FBX.....\n"; - QByteArray fbxContents = fbx.readAll(); - FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); - //results->meshCount = geometry.meshes.count(); - - int count = 0; - foreach(FBXMesh mesh, geometry.meshes) { - //get vertices for each mesh - QVector vertices = mesh.vertices; + QByteArray fbxContents = fbx.readAll(); + FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); + //results->meshCount = geometry.meshes.count(); + + int count = 0; + foreach(FBXMesh mesh, geometry.meshes) { + //get vertices for each mesh + QVector vertices = mesh.vertices; - //get the triangle indices for each mesh - QVector triangles; - foreach(FBXMeshPart part, mesh.parts) { - QVector indices = part.triangleIndices; - triangles += indices; - } + //get the triangle indices for each mesh + QVector triangles; + foreach(FBXMeshPart part, mesh.parts) { + QVector indices = part.triangleIndices; + triangles += indices; + } - //only read meshes with triangles - if (triangles.count() <= 0) - continue; - results->perMeshVertices.append(vertices); - results->perMeshTriangleIndices.append(triangles); - count++; - } + //only read meshes with triangles + if (triangles.count() <= 0) + continue; + results->perMeshVertices.append(vertices); + results->perMeshTriangleIndices.append(triangles); + count++; + } - results->meshCount = count; - return true; + results->meshCount = count; + return true; } bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const{ - VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); - int meshCount = meshes->meshCount; - int count = 0; - std::cout << "Performing V-HACD computation on " << meshCount <<" meshes ..... " << std::endl; + VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); + int meshCount = meshes->meshCount; + int count = 0; + std::cout << "Performing V-HACD computation on " << meshCount <<" meshes ..... " << std::endl; - for (int i = 0; i < meshCount; i++){ - - std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); - std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); - int nPoints = (unsigned int)vertices.size(); - int nTriangles = (unsigned int)triangles.size() / 3; - std::cout << "Mesh " << i + 1 << " : "; - // compute approximate convex decomposition - bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, nTriangles, params); - if (!res){ - std::cout << "V-HACD computation failed for Mesh : " << i + 1 << std::endl; - continue; - } - count++; //For counting number of successfull computations + for (int i = 0; i < meshCount; i++){ + + std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); + std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); + int nPoints = (unsigned int)vertices.size(); + int nTriangles = (unsigned int)triangles.size() / 3; + std::cout << "Mesh " << i + 1 << " : "; + // compute approximate convex decomposition + bool res = interfaceVHACD->Compute(&vertices[0].x, 3, nPoints, &triangles[0], 3, nTriangles, params); + if (!res){ + std::cout << "V-HACD computation failed for Mesh : " << i + 1 << std::endl; + continue; + } + count++; //For counting number of successfull computations - //Number of hulls for the mesh - unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); - results->convexHullsCountList.append(nConvexHulls); + //Number of hulls for the mesh + unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); + results->convexHullsCountList.append(nConvexHulls); - //get all the convex hulls for this mesh - QVector convexHulls; - for (unsigned int j = 0; j < nConvexHulls; j++){ - VHACD::IVHACD::ConvexHull hull; - interfaceVHACD->GetConvexHull(j, hull); - convexHulls.append(hull); - } - results->convexHullList.append(convexHulls); - } //end of for loop + //get all the convex hulls for this mesh + QVector convexHulls; + for (unsigned int j = 0; j < nConvexHulls; j++){ + VHACD::IVHACD::ConvexHull hull; + interfaceVHACD->GetConvexHull(j, hull); + convexHulls.append(hull); + } + results->convexHullList.append(convexHulls); + } //end of for loop - results->meshCount = count; + results->meshCount = count; - //release memory - interfaceVHACD->Clean(); - interfaceVHACD->Release(); + //release memory + interfaceVHACD->Clean(); + interfaceVHACD->Release(); - if (count > 0) - return true; - else - return false; + if (count > 0) + return true; + else + return false; } vhacd::VHACDUtil:: ~VHACDUtil(){ - //nothing to be cleaned + //nothing to be cleaned } //ProgressClaback implementation -void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation){ - int progress = (int)(overallProgress + 0.5); +void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, + const char * const stage, const char * const operation){ + int progress = (int)(overallProgress + 0.5); - if (progress < 10) - std::cout << "\b\b"; - else - std::cout << "\b\b\b"; - std::cout << progress << "%"; + if (progress < 10) + std::cout << "\b\b"; + else + std::cout << "\b\b\b"; + std::cout << progress << "%"; - if (progress >= 100) - std::cout << std::endl; + if (progress >= 100) + std::cout << std::endl; } diff --git a/tools/vhacd/src/VHACDUtil.h b/tools/vhacd/src/VHACDUtil.h index 036d4ce526..b87ba07ff0 100644 --- a/tools/vhacd/src/VHACDUtil.h +++ b/tools/vhacd/src/VHACDUtil.h @@ -23,32 +23,33 @@ namespace vhacd{ - typedef struct{ - int meshCount; - QVector convexHullsCountList; - QVector> convexHullList; - }ComputeResults; + typedef struct{ + int meshCount; + QVector convexHullsCountList; + QVector> convexHullList; + }ComputeResults; - typedef struct{ - int meshCount; - QVector> perMeshVertices; - QVector> perMeshTriangleIndices; - }LoadFBXResults; + typedef struct{ + int meshCount; + QVector> perMeshVertices; + QVector> perMeshTriangleIndices; + }LoadFBXResults; - class VHACDUtil{ - public: - bool loadFBX(const QString filename, vhacd::LoadFBXResults *results); - bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const; - ~VHACDUtil(); - }; + class VHACDUtil{ + public: + bool loadFBX(const QString filename, vhacd::LoadFBXResults *results); + bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params, vhacd::ComputeResults *results)const; + ~VHACDUtil(); + }; - class ProgressCallback : public VHACD::IVHACD::IUserCallback{ - public: - ProgressCallback(void); - ~ProgressCallback(); + class ProgressCallback : public VHACD::IVHACD::IUserCallback{ + public: + ProgressCallback(void); + ~ProgressCallback(); - //Couldn't follow coding guideline here due to virtual function declared in IUserCallback - void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation); - }; + //Couldn't follow coding guideline here due to virtual function declared in IUserCallback + void Update(const double overallProgress, const double stageProgress, const double operationProgress, + const char * const stage, const char * const operation); + }; } #endif //hifi_VHACDUtil_h \ No newline at end of file diff --git a/tools/vhacd/src/main.cpp b/tools/vhacd/src/main.cpp index 3d7f2d7504..e43f712fa0 100644 --- a/tools/vhacd/src/main.cpp +++ b/tools/vhacd/src/main.cpp @@ -20,93 +20,92 @@ using namespace std; using namespace VHACD; int main(int argc, char * argv[]){ - vector triangles; // array of indexes - vector points; // array of coordinates - vhacd::VHACDUtil vUtil; - vhacd::LoadFBXResults fbx; //mesh data from loaded fbx file - vhacd::ComputeResults results; // results after computing vhacd - VHACD::IVHACD::Parameters params; - vhacd::ProgressCallback pCallBack; - if (argc < 2){ - cout << "please provide a FBX file as argument\n "; - return 1; - } - string filename(argv[1]); - if (filename.empty()){ - cout << "please provide a FBX file as argument\n "; - return 1; - } + vector triangles; // array of indexes + vector points; // array of coordinates + vhacd::VHACDUtil vUtil; + vhacd::LoadFBXResults fbx; //mesh data from loaded fbx file + vhacd::ComputeResults results; // results after computing vhacd + VHACD::IVHACD::Parameters params; + vhacd::ProgressCallback pCallBack; + if (argc < 2){ + cout << "please provide a FBX file as argument\n "; + return 1; + } + string filename(argv[1]); + if (filename.empty()){ + cout << "please provide a FBX file as argument\n "; + return 1; + } - QString fname = QString::fromStdString(filename); + QString fname = QString::fromStdString(filename); - //set parameters for V-HACD - params.m_callback = &pCallBack; //progress callback - params.m_resolution = 50000; - params.m_depth = 10; - params.m_concavity = 0.003; - params.m_alpha = 0.05; // controls the bias toward clipping along symmetry planes - params.m_pca = 1; // enable/disable normalizing the mesh before applying the convex decomposition - params.m_mode = 1; // 0: voxel - based approximate convex decomposition, 1 : tetrahedron - based approximate convex decomposition - params.m_maxNumVerticesPerCH = 128; - params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls + //set parameters for V-HACD + params.m_callback = &pCallBack; //progress callback + params.m_resolution = 50000; + params.m_depth = 10; + params.m_concavity = 0.003; + params.m_alpha = 0.05; // controls the bias toward clipping along symmetry planes + params.m_pca = 1; // enable/disable normalizing the mesh before applying the convex decomposition + params.m_mode = 1; // 0: voxel - based approximate convex decomposition, 1 : tetrahedron - based approximate convex decomposition + params.m_maxNumVerticesPerCH = 128; + params.m_minVolumePerCH = 0.0001; // controls the adaptive sampling of the generated convex - hulls - // load the mesh + // load the mesh - auto begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.loadFBX(fname, &fbx)){ - cout << "Error in opening FBX file...."; - return 1; - } - auto end = std::chrono::high_resolution_clock::now(); - auto loadDuration = std::chrono::duration_cast(end - begin).count(); + auto begin = std::chrono::high_resolution_clock::now(); + if (!vUtil.loadFBX(fname, &fbx)){ + cout << "Error in opening FBX file...."; + return 1; + } + auto end = std::chrono::high_resolution_clock::now(); + auto loadDuration = std::chrono::duration_cast(end - begin).count(); - //perform vhacd computation - begin = std::chrono::high_resolution_clock::now(); - if (!vUtil.computeVHACD(&fbx, params, &results)){ - cout << "Compute Failed..."; - return 1; - } - end = std::chrono::high_resolution_clock::now(); - auto computeDuration = std::chrono::duration_cast(end - begin).count(); + //perform vhacd computation + begin = std::chrono::high_resolution_clock::now(); + if (!vUtil.computeVHACD(&fbx, params, &results)){ + cout << "Compute Failed..."; + return 1; + } + end = std::chrono::high_resolution_clock::now(); + auto computeDuration = std::chrono::duration_cast(end - begin).count(); - int totalVertices = 0; - for (int i = 0; i < fbx.meshCount; i++){ - totalVertices += fbx.perMeshVertices.at(i).count(); - } + int totalVertices = 0; + for (int i = 0; i < fbx.meshCount; i++){ + totalVertices += fbx.perMeshVertices.at(i).count(); + } - int totalTriangles = 0; - for (int i = 0; i < fbx.meshCount; i++){ - totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); - } + int totalTriangles = 0; + for (int i = 0; i < fbx.meshCount; i++){ + totalTriangles += fbx.perMeshTriangleIndices.at(i).count(); + } - int totalHulls = 0; - QVector hullCounts = results.convexHullsCountList; - for (int i = 0; i < results.meshCount; i++){ - totalHulls += hullCounts.at(i); - } - cout << endl << "Summary of V-HACD Computation..................." << endl; - cout << "File Path : " << fname.toStdString() << endl; - cout << "Number Of Meshes : " << fbx.meshCount << endl; - cout << "Processed Meshes : " << results.meshCount << endl; - cout << "Total vertices : " << totalVertices << endl; - cout << "Total Triangles : " << totalTriangles << endl; - cout << "Total Convex Hulls : " << totalHulls << endl; - cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl; - cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl; - cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); - cout << "\t" << "Number Of Hulls : " << chList.count() << endl; + int totalHulls = 0; + QVector hullCounts = results.convexHullsCountList; + for (int i = 0; i < results.meshCount; i++){ + totalHulls += hullCounts.at(i); + } + cout << endl << "Summary of V-HACD Computation..................." << endl; + cout << "File Path : " << fname.toStdString() << endl; + cout << "Number Of Meshes : " << fbx.meshCount << endl; + cout << "Processed Meshes : " << results.meshCount << endl; + cout << "Total vertices : " << totalVertices << endl; + cout << "Total Triangles : " << totalTriangles << endl; + cout << "Total Convex Hulls : " << totalHulls << endl; + cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl; + cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl; + cout << endl << "Summary per convex hull ........................" << endl < chList = results.convexHullList.at(i); + cout << "\t" << "Number Of Hulls : " << chList.count() << endl; - for (int j = 0; j < results.convexHullList.at(i).count(); j++){ + for (int j = 0; j < results.convexHullList.at(i).count(); j++){ + cout << "\tHUll : " << j + 1 << endl; + cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; + cout << "\t\tNumber Of Triangles : " << chList.at(j).m_nTriangles << endl; + } + } - cout << "\tHUll : " << j + 1 << endl; - cout << "\t\tNumber Of Points : " << chList.at(j).m_nPoints << endl; - cout << "\t\tNumber Of Triangles : " << chList.at(j).m_nTriangles << endl; - } - } - - getchar(); - return 0; + getchar(); + return 0; } \ No newline at end of file From c3a72574391f35d4c0a6dabfa89fb24117b18b14 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 11:03:06 -0800 Subject: [PATCH 264/341] Remove unused light properties from entity properties window --- examples/html/entityProperties.html | 70 ++--------------------------- 1 file changed, 4 insertions(+), 66 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index ad2b359e79..38a2ca5ea8 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -132,17 +132,7 @@ var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green"); var elLightDiffuseBlue = document.getElementById("property-light-diffuse-blue"); - var elLightAmbientRed = document.getElementById("property-light-ambient-red"); - var elLightAmbientGreen = document.getElementById("property-light-ambient-green"); - var elLightAmbientBlue = document.getElementById("property-light-ambient-blue"); - - var elLightSpecularRed = document.getElementById("property-light-specular-red"); - var elLightSpecularGreen = document.getElementById("property-light-specular-green"); - var elLightSpecularBlue = document.getElementById("property-light-specular-blue"); - var elLightConstantAttenuation = document.getElementById("property-light-constant-attenuation"); - var elLightLinearAttenuation = document.getElementById("property-light-linear-attenuation"); - var elLightQuadraticAttenuation = document.getElementById("property-light-quadratic-attenuation"); var elLightExponent = document.getElementById("property-light-exponent"); var elLightCutoff = document.getElementById("property-light-cutoff"); @@ -294,17 +284,7 @@ elLightDiffuseGreen.value = properties.diffuseColor.green; elLightDiffuseBlue.value = properties.diffuseColor.blue; - elLightAmbientRed.value = properties.ambientColor.red; - elLightAmbientGreen.value = properties.ambientColor.green; - elLightAmbientBlue.value = properties.ambientColor.blue; - - elLightSpecularRed.value = properties.specularColor.red; - elLightSpecularGreen.value = properties.specularColor.green; - elLightSpecularBlue.value = properties.specularColor.blue; - elLightConstantAttenuation.value = properties.constantAttenuation; - elLightLinearAttenuation.value = properties.linearAttenuation; - elLightQuadraticAttenuation.value = properties.quadraticAttenuation; elLightExponent.value = properties.exponent; elLightCutoff.value = properties.cutoff; } @@ -381,21 +361,7 @@ elLightDiffuseGreen.addEventListener('change', lightDiffuseChangeFunction); elLightDiffuseBlue.addEventListener('change', lightDiffuseChangeFunction); - var lightAmbientChangeFunction = createEmitColorPropertyUpdateFunction( - 'ambientColor', elLightAmbientRed, elLightAmbientGreen, elLightAmbientBlue); - elLightAmbientRed.addEventListener('change', lightAmbientChangeFunction); - elLightAmbientGreen.addEventListener('change', lightAmbientChangeFunction); - elLightAmbientBlue.addEventListener('change', lightAmbientChangeFunction); - - var lightSpecularChangeFunction = createEmitColorPropertyUpdateFunction( - 'specularColor', elLightSpecularRed, elLightSpecularGreen, elLightSpecularBlue); - elLightSpecularRed.addEventListener('change', lightSpecularChangeFunction); - elLightSpecularGreen.addEventListener('change', lightSpecularChangeFunction); - elLightSpecularBlue.addEventListener('change', lightSpecularChangeFunction); - elLightConstantAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('constantAttenuation')); - elLightLinearAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('linearAttenuation')); - elLightQuadraticAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('quadraticAttenuation')); elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent')); elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff')); @@ -715,7 +681,7 @@
-
Diffuse
+
Color
R
G
@@ -723,47 +689,19 @@
-
Ambient
-
-
R
-
G
-
B
-
-
-
-
Specular
-
-
R
-
G
-
B
-
-
-
-
Constant Attenuation
+
Intensity
-
Linear Attenuation
-
- -
-
-
-
Quadratic Attenuation
-
- -
-
-
-
Exponent
+
Spot Light Exponent
-
Cutoff (degrees)
+
Spot Light Cutoff (degrees)
From e42b708b562d1fc9e7a916c110d7a5c726945305 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 11:03:47 -0800 Subject: [PATCH 265/341] Update deferredLightingEffect::add*Light methods --- interface/src/avatar/Avatar.cpp | 3 +-- .../src/RenderableLightEntityItem.cpp | 7 +++---- .../src/DeferredLightingEffect.cpp | 21 ++++++++++--------- .../render-utils/src/DeferredLightingEffect.h | 11 ++++------ 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6dc3d4b339..467f63ccef 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -380,8 +380,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool foreach (const AvatarManager::LocalLight& light, DependencyManager::get()->getLocalLights()) { glm::vec3 direction = orientation * light.direction; DependencyManager::get()->addSpotLight(position - direction * distance, - distance * 2.0f, glm::vec3(), light.color, light.color, 1.0f, 0.5f, 0.0f, direction, - LIGHT_EXPONENT, LIGHT_CUTOFF); + distance * 2.0f, light.color, 0.5f, orientation, LIGHT_EXPONENT, LIGHT_CUTOFF); } } diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 1e0a9b6fc7..978ca11d9d 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -48,7 +48,7 @@ void RenderableLightEntityItem::render(RenderArgs* args) { glm::vec3 diffuse = glm::vec3(diffuseR, diffuseG, diffuseB); glm::vec3 specular = glm::vec3(specularR, specularG, specularB); glm::vec3 direction = IDENTITY_FRONT * rotation; - float constantAttenuation = getConstantAttenuation(); + float intensity = getConstantAttenuation(); float linearAttenuation = getLinearAttenuation(); float quadraticAttenuation = getQuadraticAttenuation(); float exponent = getExponent(); @@ -56,11 +56,10 @@ void RenderableLightEntityItem::render(RenderArgs* args) { if (_isSpotlight) { DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, - ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation, - direction, exponent, cutoff); + diffuse, intensity, rotation, exponent, cutoff); } else { DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, - ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation); + diffuse, intensity); } #ifdef WANT_DEBUG diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 1f5d0ce4c3..5e203b041d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -126,15 +126,16 @@ void DeferredLightingEffect::renderSolidCone(float base, float height, int slice releaseSimpleProgram(); } -void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient, - const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, - float linearAttenuation, float quadraticAttenuation) { - addSpotLight(position, radius, ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation); +void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color, + float intensity) { + addSpotLight(position, radius, color, intensity); } -void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient, - const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation, - float quadraticAttenuation, const glm::vec3& direction, float exponent, float cutoff) { +// Remove: ambient, specular, *Attenuation, direction +// Add: intensity, radius +// Rename: diffuseColor -> color +void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color, + float intensity, const glm::quat& orientation, float exponent, float cutoff) { int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size(); if (lightID >= _allocatedLights.size()) { @@ -144,8 +145,8 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu lp->setPosition(position); lp->setMaximumRadius(radius); - lp->setColor(diffuse); - lp->setIntensity(1.0f); + lp->setColor(color); + lp->setIntensity(intensity); //lp->setShowContour(quadraticAttenuation); if (exponent == 0.0f && cutoff == PI) { @@ -153,7 +154,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu _pointLights.push_back(lightID); } else { - lp->setDirection(direction); + lp->setOrientation(orientation); lp->setSpotAngle(cutoff); lp->setSpotExponent(exponent); lp->setType(model::Light::SPOT); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index eeb92f19c7..c375f3eb52 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -57,15 +57,12 @@ public: void renderSolidCone(float base, float height, int slices, int stacks); /// Adds a point light to render for the current frame. - void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f), - const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f), - float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f); + void addPointLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(0.0f, 0.0f, 0.0f), + float intensity = 0.5f); /// Adds a spot light to render for the current frame. - void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f), - const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f), - float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f, - const glm::vec3& direction = glm::vec3(0.0f, 0.0f, -1.0f), float exponent = 0.0f, float cutoff = PI); + void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f), + float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI); /// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object). void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); } From fdf9fdd8778d38263c4c3c17d1228ddeb9e32e9c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 26 Feb 2015 20:05:47 +0100 Subject: [PATCH 266/341] Relax head/lean when not tracking --- interface/src/avatar/MyAvatar.cpp | 9 +------- interface/src/devices/FaceTracker.cpp | 30 +++++++++++++++++++++++++++ interface/src/devices/FaceTracker.h | 12 +++++------ interface/src/devices/Faceshift.cpp | 2 ++ interface/src/devices/Visage.cpp | 12 +++++------ interface/src/devices/Visage.h | 6 +++--- 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9cdd38dbc8..8c4ea73775 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1158,15 +1158,8 @@ void MyAvatar::updateOrientation(float deltaTime) { pitch *= DEGREES_PER_RADIAN; roll *= DEGREES_PER_RADIAN; - // Record the angular velocity - Head* head = getHead(); - if (deltaTime > 0.0f) { - glm::vec3 angularVelocity(pitch - head->getBasePitch(), yaw - head->getBaseYaw(), roll - head->getBaseRoll()); - angularVelocity *= 1.0f / deltaTime; - head->setAngularVelocity(angularVelocity); - } - //Invert yaw and roll when in mirror mode + Head* head = getHead(); if (Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { head->setBaseYaw(-yaw); head->setBasePitch(pitch); diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index 8d61789715..e570e39345 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -14,3 +14,33 @@ inline float FaceTracker::getBlendshapeCoefficient(int index) const { return isValidBlendshapeIndex(index) ? _blendshapeCoefficients[index] : 0.0f; } + +float FaceTracker::getFadeCoefficient() const { + // TODO: apply exponential relaxation + return _relaxationStatus; +} + +const glm::vec3 FaceTracker::getHeadTranslation() const { + return glm::mix(glm::vec3(0.0f), _headTranslation, getFadeCoefficient()); +} + +const glm::quat FaceTracker::getHeadRotation() const { + return glm::mix(glm::quat(), _headRotation, getFadeCoefficient()); +} + +void FaceTracker::update(float deltaTime) { + static const float RELAXATION_TIME = 0.4; // sec + + if (isTracking()) { + if (_relaxationStatus == 1.0f) { + return; + } + _relaxationStatus += deltaTime / RELAXATION_TIME; + } else { + if (_relaxationStatus == 0.0f) { + return; + } + _relaxationStatus -= deltaTime / RELAXATION_TIME; + } + _relaxationStatus = glm::clamp(_relaxationStatus, 0.0f, 1.0f); +} \ No newline at end of file diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 07c479e3e3..89ba1f22f6 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -27,11 +27,13 @@ public: virtual bool isTracking() const { return false; } virtual void init() {} - virtual void update(float deltaTime) {} + virtual void update(float deltaTime); virtual void reset() {} - const glm::vec3& getHeadTranslation() const { return _headTranslation; } - const glm::quat& getHeadRotation() const { return _headRotation; } + float getFadeCoefficient() const; + + const glm::vec3 getHeadTranslation() const; + const glm::quat getHeadRotation() const; float getEstimatedEyePitch() const { return _estimatedEyePitch; } float getEstimatedEyeYaw() const { return _estimatedEyeYaw; } @@ -42,15 +44,13 @@ public: float getBlendshapeCoefficient(int index) const; protected: - - glm::vec3 _headTranslation = glm::vec3(0.0f); glm::quat _headRotation = glm::quat(); float _estimatedEyePitch = 0.0f; float _estimatedEyeYaw = 0.0f; QVector _blendshapeCoefficients; - float _fadeCoefficient = 0.0f; + float _relaxationStatus = 0.0f; // Between 0.0f and 1.0f }; #endif // hifi_FaceTracker_h diff --git a/interface/src/devices/Faceshift.cpp b/interface/src/devices/Faceshift.cpp index 87ee0ef31c..a2bb4e74a9 100644 --- a/interface/src/devices/Faceshift.cpp +++ b/interface/src/devices/Faceshift.cpp @@ -54,6 +54,8 @@ void Faceshift::update(float deltaTime) { if (!isActive()) { return; } + FaceTracker::update(deltaTime); + // get the euler angles relative to the window glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3( (_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f))))); diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 45c19a6ab3..010b872bc6 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -41,7 +41,6 @@ const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f); Visage::Visage() : _enabled(false), - _active(false), _headOrigin(DEFAULT_HEAD_ORIGIN) { #ifdef HAVE_VISAGE @@ -119,19 +118,20 @@ static const QMultiHash >& getActionUnitNameMap() } #endif -const float TRANSLATION_SCALE = 20.0f; +#ifdef HAVE_VISAGE +const float TRANSLATION_SCALE = 20.0f; void Visage::init() { connect(DependencyManager::get().data(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled())); updateEnabled(); } void Visage::update(float deltaTime) { -#ifdef HAVE_VISAGE - _active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK); - if (!_active) { + if (!isActive()) { return; } + FaceTracker::update(deltaTime); + _headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2])); _headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) - _headOrigin) * TRANSLATION_SCALE; @@ -163,12 +163,12 @@ void Visage::update(float deltaTime) { } _blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[1]; _blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[0]; -#endif } void Visage::reset() { _headOrigin += _headTranslation / TRANSLATION_SCALE; } +#endif void Visage::updateEnabled() { setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && diff --git a/interface/src/devices/Visage.h b/interface/src/devices/Visage.h index cd2ec3ecad..3ff1ea8c27 100644 --- a/interface/src/devices/Visage.h +++ b/interface/src/devices/Visage.h @@ -31,15 +31,16 @@ class Visage : public FaceTracker, public Dependency { SINGLETON_DEPENDENCY public: +#ifdef HAVE_VISAGE virtual void init(); virtual void update(float deltaTime); virtual void reset(); - virtual bool isActive() const { return _active; } + virtual bool isActive() const { return _tracker->getTrackingData(_data) == TRACK_STAT_OK; } virtual bool isTracking() const { return isActive(); } +#endif public slots: - void updateEnabled(); private: @@ -55,7 +56,6 @@ private: void setEnabled(bool enabled); bool _enabled; - bool _active; glm::vec3 _headOrigin; }; From b04dbf7a34b85ee5c013e12aedd0f66f1f14dbee Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 26 Feb 2015 11:27:40 -0800 Subject: [PATCH 267/341] fixing compilation issue on macos --- libraries/model/src/model/Stage.cpp | 264 ++++++++++++++-------------- 1 file changed, 133 insertions(+), 131 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 12ed186cf6..dd5a44a0cb 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -1,19 +1,21 @@ -// -// Stage.cpp -// libraries/model/src/model -// -// Created by Sam Gateau on 2/24/2015. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "Stage.h" - -#include -using namespace model; - - +// +// Stage.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Stage.h" + +#include +#include + +using namespace model; + + void EarthSunModel::updateAll() const { updateWorldToSurface(); updateSurfaceToEye(); @@ -72,118 +74,118 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); -} - -float moduloRange(float val, float minVal, float maxVal) { - float range = maxVal - minVal; - float rval = (val - minVal) / range; - float intval; - return modf(rval, &intval) * range + minVal; -} - -const float MAX_LONGITUDE = 180.0f; -const float MAX_LATITUDE = 90.0f; - -float validateLongitude(float lon) { - return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); -} - -float validateLatitude(float lat) { - return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); -} - -float validateAltitude(float altitude) { - const float MIN_ALTITUDE = -1000.0f; - const float MAX_ALTITUDE = 100000.0f; - return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); -} - -void EarthSunModel::setLatitude(float lat) { - _latitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setLongitude(float lon) { - _longitude = validateLongitude(lon); - invalidate(); -} -void EarthSunModel::setAltitude(float altitude) { - _altitude = validateAltitude(altitude); - invalidate(); -} - -void EarthSunModel::setSunLatitude(float lat) { - _sunLatitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setSunLongitude(float lon) { - _sunLongitude = validateLongitude(lon); - invalidate(); -} - -const int NUM_DAYS_PER_YEAR = 365; -const float NUM_HOURS_PER_DAY = 24.0f; -const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; - -SunSkyStage::SunSkyStage() : - _sunLight(new Light()) -{ - _sunLight->setType(Light::SUN); - - setSunIntensity(1.0f); - setSunColor(Vec3(1.0f, 1.0f, 1.0f)); - - // Default origin location is a special place in the world... - setOriginLocation(122.407f, 37.777f, 0.03f); - // 6pm - setDayTime(18.0f); - // Begining of march - setYearTime(60.0f); -} - -SunSkyStage::~SunSkyStage() { -} - -void SunSkyStage::setDayTime(float hour) { - _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); - invalidate(); -} - -void SunSkyStage::setYearTime(unsigned int day) { - _yearTime = day % NUM_DAYS_PER_YEAR; - invalidate(); -} - -void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { - _earthSunModel.setLongitude(longitude); - _earthSunModel.setLatitude(latitude); - _earthSunModel.setAltitude(altitude); - invalidate(); -} - -void SunSkyStage::setSunColor(const Vec3& color) { - _sunLight->setColor(color); -} -void SunSkyStage::setSunIntensity(float intensity) { - _sunLight->setIntensity(intensity); -} - -// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun -double evalSunDeclinaison(double dayNumber) { - return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); -} - -void SunSkyStage::updateGraphicsObject() const { - // Always update the sunLongitude based on the current dayTime and the current origin - // The day time is supposed to be local at the origin - double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; - double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); - _earthSunModel.setSunLongitude(sunLongitude); - - // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); - - Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); -} - +} + +double moduloRange(double val, double minVal, double maxVal) { + double range = maxVal - minVal; + double rval = (val - minVal) / range; + double intval; + return modf(rval, &intval) * range + minVal; +} + +const float MAX_LONGITUDE = 180.0f; +const float MAX_LATITUDE = 90.0f; + +float validateLongitude(float lon) { + return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); +} + +float validateLatitude(float lat) { + return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); +} + +float validateAltitude(float altitude) { + const float MIN_ALTITUDE = -1000.0f; + const float MAX_ALTITUDE = 100000.0f; + return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); +} + +void EarthSunModel::setLatitude(float lat) { + _latitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setLongitude(float lon) { + _longitude = validateLongitude(lon); + invalidate(); +} +void EarthSunModel::setAltitude(float altitude) { + _altitude = validateAltitude(altitude); + invalidate(); +} + +void EarthSunModel::setSunLatitude(float lat) { + _sunLatitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setSunLongitude(float lon) { + _sunLongitude = validateLongitude(lon); + invalidate(); +} + +const int NUM_DAYS_PER_YEAR = 365; +const float NUM_HOURS_PER_DAY = 24.0f; +const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; + +SunSkyStage::SunSkyStage() : + _sunLight(new Light()) +{ + _sunLight->setType(Light::SUN); + + setSunIntensity(1.0f); + setSunColor(Vec3(1.0f, 1.0f, 1.0f)); + + // Default origin location is a special place in the world... + setOriginLocation(122.407f, 37.777f, 0.03f); + // 6pm + setDayTime(18.0f); + // Begining of march + setYearTime(60.0f); +} + +SunSkyStage::~SunSkyStage() { +} + +void SunSkyStage::setDayTime(float hour) { + _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); + invalidate(); +} + +void SunSkyStage::setYearTime(unsigned int day) { + _yearTime = day % NUM_DAYS_PER_YEAR; + invalidate(); +} + +void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { + _earthSunModel.setLongitude(longitude); + _earthSunModel.setLatitude(latitude); + _earthSunModel.setAltitude(altitude); + invalidate(); +} + +void SunSkyStage::setSunColor(const Vec3& color) { + _sunLight->setColor(color); +} +void SunSkyStage::setSunIntensity(float intensity) { + _sunLight->setIntensity(intensity); +} + +// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclinaison(double dayNumber) { + return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); +} + +void SunSkyStage::updateGraphicsObject() const { + // Always update the sunLongitude based on the current dayTime and the current origin + // The day time is supposed to be local at the origin + double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; + double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); + _earthSunModel.setSunLongitude(sunLongitude); + + // And update the sunLAtitude as the declinaison depending of the time of the year + _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); + + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); +} + From 93106be46663ed09ec3f125adc9bc6f7533476d5 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Fri, 27 Feb 2015 00:58:55 +0530 Subject: [PATCH 268/341] VHACD dependency build instructions --- BUILD.md | 2 +- BUILD_WIN.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/BUILD.md b/BUILD.md index 98b8cffab1..6968d9bde8 100644 --- a/BUILD.md +++ b/BUILD.md @@ -4,7 +4,7 @@ * [Qt](http://qt-project.org/downloads) ~> 5.3.2 * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. - +* [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) ####CMake External Project Dependencies * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 28d26d9eb4..df50fd82c8 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -79,6 +79,21 @@ To prevent these problems, install OpenSSL yourself. Download the following bina Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version. +###vhacd +Download it directly from https://github.com/virneo/v-hacd + +To build it run the following commands + 1. cd src\ + 2. mkdir build + 3. cd build + 4. cmake .. + +Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug. + +This will create an output folder with include and lib directory inside it. + +Either copy the contents of output folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory. + ###Build High Fidelity using Visual Studio Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake. From d4367924ad5b0646f3cf682e3b0dbf836f8cc995 Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Fri, 27 Feb 2015 00:59:59 +0530 Subject: [PATCH 269/341] Clean up coding standard violations --- tools/vhacd/src/VHACDUtil.cpp | 41 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tools/vhacd/src/VHACDUtil.cpp b/tools/vhacd/src/VHACDUtil.cpp index d4ab9d7c8a..63b3bba459 100644 --- a/tools/vhacd/src/VHACDUtil.cpp +++ b/tools/vhacd/src/VHACDUtil.cpp @@ -26,25 +26,26 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re QByteArray fbxContents = fbx.readAll(); FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); //results->meshCount = geometry.meshes.count(); - + int count = 0; - foreach(FBXMesh mesh, geometry.meshes) { + foreach(FBXMesh mesh, geometry.meshes){ //get vertices for each mesh - QVector vertices = mesh.vertices; + QVector vertices = mesh.vertices; //get the triangle indices for each mesh QVector triangles; - foreach(FBXMeshPart part, mesh.parts) { + foreach(FBXMeshPart part, mesh.parts){ QVector indices = part.triangleIndices; triangles += indices; } //only read meshes with triangles - if (triangles.count() <= 0) - continue; + if (triangles.count() <= 0){ + continue; + } results->perMeshVertices.append(vertices); results->perMeshTriangleIndices.append(triangles); - count++; + count++; } results->meshCount = count; @@ -55,10 +56,10 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD(); int meshCount = meshes->meshCount; int count = 0; - std::cout << "Performing V-HACD computation on " << meshCount <<" meshes ..... " << std::endl; + std::cout << "Performing V-HACD computation on " << meshCount << " meshes ..... " << std::endl; for (int i = 0; i < meshCount; i++){ - + std::vector vertices = meshes->perMeshVertices.at(i).toStdVector(); std::vector triangles = meshes->perMeshTriangleIndices.at(i).toStdVector(); int nPoints = (unsigned int)vertices.size(); @@ -92,10 +93,13 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD interfaceVHACD->Clean(); interfaceVHACD->Release(); - if (count > 0) + if (count > 0){ return true; - else + } + else{ return false; + } + } vhacd::VHACDUtil:: ~VHACDUtil(){ @@ -103,19 +107,22 @@ vhacd::VHACDUtil:: ~VHACDUtil(){ } //ProgressClaback implementation -void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, +void vhacd::ProgressCallback::Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation){ int progress = (int)(overallProgress + 0.5); - if (progress < 10) + if (progress < 10){ std::cout << "\b\b"; - else + } + else{ std::cout << "\b\b\b"; + } + std::cout << progress << "%"; - if (progress >= 100) - std::cout << std::endl; - + if (progress >= 100){ + std::cout << std::endl; + } } vhacd::ProgressCallback::ProgressCallback(void){} From 695cfb3397485b028bfefac9b4311e3340f5e2ba Mon Sep 17 00:00:00 2001 From: Virendra Singh Date: Fri, 27 Feb 2015 01:04:23 +0530 Subject: [PATCH 270/341] VHACD dependency build instructions --- BUILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.md b/BUILD.md index 6968d9bde8..f2efe05289 100644 --- a/BUILD.md +++ b/BUILD.md @@ -5,6 +5,7 @@ * [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g * IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability. * [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) + ####CMake External Project Dependencies * [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82 From bc8d688cdea8dab4871523a66c6a123198b6ecc2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 12:04:33 -0800 Subject: [PATCH 271/341] fixing tab maybe --- examples/example/misc/sunLightExample.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 7f38211052..bc00a39246 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -11,21 +11,21 @@ var intensity = 1.0; var day = 0.0; var hour = 12.0; -var longitude = 0.0; -var latitude = -45.0; +var longitude = -115.0; +var latitude = -31.0; Scene.setDayTime(hour); -Scene.setOriginLocation(longitude, latitude, 0.0); +//Scene.setOriginLocation(longitude, latitude, 0.0); function ticktack() { hour += 0.1; - //Scene.setSunIntensity(Math.cos(time)); - if (hour > 24.0) { - hour = 0.0; - day++; - Scene.setYearTime(day); - } - Scene.setDayTime(hour); + //Scene.setSunIntensity(Math.cos(time)); + if (hour > 24.0) { + hour = 0.0; + day++; + Scene.setYearTime(day); + } + Scene.setDayTime(hour); } Script.setInterval(ticktack, 41); From 96d5a2ab4221e214d364e4437374a5059454209f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 12:10:08 -0800 Subject: [PATCH 272/341] fixing tab maybe --- examples/example/misc/sunLightExample.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index bc00a39246..47fbb9761e 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -18,7 +18,7 @@ Scene.setDayTime(hour); //Scene.setOriginLocation(longitude, latitude, 0.0); function ticktack() { - hour += 0.1; + hour += 0.1; //Scene.setSunIntensity(Math.cos(time)); if (hour > 24.0) { hour = 0.0; From 21f12c1d6c9d458c9c98376f323ff1581ac32f3b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 26 Feb 2015 13:50:43 -0800 Subject: [PATCH 273/341] Use cache ID when rendering talk bubble sphere --- interface/src/avatar/Avatar.cpp | 10 ++- interface/src/avatar/Avatar.h | 2 + libraries/render-utils/src/GeometryCache.cpp | 84 +++++++++++++++++--- libraries/render-utils/src/GeometryCache.h | 15 ++-- 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 6dc3d4b339..e5f296399e 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -77,7 +77,8 @@ Avatar::Avatar() : _moving(false), _collisionGroups(0), _initialized(false), - _shouldRenderBillboard(true) + _shouldRenderBillboard(true), + _voiceSphereID(GeometryCache::UNKNOWN_ID) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -439,8 +440,13 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef(height, height, height); + + if (_voiceSphereID == GeometryCache::UNKNOWN_ID) { + _voiceSphereID = DependencyManager::get()->allocateID(); + } DependencyManager::get()->renderSphere(sphereRadius, 15, 15, - glm::vec4(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.0f - angle / MAX_SPHERE_ANGLE)); + glm::vec4(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.0f - angle / MAX_SPHERE_ANGLE), true, + _voiceSphereID); glPopMatrix(); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 72b7ecf93a..d6977afce6 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -243,6 +243,8 @@ private: float getBillboardSize() const; static int _jointConesID; + + int _voiceSphereID; }; #endif // hifi_Avatar_h diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index dffadc730f..317b3bd6b9 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -53,18 +53,33 @@ const int NUM_COORDS_PER_VERTEX = 3; const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_INDEX = sizeof(GLushort); -void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid) { +void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) { + bool registered = (id != UNKNOWN_ID); Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0)); IntPair slicesStacksKey(slices, stacks); - Vec3Pair colorKey(glm::vec3(color.x, color.y, slices), glm::vec3(color.z, color.y, stacks)); + Vec3Pair colorKey(glm::vec3(color.x, color.y, slices), glm::vec3(color.z, color.w, stacks)); int vertices = slices * (stacks - 1) + 2; int indices = slices * (stacks - 1) * NUM_VERTICES_PER_TRIANGULATED_QUAD; - if (!_sphereVertices.contains(radiusKey)) { + if (registered && (!_registeredSphereVertices.contains(id) || _lastRegisteredSphereVertices[id] != radiusKey) + || !registered && !_sphereVertices.contains(radiusKey)) { + + if (registered && _registeredSphereVertices.contains(id)) { + _registeredSphereVertices[id].clear(); + #ifdef WANT_DEBUG + qDebug() << "renderSphere()... RELEASING REGISTERED VERTICES BUFFER"; + #endif + } + gpu::BufferPointer verticesBuffer(new gpu::Buffer()); - _sphereVertices[radiusKey] = verticesBuffer; + if (registered) { + _registeredSphereVertices[id] = verticesBuffer; + _lastRegisteredSphereVertices[id] = radiusKey; + } else { + _sphereVertices[radiusKey] = verticesBuffer; + } GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX]; GLfloat* vertex = vertexData; @@ -106,10 +121,29 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm qDebug() << " _sphereVertices.size():" << _sphereVertices.size(); #endif } + #ifdef WANT_DEBUG + else if (registered) { + qDebug() << "renderSphere()... REUSING PREVIOUSLY REGISTERED VERTICES BUFFER"; + } + #endif - if (!_sphereIndices.contains(slicesStacksKey)) { + if (registered && (!_registeredSphereIndices.contains(id) || _lastRegisteredSphereIndices[id] != slicesStacksKey) + || !registered && !_sphereIndices.contains(slicesStacksKey)) { + + if (registered && _registeredSphereIndices.contains(id)) { + _registeredSphereIndices[id].clear(); + #ifdef WANT_DEBUG + qDebug() << "renderSphere()... RELEASING REGISTERED INDICES BUFFER"; + #endif + } + gpu::BufferPointer indicesBuffer(new gpu::Buffer()); - _sphereIndices[slicesStacksKey] = indicesBuffer; + if (registered) { + _registeredSphereIndices[id] = indicesBuffer; + _lastRegisteredSphereIndices[id] = slicesStacksKey; + } else { + _sphereIndices[slicesStacksKey] = indicesBuffer; + } GLushort* indexData = new GLushort[indices]; GLushort* index = indexData; @@ -164,7 +198,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm delete[] indexData; #ifdef WANT_DEBUG - qDebug() << "GeometryCache::renderSphere()... --- CREATING INDEX BUFFER"; + qDebug() << "GeometryCache::renderSphere()... --- CREATING INDICES BUFFER"; qDebug() << " radius:" << radius; qDebug() << " slices:" << slices; qDebug() << " stacks:" << stacks; @@ -173,10 +207,29 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm qDebug() << " _sphereIndices.size():" << _sphereIndices.size(); #endif } + #ifdef WANT_DEBUG + else if (registered) { + qDebug() << "renderSphere()... REUSING PREVIOUSLY REGISTERED INDICES BUFFER"; + } + #endif + + if (registered && (!_registeredSphereColors.contains(id) || _lastRegisteredSphereColors[id] != colorKey) + || !registered && !_sphereColors.contains(colorKey)) { + + if (registered && _registeredSphereColors.contains(id)) { + _registeredSphereColors[id].clear(); + #ifdef WANT_DEBUG + qDebug() << "renderSphere()... RELEASING REGISTERED COLORS BUFFER"; + #endif + } - if (!_sphereColors.contains(colorKey)) { gpu::BufferPointer colorBuffer(new gpu::Buffer()); - _sphereColors[colorKey] = colorBuffer; + if (registered) { + _registeredSphereColors[id] = colorBuffer; + _lastRegisteredSphereColors[id] = colorKey; + } else { + _sphereColors[colorKey] = colorBuffer; + } int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | @@ -201,11 +254,16 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm qDebug() << " stacks:" << stacks; qDebug() << " _sphereColors.size():" << _sphereColors.size(); #endif - } - gpu::BufferPointer verticesBuffer = _sphereVertices[radiusKey]; - gpu::BufferPointer indicesBuffer = _sphereIndices[slicesStacksKey]; - gpu::BufferPointer colorBuffer = _sphereColors[colorKey]; + #ifdef WANT_DEBUG + else if (registered) { + qDebug() << "renderSphere()... REUSING PREVIOUSLY REGISTERED COLORS BUFFER"; + } + #endif + + gpu::BufferPointer verticesBuffer = registered ? _registeredSphereVertices[id] : _sphereVertices[radiusKey]; + gpu::BufferPointer indicesBuffer = registered ? _registeredSphereIndices[id] : _sphereIndices[slicesStacksKey]; + gpu::BufferPointer colorBuffer = registered ? _registeredSphereColors[id] : _sphereColors[colorKey]; const int VERTICES_SLOT = 0; const int NORMALS_SLOT = 1; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 864c5ff24c..92b6d44b6c 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -134,10 +134,10 @@ public: void renderCone(float base, float height, int slices, int stacks); - void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true) - { renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid); } + void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID) + { renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); } - void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true); + void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID); void renderGrid(int xDivisions, int yDivisions, const glm::vec4& color); void renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID); void renderSolidCube(float size, const glm::vec4& color); @@ -290,10 +290,15 @@ private: QHash _gridColors; QHash _sphereVertices; + QHash _registeredSphereVertices; + QHash _lastRegisteredSphereVertices; QHash _sphereIndices; + QHash _registeredSphereIndices; + QHash _lastRegisteredSphereIndices; QHash _sphereColors; - - + QHash _registeredSphereColors; + QHash _lastRegisteredSphereColors; + QHash > _networkGeometry; }; From 3c5f11e6ed0268115275e8dd297562a102484af2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 14:23:11 -0800 Subject: [PATCH 274/341] Add initial support for multi-selection in properties window --- examples/editEntities.js | 31 +++++++++++++++++-------- examples/html/entityProperties.html | 35 ++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index 9b13b167e7..ef6472e4b8 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -934,24 +934,37 @@ PropertiesTool = function(opts) { data = { type: 'update', }; - if (selectionManager.hasSelection()) { - data.id = selectionManager.selections[0].id; - data.properties = Entities.getEntityProperties(selectionManager.selections[0]); - data.properties.rotation = Quat.safeEulerAngles(data.properties.rotation); + var selections = []; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entity = {}; + entity.id = selectionManager.selections[i].id; + entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); + entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); + selections.push(entity); } + data.selections = selections; webView.eventBridge.emitScriptEvent(JSON.stringify(data)); }); webView.eventBridge.webEventReceived.connect(function(data) { - print(data); data = JSON.parse(data); if (data.type == "update") { selectionManager.saveProperties(); - if (data.properties.rotation !== undefined) { - var rotation = data.properties.rotation; - data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); + if (selectionManager.selections.length > 1) { + properties = { + locked: data.properties.locked, + visible: data.properties.visible, + }; + for (var i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], properties); + } + } else { + if (data.properties.rotation !== undefined) { + var rotation = data.properties.rotation; + data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); + } + Entities.editEntity(selectionManager.selections[0], data.properties); } - Entities.editEntity(selectionManager.selections[0], data.properties); pushCommandForSelections(); selectionManager._update(); } else if (data.type == "action") { diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index ad2b359e79..f264b569d6 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -171,12 +171,37 @@ EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); if (data.type == "update") { - if (data.properties === undefined) { - disableChildren(document.getElementById("properties"), 'input'); - } else { - var properties = data.properties; + if (data.selections.length == 0) { + elType.innerHTML = "No Selection"; + elID.innerHTML = ""; + disableChildren(document.getElementById("properties-list"), 'input'); + } else if (data.selections.length > 1) { + var selections = data.selections; - elID.innerHTML = data.id; + var ids = []; + var types = {}; + + for (var i = 0; i < selections.length; i++) { + ids.push(selections[i].id); + var type = selections[i].properties.type; + if (types[type] === undefined) { + types[type] = 0; + } + types[type]++; + } + elID.innerHTML = ids.join("
"); + + var typeStrs = []; + for (type in types) { + typeStrs.push(type + " (" + types[type] + ")"); + } + elType.innerHTML = typeStrs.join(", "); + + disableChildren(document.getElementById("properties-list"), 'input'); + } else { + var properties = data.selections[0].properties; + + elID.innerHTML = properties.id; elType.innerHTML = properties.type; From ecc003c5e1885f45f0a7f261d0cb7eeff9fd5384 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 14:23:25 -0800 Subject: [PATCH 275/341] Adjust colors for disabled input elements --- examples/html/style.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/html/style.css b/examples/html/style.css index 7177b8c8ba..0aedc43480 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -189,6 +189,11 @@ input, textarea { font-size: 7.5pt; } +input:disabled, textarea:disabled { + background-color: rgb(102, 102, 102); + color: rgb(160, 160, 160); +} + #properties-list input[type=button] { cursor: pointer; background-color: rgb(51, 102, 102); @@ -199,6 +204,11 @@ input, textarea { color: rgb(204, 204, 204); } +#properties-list input[type=button]:disabled { + background-color: rgb(41, 82, 82); + color: rgb(160, 160, 160); +} + #properties-list .property { padding: 6pt 6pt; border-top: 0.75pt solid rgb(63, 63, 63); From 74bc48ce55049cd0fb4e409d2a3461b4430380e4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 14:34:32 -0800 Subject: [PATCH 276/341] Add message to edit entities list for when no entities are nearby --- examples/html/entityList.html | 20 +++++++++++++++----- examples/html/style.css | 8 ++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/examples/html/entityList.html b/examples/html/entityList.html index bbfa4d81b8..bcc1c117ea 100644 --- a/examples/html/entityList.html +++ b/examples/html/entityList.html @@ -20,6 +20,7 @@ elRefresh = document.getElementById("refresh"); elDelete = document.getElementById("delete"); elTeleport = document.getElementById("teleport"); + elNoEntitiesMessage = document.getElementById("no-entities"); document.getElementById("entity-type").onclick = function() { setSortColumn('type'); @@ -155,11 +156,18 @@ } } else if (data.type == "update") { var newEntities = data.entities; - for (var i = 0; i < newEntities.length; i++) { - var id = newEntities[i].id; - addEntity(id, newEntities[i].type, newEntities[i].url); + if (newEntities.length == 0) { + elEntityTable.style.display = "none"; + elNoEntitiesMessage.style.display = "block"; + } else { + elEntityTable.style.display = "table"; + elNoEntitiesMessage.style.display = "none"; + for (var i = 0; i < newEntities.length; i++) { + var id = newEntities[i].id; + addEntity(id, newEntities[i].type, newEntities[i].url); + } + updateSelectedEntities(data.selectedIDs); } - updateSelectedEntities(data.selectedIDs); } }); setTimeout(refreshEntities, 1000); @@ -194,6 +202,8 @@
- +
+ No entities found within 50 meter radius. Try moving to a different location and refreshing. +
diff --git a/examples/html/style.css b/examples/html/style.css index 7177b8c8ba..5d60835e47 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -257,3 +257,11 @@ td { vertical-align: top; } + +#no-entities { + display: none; + font-size: 120%; + padding: 10pt; + font-weight: bold; + font-style: italic; +} From dc2b670fa8e6358a3f60d15ec6133abb67b5a9e2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 14:46:05 -0800 Subject: [PATCH 277/341] Remove extraneous comments --- libraries/render-utils/src/DeferredLightingEffect.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 5e203b041d..c8ad3711d3 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -131,9 +131,6 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi addSpotLight(position, radius, color, intensity); } -// Remove: ambient, specular, *Attenuation, direction -// Add: intensity, radius -// Rename: diffuseColor -> color void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color, float intensity, const glm::quat& orientation, float exponent, float cutoff) { From d60618a582801b9d9e0e4e4b5c1e07080e58a1b6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 26 Feb 2015 14:58:04 -0800 Subject: [PATCH 278/341] Remove unused variables from RenderableLightEntityItem::render --- .../src/RenderableLightEntityItem.cpp | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 978ca11d9d..7f630f1c8c 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -36,30 +36,18 @@ void RenderableLightEntityItem::render(RenderArgs* args) { float diffuseG = getDiffuseColor()[GREEN_INDEX] / MAX_COLOR; float diffuseB = getDiffuseColor()[BLUE_INDEX] / MAX_COLOR; - float ambientR = getAmbientColor()[RED_INDEX] / MAX_COLOR; - float ambientG = getAmbientColor()[GREEN_INDEX] / MAX_COLOR; - float ambientB = getAmbientColor()[BLUE_INDEX] / MAX_COLOR; + glm::vec3 color = glm::vec3(diffuseR, diffuseG, diffuseB); - float specularR = getSpecularColor()[RED_INDEX] / MAX_COLOR; - float specularG = getSpecularColor()[GREEN_INDEX] / MAX_COLOR; - float specularB = getSpecularColor()[BLUE_INDEX] / MAX_COLOR; - - glm::vec3 ambient = glm::vec3(ambientR, ambientG, ambientB); - glm::vec3 diffuse = glm::vec3(diffuseR, diffuseG, diffuseB); - glm::vec3 specular = glm::vec3(specularR, specularG, specularB); - glm::vec3 direction = IDENTITY_FRONT * rotation; float intensity = getConstantAttenuation(); - float linearAttenuation = getLinearAttenuation(); - float quadraticAttenuation = getQuadraticAttenuation(); float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); if (_isSpotlight) { - DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, - diffuse, intensity, rotation, exponent, cutoff); + DependencyManager::get()->addSpotLight(position, largestDiameter / 2.0f, + color, intensity, rotation, exponent, cutoff); } else { - DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, - diffuse, intensity); + DependencyManager::get()->addPointLight(position, largestDiameter / 2.0f, + color, intensity); } #ifdef WANT_DEBUG From 9979bbd8b52eb67e73326532e96f4e4ed723090f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 15:49:03 -0800 Subject: [PATCH 279/341] actually link debug bullet lib for WIN32 --- cmake/externals/bullet/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 587b7a12f1..e3610997d1 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -66,7 +66,7 @@ if (DEFINED BULLET_LIB_EXT) set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} release library location") if (WIN32) - set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} debug library location") + set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} debug library location") else () set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG "" CACHE FILEPATH "${_LIB_NAME} debug library location") endif () From e3b3c8e1ef8f23324f188efd7f01ad5f9e3b34f5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 16:09:21 -0800 Subject: [PATCH 280/341] Setting the defalt at a better time of the day --- libraries/model/src/model/Stage.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index dd5a44a0cb..8befec2ed3 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -136,8 +136,8 @@ SunSkyStage::SunSkyStage() : // Default origin location is a special place in the world... setOriginLocation(122.407f, 37.777f, 0.03f); - // 6pm - setDayTime(18.0f); + // Noun + setDayTime(12.0f); // Begining of march setYearTime(60.0f); } @@ -185,7 +185,10 @@ void SunSkyStage::updateGraphicsObject() const { _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); + + double originAlt = _earthSunModel.getAltitude(); + _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + } From 43da329eb4734777157123c50046aaf4b6df431d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 16:14:04 -0800 Subject: [PATCH 281/341] attempt to remove out-of-date warning for tbb --- cmake/externals/tbb/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 06da60ac04..8d6eb3924e 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -12,6 +12,7 @@ if (ANDROID) URL_MD5 f09c9abe8ec74e6558c1f89cebbe2893 BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm BUILD_IN_SOURCE 1 + UPDATE_COMMAND "" CONFIGURE_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake LOG_DOWNLOAD 1 @@ -33,6 +34,7 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} + UPDATE_COMMAND "" BUILD_COMMAND "" CONFIGURE_COMMAND "" INSTALL_COMMAND "" From eb646383e99318676000d389ad64cf32a5aea55d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 16:21:15 -0800 Subject: [PATCH 282/341] Revert "attempt to remove out-of-date warning for tbb" This reverts commit 43da329eb4734777157123c50046aaf4b6df431d. --- cmake/externals/tbb/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 8d6eb3924e..06da60ac04 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -12,7 +12,6 @@ if (ANDROID) URL_MD5 f09c9abe8ec74e6558c1f89cebbe2893 BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm BUILD_IN_SOURCE 1 - UPDATE_COMMAND "" CONFIGURE_COMMAND "" INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake LOG_DOWNLOAD 1 @@ -34,7 +33,6 @@ else () ExternalProject_Add( ${EXTERNAL_NAME} URL ${DOWNLOAD_URL} - UPDATE_COMMAND "" BUILD_COMMAND "" CONFIGURE_COMMAND "" INSTALL_COMMAND "" From 95c25086d70d06aa71d815c9ecb3d7b5dc727be4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 16:59:37 -0800 Subject: [PATCH 283/341] handle QTTOOLDIR env when looking for qmake --- cmake/externals/qxmpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt index c8bbdba6ba..9165da115f 100644 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ b/cmake/externals/qxmpp/CMakeLists.txt @@ -1,7 +1,7 @@ set(EXTERNAL_NAME qxmpp) # we need to find qmake inside QT_DIR -find_program(QMAKE_COMMAND NAME qmake PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) +find_program(QMAKE_COMMAND NAME qmake PATHS ${QT_DIR}/bin $ENV{QTTOOLDIR} NO_DEFAULT_PATH) if (NOT QMAKE_COMMAND) message(FATAL_ERROR "Could not find qmake. Qxmpp cannot be compiled without qmake.") From c80995170af3a813a8f0885c9c6f825348c9e7c7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Feb 2015 17:17:19 -0800 Subject: [PATCH 284/341] -n and -t are okay together --- assignment-client/src/AssignmentClientApp.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 7c6fb50db2..cea952a806 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -120,11 +120,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt(); } if (parser.isSet(clientTypeOption)) { - if (numForks || minForks || maxForks) { - qCritical() << "don't use -t with forking mode."; - parser.showHelp(); - Q_UNREACHABLE(); - } requestAssignmentType = (Assignment::Type) parser.value(clientTypeOption).toInt(); } From e95c197756001edc92084eadf2ba45ecf773775b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 17:17:55 -0800 Subject: [PATCH 285/341] fix header in win build guide --- BUILD_WIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 63648241a4..7a323c9a7a 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -14,7 +14,7 @@ Or you can start a regular command prompt and then run: If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. -####nmake & msbuild +####nmake Some of the external projects may require nmake to compile and install. If it is not installed at the location listed below, please ensure that it is in your PATH so CMake can find it when required. From 38f77190ebab0dcdcc61dfbb4b376af7f914e9da Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 17:20:45 -0800 Subject: [PATCH 286/341] remove PrioVR from build files --- BUILD.md | 2 +- cmake/modules/FindPrioVR.cmake | 24 ------------------------ interface/CMakeLists.txt | 2 +- interface/external/priovr/readme.txt | 16 ---------------- 4 files changed, 2 insertions(+), 42 deletions(-) delete mode 100644 cmake/modules/FindPrioVR.cmake delete mode 100644 interface/external/priovr/readme.txt diff --git a/BUILD.md b/BUILD.md index 98b8cffab1..e598ee500a 100644 --- a/BUILD.md +++ b/BUILD.md @@ -76,5 +76,5 @@ In the examples below the variable $NAME would be replaced by the name of the de ####Devices -You can support external input/output devices such as Oculus Rift, Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. +You can support external input/output devices such as Oculus Rift, Leap Motion, Faceshift, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. diff --git a/cmake/modules/FindPrioVR.cmake b/cmake/modules/FindPrioVR.cmake deleted file mode 100644 index 691ba85689..0000000000 --- a/cmake/modules/FindPrioVR.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Try to find the PrioVR library -# -# You must provide a PRIOVR_ROOT_DIR which contains lib and include directories -# -# Once done this will define -# -# PRIOVR_FOUND - system found PrioVR -# PRIOVR_INCLUDE_DIRS - the PrioVR include directory -# PRIOVR_LIBRARIES - Link this to use PrioVR -# -# Created on 5/12/2014 by Andrzej Kapolka -# Copyright (c) 2014 High Fidelity -# - -find_path(PRIOVR_INCLUDE_DIRS yei_skeletal_api.h ${PRIOVR_ROOT_DIR}/include) - -if (WIN32) - find_library(PRIOVR_LIBRARIES Skeletal_API.lib ${PRIOVR_ROOT_DIR}/lib) -endif (WIN32) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(PrioVR DEFAULT_MSG PRIOVR_INCLUDE_DIRS PRIOVR_LIBRARIES) - -mark_as_advanced(PRIOVR_INCLUDE_DIRS PRIOVR_LIBRARIES) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ee41648758..9bc4b393c5 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "RSSDK") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "RSSDK") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/external/priovr/readme.txt b/interface/external/priovr/readme.txt deleted file mode 100644 index 202a90cf12..0000000000 --- a/interface/external/priovr/readme.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Instructions for adding the PrioVR driver to Interface -Andrzej Kapolka, May 12, 2014 - -1. Download and install the YEI drivers from https://www.yeitechnology.com/yei-3-space-sensor-software-suite. If using - Window 8+, follow the workaround instructions at http://forum.yeitechnology.com/viewtopic.php?f=3&t=24. - -2. Get the PrioVR skeleton API, open ts_c_api2_priovr2/visual_studio/ThreeSpace_API_2/ThreeSpace_API_2.sln - in Visual Studio, and build it. - -3. Copy ts_c_api2_priovr2/visual_studio/ThreeSpace_API_2/Skeletal_API/yei_skeletal_api.h to interface/external/priovr/include, - ts_c_api2_priovr2/visual_studio/ThreeSpace_API_2/Debug/Skeletal_API.lib to interface/external/priovr/lib, and - ts_c_api2_priovr2/visual_studio/ThreeSpace_API_2/Debug/*.dll to your path. - -4. Delete your build directory, run cmake and build, and you should be all set. - From f6a9bd187090049e807c8ff51e32d3d5647ea276 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 17:26:41 -0800 Subject: [PATCH 287/341] REfining the naming and introducing an orientation offset --- examples/example/misc/sunLightExample.js | 10 ++++++---- libraries/model/src/model/Stage.cpp | 15 ++++++++++++++ libraries/model/src/model/Stage.h | 12 +++++++++++ .../src/SceneScriptingInterface.cpp | 20 +++++++++++-------- .../src/SceneScriptingInterface.h | 8 ++++---- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 47fbb9761e..9c58d0bac3 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -13,9 +13,11 @@ var day = 0.0; var hour = 12.0; var longitude = -115.0; var latitude = -31.0; +var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); -Scene.setDayTime(hour); -//Scene.setOriginLocation(longitude, latitude, 0.0); +Scene.setStageDayTime(hour); +Scene.setStageOrientation(stageOrientation); +Scene.setStageLocation(longitude, latitude, 0.0); function ticktack() { hour += 0.1; @@ -23,9 +25,9 @@ function ticktack() { if (hour > 24.0) { hour = 0.0; day++; - Scene.setYearTime(day); + Scene.setStageYearTime(day); } - Scene.setDayTime(hour); + Scene.setStageDayTime(hour); } Script.setInterval(ticktack, 41); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 8befec2ed3..d867056e8a 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -73,9 +73,19 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); + + // apply surface rotation offset + glm::dquat dSurfOrient(_surfaceOrientation); + lssd = glm::rotate(dSurfOrient, lssd); + _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); } +void EarthSunModel::setSurfaceOrientation(const Quat& orientation) { + _surfaceOrientation = orientation; + invalidate(); +} + double moduloRange(double val, double minVal, double maxVal) { double range = maxVal - minVal; double rval = (val - minVal) / range; @@ -155,6 +165,11 @@ void SunSkyStage::setYearTime(unsigned int day) { invalidate(); } +void SunSkyStage::setOriginOrientation(const Quat& orientation) { + _earthSunModel.setSurfaceOrientation(orientation); + invalidate(); +} + void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { _earthSunModel.setLongitude(longitude); _earthSunModel.setLatitude(latitude); diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index f99d2c1648..762e2d9717 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -33,6 +33,10 @@ public: void setAltitude(float altitude); float getAltitude() const { return _altitude; } + + void setSurfaceOrientation(const Quat& orientation); + const Quat& getSurfaceOrientation() const { valid(); return _surfaceOrientation; } + const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } @@ -67,6 +71,8 @@ protected: double _scale = 1000.0; //Km double _earthRadius = 6360.0; + Quat _surfaceOrientation; + double _longitude = 0.0; double _latitude = 0.0; double _altitude = 0.01; @@ -114,6 +120,12 @@ public: void setYearTime(unsigned int day); unsigned int getYearTime() const { return _yearTime; } + // Origin orientation used to modify the cardinal axis alignement used. + // THe default is north along +Z axis and west along +X axis. this orientation gets added + // to the transform stack producing the sun light direction. + void setOriginOrientation(const Quat& orientation); + const Quat& getOriginOrientation() const { return _earthSunModel.getSurfaceOrientation(); } + // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] void setOriginLocation(float longitude, float latitude, float surfaceAltitude); float getOriginLatitude() const { return _earthSunModel.getLatitude(); } diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index ff255a3e5e..9cac521225 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -13,10 +13,20 @@ #include "SceneScriptingInterface.h" - Q_INVOKABLE void setOriginGeoLocation(float longitude, float latitude, float altitude); -void SceneScriptingInterface::setOriginLocation(float longitude, float latitude, float altitude) { +void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) { + _skyStage->setOriginOrientation(orientation); +} +void SceneScriptingInterface::setStageLocation(float longitude, float latitude, float altitude) { _skyStage->setOriginLocation(longitude, latitude, altitude); } + +void SceneScriptingInterface::setStageDayTime(float hour) { + _skyStage->setDayTime(hour); +} +void SceneScriptingInterface::setStageYearTime(int day) { + _skyStage->setYearTime(day); +} + void SceneScriptingInterface::setSunColor(const glm::vec3& color) { _skyStage->setSunColor(color); } @@ -24,12 +34,6 @@ void SceneScriptingInterface::setSunIntensity(float intensity) { _skyStage->setSunIntensity(intensity); } -void SceneScriptingInterface::setDayTime(float hour) { - _skyStage->setDayTime(hour); -} -void SceneScriptingInterface::setYearTime(int day) { - _skyStage->setYearTime(day); -} model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { return _skyStage; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 3fc909f9a0..8ae9424c95 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -23,14 +23,14 @@ class SceneScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - Q_INVOKABLE void setOriginLocation(float longitude, float latitude, float altitude); + Q_INVOKABLE void setStageOrientation(const glm::quat& orientation); + Q_INVOKABLE void setStageLocation(float longitude, float latitude, float altitude); + Q_INVOKABLE void setStageDayTime(float hour); + Q_INVOKABLE void setStageYearTime(int day); Q_INVOKABLE void setSunColor(const glm::vec3& color); Q_INVOKABLE void setSunIntensity(float intensity); - Q_INVOKABLE void setDayTime(float hour); - Q_INVOKABLE void setYearTime(int day); - model::SunSkyStagePointer getSkyStage() const; protected: From fc2f6d47bbf3dc55fa011545feb5c65f052da788 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Feb 2015 17:28:00 -0800 Subject: [PATCH 288/341] remove references to PrioVR in interface code --- interface/src/Application.cpp | 4 - interface/src/Application.h | 4 - interface/src/avatar/MyAvatar.cpp | 14 +- interface/src/avatar/SkeletonModel.cpp | 17 +- interface/src/devices/PrioVR.cpp | 224 ------------------------- interface/src/devices/PrioVR.h | 65 ------- 6 files changed, 2 insertions(+), 326 deletions(-) delete mode 100644 interface/src/devices/PrioVR.cpp delete mode 100644 interface/src/devices/PrioVR.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bdd8f8f53..eed5a39138 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -771,7 +771,6 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); - // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() _applicationOverlay.renderOverlay(true); if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { _applicationOverlay.displayOverlayTexture(); @@ -2071,8 +2070,6 @@ void Application::update(float deltaTime) { updateVisage(); SixenseManager::getInstance().update(deltaTime); JoystickScriptingInterface::getInstance().update(); - _prioVR.update(deltaTime); - } // Dispatch input events @@ -3131,7 +3128,6 @@ void Application::resetSensors() { OculusManager::reset(); - _prioVR.reset(); //_leapmotion.reset(); QScreen* currentScreen = _window->windowHandle()->screen(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9cd19c8259..2d83f68f6b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -51,7 +51,6 @@ #include "Stars.h" #include "avatar/Avatar.h" #include "avatar/MyAvatar.h" -#include "devices/PrioVR.h" #include "devices/SixenseManager.h" #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" @@ -182,7 +181,6 @@ public: MetavoxelSystem* getMetavoxels() { return &_metavoxels; } EntityTreeRenderer* getEntities() { return &_entities; } Environment* getEnvironment() { return &_environment; } - PrioVR* getPrioVR() { return &_prioVR; } QUndoStack* getUndoStack() { return &_undoStack; } MainWindow* getWindow() { return _window; } OctreeQuery& getOctreeQuery() { return _octreeQuery; } @@ -493,8 +491,6 @@ private: MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - PrioVR _prioVR; - Camera _myCamera; // My view onto the world Camera _mirrorCamera; // Cammera for mirror view QRect _mirrorViewRect; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ba628ea0d4..55355b623d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -294,12 +294,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { return; } - if (Application::getInstance()->getPrioVR()->hasHeadRotation()) { - estimatedRotation = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getHeadRotation())); - estimatedRotation.x *= -1.0f; - estimatedRotation.z *= -1.0f; - - } else if (OculusManager::isConnected()) { + if (OculusManager::isConnected()) { estimatedPosition = OculusManager::getRelativePosition(); estimatedPosition.x *= -1.0f; _trackedHeadPosition = estimatedPosition; @@ -349,13 +344,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) { } head->setDeltaRoll(estimatedRotation.z); - // the priovr can give us exact lean - if (Application::getInstance()->getPrioVR()->isActive()) { - glm::vec3 eulers = glm::degrees(safeEulerAngles(Application::getInstance()->getPrioVR()->getTorsoRotation())); - head->setLeanSideways(eulers.z); - head->setLeanForward(eulers.x); - return; - } // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f; glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 6e207f9703..fa9846fd7d 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -106,21 +106,6 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - PrioVR* prioVR = Application::getInstance()->getPrioVR(); - if (prioVR->isActive()) { - for (int i = 0; i < prioVR->getJointRotations().size(); i++) { - int humanIKJointIndex = prioVR->getHumanIKJointIndices().at(i); - if (humanIKJointIndex == -1) { - continue; - } - int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); - if (jointIndex != -1) { - JointState& state = _jointStates[jointIndex]; - state.setRotationInBindFrame(prioVR->getJointRotations().at(i), PALM_PRIORITY); - } - } - return; - } // find the left and rightmost active palms int leftPalmIndex, rightPalmIndex; @@ -294,7 +279,7 @@ void SkeletonModel::updateJointState(int index) { } void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, JointState& state) { - if (!_owningAvatar->isMyAvatar() || Application::getInstance()->getPrioVR()->isActive()) { + if (!_owningAvatar->isMyAvatar()) { return; } // get the rotation axes in joint space and use them to adjust the rotation diff --git a/interface/src/devices/PrioVR.cpp b/interface/src/devices/PrioVR.cpp deleted file mode 100644 index 428c223eb7..0000000000 --- a/interface/src/devices/PrioVR.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// -// PrioVR.cpp -// interface/src/devices -// -// Created by Andrzej Kapolka on 5/12/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include - -#include -#include -#include -#include - -#include "Application.h" -#include "PrioVR.h" -#include "scripting/JoystickScriptingInterface.h" - -#ifdef HAVE_PRIOVR -const unsigned int SERIAL_LIST[] = { 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x0000000A, - 0x0000000C, 0x0000000D, 0x0000000E, 0x00000004, 0x00000005, 0x00000010, 0x00000011 }; -const unsigned char AXIS_LIST[] = { 9, 43, 37, 37, 37, 13, 13, 13, 52, 52, 28, 28 }; -const int LIST_LENGTH = sizeof(SERIAL_LIST) / sizeof(SERIAL_LIST[0]); - -const char* JOINT_NAMES[] = { "Neck", "Spine", "LeftArm", "LeftForeArm", "LeftHand", "RightArm", - "RightForeArm", "RightHand", "LeftUpLeg", "LeftLeg", "RightUpLeg", "RightLeg" }; - -static int indexOfHumanIKJoint(const char* jointName) { - for (int i = 0;; i++) { - QByteArray humanIKJoint = HUMANIK_JOINTS[i]; - if (humanIKJoint.isEmpty()) { - return -1; - } - if (humanIKJoint == jointName) { - return i; - } - } -} - -static void setPalm(float deltaTime, int index) { - MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); - Hand* hand = avatar->getHand(); - PalmData* palm; - bool foundHand = false; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == index) { - palm = &(hand->getPalms()[j]); - foundHand = true; - } - } - if (!foundHand) { - PalmData newPalm(hand); - hand->getPalms().push_back(newPalm); - palm = &(hand->getPalms()[hand->getNumPalms() - 1]); - palm->setSixenseID(index); - } - - palm->setActive(true); - - // Read controller buttons and joystick into the hand - const QString PRIO_JOYSTICK_NAME = "PrioVR"; - Joystick* prioJoystick = JoystickScriptingInterface::getInstance().joystickWithName(PRIO_JOYSTICK_NAME); - if (prioJoystick) { - const QVector axes = prioJoystick->getAxes(); - const QVector buttons = prioJoystick->getButtons(); - - if (axes.size() >= 4 && buttons.size() >= 4) { - if (index == LEFT_HAND_INDEX) { - palm->setControllerButtons(buttons[1] ? BUTTON_FWD : 0); - palm->setTrigger(buttons[0] ? 1.0f : 0.0f); - palm->setJoystick(axes[0], -axes[1]); - - } else { - palm->setControllerButtons(buttons[3] ? BUTTON_FWD : 0); - palm->setTrigger(buttons[2] ? 1.0f : 0.0f); - palm->setJoystick(axes[2], -axes[3]); - } - } - } - - // NOTE: this math is done in the worl-frame with unecessary complexity. - // TODO: transfom this to stay in the model-frame. - glm::vec3 position; - glm::quat rotation; - SkeletonModel* skeletonModel = &DependencyManager::get()->getMyAvatar()->getSkeletonModel(); - int jointIndex; - glm::quat inverseRotation = glm::inverse(DependencyManager::get()->getMyAvatar()->getOrientation()); - if (index == LEFT_HAND_INDEX) { - jointIndex = skeletonModel->getLeftHandJointIndex(); - skeletonModel->getJointRotationInWorldFrame(jointIndex, rotation); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); - - } else { - jointIndex = skeletonModel->getRightHandJointIndex(); - skeletonModel->getJointRotationInWorldFrame(jointIndex, rotation); - rotation = inverseRotation * rotation * glm::quat(glm::vec3(0.0f, -PI_OVER_TWO, 0.0f)); - } - skeletonModel->getJointPositionInWorldFrame(jointIndex, position); - position = inverseRotation * (position - skeletonModel->getTranslation()); - - palm->setRawRotation(rotation); - - // Compute current velocity from position change - glm::vec3 rawVelocity; - if (deltaTime > 0.0f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; - } else { - rawVelocity = glm::vec3(0.0f); - } - palm->setRawVelocity(rawVelocity); - palm->setRawPosition(position); - - // Store the one fingertip in the palm structure so we can track velocity - const float FINGER_LENGTH = 0.3f; // meters - const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); - const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; - glm::vec3 oldTipPosition = palm->getTipRawPosition(); - if (deltaTime > 0.0f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); - } else { - palm->setTipVelocity(glm::vec3(0.0f)); - } - palm->setTipPosition(newTipPosition); -} -#endif - -PrioVR::PrioVR() { -#ifdef HAVE_PRIOVR - char jointsDiscovered[LIST_LENGTH]; - _skeletalDevice = yei_setUpPrioVRSensors(0x00000000, const_cast(SERIAL_LIST), - const_cast(AXIS_LIST), jointsDiscovered, LIST_LENGTH, YEI_TIMESTAMP_SYSTEM); - if (!_skeletalDevice) { - return; - } - _jointRotations.resize(LIST_LENGTH); - _lastJointRotations.resize(LIST_LENGTH); - for (int i = 0; i < LIST_LENGTH; i++) { - _humanIKJointIndices.append(jointsDiscovered[i] ? indexOfHumanIKJoint(JOINT_NAMES[i]) : -1); - } -#endif -} - -PrioVR::~PrioVR() { -#ifdef HAVE_PRIOVR - if (_skeletalDevice) { - yei_stopStreaming(_skeletalDevice); - } -#endif -} - -const int HEAD_ROTATION_INDEX = 0; - -bool PrioVR::hasHeadRotation() const { - return _humanIKJointIndices.size() > HEAD_ROTATION_INDEX && _humanIKJointIndices.at(HEAD_ROTATION_INDEX) != -1; -} - -glm::quat PrioVR::getHeadRotation() const { - return _jointRotations.size() > HEAD_ROTATION_INDEX ? _jointRotations.at(HEAD_ROTATION_INDEX) : glm::quat(); -} - -glm::quat PrioVR::getTorsoRotation() const { - const int TORSO_ROTATION_INDEX = 1; - return _jointRotations.size() > TORSO_ROTATION_INDEX ? _jointRotations.at(TORSO_ROTATION_INDEX) : glm::quat(); -} - -void PrioVR::update(float deltaTime) { -#ifdef HAVE_PRIOVR - if (!_skeletalDevice) { - return; - } - PerformanceTimer perfTimer("PrioVR"); - unsigned int timestamp; - yei_getLastStreamDataAll(_skeletalDevice, (char*)_jointRotations.data(), - _jointRotations.size() * sizeof(glm::quat), ×tamp); - - // convert to our expected coordinate system, average with last rotations to smooth - for (int i = 0; i < _jointRotations.size(); i++) { - _jointRotations[i].y *= -1.0f; - _jointRotations[i].z *= -1.0f; - - glm::quat lastRotation = _lastJointRotations.at(i); - _lastJointRotations[i] = _jointRotations.at(i); - _jointRotations[i] = safeMix(lastRotation, _jointRotations.at(i), 0.5f); - } - - // convert the joysticks into palm data - setPalm(deltaTime, LEFT_HAND_INDEX); - setPalm(deltaTime, RIGHT_HAND_INDEX); -#endif -} - -void PrioVR::reset() { -#ifdef HAVE_PRIOVR - if (!_skeletalDevice) { - return; - } - connect(Application::getInstance(), SIGNAL(renderingOverlay()), SLOT(renderCalibrationCountdown())); - _calibrationCountdownStarted = QDateTime::currentDateTime(); -#endif -} - -void PrioVR::renderCalibrationCountdown() { -#ifdef HAVE_PRIOVR - const int COUNTDOWN_SECONDS = 3; - int secondsRemaining = COUNTDOWN_SECONDS - _calibrationCountdownStarted.secsTo(QDateTime::currentDateTime()); - if (secondsRemaining == 0) { - yei_tareSensors(_skeletalDevice); - Application::getInstance()->disconnect(this); - return; - } - static TextRenderer* textRenderer = TextRenderer::getInstance(MONO_FONT_FAMILY, 18, QFont::Bold, - false, TextRenderer::OUTLINE_EFFECT, 2); - QByteArray text = "Assume T-Pose in " + QByteArray::number(secondsRemaining) + "..."; - auto glCanvas = Application::getInstance()->getGLWidget(); - textRenderer->draw((glCanvas->width() - textRenderer->computeExtent(text.constData()).x) / 2, - glCanvas->height() / 2, - text, glm::vec4(1,1,1,1)); -#endif -} diff --git a/interface/src/devices/PrioVR.h b/interface/src/devices/PrioVR.h deleted file mode 100644 index bb563bf807..0000000000 --- a/interface/src/devices/PrioVR.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// PrioVR.h -// interface/src/devices -// -// Created by Andrzej Kapolka on 5/12/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_PrioVR_h -#define hifi_PrioVR_h - -#include -#include -#include - -#include - -#ifdef HAVE_PRIOVR -extern "C" { -#include -} -#endif - -/// Handles interaction with the PrioVR skeleton tracking suit. -class PrioVR : public QObject { - Q_OBJECT - -public: - - PrioVR(); - virtual ~PrioVR(); - - bool isActive() const { return !_jointRotations.isEmpty(); } - - bool hasHeadRotation() const; - - glm::quat getHeadRotation() const; - glm::quat getTorsoRotation() const; - - const QVector& getHumanIKJointIndices() const { return _humanIKJointIndices; } - const QVector& getJointRotations() const { return _jointRotations; } - - void update(float deltaTime); - void reset(); - -private slots: - - void renderCalibrationCountdown(); - -private: -#ifdef HAVE_PRIOVR - YEI_Device_Id _skeletalDevice; -#endif - - QVector _humanIKJointIndices; - QVector _jointRotations; - QVector _lastJointRotations; - - QDateTime _calibrationCountdownStarted; -}; - -#endif // hifi_PrioVR_h From b8322556a65a1c3cb2d15eb0de8354191f2d1b17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 26 Feb 2015 17:34:24 -0800 Subject: [PATCH 289/341] address code-review comments --- assignment-client/src/AssignmentClientApp.cpp | 7 +------ assignment-client/src/AssignmentClientMonitor.cpp | 6 +++--- libraries/networking/src/LimitedNodeList.h | 1 - 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index cea952a806..cfb77c8542 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -29,14 +29,13 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setvbuf(stdout, NULL, _IOLBF, 0); # endif - + // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us # ifdef _WIN32 installNativeEventFilter(&ShutdownEventListener::getInstance()); # else ShutdownEventListener::getInstance(); # endif - setOrganizationName("High Fidelity"); setOrganizationDomain("highfidelity.io"); setApplicationName("assignment-client"); @@ -141,7 +140,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : walletUUID = parser.value(walletDestinationOption); } - QString assignmentServerHostname; if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString(); @@ -150,7 +148,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : assignmentServerHostname = parser.value(assignmentServerHostnameOption); } - // check for an overriden assignment server port quint16 assignmentServerPort = DEFAULT_DOMAIN_SERVER_PORT; if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) { @@ -177,12 +174,10 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : if (numForks || minForks || maxForks) { - // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us AssignmentClientMonitor monitor(numForks, minForks, maxForks, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); exec(); } else { - // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us AssignmentClient client(requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); exec(); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index ffc402c04d..7517669d0b 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -43,8 +43,7 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen // create a NodeList so we can receive stats from children DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); - auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, - DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); + auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT); connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); @@ -55,7 +54,8 @@ AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmen spawnChildClient(); } - connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); + connect(&_checkSparesTimer, &QTimer::timeout, this, &AssignmentClientMonitor::checkSpares); + _checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 02234ee4f7..afc98de169 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -54,7 +54,6 @@ const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; -const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; From 74f0d98fd6ff65ae26dfda6374edc03c2a1d5ec9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 17:44:04 -0800 Subject: [PATCH 290/341] REfining the naming and introducing an orientation offset --- examples/example/misc/sunLightExample.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 9c58d0bac3..93fc06d088 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -11,8 +11,8 @@ var intensity = 1.0; var day = 0.0; var hour = 12.0; -var longitude = -115.0; -var latitude = -31.0; +var longitude = 115.0; +var latitude = 31.0; var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); Scene.setStageDayTime(hour); From c7eeebe52cc4b030a6bd6f3436497b4ee8047426 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 18:07:43 -0800 Subject: [PATCH 291/341] and fixing a bug with shadowing of lightmapped surface --- examples/example/misc/sunLightExample.js | 3 ++- libraries/render-utils/src/DeferredGlobalLight.slh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 93fc06d088..42837c6836 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -18,7 +18,7 @@ var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); Scene.setStageDayTime(hour); Scene.setStageOrientation(stageOrientation); Scene.setStageLocation(longitude, latitude, 0.0); - +/* function ticktack() { hour += 0.1; //Scene.setSunIntensity(Math.cos(time)); @@ -31,3 +31,4 @@ function ticktack() { } Script.setInterval(ticktack, 41); +*/ \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 6868b96c24..0fe2d18e74 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -95,7 +95,8 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); - float diffuseDot = dot(normal, getLightDirection(light)); + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + float diffuseDot = dot(fragNormal, -getLightDirection(light)); // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot From 9849efe0130082673622349ffc45559e68beafb4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Feb 2015 15:33:24 +0100 Subject: [PATCH 292/341] Exponential relaxation --- interface/src/devices/FaceTracker.cpp | 13 +++++++------ interface/src/devices/FaceTracker.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index e570e39345..f1ab35859b 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -16,8 +16,7 @@ inline float FaceTracker::getBlendshapeCoefficient(int index) const { } float FaceTracker::getFadeCoefficient() const { - // TODO: apply exponential relaxation - return _relaxationStatus; + return _fadeCoefficient; } const glm::vec3 FaceTracker::getHeadTranslation() const { @@ -29,18 +28,20 @@ const glm::quat FaceTracker::getHeadRotation() const { } void FaceTracker::update(float deltaTime) { - static const float RELAXATION_TIME = 0.4; // sec + static const float RELAXATION_TIME = 1.0f; // sec + static const float LAMBDA = 1.5; if (isTracking()) { if (_relaxationStatus == 1.0f) { return; } - _relaxationStatus += deltaTime / RELAXATION_TIME; + _relaxationStatus = glm::clamp(_relaxationStatus + deltaTime / RELAXATION_TIME, 0.0f, 1.0f); + _fadeCoefficient = std::exp(-LAMBDA * _relaxationStatus); } else { if (_relaxationStatus == 0.0f) { return; } - _relaxationStatus -= deltaTime / RELAXATION_TIME; + _relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f); + _fadeCoefficient = 1.0f - std::exp(-LAMBDA * (1.0f - _relaxationStatus)); } - _relaxationStatus = glm::clamp(_relaxationStatus, 0.0f, 1.0f); } \ No newline at end of file diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 89ba1f22f6..1ec0468dec 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -51,6 +51,7 @@ protected: QVector _blendshapeCoefficients; float _relaxationStatus = 0.0f; // Between 0.0f and 1.0f + float _fadeCoefficient = 0.0f; // Between 0.0f and 1.0f }; #endif // hifi_FaceTracker_h From 8615bb7cff3a39a37cd50301977e35c58b4bd6d0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Feb 2015 15:58:28 +0100 Subject: [PATCH 293/341] Make relaxation go to EPSILON within TIME --- interface/src/devices/FaceTracker.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index f1ab35859b..d6ccc38a45 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -28,20 +28,25 @@ const glm::quat FaceTracker::getHeadRotation() const { } void FaceTracker::update(float deltaTime) { - static const float RELAXATION_TIME = 1.0f; // sec + // Based on exponential distributions: http://en.wikipedia.org/wiki/Exponential_distribution + static const float EPSILON = 0.02f; static const float LAMBDA = 1.5; + static const float INVERSE_AT_EPSILON = -std::log(EPSILON) / LAMBDA; // So that f(1) = EPSILON ~ 0 + static const float RELAXATION_TIME = 0.8f; // sec if (isTracking()) { if (_relaxationStatus == 1.0f) { + _fadeCoefficient = 1.0f; return; } _relaxationStatus = glm::clamp(_relaxationStatus + deltaTime / RELAXATION_TIME, 0.0f, 1.0f); - _fadeCoefficient = std::exp(-LAMBDA * _relaxationStatus); + _fadeCoefficient = 1.0f - std::exp(-LAMBDA * _relaxationStatus * INVERSE_AT_EPSILON); } else { if (_relaxationStatus == 0.0f) { + _fadeCoefficient = 0.0f; return; } _relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f); - _fadeCoefficient = 1.0f - std::exp(-LAMBDA * (1.0f - _relaxationStatus)); + _fadeCoefficient = std::exp(-LAMBDA * (1.0f - _relaxationStatus) * INVERSE_AT_EPSILON); } } \ No newline at end of file From db90fcdb6220a7a377cd816d765631230dcbc0a5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Feb 2015 16:09:15 +0100 Subject: [PATCH 294/341] Simplify expression --- interface/src/devices/FaceTracker.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index d6ccc38a45..d3e0600057 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -29,9 +29,8 @@ const glm::quat FaceTracker::getHeadRotation() const { void FaceTracker::update(float deltaTime) { // Based on exponential distributions: http://en.wikipedia.org/wiki/Exponential_distribution - static const float EPSILON = 0.02f; - static const float LAMBDA = 1.5; - static const float INVERSE_AT_EPSILON = -std::log(EPSILON) / LAMBDA; // So that f(1) = EPSILON ~ 0 + static const float EPSILON = 0.02f; // MUST BE < 1.0f + static const float INVERSE_AT_EPSILON = -std::log(EPSILON); // So that f(1.0f) = EPSILON ~ 0.0f static const float RELAXATION_TIME = 0.8f; // sec if (isTracking()) { @@ -40,13 +39,13 @@ void FaceTracker::update(float deltaTime) { return; } _relaxationStatus = glm::clamp(_relaxationStatus + deltaTime / RELAXATION_TIME, 0.0f, 1.0f); - _fadeCoefficient = 1.0f - std::exp(-LAMBDA * _relaxationStatus * INVERSE_AT_EPSILON); + _fadeCoefficient = 1.0f - std::exp(-_relaxationStatus * INVERSE_AT_EPSILON); } else { if (_relaxationStatus == 0.0f) { _fadeCoefficient = 0.0f; return; } _relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f); - _fadeCoefficient = std::exp(-LAMBDA * (1.0f - _relaxationStatus) * INVERSE_AT_EPSILON); + _fadeCoefficient = std::exp(-(1.0f - _relaxationStatus) * INVERSE_AT_EPSILON); } } \ No newline at end of file From fa8e1549f600d948e337f52b7f39442cc2f73e5a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 27 Feb 2015 19:33:01 +0100 Subject: [PATCH 295/341] Relax blendshapes --- interface/src/devices/FaceTracker.cpp | 21 +++++++++++++++++++-- interface/src/devices/FaceTracker.h | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/interface/src/devices/FaceTracker.cpp b/interface/src/devices/FaceTracker.cpp index d3e0600057..7c1c757ec1 100644 --- a/interface/src/devices/FaceTracker.cpp +++ b/interface/src/devices/FaceTracker.cpp @@ -9,10 +9,27 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "FaceTracker.h" inline float FaceTracker::getBlendshapeCoefficient(int index) const { - return isValidBlendshapeIndex(index) ? _blendshapeCoefficients[index] : 0.0f; + return isValidBlendshapeIndex(index) ? glm::mix(0.0f, _blendshapeCoefficients[index], getFadeCoefficient()) + : 0.0f; +} + +const QVector& FaceTracker::getBlendshapeCoefficients() const { + static QVector blendshapes; + float fadeCoefficient = getFadeCoefficient(); + if (fadeCoefficient == 1.0f) { + return _blendshapeCoefficients; + } else { + blendshapes.resize(_blendshapeCoefficients.size()); + for (int i = 0; i < _blendshapeCoefficients.size(); i++) { + blendshapes[i] = glm::mix(0.0f, _blendshapeCoefficients[i], fadeCoefficient); + } + return blendshapes; + } } float FaceTracker::getFadeCoefficient() const { @@ -24,7 +41,7 @@ const glm::vec3 FaceTracker::getHeadTranslation() const { } const glm::quat FaceTracker::getHeadRotation() const { - return glm::mix(glm::quat(), _headRotation, getFadeCoefficient()); + return safeMix(glm::quat(), _headRotation, getFadeCoefficient()); } void FaceTracker::update(float deltaTime) { diff --git a/interface/src/devices/FaceTracker.h b/interface/src/devices/FaceTracker.h index 1ec0468dec..362099aaf6 100644 --- a/interface/src/devices/FaceTracker.h +++ b/interface/src/devices/FaceTracker.h @@ -40,7 +40,7 @@ public: int getNumBlendshapes() const { return _blendshapeCoefficients.size(); } bool isValidBlendshapeIndex(int index) const { return index >= 0 && index < getNumBlendshapes(); } - const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + const QVector& getBlendshapeCoefficients() const; float getBlendshapeCoefficient(int index) const; protected: From 01cac7445a2cee96522e1dd180adf508a35ed40c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 27 Feb 2015 10:58:04 -0800 Subject: [PATCH 296/341] add suppressions for log-spam caused by idle assignment-client --- domain-server/src/DomainServer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 64e0d335b1..9aec456587 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "DomainServerNodeData.h" @@ -943,8 +944,10 @@ void DomainServer::readAvailableDatagrams() { if (requestAssignment.getType() != Assignment::AgentType || noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) { + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex + ("Received a request for assignment type [^ ]+ from [^ ]+"); qDebug() << "Received a request for assignment type" << requestAssignment.getType() - << "from" << senderSockAddr; + << "from" << senderSockAddr; noisyMessageTimer.restart(); } @@ -974,6 +977,8 @@ void DomainServer::readAvailableDatagrams() { } else { if (requestAssignment.getType() != Assignment::AgentType || noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) { + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex + ("Unable to fulfill assignment request of type [^ ]+ from [^ ]+"); qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() << "from" << senderSockAddr; noisyMessageTimer.restart(); From f54f41fcf0a55e2e3636d2fd5dbb1f660bc356fc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 27 Feb 2015 11:36:45 -0800 Subject: [PATCH 297/341] fix typo --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 251f7a8702..ddc3a6ccf6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -248,7 +248,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // no matter the local port, save it to shared mem so that local assignment clients can ask what it is nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, nodeList->getNodeSocket().localPort()); - // store out local http ports in shared memory + // store our local http ports in shared memory quint16 localHttpPort = DOMAIN_SERVER_HTTP_PORT; nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_HTTP_PORT_SMEM_KEY, this, localHttpPort); quint16 localHttpsPort = DOMAIN_SERVER_HTTPS_PORT; From fdc1146339df706d0ee6e37a8dfcc7382ede0532 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 12:14:50 -0800 Subject: [PATCH 298/341] Update RenderableLightEntityItem to use update light entity --- .../src/RenderableLightEntityItem.cpp | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 1e0a9b6fc7..770473074a 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -32,25 +32,19 @@ void RenderableLightEntityItem::render(RenderArgs* args) { float largestDiameter = glm::max(dimensions.x, dimensions.y, dimensions.z); const float MAX_COLOR = 255.0f; - float diffuseR = getDiffuseColor()[RED_INDEX] / MAX_COLOR; - float diffuseG = getDiffuseColor()[GREEN_INDEX] / MAX_COLOR; - float diffuseB = getDiffuseColor()[BLUE_INDEX] / MAX_COLOR; + float colorR = getColor()[RED_INDEX] / MAX_COLOR; + float colorG = getColor()[GREEN_INDEX] / MAX_COLOR; + float colorB = getColor()[BLUE_INDEX] / MAX_COLOR; - float ambientR = getAmbientColor()[RED_INDEX] / MAX_COLOR; - float ambientG = getAmbientColor()[GREEN_INDEX] / MAX_COLOR; - float ambientB = getAmbientColor()[BLUE_INDEX] / MAX_COLOR; + glm::vec3 color = glm::vec3(colorR, colorG, colorB); + glm::vec3 diffuse = color; + glm::vec3 ambient = color; + glm::vec3 specular = color; - float specularR = getSpecularColor()[RED_INDEX] / MAX_COLOR; - float specularG = getSpecularColor()[GREEN_INDEX] / MAX_COLOR; - float specularB = getSpecularColor()[BLUE_INDEX] / MAX_COLOR; - - glm::vec3 ambient = glm::vec3(ambientR, ambientG, ambientB); - glm::vec3 diffuse = glm::vec3(diffuseR, diffuseG, diffuseB); - glm::vec3 specular = glm::vec3(specularR, specularG, specularB); glm::vec3 direction = IDENTITY_FRONT * rotation; - float constantAttenuation = getConstantAttenuation(); - float linearAttenuation = getLinearAttenuation(); - float quadraticAttenuation = getQuadraticAttenuation(); + float constantAttenuation = 0.0f; + float linearAttenuation = 0.0f; + float quadraticAttenuation = 0.0f; float exponent = getExponent(); float cutoff = glm::radians(getCutoff()); From 093e5db90d130f549ee187c152e16ba70c74461f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 13:42:56 -0800 Subject: [PATCH 299/341] Update entity light properties to use new model Rename constantAttenuation -> intensity Rename diffuseColor -> color Remove remaining attenuation and colors --- .../entities/src/EntityItemProperties.cpp | 14 ++-- libraries/entities/src/EntityItemProperties.h | 6 +- libraries/entities/src/LightEntityItem.cpp | 80 +++++++++---------- libraries/entities/src/LightEntityItem.h | 58 +++----------- 4 files changed, 61 insertions(+), 97 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f3f84876ba..ef59495d96 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -52,7 +52,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(diffuseColor, ), CONSTRUCT_PROPERTY(ambientColor, ), CONSTRUCT_PROPERTY(specularColor, ), - CONSTRUCT_PROPERTY(constantAttenuation, 1.0f), + CONSTRUCT_PROPERTY(intensity, 1.0f), CONSTRUCT_PROPERTY(linearAttenuation, 0.0f), CONSTRUCT_PROPERTY(quadraticAttenuation, 0.0f), CONSTRUCT_PROPERTY(exponent, 0.0f), @@ -225,7 +225,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_DIFFUSE_COLOR, diffuseColor); CHECK_PROPERTY_CHANGE(PROP_AMBIENT_COLOR, ambientColor); CHECK_PROPERTY_CHANGE(PROP_SPECULAR_COLOR, specularColor); - CHECK_PROPERTY_CHANGE(PROP_CONSTANT_ATTENUATION, constantAttenuation); + CHECK_PROPERTY_CHANGE(PROP_INTENSITY, intensity); CHECK_PROPERTY_CHANGE(PROP_LINEAR_ATTENUATION, linearAttenuation); CHECK_PROPERTY_CHANGE(PROP_QUADRATIC_ATTENUATION, quadraticAttenuation); CHECK_PROPERTY_CHANGE(PROP_EXPONENT, exponent); @@ -284,7 +284,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(diffuseColor, getDiffuseColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(ambientColor, getAmbientColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(specularColor, getSpecularColor()); - COPY_PROPERTY_TO_QSCRIPTVALUE(constantAttenuation); + COPY_PROPERTY_TO_QSCRIPTVALUE(intensity); COPY_PROPERTY_TO_QSCRIPTVALUE(linearAttenuation); COPY_PROPERTY_TO_QSCRIPTVALUE(quadraticAttenuation); COPY_PROPERTY_TO_QSCRIPTVALUE(exponent); @@ -362,7 +362,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(diffuseColor, setDiffuseColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(ambientColor, setAmbientColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(specularColor, setSpecularColor); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(constantAttenuation, setConstantAttenuation); + COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(intensity, setIntensity); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(linearAttenuation, setLinearAttenuation); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(quadraticAttenuation, setQuadraticAttenuation); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(exponent, setExponent); @@ -546,7 +546,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, appendColor, properties.getDiffuseColor()); APPEND_ENTITY_PROPERTY(PROP_AMBIENT_COLOR, appendColor, properties.getAmbientColor()); APPEND_ENTITY_PROPERTY(PROP_SPECULAR_COLOR, appendColor, properties.getSpecularColor()); - APPEND_ENTITY_PROPERTY(PROP_CONSTANT_ATTENUATION, appendValue, properties.getConstantAttenuation()); + APPEND_ENTITY_PROPERTY(PROP_INTENSITY, appendValue, properties.getIntensity()); APPEND_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, appendValue, properties.getLinearAttenuation()); APPEND_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, appendValue, properties.getQuadraticAttenuation()); APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent()); @@ -768,7 +768,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_DIFFUSE_COLOR, setDiffuseColor); READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_AMBIENT_COLOR, setAmbientColor); READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_SPECULAR_COLOR, setSpecularColor); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CONSTANT_ATTENUATION, float, setConstantAttenuation); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INTENSITY, float, setIntensity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINEAR_ATTENUATION, float, setLinearAttenuation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUADRATIC_ATTENUATION, float, setQuadraticAttenuation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent); @@ -838,7 +838,7 @@ void EntityItemProperties::markAllChanged() { _diffuseColorChanged = true; _ambientColorChanged = true; _specularColorChanged = true; - _constantAttenuationChanged = true; + _intensityChanged = true; _linearAttenuationChanged = true; _quadraticAttenuationChanged = true; _exponentChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 2391bcde84..9b43a21402 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -69,7 +69,7 @@ enum EntityPropertyList { PROP_DIFFUSE_COLOR, PROP_AMBIENT_COLOR, PROP_SPECULAR_COLOR, - PROP_CONSTANT_ATTENUATION, + PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION PROP_LINEAR_ATTENUATION, PROP_QUADRATIC_ATTENUATION, PROP_EXPONENT, @@ -168,7 +168,7 @@ public: DEFINE_PROPERTY_REF(PROP_DIFFUSE_COLOR, DiffuseColor, diffuseColor, xColor); DEFINE_PROPERTY_REF(PROP_AMBIENT_COLOR, AmbientColor, ambientColor, xColor); DEFINE_PROPERTY_REF(PROP_SPECULAR_COLOR, SpecularColor, specularColor, xColor); - DEFINE_PROPERTY(PROP_CONSTANT_ATTENUATION, ConstantAttenuation, constantAttenuation, float); + DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float); DEFINE_PROPERTY(PROP_LINEAR_ATTENUATION, LinearAttenuation, linearAttenuation, float); DEFINE_PROPERTY(PROP_QUADRATIC_ATTENUATION, QuadraticAttenuation, quadraticAttenuation, float); DEFINE_PROPERTY(PROP_EXPONENT, Exponent, exponent, float); @@ -291,7 +291,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, DiffuseColor, diffuseColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientColor, ambientColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpecularColor, specularColor, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, ConstantAttenuation, constantAttenuation, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Intensity, intensity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LinearAttenuation, linearAttenuation, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, QuadraticAttenuation, quadraticAttenuation, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Exponent, exponent, ""); diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 4a8dc2d582..1551eb5011 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -14,6 +14,7 @@ #include +#include "EntityItemID.h" #include "EntityTree.h" #include "EntityTreeElement.h" #include "LightEntityItem.h" @@ -32,12 +33,8 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID, const EntityI // default property values const quint8 MAX_COLOR = 255; - _ambientColor[RED_INDEX] = _ambientColor[GREEN_INDEX] = _ambientColor[BLUE_INDEX] = 0; - _diffuseColor[RED_INDEX] = _diffuseColor[GREEN_INDEX] = _diffuseColor[BLUE_INDEX] = MAX_COLOR; - _specularColor[RED_INDEX] = _specularColor[GREEN_INDEX] = _specularColor[BLUE_INDEX] = MAX_COLOR; - _constantAttenuation = 1.0f; - _linearAttenuation = 0.0f; - _quadraticAttenuation = 0.0f; + _color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0; + _intensity = 1.0f; _exponent = 0.0f; _cutoff = PI; @@ -54,12 +51,8 @@ EntityItemProperties LightEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(diffuseColor, getDiffuseXColor); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientColor, getAmbientXColor); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(specularColor, getSpecularXColor); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(constantAttenuation, getConstantAttenuation); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(linearAttenuation, getLinearAttenuation); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(quadraticAttenuation, getQuadraticAttenuation); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(intensity, getIntensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(exponent, getExponent); COPY_ENTITY_PROPERTY_TO_PROPERTIES(cutoff, getCutoff); @@ -70,17 +63,11 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(diffuseColor, setDiffuseColor); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientColor, setAmbientColor); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(specularColor, setSpecularColor); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(constantAttenuation, setConstantAttenuation); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(linearAttenuation, setLinearAttenuation); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(quadraticAttenuation, setQuadraticAttenuation); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(intensity, setIntensity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(exponent, setExponent); SET_ENTITY_PROPERTY_FROM_PROPERTIES(cutoff, setCutoff); - if (somethingChanged) { bool wantDebug = false; if (wantDebug) { @@ -101,15 +88,34 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); - READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR, _diffuseColor); - READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR, _ambientColor); - READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR, _specularColor); - READ_ENTITY_PROPERTY(PROP_CONSTANT_ATTENUATION, float, _constantAttenuation); - READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, float, _linearAttenuation); - READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, float, _quadraticAttenuation); - READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); - READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); + if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_NEW_PROPERTIES) { + rgbColor diffuseColor; + rgbColor ambientColor; + rgbColor specularColor; + float attenuation; + + READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); + + // _diffuseColor has been renamed to _color + READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR, _color); + + READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR, ambientColor); + READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR, specularColor); + + // _constantAttenuation has been renamed to _intensity + READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity); + + READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, float, attenuation); + READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, float, attenuation); + READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); + READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); + } else { + READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); + READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color); + READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity); + READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); + READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); + } return bytesRead; } @@ -119,12 +125,8 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_IS_SPOTLIGHT; - requestedProperties += PROP_DIFFUSE_COLOR; - requestedProperties += PROP_AMBIENT_COLOR; - requestedProperties += PROP_SPECULAR_COLOR; - requestedProperties += PROP_CONSTANT_ATTENUATION; - requestedProperties += PROP_LINEAR_ATTENUATION; - requestedProperties += PROP_QUADRATIC_ATTENUATION; + requestedProperties += PROP_COLOR; + requestedProperties += PROP_INTENSITY; requestedProperties += PROP_EXPONENT; requestedProperties += PROP_CUTOFF; return requestedProperties; @@ -140,12 +142,8 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, getIsSpotlight()); - APPEND_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, appendColor, getDiffuseColor()); - APPEND_ENTITY_PROPERTY(PROP_AMBIENT_COLOR, appendColor, getAmbientColor()); - APPEND_ENTITY_PROPERTY(PROP_SPECULAR_COLOR, appendColor, getSpecularColor()); - APPEND_ENTITY_PROPERTY(PROP_CONSTANT_ATTENUATION, appendValue, getConstantAttenuation()); - APPEND_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, appendValue, getLinearAttenuation()); - APPEND_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, appendValue, getQuadraticAttenuation()); + APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor()); + APPEND_ENTITY_PROPERTY(PROP_INTENSITY, appendValue, getIntensity()); APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, getExponent()); APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, getCutoff()); } diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 5e39ba26a2..cdbdb59ece 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -43,53 +43,23 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); - const rgbColor& getAmbientColor() const { return _ambientColor; } - xColor getAmbientXColor() const { - xColor color = { _ambientColor[RED_INDEX], _ambientColor[GREEN_INDEX], _ambientColor[BLUE_INDEX] }; return color; + const rgbColor& getColor() const { return _color; } + xColor getXColor() const { + xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } - void setAmbientColor(const rgbColor& value) { memcpy(_ambientColor, value, sizeof(_ambientColor)); } - void setAmbientColor(const xColor& value) { - _ambientColor[RED_INDEX] = value.red; - _ambientColor[GREEN_INDEX] = value.green; - _ambientColor[BLUE_INDEX] = value.blue; - } - - const rgbColor& getDiffuseColor() const { return _diffuseColor; } - xColor getDiffuseXColor() const { - xColor color = { _diffuseColor[RED_INDEX], _diffuseColor[GREEN_INDEX], _diffuseColor[BLUE_INDEX] }; return color; - } - - void setDiffuseColor(const rgbColor& value) { memcpy(_diffuseColor, value, sizeof(_diffuseColor)); } - void setDiffuseColor(const xColor& value) { - _diffuseColor[RED_INDEX] = value.red; - _diffuseColor[GREEN_INDEX] = value.green; - _diffuseColor[BLUE_INDEX] = value.blue; - } - - const rgbColor& getSpecularColor() const { return _specularColor; } - xColor getSpecularXColor() const { - xColor color = { _specularColor[RED_INDEX], _specularColor[GREEN_INDEX], _specularColor[BLUE_INDEX] }; return color; - } - - void setSpecularColor(const rgbColor& value) { memcpy(_specularColor, value, sizeof(_specularColor)); } - void setSpecularColor(const xColor& value) { - _specularColor[RED_INDEX] = value.red; - _specularColor[GREEN_INDEX] = value.green; - _specularColor[BLUE_INDEX] = value.blue; + void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } + void setColor(const xColor& value) { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; } bool getIsSpotlight() const { return _isSpotlight; } void setIsSpotlight(bool value) { _isSpotlight = value; } - float getConstantAttenuation() const { return _constantAttenuation; } - void setConstantAttenuation(float value) { _constantAttenuation = value; } - - float getLinearAttenuation() const { return _linearAttenuation; } - void setLinearAttenuation(float value) { _linearAttenuation = value; } - - float getQuadraticAttenuation() const { return _quadraticAttenuation; } - void setQuadraticAttenuation(float value) { _quadraticAttenuation = value; } + float getIntensity() const { return _intensity; } + void setIntensity(float value) { _intensity = value; } float getExponent() const { return _exponent; } void setExponent(float value) { _exponent = value; } @@ -103,13 +73,9 @@ public: protected: // properties of a light - rgbColor _ambientColor; - rgbColor _diffuseColor; - rgbColor _specularColor; + rgbColor _color; bool _isSpotlight; - float _constantAttenuation; - float _linearAttenuation; - float _quadraticAttenuation; + float _intensity; float _exponent; float _cutoff; From a7f84bcd307e01b6e55cf8e91ab1bb40546bb25f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 13:46:04 -0800 Subject: [PATCH 300/341] Update entity server version number --- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index db97e216ee..c8f6b6e25c 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; + return VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 32f33c01d9..44a464201b 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -128,6 +128,7 @@ const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5; const PacketVersion VERSION_ENTITIES_HAVE_USER_DATA = 6; const PacketVersion VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME = 7; const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE = 8; +const PacketVersion VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES = 9; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h From 20f3d23ae793d2b0fd3a1fd9ad16695d9b6d5722 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 13:46:26 -0800 Subject: [PATCH 301/341] Update editEntities to use new light properties --- examples/html/entityProperties.html | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index f54c2c9ce3..ef7791ea15 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -128,11 +128,11 @@ var elLightSections = document.querySelectorAll(".light-section"); var elLightSpotLight = document.getElementById("property-light-spot-light"); - var elLightDiffuseRed = document.getElementById("property-light-diffuse-red"); - var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green"); - var elLightDiffuseBlue = document.getElementById("property-light-diffuse-blue"); + var elLightColorRed = document.getElementById("property-light-color-red"); + var elLightColorGreen = document.getElementById("property-light-color-green"); + var elLightColorBlue = document.getElementById("property-light-color-blue"); - var elLightConstantAttenuation = document.getElementById("property-light-constant-attenuation"); + var elLightIntensity = document.getElementById("property-light-intensity"); var elLightExponent = document.getElementById("property-light-exponent"); var elLightCutoff = document.getElementById("property-light-cutoff"); @@ -305,11 +305,11 @@ elLightSections[i].style.display = 'block'; } - elLightDiffuseRed.value = properties.diffuseColor.red; - elLightDiffuseGreen.value = properties.diffuseColor.green; - elLightDiffuseBlue.value = properties.diffuseColor.blue; + elLightColorRed.value = properties.color.red; + elLightColorGreen.value = properties.color.green; + elLightColorBlue.value = properties.color.blue; - elLightConstantAttenuation.value = properties.constantAttenuation; + elLightIntensity.value = properties.intensity; elLightExponent.value = properties.exponent; elLightCutoff.value = properties.cutoff; } @@ -380,13 +380,13 @@ elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); - var lightDiffuseChangeFunction = createEmitColorPropertyUpdateFunction( - 'diffuseColor', elLightDiffuseRed, elLightDiffuseGreen, elLightDiffuseBlue); - elLightDiffuseRed.addEventListener('change', lightDiffuseChangeFunction); - elLightDiffuseGreen.addEventListener('change', lightDiffuseChangeFunction); - elLightDiffuseBlue.addEventListener('change', lightDiffuseChangeFunction); + var lightColorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elLightColorRed, elLightColorGreen, elLightColorBlue); + elLightColorRed.addEventListener('change', lightColorChangeFunction); + elLightColorGreen.addEventListener('change', lightColorChangeFunction); + elLightColorBlue.addEventListener('change', lightColorChangeFunction); - elLightConstantAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('constantAttenuation')); + elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity')); elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent')); elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff')); @@ -708,15 +708,15 @@
Color
-
R
-
G
-
B
+
R
+
G
+
B
Intensity
- +
From 61bc32493f4452f1eb7e63f4617a1f7a7a463876 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 13:49:17 -0800 Subject: [PATCH 302/341] Fix entity version name in LightEntityItem --- libraries/entities/src/LightEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 1551eb5011..8f075b099e 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -88,7 +88,7 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_NEW_PROPERTIES) { + if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES) { rgbColor diffuseColor; rgbColor ambientColor; rgbColor specularColor; From 84691f922c6d92e4d1ee11e014e4be627a3e4c79 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 14:04:56 -0800 Subject: [PATCH 303/341] Remove old light color properties --- .../entities/src/EntityItemProperties.cpp | 37 +------------------ libraries/entities/src/EntityItemProperties.h | 20 +++------- libraries/entities/src/LightEntityItem.cpp | 10 ++--- 3 files changed, 12 insertions(+), 55 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ef59495d96..e53a6ede3d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -49,12 +49,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(ignoreForCollisions, ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS), CONSTRUCT_PROPERTY(collisionsWillMove, ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE), CONSTRUCT_PROPERTY(isSpotlight, false), - CONSTRUCT_PROPERTY(diffuseColor, ), - CONSTRUCT_PROPERTY(ambientColor, ), - CONSTRUCT_PROPERTY(specularColor, ), CONSTRUCT_PROPERTY(intensity, 1.0f), - CONSTRUCT_PROPERTY(linearAttenuation, 0.0f), - CONSTRUCT_PROPERTY(quadraticAttenuation, 0.0f), CONSTRUCT_PROPERTY(exponent, 0.0f), CONSTRUCT_PROPERTY(cutoff, PI), CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED), @@ -222,12 +217,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_IGNORE_FOR_COLLISIONS, ignoreForCollisions); CHECK_PROPERTY_CHANGE(PROP_COLLISIONS_WILL_MOVE, collisionsWillMove); CHECK_PROPERTY_CHANGE(PROP_IS_SPOTLIGHT, isSpotlight); - CHECK_PROPERTY_CHANGE(PROP_DIFFUSE_COLOR, diffuseColor); - CHECK_PROPERTY_CHANGE(PROP_AMBIENT_COLOR, ambientColor); - CHECK_PROPERTY_CHANGE(PROP_SPECULAR_COLOR, specularColor); CHECK_PROPERTY_CHANGE(PROP_INTENSITY, intensity); - CHECK_PROPERTY_CHANGE(PROP_LINEAR_ATTENUATION, linearAttenuation); - CHECK_PROPERTY_CHANGE(PROP_QUADRATIC_ATTENUATION, quadraticAttenuation); CHECK_PROPERTY_CHANGE(PROP_EXPONENT, exponent); CHECK_PROPERTY_CHANGE(PROP_CUTOFF, cutoff); CHECK_PROPERTY_CHANGE(PROP_LOCKED, locked); @@ -281,12 +271,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(ignoreForCollisions); COPY_PROPERTY_TO_QSCRIPTVALUE(collisionsWillMove); COPY_PROPERTY_TO_QSCRIPTVALUE(isSpotlight); - COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(diffuseColor, getDiffuseColor()); - COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(ambientColor, getAmbientColor()); - COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(specularColor, getSpecularColor()); COPY_PROPERTY_TO_QSCRIPTVALUE(intensity); - COPY_PROPERTY_TO_QSCRIPTVALUE(linearAttenuation); - COPY_PROPERTY_TO_QSCRIPTVALUE(quadraticAttenuation); COPY_PROPERTY_TO_QSCRIPTVALUE(exponent); COPY_PROPERTY_TO_QSCRIPTVALUE(cutoff); COPY_PROPERTY_TO_QSCRIPTVALUE(locked); @@ -359,12 +344,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(ignoreForCollisions, setIgnoreForCollisions); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(collisionsWillMove, setCollisionsWillMove); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(isSpotlight, setIsSpotlight); - COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(diffuseColor, setDiffuseColor); - COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(ambientColor, setAmbientColor); - COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(specularColor, setSpecularColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(intensity, setIntensity); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(linearAttenuation, setLinearAttenuation); - COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(quadraticAttenuation, setQuadraticAttenuation); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(exponent, setExponent); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(cutoff, setCutoff); COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked); @@ -543,12 +523,8 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem if (properties.getType() == EntityTypes::Light) { APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, appendValue, properties.getIsSpotlight()); - APPEND_ENTITY_PROPERTY(PROP_DIFFUSE_COLOR, appendColor, properties.getDiffuseColor()); - APPEND_ENTITY_PROPERTY(PROP_AMBIENT_COLOR, appendColor, properties.getAmbientColor()); - APPEND_ENTITY_PROPERTY(PROP_SPECULAR_COLOR, appendColor, properties.getSpecularColor()); + APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_INTENSITY, appendValue, properties.getIntensity()); - APPEND_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, appendValue, properties.getLinearAttenuation()); - APPEND_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, appendValue, properties.getQuadraticAttenuation()); APPEND_ENTITY_PROPERTY(PROP_EXPONENT, appendValue, properties.getExponent()); APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff()); } @@ -765,12 +741,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Light) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight); - READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_DIFFUSE_COLOR, setDiffuseColor); - READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_AMBIENT_COLOR, setAmbientColor); - READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_SPECULAR_COLOR, setSpecularColor); + READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(PROP_COLOR, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INTENSITY, float, setIntensity); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINEAR_ATTENUATION, float, setLinearAttenuation); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUADRATIC_ATTENUATION, float, setQuadraticAttenuation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff); } @@ -835,12 +807,7 @@ void EntityItemProperties::markAllChanged() { _ignoreForCollisionsChanged = true; _collisionsWillMoveChanged = true; - _diffuseColorChanged = true; - _ambientColorChanged = true; - _specularColorChanged = true; _intensityChanged = true; - _linearAttenuationChanged = true; - _quadraticAttenuationChanged = true; _exponentChanged = true; _cutoffChanged = true; _lockedChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9b43a21402..12cc50b6ea 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -66,12 +66,12 @@ enum EntityPropertyList { // property used by Light entity PROP_IS_SPOTLIGHT, - PROP_DIFFUSE_COLOR, - PROP_AMBIENT_COLOR, - PROP_SPECULAR_COLOR, + PROP_DIFFUSE_COLOR_UNUSED, + PROP_AMBIENT_COLOR_UNUSED, + PROP_SPECULAR_COLOR_UNUSED, PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION - PROP_LINEAR_ATTENUATION, - PROP_QUADRATIC_ATTENUATION, + PROP_LINEAR_ATTENUATION_UNUSED, + PROP_QUADRATIC_ATTENUATION_UNUSED, PROP_EXPONENT, PROP_CUTOFF, @@ -165,12 +165,7 @@ public: DEFINE_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, IgnoreForCollisions, ignoreForCollisions, bool); DEFINE_PROPERTY(PROP_COLLISIONS_WILL_MOVE, CollisionsWillMove, collisionsWillMove, bool); DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool); - DEFINE_PROPERTY_REF(PROP_DIFFUSE_COLOR, DiffuseColor, diffuseColor, xColor); - DEFINE_PROPERTY_REF(PROP_AMBIENT_COLOR, AmbientColor, ambientColor, xColor); - DEFINE_PROPERTY_REF(PROP_SPECULAR_COLOR, SpecularColor, specularColor, xColor); DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float); - DEFINE_PROPERTY(PROP_LINEAR_ATTENUATION, LinearAttenuation, linearAttenuation, float); - DEFINE_PROPERTY(PROP_QUADRATIC_ATTENUATION, QuadraticAttenuation, quadraticAttenuation, float); DEFINE_PROPERTY(PROP_EXPONENT, Exponent, exponent, float); DEFINE_PROPERTY(PROP_CUTOFF, Cutoff, cutoff, float); DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool); @@ -288,12 +283,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, IgnoreForCollisions, ignoreForCollisions, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionsWillMove, collisionsWillMove, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, IsSpotlight, isSpotlight, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, DiffuseColor, diffuseColor, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientColor, ambientColor, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, SpecularColor, specularColor, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Intensity, intensity, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, LinearAttenuation, linearAttenuation, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, QuadraticAttenuation, quadraticAttenuation, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Exponent, exponent, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cutoff, cutoff, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Locked, locked, ""); diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 8f075b099e..d2fce92dca 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -97,16 +97,16 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); // _diffuseColor has been renamed to _color - READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR, _color); + READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR_UNUSED, _color); - READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR, ambientColor); - READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR, specularColor); + READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR_UNUSED, ambientColor); + READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR_UNUSED, specularColor); // _constantAttenuation has been renamed to _intensity READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity); - READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION, float, attenuation); - READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION, float, attenuation); + READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, attenuation); + READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, attenuation); READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); } else { From 11efcd70d8f0997e3e2dba62af635518d006bd95 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 14:09:46 -0800 Subject: [PATCH 304/341] Add SIGINT handling to assignment-client --- libraries/shared/src/ShutdownEventListener.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index 94975b2418..e640126b7b 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -35,6 +35,7 @@ ShutdownEventListener::ShutdownEventListener(QObject* parent) : #ifndef Q_OS_WIN // be a signal handler for SIGTERM so we can stop our children when we get it signal(SIGTERM, signalHandler); + signal(SIGINT, signalHandler); #endif } From 3ffd47a0b035b3ffae833bfe5f3bd1ed666bb5a1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:08:13 -0800 Subject: [PATCH 305/341] Update editEntities rotation arrows --- examples/libraries/entitySelectionTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 85be97b1ce..1b69075d13 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -242,8 +242,8 @@ SelectionDisplay = (function () { var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18; var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.17; - var ROTATE_ARROW_WEST_NORTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-north.png"; - var ROTATE_ARROW_WEST_SOUTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-south.png"; + var ROTATE_ARROW_WEST_NORTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-north.svg"; + var ROTATE_ARROW_WEST_SOUTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-south.svg"; var showExtendedStretchHandles = false; From cd3281521cf8a954bd396e4e06d1611ea9177e9e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:08:29 -0800 Subject: [PATCH 306/341] Update size of rotation degrees text --- examples/libraries/entitySelectionTool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 1b69075d13..5c1ff82d39 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -238,9 +238,9 @@ SelectionDisplay = (function () { // These are multipliers for sizing the rotation degrees display while rotating an entity var ROTATION_DISPLAY_DISTANCE_MULTIPLIER = 1.2; - var ROTATION_DISPLAY_SIZE_X_MULTIPLIER = 0.5; + var ROTATION_DISPLAY_SIZE_X_MULTIPLIER = 0.6; var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18; - var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.17; + var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.14; var ROTATE_ARROW_WEST_NORTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-north.svg"; var ROTATE_ARROW_WEST_SOUTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-south.svg"; From 4f4ab144b220d894dd9ce6ce6866a7347fbb622b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:10:56 -0800 Subject: [PATCH 307/341] Update handle colors and up/down arrow image --- examples/libraries/entitySelectionTool.js | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 5c1ff82d39..fe86cb7a69 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -280,11 +280,11 @@ SelectionDisplay = (function () { var originalRoll; - var rotateHandleColor = { red: 0, green: 0, blue: 0 }; - var rotateHandleAlpha = 0.7; + var handleColor = { red: 255, green: 255, blue: 255 }; + var handleAlpha = 0.7; - var highlightedHandleColor = { red: 255, green: 0, blue: 0 }; - var highlightedHandleAlpha = 0.7; + var highlightedHandleColor = { red: 120, green: 216, blue: 209 }; + var highlightedHandleAlpha = 1.0; var previousHandle = false; var previousHandleColor; @@ -385,9 +385,9 @@ SelectionDisplay = (function () { }); var grabberMoveUp = Overlays.addOverlay("billboard", { - url: HIFI_PUBLIC_BUCKET + "images/up-arrow.png", + url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg", position: { x:0, y: 0, z: 0}, - color: { red: 0, green: 0, blue: 0 }, + color: handleColor, alpha: 1.0, visible: false, size: 0.1, @@ -595,8 +595,8 @@ SelectionDisplay = (function () { var yawHandle = Overlays.addOverlay("billboard", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, - color: rotateHandleColor, - alpha: rotateHandleAlpha, + color: handleColor, + alpha: handleAlpha, visible: false, size: 0.1, scale: 0.1, @@ -608,8 +608,8 @@ SelectionDisplay = (function () { var pitchHandle = Overlays.addOverlay("billboard", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, - color: rotateHandleColor, - alpha: rotateHandleAlpha, + color: handleColor, + alpha: handleAlpha, visible: false, size: 0.1, scale: 0.1, @@ -621,8 +621,8 @@ SelectionDisplay = (function () { var rollHandle = Overlays.addOverlay("billboard", { url: ROTATE_ARROW_WEST_NORTH_URL, position: { x:0, y: 0, z: 0}, - color: rotateHandleColor, - alpha: rotateHandleAlpha, + color: handleColor, + alpha: handleAlpha, visible: false, size: 0.1, scale: 0.1, @@ -2342,14 +2342,14 @@ SelectionDisplay = (function () { case yawHandle: case pitchHandle: case rollHandle: - pickedColor = rotateHandleColor; - pickedAlpha = rotateHandleAlpha; + pickedColor = handleColor; + pickedAlpha = handleAlpha; highlightNeeded = true; break; case grabberMoveUp: - pickedColor = rotateHandleColor; - pickedAlpha = rotateHandleAlpha; + pickedColor = handleColor; + pickedAlpha = handleAlpha; highlightNeeded = true; break; From a0d9e92c641763793492e1a0df0099e97e3bfcd1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:11:23 -0800 Subject: [PATCH 308/341] Update size of rotation overlay --- examples/libraries/entitySelectionTool.js | 38 +++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index fe86cb7a69..76fb0a7835 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -533,7 +533,7 @@ SelectionDisplay = (function () { var rotateOverlayTarget = Overlays.addOverlay("circle3d", { position: { x:0, y: 0, z: 0}, - size: rotateOverlayTargetSize, + size: rotateOverlayTargetSize * 2, color: { red: 0, green: 0, blue: 0 }, alpha: 0.0, solid: true, @@ -1713,15 +1713,17 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius, + size: innerRadius * 2, innerRadius: 0.9, + startAt: 0, + endAt: 360, alpha: innerAlpha }); Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius, + size: outerRadius * 2, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -1731,7 +1733,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius, + size: outerRadius * 2, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -1809,13 +1811,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } @@ -1840,15 +1842,17 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius, + size: innerRadius * 2, innerRadius: 0.9, + startAt: 0, + endAt: 360, alpha: innerAlpha }); Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius, + size: outerRadius * 2, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -1858,7 +1862,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius, + size: outerRadius * 2, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -1929,13 +1933,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } @@ -1959,15 +1963,17 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayInner, { visible: true, - size: innerRadius, + size: innerRadius * 2, innerRadius: 0.9, + startAt: 0, + endAt: 360, alpha: innerAlpha }); Overlays.editOverlay(rotateOverlayOuter, { visible: true, - size: outerRadius, + size: outerRadius * 2, innerRadius: 0.9, startAt: 0, endAt: 360, @@ -1977,7 +1983,7 @@ SelectionDisplay = (function () { Overlays.editOverlay(rotateOverlayCurrent, { visible: true, - size: outerRadius, + size: outerRadius * 2, startAt: 0, endAt: 0, innerRadius: 0.9, @@ -2047,13 +2053,13 @@ SelectionDisplay = (function () { if (snapToInner) { Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius * 2, majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); } else { Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius * 2, majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); } From dc2cb93cce35ae0b4bb787143846385626b01ed2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:11:43 -0800 Subject: [PATCH 309/341] Add degrees symbol to rotation degrees text --- examples/libraries/entitySelectionTool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 76fb0a7835..86266d3fb5 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1692,7 +1692,7 @@ SelectionDisplay = (function () { y: innerRadius * ROTATION_DISPLAY_SIZE_Y_MULTIPLIER }, lineHeight: innerRadius * ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER, - text: normalizeDegrees(angleFromZero), + text: normalizeDegrees(angleFromZero) + "°", }); } From a48c428f426f52f3a2d3aacdd9fed96fa758b62e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 27 Feb 2015 15:29:00 -0800 Subject: [PATCH 310/341] Update highlighted handle color --- examples/libraries/entitySelectionTool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 86266d3fb5..c261e0d8a6 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -283,8 +283,8 @@ SelectionDisplay = (function () { var handleColor = { red: 255, green: 255, blue: 255 }; var handleAlpha = 0.7; - var highlightedHandleColor = { red: 120, green: 216, blue: 209 }; - var highlightedHandleAlpha = 1.0; + var highlightedHandleColor = { red: 183, green: 64, blue: 44 }; + var highlightedHandleAlpha = 0.9; var previousHandle = false; var previousHandleColor; @@ -388,7 +388,7 @@ SelectionDisplay = (function () { url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg", position: { x:0, y: 0, z: 0}, color: handleColor, - alpha: 1.0, + alpha: handleAlpha, visible: false, size: 0.1, scale: 0.1, From 31c96523fb080f70917a921923139ef2b54c5393 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Feb 2015 15:57:46 -0800 Subject: [PATCH 311/341] add support for transparency in RAW heightmaps --- libraries/metavoxels/src/Spanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index fd5a59fdfb..d2dff016e3 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -648,7 +648,7 @@ void HeightfieldHeightEditor::select() { const float CONVERSION_SCALE = 65534.0f / numeric_limits::max(); for (int i = 0; i < rawSize; i++, dest += size) { for (quint16* lineDest = dest, *end = dest + rawSize; lineDest != end; lineDest++, src++) { - *lineDest = (quint16)(*src * CONVERSION_SCALE) + CONVERSION_OFFSET; + *lineDest = (*src == 0) ? 0 : (quint16)(*src * CONVERSION_SCALE) + CONVERSION_OFFSET; } } emit heightChanged(_height = new HeightfieldHeight(size, contents)); From 5ab3cbb7ecca4d736ea936f4875c0f96769b1f5b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 27 Feb 2015 17:11:16 -0800 Subject: [PATCH 312/341] Fixed the 2 remianing issues before PR, the shadow program needed to have the binding assigned and the Head of the avatar isn't getting it's BBox evaluated --- interface/src/avatar/FaceModel.cpp | 2 ++ interface/src/avatar/Head.cpp | 1 + libraries/render-utils/src/Model.cpp | 3 +++ libraries/render-utils/src/Model.h | 3 +++ 4 files changed, 9 insertions(+) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 3523cb2176..c80772ef49 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -39,6 +39,8 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { setPupilDilation(_owningHead->getPupilDilation()); setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients()); + invalidCalculatedMeshBoxes(); + if (isActive()) { setOffset(-_geometry->getFBXGeometry().neckPivot); Model::simulateInternal(deltaTime); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 311356daf3..4bfaaae577 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -251,6 +251,7 @@ void Head::render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mod } else { RenderArgs args; args._viewFrustum = renderFrustum; + // _faceModel._calculatedMeshBoxesValid = false; _faceModel.render(alpha, mode, &args); } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c632afa084..c7e5b71b22 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -336,6 +336,9 @@ void Model::init() { _shadowProgram.addShaderFromSourceCode(QGLShader::Vertex, model_shadow_vert); _shadowProgram.addShaderFromSourceCode(QGLShader::Fragment, model_shadow_frag); + // Shadow program uses the same locations as standard rendering path but we still need to set the bindings + Model::Locations tempLoc; + initProgram(_shadowProgram, tempLoc); _skinProgram.addShaderFromSourceCode(QGLShader::Vertex, skin_model_vert); _skinProgram.addShaderFromSourceCode(QGLShader::Fragment, model_frag); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index ef96f0e05f..303fa770ad 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -269,6 +269,9 @@ protected: /// first free ancestor. float getLimbLength(int jointIndex) const; + /// Allow sub classes to force invalidating the bboxes + void invalidCalculatedMeshBoxes() { _calculatedMeshBoxesValid = false; } + private: friend class AnimationHandle; From f92efa13c8a415190a57ef03e820496c49ecf806 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 27 Feb 2015 17:35:08 -0800 Subject: [PATCH 313/341] fix typo --- interface/src/avatar/Head.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 4bfaaae577..b90b693139 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -251,8 +251,7 @@ void Head::render(float alpha, ViewFrustum* renderFrustum, Model::RenderMode mod } else { RenderArgs args; args._viewFrustum = renderFrustum; - // _faceModel._calculatedMeshBoxesValid = false; - _faceModel.render(alpha, mode, &args); + _faceModel.render(alpha, mode, &args); } } From 9cc66f3da78002456dcd8fc5739a06db91001e16 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Feb 2015 17:57:42 -0800 Subject: [PATCH 314/341] cleanup stats display behavior, reset default settings for timing details --- interface/src/Menu.cpp | 3 ++- interface/src/Menu.h | 3 ++- interface/src/ui/Stats.cpp | 46 +++++++++++++++++++++++--------------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c45fc6ed33..be5b495fe9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -453,7 +453,8 @@ Menu::Menu() { QMenu* timingMenu = developerMenu->addMenu("Timing and Stats"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); - addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayDebugTimingDetails, 0, false); + addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::OnlyDisplayTopTen, 0, true); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandUpdateTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarTiming, 0, false); addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::ExpandMyAvatarSimulateTiming, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6dbc841a42..584e4d5254 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -150,7 +150,7 @@ namespace MenuOption { const QString DisplayModelTriangles = "Display Model Triangles"; const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementProxy = "Display Model Element Bounds"; - const QString DisplayTimingDetails = "Display Timing Details"; + const QString DisplayDebugTimingDetails = "Display Timing Details"; const QString DontDoPrecisionPicking = "Don't Do Precision Picking"; const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes"; const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene"; @@ -198,6 +198,7 @@ namespace MenuOption { const QString OctreeStats = "Voxel and Entity Statistics"; const QString OffAxisProjection = "Off-Axis Projection"; const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; + const QString OnlyDisplayTopTen = "Only Display Top Ten"; const QString Pair = "Pair"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "Preferences..."; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index a4bb60bf7c..62adcb20e8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -34,7 +34,8 @@ using namespace std; -const int STATS_PELS_PER_LINE = 20; +const int STATS_PELS_PER_LINE = 16; +const int STATS_PELS_INITIALOFFSET = 12; const int STATS_GENERAL_MIN_WIDTH = 165; const int STATS_PING_MIN_WIDTH = 190; @@ -170,7 +171,7 @@ void Stats::drawBackground(unsigned int rgba, int x, int y, int width, int heigh } bool Stats::includeTimingRecord(const QString& name) { - if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { if (name.startsWith("/idle/update/")) { if (name.startsWith("/idle/update/myAvatar/")) { if (name.startsWith("/idle/update/myAvatar/simulate/")) { @@ -231,7 +232,7 @@ void Stats::display( PerformanceTimer::tallyAllTimerRecords(); // do this even if we're not displaying them, so they don't stack up - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { columnOneWidth = _generalStatsWidth + _pingStatsWidth + _geoStatsWidth; // 3 columns wide... // we will also include room for 1 line per timing record and a header of 4 lines @@ -239,15 +240,21 @@ void Stats::display( const QMap& allRecords = PerformanceTimer::getAllTimerRecords(); QMapIterator i(allRecords); + bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); + int statsLines = 0; while (i.hasNext()) { i.next(); if (includeTimingRecord(i.key())) { lines++; + statsLines++; + if (onlyDisplayTopTen && statsLines == 10) { + break; + } } } } - drawBackground(backgroundColor, horizontalOffset, 0, columnOneWidth, lines * STATS_PELS_PER_LINE + 10); + drawBackground(backgroundColor, horizontalOffset, 0, columnOneWidth, (lines + 1) * STATS_PELS_PER_LINE); horizontalOffset += 5; int columnOneHorizontalOffset = horizontalOffset; @@ -256,7 +263,7 @@ void Stats::display( QString avatarNodes = QString("Avatars: %1").arg(totalAvatars); QString framesPerSecond = QString("Framerate: %1 FPS").arg(fps, 3, 'f', 0); - verticalOffset += STATS_PELS_PER_LINE; + verticalOffset = STATS_PELS_INITIALOFFSET; // first one is offset by less than a line drawText(horizontalOffset, verticalOffset, scale, rotation, font, serverNodes.toUtf8().constData(), color); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarNodes.toUtf8().constData(), color); @@ -275,9 +282,10 @@ void Stats::display( // TODO: the display of these timing details should all be moved to JavaScript - if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) { + if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { + bool onlyDisplayTopTen = Menu::getInstance()->isOptionChecked(MenuOption::OnlyDisplayTopTen); // Timing details... - verticalOffset += STATS_PELS_PER_LINE * 6; // skip 6 lines to be under the other columns + verticalOffset += STATS_PELS_PER_LINE * 4; // skip 3 lines to be under the other columns drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, "-------------------------------------------------------- Function " "------------------------------------------------------- --msecs- -calls--", color); @@ -296,6 +304,7 @@ void Stats::display( } } + int linesDisplayed = 0; QMapIterator j(sortedRecords); j.toBack(); while (j.hasPrevious()) { @@ -311,11 +320,15 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(columnOneHorizontalOffset, verticalOffset, scale, rotation, font, perfLine.toUtf8().constData(), color); + linesDisplayed++; + if (onlyDisplayTopTen && linesDisplayed == 10) { + break; + } } } - verticalOffset = 0; + verticalOffset = STATS_PELS_INITIALOFFSET; horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + 1; if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { @@ -351,7 +364,7 @@ void Stats::display( // only draw our background if column one didn't draw a wide background if (columnOneWidth == _generalStatsWidth) { - drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, lines * STATS_PELS_PER_LINE + 10); + drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, (lines + 1) * STATS_PELS_PER_LINE); } horizontalOffset += 5; @@ -377,7 +390,6 @@ void Stats::display( voxelAvgPing = QString("Entities avg ping: --"); } - verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, audioPing.toUtf8().constData(), color); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPing.toUtf8().constData(), color); @@ -396,17 +408,17 @@ void Stats::display( drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing.toUtf8().constData(), color); } - verticalOffset = 0; + verticalOffset = STATS_PELS_INITIALOFFSET; horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + 2; } MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 avatarPos = myAvatar->getPosition(); - lines = _expanded ? 8 : 3; + lines = _expanded ? 7 : 3; if (columnOneWidth == _generalStatsWidth) { - drawBackground(backgroundColor, horizontalOffset, 0, _geoStatsWidth, lines * STATS_PELS_PER_LINE + 10); + drawBackground(backgroundColor, horizontalOffset, 0, _geoStatsWidth, (lines + 1) * STATS_PELS_PER_LINE); } horizontalOffset += 5; @@ -418,7 +430,6 @@ void Stats::display( QString avatarBodyYaw = QString("Yaw: %1").arg(myAvatar->getBodyYaw(), -1, 'f', 1); QString avatarMixerStats; - verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarPosition.toUtf8().constData(), color); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, avatarVelocity.toUtf8().constData(), color); @@ -476,13 +487,13 @@ void Stats::display( } } - verticalOffset = 0; + verticalOffset = STATS_PELS_INITIALOFFSET; horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3; - lines = _expanded ? 14 : 3; + lines = _expanded ? 10 : 2; drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset, - lines * STATS_PELS_PER_LINE + 10); + (lines + 1) * STATS_PELS_PER_LINE); horizontalOffset += 5; // Model/Entity render details @@ -491,7 +502,6 @@ void Stats::display( octreeStats << "Entity Items rendered: " << entities->getItemsRendered() << " / Out of view:" << entities->getItemsOutOfView() << " / Too small:" << entities->getItemsTooSmall(); - verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); if (_expanded) { From a338d96b9db18e9c6654a877a62bb3e0b70fdd86 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 27 Feb 2015 18:00:51 -0800 Subject: [PATCH 315/341] only render the overlay if we're actually rendering the overlay --- interface/src/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f0627f4e8..fe41621dc1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -773,9 +773,8 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); - // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() - _applicationOverlay.renderOverlay(true); if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { + _applicationOverlay.renderOverlay(true); _applicationOverlay.displayOverlayTexture(); } } From 1a3eb68e2d9c452dd7d844635c1a65c3ef206738 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 09:25:18 -0800 Subject: [PATCH 316/341] Update lightEntityItem old version handling to be more clear --- libraries/entities/src/LightEntityItem.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index d2fce92dca..3265891b18 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -89,24 +89,27 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, const unsigned char* dataAt = data; if (args.bitstreamVersion < VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES) { - rgbColor diffuseColor; - rgbColor ambientColor; - rgbColor specularColor; - float attenuation; + rgbColor ignoredColor; + float ignoredAttenuation; READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, _isSpotlight); // _diffuseColor has been renamed to _color READ_ENTITY_PROPERTY_COLOR(PROP_DIFFUSE_COLOR_UNUSED, _color); - READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR_UNUSED, ambientColor); - READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR_UNUSED, specularColor); + // Ambient and specular color are from an older format and are no longer supported. + // Their values will be ignored. + READ_ENTITY_PROPERTY_COLOR(PROP_AMBIENT_COLOR_UNUSED, ignoredColor); + READ_ENTITY_PROPERTY_COLOR(PROP_SPECULAR_COLOR_UNUSED, ignoredColor); // _constantAttenuation has been renamed to _intensity READ_ENTITY_PROPERTY(PROP_INTENSITY, float, _intensity); - READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, attenuation); - READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, attenuation); + // Linear and quadratic attenuation are from an older format and are no longer supported. + // Their values will be ignored. + READ_ENTITY_PROPERTY(PROP_LINEAR_ATTENUATION_UNUSED, float, ignoredAttenuation); + READ_ENTITY_PROPERTY(PROP_QUADRATIC_ATTENUATION_UNUSED, float, ignoredAttenuation); + READ_ENTITY_PROPERTY(PROP_EXPONENT, float, _exponent); READ_ENTITY_PROPERTY(PROP_CUTOFF, float, _cutoff); } else { From 0638459052b3510367ec96c8b8f50ac2bcc99f95 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 09:51:41 -0800 Subject: [PATCH 317/341] Add permission-checking to edit entities --- examples/editEntities.js | 46 ++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index ef6472e4b8..f6c376ba74 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -81,6 +81,8 @@ var SETTING_INSPECT_TOOL_ENABLED = "inspectToolEnabled"; var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; +var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain." + var modelURLs = [ HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Alder.fbx", HIFI_PUBLIC_BUCKET + "models/entities/2-Terrain:%20Bush1.fbx", @@ -177,25 +179,29 @@ var toolBar = (function () { that.setActive = function(active) { if (active != isActive) { - isActive = active; - if (!isActive) { - entityListTool.setVisible(false); - gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(); - cameraManager.disable(); + if (active && !Entities.canAdjustLocks()) { + Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG); } else { - hasShownPropertiesTool = false; - cameraManager.enable(); - entityListTool.setVisible(true); - gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - Window.setFocus(); + isActive = active; + if (!isActive) { + entityListTool.setVisible(false); + gridTool.setVisible(false); + grid.setEnabled(false); + propertiesTool.setVisible(false); + selectionManager.clearSelections(); + cameraManager.disable(); + } else { + hasShownPropertiesTool = false; + cameraManager.enable(); + entityListTool.setVisible(true); + gridTool.setVisible(true); + grid.setEnabled(true); + propertiesTool.setVisible(true); + Window.setFocus(); + } } } - toolBar.selectTool(activeButton, active); + toolBar.selectTool(activeButton, isActive); }; var RESIZE_INTERVAL = 50; @@ -400,6 +406,14 @@ var toolBar = (function () { that.setActive(false); }); + function checkForPermissionToEdit() { + if (isActive && !Entities.canAdjustLocks()) { + that.setActive(false); + } + } + + Script.setInterval(checkForPermissionToEdit, 1000); + that.cleanup = function () { toolBar.cleanup(); }; From 64cb51785605e5b8f23a5ea9f0b956b13d68cfdb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 10:40:11 -0800 Subject: [PATCH 318/341] Add LimitedNodeList::canAdjustLocksChanged signal --- libraries/networking/src/LimitedNodeList.cpp | 7 +++++++ libraries/networking/src/LimitedNodeList.h | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b240f0df9e..aaecd5bc38 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -96,6 +96,13 @@ void LimitedNodeList::setSessionUUID(const QUuid& sessionUUID) { } } +void LimitedNodeList::setThisNodeCanAdjustLocks(bool canAdjustLocks) { + if (_thisNodeCanAdjustLocks != canAdjustLocks) { + _thisNodeCanAdjustLocks = canAdjustLocks; + emit canAdjustLocksChanged(canAdjustLocks); + } +} + QUdpSocket& LimitedNodeList::getDTLSSocket() { if (!_dtlsSocket) { // DTLS socket getter called but no DTLS socket exists, create it now diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index afc98de169..fe386f5a49 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -82,8 +82,8 @@ public: const QUuid& getSessionUUID() const { return _sessionUUID; } void setSessionUUID(const QUuid& sessionUUID); - bool getThisNodeCanAdjustLocks() { return _thisNodeCanAdjustLocks; } - void setThisNodeCanAdjustLocks(bool canAdjustLocks) { _thisNodeCanAdjustLocks = canAdjustLocks; } + bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; } + void setThisNodeCanAdjustLocks(bool canAdjustLocks); void rebindNodeSocket(); QUdpSocket& getNodeSocket() { return _nodeSocket; } @@ -194,6 +194,8 @@ signals: void localSockAddrChanged(const HifiSockAddr& localSockAddr); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); + void canAdjustLocksChanged(bool canAdjustLocks); + void dataSent(const quint8 channel_type, const int bytes); void dataReceived(const quint8 channel_type, const int bytes); From 9a302eebedbf24fabd09d021c79128894b151ea3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 10:40:29 -0800 Subject: [PATCH 319/341] Add Entities.canAdjustLocksChanged --- libraries/entities/src/EntityScriptingInterface.cpp | 2 ++ libraries/entities/src/EntityScriptingInterface.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 0ee2e243f9..10ed98b0fa 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -19,6 +19,8 @@ EntityScriptingInterface::EntityScriptingInterface() : _nextCreatorTokenID(0), _entityTree(NULL) { + auto nodeList = DependencyManager::get(); + connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged); } void EntityScriptingInterface::queueEntityMessage(PacketType packetType, diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 6b02d6db0a..50b571541d 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -111,6 +111,8 @@ public slots: signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); + void canAdjustLocksChanged(bool canAdjustLocks); + void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mouseReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); From a443157dd75b5b112f295642cf565fcebed14c8a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 10:40:46 -0800 Subject: [PATCH 320/341] Update ScriptEngine::entityScriptingInterface to be static pointer Statically allocating the EntityScriptingInterface means we can't make sure it is initialized AFTER NodeList has been initialized --- libraries/script-engine/src/ScriptEngine.cpp | 30 +++++++++++++------- libraries/script-engine/src/ScriptEngine.h | 4 +-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3bdf9a9fa9..944714552a 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -44,7 +44,7 @@ #include "MIDIEvent.h" -EntityScriptingInterface ScriptEngine::_entityScriptingInterface; +EntityScriptingInterface* ScriptEngine::_entityScriptingInterface; static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ qDebug() << "script:print()<<" << context->argument(0).toString(); @@ -73,6 +73,13 @@ void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputCon out = qobject_cast(object.toQObject()); } +EntityScriptingInterface* ScriptEngine::getEntityScriptingInterface() { + if (ScriptEngine::_entityScriptingInterface == nullptr) { + ScriptEngine::_entityScriptingInterface = new EntityScriptingInterface(); + } + return ScriptEngine::_entityScriptingInterface; +} + ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface) : @@ -97,6 +104,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { + getEntityScriptingInterface(); _allScriptsMutex.lock(); _allKnownScriptEngines.insert(this); _allScriptsMutex.unlock(); @@ -314,7 +322,7 @@ void ScriptEngine::init() { auto sceneScriptingInterface = DependencyManager::set(); - _entityScriptingInterface.init(); + _entityScriptingInterface->init(); // register various meta-types registerMetaTypes(this); @@ -352,7 +360,7 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); registerGlobalObject("Controller", _controllerScriptingInterface); - registerGlobalObject("Entities", &_entityScriptingInterface); + registerGlobalObject("Entities", _entityScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); @@ -489,13 +497,13 @@ void ScriptEngine::run() { break; } - if (!_isFinished && _entityScriptingInterface.getEntityPacketSender()->serversExist()) { + if (!_isFinished && _entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. - _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); + _entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_entityScriptingInterface.getEntityPacketSender()->isThreaded()) { - _entityScriptingInterface.getEntityPacketSender()->process(); + if (!_entityScriptingInterface->getEntityPacketSender()->isThreaded()) { + _entityScriptingInterface->getEntityPacketSender()->process(); } } @@ -622,13 +630,13 @@ void ScriptEngine::run() { // kill the avatar identity timer delete _avatarIdentityTimer; - if (_entityScriptingInterface.getEntityPacketSender()->serversExist()) { + if (_entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. - _entityScriptingInterface.getEntityPacketSender()->releaseQueuedMessages(); + _entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_entityScriptingInterface.getEntityPacketSender()->isThreaded()) { - _entityScriptingInterface.getEntityPacketSender()->process(); + if (!_entityScriptingInterface->getEntityPacketSender()->isThreaded()) { + _entityScriptingInterface->getEntityPacketSender()->process(); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 154fdb88e3..7241baae95 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -47,7 +47,7 @@ public: ~ScriptEngine(); /// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - static EntityScriptingInterface* getEntityScriptingInterface() { return &_entityScriptingInterface; } + static EntityScriptingInterface* getEntityScriptingInterface(); ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } @@ -153,7 +153,7 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); - static EntityScriptingInterface _entityScriptingInterface; + static EntityScriptingInterface* _entityScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; From 26e3b331eefec82fa60d8208185fb5d1705e3bf0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 10:42:09 -0800 Subject: [PATCH 321/341] Update editEntities.js lock checking to use event instead of polling --- examples/editEntities.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/editEntities.js b/examples/editEntities.js index f6c376ba74..a0f3cdc167 100644 --- a/examples/editEntities.js +++ b/examples/editEntities.js @@ -406,13 +406,11 @@ var toolBar = (function () { that.setActive(false); }); - function checkForPermissionToEdit() { - if (isActive && !Entities.canAdjustLocks()) { + Entities.canAdjustLocksChanged.connect(function(canAdjustLocks) { + if (isActive && !canAdjustLocks) { that.setActive(false); } - } - - Script.setInterval(checkForPermissionToEdit, 1000); + }); that.cleanup = function () { toolBar.cleanup(); From 75a943386bca326e927d4c95e09417410055ad51 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 10:44:32 -0800 Subject: [PATCH 322/341] Remove nullptr comparison --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 944714552a..d02b88ec3b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -74,7 +74,7 @@ void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputCon } EntityScriptingInterface* ScriptEngine::getEntityScriptingInterface() { - if (ScriptEngine::_entityScriptingInterface == nullptr) { + if (!ScriptEngine::_entityScriptingInterface) { ScriptEngine::_entityScriptingInterface = new EntityScriptingInterface(); } return ScriptEngine::_entityScriptingInterface; From f739bf2116e34c79e681c13b49e803a2c1fcc4c2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 11:20:00 -0800 Subject: [PATCH 323/341] Fix properties window changes not taking affect when losing focus --- examples/html/entityProperties.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index f54c2c9ce3..53e8062517 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -439,6 +439,13 @@ percentage: parseInt(elRescaleDimensionsPct.value), })); }); + + window.onblur = function() { + // Fake a change event + var ev = document.createEvent("HTMLEvents"); + ev.initEvent("change", true, true); + document.activeElement.dispatchEvent(ev); + } } From 38a361dcf01050d4d65c415059cbbb34b852dd20 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 11:32:07 -0800 Subject: [PATCH 324/341] Remove class scope on _entityScriptingInterface property references --- libraries/script-engine/src/ScriptEngine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d02b88ec3b..53f1bae436 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -74,10 +74,10 @@ void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputCon } EntityScriptingInterface* ScriptEngine::getEntityScriptingInterface() { - if (!ScriptEngine::_entityScriptingInterface) { - ScriptEngine::_entityScriptingInterface = new EntityScriptingInterface(); + if (!_entityScriptingInterface) { + _entityScriptingInterface = new EntityScriptingInterface(); } - return ScriptEngine::_entityScriptingInterface; + return _entityScriptingInterface; } ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, From bb7b132b78c7d1de1ce0b50ba6cc1962194fbab1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 2 Mar 2015 14:18:26 -0800 Subject: [PATCH 325/341] Add a way to indicate that a specific message of a certain form should only be printed once. Different messages that match the same form will each be printed once. --- domain-server/src/DomainServer.cpp | 4 ++-- libraries/shared/src/LogHandler.cpp | 16 ++++++++++++++++ libraries/shared/src/LogHandler.h | 6 +++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9aec456587..68093b9c71 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -944,7 +944,7 @@ void DomainServer::readAvailableDatagrams() { if (requestAssignment.getType() != Assignment::AgentType || noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) { - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex + static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex ("Received a request for assignment type [^ ]+ from [^ ]+"); qDebug() << "Received a request for assignment type" << requestAssignment.getType() << "from" << senderSockAddr; @@ -977,7 +977,7 @@ void DomainServer::readAvailableDatagrams() { } else { if (requestAssignment.getType() != Assignment::AgentType || noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) { - static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex + static QString repeatedMessage = LogHandler::getInstance().addOnlyOnceMessageRegex ("Unable to fulfill assignment request of type [^ ]+ from [^ ]+"); qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType() << "from" << senderSockAddr; diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index 577bf83449..60cddb5cfe 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -101,6 +101,22 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont } } } + + // see if this message is one we should only print once + foreach(const QString& regexString, getInstance()._onlyOnceMessageRegexes) { + QRegExp onlyOnceRegex(regexString); + if (onlyOnceRegex.indexIn(message) != -1) { + if (!_onlyOnceMessageCountHash.contains(message)) { + // we have a match and haven't yet printed this message. + _onlyOnceMessageCountHash[message] = 1; + // break the foreach so we output the first match + break; + } else { + // We've already printed this message, don't print it again. + return QString(); + } + } + } } // log prefix is in the following format diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index f8f06b0033..914cad212d 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -48,6 +48,7 @@ public: static void verboseMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message); const QString& addRepeatedMessageRegex(const QString& regexString) { return *_repeatedMessageRegexes.insert(regexString); } + const QString& addOnlyOnceMessageRegex(const QString& regexString) { return *_onlyOnceMessageRegexes.insert(regexString); } private: LogHandler(); @@ -58,6 +59,9 @@ private: QSet _repeatedMessageRegexes; QHash _repeatMessageCountHash; QHash _lastRepeatedMessage; + + QSet _onlyOnceMessageRegexes; + QHash _onlyOnceMessageCountHash; }; -#endif // hifi_LogHandler_h \ No newline at end of file +#endif // hifi_LogHandler_h From b370e025c9c3c3a34c5759d714c42c8d1dd51c57 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 2 Mar 2015 15:05:31 -0800 Subject: [PATCH 326/341] Move EntityScriptingInterface instance to DependencyManager --- assignment-client/src/Agent.cpp | 12 ++++--- assignment-client/src/AssignmentClient.cpp | 2 ++ interface/src/Application.cpp | 12 ++++--- .../entities/src/EntityScriptingInterface.h | 3 +- libraries/script-engine/src/ScriptEngine.cpp | 32 +++++++------------ libraries/script-engine/src/ScriptEngine.h | 7 ---- 6 files changed, 31 insertions(+), 37 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index c545262967..d56db7aace 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -44,7 +44,7 @@ Agent::Agent(const QByteArray& packet) : // be the parent of the script engine so it gets moved when we do _scriptEngine.setParent(this); - _scriptEngine.getEntityScriptingInterface()->setPacketSender(&_entityEditSender); + DependencyManager::get()->setPacketSender(&_entityEditSender); DependencyManager::set(); DependencyManager::set(); @@ -68,8 +68,8 @@ void Agent::readPendingDatagrams() { // PacketType_JURISDICTION, first byte is the node type... switch (receivedPacket[headerBytes]) { case NodeType::EntityServer: - _scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()-> - queueReceivedPacket(matchedNode, receivedPacket); + DependencyManager::get()->getJurisdictionListener()-> + queueReceivedPacket(matchedNode, receivedPacket); break; } } @@ -211,10 +211,12 @@ void Agent::run() { _scriptEngine.registerGlobalObject("SoundCache", DependencyManager::get().data()); + auto entityScriptingInterface = DependencyManager::get(); + _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); - _entityViewer.setJurisdictionListener(_scriptEngine.getEntityScriptingInterface()->getJurisdictionListener()); + _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); _entityViewer.init(); - _scriptEngine.getEntityScriptingInterface()->setEntityTree(_entityViewer.getTree()); + entityScriptingInterface->setEntityTree(_entityViewer.getTree()); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 86680d2f03..fba96c4967 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri DependencyManager::registerInheritance(); auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); + auto entityScriptingInterface = DependencyManager::set(); // make up a uuid for this child so the parent can tell us apart. This id will be changed // when the domain server hands over an assignment. diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fe41621dc1..5f372cd2bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -241,6 +241,7 @@ bool setupEssentials(int& argc, char** argv) { auto dialogsManager = DependencyManager::set(); auto bandwidthRecorder = DependencyManager::set(); auto resouceCacheSharedItems = DependencyManager::set(); + auto entityScriptingInterface = DependencyManager::set(); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) auto speechRecognizer = DependencyManager::set(); #endif @@ -1766,8 +1767,10 @@ void Application::init() { tree->setSimulation(&_physicsEngine); _physicsEngine.init(&_entityEditSender); + auto entityScriptingInterface = DependencyManager::get(); + connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity, - ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity); + entityScriptingInterface.data(), &EntityScriptingInterface::entityCollisionWithEntity); // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity, @@ -1775,7 +1778,7 @@ void Application::init() { // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities - _entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface()); + _entities.connectSignalsToSlots(entityScriptingInterface.data()); _entityClipboardRenderer.init(); _entityClipboardRenderer.setViewFrustum(getViewFrustum()); @@ -3441,8 +3444,9 @@ void joystickFromScriptValue(const QScriptValue &object, Joystick* &out) { void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) { // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so // we can use the same ones from the application. - scriptEngine->getEntityScriptingInterface()->setPacketSender(&_entityEditSender); - scriptEngine->getEntityScriptingInterface()->setEntityTree(_entities.getTree()); + auto entityScriptingInterface = DependencyManager::get(); + entityScriptingInterface->setPacketSender(&_entityEditSender); + entityScriptingInterface->setEntityTree(_entities.getTree()); // AvatarManager has some custom types AvatarManager::registerMetaTypes(scriptEngine); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 50b571541d..bac018f2ae 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -48,7 +49,7 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra /// handles scripting of Entity commands from JS passed to assigned clients -class EntityScriptingInterface : public OctreeScriptingInterface { +class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency { Q_OBJECT public: EntityScriptingInterface(); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 53f1bae436..df327b9c5c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -44,8 +44,6 @@ #include "MIDIEvent.h" -EntityScriptingInterface* ScriptEngine::_entityScriptingInterface; - static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){ qDebug() << "script:print()<<" << context->argument(0).toString(); QString message = context->argument(0).toString() @@ -73,13 +71,6 @@ void inputControllerFromScriptValue(const QScriptValue &object, AbstractInputCon out = qobject_cast(object.toQObject()); } -EntityScriptingInterface* ScriptEngine::getEntityScriptingInterface() { - if (!_entityScriptingInterface) { - _entityScriptingInterface = new EntityScriptingInterface(); - } - return _entityScriptingInterface; -} - ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface) : @@ -104,7 +95,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam _isUserLoaded(false), _arrayBufferClass(new ArrayBufferClass(this)) { - getEntityScriptingInterface(); _allScriptsMutex.lock(); _allKnownScriptEngines.insert(this); _allScriptsMutex.unlock(); @@ -322,7 +312,8 @@ void ScriptEngine::init() { auto sceneScriptingInterface = DependencyManager::set(); - _entityScriptingInterface->init(); + auto entityScriptingInterface = DependencyManager::get(); + entityScriptingInterface->init(); // register various meta-types registerMetaTypes(this); @@ -360,7 +351,7 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); registerGlobalObject("Controller", _controllerScriptingInterface); - registerGlobalObject("Entities", _entityScriptingInterface); + registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); @@ -478,6 +469,7 @@ void ScriptEngine::run() { int thisFrame = 0; auto nodeList = DependencyManager::get(); + auto entityScriptingInterface = DependencyManager::get(); qint64 lastUpdate = usecTimestampNow(); @@ -497,13 +489,13 @@ void ScriptEngine::run() { break; } - if (!_isFinished && _entityScriptingInterface->getEntityPacketSender()->serversExist()) { + if (!_isFinished && entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. - _entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); + entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_entityScriptingInterface->getEntityPacketSender()->isThreaded()) { - _entityScriptingInterface->getEntityPacketSender()->process(); + if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { + entityScriptingInterface->getEntityPacketSender()->process(); } } @@ -630,13 +622,13 @@ void ScriptEngine::run() { // kill the avatar identity timer delete _avatarIdentityTimer; - if (_entityScriptingInterface->getEntityPacketSender()->serversExist()) { + if (entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. - _entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); + entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_entityScriptingInterface->getEntityPacketSender()->isThreaded()) { - _entityScriptingInterface->getEntityPacketSender()->process(); + if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { + entityScriptingInterface->getEntityPacketSender()->process(); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7241baae95..84d2527bd0 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -31,8 +31,6 @@ #include "ScriptUUID.h" #include "Vec3.h" -class EntityScriptingInterface; - const QString NO_SCRIPT(""); const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 1000) + 0.5); @@ -46,9 +44,6 @@ public: ~ScriptEngine(); - /// Access the EntityScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - static EntityScriptingInterface* getEntityScriptingInterface(); - ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; } /// sets the script contents, will return false if failed, will fail if script is already running @@ -153,8 +148,6 @@ private: QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); - static EntityScriptingInterface* _entityScriptingInterface; - AbstractControllerScriptingInterface* _controllerScriptingInterface; AvatarData* _avatarData; QString _scriptName; From 5c3c94a6188d2da27e49587b6627f898ab0bd44c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 2 Mar 2015 17:21:43 -0800 Subject: [PATCH 327/341] remove metavoxels --- assignment-client/CMakeLists.txt | 2 +- assignment-client/src/AssignmentFactory.cpp | 3 - .../src/metavoxels/MetavoxelServer.cpp | 367 -- .../src/metavoxels/MetavoxelServer.h | 157 - domain-server/src/DomainServer.cpp | 3 +- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 38 +- interface/src/Application.h | 5 - interface/src/DatagramProcessor.cpp | 3 - interface/src/Menu.cpp | 10 - interface/src/Menu.h | 6 - interface/src/MetavoxelSystem.cpp | 2433 ---------- interface/src/MetavoxelSystem.h | 445 -- interface/src/ui/BandwidthDialog.cpp | 8 +- interface/src/ui/BandwidthDialog.h | 3 +- interface/src/ui/CachesSizeDialog.cpp | 4 - interface/src/ui/DialogsManager.cpp | 12 - interface/src/ui/DialogsManager.h | 6 - interface/src/ui/MetavoxelEditor.cpp | 1101 ----- interface/src/ui/MetavoxelEditor.h | 479 -- .../src/ui/MetavoxelNetworkSimulator.cpp | 87 - interface/src/ui/MetavoxelNetworkSimulator.h | 41 - interface/src/ui/Stats.cpp | 42 +- interface/src/ui/Stats.h | 9 - libraries/metavoxels/CMakeLists.txt | 13 - .../metavoxels/src/AttributeRegistry.cpp | 499 -- libraries/metavoxels/src/AttributeRegistry.h | 409 -- libraries/metavoxels/src/Bitstream.cpp | 3552 --------------- libraries/metavoxels/src/Bitstream.h | 1781 -------- .../metavoxels/src/DatagramSequencer.cpp | 952 ---- libraries/metavoxels/src/DatagramSequencer.h | 445 -- libraries/metavoxels/src/Endpoint.cpp | 117 - libraries/metavoxels/src/Endpoint.h | 89 - .../metavoxels/src/MetavoxelClientManager.cpp | 446 -- .../metavoxels/src/MetavoxelClientManager.h | 157 - libraries/metavoxels/src/MetavoxelData.cpp | 1818 -------- libraries/metavoxels/src/MetavoxelData.h | 539 --- .../metavoxels/src/MetavoxelMessages.cpp | 282 -- libraries/metavoxels/src/MetavoxelMessages.h | 269 -- libraries/metavoxels/src/MetavoxelUtil.cpp | 723 --- libraries/metavoxels/src/MetavoxelUtil.h | 362 -- libraries/metavoxels/src/ScriptCache.cpp | 209 - libraries/metavoxels/src/ScriptCache.h | 152 - libraries/metavoxels/src/SharedObject.cpp | 319 -- libraries/metavoxels/src/SharedObject.h | 268 -- libraries/metavoxels/src/Spanner.cpp | 4058 ----------------- libraries/metavoxels/src/Spanner.h | 866 ---- libraries/networking/src/Assignment.cpp | 4 - libraries/networking/src/Assignment.h | 2 +- libraries/networking/src/Node.cpp | 1 - libraries/networking/src/Node.h | 1 - libraries/networking/src/PacketHeaders.cpp | 3 - libraries/networking/src/PacketHeaders.h | 20 +- .../render-utils/src/DeferredLightingEffect.h | 2 +- libraries/script-engine/CMakeLists.txt | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 2 - tests/metavoxels/CMakeLists.txt | 10 - tests/metavoxels/src/MetavoxelTests.cpp | 1230 ----- tests/metavoxels/src/MetavoxelTests.h | 251 - tests/metavoxels/src/main.cpp | 18 - tests/octree/CMakeLists.txt | 2 +- tools/CMakeLists.txt | 2 - tools/bitstream2json/CMakeLists.txt | 6 - tools/bitstream2json/src/main.cpp | 70 - tools/json2bitstream/CMakeLists.txt | 6 - tools/json2bitstream/src/main.cpp | 76 - 66 files changed, 30 insertions(+), 25269 deletions(-) delete mode 100644 assignment-client/src/metavoxels/MetavoxelServer.cpp delete mode 100644 assignment-client/src/metavoxels/MetavoxelServer.h delete mode 100644 interface/src/MetavoxelSystem.cpp delete mode 100644 interface/src/MetavoxelSystem.h delete mode 100644 interface/src/ui/MetavoxelEditor.cpp delete mode 100644 interface/src/ui/MetavoxelEditor.h delete mode 100644 interface/src/ui/MetavoxelNetworkSimulator.cpp delete mode 100644 interface/src/ui/MetavoxelNetworkSimulator.h delete mode 100644 libraries/metavoxels/CMakeLists.txt delete mode 100644 libraries/metavoxels/src/AttributeRegistry.cpp delete mode 100644 libraries/metavoxels/src/AttributeRegistry.h delete mode 100644 libraries/metavoxels/src/Bitstream.cpp delete mode 100644 libraries/metavoxels/src/Bitstream.h delete mode 100644 libraries/metavoxels/src/DatagramSequencer.cpp delete mode 100644 libraries/metavoxels/src/DatagramSequencer.h delete mode 100644 libraries/metavoxels/src/Endpoint.cpp delete mode 100644 libraries/metavoxels/src/Endpoint.h delete mode 100644 libraries/metavoxels/src/MetavoxelClientManager.cpp delete mode 100644 libraries/metavoxels/src/MetavoxelClientManager.h delete mode 100644 libraries/metavoxels/src/MetavoxelData.cpp delete mode 100644 libraries/metavoxels/src/MetavoxelData.h delete mode 100644 libraries/metavoxels/src/MetavoxelMessages.cpp delete mode 100644 libraries/metavoxels/src/MetavoxelMessages.h delete mode 100644 libraries/metavoxels/src/MetavoxelUtil.cpp delete mode 100644 libraries/metavoxels/src/MetavoxelUtil.h delete mode 100644 libraries/metavoxels/src/ScriptCache.cpp delete mode 100644 libraries/metavoxels/src/ScriptCache.h delete mode 100644 libraries/metavoxels/src/SharedObject.cpp delete mode 100644 libraries/metavoxels/src/SharedObject.h delete mode 100644 libraries/metavoxels/src/Spanner.cpp delete mode 100644 libraries/metavoxels/src/Spanner.h delete mode 100644 tests/metavoxels/CMakeLists.txt delete mode 100644 tests/metavoxels/src/MetavoxelTests.cpp delete mode 100644 tests/metavoxels/src/MetavoxelTests.h delete mode 100644 tests/metavoxels/src/main.cpp delete mode 100644 tools/bitstream2json/CMakeLists.txt delete mode 100644 tools/bitstream2json/src/main.cpp delete mode 100644 tools/json2bitstream/CMakeLists.txt delete mode 100644 tools/json2bitstream/src/main.cpp diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index ada534431a..2561a1502d 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -8,7 +8,7 @@ target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) # link in the shared libraries link_hifi_libraries( - audio avatars octree environment gpu model fbx entities metavoxels + audio avatars octree environment gpu model fbx entities networking animation shared script-engine embedded-webserver physics ) diff --git a/assignment-client/src/AssignmentFactory.cpp b/assignment-client/src/AssignmentFactory.cpp index 78e905edfa..4dafd64a92 100644 --- a/assignment-client/src/AssignmentFactory.cpp +++ b/assignment-client/src/AssignmentFactory.cpp @@ -15,7 +15,6 @@ #include "AssignmentFactory.h" #include "audio/AudioMixer.h" #include "avatars/AvatarMixer.h" -#include "metavoxels/MetavoxelServer.h" #include "entities/EntityServer.h" ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet) { @@ -34,8 +33,6 @@ ThreadedAssignment* AssignmentFactory::unpackAssignment(const QByteArray& packet return new AvatarMixer(packet); case Assignment::AgentType: return new Agent(packet); - case Assignment::MetavoxelServerType: - return new MetavoxelServer(packet); case Assignment::EntityServerType: return new EntityServer(packet); default: diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp deleted file mode 100644 index 669972cbee..0000000000 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ /dev/null @@ -1,367 +0,0 @@ -// -// MetavoxelServer.cpp -// assignment-client/src/metavoxels -// -// Created by Andrzej Kapolka on 12/18/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "MetavoxelServer.h" - -MetavoxelServer::MetavoxelServer(const QByteArray& packet) : - ThreadedAssignment(packet), - _nextSender(0), - _savedDataInitialized(false) { -} - -void MetavoxelServer::applyEdit(const MetavoxelEditMessage& edit) { - MetavoxelData data = _data; - edit.apply(data, SharedObject::getWeakHash()); - setData(data); -} - -void MetavoxelServer::setData(const MetavoxelData& data, bool loaded) { - if (_data == data) { - return; - } - emit dataChanged(_data = data); - - if (loaded) { - _savedData = data; - - } else if (!_savedDataInitialized) { - _savedDataInitialized = true; - - // start the save timer - QTimer* saveTimer = new QTimer(this); - connect(saveTimer, &QTimer::timeout, this, &MetavoxelServer::maybeSaveData); - const int SAVE_INTERVAL = 1000 * 30; - saveTimer->start(SAVE_INTERVAL); - } -} - -const QString METAVOXEL_SERVER_LOGGING_NAME = "metavoxel-server"; - -void MetavoxelServer::run() { - commonInit(METAVOXEL_SERVER_LOGGING_NAME, NodeType::MetavoxelServer); - - auto nodeList = DependencyManager::get(); - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - - connect(nodeList.data(), &NodeList::nodeAdded, this, &MetavoxelServer::maybeAttachSession); - connect(nodeList.data(), &NodeList::nodeKilled, this, &MetavoxelServer::maybeDeleteSession); - - // initialize Bitstream before using it in multiple threads - Bitstream::preThreadingInit(); - - // create the senders, each with its own thread - int threadCount = QThread::idealThreadCount(); - if (threadCount == -1) { - const int DEFAULT_THREAD_COUNT = 4; - threadCount = DEFAULT_THREAD_COUNT; - } - qDebug() << "Creating" << threadCount << "sender threads"; - for (int i = 0; i < threadCount; i++) { - QThread* thread = new QThread(this); - MetavoxelSender* sender = new MetavoxelSender(this); - sender->moveToThread(thread); - connect(thread, &QThread::finished, sender, &QObject::deleteLater); - thread->start(); - QMetaObject::invokeMethod(sender, "start"); - _senders.append(sender); - } - - // create the persister and start it in its own thread - _persister = new MetavoxelPersister(this); - QThread* persistenceThread = new QThread(this); - _persister->moveToThread(persistenceThread); - connect(persistenceThread, &QThread::finished, _persister, &QObject::deleteLater); - persistenceThread->start(); - - // queue up the load - QMetaObject::invokeMethod(_persister, "load"); -} - -void MetavoxelServer::readPendingDatagrams() { - QByteArray receivedPacket; - HifiSockAddr senderSockAddr; - - auto nodeList = DependencyManager::get(); - - while (readAvailableDatagram(receivedPacket, senderSockAddr)) { - if (nodeList->packetVersionAndHashMatch(receivedPacket)) { - switch (packetTypeForPacket(receivedPacket)) { - case PacketTypeMetavoxelData: - nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket); - break; - - default: - nodeList->processNodeData(senderSockAddr, receivedPacket); - break; - } - } - } -} - -void MetavoxelServer::aboutToFinish() { - QMetaObject::invokeMethod(_persister, "save", Q_ARG(const MetavoxelData&, _data)); - - foreach (MetavoxelSender* sender, _senders) { - sender->thread()->quit(); - sender->thread()->wait(); - } - _persister->thread()->quit(); - _persister->thread()->wait(); -} - -void MetavoxelServer::maybeAttachSession(const SharedNodePointer& node) { - if (node->getType() == NodeType::Agent) { - QMutexLocker locker(&node->getMutex()); - MetavoxelSender* sender = _senders.at(_nextSender); - _nextSender = (_nextSender + 1) % _senders.size(); - MetavoxelSession* session = new MetavoxelSession(node, sender); - session->moveToThread(sender->thread()); - QMetaObject::invokeMethod(sender, "addSession", Q_ARG(QObject*, session)); - node->setLinkedData(session); - } -} - -void MetavoxelServer::maybeDeleteSession(const SharedNodePointer& node) { - if (node->getType() == NodeType::Agent) { - // we assume the node is already locked - MetavoxelSession* session = static_cast(node->getLinkedData()); - if (session) { - node->setLinkedData(NULL); - session->deleteLater(); - } - } -} - -void MetavoxelServer::maybeSaveData() { - if (_savedData != _data) { - QMetaObject::invokeMethod(_persister, "save", Q_ARG(const MetavoxelData&, _savedData = _data)); - } -} - -MetavoxelSender::MetavoxelSender(MetavoxelServer* server) : - _server(server), - _sendTimer(this) { - - _sendTimer.setSingleShot(true); - connect(&_sendTimer, &QTimer::timeout, this, &MetavoxelSender::sendDeltas); - - connect(_server, &MetavoxelServer::dataChanged, this, &MetavoxelSender::setData); -} - -const int SEND_INTERVAL = 50; - -void MetavoxelSender::start() { - _lastSend = QDateTime::currentMSecsSinceEpoch(); - _sendTimer.start(SEND_INTERVAL); -} - -void MetavoxelSender::addSession(QObject* session) { - _sessions.insert(static_cast(session)); - connect(session, &QObject::destroyed, this, &MetavoxelSender::removeSession); -} - -void MetavoxelSender::sendDeltas() { - // send deltas for all sessions associated with our thread - foreach (MetavoxelSession* session, _sessions) { - session->update(); - } - - // restart the send timer - qint64 now = QDateTime::currentMSecsSinceEpoch(); - int elapsed = now - _lastSend; - _lastSend = now; - - _sendTimer.start(qMax(0, 2 * SEND_INTERVAL - qMax(elapsed, SEND_INTERVAL))); -} - -void MetavoxelSender::removeSession(QObject* session) { - _sessions.remove(static_cast(session)); -} - -MetavoxelSession::MetavoxelSession(const SharedNodePointer& node, MetavoxelSender* sender) : - Endpoint(node, new PacketRecord(), NULL), - _sender(sender), - _reliableDeltaChannel(NULL), - _reliableDeltaID(0) { - - connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&))); - connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived())); - connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&, Bitstream&)), - SLOT(handleMessage(const QVariant&, Bitstream&))); -} - -void MetavoxelSession::update() { - // wait until we have a valid lod before sending - if (!_lod.isValid()) { - return; - } - // if we're sending a reliable delta, wait until it's acknowledged - if (_reliableDeltaChannel) { - sendPacketGroup(); - return; - } - Bitstream& out = _sequencer.startPacket(); - int start = _sequencer.getOutputStream().getUnderlying().device()->pos(); - out << QVariant::fromValue(MetavoxelDeltaMessage()); - PacketRecord* sendRecord = getLastAcknowledgedSendRecord(); - _sender->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); - out.flush(); - int end = _sequencer.getOutputStream().getUnderlying().device()->pos(); - if (end > _sequencer.getMaxPacketSize()) { - // we need to send the delta on the reliable channel - _reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - _reliableDeltaChannel->startMessage(); - _reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start); - _reliableDeltaChannel->endMessage(); - - _reliableDeltaWriteMappings = out.getAndResetWriteMappings(); - _reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten(); - _reliableDeltaData = _sender->getData(); - _reliableDeltaLOD = _lod; - - // go back to the beginning with the current packet and note that there's a delta pending - _sequencer.getOutputStream().getUnderlying().device()->seek(start); - MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID, sendRecord->getPacketNumber(), _lodPacketNumber }; - out << (_reliableDeltaMessage = QVariant::fromValue(msg)); - _sequencer.endPacket(); - - } else { - _sequencer.endPacket(); - } - - // perhaps send additional packets to fill out the group - sendPacketGroup(1); -} - -void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) { - handleMessage(message); -} - -PacketRecord* MetavoxelSession::maybeCreateSendRecord() const { - return _reliableDeltaChannel ? new PacketRecord(_sequencer.getOutgoingPacketNumber(), - _reliableDeltaLOD, _reliableDeltaData) : new PacketRecord(_sequencer.getOutgoingPacketNumber(), - _lod, _sender->getData()); -} - -void MetavoxelSession::handleMessage(const QVariant& message) { - int userType = message.userType(); - if (userType == ClientStateMessage::Type) { - ClientStateMessage state = message.value(); - _lod = state.lod; - _lodPacketNumber = _sequencer.getIncomingPacketNumber(); - - } else if (userType == MetavoxelEditMessage::Type) { - if (_node->getCanAdjustLocks()) { - QMetaObject::invokeMethod(_sender->getServer(), "applyEdit", - Q_ARG(const MetavoxelEditMessage&, message.value())); - } - } else if (userType == QMetaType::QVariantList) { - foreach (const QVariant& element, message.toList()) { - handleMessage(element); - } - } -} - -void MetavoxelSession::checkReliableDeltaReceived() { - if (!_reliableDeltaChannel || _reliableDeltaChannel->getOffset() < _reliableDeltaReceivedOffset) { - return; - } - _sequencer.getOutputStream().persistWriteMappings(_reliableDeltaWriteMappings); - _reliableDeltaWriteMappings = Bitstream::WriteMappings(); - _reliableDeltaData = MetavoxelData(); - _reliableDeltaChannel = NULL; -} - -void MetavoxelSession::sendPacketGroup(int alreadySent) { - int additionalPackets = _sequencer.notePacketGroup() - alreadySent; - for (int i = 0; i < additionalPackets; i++) { - Bitstream& out = _sequencer.startPacket(); - if (_reliableDeltaChannel) { - out << _reliableDeltaMessage; - } else { - out << QVariant(); - } - _sequencer.endPacket(); - } -} - -MetavoxelPersister::MetavoxelPersister(MetavoxelServer* server) : - _server(server) { -} - -const char* SAVE_FILE = "/resources/metavoxels.dat"; - -const int FILE_MAGIC = 0xDADAFACE; -const int FILE_VERSION = 4; - -void MetavoxelPersister::load() { - QString path = QCoreApplication::applicationDirPath() + SAVE_FILE; - QFile file(path); - if (!file.exists()) { - return; - } - MetavoxelData data; - { - QDebug debug = qDebug() << "Reading from" << path << "..."; - file.open(QIODevice::ReadOnly); - QDataStream inStream(&file); - Bitstream in(inStream); - int magic, version; - in >> magic; - if (magic != FILE_MAGIC) { - debug << "wrong file magic: " << magic; - return; - } - in >> version; - if (version != FILE_VERSION) { - debug << "wrong file version: " << version; - return; - } - try { - in >> data; - } catch (const BitstreamException& e) { - debug << "failed, " << e.getDescription(); - return; - } - QMetaObject::invokeMethod(_server, "setData", Q_ARG(const MetavoxelData&, data), Q_ARG(bool, true)); - debug << "done."; - } - data.dumpStats(); -} - -void MetavoxelPersister::save(const MetavoxelData& data) { - QString path = QCoreApplication::applicationDirPath() + SAVE_FILE; - QDir directory = QFileInfo(path).dir(); - if (!directory.exists()) { - directory.mkpath("."); - } - QDebug debug = qDebug() << "Writing to" << path << "..."; - QSaveFile file(path); - file.open(QIODevice::WriteOnly); - QDataStream outStream(&file); - Bitstream out(outStream); - out << FILE_MAGIC << FILE_VERSION << data; - out.flush(); - file.commit(); - debug << "done."; -} diff --git a/assignment-client/src/metavoxels/MetavoxelServer.h b/assignment-client/src/metavoxels/MetavoxelServer.h deleted file mode 100644 index 2d1529b1b1..0000000000 --- a/assignment-client/src/metavoxels/MetavoxelServer.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// MetavoxelServer.h -// assignment-client/src/metavoxels -// -// Created by Andrzej Kapolka on 12/18/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelServer_h -#define hifi_MetavoxelServer_h - -#include -#include - -#include - -#include - -class MetavoxelEditMessage; -class MetavoxelPersister; -class MetavoxelSender; -class MetavoxelSession; - -/// Maintains a shared metavoxel system, accepting change requests and broadcasting updates. -class MetavoxelServer : public ThreadedAssignment { - Q_OBJECT - -public: - - MetavoxelServer(const QByteArray& packet); - - Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit); - - const MetavoxelData& getData() const { return _data; } - - Q_INVOKABLE void setData(const MetavoxelData& data, bool loaded = false); - - virtual void run(); - - virtual void readPendingDatagrams(); - - virtual void aboutToFinish(); - -signals: - - void dataChanged(const MetavoxelData& data); - -private slots: - - void maybeAttachSession(const SharedNodePointer& node); - void maybeDeleteSession(const SharedNodePointer& node); - void maybeSaveData(); - -private: - - QVector _senders; - int _nextSender; - - MetavoxelPersister* _persister; - - MetavoxelData _data; - MetavoxelData _savedData; - bool _savedDataInitialized; -}; - -/// Handles update sending for one thread. -class MetavoxelSender : public QObject { - Q_OBJECT - -public: - - MetavoxelSender(MetavoxelServer* server); - - MetavoxelServer* getServer() const { return _server; } - - const MetavoxelData& getData() const { return _data; } - - Q_INVOKABLE void start(); - - Q_INVOKABLE void addSession(QObject* session); - -private slots: - - void setData(const MetavoxelData& data) { _data = data; } - void sendDeltas(); - void removeSession(QObject* session); - -private: - - MetavoxelServer* _server; - QSet _sessions; - - QTimer _sendTimer; - qint64 _lastSend; - - MetavoxelData _data; -}; - -/// Contains the state of a single client session. -class MetavoxelSession : public Endpoint { - Q_OBJECT - -public: - - MetavoxelSession(const SharedNodePointer& node, MetavoxelSender* sender); - - virtual void update(); - -protected: - - virtual void handleMessage(const QVariant& message, Bitstream& in); - - virtual PacketRecord* maybeCreateSendRecord() const; - -private slots: - - void handleMessage(const QVariant& message); - void checkReliableDeltaReceived(); - -private: - - void sendPacketGroup(int alreadySent = 0); - - MetavoxelSender* _sender; - - MetavoxelLOD _lod; - int _lodPacketNumber; - - ReliableChannel* _reliableDeltaChannel; - int _reliableDeltaReceivedOffset; - MetavoxelData _reliableDeltaData; - MetavoxelLOD _reliableDeltaLOD; - Bitstream::WriteMappings _reliableDeltaWriteMappings; - int _reliableDeltaID; - QVariant _reliableDeltaMessage; -}; - -/// Handles persistence in a separate thread. -class MetavoxelPersister : public QObject { - Q_OBJECT - -public: - - MetavoxelPersister(MetavoxelServer* server); - - Q_INVOKABLE void load(); - Q_INVOKABLE void save(const MetavoxelData& data); - -private: - - MetavoxelServer* _server; -}; - -#endif // hifi_MetavoxelServer_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9aec456587..adb32448ab 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -559,8 +559,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet #include #include +#include #include #include @@ -75,7 +76,7 @@ #include #include #include -#include +//#include #include #include #include @@ -220,7 +221,7 @@ bool setupEssentials(int& argc, char** argv) { auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Agent, listenPort); auto geometryCache = DependencyManager::set(); - auto scriptCache = DependencyManager::set(); + //auto scriptCache = DependencyManager::set(); auto soundCache = DependencyManager::set(); auto glowEffect = DependencyManager::set(); auto faceshift = DependencyManager::set(); @@ -416,8 +417,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // tell the NodeList instance who to tell the domain server we care about nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::EntityServer - << NodeType::MetavoxelServer); + << NodeType::EntityServer); // connect to the packet sent signal of the _entityEditSender connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); @@ -600,7 +600,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - DependencyManager::destroy(); + //DependencyManager::destroy(); DependencyManager::destroy(); qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages @@ -773,8 +773,9 @@ void Application::paintGL() { { PerformanceTimer perfTimer("renderOverlay"); + // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() + _applicationOverlay.renderOverlay(true); if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) { - _applicationOverlay.renderOverlay(true); _applicationOverlay.displayOverlayTexture(); } } @@ -1443,8 +1444,7 @@ void Application::sendPingPackets() { QByteArray pingPacket = DependencyManager::get()->constructPingPacket(); controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::EntityServer - << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::MetavoxelServer); + << NodeType::AudioMixer << NodeType::AvatarMixer); } // Every second, check the frame rates and other stuff @@ -1781,8 +1781,6 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); - _metavoxels.init(); - _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); @@ -1945,16 +1943,6 @@ void Application::updateThreads(float deltaTime) { } } -void Application::updateMetavoxels(float deltaTime) { - PerformanceTimer perfTimer("updateMetavoxels"); - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()"); - - if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) { - _metavoxels.simulate(deltaTime); - } -} - void Application::cameraMenuChanged() { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { @@ -2055,7 +2043,6 @@ void Application::update(float deltaTime) { DependencyManager::get()->updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... - updateMetavoxels(deltaTime); // update metavoxels updateCamera(deltaTime); // handle various camera tweaks like off axis projection updateDialogs(deltaTime); // update various stats dialogs if present updateCursor(deltaTime); // Handle cursor updates @@ -2801,14 +2788,6 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs float originSphereRadius = 0.05f; DependencyManager::get()->renderSphere(originSphereRadius, 15, 15, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); - // also, metavoxels - if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) { - PerformanceTimer perfTimer("metavoxels"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... metavoxels..."); - _metavoxels.render(); - } - // render models... if (Menu::getInstance()->isOptionChecked(MenuOption::Entities)) { PerformanceTimer perfTimer("entities"); @@ -3485,7 +3464,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance()); - scriptEngine->registerGlobalObject("Metavoxels", &_metavoxels); scriptEngine->registerGlobalObject("GlobalServices", GlobalServicesScriptingInterface::getInstance()); qScriptRegisterMetaType(scriptEngine, DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4a8e712d30..980dc27be6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -45,7 +45,6 @@ #include "FileLogger.h" #include "GLCanvas.h" #include "Menu.h" -#include "MetavoxelSystem.h" #include "PacketHeaders.h" #include "Physics.h" #include "Stars.h" @@ -179,7 +178,6 @@ public: ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } - MetavoxelSystem* getMetavoxels() { return &_metavoxels; } EntityTreeRenderer* getEntities() { return &_entities; } Environment* getEnvironment() { return &_environment; } PrioVR* getPrioVR() { return &_prioVR; } @@ -423,7 +421,6 @@ private: void updateMouseRay(); void updateMyAvatarLookAtPosition(); void updateThreads(float deltaTime); - void updateMetavoxels(float deltaTime); void updateCamera(float deltaTime); void updateDialogs(float deltaTime); void updateCursor(float deltaTime); @@ -476,8 +473,6 @@ private: EntityTreeRenderer _entityClipboardRenderer; EntityTree _entityClipboard; - MetavoxelSystem _metavoxels; - ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) ViewFrustum _displayViewFrustum; diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index a491f9444d..1e63ce6655 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -100,9 +100,6 @@ void DatagramProcessor::processDatagrams() { } break; } - case PacketTypeMetavoxelData: - nodeList->findNodeAndUpdateWithDataFromPacket(incomingPacket); - break; case PacketTypeBulkAvatarData: case PacketTypeKillAvatar: case PacketTypeAvatarIdentity: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index be5b495fe9..2ebd589d69 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -148,8 +148,6 @@ Menu::Menu() { dialogsManager.data(), SLOT(editAnimations())); QMenu* toolsMenu = addMenu("Tools"); - addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, - dialogsManager.data(), SLOT(showMetavoxelEditor())); addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S, dialogsManager.data(), SLOT(showScriptEditor())); @@ -295,7 +293,6 @@ Menu::Menu() { QMenu* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere, Qt::SHIFT | Qt::Key_A, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Avatars, 0, true); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Entities, 0, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DontFadeOnOctreeServerChanges); @@ -394,13 +391,6 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); - QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels"); - addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false); - addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderHeightfields, 0, true); - addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderDualContourSurfaces, 0, true); - addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0, - dialogsManager.data(), SLOT(showMetavoxelNetworkSimulator())); - QMenu* handOptionsMenu = developerMenu->addMenu("Hands"); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlternateIK, 0, false); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 584e4d5254..fe1035d54b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -145,7 +145,6 @@ namespace MenuOption { const QString DisableNackPackets = "Disable NACK Packets"; const QString DisplayHands = "Show Hand Info"; const QString DisplayHandTargets = "Show Hand Targets"; - const QString DisplayHermiteData = "Display Hermite Data"; const QString DisplayModelBounds = "Display Model Bounds"; const QString DisplayModelTriangles = "Display Model Triangles"; const QString DisplayModelElementChildProxies = "Display Model Element Children"; @@ -186,12 +185,9 @@ namespace MenuOption { const QString Login = "Login"; const QString Log = "Log"; const QString LowVelocityFilter = "Low Velocity Filter"; - const QString MetavoxelEditor = "Metavoxel Editor..."; - const QString Metavoxels = "Metavoxels"; const QString Mirror = "Mirror"; const QString MuteAudio = "Mute Microphone"; const QString MuteEnvironment = "Mute Environment"; - const QString NetworkSimulator = "Network Simulator..."; const QString NewVoxelCullingMode = "New Voxel Culling Mode"; const QString NoFaceTracking = "None"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; @@ -205,10 +201,8 @@ namespace MenuOption { const QString Quit = "Quit"; const QString ReloadAllScripts = "Reload All Scripts"; const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes"; - const QString RenderDualContourSurfaces = "Render Dual Contour Surfaces"; const QString RenderFocusIndicator = "Show Eye Focus"; const QString RenderHeadCollisionShapes = "Show Head Collision Shapes"; - const QString RenderHeightfields = "Render Heightfields"; const QString RenderLookAtVectors = "Show Look-at Vectors"; const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes"; const QString RenderTargetFramerate = "Framerate"; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp deleted file mode 100644 index df8632d875..0000000000 --- a/interface/src/MetavoxelSystem.cpp +++ /dev/null @@ -1,2433 +0,0 @@ -// -// MetavoxelSystem.cpp -// interface/src -// -// Created by Andrzej Kapolka on 12/10/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "Application.h" -#include "MetavoxelSystem.h" - -using namespace std; - -REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) -REGISTER_META_OBJECT(SphereRenderer) -REGISTER_META_OBJECT(CuboidRenderer) -REGISTER_META_OBJECT(StaticModelRenderer) -REGISTER_META_OBJECT(HeightfieldRenderer) - -MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, - int minimumDelay, int maximumDelay, int bandwidthLimit) : - dropRate(dropRate), - repeatRate(repeatRate), - minimumDelay(minimumDelay), - maximumDelay(maximumDelay), - bandwidthLimit(bandwidthLimit) { -} - -MetavoxelSystem::~MetavoxelSystem() { - // kill the updater before we delete our network simulation objects - _updater->thread()->quit(); - _updater->thread()->wait(); - _updater = NULL; -} - -void MetavoxelSystem::init() { - MetavoxelClientManager::init(); - - _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + - "shaders/metavoxel_heightfield_base.vert"); - _baseHeightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + - "shaders/metavoxel_heightfield_base.frag"); - _baseHeightfieldProgram.link(); - - _baseHeightfieldProgram.bind(); - _baseHeightfieldProgram.setUniformValue("heightMap", 0); - _baseHeightfieldProgram.setUniformValue("diffuseMap", 1); - _baseHeightScaleLocation = _baseHeightfieldProgram.uniformLocation("heightScale"); - _baseColorScaleLocation = _baseHeightfieldProgram.uniformLocation("colorScale"); - _baseHeightfieldProgram.release(); - - loadSplatProgram("heightfield", _splatHeightfieldProgram, _splatHeightfieldLocations); - - _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + - "shaders/metavoxel_heightfield_cursor.vert"); - _heightfieldCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + - "shaders/metavoxel_cursor.frag"); - _heightfieldCursorProgram.link(); - - _heightfieldCursorProgram.bind(); - _heightfieldCursorProgram.setUniformValue("heightMap", 0); - _heightfieldCursorProgram.release(); - - _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + - "shaders/metavoxel_voxel_base.vert"); - _baseVoxelProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + - "shaders/metavoxel_voxel_base.frag"); - _baseVoxelProgram.link(); - - loadSplatProgram("voxel", _splatVoxelProgram, _splatVoxelLocations); - - _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + - "shaders/metavoxel_voxel_cursor.vert"); - _voxelCursorProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + - "shaders/metavoxel_cursor.frag"); - _voxelCursorProgram.link(); -} - -MetavoxelLOD MetavoxelSystem::getLOD() { - QReadLocker locker(&_lodLock); - return _lod; -} - -void MetavoxelSystem::setNetworkSimulation(const NetworkSimulation& simulation) { - QWriteLocker locker(&_networkSimulationLock); - _networkSimulation = simulation; -} - -MetavoxelSystem::NetworkSimulation MetavoxelSystem::getNetworkSimulation() { - QReadLocker locker(&_networkSimulationLock); - return _networkSimulation; -} - -class SimulateVisitor : public MetavoxelVisitor { -public: - - SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); - - virtual int visit(MetavoxelInfo& info); - -private: - - float _deltaTime; -}; - -SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod), - _deltaTime(deltaTime) { -} - -int SimulateVisitor::visit(MetavoxelInfo& info) { - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); - return STOP_RECURSION; -} - -void MetavoxelSystem::simulate(float deltaTime) { - // update the lod - { - QWriteLocker locker(&_lodLock); - const float DEFAULT_LOD_THRESHOLD = 0.01f; - _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), DEFAULT_LOD_THRESHOLD); - } - - SimulateVisitor simulateVisitor(deltaTime, getLOD()); - guideToAugmented(simulateVisitor); -} - -class RenderVisitor : public MetavoxelVisitor { -public: - - RenderVisitor(const MetavoxelLOD& lod); - - virtual int visit(MetavoxelInfo& info); -}; - -RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod) { -} - -int RenderVisitor::visit(MetavoxelInfo& info) { - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); - return STOP_RECURSION; -} - -class HeightfieldPoint { -public: - glm::vec3 vertex; - glm::vec2 textureCoord; -}; - -const int SPLAT_COUNT = 4; -const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 }; - -static const int EIGHT_BIT_MAXIMUM = 255; -static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; - -void MetavoxelSystem::render() { - // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); - _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), - viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), - viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); - - RenderVisitor renderVisitor(getLOD()); - guideToAugmented(renderVisitor, true); - - if (!_heightfieldBaseBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - DependencyManager::get()->setPrimaryDrawBuffers(true, true); - - glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_EQUAL, 0.0f); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - _baseHeightfieldProgram.bind(); - - foreach (const HeightfieldBaseLayerBatch& batch, _heightfieldBaseBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - HeightfieldPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); - glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); - - glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); - - _baseHeightfieldProgram.setUniform(_baseHeightScaleLocation, batch.heightScale); - _baseHeightfieldProgram.setUniform(_baseColorScaleLocation, batch.colorScale); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, batch.colorTextureID); - - glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - DependencyManager::get()->setPrimaryDrawBuffers(true, false); - - _baseHeightfieldProgram.release(); - - glDisable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - - if (!_heightfieldSplatBatches.isEmpty()) { - glDepthFunc(GL_LEQUAL); - glDepthMask(false); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - - _splatHeightfieldProgram.bind(); - - foreach (const HeightfieldSplatBatch& batch, _heightfieldSplatBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - HeightfieldPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); - glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); - - glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); - - _splatHeightfieldProgram.setUniformValue(_splatHeightfieldLocations.heightScale, - batch.heightScale.x, batch.heightScale.y); - _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.textureScale, batch.textureScale); - _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureOffset, batch.splatTextureOffset); - - const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; - _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesS, batch.splatTextureScalesS); - _splatHeightfieldProgram.setUniform(_splatHeightfieldLocations.splatTextureScalesT, batch.splatTextureScalesT); - _splatHeightfieldProgram.setUniformValue( - _splatHeightfieldLocations.textureValueMinima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); - _splatHeightfieldProgram.setUniformValue( - _splatHeightfieldLocations.textureValueMaxima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, batch.materialTextureID); - - for (int i = 0; i < SPLAT_COUNT; i++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); - glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); - } - - glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - for (int i = 0; i < SPLAT_COUNT; i++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - _splatHeightfieldProgram.release(); - - glDisable(GL_POLYGON_OFFSET_FILL); - glDepthMask(true); - glDepthFunc(GL_LESS); - } - - glDisable(GL_CULL_FACE); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - _heightfieldBaseBatches.clear(); - _heightfieldSplatBatches.clear(); - - if (!_voxelBaseBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) { - DependencyManager::get()->setPrimaryDrawBuffers(true, true); - - glEnableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); - glEnable(GL_CULL_FACE); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_EQUAL, 0.0f); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - _baseVoxelProgram.bind(); - - foreach (const MetavoxelBatch& batch, _voxelBaseBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - VoxelPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); - glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); - - glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - _baseVoxelProgram.release(); - - glDisable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - - DependencyManager::get()->setPrimaryDrawBuffers(true, false); - - if (!_voxelSplatBatches.isEmpty()) { - glDepthFunc(GL_LEQUAL); - glDepthMask(false); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - - _splatVoxelProgram.bind(); - - _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materials); - _splatVoxelProgram.enableAttributeArray(_splatVoxelLocations.materialWeights); - - foreach (const VoxelSplatBatch& batch, _voxelSplatBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - VoxelPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelPoint), &point->color); - glNormalPointer(GL_BYTE, sizeof(VoxelPoint), &point->normal); - - _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materials, - GL_UNSIGNED_BYTE, (qint64)&point->materials, SPLAT_COUNT, sizeof(VoxelPoint)); - _splatVoxelProgram.setAttributeBuffer(_splatVoxelLocations.materialWeights, - GL_UNSIGNED_BYTE, (qint64)&point->materialWeights, SPLAT_COUNT, sizeof(VoxelPoint)); - - const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; - _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureOffset, batch.splatTextureOffset); - _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesS, batch.splatTextureScalesS); - _splatVoxelProgram.setUniform(_splatVoxelLocations.splatTextureScalesT, batch.splatTextureScalesT); - _splatVoxelProgram.setUniformValue( - _splatVoxelLocations.textureValueMinima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP); - _splatVoxelProgram.setUniformValue( - _splatVoxelLocations.textureValueMaxima, - (batch.materialIndex + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, - (batch.materialIndex + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP); - - for (int i = 0; i < SPLAT_COUNT; i++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); - glBindTexture(GL_TEXTURE_2D, batch.splatTextureIDs[i]); - } - - glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - for (int i = 0; i < SPLAT_COUNT; i++) { - glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glActiveTexture(GL_TEXTURE0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - glDisable(GL_POLYGON_OFFSET_FILL); - glDepthMask(true); - glDepthFunc(GL_LESS); - - _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materials); - _splatVoxelProgram.disableAttributeArray(_splatVoxelLocations.materialWeights); - } - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisable(GL_CULL_FACE); - } - _voxelBaseBatches.clear(); - _voxelSplatBatches.clear(); - - if (!_hermiteBatches.isEmpty() && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)) { - DependencyManager::get()->setPrimaryDrawBuffers(true, true); - - glEnableClientState(GL_VERTEX_ARRAY); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glNormal3f(0.0f, 1.0f, 0.0f); - - DependencyManager::get()->bindSimpleProgram(); - - foreach (const HermiteBatch& batch, _hermiteBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - - glVertexPointer(3, GL_FLOAT, 0, 0); - - glDrawArrays(GL_LINES, 0, batch.vertexCount); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - DependencyManager::get()->releaseSimpleProgram(); - - glDisableClientState(GL_VERTEX_ARRAY); - - DependencyManager::get()->setPrimaryDrawBuffers(true, false); - } - _hermiteBatches.clear(); - - // give external parties a chance to join in - emit rendering(); -} - -void MetavoxelSystem::paintHeightfieldColor(const glm::vec3& position, float radius, const QColor& color) { - Sphere* sphere = new Sphere(); - sphere->setTranslation(position); - sphere->setScale(radius); - setHeightfieldColor(SharedObjectPointer(sphere), color, true); -} - -void MetavoxelSystem::paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material) { - Sphere* sphere = new Sphere(); - sphere->setTranslation(position); - sphere->setScale(radius); - setHeightfieldMaterial(SharedObjectPointer(sphere), material, true); -} - -void MetavoxelSystem::setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color, bool paint) { - MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, - SharedObjectPointer(), color, paint)) }; - applyEdit(edit, true); -} - -void MetavoxelSystem::setHeightfieldMaterial(const SharedObjectPointer& spanner, - const SharedObjectPointer& material, bool paint) { - MetavoxelEditMessage edit = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, material, QColor(), paint)) }; - applyMaterialEdit(edit, true); -} - -void MetavoxelSystem::deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const { - glDeleteTextures(1, (const GLuint*)&heightTextureID); - glDeleteTextures(1, (const GLuint*)&colorTextureID); - glDeleteTextures(1, (const GLuint*)&materialTextureID); -} - -void MetavoxelSystem::deleteBuffers(int vertexBufferID, int indexBufferID, int hermiteBufferID) const { - glDeleteBuffers(1, (const GLuint*)&vertexBufferID); - glDeleteBuffers(1, (const GLuint*)&indexBufferID); - glDeleteBuffers(1, (const GLuint*)&hermiteBufferID); -} - -class SpannerRenderVisitor : public SpannerVisitor { -public: - - SpannerRenderVisitor(const MetavoxelLOD& lod); - - virtual int visit(MetavoxelInfo& info); - virtual bool visit(Spanner* spanner); - -protected: - - int _containmentDepth; -}; - -SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), - _containmentDepth(INT_MAX) { -} - -int SpannerRenderVisitor::visit(MetavoxelInfo& info) { - if (_containmentDepth >= _depth) { - Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( - info.getBounds()); - if (intersection == Frustum::NO_INTERSECTION) { - return STOP_RECURSION; - } - _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX; - } - return SpannerVisitor::visit(info); -} - -bool SpannerRenderVisitor::visit(Spanner* spanner) { - spanner->getRenderer()->render(_lod, _containmentDepth <= _depth); - return true; -} - -class SpannerCursorRenderVisitor : public SpannerRenderVisitor { -public: - - SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds); - - virtual bool visit(Spanner* spanner); - - virtual int visit(MetavoxelInfo& info); - -private: - - Box _bounds; -}; - -SpannerCursorRenderVisitor::SpannerCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) : - SpannerRenderVisitor(lod), - _bounds(bounds) { -} - -bool SpannerCursorRenderVisitor::visit(Spanner* spanner) { - if (spanner->isHeightfield()) { - spanner->getRenderer()->render(_lod, _containmentDepth <= _depth, true); - } - return true; -} - -int SpannerCursorRenderVisitor::visit(MetavoxelInfo& info) { - return info.getBounds().intersects(_bounds) ? SpannerRenderVisitor::visit(info) : STOP_RECURSION; -} - -void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float radius) { - glDepthFunc(GL_LEQUAL); - glEnable(GL_CULL_FACE); - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - - glActiveTexture(GL_TEXTURE4); - float scale = 1.0f / radius; - glm::vec4 sCoefficients(scale, 0.0f, 0.0f, -scale * position.x); - glm::vec4 tCoefficients(0.0f, scale, 0.0f, -scale * position.y); - glm::vec4 rCoefficients(0.0f, 0.0f, scale, -scale * position.z); - glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&sCoefficients); - glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&tCoefficients); - glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&rCoefficients); - glActiveTexture(GL_TEXTURE0); - - glm::vec3 extents(radius, radius, radius); - SpannerCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents)); - guide(visitor); - - if (!_heightfieldBaseBatches.isEmpty()) { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - _heightfieldCursorProgram.bind(); - - foreach (const HeightfieldBaseLayerBatch& batch, _heightfieldBaseBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - HeightfieldPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex); - glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord); - - glBindTexture(GL_TEXTURE_2D, batch.heightTextureID); - - glDrawRangeElements(GL_TRIANGLES, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - glBindTexture(GL_TEXTURE_2D, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - _heightfieldCursorProgram.release(); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - _heightfieldBaseBatches.clear(); - - if (!_voxelBaseBatches.isEmpty()) { - glEnableClientState(GL_VERTEX_ARRAY); - - _voxelCursorProgram.bind(); - - foreach (const MetavoxelBatch& batch, _voxelBaseBatches) { - glPushMatrix(); - glTranslatef(batch.translation.x, batch.translation.y, batch.translation.z); - glm::vec3 axis = glm::axis(batch.rotation); - glRotatef(glm::degrees(glm::angle(batch.rotation)), axis.x, axis.y, axis.z); - glScalef(batch.scale.x, batch.scale.y, batch.scale.z); - - glBindBuffer(GL_ARRAY_BUFFER, batch.vertexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch.indexBufferID); - - VoxelPoint* point = 0; - glVertexPointer(3, GL_FLOAT, sizeof(VoxelPoint), &point->vertex); - - glDrawRangeElements(GL_QUADS, 0, batch.vertexCount - 1, batch.indexCount, GL_UNSIGNED_INT, 0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glPopMatrix(); - } - - _voxelCursorProgram.release(); - - glDisableClientState(GL_VERTEX_ARRAY); - } - _voxelBaseBatches.clear(); - - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_CULL_FACE); - glDepthFunc(GL_LESS); -} - -class MaterialEditApplier : public SignalHandler { -public: - - MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer texture); - - virtual void handle(); - -protected: - - MetavoxelEditMessage _message; - QSharedPointer _texture; -}; - -MaterialEditApplier::MaterialEditApplier(const MetavoxelEditMessage& message, const QSharedPointer texture) : - _message(message), - _texture(texture) { -} - -void MaterialEditApplier::handle() { - static_cast(_message.edit.data())->averageColor = _texture->getAverageColor(); - Application::getInstance()->getMetavoxels()->applyEdit(_message, true); - deleteLater(); -} - -void MetavoxelSystem::applyMaterialEdit(const MetavoxelEditMessage& message, bool reliable) { - const MaterialEdit* edit = static_cast(message.edit.constData()); - MaterialObject* material = static_cast(edit->material.data()); - if (material && material->getDiffuse().isValid()) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "applyMaterialEdit", Q_ARG(const MetavoxelEditMessage&, message), - Q_ARG(bool, reliable)); - return; - } - auto texture = DependencyManager::get()->getTexture( - material->getDiffuse(), SPLAT_TEXTURE); - if (texture->isLoaded()) { - MetavoxelEditMessage newMessage = message; - static_cast(newMessage.edit.data())->averageColor = texture->getAverageColor(); - applyEdit(newMessage, true); - - } else { - MaterialEditApplier* applier = new MaterialEditApplier(message, texture); - connect(texture.data(), &Resource::loaded, applier, &SignalHandler::handle); - } - } else { - applyEdit(message, true); - } -} - -MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { - return new MetavoxelSystemClient(node, _updater); -} - -void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { - DependencyManager::get()->eachNode([&visitor, &render](const SharedNodePointer& node){ - if (node->getType() == NodeType::MetavoxelServer) { - QMutexLocker locker(&node->getMutex()); - MetavoxelSystemClient* client = static_cast(node->getLinkedData()); - if (client) { - MetavoxelData data = client->getAugmentedData(); - data.guide(visitor); - if (render) { - // save the rendered augmented data so that its cached texture references, etc., don't - // get collected when we replace it with more recent versions - client->setRenderedAugmentedData(data); - } - } - } - }); -} - -void MetavoxelSystem::loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations) { - program.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + - "shaders/metavoxel_" + type + "_splat.vert"); - program.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + - "shaders/metavoxel_" + type + "_splat.frag"); - program.link(); - - program.bind(); - program.setUniformValue("heightMap", 0); - program.setUniformValue("textureMap", 1); - program.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT); - locations.heightScale = program.uniformLocation("heightScale"); - locations.textureScale = program.uniformLocation("textureScale"); - locations.splatTextureOffset = program.uniformLocation("splatTextureOffset"); - locations.splatTextureScalesS = program.uniformLocation("splatTextureScalesS"); - locations.splatTextureScalesT = program.uniformLocation("splatTextureScalesT"); - locations.textureValueMinima = program.uniformLocation("textureValueMinima"); - locations.textureValueMaxima = program.uniformLocation("textureValueMaxima"); - locations.materials = program.attributeLocation("materials"); - locations.materialWeights = program.attributeLocation("materialWeights"); - program.release(); -} - -Throttle::Throttle() : - _limit(INT_MAX), - _total(0) { -} - -bool Throttle::shouldThrottle(int bytes) { - // clear expired buckets - qint64 now = QDateTime::currentMSecsSinceEpoch(); - while (!_buckets.isEmpty() && now >= _buckets.first().first) { - _total -= _buckets.takeFirst().second; - } - - // if possible, add the new bucket - if (_total + bytes > _limit) { - return true; - } - const int BUCKET_DURATION = 1000; - _buckets.append(Bucket(now + BUCKET_DURATION, bytes)); - _total += bytes; - return false; -} - -MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : - MetavoxelClient(node, updater) { -} - -void MetavoxelSystemClient::setAugmentedData(const MetavoxelData& data) { - QWriteLocker locker(&_augmentedDataLock); - _augmentedData = data; -} - -MetavoxelData MetavoxelSystemClient::getAugmentedData() { - QReadLocker locker(&_augmentedDataLock); - return _augmentedData; -} - -class ReceiveDelayer : public QObject { -public: - - ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet); - -protected: - - virtual void timerEvent(QTimerEvent* event); - -private: - - SharedNodePointer _node; - QByteArray _packet; -}; - -ReceiveDelayer::ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet) : - _node(node), - _packet(packet) { -} - -void ReceiveDelayer::timerEvent(QTimerEvent* event) { - QMutexLocker locker(&_node->getMutex()); - MetavoxelClient* client = static_cast(_node->getLinkedData()); - if (client) { - QMetaObject::invokeMethod(&client->getSequencer(), "receivedDatagram", Q_ARG(const QByteArray&, _packet)); - } - deleteLater(); -} - -int MetavoxelSystemClient::parseData(const QByteArray& packet) { - // process through sequencer - MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); - if (randFloat() < simulation.dropRate) { - return packet.size(); - } - int count = (randFloat() < simulation.repeatRate) ? 2 : 1; - for (int i = 0; i < count; i++) { - if (simulation.bandwidthLimit > 0) { - _receiveThrottle.setLimit(simulation.bandwidthLimit); - if (_receiveThrottle.shouldThrottle(packet.size())) { - continue; - } - } - int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); - if (delay > 0) { - ReceiveDelayer* delayer = new ReceiveDelayer(_node, packet); - delayer->startTimer(delay); - - } else { - QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); - } - } - return packet.size(); -} - -class AugmentVisitor : public MetavoxelVisitor { -public: - - AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData); - - virtual int visit(MetavoxelInfo& info); - -private: - - const MetavoxelData& _previousData; -}; - -AugmentVisitor::AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData) : - MetavoxelVisitor(QVector() << AttributeRegistry::getInstance()->getRendererAttribute(), - QVector(), lod), - _previousData(previousData) { -} - -int AugmentVisitor::visit(MetavoxelInfo& info) { - if (!info.isLeaf) { - return DEFAULT_ORDER; - } - static_cast(info.inputValues.at(0).getInlineValue< - SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod); - return STOP_RECURSION; -} - -class Augmenter : public QRunnable { -public: - - Augmenter(const SharedNodePointer& node, const MetavoxelData& data, - const MetavoxelData& previousData, const MetavoxelLOD& lod); - - virtual void run(); - -private: - - QWeakPointer _node; - MetavoxelData _data; - MetavoxelData _previousData; - MetavoxelLOD _lod; -}; - -Augmenter::Augmenter(const SharedNodePointer& node, const MetavoxelData& data, - const MetavoxelData& previousData, const MetavoxelLOD& lod) : - _node(node), - _data(data), - _previousData(previousData), - _lod(lod) { -} - -void Augmenter::run() { - SharedNodePointer node = _node; - if (!node) { - return; - } - AugmentVisitor visitor(_lod, _previousData); - _data.guide(visitor); - QMutexLocker locker(&node->getMutex()); - QMetaObject::invokeMethod(node->getLinkedData(), "setAugmentedData", Q_ARG(const MetavoxelData&, _data)); -} - -void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) { - MetavoxelClient::dataChanged(oldData); - QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD)); -} - -class SendDelayer : public QObject { -public: - - SendDelayer(const SharedNodePointer& node, const QByteArray& data); - - virtual void timerEvent(QTimerEvent* event); - -private: - - SharedNodePointer _node; - QByteArray _data; -}; - -SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) : - _node(node), - _data(data.constData(), data.size()) { -} - -void SendDelayer::timerEvent(QTimerEvent* event) { - DependencyManager::get()->writeDatagram(_data, _node); - deleteLater(); -} - -void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { - MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); - if (randFloat() < simulation.dropRate) { - return; - } - int count = (randFloat() < simulation.repeatRate) ? 2 : 1; - for (int i = 0; i < count; i++) { - if (simulation.bandwidthLimit > 0) { - _sendThrottle.setLimit(simulation.bandwidthLimit); - if (_sendThrottle.shouldThrottle(data.size())) { - continue; - } - } - int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); - if (delay > 0) { - SendDelayer* delayer = new SendDelayer(_node, data); - delayer->startTimer(delay); - - } else { - DependencyManager::get()->writeDatagram(data, _node); - } - } -} - -BufferData::~BufferData() { -} - -void VoxelPoint::setNormal(const glm::vec3& normal) { - this->normal[0] = (char)(normal.x * 127.0f); - this->normal[1] = (char)(normal.y * 127.0f); - this->normal[2] = (char)(normal.z * 127.0f); -} - -VoxelBuffer::VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QMultiHash& quadIndices, int size, const QVector& materials) : - _vertices(vertices), - _indices(indices), - _hermite(hermite), - _hermiteEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData)), - _quadIndices(quadIndices), - _size(size), - _vertexCount(vertices.size()), - _indexCount(indices.size()), - _hermiteCount(hermite.size()), - _vertexBufferID(0), - _indexBufferID(0), - _hermiteBufferID(0), - _materials(materials) { -} - -VoxelBuffer::~VoxelBuffer() { - QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteBuffers", Q_ARG(int, _vertexBufferID), - Q_ARG(int, _indexBufferID), Q_ARG(int, _hermiteBufferID)); -} - -bool VoxelBuffer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float boundsDistance, float& distance) const { - float highest = _size - 1.0f; - glm::vec3 position = (origin + direction * boundsDistance) * highest; - glm::vec3 floors = glm::floor(position); - int max = _size - 2; - int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max); - forever { - VoxelCoord key(qRgb(x, y, z)); - for (QMultiHash::const_iterator it = _quadIndices.constFind(key); - it != _quadIndices.constEnd() && it.key() == key; it++) { - const int* indices = _indices.constData() + *it; - if (findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, - _vertices.at(indices[1]).vertex, _vertices.at(indices[2]).vertex, distance) || - findRayTriangleIntersection(origin, direction, _vertices.at(indices[0]).vertex, - _vertices.at(indices[2]).vertex, _vertices.at(indices[3]).vertex, distance)) { - return true; - } - } - float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX; - if (direction.x > 0.0f) { - xDistance = (x + 1.0f - position.x) / direction.x; - } else if (direction.x < 0.0f) { - xDistance = (x - position.x) / direction.x; - } - if (direction.y > 0.0f) { - yDistance = (y + 1.0f - position.y) / direction.y; - } else if (direction.y < 0.0f) { - yDistance = (y - position.y) / direction.y; - } - if (direction.z > 0.0f) { - zDistance = (z + 1.0f - position.z) / direction.z; - } else if (direction.z < 0.0f) { - zDistance = (z - position.z) / direction.z; - } - float minimumDistance = qMin(xDistance, qMin(yDistance, zDistance)); - if (minimumDistance == xDistance) { - if (direction.x > 0.0f) { - if (x++ == max) { - return false; - } - } else if (x-- == 0) { - return false; - } - } - if (minimumDistance == yDistance) { - if (direction.y > 0.0f) { - if (y++ == max) { - return false; - } - } else if (y-- == 0) { - return false; - } - } - if (minimumDistance == zDistance) { - if (direction.z > 0.0f) { - if (z++ == max) { - return false; - } - } else if (z-- == 0) { - return false; - } - } - position += direction * minimumDistance; - } - return false; -} - -void VoxelBuffer::render(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, bool cursor) { - if (_vertexBufferID == 0) { - glGenBuffers(1, &_vertexBufferID); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID); - glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(VoxelPoint), _vertices.constData(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glGenBuffers(1, &_indexBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.constData(), GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - if (!_materials.isEmpty()) { - _networkTextures.resize(_materials.size()); - auto textureCache = DependencyManager::get(); - for (int i = 0; i < _materials.size(); i++) { - const SharedObjectPointer material = _materials.at(i); - if (material) { - _networkTextures[i] = textureCache->getTexture( - static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); - } - } - } - } - - MetavoxelBatch baseBatch; - baseBatch.translation = translation; - baseBatch.rotation = rotation; - baseBatch.scale = scale; - baseBatch.vertexBufferID = _vertexBufferID; - baseBatch.indexBufferID = _indexBufferID; - baseBatch.vertexCount = _vertexCount; - baseBatch.indexCount = _indexCount; - Application::getInstance()->getMetavoxels()->addVoxelBaseBatch(baseBatch); - - if (!(cursor || _materials.isEmpty())) { - VoxelSplatBatch splatBatch; - splatBatch.translation = translation; - splatBatch.rotation = rotation; - splatBatch.scale = scale; - splatBatch.vertexBufferID = _vertexBufferID; - splatBatch.indexBufferID = _indexBufferID; - splatBatch.vertexCount = _vertexCount; - splatBatch.indexCount = _indexCount; - splatBatch.splatTextureOffset = glm::vec3( - glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x, - glm::dot(translation, rotation * glm::vec3(0.0f, 1.0f, 0.0f)) / scale.y, - glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z); - - for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) { - for (int j = 0; j < SPLAT_COUNT; j++) { - int index = i + j; - if (index < _networkTextures.size()) { - const NetworkTexturePointer& texture = _networkTextures.at(index); - if (texture) { - MaterialObject* material = static_cast(_materials.at(index).data()); - splatBatch.splatTextureScalesS[j] = scale.x / material->getScaleS(); - splatBatch.splatTextureScalesT[j] = scale.z / material->getScaleT(); - splatBatch.splatTextureIDs[j] = texture->getID(); - - } else { - splatBatch.splatTextureIDs[j] = 0; - } - } else { - splatBatch.splatTextureIDs[j] = 0; - } - } - splatBatch.materialIndex = i; - Application::getInstance()->getMetavoxels()->addVoxelSplatBatch(splatBatch); - } - } - - if (_hermiteCount > 0) { - if (_hermiteBufferID == 0) { - glGenBuffers(1, &_hermiteBufferID); - glBindBuffer(GL_ARRAY_BUFFER, _hermiteBufferID); - glBufferData(GL_ARRAY_BUFFER, _hermite.size() * sizeof(glm::vec3), _hermite.constData(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - _hermite.clear(); - } - HermiteBatch hermiteBatch; - hermiteBatch.translation = translation; - hermiteBatch.rotation = rotation; - hermiteBatch.scale = scale; - hermiteBatch.vertexBufferID = _hermiteBufferID; - hermiteBatch.vertexCount = _hermiteCount; - Application::getInstance()->getMetavoxels()->addHermiteBatch(hermiteBatch); - } -} - -DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() { -} - -class SpannerSimulateVisitor : public SpannerVisitor { -public: - - SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod); - - virtual bool visit(Spanner* spanner); - -private: - - float _deltaTime; -}; - -SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod), - _deltaTime(deltaTime) { -} - -bool SpannerSimulateVisitor::visit(Spanner* spanner) { - spanner->getRenderer()->simulate(_deltaTime); - return true; -} - -void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime, - MetavoxelInfo& info, const MetavoxelLOD& lod) { - SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod); - data.guide(spannerSimulateVisitor); -} - -void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod) { - SpannerRenderVisitor spannerRenderVisitor(lod); - data.guide(spannerRenderVisitor); -} - -SphereRenderer::SphereRenderer() { -} - -void SphereRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - Sphere* sphere = static_cast(_spanner); - const QColor& color = sphere->getColor(); - - glPushMatrix(); - const glm::vec3& translation = sphere->getTranslation(); - glTranslatef(translation.x, translation.y, translation.z); - glm::quat rotation = sphere->getRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - DependencyManager::get()->renderSolidSphere(sphere->getScale(), 32, 32, - glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())); - - glPopMatrix(); -} - -CuboidRenderer::CuboidRenderer() { -} - -void CuboidRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - Cuboid* cuboid = static_cast(_spanner); - const QColor& color = cuboid->getColor(); - - glPushMatrix(); - const glm::vec3& translation = cuboid->getTranslation(); - glTranslatef(translation.x, translation.y, translation.z); - glm::quat rotation = cuboid->getRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glScalef(1.0f, cuboid->getAspectY(), cuboid->getAspectZ()); - - DependencyManager::get()->renderSolidCube(cuboid->getScale() * 2.0f, - glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF())); - - glPopMatrix(); -} - -StaticModelRenderer::StaticModelRenderer() : - _model(new Model(this)) { -} - -void StaticModelRenderer::init(Spanner* spanner) { - SpannerRenderer::init(spanner); - - _model->init(); - - StaticModel* staticModel = static_cast(spanner); - applyTranslation(staticModel->getTranslation()); - applyRotation(staticModel->getRotation()); - applyScale(staticModel->getScale()); - applyURL(staticModel->getURL()); - - connect(spanner, SIGNAL(translationChanged(const glm::vec3&)), SLOT(applyTranslation(const glm::vec3&))); - connect(spanner, SIGNAL(rotationChanged(const glm::quat&)), SLOT(applyRotation(const glm::quat&))); - connect(spanner, SIGNAL(scaleChanged(float)), SLOT(applyScale(float))); - connect(spanner, SIGNAL(urlChanged(const QUrl&)), SLOT(applyURL(const QUrl&))); -} - -void StaticModelRenderer::simulate(float deltaTime) { - // update the bounds - Box bounds; - if (_model->isActive()) { - const Extents& extents = _model->getGeometry()->getFBXGeometry().meshExtents; - bounds = Box(extents.minimum, extents.maximum); - } - static_cast(_spanner)->setBounds(glm::translate(_model->getTranslation()) * - glm::mat4_cast(_model->getRotation()) * glm::scale(_model->getScale()) * bounds); - _model->simulate(deltaTime); -} - -void StaticModelRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - _model->render(); -} - -bool StaticModelRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - RayIntersectionInfo info; - info._rayStart = origin; - info._rayDirection = direction; - if (!_model->findRayIntersection(info)) { - return false; - } - distance = info._hitDistance; - return true; -} - -void StaticModelRenderer::applyTranslation(const glm::vec3& translation) { - _model->setTranslation(translation); -} - -void StaticModelRenderer::applyRotation(const glm::quat& rotation) { - _model->setRotation(rotation); -} - -void StaticModelRenderer::applyScale(float scale) { - _model->setScale(glm::vec3(scale, scale, scale)); -} - -void StaticModelRenderer::applyURL(const QUrl& url) { - _model->setURL(url); -} - -HeightfieldRenderer::HeightfieldRenderer() { -} - -const int X_MAXIMUM_FLAG = 1; -const int Y_MAXIMUM_FLAG = 2; - -static void renderNode(const HeightfieldNodePointer& node, Heightfield* heightfield, const MetavoxelLOD& lod, - const glm::vec2& minimum, float size, bool contained, bool cursor) { - const glm::quat& rotation = heightfield->getRotation(); - glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(), - heightfield->getScale() * heightfield->getAspectZ() * size); - glm::vec3 translation = heightfield->getTranslation() + rotation * glm::vec3(minimum.x * heightfield->getScale(), - 0.0f, minimum.y * heightfield->getScale() * heightfield->getAspectZ()); - if (!contained) { - Frustum::IntersectionType type = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType( - glm::translate(translation) * glm::mat4_cast(rotation) * Box(glm::vec3(), scale)); - if (type == Frustum::NO_INTERSECTION) { - return; - } - if (type == Frustum::CONTAINS_INTERSECTION) { - contained = true; - } - } - if (!node->isLeaf() && lod.shouldSubdivide(minimum, size)) { - float nextSize = size * 0.5f; - for (int i = 0; i < HeightfieldNode::CHILD_COUNT; i++) { - renderNode(node->getChild(i), heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f, - i & Y_MAXIMUM_FLAG ? nextSize : 0.0f), nextSize, contained, cursor); - } - return; - } - HeightfieldNodeRenderer* renderer = static_cast(node->getRenderer()); - if (!renderer) { - node->setRenderer(renderer = new HeightfieldNodeRenderer()); - } - renderer->render(node, translation, rotation, scale, cursor); -} - -void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - Heightfield* heightfield = static_cast(_spanner); - renderNode(heightfield->getRoot(), heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor); -} - -HeightfieldNodeRenderer::HeightfieldNodeRenderer() : - _heightTextureID(0), - _colorTextureID(0), - _materialTextureID(0) { -} - -HeightfieldNodeRenderer::~HeightfieldNodeRenderer() { - QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", Q_ARG(int, _heightTextureID), - Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID)); -} - -bool HeightfieldNodeRenderer::findRayIntersection(const glm::vec3& translation, const glm::quat& rotation, - const glm::vec3& scale, const glm::vec3& origin, const glm::vec3& direction, - float boundsDistance, float& distance) const { - if (!_voxels) { - return false; - } - glm::quat inverseRotation = glm::inverse(rotation); - float inverseScale = 1.0f / scale.x; - return static_cast(_voxels.data())->findRayIntersection( - inverseRotation * (origin - translation) * inverseScale, inverseRotation * direction * inverseScale, - boundsDistance, distance); -} - -class EdgeCrossing { -public: - glm::vec3 point; - glm::vec3 normal; - QRgb color; - char material; - - void setColorMaterial(const StackArray::Entry& entry) { color = entry.color; material = entry.material; } - - void mix(const EdgeCrossing& first, const EdgeCrossing& second, float t); - - VoxelPoint createPoint(int clampedX, int clampedZ, float step) const; -}; - -void EdgeCrossing::mix(const EdgeCrossing& first, const EdgeCrossing& second, float t) { - point = glm::mix(first.point, second.point, t); - normal = glm::normalize(glm::mix(first.normal, second.normal, t)); - color = qRgb(glm::mix(qRed(first.color), qRed(second.color), t), glm::mix(qGreen(first.color), qGreen(second.color), t), - glm::mix(qBlue(first.color), qBlue(second.color), t)); - material = (t < 0.5f) ? first.material : second.material; -} - -VoxelPoint EdgeCrossing::createPoint(int clampedX, int clampedZ, float step) const { - VoxelPoint voxelPoint = { glm::vec3(clampedX + point.x, point.y, clampedZ + point.z) * step, - { (quint8)qRed(color), (quint8)qGreen(color), (quint8)qBlue(color) }, - { (char)(normal.x * numeric_limits::max()), (char)(normal.y * numeric_limits::max()), - (char)(normal.z * numeric_limits::max()) }, - { (quint8)material, 0, 0, 0 }, - { numeric_limits::max(), 0, 0, 0 } }; - return voxelPoint; -} - -const int MAX_NORMALS_PER_VERTEX = 4; - -class NormalIndex { -public: - int indices[MAX_NORMALS_PER_VERTEX]; - - bool isValid() const; - - int getClosestIndex(const glm::vec3& normal, QVector& vertices) const; -}; - -bool NormalIndex::isValid() const { - for (int i = 0; i < MAX_NORMALS_PER_VERTEX; i++) { - if (indices[i] >= 0) { - return true; - } - } - return false; -} - -int NormalIndex::getClosestIndex(const glm::vec3& normal, QVector& vertices) const { - int firstIndex = indices[0]; - int closestIndex = firstIndex; - const VoxelPoint& firstVertex = vertices.at(firstIndex); - float closest = normal.x * firstVertex.normal[0] + normal.y * firstVertex.normal[1] + normal.z * firstVertex.normal[2]; - for (int i = 1; i < MAX_NORMALS_PER_VERTEX; i++) { - int index = indices[i]; - if (index == firstIndex) { - break; - } - const VoxelPoint& vertex = vertices.at(index); - float product = normal.x * vertex.normal[0] + normal.y * vertex.normal[1] + normal.z * vertex.normal[2]; - if (product > closest) { - closest = product; - closestIndex = index; - } - } - return closestIndex; -} - -static glm::vec3 safeNormalize(const glm::vec3& vector) { - float length = glm::length(vector); - return (length > 0.0f) ? (vector / length) : vector; -} - -class IndexVector : public QVector { -public: - - int position; - - void swap(IndexVector& other) { QVector::swap(other); qSwap(position, other.position); } - - const NormalIndex& get(int y) const; -}; - -const NormalIndex& IndexVector::get(int y) const { - static NormalIndex invalidIndex = { { -1, -1, -1, -1 } }; - int relative = y - position; - return (relative >= 0 && relative < size()) ? at(relative) : invalidIndex; -} - -static inline glm::vec3 getNormal(const QVector& vertices, const NormalIndex& i0, - const NormalIndex& i1, const NormalIndex& i2, const NormalIndex& i3) { - // check both triangles in case one is degenerate - const glm::vec3& v0 = vertices.at(i0.indices[0]).vertex; - glm::vec3 normal = glm::cross(vertices.at(i1.indices[0]).vertex - v0, vertices.at(i2.indices[0]).vertex - v0); - if (glm::length(normal) > EPSILON) { - return normal; - } - return glm::cross(vertices.at(i2.indices[0]).vertex - v0, vertices.at(i3.indices[0]).vertex - v0); -} - -static inline void appendTriangle(const EdgeCrossing& e0, const EdgeCrossing& e1, const EdgeCrossing& e2, - int clampedX, int clampedZ, float step, QVector& vertices, QVector& indices, - QMultiHash& quadIndices) { - int firstIndex = vertices.size(); - vertices.append(e0.createPoint(clampedX, clampedZ, step)); - vertices.append(e1.createPoint(clampedX, clampedZ, step)); - vertices.append(e2.createPoint(clampedX, clampedZ, step)); - indices.append(firstIndex); - indices.append(firstIndex + 1); - indices.append(firstIndex + 2); - indices.append(firstIndex + 2); - - int minimumY = qMin((int)e0.point.y, qMin((int)e1.point.y, (int)e2.point.y)); - int maximumY = qMax((int)e0.point.y, qMax((int)e1.point.y, (int)e2.point.y)); - for (int y = minimumY; y <= maximumY; y++) { - quadIndices.insert(qRgb(clampedX, y, clampedZ), firstIndex); - } -} - -const int CORNER_COUNT = 4; - -static StackArray::Entry getEntry(const StackArray* lineSrc, int stackWidth, int y, float heightfieldHeight, - EdgeCrossing cornerCrossings[CORNER_COUNT], int cornerIndex) { - int offsetX = (cornerIndex & X_MAXIMUM_FLAG) ? 1 : 0; - int offsetZ = (cornerIndex & Y_MAXIMUM_FLAG) ? 1 : 0; - const StackArray& src = lineSrc[offsetZ * stackWidth + offsetX]; - int count = src.getEntryCount(); - if (count > 0) { - int relative = y - src.getPosition(); - if (relative < count && (relative >= 0 || heightfieldHeight == 0.0f)) { - return src.getEntry(y, heightfieldHeight); - } - } - const EdgeCrossing& cornerCrossing = cornerCrossings[cornerIndex]; - if (cornerCrossing.point.y == 0.0f) { - return src.getEntry(y, heightfieldHeight); - } - StackArray::Entry entry; - bool set = false; - if (cornerCrossing.point.y >= y) { - entry.color = cornerCrossing.color; - entry.material = cornerCrossing.material; - set = true; - entry.setHermiteY(cornerCrossing.normal, glm::clamp(cornerCrossing.point.y - y, 0.0f, 1.0f)); - - } else { - entry.material = entry.color = 0; - } - if (!(cornerIndex & X_MAXIMUM_FLAG)) { - const EdgeCrossing& nextCornerCrossingX = cornerCrossings[cornerIndex | X_MAXIMUM_FLAG]; - if (nextCornerCrossingX.point.y != 0.0f && (nextCornerCrossingX.point.y >= y) != set) { - float t = glm::clamp((y - cornerCrossing.point.y) / - (nextCornerCrossingX.point.y - cornerCrossing.point.y), 0.0f, 1.0f); - entry.setHermiteX(glm::normalize(glm::mix(cornerCrossing.normal, nextCornerCrossingX.normal, t)), t); - } - } - if (!(cornerIndex & Y_MAXIMUM_FLAG)) { - const EdgeCrossing& nextCornerCrossingZ = cornerCrossings[cornerIndex | Y_MAXIMUM_FLAG]; - if (nextCornerCrossingZ.point.y != 0.0f && (nextCornerCrossingZ.point.y >= y) != set) { - float t = glm::clamp((y - cornerCrossing.point.y) / - (nextCornerCrossingZ.point.y - cornerCrossing.point.y), 0.0f, 1.0f); - entry.setHermiteZ(glm::normalize(glm::mix(cornerCrossing.normal, nextCornerCrossingZ.normal, t)), t); - } - } - return entry; -} - -void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation, - const glm::quat& rotation, const glm::vec3& scale, bool cursor) { - if (!node->getHeight()) { - return; - } - int width = node->getHeight()->getWidth(); - int height = node->getHeight()->getContents().size() / width; - int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER; - int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER; - int vertexCount = width * height; - int rows = height - 1; - int columns = width - 1; - int indexCount = rows * columns * 3 * 2; - BufferPair& bufferPair = _bufferPairs[IntPair(width, height)]; - if (!bufferPair.first.isCreated()) { - QVector vertices(vertexCount); - HeightfieldPoint* point = vertices.data(); - - float xStep = 1.0f / (innerWidth - 1); - float zStep = 1.0f / (innerHeight - 1); - float z = -zStep; - float sStep = 1.0f / width; - float tStep = 1.0f / height; - float t = tStep / 2.0f; - for (int i = 0; i < height; i++, z += zStep, t += tStep) { - float x = -xStep; - float s = sStep / 2.0f; - const float SKIRT_LENGTH = 0.25f; - float baseY = (i == 0 || i == height - 1) ? -SKIRT_LENGTH : 0.0f; - for (int j = 0; j < width; j++, point++, x += xStep, s += sStep) { - point->vertex = glm::vec3(x, (j == 0 || j == width - 1) ? -SKIRT_LENGTH : baseY, z); - point->textureCoord = glm::vec2(s, t); - } - } - - bufferPair.first.setUsagePattern(QOpenGLBuffer::StaticDraw); - bufferPair.first.create(); - bufferPair.first.bind(); - bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint)); - bufferPair.first.release(); - - QVector indices(indexCount); - int* index = indices.data(); - for (int i = 0; i < rows; i++) { - int lineIndex = i * width; - int nextLineIndex = (i + 1) * width; - for (int j = 0; j < columns; j++) { - *index++ = lineIndex + j; - *index++ = nextLineIndex + j; - *index++ = nextLineIndex + j + 1; - - *index++ = nextLineIndex + j + 1; - *index++ = lineIndex + j + 1; - *index++ = lineIndex + j; - } - } - - bufferPair.second = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); - bufferPair.second.create(); - bufferPair.second.bind(); - bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int)); - bufferPair.second.release(); - } - if (_heightTextureID == 0) { - // we use non-aligned data for the various layers - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glGenTextures(1, &_heightTextureID); - glBindTexture(GL_TEXTURE_2D, _heightTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0, - GL_RED, GL_UNSIGNED_SHORT, node->getHeight()->getContents().constData()); - - glGenTextures(1, &_colorTextureID); - glBindTexture(GL_TEXTURE_2D, _colorTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (node->getColor()) { - const QByteArray& contents = node->getColor()->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, node->getColor()->getWidth(), - contents.size() / (node->getColor()->getWidth() * DataBlock::COLOR_BYTES), - 0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData()); - glGenerateMipmap(GL_TEXTURE_2D); - - } else { - const quint8 WHITE_COLOR[] = { 255, 255, 255 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR); - } - - glGenTextures(1, &_materialTextureID); - glBindTexture(GL_TEXTURE_2D, _materialTextureID); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (node->getMaterial()) { - const QByteArray& contents = node->getMaterial()->getContents(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, node->getMaterial()->getWidth(), - contents.size() / node->getMaterial()->getWidth(), - 0, GL_RED, GL_UNSIGNED_BYTE, contents.constData()); - - const QVector& materials = node->getMaterial()->getMaterials(); - _networkTextures.resize(materials.size()); - auto textureCache = DependencyManager::get(); - for (int i = 0; i < materials.size(); i++) { - const SharedObjectPointer& material = materials.at(i); - if (material) { - _networkTextures[i] = textureCache->getTexture( - static_cast(material.data())->getDiffuse(), SPLAT_TEXTURE); - } - } - } else { - const quint8 ZERO_VALUE = 0; - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, &ZERO_VALUE); - } - glBindTexture(GL_TEXTURE_2D, 0); - - // restore the default alignment; it's what Qt uses for image storage - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } - bool displayHermite = Menu::getInstance()->isOptionChecked(MenuOption::DisplayHermiteData); - if ((!_voxels || (displayHermite && !static_cast(_voxels.data())->isHermiteEnabled())) && node->getStack()) { - // see http://www.frankpetterson.com/publications/dualcontour/dualcontour.pdf for a description of the - // dual contour algorithm for generating meshes from voxel data using Hermite-tagged edges - - QVector vertices; - QVector indices; - QVector hermiteSegments; - QMultiHash quadIndices; - - int stackWidth = node->getStack()->getWidth(); - int stackHeight = node->getStack()->getContents().size() / stackWidth; - int innerStackWidth = stackWidth - HeightfieldData::SHARED_EDGE; - int innerStackHeight = stackHeight - HeightfieldData::SHARED_EDGE; - const StackArray* src = node->getStack()->getContents().constData(); - const quint16* heightSrc = node->getHeight()->getContents().constData() + - (width + 1) * HeightfieldHeight::HEIGHT_BORDER; - QVector stackMaterials = node->getStack()->getMaterials(); - QHash materialMap; - - int colorWidth; - const uchar* colorSrc = NULL; - float colorStepX, colorStepZ; - if (node->getColor()) { - colorWidth = node->getColor()->getWidth(); - int colorHeight = node->getColor()->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - colorSrc = (const uchar*)node->getColor()->getContents().constData(); - colorStepX = (colorWidth - HeightfieldData::SHARED_EDGE) / (float)innerStackWidth; - colorStepZ = (colorHeight - HeightfieldData::SHARED_EDGE) / (float)innerStackHeight; - } - - int materialWidth; - const uchar* materialSrc = NULL; - float materialStepX, materialStepZ; - if (node->getMaterial()) { - materialWidth = node->getMaterial()->getWidth(); - int materialHeight = node->getMaterial()->getContents().size() / materialWidth; - materialSrc = (const uchar*)node->getMaterial()->getContents().constData(); - materialStepX = (materialWidth - HeightfieldData::SHARED_EDGE) / (float)innerStackWidth; - materialStepZ = (materialHeight - HeightfieldData::SHARED_EDGE) / (float)innerStackHeight; - } - - const int EDGES_PER_CUBE = 12; - EdgeCrossing crossings[EDGES_PER_CUBE * 2]; - - // as we scan down the cube generating vertices between grid points, we remember the indices of the last - // (element, line, section--x, y, z) so that we can connect generated vertices as quads - IndexVector indicesX; - IndexVector lastIndicesX; - QVector indicesZ(stackWidth + 1); - QVector lastIndicesZ(stackWidth + 1); - float step = 1.0f / innerStackWidth; - float voxelScale = scale.y / (numeric_limits::max() * scale.x * step); - - for (int z = 0; z <= stackHeight; z++) { - bool middleZ = (z != 0 && z != stackHeight); - const StackArray* lineSrc = src; - const quint16* heightLineSrc = heightSrc; - for (int x = 0; x <= stackWidth; x++) { - bool middleX = (x != 0 && x != stackWidth); - - // find the y extents of this and the neighboring columns - int minimumY = INT_MAX, maximumY = -1; - lineSrc->getExtents(minimumY, maximumY); - if (middleX) { - lineSrc[1].getExtents(minimumY, maximumY); - if (middleZ) { - lineSrc[stackWidth + 1].getExtents(minimumY, maximumY); - } - } - if (middleZ) { - lineSrc[stackWidth].getExtents(minimumY, maximumY); - } - if (maximumY >= minimumY) { - float heightfieldHeight = *heightLineSrc * voxelScale; - float nextHeightfieldHeightX = heightLineSrc[1] * voxelScale; - float nextHeightfieldHeightZ = heightLineSrc[width] * voxelScale; - float nextHeightfieldHeightXZ = heightLineSrc[width + 1] * voxelScale; - const int UPPER_LEFT_CORNER = 1; - const int UPPER_RIGHT_CORNER = 2; - const int LOWER_LEFT_CORNER = 4; - const int LOWER_RIGHT_CORNER = 8; - const int NO_CORNERS = 0; - const int ALL_CORNERS = UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER | LOWER_RIGHT_CORNER; - const int NEXT_CORNERS[] = { 1, 3, 0, 2 }; - int corners = NO_CORNERS; - if (heightfieldHeight != 0.0f) { - corners |= UPPER_LEFT_CORNER; - } - if (nextHeightfieldHeightX != 0.0f && x != stackWidth) { - corners |= UPPER_RIGHT_CORNER; - } - if (nextHeightfieldHeightZ != 0.0f && z != stackHeight) { - corners |= LOWER_LEFT_CORNER; - } - if (nextHeightfieldHeightXZ != 0.0f && x != stackWidth && z != stackHeight) { - corners |= LOWER_RIGHT_CORNER; - } - bool stitchable = x != 0 && z != 0 && !(corners == NO_CORNERS || corners == ALL_CORNERS); - EdgeCrossing cornerCrossings[CORNER_COUNT]; - int clampedX = qMax(x - 1, 0), clampedZ = qMax(z - 1, 0); - int cornerMinimumY = INT_MAX, cornerMaximumY = -1; - if (stitchable) { - for (int i = 0; i < CORNER_COUNT; i++) { - if (!(corners & (1 << i))) { - continue; - } - int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0; - int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0; - const quint16* height = heightLineSrc + offsetZ * width + offsetX; - float heightValue = *height * voxelScale; - int y = (int)heightValue; - cornerMinimumY = qMin(cornerMinimumY, y); - cornerMaximumY = qMax(cornerMaximumY, y); - EdgeCrossing& crossing = cornerCrossings[i]; - crossing.point = glm::vec3(offsetX, heightValue, offsetZ); - int left = height[-1]; - int right = height[1]; - int down = height[-width]; - int up = height[width]; - crossing.normal = glm::normalize(glm::vec3((left == 0 || right == 0) ? 0.0f : left - right, - 2.0f / voxelScale, (up == 0 || down == 0) ? 0.0f : down - up)); - int clampedOffsetX = clampedX + offsetX, clampedOffsetZ = clampedZ + offsetZ; - if (colorSrc) { - const uchar* color = colorSrc + ((int)(clampedOffsetZ * colorStepZ) * colorWidth + - (int)(clampedOffsetX * colorStepX)) * DataBlock::COLOR_BYTES; - crossing.color = qRgb(color[0], color[1], color[2]); - - } else { - crossing.color = qRgb(numeric_limits::max(), numeric_limits::max(), - numeric_limits::max()); - } - int material = 0; - if (materialSrc) { - material = materialSrc[(int)(clampedOffsetZ * materialStepZ) * materialWidth + - (int)(clampedOffsetX * materialStepX)]; - if (material != 0) { - int& mapping = materialMap[material]; - if (mapping == 0) { - mapping = getMaterialIndex(node->getMaterial()->getMaterials().at(material - 1), - stackMaterials); - } - material = mapping; - } - } - crossing.material = material; - } - minimumY = qMin(minimumY, cornerMinimumY); - maximumY = qMax(maximumY, cornerMaximumY); - - if (corners == (LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER)) { - appendTriangle(cornerCrossings[1], cornerCrossings[0], cornerCrossings[2], - clampedX, clampedZ, step, vertices, indices, quadIndices); - - } else if (corners == (UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER)) { - appendTriangle(cornerCrossings[2], cornerCrossings[3], cornerCrossings[1], - clampedX, clampedZ, step, vertices, indices, quadIndices); - } - } - int position = minimumY; - int count = maximumY - minimumY + 1; - NormalIndex lastIndexY = { { -1, -1, -1, -1 } }; - indicesX.position = position; - indicesX.resize(count); - indicesZ[x].position = position; - indicesZ[x].resize(count); - for (int y = position, end = position + count; y < end; y++) { - StackArray::Entry entry = getEntry(lineSrc, stackWidth, y, heightfieldHeight, cornerCrossings, 0); - if (displayHermite && x != 0 && z != 0 && !lineSrc->isEmpty() && y >= lineSrc->getPosition()) { - glm::vec3 normal; - if (entry.hermiteX != 0) { - glm::vec3 start = glm::vec3(clampedX + entry.getHermiteX(normal), y, clampedZ) * step; - hermiteSegments.append(start); - hermiteSegments.append(start + normal * step); - } - if (entry.hermiteY != 0) { - glm::vec3 start = glm::vec3(clampedX, y + entry.getHermiteY(normal), clampedZ) * step; - hermiteSegments.append(start); - hermiteSegments.append(start + normal * step); - } - if (entry.hermiteZ != 0) { - glm::vec3 start = glm::vec3(clampedX, y, clampedZ + entry.getHermiteZ(normal)) * step; - hermiteSegments.append(start); - hermiteSegments.append(start + normal * step); - } - } - // number variables correspond to cube corners, where the x, y, and z components are represented as - // bits in the 0, 1, and 2 position, respectively; hence, alpha0 is the value at the minimum x, y, and - // z corner and alpha7 is the value at the maximum x, y, and z - int alpha0 = lineSrc->getEntryAlpha(y, heightfieldHeight); - int alpha2 = lineSrc->getEntryAlpha(y + 1, heightfieldHeight); - int alpha1 = alpha0, alpha3 = alpha2, alpha4 = alpha0, alpha6 = alpha2; - int alphaTotal = alpha0 + alpha2; - int possibleTotal = 2 * numeric_limits::max(); - - // cubes on the edge are two-dimensional: this ensures that their vertices will be shared between - // neighboring blocks, which share only one layer of points - if (middleZ) { - alphaTotal += (alpha4 = lineSrc[stackWidth].getEntryAlpha(y, nextHeightfieldHeightZ)); - possibleTotal += numeric_limits::max(); - - alphaTotal += (alpha6 = lineSrc[stackWidth].getEntryAlpha(y + 1, nextHeightfieldHeightZ)); - possibleTotal += numeric_limits::max(); - } - int alpha5 = alpha4, alpha7 = alpha6; - if (middleX) { - alphaTotal += (alpha1 = lineSrc[1].getEntryAlpha(y, nextHeightfieldHeightX)); - possibleTotal += numeric_limits::max(); - - alphaTotal += (alpha3 = lineSrc[1].getEntryAlpha(y + 1, nextHeightfieldHeightX)); - possibleTotal += numeric_limits::max(); - - if (middleZ) { - alphaTotal += (alpha5 = lineSrc[stackWidth + 1].getEntryAlpha(y, nextHeightfieldHeightXZ)); - possibleTotal += numeric_limits::max(); - - alphaTotal += (alpha7 = lineSrc[stackWidth + 1].getEntryAlpha(y + 1, nextHeightfieldHeightXZ)); - possibleTotal += numeric_limits::max(); - } - } - if (alphaTotal == 0 || alphaTotal == possibleTotal) { - continue; // no corners set/all corners set - } - // we first look for crossings with the heightfield corner vertices; these take priority - int crossingCount = 0; - if (y >= cornerMinimumY && y <= cornerMaximumY) { - // first look for set corners, which override any interpolated values - int crossedCorners = NO_CORNERS; - for (int i = 0; i < CORNER_COUNT; i++) { - if (!(corners & (1 << i))) { - continue; - } - const EdgeCrossing& cornerCrossing = cornerCrossings[i]; - if (cornerCrossing.point.y >= y && cornerCrossing.point.y < y + 1) { - crossedCorners |= (1 << i); - } - } - switch (crossedCorners) { - case UPPER_LEFT_CORNER: - case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER: - case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER | UPPER_LEFT_CORNER: - case UPPER_LEFT_CORNER | LOWER_RIGHT_CORNER: - crossings[crossingCount++] = cornerCrossings[0]; - crossings[crossingCount - 1].point.y -= y; - break; - - case UPPER_RIGHT_CORNER: - case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER: - case UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER: - case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER: - crossings[crossingCount++] = cornerCrossings[1]; - crossings[crossingCount - 1].point.y -= y; - break; - - case LOWER_LEFT_CORNER: - case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER: - case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER: - crossings[crossingCount++] = cornerCrossings[2]; - crossings[crossingCount - 1].point.y -= y; - break; - - case LOWER_RIGHT_CORNER: - case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER: - case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER: - crossings[crossingCount++] = cornerCrossings[3]; - crossings[crossingCount - 1].point.y -= y; - break; - - case NO_CORNERS: - for (int i = 0; i < CORNER_COUNT; i++) { - if (!(corners & (1 << i))) { - continue; - } - int nextIndex = NEXT_CORNERS[i]; - if (!(corners & (1 << nextIndex))) { - continue; - } - const EdgeCrossing& cornerCrossing = cornerCrossings[i]; - const EdgeCrossing& nextCornerCrossing = cornerCrossings[nextIndex]; - float divisor = (nextCornerCrossing.point.y - cornerCrossing.point.y); - if (divisor == 0.0f) { - continue; - } - float t1 = (y - cornerCrossing.point.y) / divisor; - float t2 = (y + 1 - cornerCrossing.point.y) / divisor; - if (t1 >= 0.0f && t1 <= 1.0f) { - crossings[crossingCount++].mix(cornerCrossing, nextCornerCrossing, t1); - crossings[crossingCount - 1].point.y -= y; - } - if (t2 >= 0.0f && t2 <= 1.0f) { - crossings[crossingCount++].mix(cornerCrossing, nextCornerCrossing, t2); - crossings[crossingCount - 1].point.y -= y; - } - } - break; - } - } - - // the terrifying conditional code that follows checks each cube edge for a crossing, gathering - // its properties (color, material, normal) if one is present; as before, boundary edges are excluded - if (crossingCount == 0) { - StackArray::Entry nextEntryY = getEntry(lineSrc, stackWidth, y + 1, - heightfieldHeight, cornerCrossings, 0); - if (middleX) { - StackArray::Entry nextEntryX = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightX, - cornerCrossings, 1); - StackArray::Entry nextEntryXY = getEntry(lineSrc, stackWidth, y + 1, nextHeightfieldHeightX, - cornerCrossings, 1); - if (alpha0 != alpha1) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(entry.getHermiteX(crossing.normal), 0.0f, 0.0f); - crossing.setColorMaterial(alpha0 == 0 ? nextEntryX : entry); - } - if (alpha1 != alpha3) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(1.0f, nextEntryX.getHermiteY(crossing.normal), 0.0f); - crossing.setColorMaterial(alpha1 == 0 ? nextEntryXY : nextEntryX); - } - if (alpha2 != alpha3) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(nextEntryY.getHermiteX(crossing.normal), 1.0f, 0.0f); - crossing.setColorMaterial(alpha2 == 0 ? nextEntryXY : nextEntryY); - } - if (middleZ) { - StackArray::Entry nextEntryZ = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightZ, - cornerCrossings, 2); - StackArray::Entry nextEntryXZ = getEntry(lineSrc, stackWidth, y, nextHeightfieldHeightXZ, - cornerCrossings, 3); - StackArray::Entry nextEntryXYZ = getEntry(lineSrc, stackWidth, y + 1, - nextHeightfieldHeightXZ, cornerCrossings, 3); - if (alpha1 != alpha5) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(1.0f, 0.0f, nextEntryX.getHermiteZ(crossing.normal)); - crossing.setColorMaterial(alpha1 == 0 ? nextEntryXZ : nextEntryX); - } - if (alpha3 != alpha7) { - EdgeCrossing& crossing = crossings[crossingCount++]; - StackArray::Entry nextEntryXY = getEntry(lineSrc, stackWidth, y + 1, - nextHeightfieldHeightX, cornerCrossings, 1); - crossing.point = glm::vec3(1.0f, 1.0f, nextEntryXY.getHermiteZ(crossing.normal)); - crossing.setColorMaterial(alpha3 == 0 ? nextEntryXYZ : nextEntryXY); - } - if (alpha4 != alpha5) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(nextEntryZ.getHermiteX(crossing.normal), 0.0f, 1.0f); - crossing.setColorMaterial(alpha4 == 0 ? nextEntryXZ : nextEntryZ); - } - if (alpha5 != alpha7) { - EdgeCrossing& crossing = crossings[crossingCount++]; - StackArray::Entry nextEntryXZ = getEntry(lineSrc, stackWidth, y, - nextHeightfieldHeightXZ, cornerCrossings, 3); - crossing.point = glm::vec3(1.0f, nextEntryXZ.getHermiteY(crossing.normal), 1.0f); - crossing.setColorMaterial(alpha5 == 0 ? nextEntryXYZ : nextEntryXZ); - } - if (alpha6 != alpha7) { - EdgeCrossing& crossing = crossings[crossingCount++]; - StackArray::Entry nextEntryYZ = getEntry(lineSrc, stackWidth, y + 1, - nextHeightfieldHeightZ, cornerCrossings, 2); - crossing.point = glm::vec3(nextEntryYZ.getHermiteX(crossing.normal), 1.0f, 1.0f); - crossing.setColorMaterial(alpha6 == 0 ? nextEntryXYZ : nextEntryYZ); - } - } - } - if (alpha0 != alpha2) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(0.0f, entry.getHermiteY(crossing.normal), 0.0f); - crossing.setColorMaterial(alpha0 == 0 ? nextEntryY : entry); - } - if (middleZ) { - StackArray::Entry nextEntryZ = getEntry(lineSrc, stackWidth, y, - nextHeightfieldHeightZ, cornerCrossings, 2); - StackArray::Entry nextEntryYZ = getEntry(lineSrc, stackWidth, y + 1, - nextHeightfieldHeightZ, cornerCrossings, 2); - if (alpha0 != alpha4) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(0.0f, 0.0f, entry.getHermiteZ(crossing.normal)); - crossing.setColorMaterial(alpha0 == 0 ? nextEntryZ : entry); - } - if (alpha2 != alpha6) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(0.0f, 1.0f, nextEntryY.getHermiteZ(crossing.normal)); - crossing.setColorMaterial(alpha2 == 0 ? nextEntryYZ : nextEntryY); - } - if (alpha4 != alpha6) { - EdgeCrossing& crossing = crossings[crossingCount++]; - crossing.point = glm::vec3(0.0f, nextEntryZ.getHermiteY(crossing.normal), 1.0f); - crossing.setColorMaterial(alpha4 == 0 ? nextEntryYZ : nextEntryZ); - } - } - } - // make sure we have valid crossings to include - int validCrossings = 0; - for (int i = 0; i < crossingCount; i++) { - if (qAlpha(crossings[i].color) != 0) { - validCrossings++; - } - } - NormalIndex index = { { -1, -1, -1, -1 } }; - if (validCrossings != 0) { - index.indices[0] = index.indices[1] = index.indices[2] = index.indices[3] = vertices.size(); - glm::vec3 center; - glm::vec3 normals[MAX_NORMALS_PER_VERTEX]; - int normalCount = 0; - const float CREASE_COS_NORMAL = glm::cos(glm::radians(45.0f)); - const int MAX_MATERIALS_PER_VERTEX = 4; - quint8 materials[] = { 0, 0, 0, 0 }; - glm::vec4 materialWeights; - float totalWeight = 0.0f; - int red = 0, green = 0, blue = 0; - for (int i = 0; i < crossingCount; i++) { - const EdgeCrossing& crossing = crossings[i]; - if (qAlpha(crossing.color) == 0) { - continue; - } - center += crossing.point; - - int j = 0; - for (; j < normalCount; j++) { - if (glm::dot(normals[j], crossing.normal) > CREASE_COS_NORMAL) { - normals[j] = safeNormalize(normals[j] + crossing.normal); - break; - } - } - if (j == normalCount) { - normals[normalCount++] = crossing.normal; - } - - red += qRed(crossing.color); - green += qGreen(crossing.color); - blue += qBlue(crossing.color); - - // when assigning a material, search for its presence and, if not found, - // place it in the first empty slot - if (crossing.material != 0) { - for (j = 0; j < MAX_MATERIALS_PER_VERTEX; j++) { - if (materials[j] == crossing.material) { - materialWeights[j] += 1.0f; - totalWeight += 1.0f; - break; - - } else if (materials[j] == 0) { - materials[j] = crossing.material; - materialWeights[j] = 1.0f; - totalWeight += 1.0f; - break; - } - } - } - } - center /= validCrossings; - - // use a sequence of Givens rotations to perform a QR decomposition - // see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf - glm::mat4 r(0.0f); - glm::vec4 bottom; - for (int i = 0; i < crossingCount; i++) { - const EdgeCrossing& crossing = crossings[i]; - if (qAlpha(crossing.color) == 0) { - continue; - } - bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center)); - - for (int j = 0; j < 4; j++) { - float angle = glm::atan(-bottom[j], r[j][j]); - float sina = glm::sin(angle); - float cosa = glm::cos(angle); - - for (int k = 0; k < 4; k++) { - float tmp = bottom[k]; - bottom[k] = sina * r[k][j] + cosa * tmp; - r[k][j] = cosa * r[k][j] - sina * tmp; - } - } - } - - // extract the submatrices, form ata - glm::mat3 a(r); - glm::vec3 b(r[3]); - glm::mat3 atrans = glm::transpose(a); - glm::mat3 ata = atrans * a; - - // find the eigenvalues and eigenvectors of ata - // (see http://en.wikipedia.org/wiki/Jacobi_eigenvalue_algorithm) - glm::mat3 d = ata; - glm::quat combinedRotation; - const int MAX_ITERATIONS = 20; - for (int i = 0; i < MAX_ITERATIONS; i++) { - glm::vec3 offDiagonals = glm::abs(glm::vec3(d[1][0], d[2][0], d[2][1])); - int largestIndex = (offDiagonals[0] > offDiagonals[1]) ? - (offDiagonals[0] > offDiagonals[2] ? 0 : 2) : (offDiagonals[1] > offDiagonals[2] ? 1 : 2); - const float DESIRED_PRECISION = 0.00001f; - if (offDiagonals[largestIndex] < DESIRED_PRECISION) { - break; - } - int largestJ = (largestIndex == 2) ? 1 : 0; - int largestI = (largestIndex == 0) ? 1 : 2; - float sjj = d[largestJ][largestJ]; - float sii = d[largestI][largestI]; - float angle = glm::atan(2.0f * d[largestJ][largestI], sjj - sii) / 2.0f; - glm::quat rotation = glm::angleAxis(angle, largestIndex == 0 ? glm::vec3(0.0f, 0.0f, -1.0f) : - (largestIndex == 1 ? glm::vec3(0.0f, 1.0f, 0.0f) : glm::vec3(-1.0f, 0.0f, 0.0f))); - combinedRotation = glm::normalize(rotation * combinedRotation); - glm::mat3 matrix = glm::mat3_cast(combinedRotation); - d = matrix * ata * glm::transpose(matrix); - } - - // form the singular matrix from the eigenvalues - const float MIN_SINGULAR_THRESHOLD = 0.1f; - d[0][0] = (d[0][0] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[0][0]; - d[1][1] = (d[1][1] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[1][1]; - d[2][2] = (d[2][2] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[2][2]; - - // compute the pseudo-inverse, ataplus, and use to find the minimizing solution - glm::mat3 u = glm::mat3_cast(combinedRotation); - glm::mat3 ataplus = glm::transpose(u) * d * u; - glm::vec3 solution = (ataplus * atrans * b) + center; - - // make sure it doesn't fall beyond the cell boundaries - center = glm::clamp(solution, 0.0f, 1.0f); - - if (totalWeight > 0.0f) { - materialWeights *= (numeric_limits::max() / totalWeight); - } - VoxelPoint point = { (glm::vec3(clampedX, y, clampedZ) + center) * step, - { (quint8)(red / validCrossings), (quint8)(green / validCrossings), - (quint8)(blue / validCrossings) }, - { (char)(normals[0].x * 127.0f), (char)(normals[0].y * 127.0f), - (char)(normals[0].z * 127.0f) }, - { materials[0], materials[1], materials[2], materials[3] }, - { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2], - (quint8)materialWeights[3] } }; - - vertices.append(point); - for (int i = 1; i < normalCount; i++) { - index.indices[i] = vertices.size(); - point.setNormal(normals[i]); - vertices.append(point); - } - } - - // the first x, y, and z are repeated for the boundary edge; past that, we consider generating - // quads for each edge that includes a transition, using indices of previously generated vertices - int reclampedX = qMin(clampedX, stackWidth - 1); - int reclampedZ = qMin(clampedZ, stackHeight - 1); - if (alpha0 != alpha1 && y > position && z > 0) { - const NormalIndex& index1 = lastIndexY; - const NormalIndex& index2 = lastIndicesZ[x].get(y - 1); - const NormalIndex& index3 = lastIndicesZ[x].get(y); - if (index.isValid() && index1.isValid() && index2.isValid() && index3.isValid()) { - quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size()); - quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ), indices.size()); - if (reclampedZ > 0) { - quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ - 1), indices.size()); - quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size()); - } - glm::vec3 normal = getNormal(vertices, index, index1, index2, index3); - if (alpha0 == 0) { // quad faces negative x - indices.append(index3.getClosestIndex(normal = -normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index1.getClosestIndex(normal, vertices)); - } else { // quad faces positive x - indices.append(index1.getClosestIndex(normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index3.getClosestIndex(normal, vertices)); - } - indices.append(index.getClosestIndex(normal, vertices)); - } - } - - if (alpha0 != alpha2 && x > 0 && z > 0) { - const NormalIndex& index1 = lastIndicesZ[x].get(y); - const NormalIndex& index2 = lastIndicesZ[x - 1].get(y); - const NormalIndex& index3 = lastIndicesX.get(y); - if (index.isValid() && index1.isValid() && index2.isValid() && index3.isValid()) { - quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size()); - if (reclampedX > 0) { - quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ), indices.size()); - if (reclampedZ > 0) { - quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ - 1), indices.size()); - } - } - if (reclampedZ > 0) { - quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size()); - } - glm::vec3 normal = getNormal(vertices, index, index3, index2, index1); - if (alpha0 == 0) { // quad faces negative y - indices.append(index3.getClosestIndex(normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index1.getClosestIndex(normal, vertices)); - } else { // quad faces positive y - indices.append(index1.getClosestIndex(normal = -normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index3.getClosestIndex(normal, vertices)); - } - indices.append(index.getClosestIndex(normal, vertices)); - } - } - - if (alpha0 != alpha4 && x > 0 && y > position) { - const NormalIndex& index1 = lastIndexY; - const NormalIndex& index2 = lastIndicesX.get(y - 1); - const NormalIndex& index3 = lastIndicesX.get(y); - if (index.isValid() && index1.isValid() && index2.isValid() && index3.isValid()) { - quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size()); - if (reclampedX > 0) { - quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ), indices.size()); - quadIndices.insert(qRgb(reclampedX - 1, y - 1, reclampedZ), indices.size()); - } - quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ), indices.size()); - - glm::vec3 normal = getNormal(vertices, index, index1, index2, index3); - if (alpha0 == 0) { // quad faces negative z - indices.append(index1.getClosestIndex(normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index3.getClosestIndex(normal, vertices)); - } else { // quad faces positive z - indices.append(index3.getClosestIndex(normal = -normal, vertices)); - indices.append(index2.getClosestIndex(normal, vertices)); - indices.append(index1.getClosestIndex(normal, vertices)); - } - indices.append(index.getClosestIndex(normal, vertices)); - } - } - lastIndexY = index; - indicesX[y - position] = index; - indicesZ[x][y - position] = index; - } - } else { - indicesX.clear(); - indicesZ[x].clear(); - } - if (x != 0) { - lineSrc++; - heightLineSrc++; - } - indicesX.swap(lastIndicesX); - } - if (z != 0) { - src += stackWidth; - heightSrc += width; - } - indicesZ.swap(lastIndicesZ); - lastIndicesX.clear(); - } - _voxels = new VoxelBuffer(vertices, indices, hermiteSegments, quadIndices, stackWidth, stackMaterials); - } - - if (_voxels) { - _voxels->render(translation, rotation, glm::vec3(scale.x, scale.x, scale.x), cursor); - } - - HeightfieldBaseLayerBatch baseBatch; - baseBatch.vertexBufferID = bufferPair.first.bufferId(); - baseBatch.indexBufferID = bufferPair.second.bufferId(); - baseBatch.translation = translation; - baseBatch.rotation = rotation; - baseBatch.scale = scale; - baseBatch.vertexCount = vertexCount; - baseBatch.indexCount = indexCount; - baseBatch.heightTextureID = _heightTextureID; - baseBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, (innerWidth - 1) / -2.0f, (innerHeight - 1) / -2.0f); - baseBatch.colorTextureID = _colorTextureID; - float widthMultiplier = 1.0f / (0.5f - 1.5f / width); - float heightMultiplier = 1.0f / (0.5f - 1.5f / height); - if (node->getColor()) { - int colorWidth = node->getColor()->getWidth(); - int colorHeight = node->getColor()->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - baseBatch.colorScale = glm::vec2((0.5f - 0.5f / colorWidth) * widthMultiplier, - (0.5f - 0.5f / colorHeight) * heightMultiplier); - } - Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch); - - if (!(cursor || _networkTextures.isEmpty())) { - HeightfieldSplatBatch splatBatch; - splatBatch.vertexBufferID = bufferPair.first.bufferId(); - splatBatch.indexBufferID = bufferPair.second.bufferId(); - splatBatch.translation = translation; - splatBatch.rotation = rotation; - splatBatch.scale = scale; - splatBatch.vertexCount = vertexCount; - splatBatch.indexCount = indexCount; - splatBatch.heightTextureID = _heightTextureID; - splatBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, 0.0f, 0.0f); - splatBatch.materialTextureID = _materialTextureID; - if (node->getMaterial()) { - int materialWidth = node->getMaterial()->getWidth(); - int materialHeight = node->getMaterial()->getContents().size() / materialWidth; - splatBatch.textureScale = glm::vec2((0.5f - 0.5f / materialWidth) * widthMultiplier, - (0.5f - 0.5f / materialHeight) * heightMultiplier); - } - splatBatch.splatTextureOffset = glm::vec2( - glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x, - glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z); - - const QVector& materials = node->getMaterial()->getMaterials(); - for (int i = 0; i < materials.size(); i += SPLAT_COUNT) { - for (int j = 0; j < SPLAT_COUNT; j++) { - int index = i + j; - if (index < _networkTextures.size()) { - const NetworkTexturePointer& texture = _networkTextures.at(index); - if (texture) { - MaterialObject* material = static_cast(materials.at(index).data()); - splatBatch.splatTextureScalesS[j] = scale.x / material->getScaleS(); - splatBatch.splatTextureScalesT[j] = scale.z / material->getScaleT(); - splatBatch.splatTextureIDs[j] = texture->getID(); - - } else { - splatBatch.splatTextureIDs[j] = 0; - } - } else { - splatBatch.splatTextureIDs[j] = 0; - } - } - splatBatch.materialIndex = i; - Application::getInstance()->getMetavoxels()->addHeightfieldSplatBatch(splatBatch); - } - } -} - -QHash HeightfieldNodeRenderer::_bufferPairs; - diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h deleted file mode 100644 index 28e5758840..0000000000 --- a/interface/src/MetavoxelSystem.h +++ /dev/null @@ -1,445 +0,0 @@ -// -// MetavoxelSystem.h -// interface/src -// -// Created by Andrzej Kapolka on 12/10/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelSystem_h -#define hifi_MetavoxelSystem_h - -#include -#include -#include -#include - -#include - -#include -#include -#include - -class HeightfieldBaseLayerBatch; -class HeightfieldSplatBatch; -class HermiteBatch; -class MetavoxelBatch; -class Model; -class VoxelSplatBatch; - -/// Renders a metavoxel tree. -class MetavoxelSystem : public MetavoxelClientManager { - Q_OBJECT - -public: - - class NetworkSimulation { - public: - float dropRate; - float repeatRate; - int minimumDelay; - int maximumDelay; - int bandwidthLimit; - - NetworkSimulation(float dropRate = 0.0f, float repeatRate = 0.0f, int minimumDelay = 0, - int maximumDelay = 0, int bandwidthLimit = 0); - }; - - virtual ~MetavoxelSystem(); - - virtual void init(); - - virtual MetavoxelLOD getLOD(); - - const Frustum& getFrustum() const { return _frustum; } - - void setNetworkSimulation(const NetworkSimulation& simulation); - NetworkSimulation getNetworkSimulation(); - - void simulate(float deltaTime); - void render(); - - void renderHeightfieldCursor(const glm::vec3& position, float radius); - - Q_INVOKABLE void paintHeightfieldColor(const glm::vec3& position, float radius, const QColor& color); - - Q_INVOKABLE void paintHeightfieldMaterial(const glm::vec3& position, float radius, const SharedObjectPointer& material); - - Q_INVOKABLE void setHeightfieldColor(const SharedObjectPointer& spanner, const QColor& color, bool paint = false); - - Q_INVOKABLE void setHeightfieldMaterial(const SharedObjectPointer& spanner, - const SharedObjectPointer& material, bool paint = false); - - void addHeightfieldBaseBatch(const HeightfieldBaseLayerBatch& batch) { _heightfieldBaseBatches.append(batch); } - void addHeightfieldSplatBatch(const HeightfieldSplatBatch& batch) { _heightfieldSplatBatches.append(batch); } - - void addVoxelBaseBatch(const MetavoxelBatch& batch) { _voxelBaseBatches.append(batch); } - void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); } - - void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); } - - Q_INVOKABLE void deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const; - Q_INVOKABLE void deleteBuffers(int vertexBufferID, int indexBufferID, int hermiteBufferID) const; - -signals: - - void rendering(); - -protected: - - Q_INVOKABLE void applyMaterialEdit(const MetavoxelEditMessage& message, bool reliable = false); - - virtual MetavoxelClient* createClient(const SharedNodePointer& node); - -private: - - void guideToAugmented(MetavoxelVisitor& visitor, bool render = false); - - MetavoxelLOD _lod; - QReadWriteLock _lodLock; - Frustum _frustum; - - NetworkSimulation _networkSimulation; - QReadWriteLock _networkSimulationLock; - - QVector _heightfieldBaseBatches; - QVector _heightfieldSplatBatches; - QVector _voxelBaseBatches; - QVector _voxelSplatBatches; - QVector _hermiteBatches; - - ProgramObject _baseHeightfieldProgram; - int _baseHeightScaleLocation; - int _baseColorScaleLocation; - - class SplatLocations { - public: - int heightScale; - int textureScale; - int splatTextureOffset; - int splatTextureScalesS; - int splatTextureScalesT; - int textureValueMinima; - int textureValueMaxima; - int materials; - int materialWeights; - }; - - ProgramObject _splatHeightfieldProgram; - SplatLocations _splatHeightfieldLocations; - - int _splatHeightScaleLocation; - int _splatTextureScaleLocation; - int _splatTextureOffsetLocation; - int _splatTextureScalesSLocation; - int _splatTextureScalesTLocation; - int _splatTextureValueMinimaLocation; - int _splatTextureValueMaximaLocation; - - ProgramObject _heightfieldCursorProgram; - - ProgramObject _baseVoxelProgram; - ProgramObject _splatVoxelProgram; - SplatLocations _splatVoxelLocations; - - ProgramObject _voxelCursorProgram; - - static void loadSplatProgram(const char* type, ProgramObject& program, SplatLocations& locations); -}; - -/// Base class for all batches. -class MetavoxelBatch { -public: - GLuint vertexBufferID; - GLuint indexBufferID; - glm::vec3 translation; - glm::quat rotation; - glm::vec3 scale; - int vertexCount; - int indexCount; -}; - -/// Base class for heightfield batches. -class HeightfieldBatch : public MetavoxelBatch { -public: - GLuint heightTextureID; - glm::vec4 heightScale; -}; - -/// A batch containing a heightfield base layer. -class HeightfieldBaseLayerBatch : public HeightfieldBatch { -public: - GLuint colorTextureID; - glm::vec2 colorScale; -}; - -/// A batch containing a heightfield splat. -class HeightfieldSplatBatch : public HeightfieldBatch { -public: - GLuint materialTextureID; - glm::vec2 textureScale; - glm::vec2 splatTextureOffset; - int splatTextureIDs[4]; - glm::vec4 splatTextureScalesS; - glm::vec4 splatTextureScalesT; - int materialIndex; -}; - -/// A batch containing a voxel splat. -class VoxelSplatBatch : public MetavoxelBatch { -public: - glm::vec3 splatTextureOffset; - int splatTextureIDs[4]; - glm::vec4 splatTextureScalesS; - glm::vec4 splatTextureScalesT; - int materialIndex; -}; - -/// A batch containing Hermite data for debugging. -class HermiteBatch { -public: - GLuint vertexBufferID; - glm::vec3 translation; - glm::quat rotation; - glm::vec3 scale; - int vertexCount; -}; - -/// Generic abstract base class for objects that handle a signal. -class SignalHandler : public QObject { - Q_OBJECT - -public slots: - - virtual void handle() = 0; -}; - -/// Simple throttle for limiting bandwidth on a per-second basis. -class Throttle { -public: - - Throttle(); - - /// Sets the per-second limit. - void setLimit(int limit) { _limit = limit; } - - /// Determines whether the message with the given size should be throttled (discarded). If not, registers the message - /// as having been processed (i.e., contributing to later throttling). - bool shouldThrottle(int bytes); - -private: - - int _limit; - int _total; - - typedef QPair Bucket; - QList _buckets; -}; - -/// A client session associated with a single server. -class MetavoxelSystemClient : public MetavoxelClient { - Q_OBJECT - -public: - - MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater); - - Q_INVOKABLE void setAugmentedData(const MetavoxelData& data); - - /// Returns a copy of the augmented data. This function is thread-safe. - MetavoxelData getAugmentedData(); - - void setRenderedAugmentedData(const MetavoxelData& data) { _renderedAugmentedData = data; } - - virtual int parseData(const QByteArray& packet); - -protected: - - virtual void dataChanged(const MetavoxelData& oldData); - virtual void sendDatagram(const QByteArray& data); - -private: - - MetavoxelData _augmentedData; - MetavoxelData _renderedAugmentedData; - QReadWriteLock _augmentedDataLock; - - Throttle _sendThrottle; - Throttle _receiveThrottle; -}; - -/// Base class for cached static buffers. -class BufferData : public QSharedData { -public: - - virtual ~BufferData(); - - virtual void render(const glm::vec3& translation, const glm::quat& rotation, - const glm::vec3& scale, bool cursor = false) = 0; -}; - -typedef QExplicitlySharedDataPointer BufferDataPointer; - -/// Describes contents of a vertex in a voxel buffer. -class VoxelPoint { -public: - glm::vec3 vertex; - quint8 color[3]; - char normal[3]; - quint8 materials[4]; - quint8 materialWeights[4]; - - void setNormal(const glm::vec3& normal); -}; - -/// A container for a coordinate within a voxel block. -class VoxelCoord { -public: - QRgb encoded; - - VoxelCoord(QRgb encoded) : encoded(encoded) { } - - bool operator==(const VoxelCoord& other) const { return encoded == other.encoded; } -}; - -inline uint qHash(const VoxelCoord& coord, uint seed) { - // multiply by prime numbers greater than the possible size - return qHash(qRed(coord.encoded) + 257 * (qGreen(coord.encoded) + 263 * qBlue(coord.encoded)), seed); -} - -/// Contains the information necessary to render a voxel block. -class VoxelBuffer : public BufferData { -public: - - VoxelBuffer(const QVector& vertices, const QVector& indices, const QVector& hermite, - const QMultiHash& quadIndices, int size, const QVector& materials = - QVector()); - virtual ~VoxelBuffer(); - - bool isHermiteEnabled() const { return _hermiteEnabled; } - - /// Finds the first intersection between the described ray and the voxel data. - bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float boundsDistance, float& distance) const; - - virtual void render(const glm::vec3& translation, const glm::quat& rotation, - const glm::vec3& scale, bool cursor = false); - -private: - - QVector _vertices; - QVector _indices; - QVector _hermite; - bool _hermiteEnabled; - QMultiHash _quadIndices; - int _size; - int _vertexCount; - int _indexCount; - int _hermiteCount; - GLuint _vertexBufferID; - GLuint _indexBufferID; - GLuint _hermiteBufferID; - QVector _materials; - QVector _networkTextures; -}; - -/// Renders metavoxels as points. -class DefaultMetavoxelRendererImplementation : public MetavoxelRendererImplementation { - Q_OBJECT - -public: - - Q_INVOKABLE DefaultMetavoxelRendererImplementation(); - - virtual void simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod); - virtual void render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod); -}; - -/// Renders spheres. -class SphereRenderer : public SpannerRenderer { - Q_OBJECT - -public: - - Q_INVOKABLE SphereRenderer(); - - virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); -}; - -/// Renders cuboids. -class CuboidRenderer : public SpannerRenderer { - Q_OBJECT - -public: - - Q_INVOKABLE CuboidRenderer(); - - virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); -}; - -/// Renders static models. -class StaticModelRenderer : public SpannerRenderer { - Q_OBJECT - -public: - - Q_INVOKABLE StaticModelRenderer(); - - virtual void init(Spanner* spanner); - virtual void simulate(float deltaTime); - virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - -private slots: - - void applyTranslation(const glm::vec3& translation); - void applyRotation(const glm::quat& rotation); - void applyScale(float scale); - void applyURL(const QUrl& url); - -private: - - Model* _model; -}; - -/// Renders heightfields. -class HeightfieldRenderer : public SpannerRenderer { - Q_OBJECT - -public: - - Q_INVOKABLE HeightfieldRenderer(); - - virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); -}; - -/// Renders a single quadtree node. -class HeightfieldNodeRenderer : public AbstractHeightfieldNodeRenderer { -public: - - HeightfieldNodeRenderer(); - virtual ~HeightfieldNodeRenderer(); - - virtual bool findRayIntersection(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& origin, const glm::vec3& direction, float boundsDistance, float& distance) const; - - void render(const HeightfieldNodePointer& node, const glm::vec3& translation, - const glm::quat& rotation, const glm::vec3& scale, bool cursor); - -private: - - GLuint _heightTextureID; - GLuint _colorTextureID; - GLuint _materialTextureID; - QVector _networkTextures; - - BufferDataPointer _voxels; - - typedef QPair IntPair; - typedef QPair BufferPair; - static QHash _bufferPairs; -}; - -#endif // hifi_MetavoxelSystem_h diff --git a/interface/src/ui/BandwidthDialog.cpp b/interface/src/ui/BandwidthDialog.cpp index 044774fad6..b3bc934006 100644 --- a/interface/src/ui/BandwidthDialog.cpp +++ b/interface/src/ui/BandwidthDialog.cpp @@ -86,12 +86,10 @@ BandwidthDialog::BandwidthDialog(QWidget* parent) : new BandwidthChannelDisplay({NodeType::EntityServer}, form, "Octree", "Kbps", 1.0, COLOR2); _allChannelDisplays[3] = _octreeChannelDisplay = new BandwidthChannelDisplay({NodeType::DomainServer}, form, "Domain", "Kbps", 1.0, COLOR2); - _allChannelDisplays[4] = _metavoxelsChannelDisplay = - new BandwidthChannelDisplay({NodeType::MetavoxelServer, NodeType::EnvironmentServer}, form, "Metavoxels", "Kbps", 1.0, COLOR2); - _allChannelDisplays[5] = _otherChannelDisplay = + _allChannelDisplays[4] = _otherChannelDisplay = new BandwidthChannelDisplay({NodeType::Unassigned}, form, "Other", "Kbps", 1.0, COLOR2); - _allChannelDisplays[6] = _totalChannelDisplay = - new BandwidthChannelDisplay({NodeType::DomainServer, NodeType::EntityServer, NodeType::MetavoxelServer, + _allChannelDisplays[5] = _totalChannelDisplay = + new BandwidthChannelDisplay({NodeType::DomainServer, NodeType::EntityServer, NodeType::EnvironmentServer, NodeType::AudioMixer, NodeType::Agent, NodeType::AvatarMixer, NodeType::Unassigned}, form, "Total", "Kbps", 1.0, COLOR2); diff --git a/interface/src/ui/BandwidthDialog.h b/interface/src/ui/BandwidthDialog.h index cf4c34b0a9..a504a5964f 100644 --- a/interface/src/ui/BandwidthDialog.h +++ b/interface/src/ui/BandwidthDialog.h @@ -63,11 +63,10 @@ private: BandwidthChannelDisplay* _avatarsChannelDisplay; BandwidthChannelDisplay* _octreeChannelDisplay; BandwidthChannelDisplay* _domainChannelDisplay; - BandwidthChannelDisplay* _metavoxelsChannelDisplay; BandwidthChannelDisplay* _otherChannelDisplay; BandwidthChannelDisplay* _totalChannelDisplay; // sums of all the other channels - static const unsigned int _CHANNELCOUNT = 7; + static const unsigned int _CHANNELCOUNT = 6; BandwidthChannelDisplay* _allChannelDisplays[_CHANNELCOUNT]; diff --git a/interface/src/ui/CachesSizeDialog.cpp b/interface/src/ui/CachesSizeDialog.cpp index d21d1c2db8..a29793349f 100644 --- a/interface/src/ui/CachesSizeDialog.cpp +++ b/interface/src/ui/CachesSizeDialog.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -42,7 +41,6 @@ CachesSizeDialog::CachesSizeDialog(QWidget* parent) : form->addRow("Animations cache size (MB):", _animations = createDoubleSpinBox(this)); form->addRow("Geometries cache size (MB):", _geometries = createDoubleSpinBox(this)); - form->addRow("Scripts cache size (MB):", _scripts = createDoubleSpinBox(this)); form->addRow("Sounds cache size (MB):", _sounds = createDoubleSpinBox(this)); form->addRow("Textures cache size (MB):", _textures = createDoubleSpinBox(this)); @@ -59,7 +57,6 @@ CachesSizeDialog::CachesSizeDialog(QWidget* parent) : void CachesSizeDialog::confirmClicked(bool checked) { DependencyManager::get()->setUnusedResourceCacheSize(_animations->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_geometries->value() * BYTES_PER_MEGABYTES); - DependencyManager::get()->setUnusedResourceCacheSize(_scripts->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_sounds->value() * BYTES_PER_MEGABYTES); DependencyManager::get()->setUnusedResourceCacheSize(_textures->value() * BYTES_PER_MEGABYTES); @@ -69,7 +66,6 @@ void CachesSizeDialog::confirmClicked(bool checked) { void CachesSizeDialog::resetClicked(bool checked) { _animations->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _geometries->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); - _scripts->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _sounds->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); _textures->setValue(DependencyManager::get()->getUnusedResourceCacheSize() / BYTES_PER_MEGABYTES); } diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 752e205a6a..7bbf92462b 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -23,8 +23,6 @@ #include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" -#include "MetavoxelEditor.h" -#include "MetavoxelNetworkSimulator.h" #include "OctreeStatsDialog.h" #include "PreferencesDialog.h" #include "ScriptEditorWindow.h" @@ -148,16 +146,6 @@ void DialogsManager::hmdToolsClosed() { _hmdToolsDialog->hide(); } -void DialogsManager::showMetavoxelEditor() { - maybeCreateDialog(_metavoxelEditor); - _metavoxelEditor->raise(); -} - -void DialogsManager::showMetavoxelNetworkSimulator() { - maybeCreateDialog(_metavoxelNetworkSimulator); - _metavoxelNetworkSimulator->raise(); -} - void DialogsManager::showScriptEditor() { maybeCreateDialog(_scriptEditor); _scriptEditor->raise(); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 465c6829ad..8aafda1da8 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -29,8 +29,6 @@ class ChatWindow; class BandwidthDialog; class LodToolsDialog; class LoginDialog; -class MetavoxelEditor; -class MetavoxelNetworkSimulator; class OctreeStatsDialog; class PreferencesDialog; class ScriptEditorWindow; @@ -59,8 +57,6 @@ public slots: void bandwidthDetails(); void lodTools(); void hmdTools(bool showTools); - void showMetavoxelEditor(); - void showMetavoxelNetworkSimulator(); void showScriptEditor(); void showChat(); @@ -95,8 +91,6 @@ private: QPointer _hmdToolsDialog; QPointer _lodToolsDialog; QPointer _loginDialog; - QPointer _metavoxelEditor; - QPointer _metavoxelNetworkSimulator; QPointer _octreeStatsDialog; QPointer _preferencesDialog; QPointer _scriptEditor; diff --git a/interface/src/ui/MetavoxelEditor.cpp b/interface/src/ui/MetavoxelEditor.cpp deleted file mode 100644 index 34c6ec9a30..0000000000 --- a/interface/src/ui/MetavoxelEditor.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -// -// MetavoxelEditor.cpp -// interface/src/ui -// -// Created by Andrzej Kapolka on 1/21/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -// include this before QOpenGLFramebufferObject, which includes an earlier version of OpenGL -#include "InterfaceConfig.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "Application.h" -#include "MetavoxelEditor.h" - -using namespace std; - -enum GridPlane { - GRID_PLANE_XY, GRID_PLANE_XZ, GRID_PLANE_YZ -}; - -const glm::vec2 INVALID_VECTOR(FLT_MAX, FLT_MAX); - -MetavoxelEditor::MetavoxelEditor(QWidget* parent) : - QWidget(parent, Qt::Tool) { - - setWindowTitle("Metavoxel Editor"); - setAttribute(Qt::WA_DeleteOnClose); - - QVBoxLayout* topLayout = new QVBoxLayout(); - setLayout(topLayout); - - QGroupBox* attributeGroup = new QGroupBox(); - attributeGroup->setTitle("Attributes"); - topLayout->addWidget(attributeGroup); - - QVBoxLayout* attributeLayout = new QVBoxLayout(); - attributeGroup->setLayout(attributeLayout); - - attributeLayout->addWidget(_attributes = new QListWidget()); - connect(_attributes, SIGNAL(itemSelectionChanged()), SLOT(selectedAttributeChanged())); - - QHBoxLayout* attributeButtonLayout = new QHBoxLayout(); - attributeLayout->addLayout(attributeButtonLayout); - - QPushButton* newAttribute = new QPushButton("New..."); - attributeButtonLayout->addWidget(newAttribute, 1); - connect(newAttribute, SIGNAL(clicked()), SLOT(createNewAttribute())); - - attributeButtonLayout->addWidget(_deleteAttribute = new QPushButton("Delete"), 1); - _deleteAttribute->setEnabled(false); - connect(_deleteAttribute, SIGNAL(clicked()), SLOT(deleteSelectedAttribute())); - - attributeButtonLayout->addWidget(_showAll = new QCheckBox("Show All")); - connect(_showAll, SIGNAL(clicked()), SLOT(updateAttributes())); - - QFormLayout* formLayout = new QFormLayout(); - topLayout->addLayout(formLayout); - - formLayout->addRow("Grid Plane:", _gridPlane = new QComboBox()); - _gridPlane->addItem("X/Y"); - _gridPlane->addItem("X/Z"); - _gridPlane->addItem("Y/Z"); - _gridPlane->setCurrentIndex(GRID_PLANE_XZ); - connect(_gridPlane, SIGNAL(currentIndexChanged(int)), SLOT(centerGridPosition())); - - formLayout->addRow("Grid Spacing:", _gridSpacing = new QDoubleSpinBox()); - _gridSpacing->setMinimum(-FLT_MAX); - _gridSpacing->setMaximum(FLT_MAX); - _gridSpacing->setPrefix("2^"); - _gridSpacing->setValue(0.0); - connect(_gridSpacing, SIGNAL(valueChanged(double)), SLOT(alignGridPosition())); - - formLayout->addRow("Grid Position:", _gridPosition = new QDoubleSpinBox()); - _gridPosition->setMinimum(-FLT_MAX); - _gridPosition->setMaximum(FLT_MAX); - alignGridPosition(); - centerGridPosition(); - - formLayout->addRow("Tool:", _toolBox = new QComboBox()); - connect(_toolBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTool())); - - _value = new QGroupBox(); - _value->setTitle("Value"); - topLayout->addWidget(_value); - - QVBoxLayout* valueLayout = new QVBoxLayout(); - _value->setLayout(valueLayout); - - valueLayout->addWidget(_valueArea = new QScrollArea()); - _valueArea->setMinimumHeight(200); - _valueArea->setWidgetResizable(true); - - addTool(new BoxSetTool(this)); - addTool(new GlobalSetTool(this)); - addTool(new InsertSpannerTool(this)); - addTool(new RemoveSpannerTool(this)); - addTool(new ClearSpannersTool(this)); - addTool(new ImportHeightfieldTool(this)); - addTool(new HeightfieldHeightBrushTool(this)); - addTool(new HeightfieldMaterialBrushTool(this)); - addTool(new HeightfieldSculptBrushTool(this)); - addTool(new HeightfieldFillBrushTool(this)); - addTool(new HeightfieldMaterialBoxTool(this)); - addTool(new HeightfieldMaterialSpannerTool(this)); - - updateAttributes(); - - connect(Application::getInstance(), SIGNAL(simulating(float)), SLOT(simulate(float))); - connect(Application::getInstance(), SIGNAL(renderingInWorldInterface()), SLOT(render())); - connect(Application::getInstance()->getMetavoxels(), &MetavoxelSystem::rendering, - this, &MetavoxelEditor::renderPreview); - - Application::getInstance()->getGLWidget()->installEventFilter(this); - - show(); - - if (_gridProgram.isLinked()) { - return; - } - - _gridProgram.addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/grid.vert"); - _gridProgram.addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/grid.frag"); - _gridProgram.link(); -} - -QString MetavoxelEditor::getSelectedAttribute() const { - QList selectedItems = _attributes->selectedItems(); - return selectedItems.isEmpty() ? QString() : selectedItems.first()->text(); -} - -double MetavoxelEditor::getGridSpacing() const { - return pow(2.0, _gridSpacing->value()); -} - -double MetavoxelEditor::getGridPosition() const { - return _gridPosition->value(); -} - -glm::quat MetavoxelEditor::getGridRotation() const { - // for simplicity, we handle the other two planes by rotating them onto X/Y and performing computation there - switch (_gridPlane->currentIndex()) { - case GRID_PLANE_XY: - return glm::quat(); - - case GRID_PLANE_XZ: - return glm::angleAxis(-PI_OVER_TWO, glm::vec3(1.0f, 0.0f, 0.0f)); - - case GRID_PLANE_YZ: - default: - return glm::angleAxis(PI_OVER_TWO, glm::vec3(0.0f, 1.0f, 0.0f)); - } -} - -QVariant MetavoxelEditor::getValue() const { - QWidget* editor = _valueArea->widget(); - return editor ? editor->metaObject()->userProperty().read(editor) : QVariant(); -} - -bool MetavoxelEditor::eventFilter(QObject* watched, QEvent* event) { - // pass along to the active tool - MetavoxelTool* tool = getActiveTool(); - return tool && tool->eventFilter(watched, event); -} - -void MetavoxelEditor::selectedAttributeChanged() { - _toolBox->clear(); - - QString selected = getSelectedAttribute(); - if (selected.isNull()) { - _deleteAttribute->setEnabled(false); - _toolBox->setEnabled(false); - _value->setVisible(false); - return; - } - _deleteAttribute->setEnabled(true); - _toolBox->setEnabled(true); - - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(selected); - foreach (MetavoxelTool* tool, _tools) { - if (tool->appliesTo(attribute) && (tool->isUserFacing() || _showAll->isChecked())) { - _toolBox->addItem(tool->objectName(), QVariant::fromValue(tool)); - } - } - _value->setVisible(true); - - if (_valueArea->widget()) { - delete _valueArea->widget(); - } - QWidget* editor = attribute->createEditor(); - if (editor) { - editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); - _valueArea->setWidget(editor); - } - updateTool(); -} - -void MetavoxelEditor::createNewAttribute() { - QDialog dialog(this); - dialog.setWindowTitle("New Attribute"); - - QVBoxLayout layout; - dialog.setLayout(&layout); - - QFormLayout form; - layout.addLayout(&form); - - QLineEdit name; - form.addRow("Name:", &name); - - SharedObjectEditor editor(&Attribute::staticMetaObject, false); - editor.setObject(new FloatAttribute()); - layout.addWidget(&editor); - - QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - dialog.connect(&buttons, SIGNAL(accepted()), SLOT(accept())); - dialog.connect(&buttons, SIGNAL(rejected()), SLOT(reject())); - - layout.addWidget(&buttons); - - if (!dialog.exec()) { - return; - } - QString nameText = name.text().trimmed(); - SharedObjectPointer attribute = editor.getObject(); - attribute->setObjectName(nameText); - AttributeRegistry::getInstance()->registerAttribute(attribute.staticCast()); - - updateAttributes(nameText); -} - -void MetavoxelEditor::deleteSelectedAttribute() { - AttributeRegistry::getInstance()->deregisterAttribute(getSelectedAttribute()); - _attributes->selectionModel()->clear(); - updateAttributes(); -} - -void MetavoxelEditor::centerGridPosition() { - const float CENTER_OFFSET = 0.625f; - float eyePosition = (glm::inverse(getGridRotation()) * Application::getInstance()->getCamera()->getPosition()).z - - DependencyManager::get()->getMyAvatar()->getScale() * CENTER_OFFSET; - double step = getGridSpacing(); - _gridPosition->setValue(step * floor(eyePosition / step)); -} - -void MetavoxelEditor::alignGridPosition() { - // make sure our grid position matches our grid spacing - double step = getGridSpacing(); - _gridPosition->setSingleStep(step); - _gridPosition->setValue(step * floor(_gridPosition->value() / step)); -} - -void MetavoxelEditor::updateAttributes(const QString& select) { - // remember the selection in order to preserve it - QString selected = select.isNull() ? getSelectedAttribute() : select; - _attributes->clear(); - - // sort the names for consistent ordering - QList names; - if (_showAll->isChecked()) { - names = AttributeRegistry::getInstance()->getAttributes().keys(); - - } else { - foreach (const AttributePointer& attribute, AttributeRegistry::getInstance()->getAttributes()) { - if (attribute->isUserFacing()) { - names.append(attribute->getName()); - } - } - } - qSort(names); - - foreach (const QString& name, names) { - QListWidgetItem* item = new QListWidgetItem(name); - _attributes->addItem(item); - if (name == selected || selected.isNull()) { - item->setSelected(true); - selected = name; - } - } -} - -void MetavoxelEditor::updateTool() { - MetavoxelTool* active = getActiveTool(); - foreach (MetavoxelTool* tool, _tools) { - tool->setVisible(tool == active); - } - _value->setVisible(active && active->getUsesValue()); -} - -void MetavoxelEditor::simulate(float deltaTime) { - MetavoxelTool* tool = getActiveTool(); - if (tool) { - tool->simulate(deltaTime); - } -} - -const float GRID_BRIGHTNESS = 0.5f; - -void MetavoxelEditor::render() { - glDisable(GL_LIGHTING); - - MetavoxelTool* tool = getActiveTool(); - if (tool) { - tool->render(); - if (!tool->getUsesGrid()) { - return; - } - } - - glDepthMask(GL_FALSE); - - glPushMatrix(); - - glm::quat rotation = getGridRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - glLineWidth(1.0f); - - // center the grid around the camera position on the plane - glm::vec3 rotated = glm::inverse(rotation) * Application::getInstance()->getCamera()->getPosition(); - float spacing = getGridSpacing(); - const int GRID_DIVISIONS = 300; - glTranslatef(spacing * (floorf(rotated.x / spacing) - GRID_DIVISIONS / 2), - spacing * (floorf(rotated.y / spacing) - GRID_DIVISIONS / 2), _gridPosition->value()); - - float scale = GRID_DIVISIONS * spacing; - glScalef(scale, scale, scale); - - _gridProgram.bind(); - - DependencyManager::get()->renderGrid(GRID_DIVISIONS, GRID_DIVISIONS, glm::vec4(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, 1.0f)); - - _gridProgram.release(); - - glPopMatrix(); - - glEnable(GL_LIGHTING); - glDepthMask(GL_TRUE); -} - -void MetavoxelEditor::renderPreview() { - MetavoxelTool* tool = getActiveTool(); - if (tool) { - tool->renderPreview(); - } -} - -void MetavoxelEditor::addTool(MetavoxelTool* tool) { - _tools.append(tool); - layout()->addWidget(tool); -} - -MetavoxelTool* MetavoxelEditor::getActiveTool() const { - int index = _toolBox->currentIndex(); - return (index == -1) ? NULL : static_cast(_toolBox->itemData(index).value()); -} - -ProgramObject MetavoxelEditor::_gridProgram; - -MetavoxelTool::MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing, bool usesGrid) : - _editor(editor), - _usesValue(usesValue), - _userFacing(userFacing), - _usesGrid(usesGrid) { - - QVBoxLayout* layout = new QVBoxLayout(); - setLayout(layout); - - setObjectName(name); - setVisible(false); -} - -bool MetavoxelTool::appliesTo(const AttributePointer& attribute) const { - // shared object sets are a special case - return !attribute->inherits("SharedObjectSetAttribute"); -} - -void MetavoxelTool::simulate(float deltaTime) { - // nothing by default -} - -void MetavoxelTool::render() { - // nothing by default -} - -void MetavoxelTool::renderPreview() { - // nothing by default -} - -BoxTool::BoxTool(MetavoxelEditor* editor, const QString& name, bool usesValue, bool userFacing) : - MetavoxelTool(editor, name, usesValue, userFacing) { - - resetState(); -} - -void BoxTool::render() { - if (Application::getInstance()->isMouseHidden()) { - resetState(); - return; - } - QString selected = _editor->getSelectedAttribute(); - if (selected.isNull()) { - resetState(); - return; - } - glDepthMask(GL_FALSE); - - glPushMatrix(); - - glm::quat rotation = _editor->getGridRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - glm::quat inverseRotation = glm::inverse(rotation); - glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin(); - glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection(); - float spacing = shouldSnapToGrid() ? _editor->getGridSpacing() : 0.0f; - float position = _editor->getGridPosition(); - if (_state == RAISING_STATE) { - // find the plane at the mouse position, orthogonal to the plane, facing the eye position - glLineWidth(4.0f); - glm::vec3 eyePosition = inverseRotation * Application::getInstance()->getViewFrustum()->getOffsetPosition(); - glm::vec3 mousePoint = glm::vec3(_mousePosition, position); - glm::vec3 right = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), eyePosition - mousePoint); - glm::vec3 normal = glm::cross(right, glm::vec3(0.0f, 0.0f, 1.0f)); - float divisor = glm::dot(normal, rayDirection); - if (fabs(divisor) > EPSILON) { - float distance = (glm::dot(normal, mousePoint) - glm::dot(normal, rayOrigin)) / divisor; - float projection = rayOrigin.z + distance * rayDirection.z; - _height = (spacing == 0.0f ? projection : spacing * roundf(projection / spacing)) - position; - } - } else if (fabs(rayDirection.z) > EPSILON) { - // find the intersection of the rotated mouse ray with the plane - float distance = (position - rayOrigin.z) / rayDirection.z; - _mousePosition = glm::vec2(rayOrigin + rayDirection * distance); - glm::vec2 snappedPosition = (spacing == 0.0f) ? _mousePosition : spacing * glm::floor(_mousePosition / spacing); - - if (_state == HOVERING_STATE) { - _startPosition = _endPosition = snappedPosition; - glLineWidth(2.0f); - - } else if (_state == DRAGGING_STATE) { - _endPosition = snappedPosition; - glLineWidth(4.0f); - } - } else { - // cancel any operation in progress - resetState(); - } - - if (_startPosition != INVALID_VECTOR) { - glm::vec2 minimum = glm::min(_startPosition, _endPosition); - glm::vec2 maximum = glm::max(_startPosition, _endPosition); - - glPushMatrix(); - glTranslatef(minimum.x, minimum.y, position); - glScalef(maximum.x + spacing - minimum.x, maximum.y + spacing - minimum.y, _height); - - glTranslatef(0.5f, 0.5f, 0.5f); - if (_state != HOVERING_STATE) { - const float BOX_ALPHA = 0.25f; - QColor color = getColor(); - glm::vec4 cubeColor; - if (color.isValid()) { - cubeColor = glm::vec4(color.redF(), color.greenF(), color.blueF(), BOX_ALPHA); - } else { - cubeColor = glm::vec4(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, BOX_ALPHA); - } - glEnable(GL_CULL_FACE); - DependencyManager::get()->renderSolidCube(1.0f, cubeColor); - glDisable(GL_CULL_FACE); - } - DependencyManager::get()->renderWireCube(1.0f, glm::vec4(GRID_BRIGHTNESS, GRID_BRIGHTNESS, GRID_BRIGHTNESS, 1.0f)); - glPopMatrix(); - } - - glPopMatrix(); -} - -bool BoxTool::eventFilter(QObject* watched, QEvent* event) { - switch (_state) { - case HOVERING_STATE: - if (event->type() == QEvent::MouseButtonPress && _startPosition != INVALID_VECTOR) { - _state = DRAGGING_STATE; - return true; - } - break; - - case DRAGGING_STATE: - if (event->type() == QEvent::MouseButtonRelease) { - _state = RAISING_STATE; - return true; - } - break; - - case RAISING_STATE: - if (event->type() == QEvent::MouseButtonPress) { - if (_height != 0) { - // find the start and end corners in X/Y - float base = _editor->getGridPosition(); - float top = base + _height; - glm::quat rotation = _editor->getGridRotation(); - glm::vec3 start = rotation * glm::vec3(glm::min(_startPosition, _endPosition), glm::min(base, top)); - float spacing = shouldSnapToGrid() ? _editor->getGridSpacing() : 0.0f; - glm::vec3 end = rotation * glm::vec3(glm::max(_startPosition, _endPosition) + - glm::vec2(spacing, spacing), glm::max(base, top)); - - // find the minimum and maximum extents after rotation - applyValue(glm::min(start, end), glm::max(start, end)); - } - resetState(); - return true; - } - break; - } - return false; -} - -bool BoxTool::shouldSnapToGrid() { - return true; -} - -void BoxTool::resetState() { - _state = HOVERING_STATE; - _startPosition = INVALID_VECTOR; - _height = 0.0f; -} - -BoxSetTool::BoxSetTool(MetavoxelEditor* editor) : - BoxTool(editor, "Set Value (Box)", true, false) { -} - -QColor BoxSetTool::getColor() { - return _editor->getValue().value(); -} - -void BoxSetTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (!attribute) { - return; - } - OwnedAttributeValue value(attribute, attribute->createFromVariant(_editor->getValue())); - MetavoxelEditMessage message = { QVariant::fromValue(BoxSetEdit(Box(minimum, maximum), - _editor->getGridSpacing(), value)) }; - Application::getInstance()->getMetavoxels()->applyEdit(message); -} - -GlobalSetTool::GlobalSetTool(MetavoxelEditor* editor) : - MetavoxelTool(editor, "Set Value (Global)", true, false) { - - QPushButton* button = new QPushButton("Apply"); - layout()->addWidget(button); - connect(button, SIGNAL(clicked()), SLOT(apply())); -} - -void GlobalSetTool::apply() { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (!attribute) { - return; - } - OwnedAttributeValue value(attribute, attribute->createFromVariant(_editor->getValue())); - MetavoxelEditMessage message = { QVariant::fromValue(GlobalSetEdit(value)) }; - Application::getInstance()->getMetavoxels()->applyEdit(message); -} - -PlaceSpannerTool::PlaceSpannerTool(MetavoxelEditor* editor, const QString& name, const QString& placeText, bool usesValue) : - MetavoxelTool(editor, name, usesValue) { - - QWidget* widget = new QWidget(this); - layout()->addWidget(widget); - QHBoxLayout* box = new QHBoxLayout(); - widget->setLayout(box); - box->setContentsMargins(QMargins()); - box->addStretch(1); - box->addWidget(_followMouse = new QCheckBox("Follow Mouse")); - _followMouse->setChecked(true); - box->addStretch(1); - - if (!placeText.isEmpty()) { - QPushButton* button = new QPushButton(placeText); - layout()->addWidget(button); - connect(button, SIGNAL(clicked()), SLOT(place())); - } -} - -void PlaceSpannerTool::simulate(float deltaTime) { - Spanner* spanner = static_cast(getSpanner().data()); - Transformable* transformable = qobject_cast(spanner); - if (transformable && _followMouse->isChecked() && !Application::getInstance()->isMouseHidden()) { - // find the intersection of the mouse ray with the grid and place the transformable there - glm::quat rotation = _editor->getGridRotation(); - glm::quat inverseRotation = glm::inverse(rotation); - glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin(); - glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection(); - float position = _editor->getGridPosition(); - float distance = (position - rayOrigin.z) / rayDirection.z; - - transformable->setTranslation(rotation * glm::vec3(glm::vec2(rayOrigin + rayDirection * distance), position)); - } - spanner->getRenderer()->simulate(deltaTime); -} - -void PlaceSpannerTool::renderPreview() { - Spanner* spanner = static_cast(getSpanner().data()); - spanner->getRenderer()->render(Application::getInstance()->getMetavoxels()->getLOD()); -} - -bool PlaceSpannerTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -bool PlaceSpannerTool::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::MouseButtonPress) { - place(); - return true; - } - return false; -} - -SharedObjectPointer PlaceSpannerTool::getSpanner() { - return _editor->getValue().value(); -} - -QColor PlaceSpannerTool::getColor() { - return Qt::white; -} - -void PlaceSpannerTool::place() { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (attribute) { - applyEdit(attribute, getSpanner()->clone()); - } -} - -InsertSpannerTool::InsertSpannerTool(MetavoxelEditor* editor) : - PlaceSpannerTool(editor, "Insert Spanner", "Insert") { -} - -void InsertSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { - MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, spanner)) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); -} - -RemoveSpannerTool::RemoveSpannerTool(MetavoxelEditor* editor) : - MetavoxelTool(editor, "Remove Spanner", false, true, false) { -} - -bool RemoveSpannerTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -bool RemoveSpannerTool::eventFilter(QObject* watched, QEvent* event) { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (!attribute) { - return false; - } - if (event->type() == QEvent::MouseButtonPress) { - float distance; - SharedObjectPointer spanner = Application::getInstance()->getMetavoxels()->findFirstRaySpannerIntersection( - Application::getInstance()->getMouseRayOrigin(), Application::getInstance()->getMouseRayDirection(), - attribute, distance); - if (spanner) { - MetavoxelEditMessage message = { QVariant::fromValue(RemoveSpannerEdit(attribute, spanner->getRemoteID())) }; - Application::getInstance()->getMetavoxels()->applyEdit(message); - } - return true; - } - return false; -} - -ClearSpannersTool::ClearSpannersTool(MetavoxelEditor* editor) : - MetavoxelTool(editor, "Clear Spanners", false, true, false) { - - QPushButton* button = new QPushButton("Clear"); - layout()->addWidget(button); - connect(button, SIGNAL(clicked()), SLOT(clear())); -} - -bool ClearSpannersTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -void ClearSpannersTool::clear() { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (!attribute) { - return; - } - MetavoxelEditMessage message = { QVariant::fromValue(ClearSpannersEdit(attribute)) }; - Application::getInstance()->getMetavoxels()->applyEdit(message); -} - -HeightfieldTool::HeightfieldTool(MetavoxelEditor* editor, const QString& name) : - MetavoxelTool(editor, name, false, true, false) { - - QWidget* widget = new QWidget(); - widget->setLayout(_form = new QFormLayout()); - layout()->addWidget(widget); - - _form->addRow("Translation:", _translation = new Vec3Editor(widget)); - _form->addRow("Spacing:", _spacing = new QDoubleSpinBox()); - _spacing->setMaximum(FLT_MAX); - _spacing->setDecimals(3); - _spacing->setSingleStep(0.001); - _spacing->setValue(1.0); - - QPushButton* applyButton = new QPushButton("Apply"); - layout()->addWidget(applyButton); - connect(applyButton, &QAbstractButton::clicked, this, &HeightfieldTool::apply); -} - -bool HeightfieldTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -ImportHeightfieldTool::ImportHeightfieldTool(MetavoxelEditor* editor) : - HeightfieldTool(editor, "Import Heightfield"), - _spanner(new Heightfield()) { - - _form->addRow("Height Scale:", _heightScale = new QDoubleSpinBox()); - _heightScale->setMaximum(FLT_MAX); - _heightScale->setSingleStep(0.01); - _heightScale->setValue(16.0); - connect(_heightScale, static_cast(&QDoubleSpinBox::valueChanged), this, - &ImportHeightfieldTool::updateSpanner); - - _form->addRow("Height Offset:", _heightOffset = new QDoubleSpinBox()); - _heightOffset->setMinimum(-FLT_MAX); - _heightOffset->setMaximum(FLT_MAX); - _heightOffset->setSingleStep(0.01); - connect(_heightOffset, static_cast(&QDoubleSpinBox::valueChanged), this, - &ImportHeightfieldTool::updateSpanner); - - _form->addRow("Height:", _height = new HeightfieldHeightEditor(this)); - connect(_height, &HeightfieldHeightEditor::heightChanged, this, &ImportHeightfieldTool::updateSpanner); - - _form->addRow("Color:", _color = new HeightfieldColorEditor(this)); - connect(_color, &HeightfieldColorEditor::colorChanged, this, &ImportHeightfieldTool::updateSpanner); - - connect(_translation, &Vec3Editor::valueChanged, this, &ImportHeightfieldTool::updateSpanner); - connect(_spacing, static_cast(&QDoubleSpinBox::valueChanged), this, - &ImportHeightfieldTool::updateSpanner); -} - -void ImportHeightfieldTool::simulate(float deltaTime) { - static_cast(_spanner.data())->getRenderer()->simulate(deltaTime); -} - -void ImportHeightfieldTool::renderPreview() { - static_cast(_spanner.data())->getRenderer()->render(Application::getInstance()->getMetavoxels()->getLOD()); -} - -void ImportHeightfieldTool::apply() { - AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute()); - if (!(_height->getHeight() && attribute)) { - return; - } - MetavoxelEditMessage message = { QVariant::fromValue(InsertSpannerEdit(attribute, _spanner->clone())) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); -} - -void ImportHeightfieldTool::updateSpanner() { - Heightfield* heightfield = static_cast(_spanner.data()); - heightfield->setHeight(_height->getHeight()); - heightfield->setColor(_color->getColor()); - - float scale = 1.0f; - float aspectZ = 1.0f; - if (_height->getHeight()) { - int width = _height->getHeight()->getWidth(); - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = _height->getHeight()->getContents().size() / width - HeightfieldHeight::HEIGHT_EXTENSION; - scale = innerWidth * _spacing->value(); - aspectZ = (float)innerHeight / innerWidth; - } - heightfield->setScale(scale); - heightfield->setAspectY(_heightScale->value() / scale); - heightfield->setAspectZ(aspectZ); - heightfield->setTranslation(_translation->getValue() + glm::vec3(0.0f, _heightOffset->value(), 0.0f)); -} - -HeightfieldBrushTool::HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name) : - MetavoxelTool(editor, name, false, true, false), - _positionValid(false) { - - QWidget* widget = new QWidget(); - widget->setLayout(_form = new QFormLayout()); - layout()->addWidget(widget); - - _form->addRow("Radius:", _radius = new QDoubleSpinBox()); - _radius->setSingleStep(0.01); - _radius->setMaximum(FLT_MAX); - _radius->setValue(5.0); - - _form->addRow("Granularity:", _granularity = new QDoubleSpinBox()); - _granularity->setMinimum(-FLT_MAX); - _granularity->setMaximum(FLT_MAX); - _granularity->setPrefix("2^"); - _granularity->setValue(8.0); -} - -bool HeightfieldBrushTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -void HeightfieldBrushTool::render() { - if (Application::getInstance()->isMouseHidden()) { - return; - } - - // find the intersection with the heightfield - glm::vec3 origin = Application::getInstance()->getMouseRayOrigin(); - glm::vec3 direction = Application::getInstance()->getMouseRayDirection(); - - float distance; - if (!Application::getInstance()->getMetavoxels()->findFirstRayHeightfieldIntersection(origin, direction, distance)) { - _positionValid = false; - return; - } - _positionValid = true; - Application::getInstance()->getMetavoxels()->renderHeightfieldCursor( - _position = origin + distance * direction, _radius->value()); -} - -bool HeightfieldBrushTool::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::Wheel) { - float angle = static_cast(event)->angleDelta().y(); - const float ANGLE_SCALE = 1.0f / 1000.0f; - _radius->setValue(_radius->value() * pow(2.0f, angle * ANGLE_SCALE)); - return true; - - } else if (event->type() == QEvent::MouseButtonPress && _positionValid) { - MetavoxelEditMessage message = { createEdit(static_cast(event)->button() == Qt::RightButton) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); - return true; - } - return false; -} - -HeightfieldHeightBrushTool::HeightfieldHeightBrushTool(MetavoxelEditor* editor) : - HeightfieldBrushTool(editor, "Height Brush") { - - _form->addRow("Height:", _height = new QDoubleSpinBox()); - _height->setMinimum(-FLT_MAX); - _height->setMaximum(FLT_MAX); - _height->setValue(1.0); - - _form->addRow("Mode:", _mode = new QComboBox()); - _mode->addItem("Raise/Lower"); - _mode->addItem("Set"); - _mode->addItem("Erase"); -} - -QVariant HeightfieldHeightBrushTool::createEdit(bool alternate) { - const int SET_MODE_INDEX = 1; - const int ERASE_MODE_INDEX = 2; - return QVariant::fromValue(PaintHeightfieldHeightEdit(_position, _radius->value(), - alternate ? -_height->value() : _height->value(), _mode->currentIndex() == SET_MODE_INDEX, - _mode->currentIndex() == ERASE_MODE_INDEX, pow(2.0f, _granularity->value()))); -} - -MaterialControl::MaterialControl(QWidget* widget, QFormLayout* form, bool clearable) : - QObject(widget) { - - QHBoxLayout* colorLayout = new QHBoxLayout(); - form->addRow(colorLayout); - colorLayout->addWidget(new QLabel("Color:")); - colorLayout->addWidget(_color = new QColorEditor(widget), 1); - connect(_color, &QColorEditor::colorChanged, this, &MaterialControl::clearTexture); - if (clearable) { - QPushButton* eraseButton = new QPushButton("Erase"); - colorLayout->addWidget(eraseButton); - connect(eraseButton, &QPushButton::clicked, this, &MaterialControl::clearColor); - } - - form->addRow(_materialEditor = new SharedObjectEditor(&MaterialObject::staticMetaObject, false)); - connect(_materialEditor, &SharedObjectEditor::objectChanged, this, &MaterialControl::updateTexture); -} - -SharedObjectPointer MaterialControl::getMaterial() { - SharedObjectPointer material = _materialEditor->getObject(); - if (static_cast(material.data())->getDiffuse().isValid()) { - material = material->clone(); - - } else { - material = SharedObjectPointer(); - } - return material; -} - -void MaterialControl::clearColor() { - _color->setColor(QColor(0, 0, 0, 0)); - clearTexture(); -} - -void MaterialControl::clearTexture() { - _materialEditor->setObject(new MaterialObject()); -} - -void MaterialControl::updateTexture() { - if (_texture) { - _texture->disconnect(this); - } - MaterialObject* material = static_cast(_materialEditor->getObject().data()); - if (!material->getDiffuse().isValid()) { - _texture.clear(); - return; - } - _texture = DependencyManager::get()->getTexture(material->getDiffuse(), SPLAT_TEXTURE); - if (_texture) { - if (_texture->isLoaded()) { - textureLoaded(); - } else { - connect(_texture.data(), &Resource::loaded, this, &MaterialControl::textureLoaded); - } - } -} - -void MaterialControl::textureLoaded() { - _color->setColor(_texture->getAverageColor()); -} - -HeightfieldMaterialBrushTool::HeightfieldMaterialBrushTool(MetavoxelEditor* editor) : - HeightfieldBrushTool(editor, "Material Brush"), - _materialControl(new MaterialControl(this, _form)) { -} - -QVariant HeightfieldMaterialBrushTool::createEdit(bool alternate) { - Sphere* sphere = new Sphere(); - sphere->setTranslation(_position); - sphere->setScale(_radius->value()); - if (alternate) { - return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), - SharedObjectPointer(), QColor(0, 0, 0, 0), true, false, pow(2.0f, _granularity->value()))); - } else { - return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), - _materialControl->getMaterial(), _materialControl->getColor(), - true, false, pow(2.0f, _granularity->value()))); - } -} - -HeightfieldSculptBrushTool::HeightfieldSculptBrushTool(MetavoxelEditor* editor) : - HeightfieldBrushTool(editor, "Sculpt Brush"), - _materialControl(new MaterialControl(this, _form, true)) { -} - -QVariant HeightfieldSculptBrushTool::createEdit(bool alternate) { - Sphere* sphere = new Sphere(); - sphere->setTranslation(_position); - sphere->setScale(_radius->value()); - if (alternate) { - return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), - SharedObjectPointer(), QColor(0, 0, 0, 0), false, false, pow(2.0f, _granularity->value()))); - } else { - return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), - _materialControl->getMaterial(), _materialControl->getColor(), - false, false, pow(2.0f, _granularity->value()))); - } -} - -HeightfieldFillBrushTool::HeightfieldFillBrushTool(MetavoxelEditor* editor) : - HeightfieldBrushTool(editor, "Fill Brush") { - - _form->addRow("Mode:", _mode = new QComboBox()); - _mode->addItem("Fill"); - _mode->addItem("Voxelize"); -} - -QVariant HeightfieldFillBrushTool::createEdit(bool alternate) { - const int FILL_MODE_INDEX = 0; - if (_mode->currentIndex() == FILL_MODE_INDEX) { - return QVariant::fromValue(FillHeightfieldHeightEdit(_position, _radius->value(), - pow(2.0f, _granularity->value()))); - } - Sphere* sphere = new Sphere(); - sphere->setTranslation(_position); - sphere->setScale(_radius->value()); - return QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(sphere), - SharedObjectPointer(), QColor(), false, true, pow(2.0f, _granularity->value()))); -} - -HeightfieldMaterialBoxTool::HeightfieldMaterialBoxTool(MetavoxelEditor* editor) : - BoxTool(editor, "Set Material (Box)", false) { - - QWidget* widget = new QWidget(); - QFormLayout* form = new QFormLayout(); - widget->setLayout(form); - layout()->addWidget(widget); - - QHBoxLayout* gridLayout = new QHBoxLayout(); - gridLayout->addStretch(1); - gridLayout->addWidget(_snapToGrid = new QCheckBox("Snap to Grid")); - gridLayout->addStretch(1); - form->addRow(gridLayout); - _snapToGrid->setChecked(true); - - _materialControl = new MaterialControl(this, form, true); - - form->addRow("Granularity:", _granularity = new QDoubleSpinBox()); - _granularity->setMinimum(-FLT_MAX); - _granularity->setMaximum(FLT_MAX); - _granularity->setPrefix("2^"); - _granularity->setValue(8.0); -} - -bool HeightfieldMaterialBoxTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -bool HeightfieldMaterialBoxTool::shouldSnapToGrid() { - return _snapToGrid->isChecked(); -} - -QColor HeightfieldMaterialBoxTool::getColor() { - return _materialControl->getColor(); -} - -void HeightfieldMaterialBoxTool::applyValue(const glm::vec3& minimum, const glm::vec3& maximum) { - Cuboid* cuboid = new Cuboid(); - cuboid->setTranslation((maximum + minimum) * 0.5f); - glm::vec3 vector = (maximum - minimum) * 0.5f; - cuboid->setScale(vector.x); - cuboid->setAspectY(vector.y / vector.x); - cuboid->setAspectZ(vector.z / vector.x); - MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(SharedObjectPointer(cuboid), - _materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); -} - -HeightfieldMaterialSpannerTool::HeightfieldMaterialSpannerTool(MetavoxelEditor* editor) : - PlaceSpannerTool(editor, "Set Material (Spanner)", QString(), false) { - - QWidget* widget = new QWidget(); - QFormLayout* form = new QFormLayout(); - widget->setLayout(form); - layout()->addWidget(widget); - - form->addRow(_spannerEditor = new SharedObjectEditor(&Spanner::staticMetaObject, false, this)); - _spannerEditor->setObject(new Sphere()); - - _materialControl = new MaterialControl(this, form, true); - - form->addRow("Granularity:", _granularity = new QDoubleSpinBox()); - _granularity->setMinimum(-FLT_MAX); - _granularity->setMaximum(FLT_MAX); - _granularity->setPrefix("2^"); - _granularity->setValue(8.0); - - QPushButton* place = new QPushButton("Set"); - layout()->addWidget(place); - connect(place, &QPushButton::clicked, this, &HeightfieldMaterialSpannerTool::place); -} - -bool HeightfieldMaterialSpannerTool::appliesTo(const AttributePointer& attribute) const { - return attribute->inherits("SpannerSetAttribute"); -} - -SharedObjectPointer HeightfieldMaterialSpannerTool::getSpanner() { - return _spannerEditor->getObject(); -} - -QColor HeightfieldMaterialSpannerTool::getColor() { - return _materialControl->getColor(); -} - -void HeightfieldMaterialSpannerTool::applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) { - static_cast(spanner.data())->setWillBeVoxelized(true); - MetavoxelEditMessage message = { QVariant::fromValue(HeightfieldMaterialSpannerEdit(spanner, - _materialControl->getMaterial(), _materialControl->getColor(), false, false, pow(2.0f, _granularity->value()))) }; - Application::getInstance()->getMetavoxels()->applyEdit(message, true); -} - diff --git a/interface/src/ui/MetavoxelEditor.h b/interface/src/ui/MetavoxelEditor.h deleted file mode 100644 index 2a44a2d7d7..0000000000 --- a/interface/src/ui/MetavoxelEditor.h +++ /dev/null @@ -1,479 +0,0 @@ -// -// MetavoxelEditor.h -// interface/src/ui -// -// Created by Andrzej Kapolka on 1/21/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelEditor_h -#define hifi_MetavoxelEditor_h - -#include -#include -#include - -#include - -#include "MetavoxelSystem.h" - -class QColorEditor; -class QComboBox; -class QDoubleSpinBox; -class QGroupBox; -class QListWidget; -class QPushButton; -class QScrollArea; -class QSpinBox; - -class MetavoxelTool; -class SharedObjectEditor; -class Vec3Editor; - -/// Allows editing metavoxels. -class MetavoxelEditor : public QWidget { - Q_OBJECT - -public: - - MetavoxelEditor(QWidget* parent = nullptr); - - QString getSelectedAttribute() const; - - double getGridSpacing() const; - double getGridPosition() const; - glm::quat getGridRotation() const; - - QVariant getValue() const; - - virtual bool eventFilter(QObject* watched, QEvent* event); - -private slots: - - void selectedAttributeChanged(); - void createNewAttribute(); - void deleteSelectedAttribute(); - void centerGridPosition(); - void alignGridPosition(); - void updateAttributes(const QString& select = QString()); - void updateTool(); - - void simulate(float deltaTime); - void render(); - void renderPreview(); - -private: - - void addTool(MetavoxelTool* tool); - MetavoxelTool* getActiveTool() const; - - QListWidget* _attributes; - QPushButton* _deleteAttribute; - QCheckBox* _showAll; - - QComboBox* _gridPlane; - QDoubleSpinBox* _gridSpacing; - QDoubleSpinBox* _gridPosition; - - QList _tools; - QComboBox* _toolBox; - - QGroupBox* _value; - QScrollArea* _valueArea; - - static ProgramObject _gridProgram; -}; - -/// Base class for editor tools. -class MetavoxelTool : public QWidget { - Q_OBJECT - -public: - - MetavoxelTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true, - bool userFacing = true, bool usesGrid = true); - - bool getUsesValue() const { return _usesValue; } - - bool isUserFacing() const { return _userFacing; } - - bool getUsesGrid() const { return _usesGrid; } - - virtual bool appliesTo(const AttributePointer& attribute) const; - - virtual void simulate(float deltaTime); - - /// Renders the tool's interface, if any. - virtual void render(); - - /// Renders the tool's metavoxel preview, if any. - virtual void renderPreview(); - -protected: - - MetavoxelEditor* _editor; - bool _usesValue; - bool _userFacing; - bool _usesGrid; -}; - -/// Base class for tools that allow dragging out a 3D box. -class BoxTool : public MetavoxelTool { - Q_OBJECT - -public: - - BoxTool(MetavoxelEditor* editor, const QString& name, bool usesValue = true, bool userFacing = true); - - virtual void render(); - - virtual bool eventFilter(QObject* watched, QEvent* event); - -protected: - - virtual bool shouldSnapToGrid(); - - virtual QColor getColor() = 0; - - virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum) = 0; - -private: - - void resetState(); - - enum State { HOVERING_STATE, DRAGGING_STATE, RAISING_STATE }; - - State _state; - - glm::vec2 _mousePosition; ///< the position of the mouse in rotated space - glm::vec2 _startPosition; ///< the first corner of the selection base - glm::vec2 _endPosition; ///< the second corner of the selection base - float _height; ///< the selection height -}; - -/// Allows setting the value of a region by dragging out a box. -class BoxSetTool : public BoxTool { - Q_OBJECT - -public: - - BoxSetTool(MetavoxelEditor* editor); - -protected: - - virtual QColor getColor(); - - virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum); -}; - -/// Allows setting the value across the entire space. -class GlobalSetTool : public MetavoxelTool { - Q_OBJECT - -public: - - GlobalSetTool(MetavoxelEditor* editor); - -private slots: - - void apply(); -}; - -/// Base class for insert/set spanner tools. -class PlaceSpannerTool : public MetavoxelTool { - Q_OBJECT - -public: - - PlaceSpannerTool(MetavoxelEditor* editor, const QString& name, - const QString& placeText = QString(), bool usesValue = true); - - virtual void simulate(float deltaTime); - - virtual void renderPreview(); - - virtual bool appliesTo(const AttributePointer& attribute) const; - - virtual bool eventFilter(QObject* watched, QEvent* event); - -protected: - - virtual QColor getColor(); - virtual SharedObjectPointer getSpanner(); - virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) = 0; - -protected slots: - - void place(); - -private: - - QCheckBox* _followMouse; -}; - -/// Allows inserting a spanner into the scene. -class InsertSpannerTool : public PlaceSpannerTool { - Q_OBJECT - -public: - - InsertSpannerTool(MetavoxelEditor* editor); - -protected: - - virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner); -}; - -/// Allows removing a spanner from the scene. -class RemoveSpannerTool : public MetavoxelTool { - Q_OBJECT - -public: - - RemoveSpannerTool(MetavoxelEditor* editor); - - virtual bool appliesTo(const AttributePointer& attribute) const; - - virtual bool eventFilter(QObject* watched, QEvent* event); -}; - -/// Allows removing all spanners from the scene. -class ClearSpannersTool : public MetavoxelTool { - Q_OBJECT - -public: - - ClearSpannersTool(MetavoxelEditor* editor); - - virtual bool appliesTo(const AttributePointer& attribute) const; - -private slots: - - void clear(); -}; - -/// Base class for heightfield tools. -class HeightfieldTool : public MetavoxelTool { - Q_OBJECT - -public: - - HeightfieldTool(MetavoxelEditor* editor, const QString& name); - - virtual bool appliesTo(const AttributePointer& attribute) const; - -protected slots: - - virtual void apply() = 0; - -protected: - - QFormLayout* _form; - Vec3Editor* _translation; - QDoubleSpinBox* _spacing; -}; - -/// Allows importing a heightfield. -class ImportHeightfieldTool : public HeightfieldTool { - Q_OBJECT - -public: - - ImportHeightfieldTool(MetavoxelEditor* editor); - - virtual void simulate(float deltaTime); - - virtual void renderPreview(); - -protected: - - virtual void apply(); - -private slots: - - void updateSpanner(); - -private: - - QDoubleSpinBox* _heightScale; - QDoubleSpinBox* _heightOffset; - - HeightfieldHeightEditor* _height; - HeightfieldColorEditor* _color; - - SharedObjectPointer _spanner; -}; - -/// Base class for tools that allow painting on heightfields. -class HeightfieldBrushTool : public MetavoxelTool { - Q_OBJECT - -public: - - HeightfieldBrushTool(MetavoxelEditor* editor, const QString& name); - - virtual bool appliesTo(const AttributePointer& attribute) const; - - virtual void render(); - - virtual bool eventFilter(QObject* watched, QEvent* event); - -protected: - - virtual QVariant createEdit(bool alternate) = 0; - - QFormLayout* _form; - QDoubleSpinBox* _radius; - QDoubleSpinBox* _granularity; - - glm::vec3 _position; - bool _positionValid; -}; - -/// Allows raising or lowering parts of the heightfield. -class HeightfieldHeightBrushTool : public HeightfieldBrushTool { - Q_OBJECT - -public: - - HeightfieldHeightBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - QDoubleSpinBox* _height; - QComboBox* _mode; -}; - -/// Contains widgets for editing materials. -class MaterialControl : public QObject { - Q_OBJECT - -public: - - MaterialControl(QWidget* widget, QFormLayout* form, bool clearable = false); - - SharedObjectPointer getMaterial(); - - const QColor& getColor() const { return _color->getColor(); } - -private slots: - - void clearColor(); - void clearTexture(); - void updateTexture(); - void textureLoaded(); - -private: - - QColorEditor* _color; - SharedObjectEditor* _materialEditor; - QSharedPointer _texture; -}; - -/// Allows texturing parts of the heightfield. -class HeightfieldMaterialBrushTool : public HeightfieldBrushTool { - Q_OBJECT - -public: - - HeightfieldMaterialBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - MaterialControl* _materialControl; -}; - -/// Allows sculpting parts of the heightfield. -class HeightfieldSculptBrushTool : public HeightfieldBrushTool { - Q_OBJECT - -public: - - HeightfieldSculptBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - MaterialControl* _materialControl; -}; - -/// Allows "filling" (removing dual contour stack data) parts of the heightfield. -class HeightfieldFillBrushTool : public HeightfieldBrushTool { - Q_OBJECT - -public: - - HeightfieldFillBrushTool(MetavoxelEditor* editor); - -protected: - - virtual QVariant createEdit(bool alternate); - -private: - - QComboBox* _mode; -}; - -/// Allows setting heightfield materials by dragging out a box. -class HeightfieldMaterialBoxTool : public BoxTool { - Q_OBJECT - -public: - - HeightfieldMaterialBoxTool(MetavoxelEditor* editor); - - virtual bool appliesTo(const AttributePointer& attribute) const; - -protected: - - virtual bool shouldSnapToGrid(); - - virtual QColor getColor(); - - virtual void applyValue(const glm::vec3& minimum, const glm::vec3& maximum); - -private: - - QCheckBox* _snapToGrid; - MaterialControl* _materialControl; - QDoubleSpinBox* _granularity; -}; - -/// Allows setting heightfield materials by placing a spanner. -class HeightfieldMaterialSpannerTool : public PlaceSpannerTool { - Q_OBJECT - -public: - - HeightfieldMaterialSpannerTool(MetavoxelEditor* editor); - - virtual bool appliesTo(const AttributePointer& attribute) const; - -protected: - - virtual SharedObjectPointer getSpanner(); - virtual QColor getColor(); - virtual void applyEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner); - -private: - - SharedObjectEditor* _spannerEditor; - MaterialControl* _materialControl; - QDoubleSpinBox* _granularity; -}; - -#endif // hifi_MetavoxelEditor_h diff --git a/interface/src/ui/MetavoxelNetworkSimulator.cpp b/interface/src/ui/MetavoxelNetworkSimulator.cpp deleted file mode 100644 index dfc9f4be25..0000000000 --- a/interface/src/ui/MetavoxelNetworkSimulator.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// MetavoxelNetworkSimulator.cpp -// interface/src/ui -// -// Created by Andrzej Kapolka on 10/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include - -#include "Application.h" -#include "MetavoxelNetworkSimulator.h" - -const int BYTES_PER_KILOBYTE = 1024; - -MetavoxelNetworkSimulator::MetavoxelNetworkSimulator(QWidget* parent) : - QWidget(parent, Qt::Dialog) { - - setWindowTitle("Metavoxel Network Simulator"); - setAttribute(Qt::WA_DeleteOnClose); - - QVBoxLayout* topLayout = new QVBoxLayout(); - setLayout(topLayout); - - QFormLayout* form = new QFormLayout(); - topLayout->addLayout(form); - - MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); - - form->addRow("Drop Rate:", _dropRate = new QDoubleSpinBox()); - _dropRate->setSuffix("%"); - _dropRate->setValue(simulation.dropRate * 100.0); - connect(_dropRate, static_cast(&QDoubleSpinBox::valueChanged), this, - &MetavoxelNetworkSimulator::updateMetavoxelSystem); - - form->addRow("Repeat Rate:", _repeatRate = new QDoubleSpinBox()); - _repeatRate->setSuffix("%"); - _repeatRate->setValue(simulation.repeatRate * 100.0); - connect(_repeatRate, static_cast(&QDoubleSpinBox::valueChanged), this, - &MetavoxelNetworkSimulator::updateMetavoxelSystem); - - form->addRow("Minimum Delay:", _minimumDelay = new QSpinBox()); - _minimumDelay->setMaximum(1000); - _minimumDelay->setSuffix("ms"); - _minimumDelay->setValue(simulation.minimumDelay); - connect(_minimumDelay, static_cast(&QSpinBox::valueChanged), this, - &MetavoxelNetworkSimulator::updateMetavoxelSystem); - - form->addRow("Maximum Delay:", _maximumDelay = new QSpinBox()); - _maximumDelay->setMaximum(1000); - _maximumDelay->setSuffix("ms"); - _maximumDelay->setValue(simulation.maximumDelay); - connect(_maximumDelay, static_cast(&QSpinBox::valueChanged), this, - &MetavoxelNetworkSimulator::updateMetavoxelSystem); - - form->addRow("Bandwidth Limit:", _bandwidthLimit = new QSpinBox()); - _bandwidthLimit->setMaximum(1024 * 1024); - _bandwidthLimit->setSuffix("KB/s"); - _bandwidthLimit->setValue(simulation.bandwidthLimit / BYTES_PER_KILOBYTE); - connect(_bandwidthLimit, static_cast(&QSpinBox::valueChanged), this, - &MetavoxelNetworkSimulator::updateMetavoxelSystem); - - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this); - topLayout->addWidget(buttons); - connect(buttons, &QDialogButtonBox::accepted, this, &QWidget::close); - - show(); -} - -void MetavoxelNetworkSimulator::updateMetavoxelSystem() { - int bandwidthLimit = _bandwidthLimit->value() * BYTES_PER_KILOBYTE; - if (bandwidthLimit > 0) { - // make sure the limit is enough to let at least one packet through - const int MINIMUM_BANDWIDTH_LIMIT = 2048; - bandwidthLimit = qMax(bandwidthLimit, MINIMUM_BANDWIDTH_LIMIT); - } - Application::getInstance()->getMetavoxels()->setNetworkSimulation(MetavoxelSystem::NetworkSimulation( - _dropRate->value() / 100.0, _repeatRate->value() / 100.0, qMin(_minimumDelay->value(), _maximumDelay->value()), - qMax(_minimumDelay->value(), _maximumDelay->value()), bandwidthLimit)); -} diff --git a/interface/src/ui/MetavoxelNetworkSimulator.h b/interface/src/ui/MetavoxelNetworkSimulator.h deleted file mode 100644 index 211df48c00..0000000000 --- a/interface/src/ui/MetavoxelNetworkSimulator.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// MetavoxelNetworkSimulator.h -// interface/src/ui -// -// Created by Andrzej Kapolka on 10/20/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelNetworkSimulator_h -#define hifi_MetavoxelNetworkSimulator_h - -#include - -class QDoubleSpinBox; -class QSpinBox; - -/// Allows tweaking network simulation (packet drop percentage, etc.) settings for metavoxels. -class MetavoxelNetworkSimulator : public QWidget { - Q_OBJECT - -public: - - MetavoxelNetworkSimulator(QWidget* parent = nullptr); - -private slots: - - void updateMetavoxelSystem(); - -private: - - QDoubleSpinBox* _dropRate; - QDoubleSpinBox* _repeatRate; - QSpinBox* _minimumDelay; - QSpinBox* _maximumDelay; - QSpinBox* _bandwidthLimit; -}; - -#endif // hifi_MetavoxelNetworkSimulator_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 62adcb20e8..ec225dde72 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -55,13 +55,7 @@ Stats::Stats(): _pingStatsWidth(STATS_PING_MIN_WIDTH), _geoStatsWidth(STATS_GEO_MIN_WIDTH), _octreeStatsWidth(STATS_OCTREE_MIN_WIDTH), - _lastHorizontalOffset(0), - _metavoxelInternal(0), - _metavoxelLeaves(0), - _metavoxelSendProgress(0), - _metavoxelSendTotal(0), - _metavoxelReceiveProgress(0), - _metavoxelReceiveTotal(0) + _lastHorizontalOffset(0) { auto glCanvas = Application::getInstance()->getGLWidget(); resetWidth(glCanvas->width(), 0); @@ -460,31 +454,6 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, downloads.str().c_str(), color); - - QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels()->getUpdater(), "getStats", - Q_ARG(QObject*, this), Q_ARG(const QByteArray&, "setMetavoxelStats")); - - stringstream nodes; - nodes << "Metavoxels: " << (_metavoxelInternal + _metavoxelLeaves); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, nodes.str().c_str(), color); - - stringstream nodeTypes; - nodeTypes << "Internal: " << _metavoxelInternal << " Leaves: " << _metavoxelLeaves; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, nodeTypes.str().c_str(), color); - - if (_metavoxelSendTotal > 0 || _metavoxelReceiveTotal > 0) { - stringstream reliableStats; - if (_metavoxelSendTotal > 0) { - reliableStats << "Upload: " << (_metavoxelSendProgress * 100LL / _metavoxelSendTotal) << "% "; - } - if (_metavoxelReceiveTotal > 0) { - reliableStats << "Download: " << (_metavoxelReceiveProgress * 100LL / _metavoxelReceiveTotal) << "%"; - } - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, reliableStats.str().c_str(), color); - } } verticalOffset = STATS_PELS_INITIALOFFSET; @@ -648,12 +617,3 @@ void Stats::display( } } -void Stats::setMetavoxelStats(int internal, int leaves, int sendProgress, - int sendTotal, int receiveProgress, int receiveTotal) { - _metavoxelInternal = internal; - _metavoxelLeaves = leaves; - _metavoxelSendProgress = sendProgress; - _metavoxelSendTotal = sendTotal; - _metavoxelReceiveProgress = receiveProgress; - _metavoxelReceiveTotal = receiveTotal; -} diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index d6da8d8cc6..406496d858 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -33,9 +33,6 @@ public: int inKbitsPerSecond, int outKbitsPerSecond, int voxelPacketsToProcess); bool includeTimingRecord(const QString& name); - Q_INVOKABLE void setMetavoxelStats(int internal, int leaves, int sendProgress, - int sendTotal, int receiveProgress, int receiveTotal); - private: static Stats* _sharedInstance; @@ -52,12 +49,6 @@ private: int _lastHorizontalOffset; - int _metavoxelInternal; - int _metavoxelLeaves; - int _metavoxelSendProgress; - int _metavoxelSendTotal; - int _metavoxelReceiveProgress; - int _metavoxelReceiveTotal; }; #endif // hifi_Stats_h diff --git a/libraries/metavoxels/CMakeLists.txt b/libraries/metavoxels/CMakeLists.txt deleted file mode 100644 index 240a2d8853..0000000000 --- a/libraries/metavoxels/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -set(TARGET_NAME metavoxels) - -auto_mtc() - -# use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Network Script Widgets) - -# link in the networking library -link_hifi_libraries(shared networking) - -add_dependency_external_projects(glm) -find_package(GLM REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) \ No newline at end of file diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp deleted file mode 100644 index b23d83de55..0000000000 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ /dev/null @@ -1,499 +0,0 @@ -// -// AttributeRegistry.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include - -#include "AttributeRegistry.h" -#include "MetavoxelData.h" -#include "Spanner.h" - -REGISTER_META_OBJECT(FloatAttribute) -REGISTER_META_OBJECT(SharedObjectAttribute) -REGISTER_META_OBJECT(SharedObjectSetAttribute) -REGISTER_META_OBJECT(SpannerSetAttribute) - -static int attributePointerMetaTypeId = qRegisterMetaType(); -static int ownedAttributeValueMetaTypeId = qRegisterMetaType(); - -AttributeRegistry* AttributeRegistry::getInstance() { - static AttributeRegistry registry; - return ®istry; -} - -AttributeRegistry::AttributeRegistry() : - _guideAttribute(registerAttribute(new SharedObjectAttribute("guide", &MetavoxelGuide::staticMetaObject, - new DefaultMetavoxelGuide()))), - _rendererAttribute(registerAttribute(new SharedObjectAttribute("renderer", &MetavoxelRenderer::staticMetaObject, - new DefaultMetavoxelRenderer()))), - _spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))) { - - // our baseline LOD threshold is for voxels; spanners are a different story - const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 16.0f; - _spannersAttribute->setLODThresholdMultiplier(SPANNER_LOD_THRESHOLD_MULTIPLIER); - _spannersAttribute->setUserFacing(true); -} - -static QScriptValue qDebugFunction(QScriptContext* context, QScriptEngine* engine) { - QDebug debug = qDebug(); - - for (int i = 0; i < context->argumentCount(); i++) { - debug << context->argument(i).toString(); - } - - return QScriptValue(); -} - -void AttributeRegistry::configureScriptEngine(QScriptEngine* engine) { - QScriptValue registry = engine->newObject(); - registry.setProperty("getAttribute", engine->newFunction(getAttribute, 1)); - engine->globalObject().setProperty("AttributeRegistry", registry); - engine->globalObject().setProperty("qDebug", engine->newFunction(qDebugFunction, 1)); -} - -AttributePointer AttributeRegistry::registerAttribute(AttributePointer attribute) { - if (!attribute) { - return attribute; - } - QWriteLocker locker(&_attributesLock); - AttributePointer& pointer = _attributes[attribute->getName()]; - if (!pointer) { - pointer = attribute; - } - return pointer; -} - -void AttributeRegistry::deregisterAttribute(const QString& name) { - QWriteLocker locker(&_attributesLock); - _attributes.remove(name); -} - -AttributePointer AttributeRegistry::getAttribute(const QString& name) { - QReadLocker locker(&_attributesLock); - return _attributes.value(name); -} - -QScriptValue AttributeRegistry::getAttribute(QScriptContext* context, QScriptEngine* engine) { - return engine->newQObject(getInstance()->getAttribute(context->argument(0).toString()).data(), QScriptEngine::QtOwnership, - QScriptEngine::PreferExistingWrapperObject); -} - -AttributeValue::AttributeValue(const AttributePointer& attribute) : - _attribute(attribute), _value(attribute ? attribute->getDefaultValue() : NULL) { -} - -AttributeValue::AttributeValue(const AttributePointer& attribute, void* value) : - _attribute(attribute), _value(value) { -} - -void* AttributeValue::copy() const { - return _attribute->create(_value); -} - -bool AttributeValue::isDefault() const { - return !_attribute || _attribute->equal(_value, _attribute->getDefaultValue()); -} - -bool AttributeValue::operator==(const AttributeValue& other) const { - return _attribute == other._attribute && (!_attribute || _attribute->equal(_value, other._value)); -} - -bool AttributeValue::operator==(void* other) const { - return _attribute && _attribute->equal(_value, other); -} - -bool AttributeValue::operator!=(const AttributeValue& other) const { - return _attribute != other._attribute || (_attribute && !_attribute->equal(_value, other._value)); -} - -bool AttributeValue::operator!=(void* other) const { - return !_attribute || !_attribute->equal(_value, other); -} - -OwnedAttributeValue::OwnedAttributeValue(const AttributePointer& attribute, void* value) : - AttributeValue(attribute, value) { -} - -OwnedAttributeValue::OwnedAttributeValue(const AttributePointer& attribute) : - AttributeValue(attribute, attribute ? attribute->create() : NULL) { -} - -OwnedAttributeValue::OwnedAttributeValue(const AttributeValue& other) : - AttributeValue(other.getAttribute(), other.getAttribute() ? other.copy() : NULL) { -} - -OwnedAttributeValue::OwnedAttributeValue(const OwnedAttributeValue& other) : - AttributeValue(other.getAttribute(), other.getAttribute() ? other.copy() : NULL) { -} - -OwnedAttributeValue::~OwnedAttributeValue() { - if (_attribute) { - _attribute->destroy(_value); - } -} - -void OwnedAttributeValue::mix(const AttributeValue& first, const AttributeValue& second, float alpha) { - if (_attribute) { - _attribute->destroy(_value); - } - _attribute = first.getAttribute(); - _value = _attribute->mix(first.getValue(), second.getValue(), alpha); -} - -void OwnedAttributeValue::blend(const AttributeValue& source, const AttributeValue& dest) { - if (_attribute) { - _attribute->destroy(_value); - } - _attribute = source.getAttribute(); - _value = _attribute->blend(source.getValue(), dest.getValue()); -} - -OwnedAttributeValue& OwnedAttributeValue::operator=(const AttributeValue& other) { - if (_attribute) { - _attribute->destroy(_value); - } - if ((_attribute = other.getAttribute())) { - _value = other.copy(); - } - return *this; -} - -OwnedAttributeValue& OwnedAttributeValue::operator=(const OwnedAttributeValue& other) { - if (_attribute) { - _attribute->destroy(_value); - } - if ((_attribute = other.getAttribute())) { - _value = other.copy(); - } - return *this; -} - -Attribute::Attribute(const QString& name) : - _lodThresholdMultiplier(1.0f), - _userFacing(false) { - setObjectName(name); -} - -Attribute::~Attribute() { -} - -void Attribute::readSubdivided(MetavoxelStreamState& state, void*& value, - const MetavoxelStreamState& ancestorState, void* ancestorValue, bool isLeaf) const { - read(state.base.stream, value, isLeaf); -} - -void Attribute::writeSubdivided(MetavoxelStreamState& state, void* value, - const MetavoxelStreamState& ancestorState, void* ancestorValue, bool isLeaf) const { - write(state.base.stream, value, isLeaf); -} - -MetavoxelNode* Attribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const { - return new MetavoxelNode(value); -} - -void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { - data.createRoot(state.base.attribute)->read(state); -} - -void Attribute::writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state) { - root.write(state); -} - -void Attribute::readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state) { - data.createRoot(state.base.attribute)->readDelta(reference, state); -} - -void Attribute::writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state) { - root.writeDelta(reference, state); -} - -void Attribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { - // copy if changed - MetavoxelNode* oldRoot = data.getRoot(state.base.attribute); - MetavoxelNode* newRoot = oldRoot->readSubdivision(state); - if (newRoot != oldRoot) { - data.setRoot(state.base.attribute, newRoot); - } -} - -void Attribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { - root.writeSubdivision(state); -} - -bool Attribute::metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod) { - return firstRoot.deepEquals(this, secondRoot, minimum, size, lod); -} - -MetavoxelNode* Attribute::expandMetavoxelRoot(const MetavoxelNode& root) { - AttributePointer attribute(this); - MetavoxelNode* newParent = new MetavoxelNode(attribute); - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - MetavoxelNode* newChild = new MetavoxelNode(attribute); - newParent->setChild(i, newChild); - int index = MetavoxelNode::getOppositeChildIndex(i); - if (root.isLeaf()) { - newChild->setChild(index, new MetavoxelNode(root.getAttributeValue(attribute))); - } else { - MetavoxelNode* grandchild = root.getChild(i); - grandchild->incrementReferenceCount(); - newChild->setChild(index, grandchild); - } - for (int j = 1; j < MetavoxelNode::CHILD_COUNT; j++) { - MetavoxelNode* newGrandchild = new MetavoxelNode(attribute); - newChild->setChild((index + j) % MetavoxelNode::CHILD_COUNT, newGrandchild); - } - } - return newParent; -} - -FloatAttribute::FloatAttribute(const QString& name) : - SimpleInlineAttribute(name) { -} - -SharedObjectAttribute::SharedObjectAttribute(const QString& name, const QMetaObject* metaObject, - const SharedObjectPointer& defaultValue) : - InlineAttribute(name, defaultValue), - _metaObject(metaObject) { - -} - -void SharedObjectAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { - if (isLeaf) { - in >> *((SharedObjectPointer*)&value); - } -} - -void SharedObjectAttribute::write(Bitstream& out, void* value, bool isLeaf) const { - if (isLeaf) { - out << decodeInline(value); - } -} - -bool SharedObjectAttribute::deepEqual(void* first, void* second) const { - SharedObjectPointer firstObject = decodeInline(first); - SharedObjectPointer secondObject = decodeInline(second); - return firstObject ? firstObject->equals(secondObject) : !secondObject; -} - -bool SharedObjectAttribute::merge(void*& parent, void* children[], bool postRead) const { - SharedObjectPointer firstChild = decodeInline(children[0]); - for (int i = 1; i < MERGE_COUNT; i++) { - if (firstChild != decodeInline(children[i])) { - *(SharedObjectPointer*)&parent = _defaultValue; - return false; - } - } - *(SharedObjectPointer*)&parent = firstChild; - return true; -} - -void* SharedObjectAttribute::createFromVariant(const QVariant& value) const { - return create(encodeInline(value.value())); -} - -QWidget* SharedObjectAttribute::createEditor(QWidget* parent) const { - SharedObjectEditor* editor = new SharedObjectEditor(_metaObject, parent); - editor->setObject(_defaultValue); - return editor; -} - -SharedObjectSetAttribute::SharedObjectSetAttribute(const QString& name, const QMetaObject* metaObject) : - InlineAttribute(name), - _metaObject(metaObject) { -} - -void SharedObjectSetAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { - in >> *((SharedObjectSet*)&value); -} - -void SharedObjectSetAttribute::write(Bitstream& out, void* value, bool isLeaf) const { - out << decodeInline(value); -} - -MetavoxelNode* SharedObjectSetAttribute::createMetavoxelNode( - const AttributeValue& value, const MetavoxelNode* original) const { - return new MetavoxelNode(value, original); -} - -static bool setsEqual(const SharedObjectSet& firstSet, const SharedObjectSet& secondSet) { - if (firstSet.size() != secondSet.size()) { - return false; - } - // some hackiness here: we assume that the local ids of the first set correspond to the remote ids of the second, - // so that this will work with the tests - foreach (const SharedObjectPointer& firstObject, firstSet) { - int id = firstObject->getID(); - bool found = false; - foreach (const SharedObjectPointer& secondObject, secondSet) { - if (secondObject->getRemoteID() == id) { - if (!firstObject->equals(secondObject)) { - return false; - } - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; -} - -bool SharedObjectSetAttribute::deepEqual(void* first, void* second) const { - return setsEqual(decodeInline(first), decodeInline(second)); -} - -MetavoxelNode* SharedObjectSetAttribute::expandMetavoxelRoot(const MetavoxelNode& root) { - AttributePointer attribute(this); - MetavoxelNode* newParent = new MetavoxelNode(attribute); - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - MetavoxelNode* newChild = new MetavoxelNode(root.getAttributeValue(attribute)); - newParent->setChild(i, newChild); - if (root.isLeaf()) { - continue; - } - MetavoxelNode* grandchild = root.getChild(i); - grandchild->incrementReferenceCount(); - int index = MetavoxelNode::getOppositeChildIndex(i); - newChild->setChild(index, grandchild); - for (int j = 1; j < MetavoxelNode::CHILD_COUNT; j++) { - MetavoxelNode* newGrandchild = new MetavoxelNode(attribute); - newChild->setChild((index + j) % MetavoxelNode::CHILD_COUNT, newGrandchild); - } - } - return newParent; -} - -bool SharedObjectSetAttribute::merge(void*& parent, void* children[], bool postRead) const { - for (int i = 0; i < MERGE_COUNT; i++) { - if (!decodeInline(children[i]).isEmpty()) { - return false; - } - } - return true; -} - -AttributeValue SharedObjectSetAttribute::inherit(const AttributeValue& parentValue) const { - return AttributeValue(parentValue.getAttribute()); -} - -QWidget* SharedObjectSetAttribute::createEditor(QWidget* parent) const { - return new SharedObjectEditor(_metaObject, parent); -} - -SpannerSetAttribute::SpannerSetAttribute(const QString& name, const QMetaObject* metaObject) : - SharedObjectSetAttribute(name, metaObject) { -} - -void SpannerSetAttribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { - forever { - SharedObjectPointer object; - state.base.stream >> object; - if (!object) { - break; - } - data.insert(state.base.attribute, object); - } - // even if the root is empty, it should still exist - if (!data.getRoot(state.base.attribute)) { - data.createRoot(state.base.attribute); - } -} - -void SpannerSetAttribute::writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state) { - state.base.visit = Spanner::getAndIncrementNextVisit(); - root.writeSpanners(state); - state.base.stream << SharedObjectPointer(); -} - -void SpannerSetAttribute::readMetavoxelDelta(MetavoxelData& data, - const MetavoxelNode& reference, MetavoxelStreamState& state) { - readMetavoxelSubdivision(data, state); -} - -static void writeDeltaSubdivision(SharedObjectSet& oldSet, SharedObjectSet& newSet, Bitstream& stream) { - for (SharedObjectSet::iterator newIt = newSet.begin(); newIt != newSet.end(); ) { - SharedObjectSet::iterator oldIt = oldSet.find(*newIt); - if (oldIt == oldSet.end()) { - stream << *newIt; // added - newIt = newSet.erase(newIt); - - } else { - oldSet.erase(oldIt); - newIt++; - } - } - foreach (const SharedObjectPointer& object, oldSet) { - stream << object; // removed - } - stream << SharedObjectPointer(); - foreach (const SharedObjectPointer& object, newSet) { - object->maybeWriteSubdivision(stream); - } - stream << SharedObjectPointer(); -} - -void SpannerSetAttribute::writeMetavoxelDelta(const MetavoxelNode& root, - const MetavoxelNode& reference, MetavoxelStreamState& state) { - SharedObjectSet oldSet, newSet; - reference.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet); - root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet); - writeDeltaSubdivision(oldSet, newSet, state.base.stream); -} - -void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) { - forever { - SharedObjectPointer object; - state.base.stream >> object; - if (!object) { - break; - } - data.toggle(state.base.attribute, object); - } - forever { - SharedObjectPointer object; - state.base.stream >> object; - if (!object) { - break; - } - SharedObjectPointer newObject = object->readSubdivision(state.base.stream); - if (newObject != object) { - data.replace(state.base.attribute, object, newObject); - state.base.stream.addSubdividedObject(newObject); - } - } - // even if the root is empty, it should still exist - if (!data.getRoot(state.base.attribute)) { - data.createRoot(state.base.attribute); - } -} - -void SpannerSetAttribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) { - SharedObjectSet oldSet, newSet; - root.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet); - root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet); - writeDeltaSubdivision(oldSet, newSet, state.base.stream); -} - -bool SpannerSetAttribute::metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod) { - - SharedObjectSet firstSet; - firstRoot.getSpanners(this, minimum, size, lod, firstSet); - SharedObjectSet secondSet; - secondRoot.getSpanners(this, minimum, size, lod, secondSet); - return setsEqual(firstSet, secondSet); -} diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h deleted file mode 100644 index ea0ec263e4..0000000000 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ /dev/null @@ -1,409 +0,0 @@ -// -// AttributeRegistry.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AttributeRegistry_h -#define hifi_AttributeRegistry_h - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Bitstream.h" -#include "SharedObject.h" - -class QScriptContext; -class QScriptEngine; -class QScriptValue; - -class Attribute; -class DataBlock; -class MetavoxelData; -class MetavoxelLOD; -class MetavoxelNode; -class MetavoxelStreamState; - -typedef SharedObjectPointerTemplate AttributePointer; - -Q_DECLARE_METATYPE(AttributePointer) - -/// Maintains information about metavoxel attribute types. -class AttributeRegistry { -public: - - /// Returns a pointer to the singleton registry instance. - static AttributeRegistry* getInstance(); - - AttributeRegistry(); - - /// Configures the supplied script engine with the global AttributeRegistry property. - void configureScriptEngine(QScriptEngine* engine); - - /// Registers an attribute with the system. The registry assumes ownership of the object. - /// \return either the pointer passed as an argument, if the attribute wasn't already registered, or the existing - /// attribute - AttributePointer registerAttribute(Attribute* attribute) { return registerAttribute(AttributePointer(attribute)); } - - /// Registers an attribute with the system. - /// \return either the pointer passed as an argument, if the attribute wasn't already registered, or the existing - /// attribute - AttributePointer registerAttribute(AttributePointer attribute); - - /// Deregisters an attribute. - void deregisterAttribute(const QString& name); - - /// Retrieves an attribute by name. - AttributePointer getAttribute(const QString& name); - - /// Returns a reference to the attribute hash. - const QHash& getAttributes() const { return _attributes; } - - /// Returns a reference to the attributes lock. - QReadWriteLock& getAttributesLock() { return _attributesLock; } - - /// Returns a reference to the standard SharedObjectPointer "guide" attribute. - const AttributePointer& getGuideAttribute() const { return _guideAttribute; } - - /// Returns a reference to the standard SharedObjectPointer "renderer" attribute. - const AttributePointer& getRendererAttribute() const { return _rendererAttribute; } - - /// Returns a reference to the standard SharedObjectSet "spanners" attribute. - const AttributePointer& getSpannersAttribute() const { return _spannersAttribute; } - -private: - - static QScriptValue getAttribute(QScriptContext* context, QScriptEngine* engine); - - QHash _attributes; - QReadWriteLock _attributesLock; - - AttributePointer _guideAttribute; - AttributePointer _rendererAttribute; - AttributePointer _spannersAttribute; -}; - -/// Converts a value to a void pointer. -template inline void* encodeInline(T value) { - return *(void**)&value; -} - -/// Extracts a value from a void pointer. -template inline T decodeInline(void* value) { - return *(T*)&value; -} - -/// Pairs an attribute value with its type. -class AttributeValue { -public: - - AttributeValue(const AttributePointer& attribute = AttributePointer()); - AttributeValue(const AttributePointer& attribute, void* value); - - AttributePointer getAttribute() const { return _attribute; } - void* getValue() const { return _value; } - - template void setInlineValue(T value) { _value = encodeInline(value); } - template T getInlineValue() const { return decodeInline(_value); } - - void* copy() const; - - bool isDefault() const; - - bool operator==(const AttributeValue& other) const; - bool operator==(void* other) const; - - bool operator!=(const AttributeValue& other) const; - bool operator!=(void* other) const; - -protected: - - AttributePointer _attribute; - void* _value; -}; - -// Assumes ownership of an attribute value. -class OwnedAttributeValue : public AttributeValue { -public: - - /// Assumes ownership of the specified value. It will be destroyed when this is destroyed or reassigned. - OwnedAttributeValue(const AttributePointer& attribute, void* value); - - /// Creates an owned attribute with a copy of the specified attribute's default value. - OwnedAttributeValue(const AttributePointer& attribute = AttributePointer()); - - /// Creates an owned attribute with a copy of the specified other value. - OwnedAttributeValue(const AttributeValue& other); - - /// Creates an owned attribute with a copy of the specified other value. - OwnedAttributeValue(const OwnedAttributeValue& other); - - /// Destroys the current value, if any. - ~OwnedAttributeValue(); - - /// Sets this attribute to a mix of the first and second provided. - void mix(const AttributeValue& first, const AttributeValue& second, float alpha); - - /// Sets this attribute to a blend of the source and destination. - void blend(const AttributeValue& source, const AttributeValue& dest); - - /// Destroys the current value, if any, and copies the specified other value. - OwnedAttributeValue& operator=(const AttributeValue& other); - - /// Destroys the current value, if any, and copies the specified other value. - OwnedAttributeValue& operator=(const OwnedAttributeValue& other); -}; - -Q_DECLARE_METATYPE(OwnedAttributeValue) - -/// Represents a registered attribute. -class Attribute : public SharedObject { - Q_OBJECT - Q_PROPERTY(float lodThresholdMultiplier MEMBER _lodThresholdMultiplier) - Q_PROPERTY(bool userFacing MEMBER _userFacing) - -public: - - static const int MERGE_COUNT = 8; - - Attribute(const QString& name); - virtual ~Attribute(); - - Q_INVOKABLE QString getName() const { return objectName(); } - - float getLODThresholdMultiplier() const { return _lodThresholdMultiplier; } - void setLODThresholdMultiplier(float multiplier) { _lodThresholdMultiplier = multiplier; } - - bool isUserFacing() const { return _userFacing; } - void setUserFacing(bool userFacing) { _userFacing = userFacing; } - - void* create() const { return create(getDefaultValue()); } - virtual void* create(void* copy) const = 0; - virtual void destroy(void* value) const = 0; - - virtual void read(Bitstream& in, void*& value, bool isLeaf) const = 0; - virtual void write(Bitstream& out, void* value, bool isLeaf) const = 0; - - virtual void readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const { read(in, value, isLeaf); } - virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const { write(out, value, isLeaf); } - - virtual void readSubdivided(MetavoxelStreamState& state, void*& value, - const MetavoxelStreamState& ancestorState, void* ancestorValue, bool isLeaf) const; - virtual void writeSubdivided(MetavoxelStreamState& state, void* value, - const MetavoxelStreamState& ancestorState, void* ancestorValue, bool isLeaf) const; - - virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; - - virtual void readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state); - - virtual void readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); - - virtual void readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); - - virtual bool equal(void* first, void* second) const = 0; - - virtual bool deepEqual(void* first, void* second) const { return equal(first, second); } - - virtual bool metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod); - - /// Expands the specified root, doubling its size in each dimension. - /// \return a new node representing the result - virtual MetavoxelNode* expandMetavoxelRoot(const MetavoxelNode& root); - - /// Merges the value of a parent and its children. - /// \param postRead whether or not the merge is happening after a read - /// \return whether or not the children and parent values are all equal - virtual bool merge(void*& parent, void* children[], bool postRead = false) const = 0; - - /// Given the parent value, returns the value that children should inherit (either the parent value or the default). - virtual AttributeValue inherit(const AttributeValue& parentValue) const { return parentValue; } - - /// Mixes the first and the second, returning a new value with the result. - virtual void* mix(void* first, void* second, float alpha) const = 0; - - /// Blends the source with the destination, returning a new value with the result. - virtual void* blend(void* source, void* dest) const = 0; - - virtual void* getDefaultValue() const = 0; - - virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const { return create(); } - - virtual void* createFromVariant(const QVariant& value) const { return create(); } - - /// Creates a widget to use to edit values of this attribute, or returns NULL if the attribute isn't editable. - /// The widget should have a single "user" property that will be used to get/set the value. - virtual QWidget* createEditor(QWidget* parent = NULL) const { return NULL; } - -private: - - float _lodThresholdMultiplier; - bool _userFacing; -}; - -/// A simple attribute class that stores its values inline. -template class InlineAttribute : public Attribute { -public: - - InlineAttribute(const QString& name, const T& defaultValue = T()) : Attribute(name), _defaultValue(defaultValue) { } - - virtual void* create(void* copy) const { void* value; new (&value) T(*(T*)©); return value; } - virtual void destroy(void* value) const { ((T*)&value)->~T(); } - - virtual void read(Bitstream& in, void*& value, bool isLeaf) const; - virtual void write(Bitstream& out, void* value, bool isLeaf) const; - - virtual bool equal(void* first, void* second) const { return decodeInline(first) == decodeInline(second); } - - virtual void* mix(void* first, void* second, float alpha) const { return create(alpha < 0.5f ? first : second); } - - virtual void* blend(void* source, void* dest) const { return create(source); } - - virtual void* getDefaultValue() const { return encodeInline(_defaultValue); } - -protected: - - T _defaultValue; -}; - -template inline void InlineAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { - if (isLeaf) { - value = getDefaultValue(); - in.read(&value, bits); - } -} - -template inline void InlineAttribute::write(Bitstream& out, void* value, bool isLeaf) const { - if (isLeaf) { - out.write(&value, bits); - } -} - -/// Provides averaging using the +=, ==, and / operators. -template class SimpleInlineAttribute : public InlineAttribute { -public: - - SimpleInlineAttribute(const QString& name, const T& defaultValue = T()) : InlineAttribute(name, defaultValue) { } - - virtual bool merge(void*& parent, void* children[], bool postRead = false) const; -}; - -template inline bool SimpleInlineAttribute::merge( - void*& parent, void* children[], bool postRead) const { - T firstValue = decodeInline(children[0]); - T totalValue = firstValue; - bool allChildrenEqual = true; - for (int i = 1; i < Attribute::MERGE_COUNT; i++) { - T value = decodeInline(children[i]); - totalValue += value; - allChildrenEqual &= (firstValue == value); - } - parent = encodeInline(totalValue / Attribute::MERGE_COUNT); - return allChildrenEqual; -} - -/// A simple float attribute. -class FloatAttribute : public SimpleInlineAttribute { - Q_OBJECT - -public: - - Q_INVOKABLE FloatAttribute(const QString& name = QString()); -}; - -/// An attribute that takes the form of QObjects of a given meta-type (a subclass of SharedObject). -class SharedObjectAttribute : public InlineAttribute { - Q_OBJECT - Q_PROPERTY(const QMetaObject* metaObject MEMBER _metaObject) - -public: - - Q_INVOKABLE SharedObjectAttribute(const QString& name = QString(), - const QMetaObject* metaObject = &SharedObject::staticMetaObject, - const SharedObjectPointer& defaultValue = SharedObjectPointer()); - - virtual void read(Bitstream& in, void*& value, bool isLeaf) const; - virtual void write(Bitstream& out, void* value, bool isLeaf) const; - - virtual bool deepEqual(void* first, void* second) const; - - virtual bool merge(void*& parent, void* children[], bool postRead = false) const; - - virtual void* createFromVariant(const QVariant& value) const; - - virtual QWidget* createEditor(QWidget* parent = NULL) const; - -private: - - const QMetaObject* _metaObject; -}; - -/// An attribute that takes the form of a set of shared objects. -class SharedObjectSetAttribute : public InlineAttribute { - Q_OBJECT - Q_PROPERTY(const QMetaObject* metaObject MEMBER _metaObject) - -public: - - Q_INVOKABLE SharedObjectSetAttribute(const QString& name = QString(), - const QMetaObject* metaObject = &SharedObject::staticMetaObject); - - const QMetaObject* getMetaObject() const { return _metaObject; } - - virtual void read(Bitstream& in, void*& value, bool isLeaf) const; - virtual void write(Bitstream& out, void* value, bool isLeaf) const; - - virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; - - virtual bool deepEqual(void* first, void* second) const; - - virtual MetavoxelNode* expandMetavoxelRoot(const MetavoxelNode& root); - - virtual bool merge(void*& parent, void* children[], bool postRead = false) const; - - virtual AttributeValue inherit(const AttributeValue& parentValue) const; - - virtual QWidget* createEditor(QWidget* parent = NULL) const; - -private: - - const QMetaObject* _metaObject; -}; - -/// An attribute that takes the form of a set of spanners. -class SpannerSetAttribute : public SharedObjectSetAttribute { - Q_OBJECT - -public: - - Q_INVOKABLE SpannerSetAttribute(const QString& name = QString(), - const QMetaObject* metaObject = &SharedObject::staticMetaObject); - - virtual void readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state); - - virtual void readMetavoxelDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state); - virtual void writeMetavoxelDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state); - - virtual void readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state); - virtual void writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state); - - virtual bool metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod); -}; - -#endif // hifi_AttributeRegistry_h diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp deleted file mode 100644 index 9c672a415e..0000000000 --- a/libraries/metavoxels/src/Bitstream.cpp +++ /dev/null @@ -1,3552 +0,0 @@ -// -// Bitstream.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/2/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "AttributeRegistry.h" -#include "Bitstream.h" -#include "ScriptCache.h" - -REGISTER_SIMPLE_TYPE_STREAMER(bool) -REGISTER_SIMPLE_TYPE_STREAMER(int) -REGISTER_SIMPLE_TYPE_STREAMER(uint) -REGISTER_SIMPLE_TYPE_STREAMER(float) -REGISTER_SIMPLE_TYPE_STREAMER(QByteArray) -REGISTER_SIMPLE_TYPE_STREAMER(QColor) -REGISTER_SIMPLE_TYPE_STREAMER(QScriptValue) -REGISTER_SIMPLE_TYPE_STREAMER(QString) -REGISTER_SIMPLE_TYPE_STREAMER(QVariant) -REGISTER_SIMPLE_TYPE_STREAMER(QUrl) -REGISTER_SIMPLE_TYPE_STREAMER(QVariantList) -REGISTER_SIMPLE_TYPE_STREAMER(QVariantHash) -REGISTER_SIMPLE_TYPE_STREAMER(SharedObjectPointer) - -// some types don't quite work with our macro -static int vec3Streamer = Bitstream::registerTypeStreamer(qMetaTypeId(), new SimpleTypeStreamer()); -static int quatStreamer = Bitstream::registerTypeStreamer(qMetaTypeId(), new SimpleTypeStreamer()); -static int metaObjectStreamer = Bitstream::registerTypeStreamer(qMetaTypeId(), - new SimpleTypeStreamer()); - -static int genericValueStreamer = Bitstream::registerTypeStreamer( - qRegisterMetaType(), new GenericValueStreamer()); - -static int qVariantPairListMetaTypeId = qRegisterMetaType(); - -IDStreamer::IDStreamer(Bitstream& stream) : - _stream(stream), - _bits(1) { -} - -static int getBitsForHighestValue(int highestValue) { - // if this turns out to be a bottleneck, there are fancier ways to do it (get the position of the highest set bit): - // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious - int bits = 0; - while (highestValue != 0) { - bits++; - highestValue >>= 1; - } - return bits; -} - -void IDStreamer::setBitsFromValue(int value) { - _bits = getBitsForHighestValue(value + 1); -} - -IDStreamer& IDStreamer::operator<<(int value) { - _stream.write(&value, _bits); - if (value == (1 << _bits) - 1) { - _bits++; - } - return *this; -} - -IDStreamer& IDStreamer::operator>>(int& value) { - value = 0; - _stream.read(&value, _bits); - if (value == (1 << _bits) - 1) { - _bits++; - } - return *this; -} - -void Bitstream::preThreadingInit() { - getObjectStreamers(); - getEnumStreamers(); - getEnumStreamersByName(); -} - -int Bitstream::registerMetaObject(const char* className, const QMetaObject* metaObject) { - getMetaObjects().insert(className, metaObject); - - // register it as a subclass of itself and all of its superclasses - for (const QMetaObject* superClass = metaObject; superClass; superClass = superClass->superClass()) { - getMetaObjectSubClasses().insert(superClass, metaObject); - } - return 0; -} - -int Bitstream::registerTypeStreamer(int type, TypeStreamer* streamer) { - streamer->_type = type; - if (!streamer->_self) { - streamer->_self = TypeStreamerPointer(streamer); - } - getTypeStreamers().insert(type, streamer); - return 0; -} - -const TypeStreamer* Bitstream::getTypeStreamer(int type) { - return getTypeStreamers().value(type); -} - -const ObjectStreamer* Bitstream::getObjectStreamer(const QMetaObject* metaObject) { - return getObjectStreamers().value(metaObject); -} - -const QMetaObject* Bitstream::getMetaObject(const QByteArray& className) { - return getMetaObjects().value(className); -} - -QList Bitstream::getMetaObjectSubClasses(const QMetaObject* metaObject) { - return getMetaObjectSubClasses().values(metaObject); -} - -QScriptValue sharedObjectPointerToScriptValue(QScriptEngine* engine, const SharedObjectPointer& pointer) { - return pointer ? engine->newQObject(pointer.data()) : engine->nullValue(); -} - -void sharedObjectPointerFromScriptValue(const QScriptValue& object, SharedObjectPointer& pointer) { - pointer = qobject_cast(object.toQObject()); -} - -void Bitstream::registerTypes(QScriptEngine* engine) { - foreach (const QMetaObject* metaObject, getMetaObjects()) { - engine->globalObject().setProperty(metaObject->className(), engine->newQMetaObject(metaObject)); - } - qScriptRegisterMetaType(engine, sharedObjectPointerToScriptValue, sharedObjectPointerFromScriptValue); -} - -Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, GenericsMode genericsMode, QObject* parent) : - QObject(parent), - _underlying(underlying), - _byte(0), - _position(0), - _metadataType(metadataType), - _genericsMode(genericsMode), - _context(NULL), - _objectStreamerStreamer(*this), - _typeStreamerStreamer(*this), - _attributeStreamer(*this), - _scriptStringStreamer(*this), - _sharedObjectStreamer(*this) { -} - -void Bitstream::addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject) { - _metaObjectSubstitutions.insert(className, metaObject); -} - -void Bitstream::addTypeSubstitution(const QByteArray& typeName, int type) { - _typeStreamerSubstitutions.insert(typeName, getTypeStreamers().value(type)); -} - -void Bitstream::addTypeSubstitution(const QByteArray& typeName, const char* replacementTypeName) { - const TypeStreamer* streamer = getTypeStreamers().value(QMetaType::type(replacementTypeName)); - if (!streamer) { - streamer = getEnumStreamersByName().value(replacementTypeName); - } - _typeStreamerSubstitutions.insert(typeName, streamer); -} - -const int LAST_BIT_POSITION = BITS_IN_BYTE - 1; - -Bitstream& Bitstream::write(const void* data, int bits, int offset) { - const quint8* source = (const quint8*)data; - while (bits > 0) { - int bitsToWrite = qMin(BITS_IN_BYTE - _position, qMin(BITS_IN_BYTE - offset, bits)); - _byte |= ((*source >> offset) & ((1 << bitsToWrite) - 1)) << _position; - if ((_position += bitsToWrite) == BITS_IN_BYTE) { - flush(); - } - if ((offset += bitsToWrite) == BITS_IN_BYTE) { - source++; - offset = 0; - } - bits -= bitsToWrite; - } - return *this; -} - -Bitstream& Bitstream::read(void* data, int bits, int offset) { - quint8* dest = (quint8*)data; - while (bits > 0) { - if (_position == 0) { - _underlying >> _byte; - } - int bitsToRead = qMin(BITS_IN_BYTE - _position, qMin(BITS_IN_BYTE - offset, bits)); - int mask = ((1 << bitsToRead) - 1) << offset; - *dest = (*dest & ~mask) | (((_byte >> _position) << offset) & mask); - _position = (_position + bitsToRead) & LAST_BIT_POSITION; - if ((offset += bitsToRead) == BITS_IN_BYTE) { - dest++; - offset = 0; - } - bits -= bitsToRead; - } - return *this; -} - -void Bitstream::flush() { - if (_position != 0) { - _underlying << _byte; - reset(); - } -} - -void Bitstream::reset() { - _byte = 0; - _position = 0; -} - -Bitstream::WriteMappings Bitstream::getAndResetWriteMappings() { - WriteMappings mappings = { _objectStreamerStreamer.getAndResetTransientOffsets(), - _typeStreamerStreamer.getAndResetTransientOffsets(), - _attributeStreamer.getAndResetTransientOffsets(), - _scriptStringStreamer.getAndResetTransientOffsets(), - _sharedObjectStreamer.getAndResetTransientOffsets() }; - return mappings; -} - -void Bitstream::persistWriteMappings(const WriteMappings& mappings) { - _objectStreamerStreamer.persistTransientOffsets(mappings.objectStreamerOffsets); - _typeStreamerStreamer.persistTransientOffsets(mappings.typeStreamerOffsets); - _attributeStreamer.persistTransientOffsets(mappings.attributeOffsets); - _scriptStringStreamer.persistTransientOffsets(mappings.scriptStringOffsets); - _sharedObjectStreamer.persistTransientOffsets(mappings.sharedObjectOffsets); - - // find out when shared objects are deleted in order to clear their mappings - for (QHash::const_iterator it = mappings.sharedObjectOffsets.constBegin(); - it != mappings.sharedObjectOffsets.constEnd(); it++) { - if (!it.key()) { - continue; - } - connect(it.key().data(), SIGNAL(destroyed(QObject*)), SLOT(clearSharedObject(QObject*))); - QPointer& reference = _sharedObjectReferences[it.key()->getOriginID()]; - if (reference && reference != it.key()) { - // the object has been replaced by a successor, so we can forget about the original - _sharedObjectStreamer.removePersistentID(reference); - reference->disconnect(this); - } - reference = it.key(); - } -} - -void Bitstream::persistAndResetWriteMappings() { - persistWriteMappings(getAndResetWriteMappings()); -} - -Bitstream::ReadMappings Bitstream::getAndResetReadMappings() { - ReadMappings mappings = { _objectStreamerStreamer.getAndResetTransientValues(), - _typeStreamerStreamer.getAndResetTransientValues(), - _attributeStreamer.getAndResetTransientValues(), - _scriptStringStreamer.getAndResetTransientValues(), - _sharedObjectStreamer.getAndResetTransientValues(), - _subdividedObjects }; - _subdividedObjects.clear(); - return mappings; -} - -void Bitstream::persistReadMappings(const ReadMappings& mappings) { - _objectStreamerStreamer.persistTransientValues(mappings.objectStreamerValues); - _typeStreamerStreamer.persistTransientValues(mappings.typeStreamerValues); - _attributeStreamer.persistTransientValues(mappings.attributeValues); - _scriptStringStreamer.persistTransientValues(mappings.scriptStringValues); - _sharedObjectStreamer.persistTransientValues(mappings.sharedObjectValues); - - for (QHash::const_iterator it = mappings.sharedObjectValues.constBegin(); - it != mappings.sharedObjectValues.constEnd(); it++) { - if (!it.value()) { - continue; - } - QPointer& reference = _sharedObjectReferences[it.value()->getRemoteOriginID()]; - if (reference && reference != it.value()) { - // the object has been replaced by a successor, so we can forget about the original - _sharedObjectStreamer.removePersistentValue(reference.data()); - } - reference = it.value(); - _weakSharedObjectHash.remove(it.value()->getRemoteID()); - } - foreach (const SharedObjectPointer& object, mappings.subdividedObjects) { - QPointer& reference = _sharedObjectReferences[object->getRemoteOriginID()]; - if (reference && reference != object) { - int id = _sharedObjectStreamer.removePersistentValue(reference.data()); - if (id != 0) { - _sharedObjectStreamer.insertPersistentValue(id, object); - } - } - reference = object; - } -} - -void Bitstream::persistAndResetReadMappings() { - persistReadMappings(getAndResetReadMappings()); -} - -void Bitstream::copyPersistentMappings(const Bitstream& other) { - _objectStreamerStreamer.copyPersistentMappings(other._objectStreamerStreamer); - _typeStreamerStreamer.copyPersistentMappings(other._typeStreamerStreamer); - _attributeStreamer.copyPersistentMappings(other._attributeStreamer); - _scriptStringStreamer.copyPersistentMappings(other._scriptStringStreamer); - _sharedObjectStreamer.copyPersistentMappings(other._sharedObjectStreamer); - _sharedObjectReferences = other._sharedObjectReferences; - _weakSharedObjectHash = other._weakSharedObjectHash; -} - -void Bitstream::clearPersistentMappings() { - _objectStreamerStreamer.clearPersistentMappings(); - _typeStreamerStreamer.clearPersistentMappings(); - _attributeStreamer.clearPersistentMappings(); - _scriptStringStreamer.clearPersistentMappings(); - _sharedObjectStreamer.clearPersistentMappings(); - _sharedObjectReferences.clear(); - _weakSharedObjectHash.clear(); -} - -void Bitstream::clearSharedObject(int id) { - SharedObjectPointer object = _sharedObjectStreamer.takePersistentValue(id); - if (object) { - _weakSharedObjectHash.remove(object->getRemoteID()); - } -} - -void Bitstream::writeDelta(bool value, bool reference) { - *this << value; -} - -void Bitstream::readDelta(bool& value, bool reference) { - *this >> value; -} - -void Bitstream::writeDelta(const QVariant& value, const QVariant& reference) { - // QVariant only handles == for built-in types; we need to use our custom operators - const TypeStreamer* streamer = getTypeStreamers().value(value.userType()); - if (value.userType() == reference.userType() && (!streamer || streamer->equal(value, reference))) { - *this << false; - return; - } - *this << true; - _typeStreamerStreamer << streamer; - streamer->writeRawDelta(*this, value, reference); -} - -void Bitstream::writeRawDelta(const QVariant& value, const QVariant& reference) { - const TypeStreamer* streamer = getTypeStreamers().value(value.userType()); - _typeStreamerStreamer << streamer; - streamer->writeRawDelta(*this, value, reference); -} - -void Bitstream::readRawDelta(QVariant& value, const QVariant& reference) { - TypeStreamerPointer typeStreamer; - _typeStreamerStreamer >> typeStreamer; - typeStreamer->readRawDelta(*this, value, reference); -} - -void Bitstream::writeRawDelta(const QObject* value, const QObject* reference) { - if (!value) { - _objectStreamerStreamer << NULL; - return; - } - const QMetaObject* metaObject = value->metaObject(); - const ObjectStreamer* streamer = (metaObject == &GenericSharedObject::staticMetaObject) ? - static_cast(value)->getStreamer().data() : getObjectStreamers().value(metaObject); - _objectStreamerStreamer << streamer; - streamer->writeRawDelta(*this, value, reference); -} - -void Bitstream::readRawDelta(QObject*& value, const QObject* reference) { - ObjectStreamerPointer streamer; - _objectStreamerStreamer >> streamer; - value = streamer ? streamer->readRawDelta(*this, reference) : NULL; -} - -void Bitstream::writeRawDelta(const QScriptValue& value, const QScriptValue& reference) { - if (reference.isUndefined() || reference.isNull()) { - *this << value; - - } else if (reference.isBool()) { - if (value.isBool()) { - *this << false; - *this << value.toBool(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isNumber()) { - if (value.isNumber()) { - *this << false; - *this << value.toNumber(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isString()) { - if (value.isString()) { - *this << false; - *this << value.toString(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isVariant()) { - if (value.isVariant()) { - *this << false; - writeRawDelta(value.toVariant(), reference.toVariant()); - - } else { - *this << true; - *this << value; - } - } else if (reference.isQObject()) { - if (value.isQObject()) { - *this << false; - writeRawDelta(value.toQObject(), reference.toQObject()); - - } else { - *this << true; - *this << value; - } - } else if (reference.isQMetaObject()) { - if (value.isQMetaObject()) { - *this << false; - *this << value.toQMetaObject(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isDate()) { - if (value.isDate()) { - *this << false; - *this << value.toDateTime(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isRegExp()) { - if (value.isRegExp()) { - *this << false; - *this << value.toRegExp(); - - } else { - *this << true; - *this << value; - } - } else if (reference.isArray()) { - if (value.isArray()) { - *this << false; - int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); - *this << length; - int referenceLength = reference.property(DependencyManager::get()->getLengthString()).toInt32(); - for (int i = 0; i < length; i++) { - if (i < referenceLength) { - writeDelta(value.property(i), reference.property(i)); - } else { - *this << value.property(i); - } - } - } else { - *this << true; - *this << value; - } - } else if (reference.isObject()) { - if (value.isObject() && !(value.isArray() || value.isRegExp() || value.isDate() || - value.isQMetaObject() || value.isQObject() || value.isVariant())) { - *this << false; - for (QScriptValueIterator it(value); it.hasNext(); ) { - it.next(); - QScriptValue referenceValue = reference.property(it.scriptName()); - if (it.value() != referenceValue) { - *this << it.scriptName(); - writeRawDelta(it.value(), referenceValue); - } - } - for (QScriptValueIterator it(reference); it.hasNext(); ) { - it.next(); - if (!value.property(it.scriptName()).isValid()) { - *this << it.scriptName(); - writeRawDelta(QScriptValue(), it.value()); - } - } - *this << QScriptString(); - - } else { - *this << true; - *this << value; - } - } else { - *this << value; - } -} - -void Bitstream::readRawDelta(QScriptValue& value, const QScriptValue& reference) { - if (reference.isUndefined() || reference.isNull()) { - *this >> value; - - } else if (reference.isBool()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - bool boolValue; - *this >> boolValue; - value = QScriptValue(boolValue); - } - } else if (reference.isNumber()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - qsreal numberValue; - *this >> numberValue; - value = QScriptValue(numberValue); - } - } else if (reference.isString()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - QString stringValue; - *this >> stringValue; - value = QScriptValue(stringValue); - } - } else if (reference.isVariant()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - QVariant variant; - readRawDelta(variant, reference.toVariant()); - value = DependencyManager::get()->getEngine()->newVariant(variant); - } - } else if (reference.isQObject()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - QObject* object; - readRawDelta(object, reference.toQObject()); - value = DependencyManager::get()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); - } - } else if (reference.isQMetaObject()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - const QMetaObject* metaObject; - *this >> metaObject; - value = DependencyManager::get()->getEngine()->newQMetaObject(metaObject); - } - } else if (reference.isDate()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - QDateTime dateTime; - *this >> dateTime; - value = DependencyManager::get()->getEngine()->newDate(dateTime); - } - } else if (reference.isRegExp()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - QRegExp regExp; - *this >> regExp; - value = DependencyManager::get()->getEngine()->newRegExp(regExp); - } - } else if (reference.isArray()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - int length; - *this >> length; - value = DependencyManager::get()->getEngine()->newArray(length); - int referenceLength = reference.property(DependencyManager::get()->getLengthString()).toInt32(); - for (int i = 0; i < length; i++) { - QScriptValue element; - if (i < referenceLength) { - readDelta(element, reference.property(i)); - } else { - *this >> element; - } - value.setProperty(i, element); - } - } - } else if (reference.isObject()) { - bool typeChanged; - *this >> typeChanged; - if (typeChanged) { - *this >> value; - - } else { - // start by shallow-copying the reference - value = DependencyManager::get()->getEngine()->newObject(); - for (QScriptValueIterator it(reference); it.hasNext(); ) { - it.next(); - value.setProperty(it.scriptName(), it.value()); - } - // then apply the requested changes - forever { - QScriptString name; - *this >> name; - if (!name.isValid()) { - break; - } - QScriptValue scriptValue; - readRawDelta(scriptValue, reference.property(name)); - value.setProperty(name, scriptValue); - } - } - } else { - *this >> value; - } -} - -void Bitstream::writeAligned(const QByteArray& data) { - flush(); - _underlying.device()->write(data); -} - -QByteArray Bitstream::readAligned(int bytes) { - reset(); - return _underlying.device()->read(bytes); -} - -Bitstream& Bitstream::operator<<(bool value) { - if (value) { - _byte |= (1 << _position); - } - if (++_position == BITS_IN_BYTE) { - flush(); - } - return *this; -} - -Bitstream& Bitstream::operator>>(bool& value) { - if (_position == 0) { - _underlying >> _byte; - } - value = _byte & (1 << _position); - _position = (_position + 1) & LAST_BIT_POSITION; - return *this; -} - -Bitstream& Bitstream::operator<<(int value) { - return write(&value, 32); -} - -Bitstream& Bitstream::operator>>(int& value) { - qint32 sizedValue; - read(&sizedValue, 32); - value = sizedValue; - return *this; -} - -Bitstream& Bitstream::operator<<(uint value) { - return write(&value, 32); -} - -Bitstream& Bitstream::operator>>(uint& value) { - quint32 sizedValue; - read(&sizedValue, 32); - value = sizedValue; - return *this; -} - -Bitstream& Bitstream::operator<<(qint64 value) { - return write(&value, 64); -} - -Bitstream& Bitstream::operator>>(qint64& value) { - return read(&value, 64); -} - -Bitstream& Bitstream::operator<<(float value) { - return write(&value, 32); -} - -Bitstream& Bitstream::operator>>(float& value) { - return read(&value, 32); -} - -Bitstream& Bitstream::operator<<(double value) { - return write(&value, 64); -} - -Bitstream& Bitstream::operator>>(double& value) { - return read(&value, 64); -} - -Bitstream& Bitstream::operator<<(const glm::vec3& value) { - return *this << value.x << value.y << value.z; -} - -Bitstream& Bitstream::operator>>(glm::vec3& value) { - return *this >> value.x >> value.y >> value.z; -} - -Bitstream& Bitstream::operator<<(const glm::quat& value) { - return *this << value.w << value.x << value.y << value.z; -} - -Bitstream& Bitstream::operator>>(glm::quat& value) { - return *this >> value.w >> value.x >> value.y >> value.z; -} - -Bitstream& Bitstream::operator<<(const QByteArray& string) { - *this << string.size(); - return write(string.constData(), string.size() * BITS_IN_BYTE); -} - -Bitstream& Bitstream::operator>>(QByteArray& string) { - int size; - *this >> size; - string.resize(size); - return read(string.data(), size * BITS_IN_BYTE); -} - -Bitstream& Bitstream::operator<<(const QColor& color) { - return *this << (int)color.rgba(); -} - -Bitstream& Bitstream::operator>>(QColor& color) { - int rgba; - *this >> rgba; - color.setRgba(rgba); - return *this; -} - -Bitstream& Bitstream::operator<<(const QString& string) { - *this << string.size(); - return write(string.constData(), string.size() * sizeof(QChar) * BITS_IN_BYTE); -} - -Bitstream& Bitstream::operator>>(QString& string) { - int size; - *this >> size; - string.resize(size); - return read(string.data(), size * sizeof(QChar) * BITS_IN_BYTE); -} - -Bitstream& Bitstream::operator<<(const QUrl& url) { - return *this << url.toString(); -} - -Bitstream& Bitstream::operator>>(QUrl& url) { - QString string; - *this >> string; - url = string; - return *this; -} - -Bitstream& Bitstream::operator<<(const QDateTime& dateTime) { - return *this << dateTime.toMSecsSinceEpoch(); -} - -Bitstream& Bitstream::operator>>(QDateTime& dateTime) { - qint64 msecsSinceEpoch; - *this >> msecsSinceEpoch; - dateTime = QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch); - return *this; -} - -Bitstream& Bitstream::operator<<(const QRegExp& regExp) { - *this << regExp.pattern(); - Qt::CaseSensitivity caseSensitivity = regExp.caseSensitivity(); - write(&caseSensitivity, 1); - QRegExp::PatternSyntax syntax = regExp.patternSyntax(); - write(&syntax, 3); - return *this << regExp.isMinimal(); -} - -Bitstream& Bitstream::operator>>(QRegExp& regExp) { - QString pattern; - *this >> pattern; - Qt::CaseSensitivity caseSensitivity = (Qt::CaseSensitivity)0; - read(&caseSensitivity, 1); - QRegExp::PatternSyntax syntax = (QRegExp::PatternSyntax)0; - read(&syntax, 3); - regExp = QRegExp(pattern, caseSensitivity, syntax); - bool minimal; - *this >> minimal; - regExp.setMinimal(minimal); - return *this; -} - -Bitstream& Bitstream::operator<<(const QVariant& value) { - if (!value.isValid()) { - _typeStreamerStreamer << NULL; - return *this; - } - const TypeStreamer* streamer = getTypeStreamers().value(value.userType()); - if (streamer) { - streamer->writeVariant(*this, value); - } else { - qWarning() << "Non-streamable type: " << value.typeName() << "\n"; - } - return *this; -} - -Bitstream& Bitstream::operator>>(QVariant& value) { - TypeStreamerPointer streamer; - _typeStreamerStreamer >> streamer; - if (!streamer) { - value = QVariant(); - } else { - value = streamer->readVariant(*this); - } - return *this; -} - -Bitstream& Bitstream::operator<<(const AttributeValue& attributeValue) { - _attributeStreamer << attributeValue.getAttribute(); - if (attributeValue.getAttribute()) { - attributeValue.getAttribute()->write(*this, attributeValue.getValue(), true); - } - return *this; -} - -Bitstream& Bitstream::operator>>(OwnedAttributeValue& attributeValue) { - AttributePointer attribute; - _attributeStreamer >> attribute; - if (attribute) { - void* value = attribute->create(); - attribute->read(*this, value, true); - attributeValue = AttributeValue(attribute, value); - attribute->destroy(value); - - } else { - attributeValue = AttributeValue(); - } - return *this; -} - -Bitstream& Bitstream::operator<<(const GenericValue& value) { - value.getStreamer()->write(*this, value.getValue()); - return *this; -} - -Bitstream& Bitstream::operator>>(GenericValue& value) { - value = GenericValue(); - return *this; -} - -Bitstream& Bitstream::operator<<(const QObject* object) { - if (!object) { - _objectStreamerStreamer << NULL; - return *this; - } - const QMetaObject* metaObject = object->metaObject(); - const ObjectStreamer* streamer = (metaObject == &GenericSharedObject::staticMetaObject) ? - static_cast(object)->getStreamer().data() : getObjectStreamers().value(metaObject); - _objectStreamerStreamer << streamer; - streamer->write(*this, object); - return *this; -} - -Bitstream& Bitstream::operator>>(QObject*& object) { - ObjectStreamerPointer streamer; - _objectStreamerStreamer >> streamer; - object = streamer ? streamer->read(*this) : NULL; - return *this; -} - -Bitstream& Bitstream::operator<<(const QMetaObject* metaObject) { - _objectStreamerStreamer << getObjectStreamers().value(metaObject); - return *this; -} - -Bitstream& Bitstream::operator>>(const QMetaObject*& metaObject) { - ObjectStreamerPointer streamer; - _objectStreamerStreamer >> streamer; - metaObject = streamer->getMetaObject(); - return *this; -} - -Bitstream& Bitstream::operator<<(const ObjectStreamer* streamer) { - _objectStreamerStreamer << streamer; - return *this; -} - -Bitstream& Bitstream::operator>>(const ObjectStreamer*& streamer) { - ObjectStreamerPointer objectStreamer; - _objectStreamerStreamer >> objectStreamer; - streamer = objectStreamer.data(); - return *this; -} - -Bitstream& Bitstream::operator>>(ObjectStreamerPointer& streamer) { - _objectStreamerStreamer >> streamer; - return *this; -} - -Bitstream& Bitstream::operator<<(const TypeStreamer* streamer) { - _typeStreamerStreamer << streamer; - return *this; -} - -Bitstream& Bitstream::operator>>(const TypeStreamer*& streamer) { - TypeStreamerPointer typeStreamer; - _typeStreamerStreamer >> typeStreamer; - streamer = typeStreamer.data(); - return *this; -} - -Bitstream& Bitstream::operator>>(TypeStreamerPointer& streamer) { - _typeStreamerStreamer >> streamer; - return *this; -} - -Bitstream& Bitstream::operator<<(const AttributePointer& attribute) { - _attributeStreamer << attribute; - return *this; -} - -Bitstream& Bitstream::operator>>(AttributePointer& attribute) { - _attributeStreamer >> attribute; - return *this; -} - -Bitstream& Bitstream::operator<<(const QScriptString& string) { - _scriptStringStreamer << string; - return *this; -} - -Bitstream& Bitstream::operator>>(QScriptString& string) { - _scriptStringStreamer >> string; - return *this; -} - -enum ScriptValueType { - INVALID_SCRIPT_VALUE, - UNDEFINED_SCRIPT_VALUE, - NULL_SCRIPT_VALUE, - BOOL_SCRIPT_VALUE, - NUMBER_SCRIPT_VALUE, - STRING_SCRIPT_VALUE, - VARIANT_SCRIPT_VALUE, - QOBJECT_SCRIPT_VALUE, - QMETAOBJECT_SCRIPT_VALUE, - DATE_SCRIPT_VALUE, - REGEXP_SCRIPT_VALUE, - ARRAY_SCRIPT_VALUE, - OBJECT_SCRIPT_VALUE -}; - -const int SCRIPT_VALUE_BITS = 4; - -static void writeScriptValueType(Bitstream& out, ScriptValueType type) { - out.write(&type, SCRIPT_VALUE_BITS); -} - -static ScriptValueType readScriptValueType(Bitstream& in) { - ScriptValueType type = (ScriptValueType)0; - in.read(&type, SCRIPT_VALUE_BITS); - return type; -} - -Bitstream& Bitstream::operator<<(const QScriptValue& value) { - if (value.isUndefined()) { - writeScriptValueType(*this, UNDEFINED_SCRIPT_VALUE); - - } else if (value.isNull()) { - writeScriptValueType(*this, NULL_SCRIPT_VALUE); - - } else if (value.isBool()) { - writeScriptValueType(*this, BOOL_SCRIPT_VALUE); - *this << value.toBool(); - - } else if (value.isNumber()) { - writeScriptValueType(*this, NUMBER_SCRIPT_VALUE); - *this << value.toNumber(); - - } else if (value.isString()) { - writeScriptValueType(*this, STRING_SCRIPT_VALUE); - *this << value.toString(); - - } else if (value.isVariant()) { - writeScriptValueType(*this, VARIANT_SCRIPT_VALUE); - *this << value.toVariant(); - - } else if (value.isQObject()) { - writeScriptValueType(*this, QOBJECT_SCRIPT_VALUE); - *this << value.toQObject(); - - } else if (value.isQMetaObject()) { - writeScriptValueType(*this, QMETAOBJECT_SCRIPT_VALUE); - *this << value.toQMetaObject(); - - } else if (value.isDate()) { - writeScriptValueType(*this, DATE_SCRIPT_VALUE); - *this << value.toDateTime(); - - } else if (value.isRegExp()) { - writeScriptValueType(*this, REGEXP_SCRIPT_VALUE); - *this << value.toRegExp(); - - } else if (value.isArray()) { - writeScriptValueType(*this, ARRAY_SCRIPT_VALUE); - int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); - *this << length; - for (int i = 0; i < length; i++) { - *this << value.property(i); - } - } else if (value.isObject()) { - writeScriptValueType(*this, OBJECT_SCRIPT_VALUE); - for (QScriptValueIterator it(value); it.hasNext(); ) { - it.next(); - *this << it.scriptName(); - *this << it.value(); - } - *this << QScriptString(); - - } else { - writeScriptValueType(*this, INVALID_SCRIPT_VALUE); - } - return *this; -} - -Bitstream& Bitstream::operator>>(QScriptValue& value) { - switch (readScriptValueType(*this)) { - case UNDEFINED_SCRIPT_VALUE: - value = QScriptValue(QScriptValue::UndefinedValue); - break; - - case NULL_SCRIPT_VALUE: - value = QScriptValue(QScriptValue::NullValue); - break; - - case BOOL_SCRIPT_VALUE: { - bool boolValue; - *this >> boolValue; - value = QScriptValue(boolValue); - break; - } - case NUMBER_SCRIPT_VALUE: { - qsreal numberValue; - *this >> numberValue; - value = QScriptValue(numberValue); - break; - } - case STRING_SCRIPT_VALUE: { - QString stringValue; - *this >> stringValue; - value = QScriptValue(stringValue); - break; - } - case VARIANT_SCRIPT_VALUE: { - QVariant variantValue; - *this >> variantValue; - value = DependencyManager::get()->getEngine()->newVariant(variantValue); - break; - } - case QOBJECT_SCRIPT_VALUE: { - QObject* object; - *this >> object; - DependencyManager::get()->getEngine()->newQObject(object, QScriptEngine::ScriptOwnership); - break; - } - case QMETAOBJECT_SCRIPT_VALUE: { - const QMetaObject* metaObject; - *this >> metaObject; - DependencyManager::get()->getEngine()->newQMetaObject(metaObject); - break; - } - case DATE_SCRIPT_VALUE: { - QDateTime dateTime; - *this >> dateTime; - value = DependencyManager::get()->getEngine()->newDate(dateTime); - break; - } - case REGEXP_SCRIPT_VALUE: { - QRegExp regExp; - *this >> regExp; - value = DependencyManager::get()->getEngine()->newRegExp(regExp); - break; - } - case ARRAY_SCRIPT_VALUE: { - int length; - *this >> length; - value = DependencyManager::get()->getEngine()->newArray(length); - for (int i = 0; i < length; i++) { - QScriptValue element; - *this >> element; - value.setProperty(i, element); - } - break; - } - case OBJECT_SCRIPT_VALUE: { - value = DependencyManager::get()->getEngine()->newObject(); - forever { - QScriptString name; - *this >> name; - if (!name.isValid()) { - break; - } - QScriptValue scriptValue; - *this >> scriptValue; - value.setProperty(name, scriptValue); - } - break; - } - default: - value = QScriptValue(); - break; - } - return *this; -} - -Bitstream& Bitstream::operator<<(const SharedObjectPointer& object) { - _sharedObjectStreamer << object; - return *this; -} - -Bitstream& Bitstream::operator>>(SharedObjectPointer& object) { - _sharedObjectStreamer >> object; - return *this; -} - -Bitstream& Bitstream::operator<(const ObjectStreamer* streamer) { - if (!streamer) { - return *this << QByteArray(); - } - const char* name = streamer->getName(); - *this << QByteArray::fromRawData(name, strlen(name)); - if (_metadataType != NO_METADATA) { - streamer->writeMetadata(*this, _metadataType == FULL_METADATA); - } - return *this; -} - -static MappedObjectStreamer* createMappedObjectStreamer(const QMetaObject* metaObject, - const QVector& properties) { - for (const QMetaObject* super = metaObject; super; super = super->superClass()) { - if (super == &SharedObject::staticMetaObject) { - return new SharedObjectStreamer(metaObject, properties); - } - } - return new MappedObjectStreamer(metaObject, properties); -} - -Bitstream& Bitstream::operator>(ObjectStreamerPointer& streamer) { - QByteArray className; - *this >> className; - if (className.isEmpty()) { - streamer = ObjectStreamerPointer(); - return *this; - } - const QMetaObject* metaObject = _metaObjectSubstitutions.value(className); - if (!metaObject) { - metaObject = getMetaObjects().value(className); - } - // start out with the streamer for the named class, if any - if (metaObject) { - streamer = getObjectStreamers().value(metaObject)->getSelf(); - } else { - streamer = ObjectStreamerPointer(); - } - if (_metadataType == NO_METADATA) { - if (!metaObject) { - throw BitstreamException(QString("Unknown class name: ") + className); - } - return *this; - } - if (_genericsMode == ALL_GENERICS) { - streamer = readGenericObjectStreamer(className); - return *this; - } - if (!metaObject && _genericsMode == FALLBACK_GENERICS) { - streamer = readGenericObjectStreamer(className); - return *this; - } - int propertyCount; - *this >> propertyCount; - QVector properties(propertyCount); - for (int i = 0; i < propertyCount; i++) { - TypeStreamerPointer typeStreamer; - *this >> typeStreamer; - QMetaProperty property = QMetaProperty(); - if (_metadataType == FULL_METADATA) { - QByteArray propertyName; - *this >> propertyName; - if (metaObject) { - property = metaObject->property(metaObject->indexOfProperty(propertyName)); - } - } - properties[i] = StreamerPropertyPair(typeStreamer, property); - } - // for hash metadata, check the names/types of the properties as well as the name hash against our own class - if (_metadataType == HASH_METADATA) { - QCryptographicHash hash(QCryptographicHash::Md5); - bool matches = true; - if (metaObject) { - const QVector& localProperties = streamer->getProperties(); - if (localProperties.size() == properties.size()) { - for (int i = 0; i < localProperties.size(); i++) { - const StreamerPropertyPair& localProperty = localProperties.at(i); - if (localProperty.first != properties.at(i).first) { - matches = false; - break; - } - hash.addData(localProperty.second.name(), strlen(localProperty.second.name()) + 1); - } - } else { - matches = false; - } - } - QByteArray localHashResult = hash.result(); - QByteArray remoteHashResult(localHashResult.size(), 0); - read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE); - if (metaObject && matches && localHashResult == remoteHashResult) { - return *this; - } - } else if (metaObject) { - const QVector& localProperties = streamer->getProperties(); - if (localProperties.size() != properties.size()) { - streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); - return *this; - } - for (int i = 0; i < localProperties.size(); i++) { - const StreamerPropertyPair& property = properties.at(i); - const StreamerPropertyPair& localProperty = localProperties.at(i); - if (property.first != localProperty.first || - property.second.propertyIndex() != localProperty.second.propertyIndex()) { - streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); - return *this; - } - } - return *this; - } - streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); - return *this; -} - -Bitstream& Bitstream::operator<(const TypeStreamer* streamer) { - if (!streamer) { - *this << QByteArray(); - return *this; - } - const char* typeName = streamer->getName(); - *this << QByteArray::fromRawData(typeName, strlen(typeName)); - if (_metadataType != NO_METADATA) { - *this << (int)streamer->getCategory(); - streamer->writeMetadata(*this, _metadataType == FULL_METADATA); - } - return *this; -} - -Bitstream& Bitstream::operator>(TypeStreamerPointer& streamer) { - QByteArray typeName; - *this >> typeName; - if (typeName.isEmpty()) { - streamer = TypeStreamerPointer(); - return *this; - } - const TypeStreamer* baseStreamer = _typeStreamerSubstitutions.value(typeName); - if (!baseStreamer) { - baseStreamer = getTypeStreamers().value(QMetaType::type(typeName.constData())); - if (!baseStreamer) { - baseStreamer = getEnumStreamersByName().value(typeName); - } - } - // start out with the base, if any - if (baseStreamer) { - streamer = baseStreamer->getSelf(); - } else { - streamer = TypeStreamerPointer(); - } - if (_metadataType == NO_METADATA) { - if (!baseStreamer) { - throw BitstreamException(QString("Unknown type name: ") + typeName); - } - return *this; - } - int category; - *this >> category; - if (category == TypeStreamer::SIMPLE_CATEGORY) { - if (!streamer) { - throw BitstreamException(QString("Unknown type name: ") + typeName); - } - return *this; - } - if (_genericsMode == ALL_GENERICS) { - streamer = readGenericTypeStreamer(typeName, category); - return *this; - } - if (!baseStreamer) { - if (_genericsMode == FALLBACK_GENERICS) { - streamer = readGenericTypeStreamer(typeName, category); - return *this; - } - baseStreamer = getInvalidTypeStreamer(); - } - switch (category) { - case TypeStreamer::ENUM_CATEGORY: { - if (_metadataType == FULL_METADATA) { - int keyCount; - *this >> keyCount; - QMetaEnum metaEnum = baseStreamer->getMetaEnum(); - QHash mappings; - bool matches = (keyCount == metaEnum.keyCount()); - int highestValue = 0; - for (int i = 0; i < keyCount; i++) { - QByteArray key; - int value; - *this >> key >> value; - highestValue = qMax(value, highestValue); - int localValue = metaEnum.keyToValue(key); - if (localValue != -1) { - mappings.insert(value, localValue); - } - matches &= (value == localValue); - } - if (!matches) { - streamer = TypeStreamerPointer(new MappedEnumTypeStreamer(baseStreamer, - getBitsForHighestValue(highestValue), mappings)); - } - } else { - int bits; - *this >> bits; - QCryptographicHash hash(QCryptographicHash::Md5); - if (baseStreamer->getCategory() == TypeStreamer::ENUM_CATEGORY) { - QMetaEnum metaEnum = baseStreamer->getMetaEnum(); - for (int i = 0; i < metaEnum.keyCount(); i++) { - hash.addData(metaEnum.key(i), strlen(metaEnum.key(i)) + 1); - qint32 value = metaEnum.value(i); - hash.addData((const char*)&value, sizeof(qint32)); - } - } - QByteArray localHashResult = hash.result(); - QByteArray remoteHashResult(localHashResult.size(), 0); - read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE); - if (localHashResult != remoteHashResult) { - streamer = TypeStreamerPointer(new MappedEnumTypeStreamer(baseStreamer, bits, QHash())); - } - } - return *this; - } - case TypeStreamer::LIST_CATEGORY: - case TypeStreamer::SET_CATEGORY: { - TypeStreamerPointer valueStreamer; - *this >> valueStreamer; - if (!(baseStreamer->getCategory() == category && valueStreamer == baseStreamer->getValueStreamer())) { - streamer = TypeStreamerPointer(category == TypeStreamer::LIST_CATEGORY ? - new MappedListTypeStreamer(baseStreamer, valueStreamer) : - new MappedSetTypeStreamer(baseStreamer, valueStreamer)); - } - return *this; - } - case TypeStreamer::MAP_CATEGORY: { - TypeStreamerPointer keyStreamer, valueStreamer; - *this >> keyStreamer >> valueStreamer; - if (!(baseStreamer->getCategory() == TypeStreamer::MAP_CATEGORY && - keyStreamer == baseStreamer->getKeyStreamer() && valueStreamer == baseStreamer->getValueStreamer())) { - streamer = TypeStreamerPointer(new MappedMapTypeStreamer(baseStreamer, keyStreamer, valueStreamer)); - } - return *this; - } - } - // streamable type - int fieldCount; - *this >> fieldCount; - QVector fields(fieldCount); - for (int i = 0; i < fieldCount; i++) { - TypeStreamerPointer typeStreamer; - *this >> typeStreamer; - int index = -1; - if (_metadataType == FULL_METADATA) { - QByteArray fieldName; - *this >> fieldName; - index = baseStreamer->getFieldIndex(fieldName); - } - fields[i] = StreamerIndexPair(typeStreamer, index); - } - // for hash metadata, check the names/types of the fields as well as the name hash against our own class - if (_metadataType == HASH_METADATA) { - QCryptographicHash hash(QCryptographicHash::Md5); - bool matches = true; - const QVector& localFields = baseStreamer->getMetaFields(); - if (fieldCount != localFields.size()) { - matches = false; - - } else { - if (fieldCount == 0) { - return *this; - } - for (int i = 0; i < fieldCount; i++) { - const MetaField& localField = localFields.at(i); - if (fields.at(i).first != localField.getStreamer()) { - matches = false; - break; - } - hash.addData(localField.getName().constData(), localField.getName().size() + 1); - } - } - QByteArray localHashResult = hash.result(); - QByteArray remoteHashResult(localHashResult.size(), 0); - read(remoteHashResult.data(), remoteHashResult.size() * BITS_IN_BYTE); - if (matches && localHashResult == remoteHashResult) { - // since everything is the same, we can use the default streamer - return *this; - } - } - // if all fields are the same type and in the right order, we can use the (more efficient) default streamer - const QVector& localFields = baseStreamer->getMetaFields(); - if (fieldCount != localFields.size()) { - streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields)); - return *this; - } - for (int i = 0; i < fieldCount; i++) { - const StreamerIndexPair& field = fields.at(i); - if (field.first != localFields.at(i).getStreamer() || field.second != i) { - streamer = TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields)); - return *this; - } - } - return *this; -} - -Bitstream& Bitstream::operator<(const AttributePointer& attribute) { - return *this << (QObject*)attribute.data(); -} - -Bitstream& Bitstream::operator>(AttributePointer& attribute) { - QObject* object; - *this >> object; - attribute = AttributeRegistry::getInstance()->registerAttribute(static_cast(object)); - return *this; -} - -const QString INVALID_STRING("%INVALID%"); - -Bitstream& Bitstream::operator<(const QScriptString& string) { - return *this << (string.isValid() ? string.toString() : INVALID_STRING); -} - -Bitstream& Bitstream::operator>(QScriptString& string) { - QString rawString; - *this >> rawString; - string = (rawString == INVALID_STRING) ? QScriptString() : - DependencyManager::get()->getEngine()->toStringHandle(rawString); - return *this; -} - -Bitstream& Bitstream::operator<(const SharedObjectPointer& object) { - if (!object) { - return *this << (int)0; - } - *this << object->getID(); - *this << object->getOriginID(); - QPointer reference = _sharedObjectReferences.value(object->getOriginID()); - if (reference) { - *this << true; - writeRawDelta((const QObject*)object.data(), (const QObject*)reference.data()); - } else { - *this << false; - *this << (QObject*)object.data(); - } - return *this; -} - -Bitstream& Bitstream::operator>(SharedObjectPointer& object) { - int id; - *this >> id; - if (id == 0) { - object = SharedObjectPointer(); - return *this; - } - int originID; - *this >> originID; - bool delta; - *this >> delta; - QPointer reference = _sharedObjectReferences.value(originID); - QPointer& pointer = _weakSharedObjectHash[id]; - if (pointer) { - ObjectStreamerPointer objectStreamer; - _objectStreamerStreamer >> objectStreamer; - if (delta) { - if (!reference) { - throw BitstreamException(QString("Delta without reference [id=%1, originID=%2]").arg(id).arg(originID)); - } - objectStreamer->readRawDelta(*this, reference.data(), pointer.data()); - } else { - objectStreamer->read(*this, pointer.data()); - } - } else { - QObject* rawObject; - if (delta) { - if (!reference) { - throw BitstreamException(QString("Delta without reference [id=%1, originID=%2]").arg(id).arg(originID)); - } - readRawDelta(rawObject, (const QObject*)reference.data()); - } else { - *this >> rawObject; - } - pointer = static_cast(rawObject); - if (pointer) { - if (reference) { - pointer->setOriginID(reference->getOriginID()); - } - pointer->setRemoteID(id); - pointer->setRemoteOriginID(originID); - } else { - qDebug() << "Null object" << pointer << reference << id; - } - } - object = static_cast(pointer.data()); - return *this; -} - -void Bitstream::clearSharedObject(QObject* object) { - SharedObject* sharedObject = static_cast(object); - _sharedObjectReferences.remove(sharedObject->getOriginID()); - int id = _sharedObjectStreamer.takePersistentID(sharedObject); - if (id != 0) { - emit sharedObjectCleared(id); - } -} - -const int MD5_HASH_SIZE = 16; - -ObjectStreamerPointer Bitstream::readGenericObjectStreamer(const QByteArray& name) { - int propertyCount; - *this >> propertyCount; - QVector properties(propertyCount); - QByteArray hash; - if (propertyCount > 0) { - for (int i = 0; i < propertyCount; i++) { - TypeStreamerPointer streamer; - *this >> streamer; - QByteArray name; - if (_metadataType == FULL_METADATA) { - *this >> name; - } - properties[i] = StreamerNamePair(streamer, name); - } - if (_metadataType == HASH_METADATA) { - hash.resize(MD5_HASH_SIZE); - read(hash.data(), hash.size() * BITS_IN_BYTE); - } - } - ObjectStreamerPointer streamer = ObjectStreamerPointer(new GenericObjectStreamer(name, properties, hash)); - static_cast(streamer.data())->_weakSelf = streamer; - return streamer; -} - -TypeStreamerPointer Bitstream::readGenericTypeStreamer(const QByteArray& name, int category) { - TypeStreamerPointer streamer; - switch (category) { - case TypeStreamer::ENUM_CATEGORY: { - QVector values; - int bits; - QByteArray hash; - if (_metadataType == FULL_METADATA) { - int keyCount; - *this >> keyCount; - values.resize(keyCount); - int highestValue = 0; - for (int i = 0; i < keyCount; i++) { - QByteArray name; - int value; - *this >> name >> value; - values[i] = NameIntPair(name, value); - highestValue = qMax(highestValue, value); - } - bits = getBitsForHighestValue(highestValue); - - } else { - *this >> bits; - hash.resize(MD5_HASH_SIZE); - read(hash.data(), hash.size() * BITS_IN_BYTE); - } - streamer = TypeStreamerPointer(new GenericEnumTypeStreamer(name, values, bits, hash)); - break; - } - case TypeStreamer::STREAMABLE_CATEGORY: { - int fieldCount; - *this >> fieldCount; - QVector fields(fieldCount); - QByteArray hash; - if (fieldCount == 0) { - streamer = TypeStreamerPointer(new GenericStreamableTypeStreamer(name, fields, hash)); - break; - } - for (int i = 0; i < fieldCount; i++) { - TypeStreamerPointer streamer; - *this >> streamer; - QByteArray name; - if (_metadataType == FULL_METADATA) { - *this >> name; - } - fields[i] = StreamerNamePair(streamer, name); - } - if (_metadataType == HASH_METADATA) { - hash.resize(MD5_HASH_SIZE); - read(hash.data(), hash.size() * BITS_IN_BYTE); - } - streamer = TypeStreamerPointer(new GenericStreamableTypeStreamer(name, fields, hash)); - break; - } - case TypeStreamer::LIST_CATEGORY: - case TypeStreamer::SET_CATEGORY: { - TypeStreamerPointer valueStreamer; - *this >> valueStreamer; - streamer = TypeStreamerPointer(category == TypeStreamer::LIST_CATEGORY ? - new GenericListTypeStreamer(name, valueStreamer) : new GenericSetTypeStreamer(name, valueStreamer)); - break; - } - case TypeStreamer::MAP_CATEGORY: { - TypeStreamerPointer keyStreamer, valueStreamer; - *this >> keyStreamer >> valueStreamer; - streamer = TypeStreamerPointer(new GenericMapTypeStreamer(name, keyStreamer, valueStreamer)); - break; - } - } - static_cast(streamer.data())->_weakSelf = streamer; - return streamer; -} - -QHash& Bitstream::getMetaObjects() { - static QHash metaObjects; - return metaObjects; -} - -QMultiHash& Bitstream::getMetaObjectSubClasses() { - static QMultiHash metaObjectSubClasses; - return metaObjectSubClasses; -} - -const QHash& Bitstream::getObjectStreamers() { - static QHash objectStreamers = createObjectStreamers(); - return objectStreamers; -} - -QHash Bitstream::createObjectStreamers() { - QHash objectStreamers; - foreach (const QMetaObject* metaObject, getMetaObjects()) { - QVector properties; - for (int i = 0; i < metaObject->propertyCount(); i++) { - QMetaProperty property = metaObject->property(i); - if (!property.isStored()) { - continue; - } - const TypeStreamer* streamer; - if (property.isEnumType()) { - QMetaEnum metaEnum = property.enumerator(); - streamer = getEnumStreamers().value(ScopeNamePair( - QByteArray::fromRawData(metaEnum.scope(), strlen(metaEnum.scope())), - QByteArray::fromRawData(metaEnum.name(), strlen(metaEnum.name())))); - } else { - streamer = getTypeStreamers().value(property.userType()); - } - if (streamer) { - properties.append(StreamerPropertyPair(streamer->getSelf(), property)); - } - } - ObjectStreamerPointer streamer = ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties)); - streamer->_self = streamer; - objectStreamers.insert(metaObject, streamer.data()); - } - return objectStreamers; -} - -QHash& Bitstream::getTypeStreamers() { - static QHash typeStreamers; - return typeStreamers; -} - -const QHash& Bitstream::getEnumStreamers() { - static QHash enumStreamers = createEnumStreamers(); - return enumStreamers; -} - -static QByteArray getEnumName(const char* scope, const char* name) { - return QByteArray(scope) + "::" + name; -} - -QHash Bitstream::createEnumStreamers() { - QHash enumStreamers; - foreach (const QMetaObject* metaObject, getMetaObjects()) { - for (int i = 0; i < metaObject->enumeratorCount(); i++) { - QMetaEnum metaEnum = metaObject->enumerator(i); - const TypeStreamer*& streamer = enumStreamers[ScopeNamePair(metaEnum.scope(), metaEnum.name())]; - if (!streamer) { - // look for a streamer registered by name - streamer = getTypeStreamers().value(QMetaType::type(getEnumName(metaEnum.scope(), metaEnum.name()))); - if (!streamer) { - streamer = new EnumTypeStreamer(metaEnum); - } - } - } - } - return enumStreamers; -} - -const QHash& Bitstream::getEnumStreamersByName() { - static QHash enumStreamersByName = createEnumStreamersByName(); - return enumStreamersByName; -} - -QHash Bitstream::createEnumStreamersByName() { - QHash enumStreamersByName; - foreach (const TypeStreamer* streamer, getEnumStreamers()) { - enumStreamersByName.insert(streamer->getName(), streamer); - } - return enumStreamersByName; -} - -const TypeStreamer* Bitstream::getInvalidTypeStreamer() { - const TypeStreamer* streamer = createInvalidTypeStreamer(); - return streamer; -} - -const TypeStreamer* Bitstream::createInvalidTypeStreamer() { - TypeStreamer* streamer = new TypeStreamer(); - streamer->_type = QMetaType::UnknownType; - streamer->_self = TypeStreamerPointer(streamer); - return streamer; -} - -BitstreamException::BitstreamException(const QString& description) : - _description(description) { -} - -QJsonValue JSONWriter::getData(bool value) { - return value; -} - -QJsonValue JSONWriter::getData(int value) { - return value; -} - -QJsonValue JSONWriter::getData(uint value) { - return (int)value; -} - -QJsonValue JSONWriter::getData(float value) { - return (double)value; -} - -QJsonValue JSONWriter::getData(const QByteArray& value) { - return QString(value.toPercentEncoding()); -} - -QJsonValue JSONWriter::getData(const QColor& value) { - return value.name(); -} - -QJsonValue JSONWriter::getData(const QScriptValue& value) { - QJsonObject object; - if (value.isUndefined()) { - object.insert("type", QString("UNDEFINED")); - - } else if (value.isNull()) { - object.insert("type", QString("NULL")); - - } else if (value.isBool()) { - object.insert("type", QString("BOOL")); - object.insert("value", value.toBool()); - - } else if (value.isNumber()) { - object.insert("type", QString("NUMBER")); - object.insert("value", value.toNumber()); - - } else if (value.isString()) { - object.insert("type", QString("STRING")); - object.insert("value", value.toString()); - - } else if (value.isVariant()) { - object.insert("type", QString("VARIANT")); - object.insert("value", getData(value.toVariant())); - - } else if (value.isQObject()) { - object.insert("type", QString("QOBJECT")); - object.insert("value", getData(value.toQObject())); - - } else if (value.isQMetaObject()) { - object.insert("type", QString("QMETAOBJECT")); - object.insert("value", getData(value.toQMetaObject())); - - } else if (value.isDate()) { - object.insert("type", QString("DATE")); - object.insert("value", getData(value.toDateTime())); - - } else if (value.isRegExp()) { - object.insert("type", QString("REGEXP")); - object.insert("value", getData(value.toRegExp())); - - } else if (value.isArray()) { - object.insert("type", QString("ARRAY")); - QJsonArray array; - int length = value.property(DependencyManager::get()->getLengthString()).toInt32(); - for (int i = 0; i < length; i++) { - array.append(getData(value.property(i))); - } - object.insert("value", array); - - } else if (value.isObject()) { - object.insert("type", QString("OBJECT")); - QJsonObject valueObject; - for (QScriptValueIterator it(value); it.hasNext(); ) { - it.next(); - valueObject.insert(it.name(), getData(it.value())); - } - object.insert("value", valueObject); - - } else { - object.insert("type", QString("INVALID")); - } - return object; -} - -QJsonValue JSONWriter::getData(const QString& value) { - return value; -} - -QJsonValue JSONWriter::getData(const QUrl& value) { - return value.toString(); -} - -QJsonValue JSONWriter::getData(const QDateTime& value) { - return (qsreal)value.toMSecsSinceEpoch(); -} - -QJsonValue JSONWriter::getData(const QRegExp& value) { - QJsonObject object; - object.insert("pattern", value.pattern()); - object.insert("caseSensitivity", (int)value.caseSensitivity()); - object.insert("patternSyntax", (int)value.patternSyntax()); - object.insert("minimal", value.isMinimal()); - return object; -} - -QJsonValue JSONWriter::getData(const glm::vec3& value) { - QJsonArray array; - array.append(value.x); - array.append(value.y); - array.append(value.z); - return array; -} - -QJsonValue JSONWriter::getData(const glm::quat& value) { - QJsonArray array; - array.append(value.x); - array.append(value.y); - array.append(value.z); - array.append(value.w); - return array; -} - -QJsonValue JSONWriter::getData(const QMetaObject* metaObject) { - if (!metaObject) { - return QJsonValue(); - } - const ObjectStreamer* streamer = Bitstream::getObjectStreamers().value(metaObject); - addObjectStreamer(streamer); - return QString(streamer->getName()); -} - -QJsonValue JSONWriter::getData(const QVariant& value) { - if (!value.isValid()) { - return QJsonValue(); - } - const TypeStreamer* streamer = Bitstream::getTypeStreamers().value(value.userType()); - if (streamer) { - return streamer->getJSONVariantData(*this, value); - } else { - qWarning() << "Non-streamable type:" << value.typeName(); - return QJsonValue(); - } -} - -QJsonValue JSONWriter::getData(const SharedObjectPointer& object) { - if (object) { - addSharedObject(object); - return object->getID(); - } else { - return 0; - } -} - -QJsonValue JSONWriter::getData(const QObject* object) { - if (!object) { - return QJsonValue(); - } - const QMetaObject* metaObject = object->metaObject(); - const ObjectStreamer* streamer = (metaObject == &GenericSharedObject::staticMetaObject) ? - static_cast(object)->getStreamer().data() : - Bitstream::getObjectStreamers().value(metaObject); - return streamer->getJSONData(*this, object); -} - -QJsonValue JSONWriter::getData(const GenericValue& value) { - return value.getStreamer()->getJSONData(*this, value.getValue()); -} - -void JSONWriter::addTypeStreamer(const TypeStreamer* streamer) { - if (!_typeStreamerNames.contains(streamer->getName())) { - _typeStreamerNames.insert(streamer->getName()); - - QJsonValue metadata = streamer->getJSONMetadata(*this); - if (!metadata.isNull()) { - _typeStreamers.append(metadata); - } - } -} - -void JSONWriter::addObjectStreamer(const ObjectStreamer* streamer) { - if (!_objectStreamerNames.contains(streamer->getName())) { - _objectStreamerNames.insert(streamer->getName()); - _objectStreamers.append(streamer->getJSONMetadata(*this)); - } -} - -void JSONWriter::addSharedObject(const SharedObjectPointer& object) { - if (!_sharedObjectIDs.contains(object->getID())) { - _sharedObjectIDs.insert(object->getID()); - - QJsonObject sharedObject; - sharedObject.insert("id", object->getID()); - sharedObject.insert("data", getData(static_cast(object.data()))); - _sharedObjects.append(sharedObject); - } -} - -QJsonDocument JSONWriter::getDocument() const { - QJsonObject top; - top.insert("contents", _contents); - top.insert("objects", _sharedObjects); - top.insert("classes", _objectStreamers); - top.insert("types", _typeStreamers); - return QJsonDocument(top); -} - -JSONReader::JSONReader(const QJsonDocument& document, Bitstream::GenericsMode genericsMode) { - // create and map the type streamers in order - QJsonObject top = document.object(); - foreach (const QJsonValue& element, top.value("types").toArray()) { - QJsonObject type = element.toObject(); - QString name = type.value("name").toString(); - QByteArray latinName = name.toLatin1(); - const TypeStreamer* baseStreamer = Bitstream::getTypeStreamers().value(QMetaType::type(latinName)); - if (!baseStreamer) { - baseStreamer = Bitstream::getEnumStreamersByName().value(latinName); - } - if (!baseStreamer && genericsMode == Bitstream::NO_GENERICS) { - continue; // no built-in type and no generics allowed; we give up - } - QString category = type.value("category").toString(); - if (!baseStreamer || genericsMode == Bitstream::ALL_GENERICS) { - // create a generic streamer - TypeStreamerPointer streamer; - if (category == "ENUM") { - QVector values; - int highestValue = 0; - foreach (const QJsonValue& value, type.value("values").toArray()) { - QJsonObject object = value.toObject(); - int intValue = object.value("value").toInt(); - highestValue = qMax(intValue, highestValue); - values.append(NameIntPair(object.value("key").toString().toLatin1(), intValue)); - } - streamer = TypeStreamerPointer(new GenericEnumTypeStreamer(latinName, - values, getBitsForHighestValue(highestValue), QByteArray())); - - } else if (category == "STREAMABLE") { - QVector fields; - foreach (const QJsonValue& field, type.value("fields").toArray()) { - QJsonObject object = field.toObject(); - fields.append(StreamerNamePair(getTypeStreamer(object.value("type").toString()), - object.value("name").toString().toLatin1())); - } - streamer = TypeStreamerPointer(new GenericStreamableTypeStreamer(latinName, - fields, QByteArray())); - - } else if (category == "LIST") { - streamer = TypeStreamerPointer(new GenericListTypeStreamer(latinName, - getTypeStreamer(type.value("valueType").toString()))); - - } else if (category == "SET") { - streamer = TypeStreamerPointer(new GenericSetTypeStreamer(latinName, - getTypeStreamer(type.value("valueType").toString()))); - - } else if (category == "MAP") { - streamer = TypeStreamerPointer(new GenericMapTypeStreamer(latinName, - getTypeStreamer(type.value("keyType").toString()), - getTypeStreamer(type.value("valueType").toString()))); - } - _typeStreamers.insert(name, streamer); - static_cast(streamer.data())->_weakSelf = streamer; - continue; - } - // create a mapped streamer, determining along the way whether it matches our base - if (category == "ENUM") { - QHash mappings; - int highestValue = 0; - QMetaEnum metaEnum = baseStreamer->getMetaEnum(); - QJsonArray array = type.value("values").toArray(); - bool matches = (array.size() == metaEnum.keyCount()); - foreach (const QJsonValue& value, array) { - QJsonObject object = value.toObject(); - int intValue = object.value("value").toInt(); - highestValue = qMax(intValue, highestValue); - int mapping = metaEnum.keyToValue(object.value("key").toString().toLatin1()); - if (mapping != -1) { - mappings.insert(intValue, mapping); - } - matches &= (intValue == mapping); - } - // if everything matches our built-in enum, we can use that, which will be faster - if (matches) { - _typeStreamers.insert(name, baseStreamer->getSelf()); - } else { - _typeStreamers.insert(name, TypeStreamerPointer(new MappedEnumTypeStreamer(baseStreamer, - getBitsForHighestValue(highestValue), mappings))); - } - } else if (category == "STREAMABLE") { - QVector fields; - QJsonArray array = type.value("fields").toArray(); - const QVector& metaFields = baseStreamer->getMetaFields(); - bool matches = (array.size() == metaFields.size()); - for (int i = 0; i < array.size(); i++) { - QJsonObject object = array.at(i).toObject(); - TypeStreamerPointer streamer = getTypeStreamer(object.value("type").toString()); - int index = baseStreamer->getFieldIndex(object.value("name").toString().toLatin1()); - fields.append(StreamerIndexPair(streamer, index)); - matches &= (index == i && streamer == metaFields.at(i).getStreamer()); - } - // if everything matches our built-in streamable, we can use that, which will be faster - if (matches) { - _typeStreamers.insert(name, baseStreamer->getSelf()); - } else { - _typeStreamers.insert(name, TypeStreamerPointer(new MappedStreamableTypeStreamer(baseStreamer, fields))); - } - } else if (category == "LIST") { - TypeStreamerPointer valueStreamer = getTypeStreamer(type.value("valueType").toString()); - if (valueStreamer == baseStreamer->getValueStreamer()) { - _typeStreamers.insert(name, baseStreamer->getSelf()); - - } else { - _typeStreamers.insert(name, TypeStreamerPointer(new MappedListTypeStreamer(baseStreamer, valueStreamer))); - } - } else if (category == "SET") { - TypeStreamerPointer valueStreamer = getTypeStreamer(type.value("valueType").toString()); - if (valueStreamer == baseStreamer->getValueStreamer()) { - _typeStreamers.insert(name, baseStreamer->getSelf()); - - } else { - _typeStreamers.insert(name, TypeStreamerPointer(new MappedSetTypeStreamer(baseStreamer, valueStreamer))); - } - } else if (category == "MAP") { - TypeStreamerPointer keyStreamer = getTypeStreamer(type.value("keyType").toString()); - TypeStreamerPointer valueStreamer = getTypeStreamer(type.value("valueType").toString()); - if (keyStreamer == baseStreamer->getKeyStreamer() && valueStreamer == baseStreamer->getValueStreamer()) { - _typeStreamers.insert(name, baseStreamer->getSelf()); - - } else { - _typeStreamers.insert(name, TypeStreamerPointer(new MappedMapTypeStreamer( - baseStreamer, keyStreamer, valueStreamer))); - } - } - } - - // create and map the object streamers in order - foreach (const QJsonValue& element, top.value("classes").toArray()) { - QJsonObject clazz = element.toObject(); - QString name = clazz.value("name").toString(); - QByteArray latinName = name.toLatin1(); - const ObjectStreamer* baseStreamer = Bitstream::getObjectStreamers().value( - Bitstream::getMetaObjects().value(latinName)); - if (!baseStreamer && genericsMode == Bitstream::NO_GENERICS) { - continue; // no built-in class and no generics allowed; we give up - } - if (!baseStreamer || genericsMode == Bitstream::ALL_GENERICS) { - // create a generic streamer - QVector properties; - foreach (const QJsonValue& property, clazz.value("properties").toArray()) { - QJsonObject object = property.toObject(); - properties.append(StreamerNamePair(getTypeStreamer(object.value("type").toString()), - object.value("name").toString().toLatin1())); - } - ObjectStreamerPointer streamer = ObjectStreamerPointer(new GenericObjectStreamer( - latinName, properties, QByteArray())); - _objectStreamers.insert(name, streamer); - static_cast(streamer.data())->_weakSelf = streamer; - continue; - } - // create a mapped streamer, determining along the way whether it matches our base - const QMetaObject* metaObject = baseStreamer->getMetaObject(); - const QVector& baseProperties = baseStreamer->getProperties(); - QVector properties; - QJsonArray propertyArray = clazz.value("properties").toArray(); - bool matches = (baseProperties.size() == propertyArray.size()); - for (int i = 0; i < propertyArray.size(); i++) { - QJsonObject object = propertyArray.at(i).toObject(); - TypeStreamerPointer typeStreamer = getTypeStreamer(object.value("type").toString()); - QMetaProperty metaProperty = metaObject->property(metaObject->indexOfProperty( - object.value("name").toString().toLatin1())); - properties.append(StreamerPropertyPair(typeStreamer, metaProperty)); - - const StreamerPropertyPair& baseProperty = baseProperties.at(i); - matches &= (typeStreamer == baseProperty.first && - metaProperty.propertyIndex() == baseProperty.second.propertyIndex()); - } - // if everything matches our built-in type, we can use that directly, which will be faster - if (matches) { - _objectStreamers.insert(name, baseStreamer->getSelf()); - } else { - _objectStreamers.insert(name, ObjectStreamerPointer(createMappedObjectStreamer(metaObject, properties))); - } - } - - // create and map the objects in order - foreach (const QJsonValue& element, top.value("objects").toArray()) { - QJsonObject object = element.toObject(); - int id = object.value("id").toInt(); - QObject* qObject; - putData(object.value("data"), qObject); - if (qObject) { - _sharedObjects.insert(id, static_cast(qObject)); - } - } - - // prepare the contents for extraction - _contents = top.value("contents").toArray(); - _contentsIterator = _contents.constBegin(); -} - -void JSONReader::putData(const QJsonValue& data, bool& value) { - value = data.toBool(); -} - -void JSONReader::putData(const QJsonValue& data, int& value) { - value = data.toInt(); -} - -void JSONReader::putData(const QJsonValue& data, uint& value) { - value = data.toInt(); -} - -void JSONReader::putData(const QJsonValue& data, float& value) { - value = data.toDouble(); -} - -void JSONReader::putData(const QJsonValue& data, QByteArray& value) { - value = QByteArray::fromPercentEncoding(data.toString().toLatin1()); -} - -void JSONReader::putData(const QJsonValue& data, QColor& value) { - value.setNamedColor(data.toString()); -} - -void JSONReader::putData(const QJsonValue& data, QScriptValue& value) { - QJsonObject object = data.toObject(); - QString type = object.value("type").toString(); - if (type == "UNDEFINED") { - value = QScriptValue(QScriptValue::UndefinedValue); - - } else if (type == "NULL") { - value = QScriptValue(QScriptValue::NullValue); - - } else if (type == "BOOL") { - value = QScriptValue(object.value("value").toBool()); - - } else if (type == "NUMBER") { - value = QScriptValue(object.value("value").toDouble()); - - } else if (type == "STRING") { - value = QScriptValue(object.value("value").toString()); - - } else if (type == "VARIANT") { - QVariant variant; - putData(object.value("value"), variant); - value = DependencyManager::get()->getEngine()->newVariant(variant); - - } else if (type == "QOBJECT") { - QObject* qObject; - putData(object.value("value"), qObject); - value = DependencyManager::get()->getEngine()->newQObject(qObject, QScriptEngine::ScriptOwnership); - - } else if (type == "QMETAOBJECT") { - const QMetaObject* metaObject; - putData(object.value("value"), metaObject); - value = DependencyManager::get()->getEngine()->newQMetaObject(metaObject); - - } else if (type == "DATE") { - QDateTime dateTime; - putData(object.value("value"), dateTime); - value = DependencyManager::get()->getEngine()->newDate(dateTime); - - } else if (type == "REGEXP") { - QRegExp regExp; - putData(object.value("value"), regExp); - value = DependencyManager::get()->getEngine()->newRegExp(regExp); - - } else if (type == "ARRAY") { - QJsonArray array = object.value("value").toArray(); - value = DependencyManager::get()->getEngine()->newArray(array.size()); - for (int i = 0; i < array.size(); i++) { - QScriptValue element; - putData(array.at(i), element); - value.setProperty(i, element); - } - } else if (type == "OBJECT") { - QJsonObject jsonObject = object.value("value").toObject(); - value = DependencyManager::get()->getEngine()->newObject(); - for (QJsonObject::const_iterator it = jsonObject.constBegin(); it != jsonObject.constEnd(); it++) { - QScriptValue element; - putData(it.value(), element); - value.setProperty(it.key(), element); - } - } else { - value = QScriptValue(); - } -} - -void JSONReader::putData(const QJsonValue& data, QString& value) { - value = data.toString(); -} - -void JSONReader::putData(const QJsonValue& data, QUrl& value) { - value = data.toString(); -} - -void JSONReader::putData(const QJsonValue& data, QDateTime& value) { - value.setMSecsSinceEpoch((qint64)data.toDouble()); -} - -void JSONReader::putData(const QJsonValue& data, QRegExp& value) { - QJsonObject object = data.toObject(); - value = QRegExp(object.value("pattern").toString(), (Qt::CaseSensitivity)object.value("caseSensitivity").toInt(), - (QRegExp::PatternSyntax)object.value("patternSyntax").toInt()); - value.setMinimal(object.value("minimal").toBool()); -} - -void JSONReader::putData(const QJsonValue& data, glm::vec3& value) { - QJsonArray array = data.toArray(); - value = glm::vec3(array.at(0).toDouble(), array.at(1).toDouble(), array.at(2).toDouble()); -} - -void JSONReader::putData(const QJsonValue& data, glm::quat& value) { - QJsonArray array = data.toArray(); - value = glm::quat(array.at(0).toDouble(), array.at(1).toDouble(), array.at(2).toDouble(), array.at(3).toDouble()); -} - -void JSONReader::putData(const QJsonValue& data, const QMetaObject*& value) { - ObjectStreamerPointer streamer = _objectStreamers.value(data.toString()); - value = streamer ? streamer->getMetaObject() : NULL; -} - -void JSONReader::putData(const QJsonValue& data, QVariant& value) { - QJsonObject object = data.toObject(); - QString type = object.value("type").toString(); - TypeStreamerPointer streamer = getTypeStreamer(type); - if (streamer) { - streamer->putJSONVariantData(*this, object.value("value"), value); - } else { - value = QVariant(); - } -} - -void JSONReader::putData(const QJsonValue& data, SharedObjectPointer& value) { - value = _sharedObjects.value(data.toInt()); -} - -void JSONReader::putData(const QJsonValue& data, QObject*& value) { - QJsonObject object = data.toObject(); - ObjectStreamerPointer streamer = _objectStreamers.value(object.value("class").toString()); - value = streamer ? streamer->putJSONData(*this, object) : NULL; -} - -TypeStreamerPointer JSONReader::getTypeStreamer(const QString& name) const { - TypeStreamerPointer streamer = _typeStreamers.value(name); - if (!streamer) { - const TypeStreamer* defaultStreamer = Bitstream::getTypeStreamers().value(QMetaType::type(name.toLatin1())); - if (defaultStreamer) { - streamer = defaultStreamer->getSelf(); - } else { - qWarning() << "Unknown type:" << name; - } - } - return streamer; -} - -ObjectStreamer::ObjectStreamer(const QMetaObject* metaObject) : - _metaObject(metaObject) { -} - -ObjectStreamer::~ObjectStreamer() { -} - -const QVector& ObjectStreamer::getProperties() const { - static QVector emptyProperties; - return emptyProperties; -} - -MappedObjectStreamer::MappedObjectStreamer(const QMetaObject* metaObject, const QVector& properties) : - ObjectStreamer(metaObject), - _properties(properties) { -} - -const char* MappedObjectStreamer::getName() const { - return _metaObject->className(); -} - -const QVector& MappedObjectStreamer::getProperties() const { - return _properties; -} - -void MappedObjectStreamer::writeMetadata(Bitstream& out, bool full) const { - out << _properties.size(); - if (_properties.isEmpty()) { - return; - } - QCryptographicHash hash(QCryptographicHash::Md5); - foreach (const StreamerPropertyPair& property, _properties) { - out << property.first.data(); - if (full) { - out << QByteArray::fromRawData(property.second.name(), strlen(property.second.name())); - } else { - hash.addData(property.second.name(), strlen(property.second.name()) + 1); - } - } - if (!full) { - QByteArray hashResult = hash.result(); - out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE); - } -} - -QJsonObject MappedObjectStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(_metaObject->className())); - QJsonArray properties; - foreach (const StreamerPropertyPair& property, _properties) { - QJsonObject object; - writer.addTypeStreamer(property.first.data()); - object.insert("type", QString(property.first->getName())); - object.insert("name", QString(property.second.name())); - properties.append(object); - } - metadata.insert("properties", properties); - return metadata; -} - -QJsonObject MappedObjectStreamer::getJSONData(JSONWriter& writer, const QObject* object) const { - QJsonObject data; - writer.addObjectStreamer(this); - data.insert("class", QString(_metaObject->className())); - QJsonArray properties; - foreach (const StreamerPropertyPair& property, _properties) { - properties.append(property.first->getJSONData(writer, property.second.read(object))); - } - data.insert("properties", properties); - return data; -} - -QObject* MappedObjectStreamer::putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const { - if (!_metaObject) { - return NULL; - } - QObject* object = _metaObject->newInstance(); - QJsonArray properties = jsonObject.value("properties").toArray(); - for (int i = 0; i < _properties.size(); i++) { - const StreamerPropertyPair& property = _properties.at(i); - if (property.second.isValid()) { - QVariant value; - property.first->putJSONData(reader, properties.at(i), value); - property.second.write(object, value); - } - } - return object; -} - -bool MappedObjectStreamer::equal(const QObject* first, const QObject* second) const { - foreach (const StreamerPropertyPair& property, _properties) { - if (!property.first->equal(property.second.read(first), property.second.read(second))) { - return false; - } - } - return true; -} - -void MappedObjectStreamer::write(Bitstream& out, const QObject* object) const { - foreach (const StreamerPropertyPair& property, _properties) { - property.first->write(out, property.second.read(object)); - } -} - -void MappedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const { - foreach (const StreamerPropertyPair& property, _properties) { - property.first->writeDelta(out, property.second.read(object), (reference && reference->metaObject() == _metaObject) ? - property.second.read(reference) : QVariant()); - } -} - -QObject* MappedObjectStreamer::read(Bitstream& in, QObject* object) const { - bool reread = (object != NULL); - if (!object && _metaObject) { - object = _metaObject->newInstance(); - } - foreach (const StreamerPropertyPair& property, _properties) { - QVariant value = property.first->read(in); - if (property.second.isValid() && object && !reread) { - property.second.write(object, value); - } - } - return object; -} - -QObject* MappedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const { - bool reread = (object != NULL); - if (!object && _metaObject) { - object = _metaObject->newInstance(); - } - foreach (const StreamerPropertyPair& property, _properties) { - QVariant value; - property.first->readDelta(in, value, (property.second.isValid() && reference && - reference->metaObject() == _metaObject) ? property.second.read(reference) : QVariant()); - if (property.second.isValid() && object && !reread) { - property.second.write(object, value); - } - } - return object; -} - -SharedObjectStreamer::SharedObjectStreamer(const QMetaObject* metaObject, const QVector& properties) : - MappedObjectStreamer(metaObject, properties) { -} - -void SharedObjectStreamer::write(Bitstream& out, const QObject* object) const { - MappedObjectStreamer::write(out, object); - static_cast(object)->writeExtra(out); -} - -void SharedObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const { - MappedObjectStreamer::writeRawDelta(out, object, reference); - static_cast(object)->writeExtraDelta(out, static_cast(reference)); -} - -QObject* SharedObjectStreamer::read(Bitstream& in, QObject* object) const { - QObject* result = MappedObjectStreamer::read(in, object); - static_cast(result)->readExtra(in, object != NULL); - return result; -} - -QObject* SharedObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const { - QObject* result = MappedObjectStreamer::readRawDelta(in, reference, object); - static_cast(result)->readExtraDelta(in, static_cast(reference), object != NULL); - return result; -} - -GenericObjectStreamer::GenericObjectStreamer(const QByteArray& name, const QVector& properties, - const QByteArray& hash) : - ObjectStreamer(&GenericSharedObject::staticMetaObject), - _name(name), - _properties(properties), - _hash(hash) { -} - -const char* GenericObjectStreamer::getName() const { - return _name.constData(); -} - -void GenericObjectStreamer::writeMetadata(Bitstream& out, bool full) const { - out << _properties.size(); - if (_properties.isEmpty()) { - return; - } - foreach (const StreamerNamePair& property, _properties) { - out << property.first.data(); - if (full) { - out << property.second; - } - } - if (!full) { - if (_hash.isEmpty()) { - QCryptographicHash hash(QCryptographicHash::Md5); - foreach (const StreamerNamePair& property, _properties) { - hash.addData(property.second.constData(), property.second.size() + 1); - } - const_cast(this)->_hash = hash.result(); - } - out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE); - } -} - -QJsonObject GenericObjectStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(_name)); - QJsonArray properties; - foreach (const StreamerNamePair& property, _properties) { - QJsonObject object; - writer.addTypeStreamer(property.first.data()); - object.insert("type", QString(property.first->getName())); - object.insert("name", QString(property.second)); - properties.append(object); - } - metadata.insert("properties", properties); - return metadata; -} - -QJsonObject GenericObjectStreamer::getJSONData(JSONWriter& writer, const QObject* object) const { - QJsonObject data; - writer.addObjectStreamer(this); - data.insert("class", QString(_name)); - QJsonArray properties; - const QVariantList& values = static_cast(object)->getValues(); - for (int i = 0; i < _properties.size(); i++) { - properties.append(_properties.at(i).first->getJSONData(writer, values.at(i))); - } - data.insert("properties", properties); - return data; -} - -QObject* GenericObjectStreamer::putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const { - GenericSharedObject* object = new GenericSharedObject(_weakSelf); - QJsonArray properties = jsonObject.value("properties").toArray(); - QVariantList values; - for (int i = 0; i < _properties.size(); i++) { - QVariant value; - _properties.at(i).first->putJSONData(reader, properties.at(i), value); - values.append(value); - } - object->setValues(values); - return object; -} - -bool GenericObjectStreamer::equal(const QObject* first, const QObject* second) const { - const QVariantList& firstValues = static_cast(first)->getValues(); - const QVariantList& secondValues = static_cast(second)->getValues(); - for (int i = 0; i < _properties.size(); i++) { - if (!_properties.at(i).first->equal(firstValues.at(i), secondValues.at(i))) { - return false; - } - } - return true; -} - -void GenericObjectStreamer::write(Bitstream& out, const QObject* object) const { - const QVariantList& values = static_cast(object)->getValues(); - for (int i = 0; i < _properties.size(); i++) { - _properties.at(i).first->write(out, values.at(i)); - } -} - -void GenericObjectStreamer::writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const { - const GenericSharedObject* genericObject = static_cast(object); - const GenericSharedObject* genericReference = (reference && - reference->metaObject() == &GenericSharedObject::staticMetaObject) ? - static_cast(reference) : NULL; - for (int i = 0; i < _properties.size(); i++) { - _properties.at(i).first->writeDelta(out, genericObject->getValues().at(i), - (genericReference && genericReference->getStreamer() == genericObject->getStreamer()) ? - genericReference->getValues().at(i) : QVariant()); - } -} - -QObject* GenericObjectStreamer::read(Bitstream& in, QObject* object) const { - bool reread = (object != NULL); - if (!object) { - object = new GenericSharedObject(_weakSelf); - } - QVariantList values; - foreach (const StreamerNamePair& property, _properties) { - values.append(property.first->read(in)); - } - if (!reread) { - static_cast(object)->setValues(values); - } - return object; -} - -QObject* GenericObjectStreamer::readRawDelta(Bitstream& in, const QObject* reference, QObject* object) const { - bool reread = (object != NULL); - if (!object) { - object = new GenericSharedObject(_weakSelf); - } - QVariantList values; - for (int i = 0; i < _properties.size(); i++) { - const StreamerNamePair& property = _properties.at(i); - QVariant value; - property.first->readDelta(in, value, reference ? - static_cast(reference)->getValues().at(i) : QVariant()); - values.append(value); - } - if (!reread) { - static_cast(object)->setValues(values); - } - return object; -} - -MetaField::MetaField(const QByteArray& name, const TypeStreamer* streamer) : - _name(name), - _streamer(streamer) { -} - -GenericValue::GenericValue(const TypeStreamerPointer& streamer, const QVariant& value) : - _streamer(streamer), - _value(value) { -} - -bool GenericValue::operator==(const GenericValue& other) const { - return _streamer == other._streamer && _value == other._value; -} - -GenericSharedObject::GenericSharedObject(const ObjectStreamerPointer& streamer) : - _streamer(streamer) { -} - -TypeStreamer::~TypeStreamer() { -} - -const char* TypeStreamer::getName() const { - return QMetaType::typeName(_type); -} - -const TypeStreamer* TypeStreamer::getStreamerToWrite(const QVariant& value) const { - return this; -} - -void TypeStreamer::writeMetadata(Bitstream& out, bool full) const { - if (getCategory() != STREAMABLE_CATEGORY) { - return; - } - // streamable type - const QVector& metaFields = getMetaFields(); - out << metaFields.size(); - if (metaFields.isEmpty()) { - return; - } - QCryptographicHash hash(QCryptographicHash::Md5); - foreach (const MetaField& metaField, metaFields) { - out << metaField.getStreamer(); - if (full) { - out << metaField.getName(); - } else { - hash.addData(metaField.getName().constData(), metaField.getName().size() + 1); - } - } - if (!full) { - QByteArray hashResult = hash.result(); - out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE); - } -} - -QJsonValue TypeStreamer::getJSONMetadata(JSONWriter& writer) const { - Category category = getCategory(); - switch (category) { - case STREAMABLE_CATEGORY: { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("STREAMABLE")); - QJsonArray fields; - foreach (const MetaField& metaField, getMetaFields()) { - QJsonObject field; - writer.addTypeStreamer(metaField.getStreamer()); - field.insert("type", QString(metaField.getStreamer()->getName())); - field.insert("name", QString(metaField.getName())); - fields.append(field); - } - metadata.insert("fields", fields); - return metadata; - } - case LIST_CATEGORY: - case SET_CATEGORY: { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString(category == LIST_CATEGORY ? "LIST" : "SET")); - const TypeStreamer* valueStreamer = getValueStreamer(); - writer.addTypeStreamer(valueStreamer); - metadata.insert("valueType", QString(valueStreamer->getName())); - return metadata; - } - case MAP_CATEGORY: { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("MAP")); - const TypeStreamer* keyStreamer = getKeyStreamer(); - writer.addTypeStreamer(keyStreamer); - metadata.insert("keyType", QString(keyStreamer->getName())); - const TypeStreamer* valueStreamer = getValueStreamer(); - writer.addTypeStreamer(valueStreamer); - metadata.insert("valueType", QString(valueStreamer->getName())); - return metadata; - } - default: - return QJsonValue(); - } -} - -QJsonValue TypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - return QJsonValue(); -} - -QJsonValue TypeStreamer::getJSONVariantData(JSONWriter& writer, const QVariant& value) const { - writer.addTypeStreamer(this); - QJsonObject data; - data.insert("type", QString(getName())); - data.insert("value", getJSONData(writer, value)); - return data; -} - -void TypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = QVariant(); -} - -void TypeStreamer::putJSONVariantData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - putJSONData(reader, data, value); -} - -bool TypeStreamer::equal(const QVariant& first, const QVariant& second) const { - return first == second; -} - -void TypeStreamer::write(Bitstream& out, const QVariant& value) const { - // nothing by default -} - -QVariant TypeStreamer::read(Bitstream& in) const { - return QVariant(); -} - -void TypeStreamer::writeVariant(Bitstream& out, const QVariant& value) const { - out << this; - write(out, value); -} - -QVariant TypeStreamer::readVariant(Bitstream& in) const { - return read(in); -} - -void TypeStreamer::writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - if (value == reference) { - out << false; - } else { - out << true; - writeRawDelta(out, value, reference); - } -} - -void TypeStreamer::readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - bool changed; - in >> changed; - if (changed) { - readRawDelta(in, value, reference); - } else { - value = reference; - } -} - -void TypeStreamer::writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - // nothing by default -} - -void TypeStreamer::readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - value = reference; -} - -void TypeStreamer::setEnumValue(QVariant& object, int value, const QHash& mappings) const { - // nothing by default -} - -const QVector& TypeStreamer::getMetaFields() const { - static QVector emptyMetaFields; - return emptyMetaFields; -} - -int TypeStreamer::getFieldIndex(const QByteArray& name) const { - return -1; -} - -void TypeStreamer::setField(QVariant& object, int index, const QVariant& value) const { - // nothing by default -} - -QVariant TypeStreamer::getField(const QVariant& object, int index) const { - return QVariant(); -} - -TypeStreamer::Category TypeStreamer::getCategory() const { - return SIMPLE_CATEGORY; -} - -int TypeStreamer::getBits() const { - return 0; -} - -QMetaEnum TypeStreamer::getMetaEnum() const { - return QMetaEnum(); -} - -const TypeStreamer* TypeStreamer::getKeyStreamer() const { - return NULL; -} - -const TypeStreamer* TypeStreamer::getValueStreamer() const { - return NULL; -} - -void TypeStreamer::insert(QVariant& object, const QVariant& element) const { - // nothing by default -} - -void TypeStreamer::insert(QVariant& object, const QVariant& key, const QVariant& value) const { - // nothing by default -} - -bool TypeStreamer::remove(QVariant& object, const QVariant& key) const { - return false; -} - -QVariant TypeStreamer::getValue(const QVariant& object, const QVariant& key) const { - return QVariant(); -} - -void TypeStreamer::prune(QVariant& object, int size) const { - // nothing by default -} - -QVariant TypeStreamer::getValue(const QVariant& object, int index) const { - return QVariant(); -} - -void TypeStreamer::setValue(QVariant& object, int index, const QVariant& value) const { - // nothing by default -} - -QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer) { - return debug << (typeStreamer ? QMetaType::typeName(typeStreamer->getType()) : "null"); -} - -QDebug& operator<<(QDebug& debug, const QMetaObject* metaObject) { - return debug << (metaObject ? metaObject->className() : "null"); -} - -EnumTypeStreamer::EnumTypeStreamer(const QMetaObject* metaObject, const char* name) : - _metaObject(metaObject), - _enumName(name), - _name(getEnumName(metaObject->className(), name)), - _bits(-1) { - - _type = QMetaType::Int; - _self = TypeStreamerPointer(this); -} - -EnumTypeStreamer::EnumTypeStreamer(const QMetaEnum& metaEnum) : - _name(getEnumName(metaEnum.scope(), metaEnum.name())), - _metaEnum(metaEnum), - _bits(-1) { - - _type = QMetaType::Int; - _self = TypeStreamerPointer(this); -} - -const char* EnumTypeStreamer::getName() const { - return _name.constData(); -} - -void EnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const { - QMetaEnum metaEnum = getMetaEnum(); - if (full) { - out << metaEnum.keyCount(); - for (int i = 0; i < metaEnum.keyCount(); i++) { - out << QByteArray::fromRawData(metaEnum.key(i), strlen(metaEnum.key(i))); - out << metaEnum.value(i); - } - } else { - out << getBits(); - QCryptographicHash hash(QCryptographicHash::Md5); - for (int i = 0; i < metaEnum.keyCount(); i++) { - hash.addData(metaEnum.key(i), strlen(metaEnum.key(i)) + 1); - qint32 value = metaEnum.value(i); - hash.addData((const char*)&value, sizeof(qint32)); - } - QByteArray hashResult = hash.result(); - out.write(hashResult.constData(), hashResult.size() * BITS_IN_BYTE); - } -} - -QJsonValue EnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("ENUM")); - QJsonArray values; - QMetaEnum metaEnum = getMetaEnum(); - for (int i = 0; i < metaEnum.keyCount(); i++) { - QJsonObject value; - value.insert("key", QString(metaEnum.key(i))); - value.insert("value", metaEnum.value(i)); - values.append(value); - } - metadata.insert("values", values); - return metadata; -} - -QJsonValue EnumTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - return value.toInt(); -} - -void EnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = data.toInt(); -} - -TypeStreamer::Category EnumTypeStreamer::getCategory() const { - return ENUM_CATEGORY; -} - -int EnumTypeStreamer::getBits() const { - if (_bits == -1) { - int highestValue = 0; - QMetaEnum metaEnum = getMetaEnum(); - for (int j = 0; j < metaEnum.keyCount(); j++) { - highestValue = qMax(highestValue, metaEnum.value(j)); - } - const_cast(this)->_bits = getBitsForHighestValue(highestValue); - } - return _bits; -} - -QMetaEnum EnumTypeStreamer::getMetaEnum() const { - if (!_metaEnum.isValid()) { - const_cast(this)->_metaEnum = _metaObject->enumerator(_metaObject->indexOfEnumerator(_enumName)); - } - return _metaEnum; -} - -bool EnumTypeStreamer::equal(const QVariant& first, const QVariant& second) const { - return first.toInt() == second.toInt(); -} - -void EnumTypeStreamer::write(Bitstream& out, const QVariant& value) const { - int intValue = value.toInt(); - out.write(&intValue, getBits()); -} - -QVariant EnumTypeStreamer::read(Bitstream& in) const { - int intValue = 0; - in.read(&intValue, getBits()); - return intValue; -} - -void EnumTypeStreamer::writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - int intValue = value.toInt(), intReference = reference.toInt(); - if (intValue == intReference) { - out << false; - } else { - out << true; - out.write(&intValue, getBits()); - } -} - -void EnumTypeStreamer::readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - bool changed; - in >> changed; - if (changed) { - int intValue = 0; - in.read(&intValue, getBits()); - value = intValue; - } else { - value = reference; - } -} - -void EnumTypeStreamer::writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - int intValue = value.toInt(); - out.write(&intValue, getBits()); -} - -void EnumTypeStreamer::readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - int intValue = 0; - in.read(&intValue, getBits()); - value = intValue; -} - -void EnumTypeStreamer::setEnumValue(QVariant& object, int value, const QHash& mappings) const { - if (getMetaEnum().isFlag()) { - int combined = 0; - for (QHash::const_iterator it = mappings.constBegin(); it != mappings.constEnd(); it++) { - if (value & it.key()) { - combined |= it.value(); - } - } - object = combined; - - } else { - object = mappings.value(value); - } -} - -MappedEnumTypeStreamer::MappedEnumTypeStreamer(const TypeStreamer* baseStreamer, int bits, const QHash& mappings) : - _baseStreamer(baseStreamer), - _bits(bits), - _mappings(mappings) { -} - -void MappedEnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = QVariant(_baseStreamer->getType(), 0); - _baseStreamer->setEnumValue(value, data.toInt(), _mappings); -} - -QVariant MappedEnumTypeStreamer::read(Bitstream& in) const { - QVariant object = QVariant(_baseStreamer->getType(), 0); - int value = 0; - in.read(&value, _bits); - _baseStreamer->setEnumValue(object, value, _mappings); - return object; -} - -void MappedEnumTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const { - int value = 0; - in.read(&value, _bits); - _baseStreamer->setEnumValue(object, value, _mappings); -} - -GenericTypeStreamer::GenericTypeStreamer(const QByteArray& name) : - _name(name) { -} - -const char* GenericTypeStreamer::getName() const { - return _name.constData(); -} - -void GenericTypeStreamer::putJSONVariantData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - QVariant containedValue; - putJSONData(reader, data, containedValue); - value = QVariant::fromValue(GenericValue(_weakSelf, containedValue)); -} - -QVariant GenericTypeStreamer::readVariant(Bitstream& in) const { - return QVariant::fromValue(GenericValue(_weakSelf, read(in))); -} - -GenericEnumTypeStreamer::GenericEnumTypeStreamer(const QByteArray& name, const QVector& values, - int bits, const QByteArray& hash) : - GenericTypeStreamer(name), - _values(values), - _bits(bits), - _hash(hash) { - - _type = qMetaTypeId(); -} - -void GenericEnumTypeStreamer::writeMetadata(Bitstream& out, bool full) const { - if (full) { - out << _values.size(); - foreach (const NameIntPair& value, _values) { - out << value.first << value.second; - } - } else { - out << _bits; - if (_hash.isEmpty()) { - QCryptographicHash hash(QCryptographicHash::Md5); - foreach (const NameIntPair& value, _values) { - hash.addData(value.first.constData(), value.first.size() + 1); - qint32 intValue = value.second; - hash.addData((const char*)&intValue, sizeof(qint32)); - } - const_cast(this)->_hash = hash.result(); - } - out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE); - } -} - -QJsonValue GenericEnumTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("ENUM")); - QJsonArray values; - foreach (const NameIntPair& value, _values) { - QJsonObject object; - object.insert("key", QString(value.first)); - object.insert("value", value.second); - values.append(object); - } - metadata.insert("values", values); - return metadata; -} - -QJsonValue GenericEnumTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - return value.toInt(); -} - -void GenericEnumTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = data.toInt(); -} - -void GenericEnumTypeStreamer::write(Bitstream& out, const QVariant& value) const { - int intValue = value.toInt(); - out.write(&intValue, _bits); -} - -QVariant GenericEnumTypeStreamer::read(Bitstream& in) const { - int intValue = 0; - in.read(&intValue, _bits); - return intValue; -} - -TypeStreamer::Category GenericEnumTypeStreamer::getCategory() const { - return ENUM_CATEGORY; -} - -MappedStreamableTypeStreamer::MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer, - const QVector& fields) : - _baseStreamer(baseStreamer), - _fields(fields) { -} - -void MappedStreamableTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = QVariant(_baseStreamer->getType(), 0); - QJsonArray array = data.toArray(); - for (int i = 0; i < _fields.size(); i++) { - const StreamerIndexPair& pair = _fields.at(i); - if (pair.second != -1) { - QVariant element; - pair.first->putJSONData(reader, array.at(i), element); - _baseStreamer->setField(value, pair.second, element); - } - } -} - -QVariant MappedStreamableTypeStreamer::read(Bitstream& in) const { - QVariant object = QVariant(_baseStreamer->getType(), 0); - foreach (const StreamerIndexPair& pair, _fields) { - QVariant value = pair.first->read(in); - if (pair.second != -1) { - _baseStreamer->setField(object, pair.second, value); - } - } - return object; -} - -void MappedStreamableTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const { - foreach (const StreamerIndexPair& pair, _fields) { - QVariant value; - if (pair.second != -1) { - pair.first->readDelta(in, value, _baseStreamer->getField(reference, pair.second)); - _baseStreamer->setField(object, pair.second, value); - } else { - pair.first->readDelta(in, value, QVariant()); - } - } -} - -GenericStreamableTypeStreamer::GenericStreamableTypeStreamer(const QByteArray& name, - const QVector& fields, const QByteArray& hash) : - GenericTypeStreamer(name), - _fields(fields), - _hash(hash) { - - _type = qMetaTypeId(); -} - -void GenericStreamableTypeStreamer::writeMetadata(Bitstream& out, bool full) const { - out << _fields.size(); - if (_fields.isEmpty()) { - return; - } - foreach (const StreamerNamePair& field, _fields) { - out << field.first.data(); - if (full) { - out << field.second; - } - } - if (!full) { - if (_hash.isEmpty()) { - QCryptographicHash hash(QCryptographicHash::Md5); - foreach (const StreamerNamePair& field, _fields) { - hash.addData(field.second.constData(), field.second.size() + 1); - } - const_cast(this)->_hash = hash.result(); - } - out.write(_hash.constData(), _hash.size() * BITS_IN_BYTE); - } -} - -QJsonValue GenericStreamableTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("STREAMABLE")); - QJsonArray fields; - foreach (const StreamerNamePair& field, _fields) { - QJsonObject object; - writer.addTypeStreamer(field.first.data()); - object.insert("type", QString(field.first->getName())); - object.insert("name", QString(field.second)); - fields.append(object); - } - metadata.insert("fields", fields); - return metadata; -} - -QJsonValue GenericStreamableTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - QVariantList values = value.toList(); - QJsonArray array; - for (int i = 0; i < _fields.size(); i++) { - array.append(_fields.at(i).first->getJSONData(writer, values.at(i))); - } - return array; -} - -void GenericStreamableTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - QJsonArray array = data.toArray(); - QVariantList values; - for (int i = 0; i < _fields.size(); i++) { - QVariant element; - _fields.at(i).first->putJSONData(reader, array.at(i), element); - values.append(element); - } - value = values; -} - -void GenericStreamableTypeStreamer::write(Bitstream& out, const QVariant& value) const { - QVariantList values = value.toList(); - for (int i = 0; i < _fields.size(); i++) { - _fields.at(i).first->write(out, values.at(i)); - } -} - -QVariant GenericStreamableTypeStreamer::read(Bitstream& in) const { - QVariantList values; - foreach (const StreamerNamePair& field, _fields) { - values.append(field.first->read(in)); - } - return values; -} - -TypeStreamer::Category GenericStreamableTypeStreamer::getCategory() const { - return STREAMABLE_CATEGORY; -} - -MappedListTypeStreamer::MappedListTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer) : - _baseStreamer(baseStreamer), - _valueStreamer(valueStreamer) { -} - -void MappedListTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = QVariant(_baseStreamer->getType(), 0); - foreach (const QJsonValue& element, data.toArray()) { - QVariant elementValue; - _valueStreamer->putJSONData(reader, element, elementValue); - _baseStreamer->insert(value, elementValue); - } -} - -QVariant MappedListTypeStreamer::read(Bitstream& in) const { - QVariant object = QVariant(_baseStreamer->getType(), 0); - int size; - in >> size; - for (int i = 0; i < size; i++) { - QVariant value = _valueStreamer->read(in); - _baseStreamer->insert(object, value); - } - return object; -} - -void MappedListTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const { - object = reference; - int size, referenceSize; - in >> size >> referenceSize; - if (size < referenceSize) { - _baseStreamer->prune(object, size); - } - for (int i = 0; i < size; i++) { - if (i < referenceSize) { - QVariant value; - _valueStreamer->readDelta(in, value, _baseStreamer->getValue(reference, i)); - _baseStreamer->setValue(object, i, value); - } else { - _baseStreamer->insert(object, _valueStreamer->read(in)); - } - } -} - -GenericListTypeStreamer::GenericListTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer) : - GenericTypeStreamer(name), - _valueStreamer(valueStreamer) { - - _type = qMetaTypeId(); -} - -void GenericListTypeStreamer::writeMetadata(Bitstream& out, bool full) const { - out << _valueStreamer.data(); -} - -QJsonValue GenericListTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("LIST")); - writer.addTypeStreamer(_valueStreamer.data()); - metadata.insert("valueType", QString(_valueStreamer->getName())); - return metadata; -} - -QJsonValue GenericListTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - QVariantList values = value.toList(); - QJsonArray array; - foreach (const QVariant& element, values) { - array.append(_valueStreamer->getJSONData(writer, element)); - } - return array; -} - -void GenericListTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - QJsonArray array = data.toArray(); - QVariantList values; - foreach (const QJsonValue& element, array) { - QVariant elementValue; - _valueStreamer->putJSONData(reader, element, elementValue); - values.append(elementValue); - } - value = values; -} - -void GenericListTypeStreamer::write(Bitstream& out, const QVariant& value) const { - QVariantList values = value.toList(); - out << values.size(); - foreach (const QVariant& element, values) { - _valueStreamer->write(out, element); - } -} - -QVariant GenericListTypeStreamer::read(Bitstream& in) const { - QVariantList values; - int size; - in >> size; - for (int i = 0; i < size; i++) { - values.append(_valueStreamer->read(in)); - } - return values; -} - -TypeStreamer::Category GenericListTypeStreamer::getCategory() const { - return LIST_CATEGORY; -} - -MappedSetTypeStreamer::MappedSetTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer) : - MappedListTypeStreamer(baseStreamer, valueStreamer) { -} - -void MappedSetTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const { - object = reference; - int addedOrRemoved; - in >> addedOrRemoved; - for (int i = 0; i < addedOrRemoved; i++) { - QVariant value = _valueStreamer->read(in); - if (!_baseStreamer->remove(object, value)) { - _baseStreamer->insert(object, value); - } - } -} - -GenericSetTypeStreamer::GenericSetTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer) : - GenericListTypeStreamer(name, valueStreamer) { -} - -QJsonValue GenericSetTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("SET")); - writer.addTypeStreamer(_valueStreamer.data()); - metadata.insert("valueType", QString(_valueStreamer->getName())); - return metadata; -} - -TypeStreamer::Category GenericSetTypeStreamer::getCategory() const { - return SET_CATEGORY; -} - -MappedMapTypeStreamer::MappedMapTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& keyStreamer, - const TypeStreamerPointer& valueStreamer) : - _baseStreamer(baseStreamer), - _keyStreamer(keyStreamer), - _valueStreamer(valueStreamer) { -} - -void MappedMapTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - value = QVariant(_baseStreamer->getType(), 0); - foreach (const QJsonValue& element, data.toArray()) { - QJsonArray pair = element.toArray(); - QVariant elementKey; - _keyStreamer->putJSONData(reader, pair.at(0), elementKey); - QVariant elementValue; - _valueStreamer->putJSONData(reader, pair.at(1), elementValue); - _baseStreamer->insert(value, elementKey, elementValue); - } -} - -QVariant MappedMapTypeStreamer::read(Bitstream& in) const { - QVariant object = QVariant(_baseStreamer->getType(), 0); - int size; - in >> size; - for (int i = 0; i < size; i++) { - QVariant key = _keyStreamer->read(in); - QVariant value = _valueStreamer->read(in); - _baseStreamer->insert(object, key, value); - } - return object; -} - -void MappedMapTypeStreamer::readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const { - object = reference; - int added; - in >> added; - for (int i = 0; i < added; i++) { - QVariant key = _keyStreamer->read(in); - QVariant value = _valueStreamer->read(in); - _baseStreamer->insert(object, key, value); - } - int modified; - in >> modified; - for (int i = 0; i < modified; i++) { - QVariant key = _keyStreamer->read(in); - QVariant value; - _valueStreamer->readDelta(in, value, _baseStreamer->getValue(reference, key)); - _baseStreamer->insert(object, key, value); - } - int removed; - in >> removed; - for (int i = 0; i < removed; i++) { - QVariant key = _keyStreamer->read(in); - _baseStreamer->remove(object, key); - } -} - -GenericMapTypeStreamer::GenericMapTypeStreamer(const QByteArray& name, const TypeStreamerPointer& keyStreamer, - const TypeStreamerPointer& valueStreamer) : - GenericTypeStreamer(name), - _keyStreamer(keyStreamer), - _valueStreamer(valueStreamer) { - - _type = qMetaTypeId(); -} - -void GenericMapTypeStreamer::writeMetadata(Bitstream& out, bool full) const { - out << _keyStreamer.data() << _valueStreamer.data(); -} - -QJsonValue GenericMapTypeStreamer::getJSONMetadata(JSONWriter& writer) const { - QJsonObject metadata; - metadata.insert("name", QString(getName())); - metadata.insert("category", QString("MAP")); - writer.addTypeStreamer(_keyStreamer.data()); - metadata.insert("keyType", QString(_keyStreamer->getName())); - writer.addTypeStreamer(_valueStreamer.data()); - metadata.insert("valueType", QString(_valueStreamer->getName())); - return metadata; -} - -QJsonValue GenericMapTypeStreamer::getJSONData(JSONWriter& writer, const QVariant& value) const { - QVariantPairList values = value.value(); - QJsonArray array; - foreach (const QVariantPair& pair, values) { - QJsonArray pairArray; - pairArray.append(_keyStreamer->getJSONData(writer, pair.first)); - pairArray.append(_valueStreamer->getJSONData(writer, pair.second)); - array.append(pairArray); - } - return array; -} - -void GenericMapTypeStreamer::putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - QJsonArray array = data.toArray(); - QVariantPairList values; - foreach (const QJsonValue& element, array) { - QJsonArray pair = element.toArray(); - QVariant elementKey; - _keyStreamer->putJSONData(reader, pair.at(0), elementKey); - QVariant elementValue; - _valueStreamer->putJSONData(reader, pair.at(1), elementValue); - values.append(QVariantPair(elementKey, elementValue)); - } - value = QVariant::fromValue(values); -} - -void GenericMapTypeStreamer::write(Bitstream& out, const QVariant& value) const { - QVariantPairList values = value.value(); - out << values.size(); - foreach (const QVariantPair& pair, values) { - _keyStreamer->write(out, pair.first); - _valueStreamer->write(out, pair.second); - } -} - -QVariant GenericMapTypeStreamer::read(Bitstream& in) const { - QVariantPairList values; - int size; - in >> size; - for (int i = 0; i < size; i++) { - QVariant key = _keyStreamer->read(in); - QVariant value = _valueStreamer->read(in); - values.append(QVariantPair(key, value)); - } - return QVariant::fromValue(values); -} - -TypeStreamer::Category GenericMapTypeStreamer::getCategory() const { - return MAP_CATEGORY; -} - -QJsonValue GenericValueStreamer::getJSONVariantData(JSONWriter& writer, const QVariant& value) const { - GenericValue genericValue = value.value(); - writer.addTypeStreamer(genericValue.getStreamer().data()); - QJsonObject data; - data.insert("type", QString(genericValue.getStreamer()->getName())); - data.insert("value", genericValue.getStreamer()->getJSONData(writer, genericValue.getValue())); - return data; -} - -void GenericValueStreamer::writeVariant(Bitstream& out, const QVariant& value) const { - GenericValue genericValue = value.value(); - out << genericValue.getStreamer().data(); - genericValue.getStreamer()->write(out, genericValue.getValue()); -} - diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h deleted file mode 100644 index 121aa6c672..0000000000 --- a/libraries/metavoxels/src/Bitstream.h +++ /dev/null @@ -1,1781 +0,0 @@ -// -// Bitstream.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/2/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Bitstream_h -#define hifi_Bitstream_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "SharedObject.h" - -class QByteArray; -class QColor; -class QDataStream; -class QScriptEngine; -class QScriptValue; -class QUrl; - -class Attribute; -class AttributeValue; -class Bitstream; -class GenericValue; -class JSONWriter; -class ObjectReader; -class ObjectStreamer; -class OwnedAttributeValue; -class TypeStreamer; - -typedef SharedObjectPointerTemplate AttributePointer; - -typedef QPair ScopeNamePair; -typedef QPair NameIntPair; -typedef QSharedPointer ObjectStreamerPointer; -typedef QWeakPointer WeakObjectStreamerPointer; -typedef QSharedPointer TypeStreamerPointer; -typedef QWeakPointer WeakTypeStreamerPointer; - -typedef QPair QVariantPair; -typedef QList QVariantPairList; - -Q_DECLARE_METATYPE(QVariantPairList) - -/// Streams integer identifiers that conform to the following pattern: each ID encountered in the stream is either one that -/// has been sent (received) before, or is one more than the highest previously encountered ID (starting at zero). This allows -/// us to use the minimum number of bits to encode the IDs. -class IDStreamer { -public: - - IDStreamer(Bitstream& stream); - - void setBitsFromValue(int value); - - IDStreamer& operator<<(int value); - IDStreamer& operator>>(int& value); - -private: - - Bitstream& _stream; - int _bits; -}; - -/// Provides a means to stream repeated values efficiently. The value is first streamed along with a unique ID. When -/// subsequently streamed, only the ID is sent. -template class RepeatedValueStreamer { -public: - - RepeatedValueStreamer(Bitstream& stream) : _stream(stream), _idStreamer(stream), - _lastPersistentID(0), _lastTransientOffset(0) { } - - QHash getAndResetTransientOffsets(); - - void persistTransientOffsets(const QHash& transientOffsets); - - QHash getAndResetTransientValues(); - - void persistTransientValues(const QHash& transientValues); - - void removePersistentID(P value) { _persistentIDs.remove(value); } - - int takePersistentID(P value) { return _persistentIDs.take(value); } - - int removePersistentValue(V value) { int id = _valueIDs.take(value); _persistentValues.remove(id); return id; } - - V takePersistentValue(int id) { V value = _persistentValues.take(id); _valueIDs.remove(value); return value; } - - void insertPersistentValue(int id, V value) { _valueIDs.insert(value, id); _persistentValues.insert(id, value); } - - void copyPersistentMappings(const RepeatedValueStreamer& other); - void clearPersistentMappings(); - - RepeatedValueStreamer& operator<<(K value); - RepeatedValueStreamer& operator>>(V& value); - -private: - - Bitstream& _stream; - IDStreamer _idStreamer; - int _lastPersistentID; - int _lastTransientOffset; - QHash _persistentIDs; - QHash _transientOffsets; - QHash _persistentValues; - QHash _transientValues; - QHash _valueIDs; -}; - -template inline QHash RepeatedValueStreamer::getAndResetTransientOffsets() { - QHash transientOffsets; - _transientOffsets.swap(transientOffsets); - _lastTransientOffset = 0; - _idStreamer.setBitsFromValue(_lastPersistentID); - return transientOffsets; -} - -template inline void RepeatedValueStreamer::persistTransientOffsets( - const QHash& transientOffsets) { - int oldLastPersistentID = _lastPersistentID; - for (typename QHash::const_iterator it = transientOffsets.constBegin(); it != transientOffsets.constEnd(); it++) { - int& id = _persistentIDs[it.key()]; - if (id == 0) { - id = oldLastPersistentID + it.value(); - _lastPersistentID = qMax(_lastPersistentID, id); - } - } - _idStreamer.setBitsFromValue(_lastPersistentID); -} - -template inline QHash RepeatedValueStreamer::getAndResetTransientValues() { - QHash transientValues; - _transientValues.swap(transientValues); - _idStreamer.setBitsFromValue(_lastPersistentID); - return transientValues; -} - -template inline void RepeatedValueStreamer::persistTransientValues( - const QHash& transientValues) { - int oldLastPersistentID = _lastPersistentID; - for (typename QHash::const_iterator it = transientValues.constBegin(); it != transientValues.constEnd(); it++) { - int& id = _valueIDs[it.value()]; - if (id == 0) { - id = oldLastPersistentID + it.key(); - _lastPersistentID = qMax(_lastPersistentID, id); - _persistentValues.insert(id, it.value()); - } - } - _idStreamer.setBitsFromValue(_lastPersistentID); -} - -template inline RepeatedValueStreamer& - RepeatedValueStreamer::operator<<(K value) { - int id = _persistentIDs.value(value); - if (id == 0) { - int& offset = _transientOffsets[value]; - if (offset == 0) { - _idStreamer << (_lastPersistentID + (offset = ++_lastTransientOffset)); - _stream < value; - - } else { - _idStreamer << (_lastPersistentID + offset); - } - } else { - _idStreamer << id; - } - return *this; -} - -template inline RepeatedValueStreamer& - RepeatedValueStreamer::operator>>(V& value) { - int id; - _idStreamer >> id; - if (id <= _lastPersistentID) { - value = _persistentValues.value(id); - - } else { - int offset = id - _lastPersistentID; - typename QHash::iterator it = _transientValues.find(offset); - if (it == _transientValues.end()) { - _stream > value; - _transientValues.insert(offset, value); - - } else { - value = *it; - } - } - return *this; -} - -template inline void RepeatedValueStreamer::copyPersistentMappings( - const RepeatedValueStreamer& other) { - _lastPersistentID = other._lastPersistentID; - _idStreamer.setBitsFromValue(_lastPersistentID); - _persistentIDs = other._persistentIDs; - _transientOffsets.clear(); - _lastTransientOffset = 0; - _persistentValues = other._persistentValues; - _transientValues.clear(); - _valueIDs = other._valueIDs; -} - -template inline void RepeatedValueStreamer::clearPersistentMappings() { - _lastPersistentID = 0; - _idStreamer.setBitsFromValue(_lastPersistentID); - _persistentIDs.clear(); - _transientOffsets.clear(); - _lastTransientOffset = 0; - _persistentValues.clear(); - _transientValues.clear(); - _valueIDs.clear(); -} - -/// A stream for bit-aligned data. Through a combination of code generation, reflection, macros, and templates, provides a -/// serialization mechanism that may be used for both networking and persistent storage. For unreliable networking, the -/// class provides a mapping system that resends mappings for ids until they are acknowledged (and thus persisted). For -/// version-resilient persistence, the class provides a metadata system that maps stored types to local types (or to -/// generic containers), allowing one to add and remove fields to classes without breaking compatibility with previously -/// stored data. -/// -/// The basic usage requires one to create a Bitstream that wraps an underlying QDataStream, specifying the metadata type -/// desired and (for readers) the generics mode. Then, one uses the << or >> operators to write or read values to/from -/// the stream (a stream instance may be used for reading or writing, but not both). For write streams, the flush -/// function should be called on completion to write any partial data. -/// -/// Polymorphic types are supported via the QVariant and QObject*/SharedObjectPointer types. When you write a QVariant or -/// QObject, the type or class name (at minimum) is written to the stream. When you read a QVariant or QObject, the default -/// behavior is to look for a corresponding registered type with the written name. With hash metadata, Bitstream can verify -/// that the local type matches the stream type, throwing the streamed version away if not. With full metadata, Bitstream can -/// create a mapping from the streamed type to the local type that applies the intersection of the two types' fields. -/// -/// To register types for streaming, select from the provided templates and macros. To register a QObject (or SharedObject) -/// subclass, use REGISTER_META_OBJECT in the class's source file. To register a streamable class for use in QVariant, use -/// the STREAMABLE/STREAM/DECLARE_STREAMABLE_METATYPE macros and use the mtc tool to generate the associated implementation -/// code. To register a QObject enum for use outside the QObject's direct properties, use the -/// DECLARE_ENUM_METATYPE/IMPLEMENT_ENUM_METATYPE macro pair. To register a collection type (QList, QVector, QSet, QMap) of -/// streamable types, use the registerCollectionMetaType template function. -/// -/// Delta-streaming is supported through the writeDelta/readDelta functions (analogous to <>), which accept a reference -/// value and stream only the information necessary to turn the reference into the target value. This assumes that the -/// reference value provided when reading is identical to the one used when writing. -/// -/// Special delta handling is provided for objects tracked by SharedObjectPointers. SharedObjects have IDs (representing their -/// unique identity on one system) as well as origin IDs (representing their identity as preserved over the course of -/// mutation). Once a shared object with a given ID is written (and its mapping persisted), that object's state will not be -/// written again; only its ID will be sent. However, if an object with a new ID but the same origin ID is written, that -/// object's state will be encoded as a delta between the previous object and the new one. So, to transmit delta-encoded -/// objects, one should treat each local SharedObject instance as immutable, replacing it when mutated with a cloned instance -/// generated by calling SharedObject::clone(true) and applying the desired changes. -class Bitstream : public QObject { - Q_OBJECT - -public: - - /// Stores a set of mappings from values to ids written. Typically, one would store these mappings along with the send - /// record of the packet that contained them, persisting the mappings if/when the packet is acknowledged by the remote - /// party. - class WriteMappings { - public: - QHash objectStreamerOffsets; - QHash typeStreamerOffsets; - QHash attributeOffsets; - QHash scriptStringOffsets; - QHash sharedObjectOffsets; - }; - - /// Stores a set of mappings from ids to values read. Typically, one would store these mappings along with the receive - /// record of the packet that contained them, persisting the mappings if/when the remote party indicates that it - /// has received the local party's acknowledgement of the packet. - class ReadMappings { - public: - QHash objectStreamerValues; - QHash typeStreamerValues; - QHash attributeValues; - QHash scriptStringValues; - QHash sharedObjectValues; - QVector subdividedObjects; - }; - - /// Performs all of the various lazily initializations (of object streamers, etc.) If multiple threads need to use - /// Bitstream instances, call this beforehand to prevent errors from occurring when multiple threads attempt lazy - /// initialization simultaneously. - static void preThreadingInit(); - - /// Registers a metaobject under its name so that instances of it can be streamed. Consider using the REGISTER_META_OBJECT - /// at the top level of the source file associated with the class rather than calling this function directly. - /// \return zero; the function only returns a value so that it can be used in static initialization - static int registerMetaObject(const char* className, const QMetaObject* metaObject); - - /// Registers a streamer for the specified Qt-registered type. Consider using one of the registration macros (such as - /// REGISTER_SIMPLE_TYPE_STREAMER) at the top level of the associated source file rather than calling this function - /// directly. - /// \return zero; the function only returns a value so that it can be used in static initialization - static int registerTypeStreamer(int type, TypeStreamer* streamer); - - /// Returns the streamer registered for the supplied type, if any. - static const TypeStreamer* getTypeStreamer(int type); - - /// Returns the streamer registered for the supplied object, if any. - static const ObjectStreamer* getObjectStreamer(const QMetaObject* metaObject); - - /// Returns the meta-object registered under the supplied class name, if any. - static const QMetaObject* getMetaObject(const QByteArray& className); - - /// Returns the list of registered subclasses for the supplied meta-object. When registered, metaobjects register - /// themselves as subclasses of all of their parents, mostly in order to allow editors to provide lists of available - /// subclasses. - static QList getMetaObjectSubClasses(const QMetaObject* metaObject); - - /// Configures the supplied script engine with our registered meta-objects, allowing all of them to be instantiated from - /// scripts. - static void registerTypes(QScriptEngine* engine); - - enum MetadataType { NO_METADATA, HASH_METADATA, FULL_METADATA }; - - enum GenericsMode { NO_GENERICS, FALLBACK_GENERICS, ALL_GENERICS }; - - /// Creates a new bitstream. Note: the stream may be used for reading or writing, but not both. - /// \param metadataType the metadata type, which determines the amount of version-resiliency: with no metadata, all types - /// must match exactly; with hash metadata, any types which do not match exactly will be ignored; with full metadata, - /// fields (and enum values, etc.) will be remapped by name - /// \param genericsMode the generics mode, which determines which types will be replaced by generic equivalents: with - /// no generics, no generics will be created; with fallback generics, generics will be created for any unknown types; with - /// all generics, generics will be created for all non-simple types - Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, - GenericsMode = NO_GENERICS, QObject* parent = NULL); - - /// Returns a reference to the underlying data stream. - QDataStream& getUnderlying() { return _underlying; } - - /// Sets the context pointer. - void setContext(void* context) { _context = context; } - - /// Returns the context pointer. - void* getContext() const { return _context; } - - /// Substitutes the supplied metaobject for the given class name's default mapping. This is mostly useful for testing the - /// process of mapping between different types, but may in the future be used for permanently renaming classes. - void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject); - - /// Substitutes the supplied type for the given type name's default mapping. - void addTypeSubstitution(const QByteArray& typeName, int type); - - /// Substitutes the named type for the given type name's default mapping. - void addTypeSubstitution(const QByteArray& typeName, const char* replacementTypeName); - - /// Writes a set of bits to the underlying stream. - /// \param bits the number of bits to write - /// \param offset the offset of the first bit - Bitstream& write(const void* data, int bits, int offset = 0); - - /// Reads a set of bits from the underlying stream. - /// \param bits the number of bits to read - /// \param offset the offset of the first bit - Bitstream& read(void* data, int bits, int offset = 0); - - /// Flushes any unwritten bits to the underlying stream. - void flush(); - - /// Resets to the initial state. - void reset(); - - /// Adds a subdivided object, which will be added to the read mappings and used as a reference if persisted. - void addSubdividedObject(const SharedObjectPointer& object) { _subdividedObjects.append(object); } - - /// Returns the set of transient mappings gathered during writing and resets them. - WriteMappings getAndResetWriteMappings(); - - /// Persists a set of write mappings recorded earlier. - void persistWriteMappings(const WriteMappings& mappings); - - /// Immediately persists and resets the write mappings. - void persistAndResetWriteMappings(); - - /// Returns the set of transient mappings gathered during reading and resets them. - ReadMappings getAndResetReadMappings(); - - /// Persists a set of read mappings recorded earlier. - void persistReadMappings(const ReadMappings& mappings); - - /// Immediately persists and resets the read mappings. - void persistAndResetReadMappings(); - - /// Copies the persistent mappings from the specified other stream. - void copyPersistentMappings(const Bitstream& other); - - /// Clears the persistent mappings for this stream. - void clearPersistentMappings(); - - /// Returns a reference to the weak hash storing shared objects for this stream. - const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _weakSharedObjectHash; } - - /// Removes a shared object from the read mappings. - void clearSharedObject(int id); - - void writeDelta(bool value, bool reference); - void readDelta(bool& value, bool reference); - - void writeDelta(const QVariant& value, const QVariant& reference); - - template void writeDelta(const T& value, const T& reference); - template void readDelta(T& value, const T& reference); - - void writeRawDelta(const QVariant& value, const QVariant& reference); - void readRawDelta(QVariant& value, const QVariant& reference); - - void writeRawDelta(const QObject* value, const QObject* reference); - void readRawDelta(QObject*& value, const QObject* reference); - - void writeRawDelta(const QScriptValue& value, const QScriptValue& reference); - void readRawDelta(QScriptValue& value, const QScriptValue& reference); - - template void writeRawDelta(const T& value, const T& reference); - template void readRawDelta(T& value, const T& reference); - - template void writeRawDelta(const QList& value, const QList& reference); - template void readRawDelta(QList& value, const QList& reference); - - template void writeRawDelta(const QVector& value, const QVector& reference); - template void readRawDelta(QVector& value, const QVector& reference); - - template void writeRawDelta(const QSet& value, const QSet& reference); - template void readRawDelta(QSet& value, const QSet& reference); - - template void writeRawDelta(const QHash& value, const QHash& reference); - template void readRawDelta(QHash& value, const QHash& reference); - - /// Writes the specified array aligned on byte boundaries to avoid the inefficiency - /// of bit-twiddling (at the cost of up to seven bits of wasted space). - void writeAligned(const QByteArray& data); - QByteArray readAligned(int bytes); - - Bitstream& operator<<(bool value); - Bitstream& operator>>(bool& value); - - Bitstream& operator<<(int value); - Bitstream& operator>>(int& value); - - Bitstream& operator<<(uint value); - Bitstream& operator>>(uint& value); - - Bitstream& operator<<(qint64 value); - Bitstream& operator>>(qint64& value); - - Bitstream& operator<<(float value); - Bitstream& operator>>(float& value); - - Bitstream& operator<<(double value); - Bitstream& operator>>(double& value); - - Bitstream& operator<<(const glm::vec3& value); - Bitstream& operator>>(glm::vec3& value); - - Bitstream& operator<<(const glm::quat& value); - Bitstream& operator>>(glm::quat& value); - - Bitstream& operator<<(const QByteArray& string); - Bitstream& operator>>(QByteArray& string); - - Bitstream& operator<<(const QColor& color); - Bitstream& operator>>(QColor& color); - - Bitstream& operator<<(const QString& string); - Bitstream& operator>>(QString& string); - - Bitstream& operator<<(const QUrl& url); - Bitstream& operator>>(QUrl& url); - - Bitstream& operator<<(const QDateTime& dateTime); - Bitstream& operator>>(QDateTime& dateTime); - - Bitstream& operator<<(const QRegExp& regExp); - Bitstream& operator>>(QRegExp& regExp); - - Bitstream& operator<<(const QVariant& value); - Bitstream& operator>>(QVariant& value); - - Bitstream& operator<<(const AttributeValue& attributeValue); - Bitstream& operator>>(OwnedAttributeValue& attributeValue); - - Bitstream& operator<<(const GenericValue& value); - Bitstream& operator>>(GenericValue& value); - - template Bitstream& operator<<(const QList& list); - template Bitstream& operator>>(QList& list); - - template Bitstream& operator<<(const QVector& list); - template Bitstream& operator>>(QVector& list); - - template Bitstream& operator<<(const QSet& set); - template Bitstream& operator>>(QSet& set); - - template Bitstream& operator<<(const QHash& hash); - template Bitstream& operator>>(QHash& hash); - - Bitstream& operator<<(const QObject* object); - Bitstream& operator>>(QObject*& object); - - Bitstream& operator<<(const QMetaObject* metaObject); - Bitstream& operator>>(const QMetaObject*& metaObject); - - Bitstream& operator<<(const ObjectStreamer* streamer); - Bitstream& operator>>(const ObjectStreamer*& streamer); - Bitstream& operator>>(ObjectStreamerPointer& streamer); - - Bitstream& operator<<(const TypeStreamer* streamer); - Bitstream& operator>>(const TypeStreamer*& streamer); - Bitstream& operator>>(TypeStreamerPointer& streamer); - - Bitstream& operator<<(const AttributePointer& attribute); - Bitstream& operator>>(AttributePointer& attribute); - - Bitstream& operator<<(const QScriptString& string); - Bitstream& operator>>(QScriptString& string); - - Bitstream& operator<<(const QScriptValue& value); - Bitstream& operator>>(QScriptValue& value); - - Bitstream& operator<<(const SharedObjectPointer& object); - Bitstream& operator>>(SharedObjectPointer& object); - - Bitstream& operator<(const ObjectStreamer* streamer); - Bitstream& operator>(ObjectStreamerPointer& streamer); - - Bitstream& operator<(const TypeStreamer* streamer); - Bitstream& operator>(TypeStreamerPointer& streamer); - - Bitstream& operator<(const AttributePointer& attribute); - Bitstream& operator>(AttributePointer& attribute); - - Bitstream& operator<(const QScriptString& string); - Bitstream& operator>(QScriptString& string); - - Bitstream& operator<(const SharedObjectPointer& object); - Bitstream& operator>(SharedObjectPointer& object); - -signals: - - void sharedObjectCleared(int id); - -private slots: - - void clearSharedObject(QObject* object); - -private: - - friend class JSONReader; - friend class JSONWriter; - - ObjectStreamerPointer readGenericObjectStreamer(const QByteArray& name); - TypeStreamerPointer readGenericTypeStreamer(const QByteArray& name, int category); - - QDataStream& _underlying; - quint8 _byte; - int _position; - - MetadataType _metadataType; - GenericsMode _genericsMode; - - void* _context; - - RepeatedValueStreamer _objectStreamerStreamer; - RepeatedValueStreamer _typeStreamerStreamer; - RepeatedValueStreamer _attributeStreamer; - RepeatedValueStreamer _scriptStringStreamer; - RepeatedValueStreamer _sharedObjectStreamer; - - QVector _subdividedObjects; - - WeakSharedObjectHash _sharedObjectReferences; - - WeakSharedObjectHash _weakSharedObjectHash; - - QHash _metaObjectSubstitutions; - QHash _typeStreamerSubstitutions; - - static QHash& getMetaObjects(); - static QMultiHash& getMetaObjectSubClasses(); - static QHash& getTypeStreamers(); - - static const QHash& getObjectStreamers(); - static QHash createObjectStreamers(); - - static const QHash& getEnumStreamers(); - static QHash createEnumStreamers(); - - static const QHash& getEnumStreamersByName(); - static QHash createEnumStreamersByName(); - - static const TypeStreamer* getInvalidTypeStreamer(); - static const TypeStreamer* createInvalidTypeStreamer(); -}; - -template inline void Bitstream::writeDelta(const T& value, const T& reference) { - if (value == reference) { - *this << false; - } else { - *this << true; - writeRawDelta(value, reference); - } -} - -template inline void Bitstream::readDelta(T& value, const T& reference) { - bool changed; - *this >> changed; - if (changed) { - readRawDelta(value, reference); - } else { - value = reference; - } -} - -template inline void Bitstream::writeRawDelta(const T& value, const T& reference) { - *this << value; -} - -template inline void Bitstream::readRawDelta(T& value, const T& reference) { - *this >> value; -} - -template inline void Bitstream::writeRawDelta(const QList& value, const QList& reference) { - *this << value.size(); - *this << reference.size(); - for (int i = 0; i < value.size(); i++) { - if (i < reference.size()) { - writeDelta(value.at(i), reference.at(i)); - } else { - *this << value.at(i); - } - } -} - -template inline void Bitstream::readRawDelta(QList& value, const QList& reference) { - value = reference; - int size, referenceSize; - *this >> size >> referenceSize; - if (size < value.size()) { - value.erase(value.begin() + size, value.end()); - } - for (int i = 0; i < size; i++) { - if (i < referenceSize) { - readDelta(value[i], reference.at(i)); - } else { - T element; - *this >> element; - value.append(element); - } - } -} - -template inline void Bitstream::writeRawDelta(const QVector& value, const QVector& reference) { - *this << value.size(); - *this << reference.size(); - for (int i = 0; i < value.size(); i++) { - if (i < reference.size()) { - writeDelta(value.at(i), reference.at(i)); - } else { - *this << value.at(i); - } - } -} - -template inline void Bitstream::readRawDelta(QVector& value, const QVector& reference) { - value = reference; - int size, referenceSize; - *this >> size >> referenceSize; - if (size < value.size()) { - value.erase(value.begin() + size, value.end()); - } - for (int i = 0; i < size; i++) { - if (i < referenceSize) { - readDelta(value[i], reference.at(i)); - } else { - T element; - *this >> element; - value.append(element); - } - } -} - -template inline void Bitstream::writeRawDelta(const QSet& value, const QSet& reference) { - int addedOrRemoved = 0; - foreach (const T& element, value) { - if (!reference.contains(element)) { - addedOrRemoved++; - } - } - foreach (const T& element, reference) { - if (!value.contains(element)) { - addedOrRemoved++; - } - } - *this << addedOrRemoved; - foreach (const T& element, value) { - if (!reference.contains(element)) { - *this << element; - } - } - foreach (const T& element, reference) { - if (!value.contains(element)) { - *this << element; - } - } -} - -template inline void Bitstream::readRawDelta(QSet& value, const QSet& reference) { - value = reference; - int addedOrRemoved; - *this >> addedOrRemoved; - for (int i = 0; i < addedOrRemoved; i++) { - T element; - *this >> element; - if (!value.remove(element)) { - value.insert(element); - } - } -} - -template inline void Bitstream::writeRawDelta(const QHash& value, const QHash& reference) { - int added = 0; - int modified = 0; - for (typename QHash::const_iterator it = value.constBegin(); it != value.constEnd(); it++) { - typename QHash::const_iterator previous = reference.find(it.key()); - if (previous == reference.constEnd()) { - added++; - } else if (previous.value() != it.value()) { - modified++; - } - } - *this << added; - for (typename QHash::const_iterator it = value.constBegin(); it != value.constEnd(); it++) { - if (!reference.contains(it.key())) { - *this << it.key(); - *this << it.value(); - } - } - *this << modified; - for (typename QHash::const_iterator it = value.constBegin(); it != value.constEnd(); it++) { - typename QHash::const_iterator previous = reference.find(it.key()); - if (previous != reference.constEnd() && previous.value() != it.value()) { - *this << it.key(); - writeDelta(it.value(), previous.value()); - } - } - int removed = 0; - for (typename QHash::const_iterator it = reference.constBegin(); it != reference.constEnd(); it++) { - if (!value.contains(it.key())) { - removed++; - } - } - *this << removed; - for (typename QHash::const_iterator it = reference.constBegin(); it != reference.constEnd(); it++) { - if (!value.contains(it.key())) { - *this << it.key(); - } - } -} - -template inline void Bitstream::readRawDelta(QHash& value, const QHash& reference) { - value = reference; - int added; - *this >> added; - for (int i = 0; i < added; i++) { - K key; - V mapping; - *this >> key >> mapping; - value.insert(key, mapping); - } - int modified; - *this >> modified; - for (int i = 0; i < modified; i++) { - K key; - *this >> key; - V& mapping = value[key]; - V newMapping; - readDelta(newMapping, mapping); - mapping = newMapping; - } - int removed; - *this >> removed; - for (int i = 0; i < removed; i++) { - K key; - *this >> key; - value.remove(key); - } -} - -template inline Bitstream& Bitstream::operator<<(const QList& list) { - *this << list.size(); - foreach (const T& entry, list) { - *this << entry; - } - return *this; -} - -template inline Bitstream& Bitstream::operator>>(QList& list) { - int size; - *this >> size; - list.clear(); - list.reserve(size); - for (int i = 0; i < size; i++) { - T entry; - *this >> entry; - list.append(entry); - } - return *this; -} - -template inline Bitstream& Bitstream::operator<<(const QVector& vector) { - *this << vector.size(); - foreach (const T& entry, vector) { - *this << entry; - } - return *this; -} - -template inline Bitstream& Bitstream::operator>>(QVector& vector) { - int size; - *this >> size; - vector.clear(); - vector.reserve(size); - for (int i = 0; i < size; i++) { - T entry; - *this >> entry; - vector.append(entry); - } - return *this; -} - -template inline Bitstream& Bitstream::operator<<(const QSet& set) { - *this << set.size(); - foreach (const T& entry, set) { - *this << entry; - } - return *this; -} - -template inline Bitstream& Bitstream::operator>>(QSet& set) { - int size; - *this >> size; - set.clear(); - set.reserve(size); - for (int i = 0; i < size; i++) { - T entry; - *this >> entry; - set.insert(entry); - } - return *this; -} - -template inline Bitstream& Bitstream::operator<<(const QHash& hash) { - *this << hash.size(); - for (typename QHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); it++) { - *this << it.key(); - *this << it.value(); - } - return *this; -} - -template inline Bitstream& Bitstream::operator>>(QHash& hash) { - int size; - *this >> size; - hash.clear(); - hash.reserve(size); - for (int i = 0; i < size; i++) { - K key; - V value; - *this >> key; - *this >> value; - hash.insertMulti(key, value); - } - return *this; -} - -/// Thrown for unrecoverable errors. -class BitstreamException { -public: - - BitstreamException(const QString& description); - - const QString& getDescription() const { return _description; } - -private: - - QString _description; -}; - -/// Provides a means of writing Bitstream-able data to JSON rather than the usual binary format in a manner that allows it to -/// be manipulated and re-read, converted to binary, etc. To use, create a JSONWriter, stream values in using the << operator, -/// and call getDocument to obtain the JSON data. -class JSONWriter { -public: - - QJsonValue getData(bool value); - QJsonValue getData(int value); - QJsonValue getData(uint value); - QJsonValue getData(float value); - QJsonValue getData(const QByteArray& value); - QJsonValue getData(const QColor& value); - QJsonValue getData(const QScriptValue& value); - QJsonValue getData(const QString& value); - QJsonValue getData(const QUrl& value); - QJsonValue getData(const QDateTime& value); - QJsonValue getData(const QRegExp& value); - QJsonValue getData(const glm::vec3& value); - QJsonValue getData(const glm::quat& value); - QJsonValue getData(const QMetaObject* value); - QJsonValue getData(const QVariant& value); - QJsonValue getData(const SharedObjectPointer& value); - QJsonValue getData(const QObject* value); - QJsonValue getData(const GenericValue& value); - - template QJsonValue getData(const T& value) { return QJsonValue(); } - - template QJsonValue getData(const QList& list); - template QJsonValue getData(const QVector& list); - template QJsonValue getData(const QSet& set); - template QJsonValue getData(const QHash& hash); - - template JSONWriter& operator<<(const T& value) { _contents.append(getData(value)); return *this; } - - void appendToContents(const QJsonValue& value) { _contents.append(value); } - - void addSharedObject(const SharedObjectPointer& object); - void addObjectStreamer(const ObjectStreamer* streamer); - void addTypeStreamer(const TypeStreamer* streamer); - - QJsonDocument getDocument() const; - -private: - - QJsonArray _contents; - - QSet _sharedObjectIDs; - QJsonArray _sharedObjects; - - QSet _objectStreamerNames; - QJsonArray _objectStreamers; - - QSet _typeStreamerNames; - QJsonArray _typeStreamers; -}; - -template inline QJsonValue JSONWriter::getData(const QList& list) { - QJsonArray array; - foreach (const T& value, list) { - array.append(getData(value)); - } - return array; -} - -template inline QJsonValue JSONWriter::getData(const QVector& vector) { - QJsonArray array; - foreach (const T& value, vector) { - array.append(getData(value)); - } - return array; -} - -template inline QJsonValue JSONWriter::getData(const QSet& set) { - QJsonArray array; - foreach (const T& value, set) { - array.append(getData(value)); - } - return array; -} - -template inline QJsonValue JSONWriter::getData(const QHash& hash) { - QJsonArray array; - for (typename QHash::const_iterator it = hash.constBegin(); it != hash.constEnd(); it++) { - QJsonArray pair; - pair.append(getData(it.key())); - pair.append(getData(it.value())); - array.append(pair); - } - return array; -} - -/// Reads a document written by JSONWriter. To use, create a JSONReader and stream values out using the >> operator. -class JSONReader { -public: - - /// Creates a reader to read from the supplied document. - /// \param genericsMode the generics mode to use: NO_GENERICS to map all types in the document to built-in types, - /// FALLBACK_GENERICS to use generic containers where no matching built-in type is found, or ALL_GENERICS to - /// read all types to generic containers - JSONReader(const QJsonDocument& document, Bitstream::GenericsMode genericsMode = Bitstream::NO_GENERICS); - - void putData(const QJsonValue& data, bool& value); - void putData(const QJsonValue& data, int& value); - void putData(const QJsonValue& data, uint& value); - void putData(const QJsonValue& data, float& value); - void putData(const QJsonValue& data, QByteArray& value); - void putData(const QJsonValue& data, QColor& value); - void putData(const QJsonValue& data, QScriptValue& value); - void putData(const QJsonValue& data, QString& value); - void putData(const QJsonValue& data, QUrl& value); - void putData(const QJsonValue& data, QDateTime& value); - void putData(const QJsonValue& data, QRegExp& value); - void putData(const QJsonValue& data, glm::vec3& value); - void putData(const QJsonValue& data, glm::quat& value); - void putData(const QJsonValue& data, const QMetaObject*& value); - void putData(const QJsonValue& data, QVariant& value); - void putData(const QJsonValue& data, SharedObjectPointer& value); - void putData(const QJsonValue& data, QObject*& value); - - template void putData(const QJsonValue& data, T& value) { value = T(); } - - template void putData(const QJsonValue& data, QList& list); - template void putData(const QJsonValue& data, QVector& list); - template void putData(const QJsonValue& data, QSet& set); - template void putData(const QJsonValue& data, QHash& hash); - - template JSONReader& operator>>(T& value) { putData(*_contentsIterator++, value); return *this; } - - QJsonValue retrieveNextFromContents() { return *_contentsIterator++; } - - TypeStreamerPointer getTypeStreamer(const QString& name) const; - ObjectStreamerPointer getObjectStreamer(const QString& name) const { return _objectStreamers.value(name); } - SharedObjectPointer getSharedObject(int id) const { return _sharedObjects.value(id); } - -private: - - QJsonArray _contents; - QJsonArray::const_iterator _contentsIterator; - - QHash _typeStreamers; - QHash _objectStreamers; - QHash _sharedObjects; -}; - -template inline void JSONReader::putData(const QJsonValue& data, QList& list) { - list.clear(); - foreach (const QJsonValue& element, data.toArray()) { - T value; - putData(element, value); - list.append(value); - } -} - -template inline void JSONReader::putData(const QJsonValue& data, QVector& list) { - list.clear(); - foreach (const QJsonValue& element, data.toArray()) { - T value; - putData(element, value); - list.append(value); - } -} - -template inline void JSONReader::putData(const QJsonValue& data, QSet& set) { - set.clear(); - foreach (const QJsonValue& element, data.toArray()) { - T value; - putData(element, value); - set.insert(value); - } -} - -template inline void JSONReader::putData(const QJsonValue& data, QHash& hash) { - hash.clear(); - foreach (const QJsonValue& element, data.toArray()) { - QJsonArray pair = element.toArray(); - K key; - putData(pair.at(0), key); - V value; - putData(pair.at(1), value); - hash.insert(key, value); - } -} - -typedef QPair StreamerPropertyPair; - -/// Contains the information required to stream an object. -class ObjectStreamer { -public: - - ObjectStreamer(const QMetaObject* metaObject); - virtual ~ObjectStreamer(); - - const QMetaObject* getMetaObject() const { return _metaObject; } - const ObjectStreamerPointer& getSelf() const { return _self; } - - virtual const char* getName() const = 0; - virtual const QVector& getProperties() const; - virtual void writeMetadata(Bitstream& out, bool full) const = 0; - virtual QJsonObject getJSONMetadata(JSONWriter& writer) const = 0; - virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const = 0; - virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const = 0; - - virtual bool equal(const QObject* first, const QObject* second) const = 0; - virtual void write(Bitstream& out, const QObject* object) const = 0; - virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const = 0; - virtual QObject* read(Bitstream& in, QObject* object = NULL) const = 0; - virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const = 0; - -protected: - - friend class Bitstream; - - const QMetaObject* _metaObject; - ObjectStreamerPointer _self; ///< set/used for built-in classes (never deleted), to obtain shared pointers -}; - -/// A streamer that maps to a local class. -class MappedObjectStreamer : public ObjectStreamer { -public: - - MappedObjectStreamer(const QMetaObject* metaObject, const QVector& properties); - - virtual const char* getName() const; - virtual const QVector& getProperties() const; - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonObject getJSONMetadata(JSONWriter& writer) const; - virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const; - virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const; - virtual bool equal(const QObject* first, const QObject* second) const; - virtual void write(Bitstream& out, const QObject* object) const; - virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const; - virtual QObject* read(Bitstream& in, QObject* object = NULL) const; - virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const; - -private: - - QVector _properties; -}; - -/// A streamer that maps to a local shared object class. Shared objects can write extra, non-property data. -class SharedObjectStreamer : public MappedObjectStreamer { -public: - - SharedObjectStreamer(const QMetaObject* metaObject, const QVector& properties); - - virtual void write(Bitstream& out, const QObject* object) const; - virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const; - virtual QObject* read(Bitstream& in, QObject* object = NULL) const; - virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const; -}; - -typedef QPair StreamerNamePair; - -/// A streamer for generic objects. -class GenericObjectStreamer : public ObjectStreamer { -public: - - GenericObjectStreamer(const QByteArray& name, const QVector& properties, const QByteArray& hash); - - virtual const char* getName() const; - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonObject getJSONMetadata(JSONWriter& writer) const; - virtual QJsonObject getJSONData(JSONWriter& writer, const QObject* object) const; - virtual QObject* putJSONData(JSONReader& reader, const QJsonObject& jsonObject) const; - virtual bool equal(const QObject* first, const QObject* second) const; - virtual void write(Bitstream& out, const QObject* object) const; - virtual void writeRawDelta(Bitstream& out, const QObject* object, const QObject* reference) const; - virtual QObject* read(Bitstream& in, QObject* object = NULL) const; - virtual QObject* readRawDelta(Bitstream& in, const QObject* reference, QObject* object = NULL) const; - -private: - - friend class Bitstream; - friend class JSONReader; - - QByteArray _name; - WeakObjectStreamerPointer _weakSelf; ///< promoted to strong references in GenericSharedObject when reading - QVector _properties; - QByteArray _hash; -}; - -/// Describes a metatype field. -class MetaField { -public: - - MetaField(const QByteArray& name = QByteArray(), const TypeStreamer* streamer = NULL); - - const QByteArray& getName() const { return _name; } - const TypeStreamer* getStreamer() const { return _streamer; } - -private: - - QByteArray _name; - const TypeStreamer* _streamer; -}; - -Q_DECLARE_METATYPE(const QMetaObject*) - -/// Macro for registering streamable meta-objects. Typically, one would use this macro at the top level of the source file -/// associated with the class. The class should have a no-argument constructor flagged with Q_INVOKABLE. -#define REGISTER_META_OBJECT(x) static int x##Registration = Bitstream::registerMetaObject(#x, &x::staticMetaObject); - -/// Contains a value along with a pointer to its streamer. This is stored in QVariants when using fallback generics and -/// no mapping to a built-in type can be found, or when using all generics and the value is any non-simple type. -class GenericValue { -public: - - GenericValue(const TypeStreamerPointer& streamer = TypeStreamerPointer(), const QVariant& value = QVariant()); - - const TypeStreamerPointer& getStreamer() const { return _streamer; } - const QVariant& getValue() const { return _value; } - - bool operator==(const GenericValue& other) const; - -private: - - TypeStreamerPointer _streamer; - QVariant _value; -}; - -Q_DECLARE_METATYPE(GenericValue) - -/// Contains a list of property values along with a pointer to their metadata. This is stored when using fallback generics -/// and no mapping to a built-in class can be found, or for all QObjects when using all generics. -class GenericSharedObject : public SharedObject { - Q_OBJECT - -public: - - GenericSharedObject(const ObjectStreamerPointer& streamer); - - const ObjectStreamerPointer& getStreamer() const { return _streamer; } - - void setValues(const QVariantList& values) { _values = values; } - const QVariantList& getValues() const { return _values; } - -private: - - ObjectStreamerPointer _streamer; - QVariantList _values; -}; - -/// Interface for objects that can write values to and read values from bitstreams. -class TypeStreamer { -public: - - enum Category { SIMPLE_CATEGORY, ENUM_CATEGORY, STREAMABLE_CATEGORY, LIST_CATEGORY, SET_CATEGORY, MAP_CATEGORY }; - - virtual ~TypeStreamer(); - - int getType() const { return _type; } - - const TypeStreamerPointer& getSelf() const { return _self; } - - virtual const char* getName() const; - - virtual const TypeStreamer* getStreamerToWrite(const QVariant& value) const; - - virtual void writeMetadata(Bitstream& out, bool full) const; - - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual QJsonValue getJSONVariantData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual void putJSONVariantData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - - virtual bool equal(const QVariant& first, const QVariant& second) const; - - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - - virtual void writeVariant(Bitstream& out, const QVariant& value) const; - virtual QVariant readVariant(Bitstream& in) const; - - virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const; - virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const; - - virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const; - virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const; - - virtual void setEnumValue(QVariant& object, int value, const QHash& mappings) const; - - virtual const QVector& getMetaFields() const; - virtual int getFieldIndex(const QByteArray& name) const; - virtual void setField(QVariant& object, int index, const QVariant& value) const; - virtual QVariant getField(const QVariant& object, int index) const; - - virtual Category getCategory() const; - - virtual int getBits() const; - virtual QMetaEnum getMetaEnum() const; - - virtual const TypeStreamer* getKeyStreamer() const; - virtual const TypeStreamer* getValueStreamer() const; - - virtual void insert(QVariant& object, const QVariant& value) const; - virtual void insert(QVariant& object, const QVariant& key, const QVariant& value) const; - virtual bool remove(QVariant& object, const QVariant& key) const; - - virtual QVariant getValue(const QVariant& object, const QVariant& key) const; - - virtual void prune(QVariant& object, int size) const; - virtual QVariant getValue(const QVariant& object, int index) const; - virtual void setValue(QVariant& object, int index, const QVariant& value) const; - -protected: - - friend class Bitstream; - - int _type; - TypeStreamerPointer _self; ///< set/used for built-in types (never deleted), to obtain shared pointers -}; - -QDebug& operator<<(QDebug& debug, const TypeStreamer* typeStreamer); - -QDebug& operator<<(QDebug& debug, const QMetaObject* metaObject); - -/// A streamer that works with Bitstream's operators. -template class SimpleTypeStreamer : public TypeStreamer { -public: - - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const { - return writer.getData(value.value()); } - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const { - T rawValue; reader.putData(data, rawValue); value = QVariant::fromValue(rawValue); } - virtual bool equal(const QVariant& first, const QVariant& second) const { return first.value() == second.value(); } - virtual void write(Bitstream& out, const QVariant& value) const { out << value.value(); } - virtual QVariant read(Bitstream& in) const { T value; in >> value; return QVariant::fromValue(value); } - virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - out.writeDelta(value.value(), reference.value()); } - virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - T rawValue; in.readDelta(rawValue, reference.value()); value = QVariant::fromValue(rawValue); } - virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const { - out.writeRawDelta(value.value(), reference.value()); } - virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const { - T rawValue; in.readRawDelta(rawValue, reference.value()); value = QVariant::fromValue(rawValue); } -}; - -/// A streamer class for enumerated types. -class EnumTypeStreamer : public TypeStreamer { -public: - - EnumTypeStreamer(const QMetaObject* metaObject, const char* name); - EnumTypeStreamer(const QMetaEnum& metaEnum); - - virtual const char* getName() const; - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual Category getCategory() const; - virtual int getBits() const; - virtual QMetaEnum getMetaEnum() const; - virtual bool equal(const QVariant& first, const QVariant& second) const; - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual void writeDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const; - virtual void readDelta(Bitstream& in, QVariant& value, const QVariant& reference) const; - virtual void writeRawDelta(Bitstream& out, const QVariant& value, const QVariant& reference) const; - virtual void readRawDelta(Bitstream& in, QVariant& value, const QVariant& reference) const; - virtual void setEnumValue(QVariant& object, int value, const QHash& mappings) const; - -private: - - const QMetaObject* _metaObject; - const char* _enumName; - QByteArray _name; - QMetaEnum _metaEnum; - int _bits; -}; - -/// A streamer class for enums that maps to a local type. -class MappedEnumTypeStreamer : public TypeStreamer { -public: - - MappedEnumTypeStreamer(const TypeStreamer* baseStreamer, int bits, const QHash& mappings); - - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const; - -private: - - const TypeStreamer* _baseStreamer; - int _bits; - QHash _mappings; -}; - -/// Base class for generic type streamers, which contain all the metadata required to write out a type. -class GenericTypeStreamer : public TypeStreamer { -public: - - GenericTypeStreamer(const QByteArray& name); - - virtual const char* getName() const; - virtual void putJSONVariantData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual QVariant readVariant(Bitstream& in) const; - -protected: - - friend class Bitstream; - friend class JSONReader; - - QByteArray _name; - WeakTypeStreamerPointer _weakSelf; ///< promoted to strong references in GenericValue when reading -}; - -/// A streamer for generic enums. -class GenericEnumTypeStreamer : public GenericTypeStreamer { -public: - - GenericEnumTypeStreamer(const QByteArray& name, const QVector& values, int bits, const QByteArray& hash); - - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual Category getCategory() const; - -private: - - QVector _values; - int _bits; - QByteArray _hash; -}; - -/// A streamer for types compiled by mtc. -template class StreamableTypeStreamer : public SimpleTypeStreamer { -public: - - virtual TypeStreamer::Category getCategory() const { return TypeStreamer::STREAMABLE_CATEGORY; } - virtual const QVector& getMetaFields() const { return T::getMetaFields(); } - virtual int getFieldIndex(const QByteArray& name) const { return T::getFieldIndex(name); } - virtual void setField(QVariant& object, int index, const QVariant& value) const { - static_cast(object.data())->setField(index, value); } - virtual QVariant getField(const QVariant& object, int index) const { - return static_cast(object.constData())->getField(index); } -}; - -typedef QPair StreamerIndexPair; - -/// A streamer class for streamables that maps to a local type. -class MappedStreamableTypeStreamer : public TypeStreamer { -public: - - MappedStreamableTypeStreamer(const TypeStreamer* baseStreamer, const QVector& fields); - - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const; - -private: - - const TypeStreamer* _baseStreamer; - QVector _fields; -}; - -/// A streamer for generic enums. -class GenericStreamableTypeStreamer : public GenericTypeStreamer { -public: - - GenericStreamableTypeStreamer(const QByteArray& name, const QVector& fields, const QByteArray& hash); - - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual Category getCategory() const; - -private: - - QVector _fields; - QByteArray _hash; -}; - -/// Base template for collection streamers. -template class CollectionTypeStreamer : public SimpleTypeStreamer { -}; - -/// A streamer for list types. -template class CollectionTypeStreamer > : public SimpleTypeStreamer > { -public: - - virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); } - virtual TypeStreamer::Category getCategory() const { return TypeStreamer::LIST_CATEGORY; } - virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId()); } - virtual void insert(QVariant& object, const QVariant& value) const { - static_cast*>(object.data())->append(value.value()); } - virtual void prune(QVariant& object, int size) const { - QList* list = static_cast*>(object.data()); list->erase(list->begin() + size, list->end()); } - virtual QVariant getValue(const QVariant& object, int index) const { - return QVariant::fromValue(static_cast*>(object.constData())->at(index)); } - virtual void setValue(QVariant& object, int index, const QVariant& value) const { - static_cast*>(object.data())->replace(index, value.value()); } -}; - -/// A streamer for vector types. -template class CollectionTypeStreamer > : public SimpleTypeStreamer > { -public: - - virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); } - virtual TypeStreamer::Category getCategory() const { return TypeStreamer::LIST_CATEGORY; } - virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId()); } - virtual void insert(QVariant& object, const QVariant& value) const { - static_cast*>(object.data())->append(value.value()); } - virtual void prune(QVariant& object, int size) const { - QVector* list = static_cast*>(object.data()); list->erase(list->begin() + size, list->end()); } - virtual QVariant getValue(const QVariant& object, int index) const { - return QVariant::fromValue(static_cast*>(object.constData())->at(index)); } - virtual void setValue(QVariant& object, int index, const QVariant& value) const { - static_cast*>(object.data())->replace(index, value.value()); } -}; - -/// A streamer for lists that maps to a local type. -class MappedListTypeStreamer : public TypeStreamer { -public: - - MappedListTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer); - - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const; - -protected: - - const TypeStreamer* _baseStreamer; - TypeStreamerPointer _valueStreamer; -}; - -/// A streamer for generic lists. -class GenericListTypeStreamer : public GenericTypeStreamer { -public: - - GenericListTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer); - - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual Category getCategory() const; - -protected: - - TypeStreamerPointer _valueStreamer; -}; - -/// A streamer for set types. -template class CollectionTypeStreamer > : public SimpleTypeStreamer > { -public: - - virtual void writeMetadata(Bitstream& out, bool full) const { out << getValueStreamer(); } - virtual TypeStreamer::Category getCategory() const { return TypeStreamer::SET_CATEGORY; } - virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId()); } - virtual void insert(QVariant& object, const QVariant& value) const { - static_cast*>(object.data())->insert(value.value()); } - virtual bool remove(QVariant& object, const QVariant& key) const { - return static_cast*>(object.data())->remove(key.value()); } -}; - -/// A streamer for sets that maps to a local type. -class MappedSetTypeStreamer : public MappedListTypeStreamer { -public: - - MappedSetTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& valueStreamer); - - virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const; -}; - -/// A streamer for generic sets. -class GenericSetTypeStreamer : public GenericListTypeStreamer { -public: - - GenericSetTypeStreamer(const QByteArray& name, const TypeStreamerPointer& valueStreamer); - - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual Category getCategory() const; -}; - -/// A streamer for hash types. -template class CollectionTypeStreamer > : public SimpleTypeStreamer > { -public: - - virtual void writeMetadata(Bitstream& out, bool full) const { out << getKeyStreamer() << getValueStreamer(); } - virtual TypeStreamer::Category getCategory() const { return TypeStreamer::MAP_CATEGORY; } - virtual const TypeStreamer* getKeyStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId()); } - virtual const TypeStreamer* getValueStreamer() const { return Bitstream::getTypeStreamer(qMetaTypeId()); } - virtual void insert(QVariant& object, const QVariant& key, const QVariant& value) const { - static_cast*>(object.data())->insert(key.value(), value.value()); } - virtual bool remove(QVariant& object, const QVariant& key) const { - return static_cast*>(object.data())->remove(key.value()); } - virtual QVariant getValue(const QVariant& object, const QVariant& key) const { - return QVariant::fromValue(static_cast*>(object.constData())->value(key.value())); } -}; - -/// A streamer for maps that maps to a local type. -class MappedMapTypeStreamer : public TypeStreamer { -public: - - MappedMapTypeStreamer(const TypeStreamer* baseStreamer, const TypeStreamerPointer& keyStreamer, - const TypeStreamerPointer& valueStreamer); - - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual void readRawDelta(Bitstream& in, QVariant& object, const QVariant& reference) const; - -private: - - const TypeStreamer* _baseStreamer; - TypeStreamerPointer _keyStreamer; - TypeStreamerPointer _valueStreamer; -}; - -/// A streamer for generic maps. -class GenericMapTypeStreamer : public GenericTypeStreamer { -public: - - GenericMapTypeStreamer(const QByteArray& name, const TypeStreamerPointer& keyStreamer, - const TypeStreamerPointer& valueStreamer); - - virtual void writeMetadata(Bitstream& out, bool full) const; - virtual QJsonValue getJSONMetadata(JSONWriter& writer) const; - virtual QJsonValue getJSONData(JSONWriter& writer, const QVariant& value) const; - virtual void putJSONData(JSONReader& reader, const QJsonValue& data, QVariant& value) const; - virtual void write(Bitstream& out, const QVariant& value) const; - virtual QVariant read(Bitstream& in) const; - virtual Category getCategory() const; - -private: - - TypeStreamerPointer _keyStreamer; - TypeStreamerPointer _valueStreamer; -}; - -/// A streamer class for generic values. -class GenericValueStreamer : public SimpleTypeStreamer { -public: - - QJsonValue getJSONVariantData(JSONWriter& writer, const QVariant& value) const; - virtual void writeVariant(Bitstream& out, const QVariant& value) const; -}; - -/// Macro for registering simple type streamers. Typically, one would use this at the top level of the source file -/// associated with the type. -#define REGISTER_SIMPLE_TYPE_STREAMER(X) static int X##Streamer = \ - Bitstream::registerTypeStreamer(qMetaTypeId(), new SimpleTypeStreamer()); - -/// Macro for registering collection type (QList, QVector, QSet, QMap) streamers. Typically, one would use this at the top -/// level of the source file associated with the type. -#define REGISTER_COLLECTION_TYPE_STREAMER(X) static int x##Streamer = \ - Bitstream::registerTypeStreamer(qMetaTypeId(), new CollectionTypeStreamer()); - -/// Declares the metatype and the streaming operators. Typically, one would use this immediately after the definition of a -/// type flagged as STREAMABLE in its header file. The type should have a no-argument constructor. The last lines of this -/// macro ensure that the generated file will be included in the link phase. -#ifdef _WIN32 -#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \ - Bitstream& operator<<(Bitstream& out, const X& obj); \ - Bitstream& operator>>(Bitstream& in, X& obj); \ - template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \ - template<> void Bitstream::readRawDelta(X& value, const X& reference); \ - template<> QJsonValue JSONWriter::getData(const X& value); \ - template<> void JSONReader::putData(const QJsonValue& data, X& value); \ - bool operator==(const X& first, const X& second); \ - bool operator!=(const X& first, const X& second); \ - static const int* _TypePtr##X = &X::Type; -#elif __GNUC__ -#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \ - Bitstream& operator<<(Bitstream& out, const X& obj); \ - Bitstream& operator>>(Bitstream& in, X& obj); \ - template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \ - template<> void Bitstream::readRawDelta(X& value, const X& reference); \ - template<> QJsonValue JSONWriter::getData(const X& value); \ - template<> void JSONReader::putData(const QJsonValue& data, X& value); \ - bool operator==(const X& first, const X& second); \ - bool operator!=(const X& first, const X& second); \ - __attribute__((unused)) static const int* _TypePtr##X = &X::Type; -#else -#define STRINGIFY(x) #x -#define DECLARE_STREAMABLE_METATYPE(X) Q_DECLARE_METATYPE(X) \ - Bitstream& operator<<(Bitstream& out, const X& obj); \ - Bitstream& operator>>(Bitstream& in, X& obj); \ - template<> void Bitstream::writeRawDelta(const X& value, const X& reference); \ - template<> void Bitstream::readRawDelta(X& value, const X& reference); \ - template<> QJsonValue JSONWriter::getData(const X& value); \ - template<> void JSONReader::putData(const QJsonValue& data, X& value); \ - bool operator==(const X& first, const X& second); \ - bool operator!=(const X& first, const X& second); \ - static const int* _TypePtr##X = &X::Type; \ - _Pragma(STRINGIFY(unused(_TypePtr##X))) -#endif - -/// Declares an enum metatype. This is used when one desires to use an enum defined in a QObject outside of that class's -/// direct properties. Typically, one would use this immediately after the definition of the QObject containing the enum -/// in its header file. -#define DECLARE_ENUM_METATYPE(S, N) Q_DECLARE_METATYPE(S::N) \ - Bitstream& operator<<(Bitstream& out, const S::N& obj); \ - Bitstream& operator>>(Bitstream& in, S::N& obj); \ - template<> inline void Bitstream::writeRawDelta(const S::N& value, const S::N& reference) { *this << value; } \ - template<> inline void Bitstream::readRawDelta(S::N& value, const S::N& reference) { *this >> value; } \ - template<> inline QJsonValue JSONWriter::getData(const S::N& value) { return (int)value; } \ - template<> inline void JSONReader::putData(const QJsonValue& data, S::N& value) { value = (S::N)data.toInt(); } - -/// Implements an enum metatype. This performs the implementation of the previous macro, and would normally be used at the -/// top level of the source file associated with the QObject containing the enum. -#define IMPLEMENT_ENUM_METATYPE(S, N) \ - static int S##N##MetaTypeId = registerEnumMetaType(&S::staticMetaObject, #N); \ - Bitstream& operator<<(Bitstream& out, const S::N& obj) { \ - static int bits = Bitstream::getTypeStreamer(qMetaTypeId())->getBits(); \ - return out.write(&obj, bits); \ - } \ - Bitstream& operator>>(Bitstream& in, S::N& obj) { \ - static int bits = Bitstream::getTypeStreamer(qMetaTypeId())->getBits(); \ - obj = (S::N)0; \ - return in.read(&obj, bits); \ - } - -/// Registers a simple type and its streamer. This would typically be used at the top level of the source file associated with -/// the type, and combines the registration of the type with the Qt metatype system with the registration of a simple type -/// streamer. -/// \return the metatype id -template int registerSimpleMetaType() { - int type = qRegisterMetaType(); - Bitstream::registerTypeStreamer(type, new SimpleTypeStreamer()); - return type; -} - -/// Registers an enum type and its streamer. Rather than using this directly, consider using the IMPLEMENT_ENUM_METATYPE -/// macro. -/// \return the metatype id -template int registerEnumMetaType(const QMetaObject* metaObject, const char* name) { - int type = qRegisterMetaType(); - Bitstream::registerTypeStreamer(type, new EnumTypeStreamer(metaObject, name)); - return type; -} - -/// Registers a streamable type and its streamer. Rather than using this directly, consider using the -/// DECLARE_STREAMABLE_METATYPE macro and the mtc code generation tool. -/// \return the metatype id -template int registerStreamableMetaType() { - int type = qRegisterMetaType(); - Bitstream::registerTypeStreamer(type, new StreamableTypeStreamer()); - return type; -} - -/// Registers a collection type and its streamer. This would typically be used at the top level of the source file associated -/// with the type, and combines the registration of the type with the Qt metatype system with the registration of a collection -/// type streamer. -/// \return the metatype id -template int registerCollectionMetaType() { - int type = qRegisterMetaType(); - Bitstream::registerTypeStreamer(type, new CollectionTypeStreamer()); - return type; -} - -/// Flags a class as streamable. Use as you would Q_OBJECT: as the first line of a class definition, before any members or -/// access qualifiers. Typically, one would follow the definition with DECLARE_STREAMABLE_METATYPE. The mtc tool looks for -/// this macro in order to generate streaming (etc.) code for types. -#define STREAMABLE public: \ - static const int Type; \ - static const QVector& getMetaFields(); \ - static int getFieldIndex(const QByteArray& name); \ - void setField(int index, const QVariant& value); \ - QVariant getField(int index) const; \ - private: \ - static QHash createFieldIndices(); - -/// Flags a (public) field within or base class of a streamable type as streaming. Use before all base classes or fields that -/// you want to stream. -#define STREAM - -#endif // hifi_Bitstream_h diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp deleted file mode 100644 index ae4a96ad4f..0000000000 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ /dev/null @@ -1,952 +0,0 @@ -// -// DatagramSequencer.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/20/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include - -#include - -#include "DatagramSequencer.h" -#include "MetavoxelMessages.h" - -// in sequencer parlance, a "packet" may consist of multiple datagrams. clarify when we refer to actual datagrams -const int MAX_DATAGRAM_SIZE = MAX_PACKET_SIZE; - -const int DEFAULT_MAX_PACKET_SIZE = 3000; - -// the default slow-start threshold, which will be lowered quickly when we first encounter packet loss -const float DEFAULT_SLOW_START_THRESHOLD = 1000.0f; - -DatagramSequencer::DatagramSequencer(const QByteArray& datagramHeader, QObject* parent) : - QObject(parent), - _outgoingPacketStream(&_outgoingPacketData, QIODevice::WriteOnly), - _outputStream(_outgoingPacketStream, Bitstream::NO_METADATA, Bitstream::NO_GENERICS, this), - _incomingDatagramStream(&_incomingDatagramBuffer), - _datagramHeaderSize(datagramHeader.size()), - _outgoingPacketNumber(0), - _outgoingDatagram(MAX_DATAGRAM_SIZE, 0), - _outgoingDatagramBuffer(&_outgoingDatagram), - _outgoingDatagramStream(&_outgoingDatagramBuffer), - _incomingPacketNumber(0), - _incomingPacketStream(&_incomingPacketData, QIODevice::ReadOnly), - _inputStream(_incomingPacketStream, Bitstream::NO_METADATA, Bitstream::NO_GENERICS, this), - _receivedHighPriorityMessages(0), - _maxPacketSize(DEFAULT_MAX_PACKET_SIZE), - _packetsPerGroup(1.0f), - _packetsToWrite(0.0f), - _slowStartThreshold(DEFAULT_SLOW_START_THRESHOLD), - _packetRateIncreasePacketNumber(0), - _packetRateDecreasePacketNumber(0), - _packetDropCount(0) { - - _outgoingPacketStream.setByteOrder(QDataStream::LittleEndian); - _incomingDatagramStream.setByteOrder(QDataStream::LittleEndian); - _incomingPacketStream.setByteOrder(QDataStream::LittleEndian); - _outgoingDatagramStream.setByteOrder(QDataStream::LittleEndian); - - connect(&_outputStream, SIGNAL(sharedObjectCleared(int)), SLOT(sendClearSharedObjectMessage(int))); - connect(this, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleHighPriorityMessage(const QVariant&))); - - memcpy(_outgoingDatagram.data(), datagramHeader.constData(), _datagramHeaderSize); -} - -void DatagramSequencer::sendHighPriorityMessage(const QVariant& data) { - HighPriorityMessage message = { data, _outgoingPacketNumber + 1 }; - _highPriorityMessages.append(message); -} - -ReliableChannel* DatagramSequencer::getReliableOutputChannel(int index) { - ReliableChannel*& channel = _reliableOutputChannels[index]; - if (!channel) { - channel = new ReliableChannel(this, index, true); - } - return channel; -} - -ReliableChannel* DatagramSequencer::getReliableInputChannel(int index) { - ReliableChannel*& channel = _reliableInputChannels[index]; - if (!channel) { - channel = new ReliableChannel(this, index, false); - } - return channel; -} - -void DatagramSequencer::addReliableChannelStats(int& sendProgress, int& sendTotal, - int& receiveProgress, int& receiveTotal) const { - foreach (ReliableChannel* channel, _reliableOutputChannels) { - int sent, total; - if (channel->getMessageSendProgress(sent, total)) { - sendProgress += sent; - sendTotal += total; - } - } - foreach (ReliableChannel* channel, _reliableInputChannels) { - int received, total; - if (channel->getMessageReceiveProgress(received, total)) { - receiveProgress += received; - receiveTotal += total; - } - } -} - -int DatagramSequencer::notePacketGroup(int desiredPackets) { - // figure out how much data we have enqueued and increase the number of packets desired - int totalAvailable = 0; - foreach (ReliableChannel* channel, _reliableOutputChannels) { - totalAvailable += channel->getBytesAvailable(); - } - desiredPackets += (totalAvailable / _maxPacketSize); - - // increment our packet counter and subtract/return the integer portion - _packetsToWrite += _packetsPerGroup; - int wholePackets = (int)_packetsToWrite; - _packetsToWrite -= wholePackets; - wholePackets = qMin(wholePackets, desiredPackets); - - // if we don't want to send any more, push out the rate increase number past the group - if (desiredPackets <= _packetsPerGroup) { - _packetRateIncreasePacketNumber = _outgoingPacketNumber + wholePackets + 1; - } - - // likewise, if we're only sending one packet, don't let its loss cause rate decrease - if (wholePackets == 1) { - _packetRateDecreasePacketNumber = _outgoingPacketNumber + 2; - } - - return wholePackets; -} - -Bitstream& DatagramSequencer::startPacket() { - // start with the list of acknowledgements - _outgoingPacketStream << (quint32)_receiveRecords.size(); - foreach (const ReceiveRecord& record, _receiveRecords) { - _outgoingPacketStream << (quint32)record.packetNumber; - } - - // return the stream, allowing the caller to write the rest - return _outputStream; -} - -void DatagramSequencer::endPacket() { - // write the high-priority messages - _outputStream << _highPriorityMessages.size(); - foreach (const HighPriorityMessage& message, _highPriorityMessages) { - _outputStream << message.data; - } - _outputStream.flush(); - - // if we have space remaining, send some data from our reliable channels - int remaining = _maxPacketSize - _outgoingPacketStream.device()->pos(); - const int MINIMUM_RELIABLE_SIZE = sizeof(quint32) * 5; // count, channel number, segment count, offset, size - QVector spans; - if (remaining > MINIMUM_RELIABLE_SIZE) { - appendReliableData(remaining, spans); - } else { - _outgoingPacketStream << (quint32)0; - } - - sendPacket(QByteArray::fromRawData(_outgoingPacketData.constData(), _outgoingPacketStream.device()->pos()), spans); - _outgoingPacketStream.device()->seek(0); -} - -void DatagramSequencer::cancelPacket() { - _outputStream.reset(); - _outputStream.getAndResetWriteMappings(); - _outgoingPacketStream.device()->seek(0); -} - -/// Simple RAII-style object to keep a device open when in scope. -class QIODeviceOpener { -public: - - QIODeviceOpener(QIODevice* device, QIODevice::OpenMode mode) : _device(device) { _device->open(mode); } - ~QIODeviceOpener() { _device->close(); } - -private: - - QIODevice* _device; -}; - -void DatagramSequencer::receivedDatagram(const QByteArray& datagram) { - _incomingDatagramBuffer.setData(datagram.constData() + _datagramHeaderSize, datagram.size() - _datagramHeaderSize); - QIODeviceOpener opener(&_incomingDatagramBuffer, QIODevice::ReadOnly); - - // read the sequence number - int sequenceNumber; - _incomingDatagramStream >> sequenceNumber; - - // if it's less than the last, ignore - if (sequenceNumber < _incomingPacketNumber) { - return; - } - - // read the size and offset - quint32 packetSize, offset; - _incomingDatagramStream >> packetSize >> offset; - - // if it's greater, reset - if (sequenceNumber > _incomingPacketNumber) { - _incomingPacketNumber = sequenceNumber; - _incomingPacketData.resize(packetSize); - _offsetsReceived.clear(); - _offsetsReceived.insert(offset); - _remainingBytes = packetSize; - - } else { - // make sure it's not a duplicate - if (_offsetsReceived.contains(offset)) { - return; - } - _offsetsReceived.insert(offset); - } - - // copy in the data - memcpy(_incomingPacketData.data() + offset, _incomingDatagramBuffer.data().constData() + _incomingDatagramBuffer.pos(), - _incomingDatagramBuffer.bytesAvailable()); - - // see if we're done - if ((_remainingBytes -= _incomingDatagramBuffer.bytesAvailable()) > 0) { - return; - } - - // read the list of acknowledged packets - quint32 acknowledgementCount; - _incomingPacketStream >> acknowledgementCount; - for (quint32 i = 0; i < acknowledgementCount; i++) { - quint32 packetNumber; - _incomingPacketStream >> packetNumber; - if (_sendRecords.isEmpty()) { - continue; - } - int index = packetNumber - _sendRecords.first().packetNumber; - if (index < 0 || index >= _sendRecords.size()) { - continue; - } - QList::iterator it = _sendRecords.begin(); - for (int i = 0; i < index; i++) { - sendRecordLost(*it++); - } - sendRecordAcknowledged(*it); - emit sendAcknowledged(index); - _sendRecords.erase(_sendRecords.begin(), it + 1); - } - - try { - // alert external parties so that they can read the middle - emit readyToRead(_inputStream); - - // read and dispatch the high-priority messages - int highPriorityMessageCount; - _inputStream >> highPriorityMessageCount; - int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; - for (int i = 0; i < highPriorityMessageCount; i++) { - QVariant data; - _inputStream >> data; - if (i >= _receivedHighPriorityMessages) { - emit receivedHighPriorityMessage(data); - } - } - _receivedHighPriorityMessages = highPriorityMessageCount; - - // read the reliable data, if any - quint32 reliableChannels; - _incomingPacketStream >> reliableChannels; - for (quint32 i = 0; i < reliableChannels; i++) { - quint32 channelIndex; - _incomingPacketStream >> channelIndex; - getReliableInputChannel(channelIndex)->readData(_incomingPacketStream); - } - - // record the receipt - ReceiveRecord record = { _incomingPacketNumber, _inputStream.getAndResetReadMappings(), newHighPriorityMessages }; - _receiveRecords.append(record); - - emit receiveRecorded(); - - } catch (const BitstreamException& e) { - qWarning() << "Error reading datagram:" << e.getDescription(); - } - - _incomingPacketStream.device()->seek(0); - _inputStream.reset(); -} - -void DatagramSequencer::sendClearSharedObjectMessage(int id) { - // send it low-priority unless the channel has messages disabled - ReliableChannel* channel = getReliableOutputChannel(); - if (channel->getMessagesEnabled()) { - ClearMainChannelSharedObjectMessage message = { id }; - channel->sendMessage(QVariant::fromValue(message)); - - } else { - ClearSharedObjectMessage message = { id }; - sendHighPriorityMessage(QVariant::fromValue(message)); - } -} - -void DatagramSequencer::handleHighPriorityMessage(const QVariant& data) { - if (data.userType() == ClearSharedObjectMessage::Type) { - _inputStream.clearSharedObject(data.value().id); - } -} - -void DatagramSequencer::clearReliableChannel(QObject* object) { - ReliableChannel* channel = static_cast(object); - (channel->isOutput() ? _reliableOutputChannels : _reliableInputChannels).remove(channel->getIndex()); -} - -void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) { - // stop acknowledging the recorded packets - while (!_receiveRecords.isEmpty() && _receiveRecords.first().packetNumber <= record.lastReceivedPacketNumber) { - emit receiveAcknowledged(0); - const ReceiveRecord& received = _receiveRecords.first(); - _inputStream.persistReadMappings(received.mappings); - _receivedHighPriorityMessages -= received.newHighPriorityMessages; - _receiveRecords.removeFirst(); - } - _outputStream.persistWriteMappings(record.mappings); - - // remove the received high priority messages - for (int i = _highPriorityMessages.size() - 1; i >= 0; i--) { - if (_highPriorityMessages.at(i).firstPacketNumber <= record.packetNumber) { - _highPriorityMessages.erase(_highPriorityMessages.begin(), _highPriorityMessages.begin() + i + 1); - break; - } - } - - // acknowledge the received spans - foreach (const ChannelSpan& span, record.spans) { - ReliableChannel* channel = _reliableOutputChannels.value(span.channel); - if (channel) { - channel->spanAcknowledged(span); - } - } - - // increase the packet rate with every ack until we pass the slow start threshold; then, every round trip - if (record.packetNumber >= _packetRateIncreasePacketNumber) { - if (_packetsPerGroup >= _slowStartThreshold) { - _packetRateIncreasePacketNumber = _outgoingPacketNumber + 1; - } - _packetsPerGroup += 1.0f; - } -} - -void DatagramSequencer::sendRecordLost(const SendRecord& record) { - // notify the channels of their lost spans - foreach (const ChannelSpan& span, record.spans) { - ReliableChannel* channel = _reliableOutputChannels.value(span.channel); - if (channel) { - channel->spanLost(record.packetNumber, _outgoingPacketNumber + 1); - } - } - - // if we've lost three in a row, halve the rate and remember as threshold - if (_packetDropCount == 0 || record.packetNumber == _lastPacketDropped + 1) { - _packetDropCount++; - _lastPacketDropped = record.packetNumber; - const int CONSECUTIVE_DROPS_BEFORE_REDUCTION = 1; - if (_packetDropCount >= CONSECUTIVE_DROPS_BEFORE_REDUCTION && record.packetNumber >= _packetRateDecreasePacketNumber) { - _packetsPerGroup = qMax(_packetsPerGroup * 0.5f, 1.0f); - _slowStartThreshold = _packetsPerGroup; - _packetRateDecreasePacketNumber = _outgoingPacketNumber + 1; - } - } else { - _packetDropCount = 0; - } -} - -void DatagramSequencer::appendReliableData(int bytes, QVector& spans) { - // gather total number of bytes to write, priority - int totalBytes = 0; - float totalPriority = 0.0f; - int totalChannels = 0; - foreach (ReliableChannel* channel, _reliableOutputChannels) { - int channelBytes = channel->getBytesAvailable(); - if (channelBytes > 0) { - totalBytes += channelBytes; - totalPriority += channel->getPriority(); - totalChannels++; - } - } - _outgoingPacketStream << (quint32)totalChannels; - if (totalChannels == 0) { - return; - } - totalBytes = qMin(bytes, totalBytes); - - foreach (ReliableChannel* channel, _reliableOutputChannels) { - int channelBytes = channel->getBytesAvailable(); - if (channelBytes == 0) { - continue; - } - _outgoingPacketStream << (quint32)channel->getIndex(); - channelBytes = qMin(channelBytes, (int)(totalBytes * channel->getPriority() / totalPriority)); - channel->writeData(_outgoingPacketStream, channelBytes, spans); - totalBytes -= channelBytes; - totalPriority -= channel->getPriority(); - } -} - -void DatagramSequencer::sendPacket(const QByteArray& packet, const QVector& spans) { - QIODeviceOpener opener(&_outgoingDatagramBuffer, QIODevice::WriteOnly); - - // increment the packet number - _outgoingPacketNumber++; - - // record the send - SendRecord record = { _outgoingPacketNumber, _receiveRecords.isEmpty() ? 0 : _receiveRecords.last().packetNumber, - _outputStream.getAndResetWriteMappings(), spans }; - _sendRecords.append(record); - - emit sendRecorded(); - - // write the sequence number and size, which are the same between all fragments - _outgoingDatagramBuffer.seek(_datagramHeaderSize); - _outgoingDatagramStream << (quint32)_outgoingPacketNumber; - _outgoingDatagramStream << (quint32)packet.size(); - int initialPosition = _outgoingDatagramBuffer.pos(); - - // break the packet into MTU-sized datagrams - int offset = 0; - do { - _outgoingDatagramBuffer.seek(initialPosition); - _outgoingDatagramStream << (quint32)offset; - - int payloadSize = qMin((int)(_outgoingDatagram.size() - _outgoingDatagramBuffer.pos()), packet.size() - offset); - memcpy(_outgoingDatagram.data() + _outgoingDatagramBuffer.pos(), packet.constData() + offset, payloadSize); - - emit readyToWrite(QByteArray::fromRawData(_outgoingDatagram.constData(), _outgoingDatagramBuffer.pos() + payloadSize)); - - offset += payloadSize; - - } while(offset < packet.size()); -} - -const int INITIAL_CIRCULAR_BUFFER_CAPACITY = 16; - -CircularBuffer::CircularBuffer(QObject* parent) : - QIODevice(parent), - _data(INITIAL_CIRCULAR_BUFFER_CAPACITY, 0), - _position(0), - _size(0), - _offset(0) { -} - -void CircularBuffer::append(const char* data, int length) { - // resize to fit - int oldSize = _size; - resize(_size + length); - - // write our data in up to two segments: one from the position to the end, one from the beginning - int end = (_position + oldSize) % _data.size(); - int firstSegment = qMin(length, _data.size() - end); - memcpy(_data.data() + end, data, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - memcpy(_data.data(), data + firstSegment, secondSegment); - } -} - -void CircularBuffer::remove(int length) { - _position = (_position + length) % _data.size(); - _size -= length; -} - -QByteArray CircularBuffer::readBytes(int offset, int length) const { - QByteArray bytes(length, 0); - readBytes(offset, length, bytes.data()); - return bytes; -} - -void CircularBuffer::readBytes(int offset, int length, char* data) const { - // read in up to two segments - QByteArray array; - int start = (_position + offset) % _data.size(); - int firstSegment = qMin(length, _data.size() - start); - memcpy(data, _data.constData() + start, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - memcpy(data + firstSegment, _data.constData(), secondSegment); - } -} - -void CircularBuffer::writeBytes(int offset, int length, const char* data) { - // write in up to two segments - int start = (_position + offset) % _data.size(); - int firstSegment = qMin(length, _data.size() - start); - memcpy(_data.data() + start, data, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - memcpy(_data.data(), data + firstSegment, secondSegment); - } -} - -void CircularBuffer::writeToStream(int offset, int length, QDataStream& out) const { - // write in up to two segments - int start = (_position + offset) % _data.size(); - int firstSegment = qMin(length, _data.size() - start); - out.writeRawData(_data.constData() + start, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - out.writeRawData(_data.constData(), secondSegment); - } -} - -void CircularBuffer::readFromStream(int offset, int length, QDataStream& in) { - // resize to fit - int requiredSize = offset + length; - if (requiredSize > _size) { - resize(requiredSize); - } - - // read in up to two segments - int start = (_position + offset) % _data.size(); - int firstSegment = qMin(length, _data.size() - start); - in.readRawData(_data.data() + start, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - in.readRawData(_data.data(), secondSegment); - } -} - -void CircularBuffer::appendToBuffer(int offset, int length, CircularBuffer& buffer) const { - // append in up to two segments - int start = (_position + offset) % _data.size(); - int firstSegment = qMin(length, _data.size() - start); - buffer.append(_data.constData() + start, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - buffer.append(_data.constData(), secondSegment); - } -} - -bool CircularBuffer::atEnd() const { - return _offset >= _size; -} - -qint64 CircularBuffer::bytesAvailable() const { - return _size - _offset; -} - -bool CircularBuffer::canReadLine() const { - for (int offset = _offset; offset < _size; offset++) { - if (_data.at((_position + offset) % _data.size()) == '\n') { - return true; - } - } - return false; -} - -bool CircularBuffer::open(OpenMode flags) { - return QIODevice::open(flags | QIODevice::Unbuffered); -} - -qint64 CircularBuffer::pos() const { - return _offset; -} - -bool CircularBuffer::seek(qint64 pos) { - if (pos < 0 || pos > _size) { - return false; - } - _offset = pos; - return true; -} - -qint64 CircularBuffer::size() const { - return _size; -} - -qint64 CircularBuffer::readData(char* data, qint64 length) { - int readable = qMin((int)length, _size - _offset); - - // read in up to two segments - int start = (_position + _offset) % _data.size(); - int firstSegment = qMin((int)length, _data.size() - start); - memcpy(data, _data.constData() + start, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - memcpy(data + firstSegment, _data.constData(), secondSegment); - } - _offset += readable; - return readable; -} - -qint64 CircularBuffer::writeData(const char* data, qint64 length) { - // resize to fit - int requiredSize = _offset + length; - if (requiredSize > _size) { - resize(requiredSize); - } - - // write in up to two segments - int start = (_position + _offset) % _data.size(); - int firstSegment = qMin((int)length, _data.size() - start); - memcpy(_data.data() + start, data, firstSegment); - int secondSegment = length - firstSegment; - if (secondSegment > 0) { - memcpy(_data.data(), data + firstSegment, secondSegment); - } - _offset += length; - return length; -} - -void CircularBuffer::resize(int size) { - if (size > _data.size()) { - // double our capacity until we can fit the desired length - int newCapacity = _data.size(); - do { - newCapacity *= 2; - } while (size > newCapacity); - - int oldCapacity = _data.size(); - _data.resize(newCapacity); - - int trailing = _position + _size - oldCapacity; - if (trailing > 0) { - memcpy(_data.data() + oldCapacity, _data.constData(), trailing); - } - } - _size = size; -} - -SpanList::SpanList() : _totalSet(0) { -} - -int SpanList::set(int offset, int length) { - // if we intersect the front of the list, consume beginning spans and return advancement - if (offset <= 0) { - int intersection = offset + length; - return (intersection > 0) ? setSpans(_spans.begin(), intersection) : 0; - } - - // look for an intersection within the list - int position = 0; - for (int i = 0; i < _spans.size(); i++) { - QList::iterator it = _spans.begin() + i; - - // if we intersect the unset portion, contract it - position += it->unset; - if (offset <= position) { - int remove = position - offset; - it->unset -= remove; - - // if we continue into the set portion, expand it and consume following spans - int extra = offset + length - position; - if (extra >= 0) { - extra -= it->set; - it->set += remove; - _totalSet += remove; - if (extra > 0) { - int amount = setSpans(it + 1, extra); - _spans[i].set += amount; - _totalSet += amount; - } - // otherwise, insert a new span - } else { - Span span = { it->unset, length }; - it->unset = -extra; - _spans.insert(it, span); - _totalSet += length; - } - return 0; - } - - // if we intersect the set portion, expand it and consume following spans - position += it->set; - if (offset <= position) { - int extra = offset + length - position; - if (extra > 0) { - int amount = setSpans(it + 1, extra); - _spans[i].set += amount; - _totalSet += amount; - } - return 0; - } - } - - // add to end of list - Span span = { offset - position, length }; - _spans.append(span); - _totalSet += length; - - return 0; -} - -int SpanList::setSpans(QList::iterator it, int length) { - int remainingLength = length; - int totalRemoved = 0; - for (; it != _spans.end(); it = _spans.erase(it)) { - if (remainingLength < it->unset) { - it->unset -= remainingLength; - totalRemoved += remainingLength; - break; - } - int combined = it->unset + it->set; - remainingLength = qMax(remainingLength - combined, 0); - totalRemoved += combined; - _totalSet -= it->set; - } - return qMax(length, totalRemoved); -} - -int ReliableChannel::getBytesAvailable() const { - return _buffer.size() - _acknowledged.getTotalSet(); -} - -void ReliableChannel::startMessage() { - // write a placeholder for the length; we'll fill it in when we know what it is - _messageLengthPlaceholder = _buffer.pos(); - _dataStream << (quint32)0; -} - -void ReliableChannel::endMessage() { - _bitstream.flush(); - _bitstream.persistAndResetWriteMappings(); - - quint32 length = _buffer.pos() - _messageLengthPlaceholder; - _buffer.writeBytes(_messageLengthPlaceholder, sizeof(quint32), (const char*)&length); - - pruneOutgoingMessageStats(); - _outgoingMessageStats.append(OffsetSizePair(getBytesWritten(), length)); -} - -void ReliableChannel::sendMessage(const QVariant& message) { - startMessage(); - _bitstream << message; - endMessage(); -} - -bool ReliableChannel::getMessageSendProgress(int& sent, int& total) { - pruneOutgoingMessageStats(); - if (!_messagesEnabled || _outgoingMessageStats.isEmpty()) { - return false; - } - const OffsetSizePair& stat = _outgoingMessageStats.first(); - sent = qMax(0, stat.second - (stat.first - _offset)); - total = stat.second; - return true; -} - -bool ReliableChannel::getMessageReceiveProgress(int& received, int& total) const { - if (!_messagesEnabled || _buffer.bytesAvailable() < (int)sizeof(quint32)) { - return false; - } - quint32 length; - _buffer.readBytes(_buffer.pos(), sizeof(quint32), (char*)&length); - total = length; - received = _buffer.bytesAvailable(); - return true; -} - -void ReliableChannel::sendClearSharedObjectMessage(int id) { - ClearSharedObjectMessage message = { id }; - sendMessage(QVariant::fromValue(message)); -} - -void ReliableChannel::handleMessage(const QVariant& message, Bitstream& in) { - if (message.userType() == ClearSharedObjectMessage::Type) { - _bitstream.clearSharedObject(message.value().id); - - } else if (message.userType() == ClearMainChannelSharedObjectMessage::Type) { - static_cast(parent())->_inputStream.clearSharedObject( - message.value().id); - } -} - -ReliableChannel::ReliableChannel(DatagramSequencer* sequencer, int index, bool output) : - QObject(sequencer), - _index(index), - _output(output), - _dataStream(&_buffer), - _bitstream(_dataStream, Bitstream::NO_METADATA, Bitstream::NO_GENERICS, this), - _priority(1.0f), - _offset(0), - _writePosition(0), - _writePositionResetPacketNumber(0), - _messagesEnabled(true) { - - _buffer.open(output ? QIODevice::WriteOnly : QIODevice::ReadOnly); - _dataStream.setByteOrder(QDataStream::LittleEndian); - - connect(&_bitstream, SIGNAL(sharedObjectCleared(int)), SLOT(sendClearSharedObjectMessage(int))); - connect(this, SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&))); - - sequencer->connect(this, SIGNAL(destroyed(QObject*)), SLOT(clearReliableChannel(QObject*))); -} - -void ReliableChannel::writeData(QDataStream& out, int bytes, QVector& spans) { - if (bytes == 0) { - out << (quint32)0; - return; - } - _writePosition %= _buffer.pos(); - while (bytes > 0) { - int position = 0; - for (int i = 0; i < _acknowledged.getSpans().size(); i++) { - const SpanList::Span& span = _acknowledged.getSpans().at(i); - position += span.unset; - if (_writePosition < position) { - int start = qMax(position - span.unset, _writePosition); - int length = qMin(bytes, position - start); - writeSpan(out, start, length, spans); - writeFullSpans(out, bytes - length, i + 1, position + span.set, spans); - out << (quint32)0; - return; - } - position += span.set; - } - int leftover = _buffer.pos() - position; - position = _buffer.pos(); - - if (_writePosition < position && leftover > 0) { - int start = qMax(position - leftover, _writePosition); - int length = qMin(bytes, position - start); - writeSpan(out, start, length, spans); - writeFullSpans(out, bytes - length, 0, 0, spans); - out << (quint32)0; - return; - } - _writePosition = 0; - } -} - -void ReliableChannel::writeFullSpans(QDataStream& out, int bytes, int startingIndex, int position, - QVector& spans) { - int expandedSize = _acknowledged.getSpans().size() + 1; - for (int i = 0; i < expandedSize; i++) { - if (bytes == 0) { - return; - } - int index = (startingIndex + i) % expandedSize; - if (index == _acknowledged.getSpans().size()) { - int leftover = _buffer.pos() - position; - if (leftover > 0) { - int length = qMin(leftover, bytes); - writeSpan(out, position, length, spans); - bytes -= length; - } - position = 0; - - } else { - const SpanList::Span& span = _acknowledged.getSpans().at(index); - int length = qMin(span.unset, bytes); - writeSpan(out, position, length, spans); - bytes -= length; - position += (span.unset + span.set); - } - } -} - -int ReliableChannel::writeSpan(QDataStream& out, int position, int length, QVector& spans) { - DatagramSequencer::ChannelSpan span = { _index, _offset + position, length }; - spans.append(span); - out << (quint32)length; - out << (quint32)span.offset; - _buffer.writeToStream(position, length, out); - _writePosition = position + length; - - return length; -} - -void ReliableChannel::spanAcknowledged(const DatagramSequencer::ChannelSpan& span) { - int advancement = _acknowledged.set(span.offset - _offset, span.length); - if (advancement > 0) { - _buffer.remove(advancement); - _buffer.seek(_buffer.size()); - - _offset += advancement; - _writePosition = qMax(_writePosition - advancement, 0); - } -} - -void ReliableChannel::spanLost(int packetNumber, int nextOutgoingPacketNumber) { - // reset the write position up to once each round trip time - if (packetNumber >= _writePositionResetPacketNumber) { - _writePosition = 0; - _writePositionResetPacketNumber = nextOutgoingPacketNumber; - } -} - -void ReliableChannel::readData(QDataStream& in) { - bool readSome = false; - forever { - quint32 size; - in >> size; - if (size == 0) { - break; - } - quint32 offset; - in >> offset; - - int position = offset - _offset; - int end = position + size; - if (end <= 0) { - in.skipRawData(size); - - } else if (position < 0) { - in.skipRawData(-position); - _assemblyBuffer.readFromStream(0, end, in); - - } else { - _assemblyBuffer.readFromStream(position, size, in); - } - int advancement = _acknowledged.set(position, size); - if (advancement > 0) { - _assemblyBuffer.appendToBuffer(0, advancement, _buffer); - _assemblyBuffer.remove(advancement); - _offset += advancement; - readSome = true; - } - } - if (!readSome) { - return; - } - - forever { - // if we're expecting a message, peek into the buffer to see if we have the whole thing. - // if so, read it in, handle it, and loop back around in case there are more - if (_messagesEnabled) { - quint32 available = _buffer.bytesAvailable(); - if (available >= sizeof(quint32)) { - quint32 length; - _buffer.readBytes(_buffer.pos(), sizeof(quint32), (char*)&length); - if (available >= length) { - _dataStream.skipRawData(sizeof(quint32)); - QVariant message; - _bitstream >> message; - emit receivedMessage(message, _bitstream); - _bitstream.reset(); - _bitstream.persistAndResetReadMappings(); - continue; - } - } - // otherwise, just let whoever's listening know that data is available - } else { - emit _buffer.readyRead(); - } - break; - } - - // prune any read data from the buffer - if (_buffer.pos() > 0) { - _buffer.remove((int)_buffer.pos()); - _buffer.seek(0); - } -} - -void ReliableChannel::pruneOutgoingMessageStats() { - while (!_outgoingMessageStats.isEmpty() && _offset >= _outgoingMessageStats.first().first) { - _outgoingMessageStats.removeFirst(); - } -} - diff --git a/libraries/metavoxels/src/DatagramSequencer.h b/libraries/metavoxels/src/DatagramSequencer.h deleted file mode 100644 index 739373d137..0000000000 --- a/libraries/metavoxels/src/DatagramSequencer.h +++ /dev/null @@ -1,445 +0,0 @@ -// -// DatagramSequencer.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/20/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_DatagramSequencer_h -#define hifi_DatagramSequencer_h - -#include -#include -#include -#include -#include -#include - -#include "AttributeRegistry.h" - -class ReliableChannel; - -/// Performs datagram sequencing, packet fragmentation and reassembly. Works with Bitstream to provide methods to send and -/// receive data over UDP with varying reliability and latency characteristics. To use, create a DatagramSequencer with the -/// fixed-size header that will be included with all outgoing datagrams and expected in all incoming ones (the contents of the -/// header are not checked on receive, only skipped over, and may be modified by the party that actually send the -/// datagram--this means that the header may include dynamically generated data, as long as its size remains fixed). Connect -/// the readyToWrite signal to a slot that will actually transmit the datagram to the remote party. When a datagram is -/// received from that party, call receivedDatagram with its contents. -/// -/// A "packet" represents a batch of data sent at one time (split into one or more datagrams sized below the MTU). Packets are -/// received in full and in order or not at all (that is, a packet being assembled is dropped as soon as a fragment from the -/// next packet is received). Packets can be any size, but the larger a packet is, the more likely it is to be dropped--so, -/// it's better to keep packet sizes close to the MTU. To write a packet, call startPacket, write data to the returned -/// Bitstream, then call endPacket (which will result in one or more firings of readyToWrite). Data written in this way is not -/// guaranteed to be received, but if it is received, it will arrive in order. This is a good way to transmit delta state: -/// state that represents the change between the last acknowledged state and the current state (which, if not received, will -/// not be resent as-is; instead, it will be replaced by up-to-date new deltas). -/// -/// There are two methods for sending reliable data. The first, for small messages that require minimum-latency processing, is -/// the high priority messaging system. When you call sendHighPriorityMessage, the message that you send will be included with -/// every outgoing packet until it is acknowledged. When the receiving party first sees the message, it will fire a -/// receivedHighPriorityMessage signal. -/// -/// The second method employs a set of independent reliable channels multiplexed onto the packet stream. These channels are -/// created lazily through the getReliableOutputChannel/getReliableInputChannel functions. Output channels contain buffers -/// to which one may write either arbitrary data (as a QIODevice) or messages (as QVariants), or switch between the two. -/// Each time a packet is sent, data pending for reliable output channels is added, in proportion to their relative priorities, -/// until the packet size limit set by setMaxPacketSize is reached. On the receive side, the streams are reconstructed and -/// (again, depending on whether messages are enabled) either the QIODevice reports that data is available, or, when a complete -/// message is decoded, the receivedMessage signal is fired. -class DatagramSequencer : public QObject { - Q_OBJECT - -public: - - /// Contains the content of a high-priority message along with the number of the first packet in which it was sent. - class HighPriorityMessage { - public: - QVariant data; - int firstPacketNumber; - }; - - /// Creates a new datagram sequencer. - /// \param datagramHeader the content of the header that will be prepended to each outgoing datagram and whose length - /// will be skipped over in each incoming datagram - DatagramSequencer(const QByteArray& datagramHeader = QByteArray(), QObject* parent = NULL); - - /// Returns a reference to the weak hash mapping remote ids to shared objects. - const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _inputStream.getWeakSharedObjectHash(); } - - /// Returns the packet number of the last packet sent. - int getOutgoingPacketNumber() const { return _outgoingPacketNumber; } - - /// Returns the packet number of the last packet received (or the packet currently being assembled). - int getIncomingPacketNumber() const { return _incomingPacketNumber; } - - /// Returns a reference to the stream used to read packets. - Bitstream& getInputStream() { return _inputStream; } - - /// Returns a reference to the stream used to write packets. - Bitstream& getOutputStream() { return _outputStream; } - - /// Returns a reference to the outgoing packet data. - const QByteArray& getOutgoingPacketData() const { return _outgoingPacketData; } - - /// Returns the packet number of the sent packet at the specified index. - int getSentPacketNumber(int index) const { return _sendRecords.at(index).packetNumber; } - - /// Adds a message to the high priority queue. Will be sent with every outgoing packet until received. - void sendHighPriorityMessage(const QVariant& data); - - /// Returns a reference to the list of high priority messages not yet acknowledged. - const QList& getHighPriorityMessages() const { return _highPriorityMessages; } - - /// Sets the maximum packet size. This is a soft limit that determines how much - /// reliable data we include with each transmission. - void setMaxPacketSize(int maxPacketSize) { _maxPacketSize = maxPacketSize; } - - int getMaxPacketSize() const { return _maxPacketSize; } - - /// Returns the output channel at the specified index, creating it if necessary. - ReliableChannel* getReliableOutputChannel(int index = 0); - - /// Returns the intput channel at the specified index, creating it if necessary. - ReliableChannel* getReliableInputChannel(int index = 0); - - /// Returns a reference to the stored receive mappings at the specified index. - const Bitstream::ReadMappings& getReadMappings(int index) const { return _receiveRecords.at(index).mappings; } - - /// Adds stats for all reliable channels to the referenced variables. - void addReliableChannelStats(int& sendProgress, int& sendTotal, int& receiveProgress, int& receiveTotal) const; - - /// Notes that we're sending a group of packets. - /// \param desiredPackets the number of packets we'd like to write in the group - /// \return the number of packets to write in the group - int notePacketGroup(int desiredPackets = 1); - - /// Starts a new packet for transmission. - /// \return a reference to the Bitstream to use for writing to the packet - Bitstream& startPacket(); - - /// Sends the packet currently being written. - void endPacket(); - - /// Cancels the packet currently being written. - void cancelPacket(); - - /// Processes a datagram received from the other party, emitting readyToRead when the entire packet - /// has been successfully assembled. - Q_INVOKABLE void receivedDatagram(const QByteArray& datagram); - -signals: - - /// Emitted when a datagram is ready to be transmitted. - void readyToWrite(const QByteArray& datagram); - - /// Emitted when a packet is available to read. - void readyToRead(Bitstream& input); - - /// Emitted when we've received a high-priority message. - void receivedHighPriorityMessage(const QVariant& data); - - /// Emitted when we've recorded the transmission of a packet. - void sendRecorded(); - - /// Emitted when we've recorded the receipt of a packet (that is, at the end of packet processing). - void receiveRecorded(); - - /// Emitted when a sent packet has been acknowledged by the remote side. - /// \param index the index of the packet in our list of send records - void sendAcknowledged(int index); - - /// Emitted when our acknowledgement of a received packet has been acknowledged by the remote side. - /// \param index the index of the packet in our list of receive records - void receiveAcknowledged(int index); - -private slots: - - void sendClearSharedObjectMessage(int id); - void handleHighPriorityMessage(const QVariant& data); - void clearReliableChannel(QObject* object); - -private: - - friend class ReliableChannel; - - class ChannelSpan { - public: - int channel; - int offset; - int length; - }; - - class SendRecord { - public: - int packetNumber; - int lastReceivedPacketNumber; - Bitstream::WriteMappings mappings; - QVector spans; - }; - - class ReceiveRecord { - public: - int packetNumber; - Bitstream::ReadMappings mappings; - int newHighPriorityMessages; - - bool operator<(const ReceiveRecord& other) const { return packetNumber < other.packetNumber; } - }; - - /// Notes that the described send was acknowledged by the other party. - void sendRecordAcknowledged(const SendRecord& record); - - /// Notes that the described send was lost in transit. - void sendRecordLost(const SendRecord& record); - - /// Appends some reliable data to the outgoing packet. - void appendReliableData(int bytes, QVector& spans); - - /// Sends a packet to the other party, fragmenting it into multiple datagrams (and emitting - /// readyToWrite) as necessary. - void sendPacket(const QByteArray& packet, const QVector& spans); - - QList _sendRecords; - QList _receiveRecords; - - QByteArray _outgoingPacketData; - QDataStream _outgoingPacketStream; - Bitstream _outputStream; - - QBuffer _incomingDatagramBuffer; - QDataStream _incomingDatagramStream; - int _datagramHeaderSize; - - int _outgoingPacketNumber; - QByteArray _outgoingDatagram; - QBuffer _outgoingDatagramBuffer; - QDataStream _outgoingDatagramStream; - - int _incomingPacketNumber; - QByteArray _incomingPacketData; - QDataStream _incomingPacketStream; - Bitstream _inputStream; - QSet _offsetsReceived; - int _remainingBytes; - - QList _highPriorityMessages; - int _receivedHighPriorityMessages; - - int _maxPacketSize; - - float _packetsPerGroup; - float _packetsToWrite; - float _slowStartThreshold; - int _packetRateIncreasePacketNumber; - int _packetRateDecreasePacketNumber; - int _packetDropCount; - int _lastPacketDropped; - - QHash _reliableOutputChannels; - QHash _reliableInputChannels; -}; - -/// A circular buffer, where one may efficiently append data to the end or remove data from the beginning. -class CircularBuffer : public QIODevice { -public: - - CircularBuffer(QObject* parent = NULL); - - /// Appends data to the end of the buffer. - void append(const QByteArray& data) { append(data.constData(), data.size()); } - - /// Appends data to the end of the buffer. - void append(const char* data, int length); - - /// Removes data from the beginning of the buffer. - void remove(int length); - - /// Reads part of the data from the buffer. - QByteArray readBytes(int offset, int length) const; - - /// Reads part of the data from the buffer. - void readBytes(int offset, int length, char* data) const; - - /// Writes to part of the data in the buffer. - void writeBytes(int offset, int length, const char* data); - - /// Writes part of the buffer to the supplied stream. - void writeToStream(int offset, int length, QDataStream& out) const; - - /// Reads part of the buffer from the supplied stream. - void readFromStream(int offset, int length, QDataStream& in); - - /// Appends part of the buffer to the supplied other buffer. - void appendToBuffer(int offset, int length, CircularBuffer& buffer) const; - - virtual bool atEnd() const; - virtual qint64 bytesAvailable() const; - virtual bool canReadLine() const; - virtual bool open(OpenMode flags); - virtual qint64 pos() const; - virtual bool seek(qint64 pos); - virtual qint64 size() const; - -protected: - - virtual qint64 readData(char* data, qint64 length); - virtual qint64 writeData(const char* data, qint64 length); - -private: - - void resize(int size); - - QByteArray _data; - int _position; - int _size; - int _offset; -}; - -/// A list of contiguous spans, alternating between set and unset. Conceptually, the list is preceeded by a set -/// span of infinite length and followed by an unset span of infinite length. Within those bounds, it alternates -/// between unset and set. -class SpanList { -public: - - class Span { - public: - int unset; - int set; - }; - - SpanList(); - - const QList& getSpans() const { return _spans; } - - /// Returns the total length set. - int getTotalSet() const { return _totalSet; } - - /// Sets a region of the list. - /// \return the advancement of the set length at the beginning of the list - int set(int offset, int length); - -private: - - /// Sets the spans starting at the specified iterator, consuming at least the given length. - /// \return the actual amount set, which may be greater if we ran into an existing set span - int setSpans(QList::iterator it, int length); - - QList _spans; - int _totalSet; -}; - -/// Represents a single reliable channel multiplexed onto the datagram sequence. -class ReliableChannel : public QObject { - Q_OBJECT - -public: - - /// Returns the channel's index in the sequencer's channel map. - int getIndex() const { return _index; } - - /// Checks whether this is an output channel. - bool isOutput() const { return _output; } - - /// Returns a reference to the buffer used to write/read data to/from this channel. - CircularBuffer& getBuffer() { return _buffer; } - - /// Returns a reference to the data stream created on this channel's buffer. - QDataStream& getDataStream() { return _dataStream; } - - /// Returns a reference to the bitstream created on this channel's data stream. - Bitstream& getBitstream() { return _bitstream; } - - /// Sets the channel priority, which determines how much of this channel's data (in proportion to the other channels) to - /// include in each outgoing packet. - void setPriority(float priority) { _priority = priority; } - float getPriority() const { return _priority; } - - /// Returns the number of bytes available to read from this channel. - int getBytesAvailable() const; - - /// Returns the offset, which represents the total number of bytes acknowledged - /// (on the write end) or received completely (on the read end). - int getOffset() const { return _offset; } - - /// Returns the total number of bytes written to this channel. - int getBytesWritten() const { return _offset + _buffer.pos(); } - - /// Sets whether we expect to write/read framed messages. - void setMessagesEnabled(bool enabled) { _messagesEnabled = enabled; } - bool getMessagesEnabled() const { return _messagesEnabled; } - - /// Starts a framed message on this channel. - void startMessage(); - - /// Ends a framed message on this channel. - void endMessage(); - - /// Sends a framed message on this channel (convenience function that calls startMessage, - /// writes the message to the bitstream, then calls endMessage). - void sendMessage(const QVariant& message); - - /// Determines the number of bytes uploaded towards the currently pending message. - /// \return true if there is a message pending, in which case the sent and total arguments will be set - bool getMessageSendProgress(int& sent, int& total); - - /// Determines the number of bytes downloaded towards the currently pending message. - /// \return true if there is a message pending, in which case the received and total arguments will be set - bool getMessageReceiveProgress(int& received, int& total) const; - -signals: - - /// Fired when a framed message has been received on this channel. - void receivedMessage(const QVariant& message, Bitstream& in); - -private slots: - - void sendClearSharedObjectMessage(int id); - void handleMessage(const QVariant& message, Bitstream& in); - -private: - - friend class DatagramSequencer; - - ReliableChannel(DatagramSequencer* sequencer, int index, bool output); - - void writeData(QDataStream& out, int bytes, QVector& spans); - void writeFullSpans(QDataStream& out, int bytes, int startingIndex, int position, - QVector& spans); - int writeSpan(QDataStream& out, int position, int length, QVector& spans); - - void spanAcknowledged(const DatagramSequencer::ChannelSpan& span); - void spanLost(int packetNumber, int nextOutgoingPacketNumber); - - void readData(QDataStream& in); - - void pruneOutgoingMessageStats(); - - int _index; - bool _output; - CircularBuffer _buffer; - CircularBuffer _assemblyBuffer; - QDataStream _dataStream; - Bitstream _bitstream; - float _priority; - - int _offset; - int _writePosition; - int _writePositionResetPacketNumber; - SpanList _acknowledged; - bool _messagesEnabled; - int _messageLengthPlaceholder; ///< the location in the buffer of the message length for the current message - - typedef QPair OffsetSizePair; - QVector _outgoingMessageStats; - - int _messageReceivedOffset; ///< when reached, indicates that the most recent sent message has been received - int _messageSize; ///< the size of the most recent sent message; only valid when _messageReceivedOffset has been set -}; - -#endif // hifi_DatagramSequencer_h diff --git a/libraries/metavoxels/src/Endpoint.cpp b/libraries/metavoxels/src/Endpoint.cpp deleted file mode 100644 index a8a8f922cd..0000000000 --- a/libraries/metavoxels/src/Endpoint.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Endpoint.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 6/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "Endpoint.h" - -Endpoint::Endpoint(const SharedNodePointer& node, PacketRecord* baselineSendRecord, PacketRecord* baselineReceiveRecord) : - _node(node), - _sequencer(byteArrayWithPopulatedHeader(PacketTypeMetavoxelData), this) { - - connect(&_sequencer, SIGNAL(readyToWrite(const QByteArray&)), SLOT(sendDatagram(const QByteArray&))); - connect(&_sequencer, SIGNAL(readyToRead(Bitstream&)), SLOT(readMessage(Bitstream&))); - connect(&_sequencer, SIGNAL(sendRecorded()), SLOT(recordSend())); - connect(&_sequencer, SIGNAL(receiveRecorded()), SLOT(recordReceive())); - connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(clearSendRecordsBefore(int))); - connect(&_sequencer, SIGNAL(receiveAcknowledged(int)), SLOT(clearReceiveRecordsBefore(int))); - - // insert the baseline send and receive records - _sendRecords.append(baselineSendRecord); - _receiveRecords.append(baselineReceiveRecord); -} - -Endpoint::~Endpoint() { - foreach (PacketRecord* record, _sendRecords) { - delete record; - } - foreach (PacketRecord* record, _receiveRecords) { - delete record; - } -} - -void Endpoint::update() { - int packetsToSend = _sequencer.notePacketGroup(); - for (int i = 0; i < packetsToSend; i++) { - Bitstream& out = _sequencer.startPacket(); - writeUpdateMessage(out); - _sequencer.endPacket(); - } -} - -int Endpoint::parseData(const QByteArray& packet) { - // process through sequencer - QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); - return packet.size(); -} - -void Endpoint::sendDatagram(const QByteArray& data) { - DependencyManager::get()->writeDatagram(data, _node); -} - -void Endpoint::readMessage(Bitstream& in) { - QVariant message; - in >> message; - handleMessage(message, in); -} - -void Endpoint::handleMessage(const QVariant& message, Bitstream& in) { - if (message.userType() == QMetaType::QVariantList) { - foreach (const QVariant& element, message.toList()) { - handleMessage(element, in); - } - } -} - -void Endpoint::recordSend() { - _sendRecords.append(maybeCreateSendRecord()); -} - -void Endpoint::recordReceive() { - _receiveRecords.append(maybeCreateReceiveRecord()); -} - -void Endpoint::clearSendRecordsBefore(int index) { - QList::iterator end = _sendRecords.begin() + index + 1; - for (QList::const_iterator it = _sendRecords.begin(); it != end; it++) { - delete *it; - } - _sendRecords.erase(_sendRecords.begin(), end); -} - -void Endpoint::clearReceiveRecordsBefore(int index) { - QList::iterator end = _receiveRecords.begin() + index + 1; - for (QList::const_iterator it = _receiveRecords.begin(); it != end; it++) { - delete *it; - } - _receiveRecords.erase(_receiveRecords.begin(), end); -} - -void Endpoint::writeUpdateMessage(Bitstream& out) { - out << QVariant(); -} - -PacketRecord* Endpoint::maybeCreateSendRecord() const { - return NULL; -} - -PacketRecord* Endpoint::maybeCreateReceiveRecord() const { - return NULL; -} - -PacketRecord::PacketRecord(int packetNumber, const MetavoxelLOD& lod, const MetavoxelData& data) : - _packetNumber(packetNumber), - _lod(lod), - _data(data) { -} - -PacketRecord::~PacketRecord() { -} diff --git a/libraries/metavoxels/src/Endpoint.h b/libraries/metavoxels/src/Endpoint.h deleted file mode 100644 index c64f29878d..0000000000 --- a/libraries/metavoxels/src/Endpoint.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Endpoint.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 6/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Endpoint_h -#define hifi_Endpoint_h - -#include - -#include "DatagramSequencer.h" -#include "MetavoxelData.h" -#include "Spanner.h" - -class PacketRecord; - -/// Base class for communication endpoints: clients and server sessions. -class Endpoint : public NodeData { - Q_OBJECT - -public: - - /// The index of the input/output channel used to transmit reliable deltas. - static const int RELIABLE_DELTA_CHANNEL_INDEX = 1; - - Endpoint(const SharedNodePointer& node, PacketRecord* baselineSendRecord = NULL, - PacketRecord* baselineReceiveRecord = NULL); - virtual ~Endpoint(); - - DatagramSequencer& getSequencer() { return _sequencer; } - - virtual void update(); - - virtual int parseData(const QByteArray& packet); - -protected slots: - - virtual void sendDatagram(const QByteArray& data); - virtual void readMessage(Bitstream& in); - virtual void handleMessage(const QVariant& message, Bitstream& in); - - void recordSend(); - virtual void recordReceive(); - - virtual void clearSendRecordsBefore(int index); - virtual void clearReceiveRecordsBefore(int index); - -protected: - - virtual void writeUpdateMessage(Bitstream& out); - - virtual PacketRecord* maybeCreateSendRecord() const; - virtual PacketRecord* maybeCreateReceiveRecord() const; - - PacketRecord* getLastAcknowledgedSendRecord() const { return _sendRecords.first(); } - PacketRecord* getLastAcknowledgedReceiveRecord() const { return _receiveRecords.first(); } - - SharedNodePointer _node; - DatagramSequencer _sequencer; - - QList _sendRecords; - QList _receiveRecords; -}; - -/// Base class for packet records. -class PacketRecord { -public: - - PacketRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData()); - virtual ~PacketRecord(); - - int getPacketNumber() const { return _packetNumber; } - const MetavoxelLOD& getLOD() const { return _lod; } - const MetavoxelData& getData() const { return _data; } - -private: - - int _packetNumber; - MetavoxelLOD _lod; - MetavoxelData _data; -}; - -#endif // hifi_Endpoint_h diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp deleted file mode 100644 index 0fd845d581..0000000000 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ /dev/null @@ -1,446 +0,0 @@ -// -// MetavoxelClientManager.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 6/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include - -#include "MetavoxelClientManager.h" -#include "MetavoxelMessages.h" - -MetavoxelClientManager::MetavoxelClientManager() : - _updater(new MetavoxelUpdater(this)) { - QThread* thread = new QThread(this); - _updater->moveToThread(thread); - connect(thread, &QThread::finished, _updater, &QObject::deleteLater); - thread->start(); - QMetaObject::invokeMethod(_updater, "start"); -} - -MetavoxelClientManager::~MetavoxelClientManager() { - if (_updater) { - _updater->thread()->quit(); - _updater->thread()->wait(); - } -} - -void MetavoxelClientManager::init() { - connect(DependencyManager::get().data(), &NodeList::nodeAdded, - this, &MetavoxelClientManager::maybeAttachClient); - connect(DependencyManager::get().data(), &NodeList::nodeKilled, - this, &MetavoxelClientManager::maybeDeleteClient); -} - -SharedObjectPointer MetavoxelClientManager::findFirstRaySpannerIntersection(const glm::vec3& origin, - const glm::vec3& direction, const AttributePointer& attribute, float& distance) { - SharedObjectPointer closestSpanner; - float closestDistance = FLT_MAX; - - DependencyManager::get()->eachNode([&](const SharedNodePointer& node){ - if (node->getType() == NodeType::MetavoxelServer) { - QMutexLocker locker(&node->getMutex()); - MetavoxelClient* client = static_cast(node->getLinkedData()); - if (client) { - float clientDistance; - SharedObjectPointer clientSpanner = client->getDataCopy().findFirstRaySpannerIntersection( - origin, direction, attribute, clientDistance - ); - if (clientSpanner && clientDistance < closestDistance) { - closestSpanner = clientSpanner; - closestDistance = clientDistance; - } - } - } - }); - - if (closestSpanner) { - distance = closestDistance; - } - return closestSpanner; -} - -class RayHeightfieldIntersectionVisitor : public RaySpannerIntersectionVisitor { -public: - - float intersectionDistance; - - RayHeightfieldIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod); - - virtual bool visitSpanner(Spanner* spanner, float distance); -}; - -RayHeightfieldIntersectionVisitor::RayHeightfieldIntersectionVisitor(const glm::vec3& origin, - const glm::vec3& direction, const MetavoxelLOD& lod) : - RaySpannerIntersectionVisitor(origin, direction, QVector() << - AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod), - intersectionDistance(FLT_MAX) { -} - -bool RayHeightfieldIntersectionVisitor::visitSpanner(Spanner* spanner, float distance) { - if (spanner->isHeightfield()) { - intersectionDistance = distance; - return false; - } - return true; -} - -bool MetavoxelClientManager::findFirstRayHeightfieldIntersection(const glm::vec3& origin, - const glm::vec3& direction, float& distance) { - RayHeightfieldIntersectionVisitor visitor(origin, direction, getLOD()); - guide(visitor); - if (visitor.intersectionDistance == FLT_MAX) { - return false; - } - distance = visitor.intersectionDistance; - return true; -} - -class HeightfieldHeightVisitor : public SpannerVisitor { -public: - - float height; - - HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location); - - virtual bool visit(Spanner* spanner); - virtual int visit(MetavoxelInfo& info); - -private: - - glm::vec3 _location; -}; - -HeightfieldHeightVisitor::HeightfieldHeightVisitor(const MetavoxelLOD& lod, const glm::vec3& location) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), - QVector(), QVector(), lod), - height(-FLT_MAX), - _location(location) { -} - -bool HeightfieldHeightVisitor::visit(Spanner* spanner) { - height = qMax(height, spanner->getHeight(_location)); - return true; -} - -static const int REVERSE_ORDER = MetavoxelVisitor::encodeOrder(7, 6, 5, 4, 3, 2, 1, 0); - -int HeightfieldHeightVisitor::visit(MetavoxelInfo& info) { - if (_location.x < info.minimum.x || _location.z < info.minimum.z || _location.x > info.minimum.x + info.size || - _location.z > info.minimum.z + info.size) { - return STOP_RECURSION; - } - SpannerVisitor::visit(info); - return (height == -FLT_MAX) ? (info.isLeaf ? STOP_RECURSION : REVERSE_ORDER) : SHORT_CIRCUIT; -} - -float MetavoxelClientManager::getHeightfieldHeight(const glm::vec3& location) { - HeightfieldHeightVisitor visitor(getLOD(), location); - guide(visitor); - return visitor.height; -} - -void MetavoxelClientManager::paintHeightfieldHeight(const glm::vec3& position, float radius, float height) { - MetavoxelEditMessage edit = { QVariant::fromValue(PaintHeightfieldHeightEdit(position, radius, height)) }; - applyEdit(edit, true); -} - -void MetavoxelClientManager::applyEdit(const MetavoxelEditMessage& edit, bool reliable) { - QMetaObject::invokeMethod(_updater, "applyEdit", Q_ARG(const MetavoxelEditMessage&, edit), Q_ARG(bool, reliable)); -} - -MetavoxelLOD MetavoxelClientManager::getLOD() { - return MetavoxelLOD(); -} - -void MetavoxelClientManager::maybeAttachClient(const SharedNodePointer& node) { - if (node->getType() == NodeType::MetavoxelServer) { - QMutexLocker locker(&node->getMutex()); - MetavoxelClient* client = createClient(node); - client->moveToThread(_updater->thread()); - QMetaObject::invokeMethod(_updater, "addClient", Q_ARG(QObject*, client)); - node->setLinkedData(client); - } -} - -void MetavoxelClientManager::maybeDeleteClient(const SharedNodePointer& node) { - if (node->getType() == NodeType::MetavoxelServer) { - // we assume the node is already locked - MetavoxelClient* client = static_cast(node->getLinkedData()); - if (client) { - node->setLinkedData(NULL); - client->deleteLater(); - } - } -} - -MetavoxelClient* MetavoxelClientManager::createClient(const SharedNodePointer& node) { - return new MetavoxelClient(node, _updater); -} - -void MetavoxelClientManager::guide(MetavoxelVisitor& visitor) { - DependencyManager::get()->eachNode([&visitor](const SharedNodePointer& node){ - if (node->getType() == NodeType::MetavoxelServer) { - QMutexLocker locker(&node->getMutex()); - MetavoxelClient* client = static_cast(node->getLinkedData()); - if (client) { - client->getDataCopy().guide(visitor); - } - } - }); -} - -MetavoxelUpdater::MetavoxelUpdater(MetavoxelClientManager* clientManager) : - _clientManager(clientManager), - _sendTimer(this) { - - _sendTimer.setSingleShot(true); - connect(&_sendTimer, &QTimer::timeout, this, &MetavoxelUpdater::sendUpdates); -} - -const int SEND_INTERVAL = 33; - -void MetavoxelUpdater::start() { - _lastSend = QDateTime::currentMSecsSinceEpoch(); - _sendTimer.start(SEND_INTERVAL); -} - -void MetavoxelUpdater::addClient(QObject* client) { - _clients.insert(static_cast(client)); - connect(client, &QObject::destroyed, this, &MetavoxelUpdater::removeClient); -} - -void MetavoxelUpdater::applyEdit(const MetavoxelEditMessage& edit, bool reliable) { - // apply to all clients - foreach (MetavoxelClient* client, _clients) { - client->applyEdit(edit, reliable); - } -} - -void MetavoxelUpdater::getStats(QObject* receiver, const QByteArray& method) { - int internal = 0, leaves = 0; - int sendProgress = 0, sendTotal = 0; - int receiveProgress = 0, receiveTotal = 0; - foreach (MetavoxelClient* client, _clients) { - client->getData().countNodes(internal, leaves, _lod); - client->getSequencer().addReliableChannelStats(sendProgress, sendTotal, receiveProgress, receiveTotal); - } - QMetaObject::invokeMethod(receiver, method.constData(), Q_ARG(int, internal), Q_ARG(int, leaves), Q_ARG(int, sendProgress), - Q_ARG(int, sendTotal), Q_ARG(int, receiveProgress), Q_ARG(int, receiveTotal)); -} - -void MetavoxelUpdater::sendUpdates() { - // get the latest LOD from the client manager - _lod = _clientManager->getLOD(); - - // send updates for all clients - foreach (MetavoxelClient* client, _clients) { - client->update(); - } - - // restart the send timer - qint64 now = QDateTime::currentMSecsSinceEpoch(); - int elapsed = now - _lastSend; - _lastSend = now; - - _sendTimer.start(qMax(0, 2 * SEND_INTERVAL - qMax(elapsed, SEND_INTERVAL))); -} - -void MetavoxelUpdater::removeClient(QObject* client) { - _clients.remove(static_cast(client)); -} - -MetavoxelClient::MetavoxelClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : - Endpoint(node, new PacketRecord(), new PacketRecord()), - _updater(updater), - _reliableDeltaChannel(NULL), - _reliableDeltaID(0), - _dummyInputStream(_dummyDataStream), - _dummyPacketNumber(0) { - - connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX), - SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&))); -} - -MetavoxelData MetavoxelClient::getDataCopy() { - QReadLocker locker(&_dataCopyLock); - return _dataCopy; -} - -void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit, bool reliable) { - if (reliable) { - _sequencer.getReliableOutputChannel()->sendMessage(QVariant::fromValue(edit)); - - } else { - // apply immediately to local tree - MetavoxelData oldData = _data; - edit.apply(_data, _sequencer.getWeakSharedObjectHash()); - if (_data != oldData) { - dataChanged(oldData); - } - - // start sending it out - _sequencer.sendHighPriorityMessage(QVariant::fromValue(edit)); - } -} - -PacketRecord* MetavoxelClient::getAcknowledgedSendRecord(int packetNumber) const { - PacketRecord* lastAcknowledged = getLastAcknowledgedSendRecord(); - if (lastAcknowledged->getPacketNumber() == packetNumber) { - return lastAcknowledged; - } - foreach (PacketRecord* record, _clearedSendRecords) { - if (record->getPacketNumber() == packetNumber) { - return record; - } - } - return NULL; -} - -PacketRecord* MetavoxelClient::getAcknowledgedReceiveRecord(int packetNumber) const { - PacketRecord* lastAcknowledged = getLastAcknowledgedReceiveRecord(); - if (lastAcknowledged->getPacketNumber() == packetNumber) { - return lastAcknowledged; - } - foreach (const ClearedReceiveRecord& record, _clearedReceiveRecords) { - if (record.first->getPacketNumber() == packetNumber) { - return record.first; - } - } - return NULL; -} - -void MetavoxelClient::dataChanged(const MetavoxelData& oldData) { - // make thread-safe copy - QWriteLocker locker(&_dataCopyLock); - _dataCopy = _data; -} - -void MetavoxelClient::recordReceive() { - Endpoint::recordReceive(); - - // clear the cleared lists - foreach (PacketRecord* record, _clearedSendRecords) { - delete record; - } - _clearedSendRecords.clear(); - - foreach (const ClearedReceiveRecord& record, _clearedReceiveRecords) { - delete record.first; - } - _clearedReceiveRecords.clear(); -} - -void MetavoxelClient::clearSendRecordsBefore(int index) { - // move to cleared list - QList::iterator end = _sendRecords.begin() + index + 1; - for (QList::const_iterator it = _sendRecords.begin(); it != end; it++) { - _clearedSendRecords.append(*it); - } - _sendRecords.erase(_sendRecords.begin(), end); -} - -void MetavoxelClient::clearReceiveRecordsBefore(int index) { - // copy the mappings on first call per packet - if (_sequencer.getIncomingPacketNumber() > _dummyPacketNumber) { - _dummyPacketNumber = _sequencer.getIncomingPacketNumber(); - _dummyInputStream.copyPersistentMappings(_sequencer.getInputStream()); - } - - // move to cleared list - QList::iterator end = _receiveRecords.begin() + index + 1; - for (QList::const_iterator it = _receiveRecords.begin(); it != end; it++) { - _clearedReceiveRecords.append(ClearedReceiveRecord(*it, _sequencer.getReadMappings(index))); - } - _receiveRecords.erase(_receiveRecords.begin(), end); -} - -void MetavoxelClient::writeUpdateMessage(Bitstream& out) { - ClientStateMessage state = { _updater->getLOD() }; - out << QVariant::fromValue(state); -} - -void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) { - int userType = message.userType(); - if (userType == MetavoxelDeltaMessage::Type) { - if (_reliableDeltaChannel) { - MetavoxelData reference = _remoteData; - MetavoxelLOD referenceLOD = _remoteDataLOD; - _remoteData.readDelta(reference, referenceLOD, in, _remoteDataLOD = _reliableDeltaLOD); - _sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings()); - in.clearPersistentMappings(); - _reliableDeltaChannel = NULL; - - } else { - PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); - _remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, - _remoteDataLOD = getLastAcknowledgedSendRecord()->getLOD()); - in.reset(); - } - // copy to local and reapply local edits - MetavoxelData oldData = _data; - _data = _remoteData; - foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) { - if (message.data.userType() == MetavoxelEditMessage::Type) { - message.data.value().apply(_data, _sequencer.getWeakSharedObjectHash()); - } - } - if (_data != oldData) { - dataChanged(oldData); - } - } else if (userType == MetavoxelDeltaPendingMessage::Type) { - // check the id to make sure this is not a delta we've already processed - MetavoxelDeltaPendingMessage pending = message.value(); - if (pending.id > _reliableDeltaID) { - _reliableDeltaID = pending.id; - PacketRecord* sendRecord = getAcknowledgedSendRecord(pending.receivedPacketNumber); - if (!sendRecord) { - qWarning() << "Missing send record for delta" << pending.receivedPacketNumber; - return; - } - _reliableDeltaLOD = sendRecord->getLOD(); - PacketRecord* receiveRecord = getAcknowledgedReceiveRecord(pending.sentPacketNumber); - if (!receiveRecord) { - qWarning() << "Missing receive record for delta" << pending.sentPacketNumber; - return; - } - _remoteDataLOD = receiveRecord->getLOD(); - _remoteData = receiveRecord->getData(); - - _reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - if (receiveRecord == getLastAcknowledgedReceiveRecord()) { - _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream()); - - } else { - _reliableDeltaChannel->getBitstream().copyPersistentMappings(_dummyInputStream); - foreach (const ClearedReceiveRecord& record, _clearedReceiveRecords) { - _reliableDeltaChannel->getBitstream().persistReadMappings(record.second); - if (record.first == receiveRecord) { - break; - } - } - } - } - } else { - Endpoint::handleMessage(message, in); - } -} - -PacketRecord* MetavoxelClient::maybeCreateSendRecord() const { - return new PacketRecord(_sequencer.getOutgoingPacketNumber(), - _reliableDeltaChannel ? _reliableDeltaLOD : _updater->getLOD()); -} - -PacketRecord* MetavoxelClient::maybeCreateReceiveRecord() const { - return new PacketRecord(_sequencer.getIncomingPacketNumber(), _remoteDataLOD, _remoteData); -} - diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h deleted file mode 100644 index 8d029c172f..0000000000 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// MetavoxelClientManager.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 6/26/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelClientManager_h -#define hifi_MetavoxelClientManager_h - -#include -#include - -#include "Endpoint.h" - -class MetavoxelClient; -class MetavoxelEditMessage; -class MetavoxelUpdater; - -/// Manages the set of connected metavoxel clients. -class MetavoxelClientManager : public QObject { - Q_OBJECT - -public: - - MetavoxelClientManager(); - virtual ~MetavoxelClientManager(); - - virtual void init(); - - MetavoxelUpdater* getUpdater() const { return _updater; } - - SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, - const AttributePointer& attribute, float& distance); - - bool findFirstRayHeightfieldIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance); - - Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location); - - Q_INVOKABLE void paintHeightfieldHeight(const glm::vec3& position, float radius, float height); - - Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); - - /// Returns the current LOD. This must be thread-safe, as it will be called from the updater thread. - virtual MetavoxelLOD getLOD(); - -private slots: - - void maybeAttachClient(const SharedNodePointer& node); - void maybeDeleteClient(const SharedNodePointer& node); - -protected: - - virtual MetavoxelClient* createClient(const SharedNodePointer& node); - - void guide(MetavoxelVisitor& visitor); - - MetavoxelUpdater* _updater; -}; - -/// Handles updates in a dedicated thread. -class MetavoxelUpdater : public QObject { - Q_OBJECT - -public: - - MetavoxelUpdater(MetavoxelClientManager* clientManager); - - const MetavoxelLOD& getLOD() const { return _lod; } - - Q_INVOKABLE void start(); - - Q_INVOKABLE void addClient(QObject* client); - - Q_INVOKABLE void applyEdit(const MetavoxelEditMessage& edit, bool reliable); - - /// Requests a set of statistics. The receiving method should take six integer arguments: internal node count, leaf count, - /// send progress, send total, receive progress, receive total. - Q_INVOKABLE void getStats(QObject* receiver, const QByteArray& method); - -private slots: - - void sendUpdates(); - void removeClient(QObject* client); - -private: - - MetavoxelClientManager* _clientManager; - QSet _clients; - - QTimer _sendTimer; - qint64 _lastSend; - - MetavoxelLOD _lod; -}; - -/// Base class for metavoxel clients. -class MetavoxelClient : public Endpoint { - Q_OBJECT - -public: - - MetavoxelClient(const SharedNodePointer& node, MetavoxelUpdater* updater); - - /// Returns a reference to the most recent data. This function is *not* thread-safe. - const MetavoxelData& getData() const { return _data; } - - /// Returns a copy of the most recent data. This function *is* thread-safe. - MetavoxelData getDataCopy(); - - void applyEdit(const MetavoxelEditMessage& edit, bool reliable = false); - -protected: - - PacketRecord* getAcknowledgedSendRecord(int packetNumber) const; - PacketRecord* getAcknowledgedReceiveRecord(int packetNumber) const; - - virtual void dataChanged(const MetavoxelData& oldData); - - virtual void recordReceive(); - - virtual void clearSendRecordsBefore(int index); - virtual void clearReceiveRecordsBefore(int index); - - virtual void writeUpdateMessage(Bitstream& out); - virtual void handleMessage(const QVariant& message, Bitstream& in); - - virtual PacketRecord* maybeCreateSendRecord() const; - virtual PacketRecord* maybeCreateReceiveRecord() const; - - MetavoxelUpdater* _updater; - MetavoxelData _data; - MetavoxelData _remoteData; - MetavoxelLOD _remoteDataLOD; - - ReliableChannel* _reliableDeltaChannel; - MetavoxelLOD _reliableDeltaLOD; - int _reliableDeltaID; - QVariant _reliableDeltaMessage; - - MetavoxelData _dataCopy; - QReadWriteLock _dataCopyLock; - - QDataStream _dummyDataStream; - Bitstream _dummyInputStream; - int _dummyPacketNumber; - QList _clearedSendRecords; - - typedef QPair ClearedReceiveRecord; - QList _clearedReceiveRecords; -}; - -#endif // hifi_MetavoxelClientManager_h diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp deleted file mode 100644 index b8b03226d2..0000000000 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ /dev/null @@ -1,1818 +0,0 @@ -// -// MetavoxelData.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include - -#include "MetavoxelData.h" -#include "Spanner.h" - -REGISTER_META_OBJECT(MetavoxelGuide) -REGISTER_META_OBJECT(DefaultMetavoxelGuide) -REGISTER_META_OBJECT(MetavoxelRenderer) -REGISTER_META_OBJECT(DefaultMetavoxelRenderer) - -static int metavoxelDataTypeId = registerSimpleMetaType(); - -MetavoxelLOD::MetavoxelLOD(const glm::vec3& position, float threshold) : - position(position), - threshold(threshold) { -} - -bool MetavoxelLOD::shouldSubdivide(const glm::vec3& minimum, float size, float multiplier) const { - float halfSize = size * 0.5f; - return size >= (glm::distance(position, minimum + glm::vec3(halfSize, halfSize, halfSize)) - halfSize) * - threshold * multiplier; -} - -bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size, - const MetavoxelLOD& reference, float multiplier) const { - if (position == reference.position && threshold >= reference.threshold) { - return false; // first off, nothing becomes subdivided if it doesn't change - } - if (!shouldSubdivide(minimum, size, multiplier)) { - return false; // this one must be subdivided - } - // TODO: find some way of culling subtrees that can't possibly contain subdivided nodes - return true; -} - -bool MetavoxelLOD::becameSubdividedOrCollapsed(const glm::vec3& minimum, float size, - const MetavoxelLOD& reference, float multiplier) const { - if (position == reference.position && threshold == reference.threshold) { - return false; // first off, nothing becomes subdivided or collapsed if it doesn't change - } - if (!(shouldSubdivide(minimum, size, multiplier) || reference.shouldSubdivide(minimum, size, multiplier))) { - return false; // this one or the reference must be subdivided - } - // TODO: find some way of culling subtrees that can't possibly contain subdivided or collapsed nodes - return true; -} - -bool MetavoxelLOD::shouldSubdivide(const glm::vec2& minimum, float size, float multiplier) const { - float halfSize = size * 0.5f; - return size >= (glm::distance(glm::vec2(position), minimum + glm::vec2(halfSize, halfSize)) - halfSize) * - threshold * multiplier; -} - -bool MetavoxelLOD::becameSubdivided(const glm::vec2& minimum, float size, - const MetavoxelLOD& reference, float multiplier) const { - if (position == reference.position && threshold >= reference.threshold) { - return false; // first off, nothing becomes subdivided if it doesn't change - } - if (!shouldSubdivide(minimum, size, multiplier)) { - return false; // this one must be subdivided - } - // TODO: find some way of culling subtrees that can't possibly contain subdivided nodes - return true; -} - -bool MetavoxelLOD::becameSubdividedOrCollapsed(const glm::vec2& minimum, float size, - const MetavoxelLOD& reference, float multiplier) const { - if (position == reference.position && threshold == reference.threshold) { - return false; // first off, nothing becomes subdivided or collapsed if it doesn't change - } - if (!(shouldSubdivide(minimum, size, multiplier) || reference.shouldSubdivide(minimum, size, multiplier))) { - return false; // this one or the reference must be subdivided - } - // TODO: find some way of culling subtrees that can't possibly contain subdivided or collapsed nodes - return true; -} - -MetavoxelData::MetavoxelData() : _size(1.0f) { -} - -MetavoxelData::MetavoxelData(const MetavoxelData& other) : - _size(other._size), - _roots(other._roots) { - - incrementRootReferenceCounts(); -} - -MetavoxelData::~MetavoxelData() { - decrementRootReferenceCounts(); -} - -MetavoxelData& MetavoxelData::operator=(const MetavoxelData& other) { - decrementRootReferenceCounts(); - _size = other._size; - _roots = other._roots; - incrementRootReferenceCounts(); - return *this; -} - -Box MetavoxelData::getBounds() const { - float halfSize = _size * 0.5f; - return Box(glm::vec3(-halfSize, -halfSize, -halfSize), glm::vec3(halfSize, halfSize, halfSize)); -} - -void MetavoxelData::guide(MetavoxelVisitor& visitor) { - // let the visitor know we're about to begin a tour - visitor.prepare(this); - - // start with the root values/defaults (plus the guide attribute) - const QVector& inputs = visitor.getInputs(); - const QVector& outputs = visitor.getOutputs(); - MetavoxelVisitation& firstVisitation = visitor.acquireVisitation(); - firstVisitation.info.minimum = getMinimum(); - firstVisitation.info.size = _size; - for (int i = 0; i < inputs.size(); i++) { - const AttributePointer& input = inputs.at(i); - MetavoxelNode* node = _roots.value(input); - firstVisitation.inputNodes[i] = node; - firstVisitation.info.inputValues[i] = node ? node->getAttributeValue(input) : input; - } - AttributePointer guideAttribute = AttributeRegistry::getInstance()->getGuideAttribute(); - MetavoxelNode* node = _roots.value(guideAttribute); - firstVisitation.inputNodes.last() = node; - firstVisitation.info.inputValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute; - for (int i = 0; i < outputs.size(); i++) { - MetavoxelNode* node = _roots.value(outputs.at(i)); - firstVisitation.outputNodes[i] = node; - } - static_cast(firstVisitation.info.inputValues.last().getInlineValue< - SharedObjectPointer>().data())->guide(firstVisitation); - for (int i = 0; i < outputs.size(); i++) { - OwnedAttributeValue& value = firstVisitation.info.outputValues[i]; - if (!value.getAttribute()) { - continue; - } - // replace the old node with the new - MetavoxelNode*& node = _roots[value.getAttribute()]; - if (node) { - node->decrementReferenceCount(value.getAttribute()); - } - node = firstVisitation.outputNodes.at(i); - if (node->isLeaf() && value.isDefault()) { - // immediately remove the new node if redundant - node->decrementReferenceCount(value.getAttribute()); - _roots.remove(value.getAttribute()); - } - value = AttributeValue(); - } - visitor.releaseVisitation(); -} - -void MetavoxelData::guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor) { - // if the other data is smaller, we need to expand it to compare - const MetavoxelData* expandedOther = &other; - if (_size > other._size) { - MetavoxelData* expanded = new MetavoxelData(other); - while (expanded->_size < _size) { - expanded->expand(); - } - expandedOther = expanded; - } - - // let the visitor know we're about to begin a tour - visitor.prepare(this); - - // start with the root values/defaults (plus the guide attribute) - const QVector& inputs = visitor.getInputs(); - const QVector& outputs = visitor.getOutputs(); - MetavoxelVisitation& firstVisitation = visitor.acquireVisitation(); - firstVisitation.compareNodes.resize(inputs.size() + 1); - firstVisitation.info.minimum = getMinimum(); - firstVisitation.info.size = _size; - bool allNodesSame = true; - for (int i = 0; i < inputs.size(); i++) { - const AttributePointer& input = inputs.at(i); - MetavoxelNode* node = _roots.value(input); - firstVisitation.inputNodes[i] = node; - firstVisitation.info.inputValues[i] = node ? node->getAttributeValue(input) : input; - MetavoxelNode* compareNode = expandedOther->_roots.value(input); - firstVisitation.compareNodes[i] = compareNode; - allNodesSame &= (node == compareNode); - } - AttributePointer guideAttribute = AttributeRegistry::getInstance()->getGuideAttribute(); - MetavoxelNode* node = _roots.value(guideAttribute); - firstVisitation.inputNodes.last() = node; - firstVisitation.info.inputValues.last() = node ? node->getAttributeValue(guideAttribute) : guideAttribute; - MetavoxelNode* compareNode = expandedOther->_roots.value(guideAttribute); - firstVisitation.compareNodes.last() = compareNode; - allNodesSame &= (node == compareNode); - if (!allNodesSame) { - for (int i = 0; i < outputs.size(); i++) { - MetavoxelNode* node = _roots.value(outputs.at(i)); - firstVisitation.outputNodes[i] = node; - } - static_cast(firstVisitation.info.inputValues.last().getInlineValue< - SharedObjectPointer>().data())->guideToDifferent(firstVisitation); - for (int i = 0; i < outputs.size(); i++) { - OwnedAttributeValue& value = firstVisitation.info.outputValues[i]; - if (!value.getAttribute()) { - continue; - } - // replace the old node with the new - MetavoxelNode*& node = _roots[value.getAttribute()]; - if (node) { - node->decrementReferenceCount(value.getAttribute()); - } - node = firstVisitation.outputNodes.at(i); - if (node->isLeaf() && value.isDefault()) { - // immediately remove the new node if redundant - node->decrementReferenceCount(value.getAttribute()); - _roots.remove(value.getAttribute()); - } - value = AttributeValue(); - } - } - visitor.releaseVisitation(); - - // delete the expanded other if we had to expand - if (expandedOther != &other) { - delete expandedOther; - } -} - -typedef void (*SpannerUpdateFunction)(SharedObjectSet& set, const SharedObjectPointer& object); - -void insertSpanner(SharedObjectSet& set, const SharedObjectPointer& object) { - set.insert(object); -} - -void removeSpanner(SharedObjectSet& set, const SharedObjectPointer& object) { - set.remove(object); -} - -void toggleSpanner(SharedObjectSet& set, const SharedObjectPointer& object) { - if (!set.remove(object)) { - set.insert(object); - } -} - -template class SpannerUpdateVisitor : public MetavoxelVisitor { -public: - - SpannerUpdateVisitor(const AttributePointer& attribute, const Box& bounds, - float granularity, const SharedObjectPointer& object); - - virtual int visit(MetavoxelInfo& info); - -private: - - const AttributePointer& _attribute; - const Box& _bounds; - float _longestSide; - const SharedObjectPointer& _object; -}; - -template SpannerUpdateVisitor::SpannerUpdateVisitor(const AttributePointer& attribute, - const Box& bounds, float granularity, const SharedObjectPointer& object) : - MetavoxelVisitor(QVector() << attribute, QVector() << attribute), - _attribute(attribute), - _bounds(bounds), - _longestSide(qMax(bounds.getLongestSide(), granularity)), - _object(object) { -} - -template int SpannerUpdateVisitor::visit(MetavoxelInfo& info) { - if (!info.getBounds().intersects(_bounds)) { - return STOP_RECURSION; - } - if (info.size > _longestSide) { - return DEFAULT_ORDER; - } - SharedObjectSet set = info.inputValues.at(0).getInlineValue(); - F(set, _object); - info.outputValues[0] = AttributeValue(_attribute, encodeInline(set)); - return STOP_RECURSION; -} - -void MetavoxelData::insert(const AttributePointer& attribute, const SharedObjectPointer& object) { - Spanner* spanner = static_cast(object.data()); - insert(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object); -} - -void MetavoxelData::insert(const AttributePointer& attribute, const Box& bounds, - float granularity, const SharedObjectPointer& object) { - // expand to fit the entire bounds - while (!getBounds().contains(bounds)) { - expand(); - } - SpannerUpdateVisitor visitor(attribute, bounds, granularity, object); - guide(visitor); -} - -void MetavoxelData::remove(const AttributePointer& attribute, const SharedObjectPointer& object) { - Spanner* spanner = static_cast(object.data()); - remove(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object); -} - -void MetavoxelData::remove(const AttributePointer& attribute, const Box& bounds, - float granularity, const SharedObjectPointer& object) { - SpannerUpdateVisitor visitor(attribute, bounds, granularity, object); - guide(visitor); -} - -void MetavoxelData::toggle(const AttributePointer& attribute, const SharedObjectPointer& object) { - Spanner* spanner = static_cast(object.data()); - toggle(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object); -} - -void MetavoxelData::toggle(const AttributePointer& attribute, const Box& bounds, - float granularity, const SharedObjectPointer& object) { - SpannerUpdateVisitor visitor(attribute, bounds, granularity, object); - guide(visitor); -} - -void MetavoxelData::replace(const AttributePointer& attribute, const SharedObjectPointer& oldObject, - const SharedObjectPointer& newObject) { - Spanner* spanner = static_cast(oldObject.data()); - replace(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), oldObject, newObject); -} - -class SpannerReplaceVisitor : public MetavoxelVisitor { -public: - - SpannerReplaceVisitor(const AttributePointer& attribute, const Box& bounds, - float granularity, const SharedObjectPointer& oldObject, const SharedObjectPointer& newObject); - - virtual int visit(MetavoxelInfo& info); - -private: - - const AttributePointer& _attribute; - const Box& _bounds; - float _longestSide; - const SharedObjectPointer& _oldObject; - const SharedObjectPointer& _newObject; -}; - -SpannerReplaceVisitor::SpannerReplaceVisitor(const AttributePointer& attribute, const Box& bounds, float granularity, - const SharedObjectPointer& oldObject, const SharedObjectPointer& newObject) : - MetavoxelVisitor(QVector() << attribute, QVector() << attribute), - _attribute(attribute), - _bounds(bounds), - _longestSide(qMax(bounds.getLongestSide(), granularity)), - _oldObject(oldObject), - _newObject(newObject) { -} - -int SpannerReplaceVisitor::visit(MetavoxelInfo& info) { - if (!info.getBounds().intersects(_bounds)) { - return STOP_RECURSION; - } - if (info.size > _longestSide) { - return DEFAULT_ORDER; - } - SharedObjectSet set = info.inputValues.at(0).getInlineValue(); - if (set.remove(_oldObject)) { - set.insert(_newObject); - } - info.outputValues[0] = AttributeValue(_attribute, encodeInline(set)); - return STOP_RECURSION; -} - -void MetavoxelData::replace(const AttributePointer& attribute, const Box& bounds, float granularity, - const SharedObjectPointer& oldObject, const SharedObjectPointer& newObject) { - Spanner* newSpanner = static_cast(newObject.data()); - if (!newSpanner) { - remove(attribute, bounds, granularity, oldObject); - return; - } - if (bounds != newSpanner->getBounds() || granularity != newSpanner->getPlacementGranularity()) { - // if the bounds have changed, we must remove and reinsert - remove(attribute, bounds, granularity, oldObject); - insert(attribute, newSpanner->getBounds(), newSpanner->getPlacementGranularity(), newObject); - return; - } - SpannerReplaceVisitor visitor(attribute, bounds, granularity, oldObject, newObject); - guide(visitor); -} - -class SpannerFetchVisitor : public SpannerVisitor { -public: - - SpannerFetchVisitor(const AttributePointer& attribute, const Box& bounds, QVector& results); - - virtual bool visit(Spanner* spanner); - - virtual int visit(MetavoxelInfo& info); - -private: - - const Box& _bounds; - QVector& _results; -}; - -SpannerFetchVisitor::SpannerFetchVisitor(const AttributePointer& attribute, const Box& bounds, - QVector& results) : - SpannerVisitor(QVector() << attribute), - _bounds(bounds), - _results(results) { -} - -bool SpannerFetchVisitor::visit(Spanner* spanner) { - if (spanner->getBounds().intersects(_bounds)) { - _results.append(spanner); - } - return true; -} - -int SpannerFetchVisitor::visit(MetavoxelInfo& info) { - return info.getBounds().intersects(_bounds) ? SpannerVisitor::visit(info) : STOP_RECURSION; -} - -void MetavoxelData::getIntersecting(const AttributePointer& attribute, const Box& bounds, - QVector& results) { - SpannerFetchVisitor visitor(attribute, bounds, results); - guide(visitor); -} - -void MetavoxelData::clear(const AttributePointer& attribute) { - MetavoxelNode* node = _roots.take(attribute); - if (node) { - node->decrementReferenceCount(attribute); - } -} - -void MetavoxelData::touch(const AttributePointer& attribute) { - MetavoxelNode* root = _roots.value(attribute); - if (root) { - setRoot(attribute, root->touch(attribute)); - } -} - -class FirstRaySpannerIntersectionVisitor : public RaySpannerIntersectionVisitor { -public: - - FirstRaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, - const AttributePointer& attribute, const MetavoxelLOD& lod); - - Spanner* getSpanner() const { return _spanner; } - float getDistance() const { return _distance; } - - virtual bool visitSpanner(Spanner* spanner, float distance); - -private: - - Spanner* _spanner; - float _distance; -}; - -FirstRaySpannerIntersectionVisitor::FirstRaySpannerIntersectionVisitor( - const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, const MetavoxelLOD& lod) : - RaySpannerIntersectionVisitor(origin, direction, QVector() << attribute, - QVector(), QVector(), lod), - _spanner(NULL) { -} - -bool FirstRaySpannerIntersectionVisitor::visitSpanner(Spanner* spanner, float distance) { - _spanner = spanner; - _distance = distance; - return false; -} - -SharedObjectPointer MetavoxelData::findFirstRaySpannerIntersection( - const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, - float& distance, const MetavoxelLOD& lod) { - FirstRaySpannerIntersectionVisitor visitor(origin, direction, attribute, lod); - guide(visitor); - if (!visitor.getSpanner()) { - return SharedObjectPointer(); - } - distance = visitor.getDistance(); - return SharedObjectPointer(visitor.getSpanner()); -} - -const int X_MAXIMUM_FLAG = 1; -const int Y_MAXIMUM_FLAG = 2; -const int Z_MAXIMUM_FLAG = 4; -const int MAXIMUM_FLAG_MASK = X_MAXIMUM_FLAG | Y_MAXIMUM_FLAG | Z_MAXIMUM_FLAG; - -static glm::vec3 getNextMinimum(const glm::vec3& minimum, float nextSize, int index) { - return minimum + glm::vec3( - (index & X_MAXIMUM_FLAG) ? nextSize : 0.0f, - (index & Y_MAXIMUM_FLAG) ? nextSize : 0.0f, - (index & Z_MAXIMUM_FLAG) ? nextSize : 0.0f); -} - -static void setNode(const AttributeValue& value, MetavoxelNode*& node, MetavoxelNode* other, bool blend) { - if (!blend) { - // if we're not blending, we can just make a shallow copy - if (node) { - node->decrementReferenceCount(value.getAttribute()); - } - (node = other)->incrementReferenceCount(); - return; - } - if (node) { - MetavoxelNode* oldNode = node; - node = new MetavoxelNode(value.getAttribute(), oldNode); - oldNode->decrementReferenceCount(value.getAttribute()); - - } else { - node = new MetavoxelNode(value); - } - OwnedAttributeValue oldValue = node->getAttributeValue(value.getAttribute()); - node->blendAttributeValues(other->getAttributeValue(value.getAttribute()), oldValue); - if (!other->isLeaf()) { - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - MetavoxelNode* child = node->getChild(i); - setNode(oldValue, child, other->getChild(i), true); - node->setChild(i, child); - } - } - node->mergeChildren(value.getAttribute()); -} - -static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm::vec3& minimum, float size, - MetavoxelNode* other, const glm::vec3& otherMinimum, float otherSize, bool blend) { - if (otherSize >= size) { - setNode(value, node, other, blend); - return; - } - if (node) { - MetavoxelNode* oldNode = node; - node = new MetavoxelNode(value.getAttribute(), oldNode); - oldNode->decrementReferenceCount(value.getAttribute()); - - } else { - node = new MetavoxelNode(value); - } - int index = 0; - float otherHalfSize = otherSize * 0.5f; - float nextSize = size * 0.5f; - if (otherMinimum.x + otherHalfSize >= minimum.x + nextSize) { - index |= X_MAXIMUM_FLAG; - } - if (otherMinimum.y + otherHalfSize >= minimum.y + nextSize) { - index |= Y_MAXIMUM_FLAG; - } - if (otherMinimum.z + otherHalfSize >= minimum.z + nextSize) { - index |= Z_MAXIMUM_FLAG; - } - if (node->isLeaf()) { - for (int i = 1; i < MetavoxelNode::CHILD_COUNT; i++) { - node->setChild((index + i) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode( - node->getAttributeValue(value.getAttribute()))); - } - } - MetavoxelNode* nextNode = node->getChild(index); - setNode(node->getAttributeValue(value.getAttribute()), nextNode, getNextMinimum(minimum, nextSize, index), - nextSize, other, otherMinimum, otherSize, blend); - node->setChild(index, nextNode); - node->mergeChildren(value.getAttribute()); -} - -void MetavoxelData::set(const glm::vec3& minimum, const MetavoxelData& data, bool blend) { - // expand to fit the entire data - Box bounds(minimum, minimum + glm::vec3(data.getSize(), data.getSize(), data.getSize())); - while (!getBounds().contains(bounds)) { - expand(); - } - - // set/mix each attribute separately - for (QHash::const_iterator it = data._roots.constBegin(); - it != data._roots.constEnd(); it++) { - MetavoxelNode*& root = _roots[it.key()]; - setNode(it.key(), root, getMinimum(), getSize(), it.value(), minimum, data.getSize(), blend); - if (root->isLeaf() && root->getAttributeValue(it.key()).isDefault()) { - _roots.remove(it.key()); - root->decrementReferenceCount(it.key()); - } - } -} - -void MetavoxelData::expand() { - for (QHash::iterator it = _roots.begin(); it != _roots.end(); it++) { - MetavoxelNode* newNode = it.key()->expandMetavoxelRoot(*it.value()); - it.value()->decrementReferenceCount(it.key()); - it.value() = newNode; - } - _size *= 2.0f; -} - -void MetavoxelData::read(Bitstream& in, const MetavoxelLOD& lod) { - // clear out any existing roots - decrementRootReferenceCounts(); - _roots.clear(); - - in >> _size; - - // read in the new roots - forever { - AttributePointer attribute; - in >> attribute; - if (!attribute) { - break; - } - MetavoxelStreamBase base = { attribute, in, lod, lod }; - MetavoxelStreamState state = { base, getMinimum(), _size }; - in.setContext(&base); - attribute->readMetavoxelRoot(*this, state); - in.setContext(NULL); - } -} - -void MetavoxelData::write(Bitstream& out, const MetavoxelLOD& lod) const { - out << _size; - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - out << it.key(); - MetavoxelStreamBase base = { it.key(), out, lod, lod }; - MetavoxelStreamState state = { base, getMinimum(), _size }; - out.setContext(&base); - it.key()->writeMetavoxelRoot(*it.value(), state); - out.setContext(NULL); - } - out << AttributePointer(); -} - -void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, - Bitstream& in, const MetavoxelLOD& lod) { - // shallow copy the reference - *this = reference; - - QHash remainingRoots = _roots; - - bool changed; - in >> changed; - if (changed) { - bool sizeChanged; - in >> sizeChanged; - if (sizeChanged) { - float size; - in >> size; - while (_size < size) { - expand(); - } - } - - glm::vec3 minimum = getMinimum(); - forever { - AttributePointer attribute; - in >> attribute; - if (!attribute) { - break; - } - MetavoxelStreamBase base = { attribute, in, lod, referenceLOD }; - MetavoxelStreamState state = { base, minimum, _size }; - MetavoxelNode* oldRoot = _roots.value(attribute); - in.setContext(&base); - if (oldRoot) { - bool changed; - in >> changed; - if (changed) { - oldRoot->incrementReferenceCount(); - attribute->readMetavoxelDelta(*this, *oldRoot, state); - oldRoot->decrementReferenceCount(attribute); - } else { - attribute->readMetavoxelSubdivision(*this, state); - } - remainingRoots.remove(attribute); - - } else { - attribute->readMetavoxelRoot(*this, state); - } - in.setContext(NULL); - } - - forever { - AttributePointer attribute; - in >> attribute; - if (!attribute) { - break; - } - _roots.take(attribute)->decrementReferenceCount(attribute); - remainingRoots.remove(attribute); - } - } - - // read subdivisions for the remaining roots if there's any chance of a collapse - if (!(lod.position == referenceLOD.position && lod.threshold <= referenceLOD.threshold)) { - glm::vec3 minimum = getMinimum(); - for (QHash::const_iterator it = remainingRoots.constBegin(); - it != remainingRoots.constEnd(); it++) { - MetavoxelStreamBase base = { it.key(), in, lod, referenceLOD }; - MetavoxelStreamState state = { base, minimum, _size }; - in.setContext(&base); - it.key()->readMetavoxelSubdivision(*this, state); - in.setContext(NULL); - } - } -} - -void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, - Bitstream& out, const MetavoxelLOD& lod) const { - // first things first: there might be no change whatsoever - glm::vec3 minimum = getMinimum(); - bool becameSubdivided = lod.becameSubdivided(minimum, _size, referenceLOD); - if (_size == reference._size && _roots == reference._roots && !becameSubdivided) { - out << false; - return; - } - out << true; - - // compare the size; if changed (rare), we must compare to the expanded reference - const MetavoxelData* expandedReference = &reference; - if (_size == reference._size) { - out << false; - } else { - out << true; - out << _size; - - MetavoxelData* expanded = new MetavoxelData(reference); - while (expanded->_size < _size) { - expanded->expand(); - } - expandedReference = expanded; - } - - // write the added/changed/subdivided roots - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - MetavoxelNode* referenceRoot = expandedReference->_roots.value(it.key()); - MetavoxelStreamBase base = { it.key(), out, lod, referenceLOD }; - MetavoxelStreamState state = { base, minimum, _size }; - out.setContext(&base); - if (it.value() != referenceRoot || becameSubdivided) { - out << it.key(); - if (referenceRoot) { - if (it.value() == referenceRoot) { - out << false; - it.key()->writeMetavoxelSubdivision(*it.value(), state); - } else { - out << true; - it.key()->writeMetavoxelDelta(*it.value(), *referenceRoot, state); - } - } else { - it.key()->writeMetavoxelRoot(*it.value(), state); - } - } - out.setContext(NULL); - } - out << AttributePointer(); - - // same with nodes removed - for (QHash::const_iterator it = expandedReference->_roots.constBegin(); - it != expandedReference->_roots.constEnd(); it++) { - if (!_roots.contains(it.key())) { - out << it.key(); - } - } - out << AttributePointer(); - - // delete the expanded reference if we had to expand - if (expandedReference != &reference) { - delete expandedReference; - } -} - -void MetavoxelData::setRoot(const AttributePointer& attribute, MetavoxelNode* root) { - MetavoxelNode*& rootReference = _roots[attribute]; - if (rootReference) { - rootReference->decrementReferenceCount(attribute); - } - rootReference = root; -} - -MetavoxelNode* MetavoxelData::createRoot(const AttributePointer& attribute) { - MetavoxelNode* root = new MetavoxelNode(attribute); - setRoot(attribute, root); - return root; -} - -bool MetavoxelData::deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod) const { - if (_size != other._size) { - return false; - } - if (_roots.size() != other._roots.size()) { - return false; - } - glm::vec3 minimum = getMinimum(); - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - MetavoxelNode* otherNode = other._roots.value(it.key()); - if (!(otherNode && it.key()->metavoxelRootsEqual(*it.value(), *otherNode, minimum, _size, lod))) { - return false; - } - } - return true; -} - -void MetavoxelData::countNodes(int& internal, int& leaves, const MetavoxelLOD& lod) const { - glm::vec3 minimum = getMinimum(); - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - it.value()->countNodes(it.key(), minimum, _size, lod, internal, leaves); - } -} - -void MetavoxelData::dumpStats(QDebug debug) const { - QDebugStateSaver saver(debug); - debug.nospace() << "[size=" << _size << ", roots=["; - int totalInternal = 0, totalLeaves = 0; - glm::vec3 minimum = getMinimum(); - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - if (it != _roots.constBegin()) { - debug << ", "; - } - debug << it.key()->getName() << " (" << it.key()->metaObject()->className() << "): "; - int internal = 0, leaves = 0; - it.value()->countNodes(it.key(), minimum, _size, MetavoxelLOD(), internal, leaves); - debug << internal << " internal, " << leaves << " leaves, " << (internal + leaves) << " total"; - totalInternal += internal; - totalLeaves += leaves; - } - debug << "], totalInternal=" << totalInternal << ", totalLeaves=" << totalLeaves << - ", grandTotal=" << (totalInternal + totalLeaves) << "]"; -} - -bool MetavoxelData::operator==(const MetavoxelData& other) const { - return _size == other._size && _roots == other._roots; -} - -bool MetavoxelData::operator!=(const MetavoxelData& other) const { - return _size != other._size || _roots != other._roots; -} - -void MetavoxelData::incrementRootReferenceCounts() { - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - it.value()->incrementReferenceCount(); - } -} - -void MetavoxelData::decrementRootReferenceCounts() { - for (QHash::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) { - it.value()->decrementReferenceCount(it.key()); - } -} - -Bitstream& operator<<(Bitstream& out, const MetavoxelData& data) { - data.write(out); - return out; -} - -Bitstream& operator>>(Bitstream& in, MetavoxelData& data) { - data.read(in); - return in; -} - -template<> void Bitstream::writeDelta(const MetavoxelData& value, const MetavoxelData& reference) { - value.writeDelta(reference, MetavoxelLOD(), *this, MetavoxelLOD()); -} - -template<> void Bitstream::readDelta(MetavoxelData& value, const MetavoxelData& reference) { - value.readDelta(reference, MetavoxelLOD(), *this, MetavoxelLOD()); -} - -bool MetavoxelStreamState::shouldSubdivide() const { - return base.lod.shouldSubdivide(minimum, size, base.attribute->getLODThresholdMultiplier()); -} - -bool MetavoxelStreamState::shouldSubdivideReference() const { - return base.referenceLOD.shouldSubdivide(minimum, size, base.attribute->getLODThresholdMultiplier()); -} - -bool MetavoxelStreamState::becameSubdivided() const { - return base.lod.becameSubdivided(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier()); -} - -bool MetavoxelStreamState::becameSubdividedOrCollapsed() const { - return base.lod.becameSubdividedOrCollapsed(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier()); -} - -void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) { - minimum = getNextMinimum(lastMinimum, size, index); -} - -int MetavoxelNode::getOppositeChildIndex(int index) { - return index ^ MAXIMUM_FLAG_MASK; -} - -MetavoxelNode::MetavoxelNode(const AttributeValue& attributeValue, const MetavoxelNode* copyChildren) : - _referenceCount(1) { - - _attributeValue = attributeValue.copy(); - if (copyChildren) { - for (int i = 0; i < CHILD_COUNT; i++) { - if ((_children[i] = copyChildren->_children[i])) { - _children[i]->incrementReferenceCount(); - } - } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i] = NULL; - } - } -} - -MetavoxelNode::MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy) : - _referenceCount(1) { - - _attributeValue = attribute->create(copy->_attributeValue); - for (int i = 0; i < CHILD_COUNT; i++) { - if ((_children[i] = copy->_children[i])) { - _children[i]->incrementReferenceCount(); - } - } -} - -void MetavoxelNode::setAttributeValue(const AttributeValue& attributeValue) { - attributeValue.getAttribute()->destroy(_attributeValue); - _attributeValue = attributeValue.copy(); -} - -void MetavoxelNode::blendAttributeValues(const AttributeValue& source, const AttributeValue& dest) { - source.getAttribute()->destroy(_attributeValue); - _attributeValue = source.getAttribute()->blend(source.getValue(), dest.getValue()); -} - -AttributeValue MetavoxelNode::getAttributeValue(const AttributePointer& attribute) const { - return AttributeValue(attribute, _attributeValue); -} - -void MetavoxelNode::mergeChildren(const AttributePointer& attribute, bool postRead) { - if (isLeaf()) { - return; - } - void* childValues[CHILD_COUNT]; - bool allLeaves = true; - for (int i = 0; i < CHILD_COUNT; i++) { - childValues[i] = _children[i]->_attributeValue; - allLeaves &= _children[i]->isLeaf(); - } - if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves && !postRead) { - clearChildren(attribute); - } -} - -bool MetavoxelNode::isLeaf() const { - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - return false; - } - } - return true; -} - -void MetavoxelNode::read(MetavoxelStreamState& state) { - clearChildren(state.base.attribute); - - if (!state.shouldSubdivide()) { - state.base.attribute->read(state.base.stream, _attributeValue, true); - return; - } - bool leaf; - state.base.stream >> leaf; - state.base.attribute->read(state.base.stream, _attributeValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new MetavoxelNode(state.base.attribute); - _children[i]->read(nextState); - } - mergeChildren(state.base.attribute, true); - } -} - -void MetavoxelNode::write(MetavoxelStreamState& state) const { - if (!state.shouldSubdivide()) { - state.base.attribute->write(state.base.stream, _attributeValue, true); - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - state.base.attribute->write(state.base.stream, _attributeValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->write(nextState); - } - } -} - -void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) { - clearChildren(state.base.attribute); - - if (!state.shouldSubdivide()) { - state.base.attribute->readDelta(state.base.stream, _attributeValue, reference._attributeValue, true); - return; - } - bool leaf; - state.base.stream >> leaf; - state.base.attribute->readDelta(state.base.stream, _attributeValue, reference._attributeValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - if (reference.isLeaf() || !state.shouldSubdivideReference()) { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new MetavoxelNode(state.base.attribute); - _children[i]->read(nextState); - } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - bool changed; - state.base.stream >> changed; - if (changed) { - _children[i] = new MetavoxelNode(state.base.attribute); - _children[i]->readDelta(*reference._children[i], nextState); - } else { - if (nextState.becameSubdividedOrCollapsed()) { - _children[i] = reference._children[i]->readSubdivision(nextState); - if (_children[i] == reference._children[i]) { - _children[i]->incrementReferenceCount(); - } - } else { - _children[i] = reference._children[i]; - _children[i]->incrementReferenceCount(); - } - } - } - } - mergeChildren(state.base.attribute, true); - } -} - -void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const { - if (!state.shouldSubdivide()) { - state.base.attribute->writeDelta(state.base.stream, _attributeValue, reference._attributeValue, true); - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - state.base.attribute->writeDelta(state.base.stream, _attributeValue, reference._attributeValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - if (reference.isLeaf() || !state.shouldSubdivideReference()) { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->write(nextState); - } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (_children[i] == reference._children[i]) { - state.base.stream << false; - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } - } else { - state.base.stream << true; - _children[i]->writeDelta(*reference._children[i], nextState); - } - } - } - } -} - -MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) { - if (state.shouldSubdivide()) { - if (!state.shouldSubdivideReference()) { - bool leaf; - state.base.stream >> leaf; - if (leaf) { - return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.base.attribute)); - - } else { - MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.base.attribute)); - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - newNode->_children[i] = new MetavoxelNode(state.base.attribute); - newNode->_children[i]->readSubdivided(nextState, state, _attributeValue); - } - return newNode; - } - } else if (!isLeaf()) { - MetavoxelNode* node = this; - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdividedOrCollapsed()) { - MetavoxelNode* child = _children[i]->readSubdivision(nextState); - if (child != _children[i]) { - if (node == this) { - node = new MetavoxelNode(state.base.attribute, this); - } - node->_children[i] = child; - _children[i]->decrementReferenceCount(state.base.attribute); - } - } - } - if (node != this) { - node->mergeChildren(state.base.attribute, true); - } - return node; - } - } else if (!isLeaf()) { - return new MetavoxelNode(getAttributeValue(state.base.attribute)); - } - return this; -} - -void MetavoxelNode::writeSubdivision(MetavoxelStreamState& state) const { - if (!state.shouldSubdivide()) { - return; - } - bool leaf = isLeaf(); - if (!state.shouldSubdivideReference()) { - state.base.stream << leaf; - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSubdivided(nextState, state, _attributeValue); - } - } - } else if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } - } - } -} - -void MetavoxelNode::readSubdivided(MetavoxelStreamState& state, const MetavoxelStreamState& ancestorState, - void* ancestorValue) { - clearChildren(state.base.attribute); - - if (!state.shouldSubdivide()) { - state.base.attribute->readSubdivided(state, _attributeValue, ancestorState, ancestorValue, true); - return; - } - bool leaf; - state.base.stream >> leaf; - state.base.attribute->readSubdivided(state, _attributeValue, ancestorState, ancestorValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new MetavoxelNode(state.base.attribute); - _children[i]->readSubdivided(nextState, ancestorState, ancestorValue); - } - mergeChildren(state.base.attribute, true); - } -} - -void MetavoxelNode::writeSubdivided(MetavoxelStreamState& state, const MetavoxelStreamState& ancestorState, - void* ancestorValue) const { - if (!state.shouldSubdivide()) { - state.base.attribute->writeSubdivided(state, _attributeValue, ancestorState, ancestorValue, true); - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - state.base.attribute->writeSubdivided(state, _attributeValue, ancestorState, ancestorValue, leaf); - if (!leaf) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSubdivided(nextState, ancestorState, ancestorValue); - } - } -} - -void MetavoxelNode::writeSpanners(MetavoxelStreamState& state) const { - foreach (const SharedObjectPointer& object, decodeInline(_attributeValue)) { - if (static_cast(object.data())->testAndSetVisited(state.base.visit)) { - state.base.stream << object; - } - } - if (!state.shouldSubdivide() || isLeaf()) { - return; - } - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSpanners(nextState); - } -} - -void MetavoxelNode::decrementReferenceCount(const AttributePointer& attribute) { - if (!_referenceCount.deref()) { - destroy(attribute); - delete this; - } -} - -void MetavoxelNode::destroy(const AttributePointer& attribute) { - attribute->destroy(_attributeValue); - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - _children[i]->decrementReferenceCount(attribute); - } - } -} - -bool MetavoxelNode::clearChildren(const AttributePointer& attribute) { - bool cleared = false; - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - _children[i]->decrementReferenceCount(attribute); - _children[i] = NULL; - cleared = true; - } - } - return cleared; -} - -bool MetavoxelNode::deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod) const { - if (!attribute->deepEqual(_attributeValue, other._attributeValue)) { - return false; - } - if (!lod.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier())) { - return true; - } - bool leaf = isLeaf(), otherLeaf = other.isLeaf(); - if (leaf && otherLeaf) { - return true; - } - if (leaf || otherLeaf) { - return false; - } - float nextSize = size * 0.5f; - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextMinimum = getNextMinimum(minimum, nextSize, i); - if (!_children[i]->deepEquals(attribute, *(other._children[i]), nextMinimum, nextSize, lod)) { - return false; - } - } - return true; -} - -void MetavoxelNode::getSpanners(const AttributePointer& attribute, const glm::vec3& minimum, - float size, const MetavoxelLOD& lod, SharedObjectSet& results) const { - results.unite(decodeInline(_attributeValue)); - if (isLeaf() || !lod.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier())) { - return; - } - float nextSize = size * 0.5f; - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i]->getSpanners(attribute, getNextMinimum(minimum, nextSize, i), nextSize, lod, results); - } -} - -void MetavoxelNode::countNodes(const AttributePointer& attribute, const glm::vec3& minimum, - float size, const MetavoxelLOD& lod, int& internal, int& leaves) const { - if (isLeaf() || !lod.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier())) { - leaves++; - return; - } - internal++; - float nextSize = size * 0.5f; - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i]->countNodes(attribute, getNextMinimum(minimum, nextSize, i), nextSize, lod, internal, leaves); - } -} - -MetavoxelNode* MetavoxelNode::touch(const AttributePointer& attribute) const { - MetavoxelNode* node = new MetavoxelNode(getAttributeValue(attribute)); - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - node->setChild(i, _children[i]->touch(attribute)); - } - } - return node; -} - -MetavoxelInfo::MetavoxelInfo(MetavoxelInfo* parentInfo, int inputValuesSize, int outputValuesSize) : - parentInfo(parentInfo), - inputValues(inputValuesSize), - outputValues(outputValuesSize) { -} - -MetavoxelInfo::MetavoxelInfo() { -} - -int MetavoxelVisitor::encodeOrder(int first, int second, int third, int fourth, - int fifth, int sixth, int seventh, int eighth) { - return first | (second << 3) | (third << 6) | (fourth << 9) | - (fifth << 12) | (sixth << 15) | (seventh << 18) | (eighth << 21); -} - -class IndexDistance { -public: - int index; - float distance; -}; - -bool operator<(const IndexDistance& first, const IndexDistance& second) { - return first.distance < second.distance; -} - -int MetavoxelVisitor::encodeOrder(const glm::vec3& direction) { - QList indexDistances; - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - IndexDistance indexDistance = { i, glm::dot(direction, getNextMinimum(glm::vec3(), 1.0f, i)) }; - indexDistances.append(indexDistance); - } - qStableSort(indexDistances); - return encodeOrder(indexDistances.at(0).index, indexDistances.at(1).index, indexDistances.at(2).index, - indexDistances.at(3).index, indexDistances.at(4).index, indexDistances.at(5).index, - indexDistances.at(6).index, indexDistances.at(7).index); -} - -const int ORDER_ELEMENT_BITS = 3; -const int ORDER_ELEMENT_MASK = (1 << ORDER_ELEMENT_BITS) - 1; - -int MetavoxelVisitor::encodeRandomOrder() { - // see http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_.22inside-out.22_algorithm - int order = 0; - int randomValues = rand(); - for (int i = 0, iShift = 0; i < MetavoxelNode::CHILD_COUNT; i++, iShift += ORDER_ELEMENT_BITS) { - int j = (randomValues >> iShift) % (i + 1); - int jShift = j * ORDER_ELEMENT_BITS; - if (j != i) { - int jValue = (order >> jShift) & ORDER_ELEMENT_MASK; - order |= (jValue << iShift); - } - order = (order & ~(ORDER_ELEMENT_MASK << jShift)) | (i << jShift); - } - return order; -} - -const int MetavoxelVisitor::DEFAULT_ORDER = encodeOrder(0, 1, 2, 3, 4, 5, 6, 7); -const int MetavoxelVisitor::STOP_RECURSION = 0; -const int MetavoxelVisitor::SHORT_CIRCUIT = -1; -const int MetavoxelVisitor::ALL_NODES = 1 << 24; -const int MetavoxelVisitor::ALL_NODES_REST = 1 << 25; - -MetavoxelVisitor::MetavoxelVisitor(const QVector& inputs, - const QVector& outputs, const MetavoxelLOD& lod) : - _inputs(inputs), - _outputs(outputs), - _lod(lod), - _minimumLODThresholdMultiplier(FLT_MAX), - _depth(-1) { - - // find the minimum LOD threshold multiplier over all attributes - foreach (const AttributePointer& attribute, _inputs) { - _minimumLODThresholdMultiplier = qMin(attribute->getLODThresholdMultiplier(), _minimumLODThresholdMultiplier); - } - foreach (const AttributePointer& attribute, _outputs) { - _minimumLODThresholdMultiplier = qMin(attribute->getLODThresholdMultiplier(), _minimumLODThresholdMultiplier); - } -} - -MetavoxelVisitor::~MetavoxelVisitor() { -} - -void MetavoxelVisitor::prepare(MetavoxelData* data) { - _data = data; -} - -bool MetavoxelVisitor::postVisit(MetavoxelInfo& info) { - return false; -} - -MetavoxelVisitation& MetavoxelVisitor::acquireVisitation() { - if (++_depth >= _visitations.size()) { - _visitations.append(MetavoxelVisitation(_depth == 0 ? NULL : &_visitations[_depth - 1], - this, _inputs.size() + 1, _outputs.size())); - } - return _visitations[_depth]; -} - -SpannerVisitor::SpannerVisitor(const QVector& spannerInputs, const QVector& inputs, - const QVector& outputs, const MetavoxelLOD& lod, int order) : - MetavoxelVisitor(inputs + spannerInputs, outputs, lod), - _spannerInputCount(spannerInputs.size()), - _order(order) { -} - -void SpannerVisitor::prepare(MetavoxelData* data) { - MetavoxelVisitor::prepare(data); - _visit = Spanner::getAndIncrementNextVisit(); -} - -int SpannerVisitor::visit(MetavoxelInfo& info) { - for (int end = _inputs.size(), i = end - _spannerInputCount; i < end; i++) { - foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue()) { - Spanner* spanner = static_cast(object.data()); - if (spanner->testAndSetVisited(_visit) && !visit(spanner)) { - return SHORT_CIRCUIT; - } - } - } - return info.isLeaf ? STOP_RECURSION : _order; -} - -RayIntersectionVisitor::RayIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, - const QVector& inputs, const QVector& outputs, const MetavoxelLOD& lod) : - MetavoxelVisitor(inputs, outputs, lod), - _origin(origin), - _direction(direction), - _order(encodeOrder(direction)) { -} - -int RayIntersectionVisitor::visit(MetavoxelInfo& info) { - float distance; - if (!info.getBounds().findRayIntersection(_origin, _direction, distance)) { - return STOP_RECURSION; - } - return visit(info, distance); -} - -RaySpannerIntersectionVisitor::RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, - const QVector& spannerInputs, const QVector& inputs, - const QVector& outputs, const MetavoxelLOD& lod) : - RayIntersectionVisitor(origin, direction, inputs + spannerInputs, outputs, lod), - _spannerInputCount(spannerInputs.size()) { -} - -void RaySpannerIntersectionVisitor::prepare(MetavoxelData* data) { - MetavoxelVisitor::prepare(data); - _visit = Spanner::getAndIncrementNextVisit(); -} - -class SpannerDistance { -public: - Spanner* spanner; - float distance; -}; - -bool operator<(const SpannerDistance& first, const SpannerDistance& second) { - return first.distance < second.distance; -} - -int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { - QVarLengthArray spannerDistances; - for (int end = _inputs.size(), i = end - _spannerInputCount; i < end; i++) { - foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue()) { - Spanner* spanner = static_cast(object.data()); - if (spanner->testAndSetVisited(_visit)) { - SpannerDistance spannerDistance = { spanner }; - if (spanner->findRayIntersection(_origin, _direction, spannerDistance.distance)) { - spannerDistances.append(spannerDistance); - } - } - } - qStableSort(spannerDistances); - foreach (const SpannerDistance& spannerDistance, spannerDistances) { - if (!visitSpanner(spannerDistance.spanner, spannerDistance.distance)) { - return SHORT_CIRCUIT; - } - } - } - return info.isLeaf ? STOP_RECURSION : _order; -} - -bool MetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { - return guide(visitation); -} - -DefaultMetavoxelGuide::DefaultMetavoxelGuide() { -} - -static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, int encodedOrder) { - MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation(); - nextVisitation.info.size = visitation.info.size * 0.5f; - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - // the encoded order tells us the child indices for each iteration - int index = encodedOrder & ORDER_ELEMENT_MASK; - encodedOrder >>= ORDER_ELEMENT_BITS; - for (int j = 0; j < visitation.inputNodes.size(); j++) { - MetavoxelNode* node = visitation.inputNodes.at(j); - const AttributeValue& parentValue = visitation.info.inputValues.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * - parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; - nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? - child->getAttributeValue(parentValue.getAttribute()) : parentValue.getAttribute()->inherit(parentValue); - } - for (int j = 0; j < visitation.outputNodes.size(); j++) { - MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * - visitation.visitor->getOutputs().at(j)->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; - nextVisitation.outputNodes[j] = child; - } - nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, index); - if (!static_cast(nextVisitation.info.inputValues.last().getInlineValue< - SharedObjectPointer>().data())->guide(nextVisitation)) { - visitation.visitor->releaseVisitation(); - return false; - } - for (int j = 0; j < nextVisitation.outputNodes.size(); j++) { - OwnedAttributeValue& value = nextVisitation.info.outputValues[j]; - if (!value.getAttribute()) { - continue; - } - // replace the child - OwnedAttributeValue& parentValue = visitation.info.outputValues[j]; - if (!parentValue.getAttribute()) { - // shallow-copy the parent node on first change - parentValue = value; - MetavoxelNode*& node = visitation.outputNodes[j]; - if (node) { - node = new MetavoxelNode(value.getAttribute(), node); - } else { - // create leaf with inherited value - node = new MetavoxelNode(value.getAttribute()->inherit(visitation.getInheritedOutputValue(j))); - } - } - MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = node->getChild(index); - if (child) { - child->decrementReferenceCount(value.getAttribute()); - } else { - // it's a leaf; we need to split it up - AttributeValue nodeValue = value.getAttribute()->inherit(node->getAttributeValue(value.getAttribute())); - for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) { - node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue)); - } - } - node->setChild(index, nextVisitation.outputNodes.at(j)); - value = AttributeValue(); - } - } - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& value = visitation.info.outputValues[i]; - if (value.getAttribute()) { - MetavoxelNode* node = visitation.outputNodes.at(i); - node->mergeChildren(value.getAttribute()); - value = node->getAttributeValue(value.getAttribute()); - } - } - visitation.visitor->releaseVisitation(); - visitation.info.outputValues.swap(nextVisitation.info.outputValues); - bool changed = visitation.visitor->postVisit(visitation.info); - visitation.info.outputValues.swap(nextVisitation.info.outputValues); - if (changed) { - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& newValue = nextVisitation.info.outputValues[i]; - if (!newValue.getAttribute()) { - continue; - } - OwnedAttributeValue& value = visitation.info.outputValues[i]; - MetavoxelNode*& node = visitation.outputNodes[i]; - if (value.getAttribute()) { - node->setAttributeValue(value = newValue); - - } else if (!(node && node->isLeaf() && newValue.getAttribute()->equal( - newValue.getValue(), node->getAttributeValue()))) { - node = newValue.getAttribute()->createMetavoxelNode(value = newValue, node); - } - newValue = AttributeValue(); - } - } - return true; -} - -bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { - // save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute - float halfSize = visitation.info.size * 0.5f; - visitation.info.lodBase = (glm::distance(visitation.visitor->getLOD().position, visitation.info.minimum + - glm::vec3(halfSize, halfSize, halfSize)) - halfSize) * visitation.visitor->getLOD().threshold; - visitation.info.isLODLeaf = (visitation.info.size < visitation.info.lodBase * - visitation.visitor->getMinimumLODThresholdMultiplier()); - visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves(); - int encodedOrder = visitation.visitor->visit(visitation.info); - if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) { - return false; - } - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& value = visitation.info.outputValues[i]; - if (!value.getAttribute()) { - continue; - } - MetavoxelNode*& node = visitation.outputNodes[i]; - if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) { - // "set" to same value; disregard - value = AttributeValue(); - } else { - node = value.getAttribute()->createMetavoxelNode(value, node); - } - } - if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) { - return true; - } - return (encodedOrder == MetavoxelVisitor::STOP_RECURSION || defaultGuideToChildren(visitation, encodedOrder)); -} - -bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { - // save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute - float halfSize = visitation.info.size * 0.5f; - visitation.info.lodBase = (glm::distance(visitation.visitor->getLOD().position, visitation.info.minimum + - glm::vec3(halfSize, halfSize, halfSize)) - halfSize) * visitation.visitor->getLOD().threshold; - visitation.info.isLODLeaf = (visitation.info.size < visitation.info.lodBase * - visitation.visitor->getMinimumLODThresholdMultiplier()); - visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves(); - int encodedOrder = visitation.visitor->visit(visitation.info); - if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) { - return false; - } - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& value = visitation.info.outputValues[i]; - if (!value.getAttribute()) { - continue; - } - MetavoxelNode*& node = visitation.outputNodes[i]; - if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) { - // "set" to same value; disregard - value = AttributeValue(); - } else { - node = value.getAttribute()->createMetavoxelNode(value, node); - } - } - if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) { - return true; - } - if (encodedOrder & MetavoxelVisitor::ALL_NODES_REST) { - return defaultGuideToChildren(visitation, encodedOrder); - } - bool onlyVisitDifferent = !(encodedOrder & MetavoxelVisitor::ALL_NODES); - MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation(); - nextVisitation.compareNodes.resize(visitation.compareNodes.size()); - nextVisitation.info.size = visitation.info.size * 0.5f; - for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - // the encoded order tells us the child indices for each iteration - int index = encodedOrder & ORDER_ELEMENT_MASK; - encodedOrder >>= ORDER_ELEMENT_BITS; - bool allNodesSame = onlyVisitDifferent; - for (int j = 0; j < visitation.inputNodes.size(); j++) { - MetavoxelNode* node = visitation.inputNodes.at(j); - const AttributeValue& parentValue = visitation.info.inputValues.at(j); - bool expand = (visitation.info.size >= visitation.info.lodBase * - parentValue.getAttribute()->getLODThresholdMultiplier()); - MetavoxelNode* child = (node && expand) ? node->getChild(index) : NULL; - nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? - child->getAttributeValue(parentValue.getAttribute()) : parentValue.getAttribute()->inherit(parentValue); - MetavoxelNode* compareNode = visitation.compareNodes.at(j); - MetavoxelNode* compareChild = (compareNode && expand) ? compareNode->getChild(index) : NULL; - nextVisitation.compareNodes[j] = compareChild; - allNodesSame &= (child == compareChild); - } - if (allNodesSame) { - continue; - } - for (int j = 0; j < visitation.outputNodes.size(); j++) { - MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * - visitation.visitor->getOutputs().at(j)->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; - nextVisitation.outputNodes[j] = child; - } - nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, index); - if (!static_cast(nextVisitation.info.inputValues.last().getInlineValue< - SharedObjectPointer>().data())->guideToDifferent(nextVisitation)) { - visitation.visitor->releaseVisitation(); - return false; - } - for (int j = 0; j < nextVisitation.outputNodes.size(); j++) { - OwnedAttributeValue& value = nextVisitation.info.outputValues[j]; - if (!value.getAttribute()) { - continue; - } - // replace the child - OwnedAttributeValue& parentValue = visitation.info.outputValues[j]; - if (!parentValue.getAttribute()) { - // shallow-copy the parent node on first change - parentValue = value; - MetavoxelNode*& node = visitation.outputNodes[j]; - if (node) { - node = new MetavoxelNode(value.getAttribute(), node); - } else { - // create leaf with inherited value - node = new MetavoxelNode(value.getAttribute()->inherit(visitation.getInheritedOutputValue(j))); - } - } - MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = node->getChild(index); - if (child) { - child->decrementReferenceCount(value.getAttribute()); - } else { - // it's a leaf; we need to split it up - AttributeValue nodeValue = value.getAttribute()->inherit(node->getAttributeValue(value.getAttribute())); - for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) { - node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue)); - } - } - node->setChild(index, nextVisitation.outputNodes.at(j)); - value = AttributeValue(); - } - } - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& value = visitation.info.outputValues[i]; - if (value.getAttribute()) { - MetavoxelNode* node = visitation.outputNodes.at(i); - node->mergeChildren(value.getAttribute()); - value = node->getAttributeValue(value.getAttribute()); - } - } - visitation.visitor->releaseVisitation(); - visitation.info.outputValues.swap(nextVisitation.info.outputValues); - bool changed = visitation.visitor->postVisit(visitation.info); - visitation.info.outputValues.swap(nextVisitation.info.outputValues); - if (changed) { - for (int i = 0; i < visitation.outputNodes.size(); i++) { - OwnedAttributeValue& newValue = nextVisitation.info.outputValues[i]; - if (!newValue.getAttribute()) { - continue; - } - OwnedAttributeValue& value = visitation.info.outputValues[i]; - MetavoxelNode*& node = visitation.outputNodes[i]; - if (value.getAttribute()) { - node->setAttributeValue(value = newValue); - - } else if (!(node && node->isLeaf() && newValue.getAttribute()->equal( - newValue.getValue(), node->getAttributeValue()))) { - node = newValue.getAttribute()->createMetavoxelNode(value = newValue, node); - } - newValue = AttributeValue(); - } - } - return true; -} - -MetavoxelVisitation::MetavoxelVisitation(MetavoxelVisitation* previous, - MetavoxelVisitor* visitor, int inputNodesSize, int outputNodesSize) : - previous(previous), - visitor(visitor), - inputNodes(inputNodesSize), - outputNodes(outputNodesSize), - info(previous ? &previous->info : NULL, inputNodesSize, outputNodesSize) { -} - -MetavoxelVisitation::MetavoxelVisitation() { -} - -bool MetavoxelVisitation::isInputLeaf(int index) const { - MetavoxelNode* node = inputNodes.at(index); - return !node || node->isLeaf() || info.size < info.lodBase * - info.inputValues.at(index).getAttribute()->getLODThresholdMultiplier(); -} - -bool MetavoxelVisitation::allInputNodesLeaves() const { - foreach (MetavoxelNode* node, inputNodes) { - if (node && !node->isLeaf()) { - return false; - } - } - return true; -} - -AttributeValue MetavoxelVisitation::getInheritedOutputValue(int index) const { - for (const MetavoxelVisitation* visitation = previous; visitation; visitation = visitation->previous) { - MetavoxelNode* node = visitation->outputNodes.at(index); - if (node) { - return node->getAttributeValue(visitor->getOutputs().at(index)); - } - } - return AttributeValue(visitor->getOutputs().at(index)); -} - -MetavoxelRenderer::MetavoxelRenderer() : - _implementation(NULL) { -} - -MetavoxelRendererImplementation* MetavoxelRenderer::getImplementation() { - QMutexLocker locker(&_implementationMutex); - if (!_implementation) { - QByteArray className = getImplementationClassName(); - const QMetaObject* metaObject = Bitstream::getMetaObject(className); - if (!metaObject) { - qDebug() << "Unknown class name:" << className; - metaObject = &MetavoxelRendererImplementation::staticMetaObject; - } - _implementation = static_cast(metaObject->newInstance()); - connect(this, &QObject::destroyed, _implementation, &QObject::deleteLater); - _implementation->init(this); - } - return _implementation; -} - -MetavoxelRendererImplementation::MetavoxelRendererImplementation() { -} - -void MetavoxelRendererImplementation::init(MetavoxelRenderer* renderer) { - _renderer = renderer; -} - -void MetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous, - MetavoxelInfo& info, const MetavoxelLOD& lod) { - // nothing by default -} - -void MetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime, - MetavoxelInfo& info, const MetavoxelLOD& lod) { - // nothing by default -} - -void MetavoxelRendererImplementation::render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod) { - // nothing by default -} - -QByteArray MetavoxelRenderer::getImplementationClassName() const { - return "MetavoxelRendererImplementation"; -} - -DefaultMetavoxelRenderer::DefaultMetavoxelRenderer() { -} - -QByteArray DefaultMetavoxelRenderer::getImplementationClassName() const { - return "DefaultMetavoxelRendererImplementation"; -} - diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h deleted file mode 100644 index 806c5bf2ae..0000000000 --- a/libraries/metavoxels/src/MetavoxelData.h +++ /dev/null @@ -1,539 +0,0 @@ -// -// MetavoxelData.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelData_h -#define hifi_MetavoxelData_h - -#include -#include -#include -#include -#include - -#include - -#include "AttributeRegistry.h" -#include "MetavoxelUtil.h" - -class MetavoxelInfo; -class MetavoxelNode; -class MetavoxelRendererImplementation; -class MetavoxelVisitation; -class MetavoxelVisitor; -class Spanner; - -/// Determines whether to subdivide each node when traversing. Contains the position (presumed to be of the viewer) and a -/// threshold value, where lower thresholds cause smaller/more distant voxels to be subdivided. -class MetavoxelLOD { - STREAMABLE - -public: - STREAM glm::vec3 position; - STREAM float threshold; - - MetavoxelLOD(const glm::vec3& position = glm::vec3(), float threshold = 0.0f); - - bool isValid() const { return threshold > 0.0f; } - - /// Checks whether, according to this LOD, we should subdivide the described voxel. - bool shouldSubdivide(const glm::vec3& minimum, float size, float multiplier = 1.0f) const; - - /// Checks whether the node or any of the nodes underneath it have had subdivision enabled as compared to the reference. - bool becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const; - - /// Checks whether the node or any of the nodes underneath it have had subdivision - /// enabled or disabled as compared to the reference. - bool becameSubdividedOrCollapsed(const glm::vec3& minimum, float size, - const MetavoxelLOD& reference, float multiplier = 1.0f) const; - - /// Checks whether, according to this LOD, we should subdivide the described region. - bool shouldSubdivide(const glm::vec2& minimum, float size, float multiplier = 1.0f) const; - - /// Checks whether the node or any of the nodes underneath it have had subdivision enabled as compared to the reference. - bool becameSubdivided(const glm::vec2& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const; - - /// Checks whether the node or any of the nodes underneath it have had subdivision - /// enabled or disabled as compared to the reference. - bool becameSubdividedOrCollapsed(const glm::vec2& minimum, float size, - const MetavoxelLOD& reference, float multiplier = 1.0f) const; -}; - -DECLARE_STREAMABLE_METATYPE(MetavoxelLOD) - -/// The base metavoxel representation shared between server and client. Contains a size (for all dimensions) and a set of -/// octrees for different attributes. -class MetavoxelData { -public: - - MetavoxelData(); - MetavoxelData(const MetavoxelData& other); - ~MetavoxelData(); - - MetavoxelData& operator=(const MetavoxelData& other); - - /// Sets the size in all dimensions. - void setSize(float size) { _size = size; } - float getSize() const { return _size; } - - /// Returns the minimum extent of the octrees (which are centered about the origin). - glm::vec3 getMinimum() const { return glm::vec3(_size, _size, _size) * -0.5f; } - - /// Returns the bounds of the octrees. - Box getBounds() const; - - /// Applies the specified visitor to the contained voxels. - void guide(MetavoxelVisitor& visitor); - - /// Guides the specified visitor to the voxels that differ from those of the specified other. - void guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor); - - /// Inserts a spanner into the specified attribute layer. - void insert(const AttributePointer& attribute, const SharedObjectPointer& object); - void insert(const AttributePointer& attribute, const Box& bounds, float granularity, const SharedObjectPointer& object); - - /// Removes a spanner from the specified attribute layer. - void remove(const AttributePointer& attribute, const SharedObjectPointer& object); - void remove(const AttributePointer& attribute, const Box& bounds, float granularity, const SharedObjectPointer& object); - - /// Toggles the existence of a spanner in the specified attribute layer (removes if present, adds if not). - void toggle(const AttributePointer& attribute, const SharedObjectPointer& object); - void toggle(const AttributePointer& attribute, const Box& bounds, float granularity, const SharedObjectPointer& object); - - /// Replaces a spanner in the specified attribute layer. - void replace(const AttributePointer& attribute, const SharedObjectPointer& oldObject, - const SharedObjectPointer& newObject); - void replace(const AttributePointer& attribute, const Box& bounds, float granularity, const SharedObjectPointer& oldObject, - const SharedObjectPointer& newObject); - - /// Retrieves all spanners that intersect the specified bounds. - void getIntersecting(const AttributePointer& attribute, const Box& bounds, QVector& results); - - /// Clears all data in the specified attribute layer. - void clear(const AttributePointer& attribute); - - /// "Touches" all data in the specified attribute layer, making it look as if it has changed. - void touch(const AttributePointer& attribute); - - /// Convenience function that finds the first spanner intersecting the provided ray. - SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction, - const AttributePointer& attribute, float& distance, const MetavoxelLOD& lod = MetavoxelLOD()); - - /// Sets part of the data. - void set(const glm::vec3& minimum, const MetavoxelData& data, bool blend = false); - - /// Expands the tree, doubling its size in all dimensions (that is, increasing its volume eightfold). - void expand(); - - void read(Bitstream& in, const MetavoxelLOD& lod = MetavoxelLOD()); - void write(Bitstream& out, const MetavoxelLOD& lod = MetavoxelLOD()) const; - - void readDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, Bitstream& in, const MetavoxelLOD& lod); - void writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD, - Bitstream& out, const MetavoxelLOD& lod) const; - - void setRoot(const AttributePointer& attribute, MetavoxelNode* root); - MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); } - MetavoxelNode* createRoot(const AttributePointer& attribute); - - /// Performs a deep comparison between this data and the specified other (as opposed to the == operator, which does a - /// shallow comparison). - bool deepEquals(const MetavoxelData& other, const MetavoxelLOD& lod = MetavoxelLOD()) const; - - /// Counts the nodes in the data. - void countNodes(int& internalNodes, int& leaves, const MetavoxelLOD& lod = MetavoxelLOD()) const; - - void dumpStats(QDebug debug = QDebug(QtDebugMsg)) const; - - bool operator==(const MetavoxelData& other) const; - bool operator!=(const MetavoxelData& other) const; - -private: - - friend class MetavoxelVisitation; - - void incrementRootReferenceCounts(); - void decrementRootReferenceCounts(); - - float _size; - QHash _roots; -}; - -Bitstream& operator<<(Bitstream& out, const MetavoxelData& data); - -Bitstream& operator>>(Bitstream& in, MetavoxelData& data); - -template<> void Bitstream::writeDelta(const MetavoxelData& value, const MetavoxelData& reference); - -template<> void Bitstream::readDelta(MetavoxelData& value, const MetavoxelData& reference); - -Q_DECLARE_METATYPE(MetavoxelData) - -/// Holds the base state used in streaming metavoxel data. -class MetavoxelStreamBase { -public: - const AttributePointer& attribute; - Bitstream& stream; - const MetavoxelLOD& lod; - const MetavoxelLOD& referenceLOD; - int visit; -}; - -/// Holds the state used in streaming a metavoxel node. -class MetavoxelStreamState { -public: - MetavoxelStreamBase& base; - glm::vec3 minimum; - float size; - - bool shouldSubdivide() const; - bool shouldSubdivideReference() const; - bool becameSubdivided() const; - bool becameSubdividedOrCollapsed() const; - - void setMinimum(const glm::vec3& lastMinimum, int index); -}; - -/// A single node within a metavoxel layer. -class MetavoxelNode { -public: - - static const int CHILD_COUNT = 8; - - static int getOppositeChildIndex(int index); - - MetavoxelNode(const AttributeValue& attributeValue, const MetavoxelNode* copyChildren = NULL); - MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy); - - void setAttributeValue(const AttributeValue& attributeValue); - - void blendAttributeValues(const AttributeValue& source, const AttributeValue& dest); - - AttributeValue getAttributeValue(const AttributePointer& attribute) const; - void* getAttributeValue() const { return _attributeValue; } - - void mergeChildren(const AttributePointer& attribute, bool postRead = false); - - MetavoxelNode* getChild(int index) const { return _children[index]; } - void setChild(int index, MetavoxelNode* child) { _children[index] = child; } - - bool isLeaf() const; - - void read(MetavoxelStreamState& state); - void write(MetavoxelStreamState& state) const; - - void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state); - void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const; - - MetavoxelNode* readSubdivision(MetavoxelStreamState& state); - void writeSubdivision(MetavoxelStreamState& state) const; - - void readSubdivided(MetavoxelStreamState& state, const MetavoxelStreamState& ancestorState, void* ancestorValue); - void writeSubdivided(MetavoxelStreamState& state, const MetavoxelStreamState& ancestorState, void* ancestorValue) const; - - void writeSpanners(MetavoxelStreamState& state) const; - - /// Increments the node's reference count. - void incrementReferenceCount() { _referenceCount.ref(); } - - /// Decrements the node's reference count. If the resulting reference count is zero, destroys the node - /// and calls delete this. - void decrementReferenceCount(const AttributePointer& attribute); - - void destroy(const AttributePointer& attribute); - - bool clearChildren(const AttributePointer& attribute); - - /// Performs a deep comparison between this and the specified other node. - bool deepEquals(const AttributePointer& attribute, const MetavoxelNode& other, - const glm::vec3& minimum, float size, const MetavoxelLOD& lod) const; - - /// Retrieves all spanners satisfying the LOD constraint, placing them in the provided set. - void getSpanners(const AttributePointer& attribute, const glm::vec3& minimum, - float size, const MetavoxelLOD& lod, SharedObjectSet& results) const; - - void countNodes(const AttributePointer& attribute, const glm::vec3& minimum, - float size, const MetavoxelLOD& lod, int& internalNodes, int& leaves) const; - - MetavoxelNode* touch(const AttributePointer& attribute) const; - -private: - Q_DISABLE_COPY(MetavoxelNode) - - friend class MetavoxelVisitation; - - QAtomicInt _referenceCount; - void* _attributeValue; - MetavoxelNode* _children[CHILD_COUNT]; -}; - -/// Contains information about a metavoxel (explicit or procedural). -class MetavoxelInfo { -public: - - MetavoxelInfo* parentInfo; - glm::vec3 minimum; ///< the minimum extent of the area covered by the voxel - float size; ///< the size of the voxel in all dimensions - QVector inputValues; - QVector outputValues; - float lodBase; - bool isLODLeaf; - bool isLeaf; - - MetavoxelInfo(MetavoxelInfo* parentInfo, int inputValuesSize, int outputValuesSize); - MetavoxelInfo(); - - Box getBounds() const { return Box(minimum, minimum + glm::vec3(size, size, size)); } - glm::vec3 getCenter() const { return minimum + glm::vec3(size, size, size) * 0.5f; } -}; - -/// Base class for visitors to metavoxels. -class MetavoxelVisitor { -public: - - /// Encodes a visitation order sequence for the children of a metavoxel. - static int encodeOrder(int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eighth); - - /// Encodes a visitation order sequence that visits each child as sorted along the specified direction. - static int encodeOrder(const glm::vec3& direction); - - /// Returns a random visitation order sequence. - static int encodeRandomOrder(); - - /// The default visitation order. - static const int DEFAULT_ORDER; - - /// A special "order" that instructs the guide to stop recursion. - static const int STOP_RECURSION; - - /// A special "order" that short-circuits the tour. - static const int SHORT_CIRCUIT; - - /// A flag combined with an order that instructs us to return to visiting all nodes (rather than the different ones) for - /// just this level. - static const int ALL_NODES; - - /// A flag combined with an order that instructs us to return to visiting all nodes (rather than the different ones) for - /// this level and all beneath it. - static const int ALL_NODES_REST; - - MetavoxelVisitor(const QVector& inputs, - const QVector& outputs = QVector(), - const MetavoxelLOD& lod = MetavoxelLOD()); - virtual ~MetavoxelVisitor(); - - /// Returns a reference to the list of input attributes desired. - const QVector& getInputs() const { return _inputs; } - - /// Returns a reference to the list of output attributes provided. - const QVector& getOutputs() const { return _outputs; } - - /// Returns a reference to the level of detail that will determine subdivision levels. - const MetavoxelLOD& getLOD() const { return _lod; } - - void setLOD(const MetavoxelLOD& lod) { _lod = lod; } - - float getMinimumLODThresholdMultiplier() const { return _minimumLODThresholdMultiplier; } - - /// Prepares for a new tour of the metavoxel data. - virtual void prepare(MetavoxelData* data); - - /// Visits a metavoxel. - /// \param info the metavoxel data - /// \return the encoded order in which to traverse the children, zero to stop recursion, or -1 to short-circuit the tour. - /// If child traversal is requested, postVisit will be called after we return from traversing the children and have merged - /// their values - virtual int visit(MetavoxelInfo& info) = 0; - - /// Called after we have visited all of a metavoxel's children. - /// \return whether or not any outputs were set in the info - virtual bool postVisit(MetavoxelInfo& info); - - /// Acquires the next visitation, incrementing the depth. - MetavoxelVisitation& acquireVisitation(); - - /// Releases the current visitation, decrementing the depth. - void releaseVisitation() { _depth--; } - -protected: - - QVector _inputs; - QVector _outputs; - MetavoxelLOD _lod; - float _minimumLODThresholdMultiplier; - MetavoxelData* _data; - QList _visitations; - int _depth; -}; - -/// Base class for visitors to spanners. -class SpannerVisitor : public MetavoxelVisitor { -public: - - SpannerVisitor(const QVector& spannerInputs, - const QVector& inputs = QVector(), - const QVector& outputs = QVector(), - const MetavoxelLOD& lod = MetavoxelLOD(), - int order = DEFAULT_ORDER); - - /// Visits a spanner. - /// \return true to continue, false to short-circuit the tour - virtual bool visit(Spanner* spanner) = 0; - - virtual void prepare(MetavoxelData* data); - virtual int visit(MetavoxelInfo& info); - -protected: - - int _spannerInputCount; - int _order; - int _visit; -}; - -/// Base class for ray intersection visitors. -class RayIntersectionVisitor : public MetavoxelVisitor { -public: - - RayIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, - const QVector& inputs, - const QVector& outputs = QVector(), - const MetavoxelLOD& lod = MetavoxelLOD()); - - /// Visits a metavoxel that the ray intersects. - virtual int visit(MetavoxelInfo& info, float distance) = 0; - - virtual int visit(MetavoxelInfo& info); - -protected: - - glm::vec3 _origin; - glm::vec3 _direction; - int _order; -}; - -/// Base class for ray intersection spanner visitors. -class RaySpannerIntersectionVisitor : public RayIntersectionVisitor { -public: - - RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, - const QVector& spannerInputs, - const QVector& inputs = QVector(), - const QVector& outputs = QVector(), - const MetavoxelLOD& lod = MetavoxelLOD()); - - /// Visits a spanner that the ray intersects. - /// \return true to continue, false to short-circuit the tour - virtual bool visitSpanner(Spanner* spanner, float distance) = 0; - - virtual void prepare(MetavoxelData* data); - virtual int visit(MetavoxelInfo& info, float distance); - -protected: - - int _spannerInputCount; - int _visit; -}; - -/// Interface for objects that guide metavoxel visitors. -class MetavoxelGuide : public SharedObject { - Q_OBJECT - -public: - - /// Guides the specified visitor to the contained voxels. - /// \return true to keep going, false to short circuit the tour - virtual bool guide(MetavoxelVisitation& visitation) = 0; - - /// Guides the specified visitor to the voxels that differ from a reference. - /// \return true to keep going, false to short circuit the tour - virtual bool guideToDifferent(MetavoxelVisitation& visitation); -}; - -/// Guides visitors through the explicit content of the system. -class DefaultMetavoxelGuide : public MetavoxelGuide { - Q_OBJECT - -public: - - Q_INVOKABLE DefaultMetavoxelGuide(); - - virtual bool guide(MetavoxelVisitation& visitation); - virtual bool guideToDifferent(MetavoxelVisitation& visitation); -}; - -/// Contains the state associated with a visit to a metavoxel system. -class MetavoxelVisitation { -public: - - MetavoxelVisitation* previous; - MetavoxelVisitor* visitor; - QVector inputNodes; - QVector outputNodes; - QVector compareNodes; - MetavoxelInfo info; - - MetavoxelVisitation(MetavoxelVisitation* previous, MetavoxelVisitor* visitor, int inputNodesSize, int outputNodesSize); - MetavoxelVisitation(); - - bool isInputLeaf(int index) const; - bool allInputNodesLeaves() const; - AttributeValue getInheritedOutputValue(int index) const; -}; - -/// Base class for objects that render metavoxels. -class MetavoxelRenderer : public SharedObject { - Q_OBJECT - -public: - - MetavoxelRenderer(); - - /// Returns a pointer to the implementation, creating it if necessary. - MetavoxelRendererImplementation* getImplementation(); - -protected: - - MetavoxelRendererImplementation* _implementation; - QMutex _implementationMutex; - - /// Returns the name of the class to instantiate for the implementation. - virtual QByteArray getImplementationClassName() const; -}; - -/// Base class for renderer implementations. -class MetavoxelRendererImplementation : public SharedObject { - Q_OBJECT - -public: - - Q_INVOKABLE MetavoxelRendererImplementation(); - - virtual void init(MetavoxelRenderer* renderer); - virtual void augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod); - virtual void simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod); - virtual void render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod); - -protected: - - MetavoxelRenderer* _renderer; -}; - -/// The standard, usual renderer. -class DefaultMetavoxelRenderer : public MetavoxelRenderer { - Q_OBJECT - -public: - - Q_INVOKABLE DefaultMetavoxelRenderer(); - - virtual QByteArray getImplementationClassName() const; -}; - -#endif // hifi_MetavoxelData_h diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp deleted file mode 100644 index 98da28cafa..0000000000 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// -// MetavoxelMessages.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 1/24/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "MetavoxelMessages.h" -#include "Spanner.h" - -void MetavoxelEditMessage::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - static_cast(edit.data())->apply(data, objects); -} - -MetavoxelEdit::~MetavoxelEdit() { -} - -void MetavoxelEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // nothing by default -} - -BoxSetEdit::BoxSetEdit(const Box& region, float granularity, const OwnedAttributeValue& value) : - region(region), granularity(granularity), value(value) { -} - -class BoxSetEditVisitor : public MetavoxelVisitor { -public: - - BoxSetEditVisitor(const BoxSetEdit& edit); - - virtual int visit(MetavoxelInfo& info); - -private: - - const BoxSetEdit& _edit; -}; - -BoxSetEditVisitor::BoxSetEditVisitor(const BoxSetEdit& edit) : - MetavoxelVisitor(QVector(), QVector() << edit.value.getAttribute()), - _edit(edit) { -} - -int BoxSetEditVisitor::visit(MetavoxelInfo& info) { - // find the intersection between volume and voxel - glm::vec3 minimum = glm::max(info.minimum, _edit.region.minimum); - glm::vec3 maximum = glm::min(info.minimum + glm::vec3(info.size, info.size, info.size), _edit.region.maximum); - glm::vec3 size = maximum - minimum; - if (size.x <= 0.0f || size.y <= 0.0f || size.z <= 0.0f) { - return STOP_RECURSION; // disjoint - } - float volume = (size.x * size.y * size.z) / (info.size * info.size * info.size); - if (volume >= 1.0f) { - info.outputValues[0] = _edit.value; - return STOP_RECURSION; // entirely contained - } - if (info.size <= _edit.granularity) { - if (volume >= 0.5f) { - info.outputValues[0] = _edit.value; - } - return STOP_RECURSION; // reached granularity limit; take best guess - } - return DEFAULT_ORDER; // subdivide -} - -void BoxSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // expand to fit the entire edit - while (!data.getBounds().contains(region)) { - data.expand(); - } - - BoxSetEditVisitor setVisitor(*this); - data.guide(setVisitor); -} - -GlobalSetEdit::GlobalSetEdit(const OwnedAttributeValue& value) : - value(value) { -} - -class GlobalSetEditVisitor : public MetavoxelVisitor { -public: - - GlobalSetEditVisitor(const GlobalSetEdit& edit); - - virtual int visit(MetavoxelInfo& info); - -private: - - const GlobalSetEdit& _edit; -}; - -GlobalSetEditVisitor::GlobalSetEditVisitor(const GlobalSetEdit& edit) : - MetavoxelVisitor(QVector(), QVector() << edit.value.getAttribute()), - _edit(edit) { -} - -int GlobalSetEditVisitor::visit(MetavoxelInfo& info) { - info.outputValues[0] = _edit.value; - return STOP_RECURSION; // entirely contained -} - -void GlobalSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - GlobalSetEditVisitor visitor(*this); - data.guide(visitor); -} - -InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) : - attribute(attribute), - spanner(spanner) { -} - -void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - data.insert(attribute, spanner); -} - -RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id) : - attribute(attribute), - id(id) { -} - -void RemoveSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - SharedObject* object = objects.value(id); - if (object) { - data.remove(attribute, object); - } -} - -ClearSpannersEdit::ClearSpannersEdit(const AttributePointer& attribute) : - attribute(attribute) { -} - -void ClearSpannersEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - data.clear(attribute); -} - -SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data, bool blend) : - minimum(minimum), - data(data), - blend(blend) { -} - -void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - data.set(minimum, this->data, blend); -} - -PaintHeightfieldHeightEdit::PaintHeightfieldHeightEdit(const glm::vec3& position, float radius, - float height, bool set, bool erase, float granularity) : - position(position), - radius(radius), - height(height), - set(set), - erase(erase), - granularity(granularity) { -} - -void PaintHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // increase the extents slightly to include neighboring tiles - const float RADIUS_EXTENSION = 1.1f; - glm::vec3 extents = glm::vec3(radius, radius, radius) * RADIUS_EXTENSION; - QVector results; - data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), - Box(position - extents, position + extents), results); - - foreach (const SharedObjectPointer& spanner, results) { - Spanner* newSpanner = static_cast(spanner.data())->paintHeight(position, radius, - height, set, erase, granularity); - if (newSpanner != spanner) { - data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner); - } - } -} - -MaterialEdit::MaterialEdit(const SharedObjectPointer& material, const QColor& averageColor) : - material(material), - averageColor(averageColor) { -} - -HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner, - const SharedObjectPointer& material, const QColor& averageColor, bool paint, bool voxelize, float granularity) : - MaterialEdit(material, averageColor), - spanner(spanner), - paint(paint), - voxelize(voxelize), - granularity(granularity) { -} - -class SpannerProjectionFetchVisitor : public SpannerVisitor { -public: - - SpannerProjectionFetchVisitor(const Box& bounds, QVector& results); - - virtual bool visit(Spanner* spanner); - -private: - - const Box& _bounds; - QVector& _results; - float _closestDistance; -}; - -SpannerProjectionFetchVisitor::SpannerProjectionFetchVisitor(const Box& bounds, QVector& results) : - SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute()), - _bounds(bounds), - _results(results), - _closestDistance(FLT_MAX) { -} - -bool SpannerProjectionFetchVisitor::visit(Spanner* spanner) { - Heightfield* heightfield = qobject_cast(spanner); - if (!heightfield) { - return true; - } - glm::mat4 transform = glm::scale(1.0f / glm::vec3(heightfield->getScale(), - heightfield->getScale() * heightfield->getAspectY(), - heightfield->getScale() * heightfield->getAspectZ())) * - glm::mat4_cast(glm::inverse(heightfield->getRotation())) * glm::translate(-heightfield->getTranslation()); - Box transformedBounds = transform * _bounds; - if (transformedBounds.maximum.x < 0.0f || transformedBounds.maximum.z < 0.0f || - transformedBounds.minimum.x > 1.0f || transformedBounds.minimum.z > 1.0f) { - return true; - } - float distance = qMin(glm::abs(transformedBounds.minimum.y), glm::abs(transformedBounds.maximum.y)); - if (distance < _closestDistance) { - _results.clear(); - _results.append(spanner); - _closestDistance = distance; - } - return true; -} - -void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - // make sure the color meets our transparency requirements - QColor color = averageColor; - if (paint) { - color.setAlphaF(1.0f); - - } else if (color.alphaF() < 0.5f) { - color = QColor(0, 0, 0, 0); - } - QVector results; - data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), - static_cast(spanner.data())->getBounds(), results); - - // if there's nothing intersecting directly, find the closest heightfield that intersects the projection - if (results.isEmpty()) { - SpannerProjectionFetchVisitor visitor(static_cast(spanner.data())->getBounds(), results); - data.guide(visitor); - } - - foreach (const SharedObjectPointer& result, results) { - Spanner* newResult = static_cast(result.data())->setMaterial(spanner, material, - color, paint, voxelize, granularity); - if (newResult != result) { - data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), result, newResult); - } - } -} - -FillHeightfieldHeightEdit::FillHeightfieldHeightEdit(const glm::vec3& position, float radius, float granularity) : - position(position), - radius(radius), - granularity(granularity) { -} - -void FillHeightfieldHeightEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { - glm::vec3 extents = glm::vec3(radius, radius, radius); - QVector results; - data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(), - Box(position - extents, position + extents), results); - - foreach (const SharedObjectPointer& spanner, results) { - Spanner* newSpanner = static_cast(spanner.data())->fillHeight(position, radius, granularity); - if (newSpanner != spanner) { - data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), spanner, newSpanner); - } - } -} diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h deleted file mode 100644 index 7fbe2b4243..0000000000 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ /dev/null @@ -1,269 +0,0 @@ -// -// MetavoxelMessages.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/31/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelMessages_h -#define hifi_MetavoxelMessages_h - -#include "MetavoxelData.h" - -/// Requests to close the session. -class CloseSessionMessage { - STREAMABLE -}; - -DECLARE_STREAMABLE_METATYPE(CloseSessionMessage) - -/// Clears the mapping for a shared object. -class ClearSharedObjectMessage { - STREAMABLE - -public: - - STREAM int id; -}; - -DECLARE_STREAMABLE_METATYPE(ClearSharedObjectMessage) - -/// Clears the mapping for a shared object on the main channel (as opposed to the one on which the message was sent). -class ClearMainChannelSharedObjectMessage { - STREAMABLE - -public: - - STREAM int id; -}; - -DECLARE_STREAMABLE_METATYPE(ClearMainChannelSharedObjectMessage) - -/// A message containing the state of a client. -class ClientStateMessage { - STREAMABLE - -public: - - STREAM MetavoxelLOD lod; -}; - -DECLARE_STREAMABLE_METATYPE(ClientStateMessage) - -/// A message preceding metavoxel delta information. The actual delta will follow it in the stream. -class MetavoxelDeltaMessage { - STREAMABLE -}; - -DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaMessage) - -/// A message indicating that metavoxel delta information is being sent on a reliable channel. -class MetavoxelDeltaPendingMessage { - STREAMABLE - -public: - - STREAM int id; - STREAM int sentPacketNumber; - STREAM int receivedPacketNumber; -}; - -DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage) - -/// A simple streamable edit. -class MetavoxelEditMessage { - STREAMABLE - -public: - - STREAM QVariant edit; - - void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(MetavoxelEditMessage) - -/// Abstract base class for edits. -class MetavoxelEdit { -public: - - virtual ~MetavoxelEdit(); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -/// An edit that sets the region within a box to a value. -class BoxSetEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM Box region; - STREAM float granularity; - STREAM OwnedAttributeValue value; - - BoxSetEdit(const Box& region = Box(), float granularity = 0.0f, - const OwnedAttributeValue& value = OwnedAttributeValue()); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(BoxSetEdit) - -/// An edit that sets the entire tree to a value. -class GlobalSetEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM OwnedAttributeValue value; - - GlobalSetEdit(const OwnedAttributeValue& value = OwnedAttributeValue()); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(GlobalSetEdit) - -/// An edit that inserts a spanner into the tree. -class InsertSpannerEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM AttributePointer attribute; - STREAM SharedObjectPointer spanner; - - InsertSpannerEdit(const AttributePointer& attribute = AttributePointer(), - const SharedObjectPointer& spanner = SharedObjectPointer()); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(InsertSpannerEdit) - -/// An edit that removes a spanner from the tree. -class RemoveSpannerEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM AttributePointer attribute; - STREAM int id; - - RemoveSpannerEdit(const AttributePointer& attribute = AttributePointer(), int id = 0); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(RemoveSpannerEdit) - -/// An edit that clears all spanners from the tree. -class ClearSpannersEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM AttributePointer attribute; - - ClearSpannersEdit(const AttributePointer& attribute = AttributePointer()); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(ClearSpannersEdit) - -/// An edit that directly sets part of the metavoxel data. -class SetDataEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM glm::vec3 minimum; - STREAM MetavoxelData data; - STREAM bool blend; - - SetDataEdit(const glm::vec3& minimum = glm::vec3(), const MetavoxelData& data = MetavoxelData(), bool blend = false); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(SetDataEdit) - -/// An edit that sets a region of a heightfield height. -class PaintHeightfieldHeightEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM glm::vec3 position; - STREAM float radius; - STREAM float height; - STREAM bool set; - STREAM bool erase; - STREAM float granularity; - - PaintHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, - float height = 0.0f, bool set = false, bool erase = false, float granularity = 0.0f); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(PaintHeightfieldHeightEdit) - -/// Base class for edits that have materials. -class MaterialEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM SharedObjectPointer material; - STREAM QColor averageColor; - - MaterialEdit(const SharedObjectPointer& material = SharedObjectPointer(), const QColor& averageColor = QColor()); -}; - -DECLARE_STREAMABLE_METATYPE(MaterialEdit) - -/// An edit that sets the materials of a heightfield within a spanner to a value. -class HeightfieldMaterialSpannerEdit : STREAM public MaterialEdit { - STREAMABLE - -public: - - STREAM SharedObjectPointer spanner; - STREAM bool paint; - STREAM bool voxelize; - STREAM float granularity; - - HeightfieldMaterialSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer(), - const SharedObjectPointer& material = SharedObjectPointer(), - const QColor& averageColor = QColor(), bool paint = false, bool voxelize = false, float granularity = 0.0f); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(HeightfieldMaterialSpannerEdit) - -/// An edit that fills a region of a heightfield height. -class FillHeightfieldHeightEdit : public MetavoxelEdit { - STREAMABLE - -public: - - STREAM glm::vec3 position; - STREAM float radius; - STREAM float granularity; - - FillHeightfieldHeightEdit(const glm::vec3& position = glm::vec3(), float radius = 0.0f, float granularity = 0.0f); - - virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const; -}; - -DECLARE_STREAMABLE_METATYPE(FillHeightfieldHeightEdit) - -#endif // hifi_MetavoxelMessages_h diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp deleted file mode 100644 index 4e86e1c636..0000000000 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ /dev/null @@ -1,723 +0,0 @@ -// -// MetavoxelUtil.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/30/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "MetavoxelUtil.h" -#include "ScriptCache.h" -#include "StreamUtils.h" - -static int scriptHashType = qRegisterMetaType(); -static int parameterizedURLType = qRegisterMetaType(); - -REGISTER_SIMPLE_TYPE_STREAMER(ScriptHash) -REGISTER_SIMPLE_TYPE_STREAMER(ParameterizedURL) - -class DelegatingItemEditorFactory : public QItemEditorFactory { -public: - - DelegatingItemEditorFactory(); - - virtual QWidget* createEditor(int userType, QWidget* parent) const; - virtual QByteArray valuePropertyName(int userType) const; - -private: - - const QItemEditorFactory* _parentFactory; -}; - -class DoubleEditor : public QDoubleSpinBox { -public: - - DoubleEditor(QWidget* parent = NULL); -}; - -DoubleEditor::DoubleEditor(QWidget* parent) : QDoubleSpinBox(parent) { - setMinimum(-FLT_MAX); - setMaximum(FLT_MAX); - setSingleStep(0.01); -} - -DelegatingItemEditorFactory::DelegatingItemEditorFactory() : - _parentFactory(QItemEditorFactory::defaultFactory()) { - - QItemEditorFactory::setDefaultFactory(this); -} - -QWidget* DelegatingItemEditorFactory::createEditor(int userType, QWidget* parent) const { - QWidget* editor = QItemEditorFactory::createEditor(userType, parent); - return (!editor) ? _parentFactory->createEditor(userType, parent) : editor; -} - -QByteArray DelegatingItemEditorFactory::valuePropertyName(int userType) const { - QByteArray propertyName = QItemEditorFactory::valuePropertyName(userType); - return propertyName.isNull() ? _parentFactory->valuePropertyName(userType) : propertyName; -} - -QItemEditorFactory* getItemEditorFactory() { - static QItemEditorFactory* factory = new DelegatingItemEditorFactory(); - return factory; -} - -static QItemEditorCreatorBase* createDoubleEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createQMetaObjectEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createQColorEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createQUrlEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createVec3EditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createQuatEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createParameterizedURLEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* doubleEditorCreator = createDoubleEditorCreator(); -static QItemEditorCreatorBase* qMetaObjectEditorCreator = createQMetaObjectEditorCreator(); -static QItemEditorCreatorBase* qColorEditorCreator = createQColorEditorCreator(); -static QItemEditorCreatorBase* qUrlEditorCreator = createQUrlEditorCreator(); -static QItemEditorCreatorBase* vec3EditorCreator = createVec3EditorCreator(); -static QItemEditorCreatorBase* quatEditorCreator = createQuatEditorCreator(); -static QItemEditorCreatorBase* parameterizedURLEditorCreator = createParameterizedURLEditorCreator(); - -QByteArray signal(const char* signature) { - static QByteArray prototype = SIGNAL(dummyMethod()); - QByteArray signal = prototype; - return signal.replace("dummyMethod()", signature); -} - -Box::Box(const glm::vec3& minimum, const glm::vec3& maximum) : - minimum(minimum), maximum(maximum) { -} - -void Box::add(const Box& other) { - minimum = glm::min(minimum, other.minimum); - maximum = glm::max(maximum, other.maximum); -} - -bool Box::contains(const glm::vec3& point) const { - return point.x >= minimum.x && point.x <= maximum.x && - point.y >= minimum.y && point.y <= maximum.y && - point.z >= minimum.z && point.z <= maximum.z; -} - -bool Box::contains(const Box& other) const { - return other.minimum.x >= minimum.x && other.maximum.x <= maximum.x && - other.minimum.y >= minimum.y && other.maximum.y <= maximum.y && - other.minimum.z >= minimum.z && other.maximum.z <= maximum.z; -} - -bool Box::intersects(const Box& other) const { - return other.maximum.x >= minimum.x && other.minimum.x <= maximum.x && - other.maximum.y >= minimum.y && other.minimum.y <= maximum.y && - other.maximum.z >= minimum.z && other.minimum.z <= maximum.z; -} - -Box Box::getIntersection(const Box& other) const { - return Box(glm::max(minimum, other.minimum), glm::min(maximum, other.maximum)); -} - -bool Box::isEmpty() const { - return minimum.x >= maximum.x || minimum.y >= maximum.y || minimum.z >= maximum.z; -} - -const int X_MAXIMUM_FLAG = 1; -const int Y_MAXIMUM_FLAG = 2; -const int Z_MAXIMUM_FLAG = 4; - -glm::vec3 Box::getVertex(int index) const { - return glm::vec3( - (index & X_MAXIMUM_FLAG) ? maximum.x : minimum.x, - (index & Y_MAXIMUM_FLAG) ? maximum.y : minimum.y, - (index & Z_MAXIMUM_FLAG) ? maximum.z : minimum.z); -} - -// finds the intersection between a ray and the facing plane on one axis -static bool findIntersection(float origin, float direction, float minimum, float maximum, float& distance) { - if (direction > EPSILON) { - distance = (minimum - origin) / direction; - return true; - } else if (direction < -EPSILON) { - distance = (maximum - origin) / direction; - return true; - } - return false; -} - -// determines whether a value is within the extents -static bool isWithin(float value, float minimum, float maximum) { - return value >= minimum && value <= maximum; -} - -bool Box::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - // handle the trivial case where the box contains the origin - if (contains(origin)) { - distance = 0.0f; - return true; - } - // check each axis - float axisDistance; - if ((findIntersection(origin.x, direction.x, minimum.x, maximum.x, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, minimum.y, maximum.y) && - isWithin(origin.z + axisDistance*direction.z, minimum.z, maximum.z))) { - distance = axisDistance; - return true; - } - if ((findIntersection(origin.y, direction.y, minimum.y, maximum.y, axisDistance) && axisDistance >= 0 && - isWithin(origin.x + axisDistance*direction.x, minimum.x, maximum.x) && - isWithin(origin.z + axisDistance*direction.z, minimum.z, maximum.z))) { - distance = axisDistance; - return true; - } - if ((findIntersection(origin.z, direction.z, minimum.z, maximum.z, axisDistance) && axisDistance >= 0 && - isWithin(origin.y + axisDistance*direction.y, minimum.y, maximum.y) && - isWithin(origin.x + axisDistance*direction.x, minimum.x, maximum.x))) { - distance = axisDistance; - return true; - } - return false; -} - -Box operator*(const glm::mat4& matrix, const Box& box) { - // start with the constant component - Box newBox(glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]), glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2])); - - // for each element, we choose the minimum or maximum based on the matrix sign - if (matrix[0][0] >= 0.0f) { - newBox.minimum.x += matrix[0][0] * box.minimum.x; - newBox.maximum.x += matrix[0][0] * box.maximum.x; - } else { - newBox.minimum.x += matrix[0][0] * box.maximum.x; - newBox.maximum.x += matrix[0][0] * box.minimum.x; - } - if (matrix[1][0] >= 0.0f) { - newBox.minimum.x += matrix[1][0] * box.minimum.y; - newBox.maximum.x += matrix[1][0] * box.maximum.y; - } else { - newBox.minimum.x += matrix[1][0] * box.maximum.y; - newBox.maximum.x += matrix[1][0] * box.minimum.y; - } - if (matrix[2][0] >= 0.0f) { - newBox.minimum.x += matrix[2][0] * box.minimum.z; - newBox.maximum.x += matrix[2][0] * box.maximum.z; - } else { - newBox.minimum.x += matrix[2][0] * box.maximum.z; - newBox.maximum.x += matrix[2][0] * box.minimum.z; - } - - if (matrix[0][1] >= 0.0f) { - newBox.minimum.y += matrix[0][1] * box.minimum.x; - newBox.maximum.y += matrix[0][1] * box.maximum.x; - } else { - newBox.minimum.y += matrix[0][1] * box.maximum.x; - newBox.maximum.y += matrix[0][1] * box.minimum.x; - } - if (matrix[1][1] >= 0.0f) { - newBox.minimum.y += matrix[1][1] * box.minimum.y; - newBox.maximum.y += matrix[1][1] * box.maximum.y; - } else { - newBox.minimum.y += matrix[1][1] * box.maximum.y; - newBox.maximum.y += matrix[1][1] * box.minimum.y; - } - if (matrix[2][1] >= 0.0f) { - newBox.minimum.y += matrix[2][1] * box.minimum.z; - newBox.maximum.y += matrix[2][1] * box.maximum.z; - } else { - newBox.minimum.y += matrix[2][1] * box.maximum.z; - newBox.maximum.y += matrix[2][1] * box.minimum.z; - } - - if (matrix[0][2] >= 0.0f) { - newBox.minimum.z += matrix[0][2] * box.minimum.x; - newBox.maximum.z += matrix[0][2] * box.maximum.x; - } else { - newBox.minimum.z += matrix[0][2] * box.maximum.x; - newBox.maximum.z += matrix[0][2] * box.minimum.x; - } - if (matrix[1][2] >= 0.0f) { - newBox.minimum.z += matrix[1][2] * box.minimum.y; - newBox.maximum.z += matrix[1][2] * box.maximum.y; - } else { - newBox.minimum.z += matrix[1][2] * box.maximum.y; - newBox.maximum.z += matrix[1][2] * box.minimum.y; - } - if (matrix[2][2] >= 0.0f) { - newBox.minimum.z += matrix[2][2] * box.minimum.z; - newBox.maximum.z += matrix[2][2] * box.maximum.z; - } else { - newBox.minimum.z += matrix[2][2] * box.maximum.z; - newBox.maximum.z += matrix[2][2] * box.minimum.z; - } - - return newBox; -} - -QDebug& operator<<(QDebug& dbg, const Box& box) { - return dbg.nospace() << "{type='Box', minimum=" << box.minimum << ", maximum=" << box.maximum << "}"; -} - -AxisExtents::AxisExtents(const glm::vec3& first0, const glm::vec3& first1, const glm::vec3& first2, const glm::vec3& second) : - axis(glm::cross(first2 - first1, first0 - first1)), - minimum(glm::dot(first1, axis)), - maximum(glm::dot(second, axis)) { -} - -AxisExtents::AxisExtents(const glm::vec3& axis, float minimum, float maximum) : - axis(axis), - minimum(minimum), - maximum(maximum) { -} - -void Frustum::set(const glm::vec3& farTopLeft, const glm::vec3& farTopRight, const glm::vec3& farBottomLeft, - const glm::vec3& farBottomRight, const glm::vec3& nearTopLeft, const glm::vec3& nearTopRight, - const glm::vec3& nearBottomLeft, const glm::vec3& nearBottomRight) { - - _vertices[0] = farBottomLeft; - _vertices[1] = farBottomRight; - _vertices[2] = farTopLeft; - _vertices[3] = farTopRight; - _vertices[4] = nearBottomLeft; - _vertices[5] = nearBottomRight; - _vertices[6] = nearTopLeft; - _vertices[7] = nearTopRight; - - // compute the bounds - _bounds.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX); - _bounds.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX); - for (int i = 0; i < VERTEX_COUNT; i++) { - _bounds.minimum = glm::min(_bounds.minimum, _vertices[i]); - _bounds.maximum = glm::max(_bounds.maximum, _vertices[i]); - } - - // compute the extents for each side - _sideExtents[0] = AxisExtents(nearBottomLeft, nearTopLeft, nearTopRight, farBottomLeft); - _sideExtents[1] = AxisExtents(nearBottomLeft, farBottomLeft, farTopLeft, farBottomRight); - _sideExtents[2] = AxisExtents(nearBottomRight, nearTopRight, farTopRight, farBottomLeft); - _sideExtents[3] = AxisExtents(nearBottomLeft, nearBottomRight, farBottomRight, farTopLeft); - _sideExtents[4] = AxisExtents(nearTopLeft, farTopLeft, farTopRight, farBottomRight); - - // the other set of extents are derived from the cross products of the frustum and box edges - glm::vec3 edges[] = { nearBottomRight - nearBottomLeft, nearTopLeft - nearBottomLeft, farBottomLeft - nearBottomLeft, - farBottomRight - nearBottomRight, farTopLeft - nearTopLeft, farTopRight - nearTopRight }; - const int AXIS_COUNT = 3; - for (uint i = 0, extentIndex = 0; i < sizeof(edges) / sizeof(edges[0]); i++) { - for (int j = 0; j < AXIS_COUNT; j++) { - glm::vec3 axis; - axis[j] = 1.0f; - glm::vec3 crossProduct = glm::cross(edges[i], axis); - float minimum = FLT_MAX, maximum = -FLT_MAX; - for (int k = 0; k < VERTEX_COUNT; k++) { - float projection = glm::dot(crossProduct, _vertices[k]); - minimum = glm::min(minimum, projection); - maximum = glm::max(maximum, projection); - } - _crossProductExtents[extentIndex++] = AxisExtents(crossProduct, minimum, maximum); - } - } -} - -Frustum::IntersectionType Frustum::getIntersectionType(const Box& box) const { - // first check the bounds (equivalent to checking frustum vertices against box extents) - if (!_bounds.intersects(box)) { - return NO_INTERSECTION; - } - - // check box vertices against side extents - bool allInside = true; - for (int i = 0; i < SIDE_EXTENT_COUNT; i++) { - const AxisExtents& extents = _sideExtents[i]; - float firstProjection = glm::dot(box.getVertex(0), extents.axis); - if (firstProjection < extents.minimum) { - allInside = false; - for (int j = 1; j < Box::VERTEX_COUNT; j++) { - if (glm::dot(box.getVertex(j), extents.axis) >= extents.minimum) { - goto sideContinue; - } - } - return NO_INTERSECTION; - - } else if (firstProjection > extents.maximum) { - allInside = false; - for (int j = 1; j < Box::VERTEX_COUNT; j++) { - if (glm::dot(box.getVertex(j), extents.axis) <= extents.maximum) { - goto sideContinue; - } - } - return NO_INTERSECTION; - - } else if (allInside) { - for (int j = 1; j < Box::VERTEX_COUNT; j++) { - float projection = glm::dot(box.getVertex(j), extents.axis); - if (projection < extents.minimum || projection > extents.maximum) { - allInside = false; - goto sideContinue; - } - } - } - sideContinue: ; - } - if (allInside) { - return CONTAINS_INTERSECTION; - } - - // check box vertices against cross product extents - for (int i = 0; i < CROSS_PRODUCT_EXTENT_COUNT; i++) { - const AxisExtents& extents = _crossProductExtents[i]; - float firstProjection = glm::dot(box.getVertex(0), extents.axis); - if (firstProjection < extents.minimum) { - for (int j = 1; j < Box::VERTEX_COUNT; j++) { - if (glm::dot(box.getVertex(j), extents.axis) >= extents.minimum) { - goto crossProductContinue; - } - } - return NO_INTERSECTION; - - } else if (firstProjection > extents.maximum) { - for (int j = 1; j < Box::VERTEX_COUNT; j++) { - if (glm::dot(box.getVertex(j), extents.axis) <= extents.maximum) { - goto crossProductContinue; - } - } - return NO_INTERSECTION; - } - crossProductContinue: ; - } - - return PARTIAL_INTERSECTION; -} - -QMetaObjectEditor::QMetaObjectEditor(QWidget* parent) : QWidget(parent) { - QVBoxLayout* layout = new QVBoxLayout(); - layout->setContentsMargins(QMargins()); - layout->setAlignment(Qt::AlignTop); - setLayout(layout); - layout->addWidget(_box = new QComboBox()); - connect(_box, SIGNAL(currentIndexChanged(int)), SLOT(updateMetaObject())); - - foreach (const QMetaObject* metaObject, Bitstream::getMetaObjectSubClasses(&SharedObject::staticMetaObject)) { - _box->addItem(metaObject->className(), QVariant::fromValue(metaObject)); - } -} - -void QMetaObjectEditor::setMetaObject(const QMetaObject* metaObject) { - _metaObject = metaObject; - _box->setCurrentIndex(_metaObject ? _box->findText(_metaObject->className()) : -1); -} - -void QMetaObjectEditor::updateMetaObject() { - int index = _box->currentIndex(); - emit metaObjectChanged(_metaObject = (index == -1) ? NULL : _box->itemData(index).value()); -} - -QColorEditor::QColorEditor(QWidget* parent) : QWidget(parent) { - QVBoxLayout* layout = new QVBoxLayout(); - layout->setContentsMargins(QMargins()); - layout->setAlignment(Qt::AlignTop); - setLayout(layout); - layout->addWidget(_button = new QPushButton()); - connect(_button, SIGNAL(clicked()), SLOT(selectColor())); - setColor(QColor()); -} - -void QColorEditor::setColor(const QColor& color) { - QString name = (_color = color).name(); - _button->setStyleSheet(QString("background: %1; color: %2").arg(name, QColor::fromRgb(~color.rgb()).name())); - _button->setText(name); -} - -void QColorEditor::selectColor() { - QColor color = QColorDialog::getColor(_color, this, QString(), QColorDialog::ShowAlphaChannel); - if (color.isValid()) { - setColor(color); - emit colorChanged(color); - } -} - -Setting::Handle editorURLs("editorURLs"); - -QUrlEditor::QUrlEditor(QWidget* parent) : - QComboBox(parent) { - - setEditable(true); - setInsertPolicy(InsertAtTop); - - // populate initial URL list from settings - addItems(editorURLs.get()); - - connect(this, SIGNAL(activated(const QString&)), SLOT(updateURL(const QString&))); - connect(model(), SIGNAL(rowsInserted(const QModelIndex&,int,int)), SLOT(updateSettings())); -} - -void QUrlEditor::setURL(const QUrl& url) { - setCurrentText((_url = url).toString()); -} - -void QUrlEditor::updateURL(const QString& text) { - emit urlChanged(_url = text); -} - -void QUrlEditor::updateSettings() { - QStringList urls; - const int MAX_STORED_URLS = 10; - for (int i = 0, size = qMin(MAX_STORED_URLS, count()); i < size; i++) { - urls.append(itemText(i)); - } - editorURLs.set(urls); -} - -BaseVec3Editor::BaseVec3Editor(QWidget* parent) : QWidget(parent) { - QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(QMargins()); - setLayout(layout); - - layout->addWidget(_x = createComponentBox()); - layout->addWidget(_y = createComponentBox()); - layout->addWidget(_z = createComponentBox()); -} - -void BaseVec3Editor::setSingleStep(double singleStep) { - _x->setSingleStep(singleStep); - _y->setSingleStep(singleStep); - _z->setSingleStep(singleStep); -} - -double BaseVec3Editor::getSingleStep() const { - return _x->singleStep(); -} - -QDoubleSpinBox* BaseVec3Editor::createComponentBox() { - QDoubleSpinBox* box = new QDoubleSpinBox(); - box->setMinimum(-FLT_MAX); - box->setMaximum(FLT_MAX); - box->setMinimumWidth(50); - connect(box, SIGNAL(valueChanged(double)), SLOT(updateValue())); - return box; -} - -Vec3Editor::Vec3Editor(QWidget* parent) : BaseVec3Editor(parent) { - setSingleStep(0.01); -} - -static void setComponentValue(QDoubleSpinBox* box, double value) { - box->blockSignals(true); - box->setValue(value); - box->blockSignals(false); -} - -void Vec3Editor::setValue(const glm::vec3& value) { - _value = value; - setComponentValue(_x, value.x); - setComponentValue(_y, value.y); - setComponentValue(_z, value.z); -} - -void Vec3Editor::updateValue() { - emit valueChanged(_value = glm::vec3(_x->value(), _y->value(), _z->value())); -} - -QuatEditor::QuatEditor(QWidget* parent) : BaseVec3Editor(parent) { - _x->setRange(-179.0, 180.0); - _y->setRange(-179.0, 180.0); - _z->setRange(-179.0, 180.0); - - _x->setWrapping(true); - _y->setWrapping(true); - _z->setWrapping(true); -} - -void QuatEditor::setValue(const glm::quat& value) { - if (_value != value) { - glm::vec3 eulers = glm::degrees(safeEulerAngles(_value = value)); - setComponentValue(_x, eulers.x); - setComponentValue(_y, eulers.y); - setComponentValue(_z, eulers.z); - } -} - -void QuatEditor::updateValue() { - glm::quat value(glm::radians(glm::vec3(_x->value(), _y->value(), _z->value()))); - if (_value != value) { - emit valueChanged(_value = value); - } -} - -ParameterizedURL::ParameterizedURL(const QUrl& url, const ScriptHash& parameters) : - _url(url), - _parameters(parameters) { -} - -bool ParameterizedURL::operator==(const ParameterizedURL& other) const { - return _url == other._url && _parameters == other._parameters; -} - -bool ParameterizedURL::operator!=(const ParameterizedURL& other) const { - return _url != other._url || _parameters != other._parameters; -} - -uint qHash(const ParameterizedURL& url, uint seed) { - // just hash on the URL, for now - return qHash(url.getURL(), seed); -} - -Bitstream& operator<<(Bitstream& out, const ParameterizedURL& url) { - out << url.getURL(); - out << url.getParameters(); - return out; -} - -Bitstream& operator>>(Bitstream& in, ParameterizedURL& url) { - QUrl qurl; - in >> qurl; - ScriptHash parameters; - in >> parameters; - url = ParameterizedURL(qurl, parameters); - return in; -} - -ParameterizedURLEditor::ParameterizedURLEditor(QWidget* parent) : - QWidget(parent) { - - QVBoxLayout* layout = new QVBoxLayout(); - layout->setContentsMargins(QMargins()); - setLayout(layout); - - QWidget* lineContainer = new QWidget(); - layout->addWidget(lineContainer); - - QHBoxLayout* lineLayout = new QHBoxLayout(); - lineContainer->setLayout(lineLayout); - lineLayout->setContentsMargins(QMargins()); - - lineLayout->addWidget(&_urlEditor, 1); - connect(&_urlEditor, SIGNAL(urlChanged(const QUrl&)), SLOT(updateURL())); - connect(&_urlEditor, SIGNAL(urlChanged(const QUrl&)), SLOT(updateParameters())); - - QPushButton* refresh = new QPushButton("..."); - connect(refresh, SIGNAL(clicked(bool)), SLOT(updateParameters())); - lineLayout->addWidget(refresh); -} - -void ParameterizedURLEditor::setURL(const ParameterizedURL& url) { - _urlEditor.setURL((_url = url).getURL()); - updateParameters(); -} - -void ParameterizedURLEditor::updateURL() { - ScriptHash parameters; - if (layout()->count() > 1) { - QFormLayout* form = static_cast(layout()->itemAt(1)); - for (int i = 0; i < form->rowCount(); i++) { - QWidget* widget = form->itemAt(i, QFormLayout::FieldRole)->widget(); - QByteArray valuePropertyName = widget->property("valuePropertyName").toByteArray(); - const QMetaObject* widgetMetaObject = widget->metaObject(); - QMetaProperty widgetProperty = widgetMetaObject->property(widgetMetaObject->indexOfProperty(valuePropertyName)); - parameters.insert(DependencyManager::get()->getEngine()->toStringHandle( - widget->property("parameterName").toString()), widgetProperty.read(widget)); - } - } - emit urlChanged(_url = ParameterizedURL(_urlEditor.getURL(), parameters)); - if (_program) { - _program->disconnect(this); - } -} - -void ParameterizedURLEditor::updateParameters() { - if (_program) { - _program->disconnect(this); - } - _program = DependencyManager::get()->getProgram(_url.getURL()); - if (_program->isLoaded()) { - continueUpdatingParameters(); - } else { - connect(_program.data(), SIGNAL(loaded()), SLOT(continueUpdatingParameters())); - } -} - -void ParameterizedURLEditor::continueUpdatingParameters() { - QVBoxLayout* layout = static_cast(this->layout()); - if (layout->count() > 1) { - QFormLayout* form = static_cast(layout->takeAt(1)); - for (int i = form->count() - 1; i >= 0; i--) { - QLayoutItem* item = form->takeAt(i); - if (item->widget()) { - delete item->widget(); - } - delete item; - } - delete form; - } - QSharedPointer value = DependencyManager::get()->getValue(_url.getURL()); - const QList& parameters = static_cast(value.data())->getParameterInfo(); - if (parameters.isEmpty()) { - return; - } - QFormLayout* form = new QFormLayout(); - layout->addLayout(form); - foreach (const ParameterInfo& parameter, parameters) { - QWidget* widget = QItemEditorFactory::defaultFactory()->createEditor(parameter.type, NULL); - if (widget) { - form->addRow(parameter.name.toString() + ":", widget); - QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(parameter.type); - widget->setProperty("parameterName", parameter.name.toString()); - widget->setProperty("valuePropertyName", valuePropertyName); - const QMetaObject* widgetMetaObject = widget->metaObject(); - QMetaProperty widgetProperty = widgetMetaObject->property(widgetMetaObject->indexOfProperty(valuePropertyName)); - widgetProperty.write(widget, _url.getParameters().value(parameter.name)); - if (widgetProperty.hasNotifySignal()) { - connect(widget, signal(widgetProperty.notifySignal().methodSignature()), SLOT(updateURL())); - } - } - } -} diff --git a/libraries/metavoxels/src/MetavoxelUtil.h b/libraries/metavoxels/src/MetavoxelUtil.h deleted file mode 100644 index 3be54ca60d..0000000000 --- a/libraries/metavoxels/src/MetavoxelUtil.h +++ /dev/null @@ -1,362 +0,0 @@ -// -// MetavoxelUtil.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 12/30/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelUtil_h -#define hifi_MetavoxelUtil_h - -#include -#include -#include -#include -#include -#include - -#include - -#include "Bitstream.h" - -class QByteArray; -class QDoubleSpinBox; -class QItemEditorFactory; -class QPushButton; - -class NetworkProgram; - -/// Performs the runtime equivalent of Qt's SIGNAL macro, which is to attach a prefix to the signature. -QByteArray signal(const char* signature); - -/// A streamable axis-aligned bounding box. -class Box { - STREAMABLE - -public: - - static const int VERTEX_COUNT = 8; - - STREAM glm::vec3 minimum; - STREAM glm::vec3 maximum; - - explicit Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3()); - - void add(const Box& other); - - bool contains(const glm::vec3& point) const; - - bool contains(const Box& other) const; - - bool intersects(const Box& other) const; - - Box getIntersection(const Box& other) const; - - bool isEmpty() const; - - float getLongestSide() const { return qMax(qMax(maximum.x - minimum.x, maximum.y - minimum.y), maximum.z - minimum.z); } - - glm::vec3 getVertex(int index) const; - - glm::vec3 getCenter() const { return (minimum + maximum) * 0.5f; } - - bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; -}; - -DECLARE_STREAMABLE_METATYPE(Box) - -Box operator*(const glm::mat4& matrix, const Box& box); - -QDebug& operator<<(QDebug& out, const Box& box); - -/// Represents the extents along an axis. -class AxisExtents { -public: - glm::vec3 axis; - float minimum; - float maximum; - - /// Creates a set of extents given three points on the first plane and one on the second. - AxisExtents(const glm::vec3& first0, const glm::vec3& first1, const glm::vec3& first2, const glm::vec3& second); - - AxisExtents(const glm::vec3& axis = glm::vec3(), float minimum = 0.0f, float maximum = 0.0f); -}; - -/// A simple pyramidal frustum for intersection testing. -class Frustum { -public: - - void set(const glm::vec3& farTopLeft, const glm::vec3& farTopRight, const glm::vec3& farBottomLeft, - const glm::vec3& farBottomRight, const glm::vec3& nearTopLeft, const glm::vec3& nearTopRight, - const glm::vec3& nearBottomLeft, const glm::vec3& nearBottomRight); - - enum IntersectionType { NO_INTERSECTION, PARTIAL_INTERSECTION, CONTAINS_INTERSECTION }; - - IntersectionType getIntersectionType(const Box& box) const; - -private: - - static const int VERTEX_COUNT = 8; - static const int SIDE_EXTENT_COUNT = 5; - static const int CROSS_PRODUCT_EXTENT_COUNT = 18; - - glm::vec3 _vertices[VERTEX_COUNT]; - Box _bounds; - AxisExtents _sideExtents[SIDE_EXTENT_COUNT]; - AxisExtents _crossProductExtents[CROSS_PRODUCT_EXTENT_COUNT]; -}; - -/// Returns a pointer to the singleton item editor factory. -QItemEditorFactory* getItemEditorFactory(); - -/// Because Windows doesn't necessarily have the staticMetaObject available when we want to create, -/// this class simply delays the value property name lookup until actually requested. -template class LazyItemEditorCreator : public QItemEditorCreatorBase { -public: - - virtual QWidget* createWidget(QWidget* parent) const { return new T(parent); } - - virtual QByteArray valuePropertyName() const; - -protected: - - QByteArray _valuePropertyName; -}; - -template QByteArray LazyItemEditorCreator::valuePropertyName() const { - if (_valuePropertyName.isNull()) { - const_cast*>(this)->_valuePropertyName = T::staticMetaObject.userProperty().name(); - } - return _valuePropertyName; -} - -/// Editor for meta-object values. -class QMetaObjectEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(const QMetaObject* metaObject MEMBER _metaObject WRITE setMetaObject NOTIFY metaObjectChanged USER true) - -public: - - QMetaObjectEditor(QWidget* parent); - -signals: - - void metaObjectChanged(const QMetaObject* metaObject); - -public slots: - - void setMetaObject(const QMetaObject* metaObject); - -private slots: - - void updateMetaObject(); - -private: - - QComboBox* _box; - const QMetaObject* _metaObject; -}; - -/// Editor for color values. -class QColorEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(QColor color MEMBER _color WRITE setColor NOTIFY colorChanged USER true) - -public: - - QColorEditor(QWidget* parent); - - const QColor& getColor() const { return _color; } - -signals: - - void colorChanged(const QColor& color); - -public slots: - - void setColor(const QColor& color); - -private slots: - - void selectColor(); - -private: - - QPushButton* _button; - QColor _color; -}; - -/// Editor for URL values. -class QUrlEditor : public QComboBox { - Q_OBJECT - Q_PROPERTY(QUrl url READ getURL WRITE setURL NOTIFY urlChanged USER true) - -public: - - QUrlEditor(QWidget* parent = NULL); - - void setURL(const QUrl& url); - const QUrl& getURL() { return _url; } - -signals: - - void urlChanged(const QUrl& url); - -private slots: - - void updateURL(const QString& text); - void updateSettings(); - -private: - - QUrl _url; -}; - -/// Base class for Vec3Editor and QuatEditor. -class BaseVec3Editor : public QWidget { - Q_OBJECT - -public: - - BaseVec3Editor(QWidget* parent); - - void setSingleStep(double singleStep); - double getSingleStep() const; - -protected slots: - - virtual void updateValue() = 0; - -protected: - - QDoubleSpinBox* createComponentBox(); - - QDoubleSpinBox* _x; - QDoubleSpinBox* _y; - QDoubleSpinBox* _z; -}; - -/// Editor for vector values. -class Vec3Editor : public BaseVec3Editor { - Q_OBJECT - Q_PROPERTY(glm::vec3 value MEMBER _value WRITE setValue NOTIFY valueChanged USER true) - -public: - - Vec3Editor(QWidget* parent); - - const glm::vec3& getValue() const { return _value; } - -signals: - - void valueChanged(const glm::vec3& vector); - -public slots: - - void setValue(const glm::vec3& vector); - -protected: - - virtual void updateValue(); - -private: - - glm::vec3 _value; -}; - -/// Editor for quaternion values. -class QuatEditor : public BaseVec3Editor { - Q_OBJECT - Q_PROPERTY(glm::quat value MEMBER _value WRITE setValue NOTIFY valueChanged USER true) - -public: - - QuatEditor(QWidget* parent); - -signals: - - void valueChanged(const glm::quat& value); - -public slots: - - void setValue(const glm::quat& value); - -protected: - - virtual void updateValue(); - -private: - - glm::quat _value; -}; - -typedef QHash ScriptHash; - -Q_DECLARE_METATYPE(ScriptHash) - -/// Combines a URL with a set of typed parameters. -class ParameterizedURL { -public: - - ParameterizedURL(const QUrl& url = QUrl(), const ScriptHash& parameters = ScriptHash()); - - bool isValid() const { return _url.isValid(); } - - void setURL(const QUrl& url) { _url = url; } - const QUrl& getURL() const { return _url; } - - void setParameters(const ScriptHash& parameters) { _parameters = parameters; } - const ScriptHash& getParameters() const { return _parameters; } - - bool operator==(const ParameterizedURL& other) const; - bool operator!=(const ParameterizedURL& other) const; - -private: - - QUrl _url; - ScriptHash _parameters; -}; - -uint qHash(const ParameterizedURL& url, uint seed = 0); - -Bitstream& operator<<(Bitstream& out, const ParameterizedURL& url); -Bitstream& operator>>(Bitstream& in, ParameterizedURL& url); - -Q_DECLARE_METATYPE(ParameterizedURL) - -/// Allows editing parameterized URLs. -class ParameterizedURLEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(ParameterizedURL url MEMBER _url WRITE setURL NOTIFY urlChanged USER true) - -public: - - ParameterizedURLEditor(QWidget* parent = NULL); - -signals: - - void urlChanged(const ParameterizedURL& url); - -public slots: - - void setURL(const ParameterizedURL& url); - -private slots: - - void updateURL(); - void updateParameters(); - void continueUpdatingParameters(); - -private: - - ParameterizedURL _url; - QSharedPointer _program; - - QUrlEditor _urlEditor; -}; - -#endif // hifi_MetavoxelUtil_h diff --git a/libraries/metavoxels/src/ScriptCache.cpp b/libraries/metavoxels/src/ScriptCache.cpp deleted file mode 100644 index b7e81b5381..0000000000 --- a/libraries/metavoxels/src/ScriptCache.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// ScriptCache.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 2/4/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include -#include -#include - -#include "AttributeRegistry.h" -#include "ScriptCache.h" - -static int scriptValueMetaTypeId = qRegisterMetaType(); -static bool scriptValueComparators = QMetaType::registerComparators(); - -bool operator==(const QScriptValue& first, const QScriptValue& second) { - if (first.isUndefined()) { - return second.isUndefined(); - - } else if (first.isNull()) { - return second.isNull(); - - } else if (first.isBool()) { - return second.isBool() && first.toBool() == second.toBool(); - - } else if (first.isNumber()) { - return second.isNumber() && first.toNumber() == second.toNumber(); - - } else if (first.isString()) { - return second.isString() && first.toString() == second.toString(); - - } else if (first.isVariant()) { - return second.isVariant() && first.toVariant() == second.toVariant(); - - } else if (first.isQObject()) { - return second.isQObject() && first.toQObject() == second.toQObject(); - - } else if (first.isQMetaObject()) { - return second.isQMetaObject() && first.toQMetaObject() == second.toQMetaObject(); - - } else if (first.isDate()) { - return second.isDate() && first.toDateTime() == second.toDateTime(); - - } else if (first.isRegExp()) { - return second.isRegExp() && first.toRegExp() == second.toRegExp(); - - } else if (first.isArray()) { - if (!second.isArray()) { - return false; - } - int length = first.property(DependencyManager::get()->getLengthString()).toInt32(); - if (second.property(DependencyManager::get()->getLengthString()).toInt32() != length) { - return false; - } - for (int i = 0; i < length; i++) { - if (first.property(i) != second.property(i)) { - return false; - } - } - return true; - - } else if (first.isObject()) { - if (!second.isObject()) { - return false; - } - int propertyCount = 0; - for (QScriptValueIterator it(first); it.hasNext(); ) { - it.next(); - if (second.property(it.scriptName()) != it.value()) { - return false; - } - propertyCount++; - } - // make sure the second has exactly as many properties as the first - for (QScriptValueIterator it(second); it.hasNext(); ) { - it.next(); - if (--propertyCount < 0) { - return false; - } - } - return true; - - } else { - // if none of the above tests apply, first must be invalid - return !second.isValid(); - } -} - -bool operator!=(const QScriptValue& first, const QScriptValue& second) { - return !(first == second); -} - -bool operator<(const QScriptValue& first, const QScriptValue& second) { - return first.lessThan(second); -} - -ScriptCache::ScriptCache() : - _engine(NULL) -{ - setEngine(new QScriptEngine(this)); - - const qint64 SCRIPT_DEFAULT_UNUSED_MAX_SIZE = 50 * BYTES_PER_MEGABYTES; - setUnusedResourceCacheSize(SCRIPT_DEFAULT_UNUSED_MAX_SIZE); -} - -void ScriptCache::setEngine(QScriptEngine* engine) { - if (_engine && _engine->parent() == this) { - delete _engine; - } - AttributeRegistry::getInstance()->configureScriptEngine(_engine = engine); - _parametersString = engine->toStringHandle("parameters"); - _lengthString = engine->toStringHandle("length"); - _nameString = engine->toStringHandle("name"); - _typeString = engine->toStringHandle("type"); - _generatorString = engine->toStringHandle("generator"); -} - -QSharedPointer ScriptCache::getValue(const ParameterizedURL& url) { - QSharedPointer value = _networkValues.value(url); - if (value.isNull()) { - value = QSharedPointer(url.getParameters().isEmpty() ? - (NetworkValue*)new RootNetworkValue(getProgram(url.getURL())) : - (NetworkValue*)new DerivedNetworkValue(getValue(url.getURL()), url.getParameters())); - _networkValues.insert(url, value); - } - return value; -} - -QSharedPointer ScriptCache::createResource(const QUrl& url, - const QSharedPointer& fallback, bool delayLoad, const void* extra) { - return QSharedPointer(new NetworkProgram(this, url), &Resource::allReferencesCleared); -} - -NetworkProgram::NetworkProgram(ScriptCache* cache, const QUrl& url) : - Resource(url), - _cache(cache) { -} - -void NetworkProgram::downloadFinished(QNetworkReply* reply) { - _program = QScriptProgram(QTextStream(reply).readAll(), reply->url().toString()); - reply->deleteLater(); - finishedLoading(true); - emit loaded(); -} - -NetworkValue::~NetworkValue() { -} - -RootNetworkValue::RootNetworkValue(const QSharedPointer& program) : - _program(program) { -} - -QScriptValue& RootNetworkValue::getValue() { - if (!_value.isValid() && _program->isLoaded()) { - _value = _program->getCache()->getEngine()->evaluate(_program->getProgram()); - } - return _value; -} - -const QList& RootNetworkValue::getParameterInfo() { - if (isLoaded() && _parameterInfo.isEmpty()) { - ScriptCache* cache = _program->getCache(); - QScriptEngine* engine = cache->getEngine(); - QScriptValue parameters = _value.property(cache->getParametersString()); - if (parameters.isArray()) { - int length = parameters.property(cache->getLengthString()).toInt32(); - for (int i = 0; i < length; i++) { - QScriptValue parameter = parameters.property(i); - ParameterInfo info = { engine->toStringHandle(parameter.property(cache->getNameString()).toString()), - QMetaType::type(parameter.property(cache->getTypeString()).toString().toUtf8().constData()) }; - _parameterInfo.append(info); - } - } - } - return _parameterInfo; -} - -DerivedNetworkValue::DerivedNetworkValue(const QSharedPointer& baseValue, const ScriptHash& parameters) : - _baseValue(baseValue), - _parameters(parameters) { -} - -QScriptValue& DerivedNetworkValue::getValue() { - if (!_value.isValid() && _baseValue->isLoaded()) { - RootNetworkValue* root = static_cast(_baseValue.data()); - ScriptCache* cache = root->getProgram()->getCache(); - QScriptValue generator = _baseValue->getValue().property(cache->getGeneratorString()); - if (generator.isFunction()) { - QScriptValueList arguments; - foreach (const ParameterInfo& parameter, root->getParameterInfo()) { - arguments.append(cache->getEngine()->newVariant(_parameters.value(parameter.name))); - } - _value = generator.call(QScriptValue(), arguments); - - } else { - _value = _baseValue->getValue(); - } - } - return _value; -} diff --git a/libraries/metavoxels/src/ScriptCache.h b/libraries/metavoxels/src/ScriptCache.h deleted file mode 100644 index b9294a7504..0000000000 --- a/libraries/metavoxels/src/ScriptCache.h +++ /dev/null @@ -1,152 +0,0 @@ -// -// ScriptCache.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 2/4/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ScriptCache_h -#define hifi_ScriptCache_h - -#include -#include - -#include - -#include "MetavoxelUtil.h" - -class QScriptEngine; - -class NetworkProgram; -class NetworkValue; - -/// Maintains a cache of loaded scripts. -class ScriptCache : public ResourceCache, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: - ScriptCache(); - - void setEngine(QScriptEngine* engine); - QScriptEngine* getEngine() const { return _engine; } - - /// Loads a script program from the specified URL. - QSharedPointer getProgram(const QUrl& url) { return getResource(url).staticCast(); } - - /// Loads a script value from the specified URL. - QSharedPointer getValue(const ParameterizedURL& url); - - const QScriptString& getParametersString() const { return _parametersString; } - const QScriptString& getLengthString() const { return _lengthString; } - const QScriptString& getNameString() const { return _nameString; } - const QScriptString& getTypeString() const { return _typeString; } - const QScriptString& getGeneratorString() const { return _generatorString; } - -protected: - - virtual QSharedPointer createResource(const QUrl& url, - const QSharedPointer& fallback, bool delayLoad, const void* extra); - -private: - - QScriptEngine* _engine; - QHash > _networkValues; - QScriptString _parametersString; - QScriptString _lengthString; - QScriptString _nameString; - QScriptString _typeString; - QScriptString _generatorString; -}; - -Q_DECLARE_METATYPE(QScriptValue) - -bool operator==(const QScriptValue& first, const QScriptValue& second); -bool operator!=(const QScriptValue& first, const QScriptValue& second); -bool operator<(const QScriptValue& first, const QScriptValue& second); - -/// A program loaded from the network. -class NetworkProgram : public Resource { - Q_OBJECT - -public: - - NetworkProgram(ScriptCache* cache, const QUrl& url); - - ScriptCache* getCache() const { return _cache; } - - const QScriptProgram& getProgram() const { return _program; } - -signals: - - void loaded(); - -protected: - - virtual void downloadFinished(QNetworkReply* reply); - -private: - - ScriptCache* _cache; - QScriptProgram _program; -}; - -/// Abstract base class of values loaded from the network. -class NetworkValue { -public: - - virtual ~NetworkValue(); - - bool isLoaded() { return getValue().isValid(); } - - virtual QScriptValue& getValue() = 0; - -protected: - - QScriptValue _value; -}; - -/// Contains information about a script parameter. -class ParameterInfo { -public: - QScriptString name; - int type; -}; - -/// The direct result of running a program. -class RootNetworkValue : public NetworkValue { -public: - - RootNetworkValue(const QSharedPointer& program); - - const QSharedPointer& getProgram() const { return _program; } - - virtual QScriptValue& getValue(); - - const QList& getParameterInfo(); - -private: - - QSharedPointer _program; - QList _parameterInfo; -}; - -/// The result of running a program's generator using a set of arguments. -class DerivedNetworkValue : public NetworkValue { -public: - - DerivedNetworkValue(const QSharedPointer& baseValue, const ScriptHash& parameters); - - virtual QScriptValue& getValue(); - -private: - - QSharedPointer _baseValue; - ScriptHash _parameters; -}; - -#endif // hifi_ScriptCache_h diff --git a/libraries/metavoxels/src/SharedObject.cpp b/libraries/metavoxels/src/SharedObject.cpp deleted file mode 100644 index 6369037e2a..0000000000 --- a/libraries/metavoxels/src/SharedObject.cpp +++ /dev/null @@ -1,319 +0,0 @@ -// -// SharedObject.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 2/5/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include - -#include "Bitstream.h" -#include "MetavoxelUtil.h" -#include "SharedObject.h" - -REGISTER_META_OBJECT(SharedObject) - -SharedObject::SharedObject() : - _id(_nextID.fetchAndAddOrdered(1)), - _originID(_id), - _remoteID(0), - _remoteOriginID(0) { - - QWriteLocker locker(&_weakHashLock); - _weakHash.insert(_id, this); -} - -void SharedObject::setID(int id) { - QWriteLocker locker(&_weakHashLock); - _weakHash.remove(_id); - _weakHash.insert(_id = id, this); -} - -void SharedObject::incrementReferenceCount() { - _referenceCount.ref(); -} - -void SharedObject::decrementReferenceCount() { - if (!_referenceCount.deref()) { - { - QWriteLocker locker(&_weakHashLock); - _weakHash.remove(_id); - } - delete this; - } -} - -SharedObject* SharedObject::clone(bool withID, SharedObject* target) const { - // default behavior is to make a copy using the no-arg constructor and copy the stored properties - const QMetaObject* metaObject = this->metaObject(); - if (!target) { - target = static_cast(metaObject->newInstance()); - } - for (int i = 0; i < metaObject->propertyCount(); i++) { - QMetaProperty property = metaObject->property(i); - if (property.isStored()) { - if (property.userType() == qMetaTypeId()) { - SharedObject* value = property.read(this).value().data(); - property.write(target, QVariant::fromValue(value ? value->clone(withID) : value)); - } else { - property.write(target, property.read(this)); - } - } - } - foreach (const QByteArray& propertyName, dynamicPropertyNames()) { - target->setProperty(propertyName, property(propertyName)); - } - if (withID) { - target->setOriginID(_originID); - } - return target; -} - -bool SharedObject::equals(const SharedObject* other, bool sharedAncestry) const { - if (!other) { - return false; - } - if (other == this) { - return true; - } - // default behavior is to compare the properties - const QMetaObject* metaObject = this->metaObject(); - if (metaObject != other->metaObject() && !sharedAncestry) { - return false; - } - // use the streamer, if we have one - const ObjectStreamer* streamer = Bitstream::getObjectStreamer(metaObject); - if (streamer) { - if (!streamer->equal(this, other)) { - return false; - } - } else { - for (int i = 0; i < metaObject->propertyCount(); i++) { - QMetaProperty property = metaObject->property(i); - if (property.isStored() && property.read(this) != property.read(other)) { - return false; - } - } - } - QList dynamicPropertyNames = this->dynamicPropertyNames(); - if (dynamicPropertyNames.size() != other->dynamicPropertyNames().size()) { - return false; - } - foreach (const QByteArray& propertyName, dynamicPropertyNames) { - if (property(propertyName) != other->property(propertyName)) { - return false; - } - } - return true; -} - -void SharedObject::dump(QDebug debug) const { - debug << this; - const QMetaObject* metaObject = this->metaObject(); - for (int i = 0; i < metaObject->propertyCount(); i++) { - QMetaProperty property = metaObject->property(i); - if (property.isStored()) { - debug << property.name() << property.read(this); - } - } - QList dynamicPropertyNames = this->dynamicPropertyNames(); - foreach (const QByteArray& propertyName, dynamicPropertyNames) { - debug << propertyName << property(propertyName); - } -} - -void SharedObject::writeExtra(Bitstream& out) const { - // nothing by default -} - -void SharedObject::readExtra(Bitstream& in, bool reread) { - // nothing by default -} - -void SharedObject::writeExtraDelta(Bitstream& out, const SharedObject* reference) const { - // nothing by default -} - -void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) { - // nothing by default -} - -void SharedObject::maybeWriteSubdivision(Bitstream& out) { - // nothing by default -} - -SharedObject* SharedObject::readSubdivision(Bitstream& in) { - return this; -} - -QAtomicInt SharedObject::_nextID(1); -WeakSharedObjectHash SharedObject::_weakHash; -QReadWriteLock SharedObject::_weakHashLock; - -void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash) { - for (WeakSharedObjectHash::iterator it = hash.begin(); it != hash.end(); ) { - if (!it.value()) { - it = hash.erase(it); - } else { - it++; - } - } -} - -SharedObjectEditor::SharedObjectEditor(const QMetaObject* metaObject, bool nullable, QWidget* parent) : QWidget(parent) { - QVBoxLayout* layout = new QVBoxLayout(); - layout->setAlignment(Qt::AlignTop); - setLayout(layout); - - QFormLayout* form = new QFormLayout(); - layout->addLayout(form); - - form->addRow("Type:", _type = new QComboBox()); - if (nullable) { - _type->addItem("(none)"); - } - foreach (const QMetaObject* metaObject, Bitstream::getMetaObjectSubClasses(metaObject)) { - // add constructable subclasses - if (metaObject->constructorCount() > 0) { - _type->addItem(metaObject->className(), QVariant::fromValue(metaObject)); - } - } - connect(_type, SIGNAL(currentIndexChanged(int)), SLOT(updateType())); - updateType(); -} - -void SharedObjectEditor::setObject(const SharedObjectPointer& object) { - _object = object; - const QMetaObject* metaObject = object ? object->metaObject() : NULL; - int index = _type->findData(QVariant::fromValue(metaObject)); - if (index != -1) { - // ensure that we call updateType to obtain the values - if (_type->currentIndex() == index) { - updateType(); - } else { - _type->setCurrentIndex(index); - } - } -} - -void SharedObjectEditor::detachObject() { - SharedObject* oldObject = _object.data(); - if (!_object.detach()) { - return; - } - oldObject->disconnect(this); - const QMetaObject* metaObject = _object->metaObject(); - - QFormLayout* form = static_cast(layout()->itemAt(1)); - for (int i = 0; i < form->rowCount(); i++) { - QWidget* widget = form->itemAt(i, QFormLayout::FieldRole)->widget(); - QMetaProperty property = metaObject->property(widget->property("propertyIndex").toInt()); - if (property.hasNotifySignal()) { - connect(_object.data(), signal(property.notifySignal().methodSignature()), SLOT(updateProperty())); - } - } -} - -const QMetaObject* getOwningAncestor(const QMetaObject* metaObject, int propertyIndex) { - while (propertyIndex < metaObject->propertyOffset()) { - metaObject = metaObject->superClass(); - } - return metaObject; -} - -void SharedObjectEditor::updateType() { - // delete the existing rows - if (layout()->count() > 1) { - QFormLayout* form = static_cast(layout()->takeAt(1)); - while (!form->isEmpty()) { - QLayoutItem* item = form->takeAt(0); - if (item->widget()) { - delete item->widget(); - } - delete item; - } - delete form; - } - QObject* oldObject = static_cast(_object.data()); - const QMetaObject* oldMetaObject = NULL; - if (oldObject) { - oldMetaObject = oldObject->metaObject(); - oldObject->disconnect(this); - } - const QMetaObject* metaObject = _type->itemData(_type->currentIndex()).value(); - if (!metaObject) { - _object.reset(); - emit objectChanged(_object); - return; - } - QObject* newObject = metaObject->newInstance(); - - QFormLayout* form = new QFormLayout(); - static_cast(layout())->addLayout(form); - for (int i = QObject::staticMetaObject.propertyCount(); i < metaObject->propertyCount(); i++) { - QMetaProperty property = metaObject->property(i); - if (!property.isDesignable()) { - continue; - } - if (oldMetaObject && i < oldMetaObject->propertyCount() && - getOwningAncestor(metaObject, i) == getOwningAncestor(oldMetaObject, i)) { - // copy the state of the shared ancestry - property.write(newObject, property.read(oldObject)); - } - QWidget* widget = QItemEditorFactory::defaultFactory()->createEditor(property.userType(), NULL); - if (widget) { - widget->setProperty("propertyIndex", i); - form->addRow(QByteArray(property.name()) + ':', widget); - QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(property.userType()); - const QMetaObject* widgetMetaObject = widget->metaObject(); - QMetaProperty widgetProperty = widgetMetaObject->property(widgetMetaObject->indexOfProperty(valuePropertyName)); - widgetProperty.write(widget, property.read(newObject)); - if (widgetProperty.hasNotifySignal()) { - connect(widget, signal(widgetProperty.notifySignal().methodSignature()), SLOT(propertyChanged())); - } - if (property.hasNotifySignal()) { - widget->setProperty("notifySignalIndex", property.notifySignalIndex()); - connect(newObject, signal(property.notifySignal().methodSignature()), SLOT(updateProperty())); - } - } - } - emit objectChanged(_object = static_cast(newObject)); -} - -void SharedObjectEditor::propertyChanged() { - QFormLayout* form = static_cast(layout()->itemAt(1)); - for (int i = 0; i < form->rowCount(); i++) { - QWidget* widget = form->itemAt(i, QFormLayout::FieldRole)->widget(); - if (widget != sender()) { - continue; - } - detachObject(); - QObject* object = _object.data(); - QMetaProperty property = object->metaObject()->property(widget->property("propertyIndex").toInt()); - QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(property.userType()); - property.write(object, widget->property(valuePropertyName)); - } - emit objectChanged(_object); -} - -void SharedObjectEditor::updateProperty() { - QFormLayout* form = static_cast(layout()->itemAt(1)); - for (int i = 0; i < form->rowCount(); i++) { - QWidget* widget = form->itemAt(i, QFormLayout::FieldRole)->widget(); - if (widget->property("notifySignalIndex").toInt() != senderSignalIndex()) { - continue; - } - QMetaProperty property = _object->metaObject()->property(widget->property("propertyIndex").toInt()); - QByteArray valuePropertyName = QItemEditorFactory::defaultFactory()->valuePropertyName(property.userType()); - widget->setProperty(valuePropertyName, property.read(_object.data())); - } -} diff --git a/libraries/metavoxels/src/SharedObject.h b/libraries/metavoxels/src/SharedObject.h deleted file mode 100644 index cd46ae9658..0000000000 --- a/libraries/metavoxels/src/SharedObject.h +++ /dev/null @@ -1,268 +0,0 @@ -// -// SharedObject.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 2/5/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_SharedObject_h -#define hifi_SharedObject_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class QComboBox; - -class Bitstream; -class SharedObject; - -typedef QHash > WeakSharedObjectHash; - -/// A QObject that may be shared over the network. -class SharedObject : public QObject { - Q_OBJECT - -public: - - /// Returns the weak hash under which all local shared objects are registered. - static const WeakSharedObjectHash& getWeakHash() { return _weakHash; } - - /// Returns a reference to the weak hash lock. - static QReadWriteLock& getWeakHashLock() { return _weakHashLock; } - - Q_INVOKABLE SharedObject(); - - /// Returns the unique local ID for this object. - int getID() const { return _id; } - - void setID(int id); - - /// Returns the local origin ID for this object. - int getOriginID() const { return _originID; } - - void setOriginID(int originID) { _originID = originID; } - - /// Returns the unique remote ID for this object, or zero if this is a local object. - int getRemoteID() const { return _remoteID; } - - void setRemoteID(int remoteID) { _remoteID = remoteID; } - - /// Returns the remote origin ID for this object, or zero if this is a local object. - int getRemoteOriginID() const { return _remoteOriginID; } - - void setRemoteOriginID(int remoteOriginID) { _remoteOriginID = remoteOriginID; } - - int getReferenceCount() const { return _referenceCount.load(); } - void incrementReferenceCount(); - void decrementReferenceCount(); - - /// Creates a new clone of this object. - /// \param withID if true, give the clone the same origin ID as this object - /// \target if non-NULL, a target object to populate (as opposed to creating a new instance of this object's class) - virtual SharedObject* clone(bool withID = false, SharedObject* target = NULL) const; - - /// Tests this object for equality with another. - /// \param sharedAncestry if true and the classes of the objects differ, compare their shared ancestry (assuming that - /// this is an instance of a superclass of the other object's class) rather than simply returning false. - virtual bool equals(const SharedObject* other, bool sharedAncestry = false) const; - - /// Dumps the contents of this object to the debug output. - virtual void dump(QDebug debug = QDebug(QtDebugMsg)) const; - - /// Writes the non-property contents of this object to the specified stream. - virtual void writeExtra(Bitstream& out) const; - - /// Reads the non-property contents of this object from the specified stream. - /// \param reread if true, reread the contents from the stream but don't reapply them - virtual void readExtra(Bitstream& in, bool reread = false); - - /// Writes the delta-encoded non-property contents of this object to the specified stream. - virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; - - /// Reads the delta-encoded non-property contents of this object from the specified stream. - /// \param reread if true, reread the contents from the stream but don't reapply them - virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread = false); - - /// Writes the subdivision of the contents of this object (preceeded by a - /// reference to the object itself) to the specified stream if necessary. - virtual void maybeWriteSubdivision(Bitstream& out); - - /// Reads the subdivision of this object from the specified stream. - /// \return the modified object, or this if no modification was performed - virtual SharedObject* readSubdivision(Bitstream& in); - -private: - - int _id; - int _originID; - int _remoteID; - int _remoteOriginID; - QAtomicInt _referenceCount; - - static QAtomicInt _nextID; - static WeakSharedObjectHash _weakHash; - static QReadWriteLock _weakHashLock; -}; - -/// Removes the null references from the supplied hash. -void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash); - -/// A pointer to a shared object. -template class SharedObjectPointerTemplate { -public: - - SharedObjectPointerTemplate(T* data = NULL); - SharedObjectPointerTemplate(const SharedObjectPointerTemplate& other); - ~SharedObjectPointerTemplate(); - - T* data() const { return _data; } - - /// "Detaches" this object, making a new copy if its reference count is greater than one. - bool detach(); - - void swap(SharedObjectPointerTemplate& other) { qSwap(_data, other._data); } - - void reset(); - - bool operator!() const { return !_data; } - operator T*() const { return _data; } - T& operator*() const { return *_data; } - T* operator->() const { return _data; } - - template SharedObjectPointerTemplate staticCast() const; - - SharedObjectPointerTemplate& operator=(T* data); - SharedObjectPointerTemplate& operator=(const SharedObjectPointerTemplate& other); - - bool operator==(const SharedObjectPointerTemplate& other) const { return _data == other._data; } - bool operator!=(const SharedObjectPointerTemplate& other) const { return _data != other._data; } - -private: - - T* _data; -}; - -template inline SharedObjectPointerTemplate::SharedObjectPointerTemplate(T* data) : _data(data) { - if (_data) { - _data->incrementReferenceCount(); - } -} - -template inline SharedObjectPointerTemplate::SharedObjectPointerTemplate(const SharedObjectPointerTemplate& other) : - _data(other._data) { - - if (_data) { - _data->incrementReferenceCount(); - } -} - -template inline SharedObjectPointerTemplate::~SharedObjectPointerTemplate() { - if (_data) { - _data->decrementReferenceCount(); - } -} - -template inline bool SharedObjectPointerTemplate::detach() { - if (_data && _data->getReferenceCount() > 1) { - _data->decrementReferenceCount(); - (_data = _data->clone())->incrementReferenceCount(); - return true; - } - return false; -} - -template inline void SharedObjectPointerTemplate::reset() { - if (_data) { - _data->decrementReferenceCount(); - } - _data = NULL; -} - -template template inline SharedObjectPointerTemplate SharedObjectPointerTemplate::staticCast() const { - return SharedObjectPointerTemplate(static_cast(_data)); -} - -template inline SharedObjectPointerTemplate& SharedObjectPointerTemplate::operator=(T* data) { - if (_data) { - _data->decrementReferenceCount(); - } - if ((_data = data)) { - _data->incrementReferenceCount(); - } - return *this; -} - -template inline SharedObjectPointerTemplate& SharedObjectPointerTemplate::operator=( - const SharedObjectPointerTemplate& other) { - if (_data) { - _data->decrementReferenceCount(); - } - if ((_data = other._data)) { - _data->incrementReferenceCount(); - } - return *this; -} - -template uint qHash(const SharedObjectPointerTemplate& pointer, uint seed = 0) { - return qHash(pointer.data(), seed); -} - -template bool equals(const SharedObjectPointerTemplate& first, - const SharedObjectPointerTemplate& second) { - return first ? first->equals(second) : !second; -} - -typedef SharedObjectPointerTemplate SharedObjectPointer; - -Q_DECLARE_METATYPE(SharedObjectPointer) - -typedef QSet SharedObjectSet; - -Q_DECLARE_METATYPE(SharedObjectSet) - -/// Allows editing shared object instances. -class SharedObjectEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(SharedObjectPointer object READ getObject WRITE setObject NOTIFY objectChanged USER true) - -public: - - SharedObjectEditor(const QMetaObject* metaObject, bool nullable = true, QWidget* parent = NULL); - - const SharedObjectPointer& getObject() const { return _object; } - - /// "Detaches" the object pointer, copying it if anyone else is holding a reference. - void detachObject(); - -signals: - - void objectChanged(const SharedObjectPointer& object); - -public slots: - - void setObject(const SharedObjectPointer& object); - -private slots: - - void updateType(); - void propertyChanged(); - void updateProperty(); - -private: - - QComboBox* _type; - SharedObjectPointer _object; -}; - -#endif // hifi_SharedObject_h diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp deleted file mode 100644 index d2dff016e3..0000000000 --- a/libraries/metavoxels/src/Spanner.cpp +++ /dev/null @@ -1,4058 +0,0 @@ -// -// Spanner.cpp -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 11/10/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "MetavoxelData.h" -#include "Spanner.h" - -using namespace std; - -REGISTER_META_OBJECT(Spanner) -REGISTER_META_OBJECT(Heightfield) -REGISTER_META_OBJECT(Sphere) -REGISTER_META_OBJECT(Cuboid) -REGISTER_META_OBJECT(StaticModel) -REGISTER_META_OBJECT(MaterialObject) - -static int heightfieldHeightTypeId = registerSimpleMetaType(); -static int heightfieldColorTypeId = registerSimpleMetaType(); -static int heightfieldMaterialTypeId = registerSimpleMetaType(); - -static QItemEditorCreatorBase* createHeightfieldHeightEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* createHeightfieldColorEditorCreator() { - QItemEditorCreatorBase* creator = new LazyItemEditorCreator(); - getItemEditorFactory()->registerEditor(qMetaTypeId(), creator); - return creator; -} - -static QItemEditorCreatorBase* heightfieldHeightEditorCreator = createHeightfieldHeightEditorCreator(); -static QItemEditorCreatorBase* heightfieldColorEditorCreator = createHeightfieldColorEditorCreator(); - -const float DEFAULT_PLACEMENT_GRANULARITY = 0.01f; -const float DEFAULT_VOXELIZATION_GRANULARITY = powf(2.0f, -3.0f); - -Setting::Handle heightfieldDir("heightDir"); - -Spanner::Spanner() : - _renderer(NULL), - _placementGranularity(DEFAULT_PLACEMENT_GRANULARITY), - _voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY), - _merged(false), - _willBeVoxelized(false) { -} - -void Spanner::setBounds(const Box& bounds) { - if (_bounds == bounds) { - return; - } - emit boundsWillChange(); - emit boundsChanged(_bounds = bounds); -} - -bool Spanner::testAndSetVisited(int visit) { - QMutexLocker locker(&_lastVisitsMutex); - int& lastVisit = _lastVisits[QThread::currentThread()]; - if (lastVisit == visit) { - return false; - } - lastVisit = visit; - return true; -} - -SpannerRenderer* Spanner::getRenderer() { - if (!_renderer) { - QByteArray className = getRendererClassName(); - const QMetaObject* metaObject = Bitstream::getMetaObject(className); - if (!metaObject) { - qDebug() << "Unknown class name:" << className; - metaObject = &SpannerRenderer::staticMetaObject; - } - _renderer = static_cast(metaObject->newInstance()); - connect(this, &QObject::destroyed, _renderer, &QObject::deleteLater); - _renderer->init(this); - } - return _renderer; -} - -bool Spanner::isHeightfield() const { - return false; -} - -float Spanner::getHeight(const glm::vec3& location) const { - return -FLT_MAX; -} - -bool Spanner::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - return _bounds.findRayIntersection(origin, direction, distance); -} - -Spanner* Spanner::paintHeight(const glm::vec3& position, float radius, float height, bool set, bool erase, float granularity) { - return this; -} - -Spanner* Spanner::fillHeight(const glm::vec3& position, float radius, float granularity) { - return this; -} - -Spanner* Spanner::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint, bool voxelize, float granularity) { - return this; -} - -bool Spanner::hasOwnColors() const { - return false; -} - -bool Spanner::hasOwnMaterials() const { - return false; -} - -QRgb Spanner::getColorAt(const glm::vec3& point) { - return 0; -} - -int Spanner::getMaterialAt(const glm::vec3& point) { - return 0; -} - -QVector& Spanner::getMaterials() { - static QVector emptyMaterials; - return emptyMaterials; -} - -bool Spanner::contains(const glm::vec3& point) { - return false; -} - -bool Spanner::intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal) { - return false; -} - -QByteArray Spanner::getRendererClassName() const { - return "SpannerRendererer"; -} - -QAtomicInt Spanner::_nextVisit(1); - -SpannerRenderer::SpannerRenderer() { -} - -void SpannerRenderer::init(Spanner* spanner) { - _spanner = spanner; -} - -void SpannerRenderer::simulate(float deltaTime) { - // nothing by default -} - -void SpannerRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) { - // nothing by default -} - -bool SpannerRenderer::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - return false; -} - -Transformable::Transformable() : _scale(1.0f) { -} - -void Transformable::setTranslation(const glm::vec3& translation) { - if (_translation != translation) { - emit translationChanged(_translation = translation); - } -} - -void Transformable::setRotation(const glm::quat& rotation) { - if (_rotation != rotation) { - emit rotationChanged(_rotation = rotation); - } -} - -void Transformable::setScale(float scale) { - if (_scale != scale) { - emit scaleChanged(_scale = scale); - } -} - -ColorTransformable::ColorTransformable() : - _color(Qt::white) { -} - -void ColorTransformable::setColor(const QColor& color) { - if (_color != color) { - emit colorChanged(_color = color); - } -} - -Sphere::Sphere() { - connect(this, SIGNAL(translationChanged(const glm::vec3&)), SLOT(updateBounds())); - connect(this, SIGNAL(scaleChanged(float)), SLOT(updateBounds())); - updateBounds(); -} - -bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - return findRaySphereIntersection(origin, direction, getTranslation(), getScale(), distance); -} - -bool Sphere::contains(const glm::vec3& point) { - return glm::distance(point, getTranslation()) <= getScale(); -} - -bool Sphere::intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal) { - glm::vec3 relativeStart = start - getTranslation(); - glm::vec3 vector = end - start; - float a = glm::dot(vector, vector); - if (a == 0.0f) { - return false; - } - float b = glm::dot(relativeStart, vector); - float radicand = b * b - a * (glm::dot(relativeStart, relativeStart) - getScale() * getScale()); - if (radicand < 0.0f) { - return false; - } - float radical = glm::sqrt(radicand); - float first = (-b - radical) / a; - if (first >= 0.0f && first <= 1.0f) { - distance = first; - normal = glm::normalize(relativeStart + vector * distance); - return true; - } - float second = (-b + radical) / a; - if (second >= 0.0f && second <= 1.0f) { - distance = second; - normal = glm::normalize(relativeStart + vector * distance); - return true; - } - return false; -} - -QByteArray Sphere::getRendererClassName() const { - return "SphereRenderer"; -} - -void Sphere::updateBounds() { - glm::vec3 extent(getScale(), getScale(), getScale()); - setBounds(Box(getTranslation() - extent, getTranslation() + extent)); -} - -Cuboid::Cuboid() : - _aspectY(1.0f), - _aspectZ(1.0f) { - - connect(this, &Cuboid::translationChanged, this, &Cuboid::updateBoundsAndPlanes); - connect(this, &Cuboid::rotationChanged, this, &Cuboid::updateBoundsAndPlanes); - connect(this, &Cuboid::scaleChanged, this, &Cuboid::updateBoundsAndPlanes); - connect(this, &Cuboid::aspectYChanged, this, &Cuboid::updateBoundsAndPlanes); - connect(this, &Cuboid::aspectZChanged, this, &Cuboid::updateBoundsAndPlanes); - updateBoundsAndPlanes(); -} - -void Cuboid::setAspectY(float aspectY) { - if (_aspectY != aspectY) { - emit aspectYChanged(_aspectY = aspectY); - } -} - -void Cuboid::setAspectZ(float aspectZ) { - if (_aspectZ != aspectZ) { - emit aspectZChanged(_aspectZ = aspectZ); - } -} - -bool Cuboid::contains(const glm::vec3& point) { - glm::vec4 point4(point, 1.0f); - for (int i = 0; i < PLANE_COUNT; i++) { - if (glm::dot(_planes[i], point4) > 0.0f) { - return false; - } - } - return true; -} - -bool Cuboid::intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal) { - glm::vec4 start4(start, 1.0f); - glm::vec4 vector = glm::vec4(end - start, 0.0f); - for (int i = 0; i < PLANE_COUNT; i++) { - // first check the segment against the plane - float divisor = glm::dot(_planes[i], vector); - if (glm::abs(divisor) < EPSILON) { - continue; - } - float t = -glm::dot(_planes[i], start4) / divisor; - if (t < 0.0f || t > 1.0f) { - continue; - } - // now that we've established that it intersects the plane, check against the other sides - glm::vec4 point = start4 + vector * t; - const int PLANES_PER_AXIS = 2; - int indexOffset = ((i / PLANES_PER_AXIS) + 1) * PLANES_PER_AXIS; - for (int j = 0; j < PLANE_COUNT - PLANES_PER_AXIS; j++) { - if (glm::dot(_planes[(indexOffset + j) % PLANE_COUNT], point) > 0.0f) { - goto outerContinue; - } - } - distance = t; - normal = glm::vec3(_planes[i]); - return true; - - outerContinue: ; - } - return false; -} - -QByteArray Cuboid::getRendererClassName() const { - return "CuboidRenderer"; -} - -void Cuboid::updateBoundsAndPlanes() { - glm::vec3 extent(getScale(), getScale() * _aspectY, getScale() * _aspectZ); - glm::mat4 rotationMatrix = glm::mat4_cast(getRotation()); - setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(-extent, extent)); - - glm::vec4 translation4 = glm::vec4(getTranslation(), 1.0f); - _planes[0] = glm::vec4(glm::vec3(rotationMatrix[0]), -glm::dot(rotationMatrix[0], translation4) - getScale()); - _planes[1] = glm::vec4(glm::vec3(-rotationMatrix[0]), glm::dot(rotationMatrix[0], translation4) - getScale()); - _planes[2] = glm::vec4(glm::vec3(rotationMatrix[1]), -glm::dot(rotationMatrix[1], translation4) - getScale() * _aspectY); - _planes[3] = glm::vec4(glm::vec3(-rotationMatrix[1]), glm::dot(rotationMatrix[1], translation4) - getScale() * _aspectY); - _planes[4] = glm::vec4(glm::vec3(rotationMatrix[2]), -glm::dot(rotationMatrix[2], translation4) - getScale() * _aspectZ); - _planes[5] = glm::vec4(glm::vec3(-rotationMatrix[2]), glm::dot(rotationMatrix[2], translation4) - getScale() * _aspectZ); -} - -StaticModel::StaticModel() { -} - -void StaticModel::setURL(const QUrl& url) { - if (_url != url) { - emit urlChanged(_url = url); - } -} - -bool StaticModel::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - // delegate to renderer, if we have one - return _renderer ? _renderer->findRayIntersection(origin, direction, distance) : - Spanner::findRayIntersection(origin, direction, distance); -} - -QByteArray StaticModel::getRendererClassName() const { - return "StaticModelRenderer"; -} - -DataBlock::~DataBlock() { -} - -const int HeightfieldData::SHARED_EDGE = 1; - -HeightfieldData::HeightfieldData(int width) : - _width(width) { -} - -const int HEIGHTFIELD_DATA_HEADER_SIZE = sizeof(qint32) * 4; - -static QByteArray encodeHeightfieldHeight(int offsetX, int offsetY, int width, int height, const QVector& contents) { - QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0); - qint32* header = (qint32*)inflated.data(); - *header++ = offsetX; - *header++ = offsetY; - *header++ = width; - *header++ = height; - if (!contents.isEmpty()) { - // encode with Paeth filter (see http://en.wikipedia.org/wiki/Portable_Network_Graphics#Filtering) - QVector filteredContents(contents.size()); - const quint16* src = contents.constData(); - quint16* dest = filteredContents.data(); - *dest++ = *src++; - for (quint16* end = dest + width - 1; dest != end; dest++, src++) { - *dest = *src - src[-1]; - } - for (int y = 1; y < height; y++) { - *dest++ = *src - src[-width]; - src++; - for (quint16* end = dest + width - 1; dest != end; dest++, src++) { - int a = src[-1]; - int b = src[-width]; - int c = src[-width - 1]; - int p = a + b - c; - int ad = abs(a - p); - int bd = abs(b - p); - int cd = abs(c - p); - *dest = *src - (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c)); - } - } - inflated.append((const char*)filteredContents.constData(), filteredContents.size() * sizeof(quint16)); - } - return qCompress(inflated); -} - -static QVector decodeHeightfieldHeight(const QByteArray& encoded, int& offsetX, int& offsetY, - int& width, int& height) { - QByteArray inflated = qUncompress(encoded); - const qint32* header = (const qint32*)inflated.constData(); - offsetX = *header++; - offsetY = *header++; - width = *header++; - height = *header++; - int payloadSize = inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE; - QVector unfiltered(payloadSize / sizeof(quint16)); - if (!unfiltered.isEmpty()) { - quint16* dest = unfiltered.data(); - const quint16* src = (const quint16*)(inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE); - *dest++ = *src++; - for (quint16* end = dest + width - 1; dest != end; dest++, src++) { - *dest = *src + dest[-1]; - } - for (int y = 1; y < height; y++) { - *dest = (*src++) + dest[-width]; - dest++; - for (quint16* end = dest + width - 1; dest != end; dest++, src++) { - int a = dest[-1]; - int b = dest[-width]; - int c = dest[-width - 1]; - int p = a + b - c; - int ad = abs(a - p); - int bd = abs(b - p); - int cd = abs(c - p); - *dest = *src + (ad < bd ? (ad < cd ? a : c) : (bd < cd ? b : c)); - } - } - } - return unfiltered; -} - -const int HeightfieldHeight::HEIGHT_BORDER = 1; -const int HeightfieldHeight::HEIGHT_EXTENSION = SHARED_EDGE + 2 * HEIGHT_BORDER; - -HeightfieldHeight::HeightfieldHeight(int width, const QVector& contents) : - HeightfieldData(width), - _contents(contents) { -} - -HeightfieldHeight::HeightfieldHeight(Bitstream& in, int bytes) { - read(in, bytes); -} - -HeightfieldHeight::HeightfieldHeight(Bitstream& in, int bytes, const HeightfieldHeightPointer& reference) { - if (!reference) { - read(in, bytes); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - reference->setEncodedDelta(in.readAligned(bytes)); - reference->setDeltaData(DataBlockPointer(this)); - _width = reference->getWidth(); - _contents = reference->getContents(); - - int offsetX, offsetY, width, height; - QVector delta = decodeHeightfieldHeight(reference->getEncodedDelta(), offsetX, offsetY, width, height); - if (delta.isEmpty()) { - return; - } - if (offsetX == 0) { - _contents = delta; - _width = width; - return; - } - int minX = offsetX - 1; - int minY = offsetY - 1; - const quint16* src = delta.constData(); - quint16* dest = _contents.data() + minY * _width + minX; - for (int y = 0; y < height; y++, src += width, dest += _width) { - memcpy(dest, src, width * sizeof(quint16)); - } -} - -void HeightfieldHeight::write(Bitstream& out) { - QMutexLocker locker(&_encodedMutex); - if (_encoded.isEmpty()) { - _encoded = encodeHeightfieldHeight(0, 0, _width, _contents.size() / _width, _contents); - } - out << _encoded.size(); - out.writeAligned(_encoded); -} - -void HeightfieldHeight::writeDelta(Bitstream& out, const HeightfieldHeightPointer& reference) { - if (!reference || reference->getWidth() != _width || reference->getContents().size() != _contents.size()) { - write(out); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) { - int height = _contents.size() / _width; - int minX = _width, minY = height; - int maxX = -1, maxY = -1; - const quint16* src = _contents.constData(); - const quint16* ref = reference->getContents().constData(); - for (int y = 0; y < height; y++) { - bool difference = false; - for (int x = 0; x < _width; x++) { - if (*src++ != *ref++) { - minX = qMin(minX, x); - maxX = qMax(maxX, x); - difference = true; - } - } - if (difference) { - minY = qMin(minY, y); - maxY = qMax(maxY, y); - } - } - QVector delta; - int deltaWidth = 0, deltaHeight = 0; - if (maxX >= minX) { - deltaWidth = maxX - minX + 1; - deltaHeight = maxY - minY + 1; - delta = QVector(deltaWidth * deltaHeight); - quint16* dest = delta.data(); - src = _contents.constData() + minY * _width + minX; - for (int y = 0; y < deltaHeight; y++, src += _width, dest += deltaWidth) { - memcpy(dest, src, deltaWidth * sizeof(quint16)); - } - } - reference->setEncodedDelta(encodeHeightfieldHeight(minX + 1, minY + 1, deltaWidth, deltaHeight, delta)); - reference->setDeltaData(DataBlockPointer(this)); - } - out << reference->getEncodedDelta().size(); - out.writeAligned(reference->getEncodedDelta()); -} - -void HeightfieldHeight::read(Bitstream& in, int bytes) { - int offsetX, offsetY, height; - _contents = decodeHeightfieldHeight(_encoded = in.readAligned(bytes), offsetX, offsetY, _width, height); -} - -Bitstream& operator<<(Bitstream& out, const HeightfieldHeightPointer& value) { - if (value) { - value->write(out); - } else { - out << 0; - } - return out; -} - -Bitstream& operator>>(Bitstream& in, HeightfieldHeightPointer& value) { - int size; - in >> size; - if (size == 0) { - value = HeightfieldHeightPointer(); - } else { - value = new HeightfieldHeight(in, size); - } - return in; -} - -template<> void Bitstream::writeRawDelta(const HeightfieldHeightPointer& value, const HeightfieldHeightPointer& reference) { - if (value) { - value->writeDelta(*this, reference); - } else { - *this << 0; - } -} - -template<> void Bitstream::readRawDelta(HeightfieldHeightPointer& value, const HeightfieldHeightPointer& reference) { - int size; - *this >> size; - if (size == 0) { - value = HeightfieldHeightPointer(); - } else { - value = new HeightfieldHeight(*this, size, reference); - } -} - -HeightfieldHeightEditor::HeightfieldHeightEditor(QWidget* parent) : - QWidget(parent) { - - QHBoxLayout* layout = new QHBoxLayout(); - setLayout(layout); - - layout->addWidget(_select = new QPushButton("Select")); - connect(_select, &QPushButton::clicked, this, &HeightfieldHeightEditor::select); - - layout->addWidget(_clear = new QPushButton("Clear")); - connect(_clear, &QPushButton::clicked, this, &HeightfieldHeightEditor::clear); - _clear->setEnabled(false); -} - -void HeightfieldHeightEditor::setHeight(const HeightfieldHeightPointer& height) { - if ((_height = height)) { - _clear->setEnabled(true); - } else { - _clear->setEnabled(false); - } -} - -static int getHeightfieldSize(int size) { - return (int)glm::pow(2.0f, glm::round(glm::log((float)size - HeightfieldData::SHARED_EDGE) / - glm::log(2.0f))) + HeightfieldData::SHARED_EDGE; -} - -void HeightfieldHeightEditor::select() { - QString result = QFileDialog::getOpenFileName(this, "Select Height Image", - heightfieldDir.get(), - "Images (*.png *.jpg *.bmp *.raw *.mdr)"); - if (result.isNull()) { - return; - } - heightfieldDir.set(QFileInfo(result).path()); - const quint16 CONVERSION_OFFSET = 1; - QString lowerResult = result.toLower(); - bool isMDR = lowerResult.endsWith(".mdr"); - if (lowerResult.endsWith(".raw") || isMDR) { - QFile input(result); - input.open(QIODevice::ReadOnly); - QDataStream in(&input); - in.setByteOrder(QDataStream::LittleEndian); - if (isMDR) { - const int MDR_HEADER_SIZE = 1024; - input.seek(MDR_HEADER_SIZE); - } - int available = input.bytesAvailable() / sizeof(quint16); - QVector rawContents(available); - for (quint16* height = rawContents.data(), *end = height + available; height != end; height++) { - in >> *height; - } - if (rawContents.isEmpty()) { - QMessageBox::warning(this, "Invalid Image", "The selected image could not be read."); - return; - } - int rawSize = glm::sqrt((float)rawContents.size()); - int size = getHeightfieldSize(rawSize) + 2 * HeightfieldHeight::HEIGHT_BORDER; - QVector contents(size * size); - quint16* dest = contents.data() + (size + 1) * HeightfieldHeight::HEIGHT_BORDER; - const quint16* src = rawContents.constData(); - const float CONVERSION_SCALE = 65534.0f / numeric_limits::max(); - for (int i = 0; i < rawSize; i++, dest += size) { - for (quint16* lineDest = dest, *end = dest + rawSize; lineDest != end; lineDest++, src++) { - *lineDest = (*src == 0) ? 0 : (quint16)(*src * CONVERSION_SCALE) + CONVERSION_OFFSET; - } - } - emit heightChanged(_height = new HeightfieldHeight(size, contents)); - _clear->setEnabled(true); - return; - } - QImage image; - if (!image.load(result)) { - QMessageBox::warning(this, "Invalid Image", "The selected image could not be read."); - return; - } - image = image.convertToFormat(QImage::Format_ARGB32); - int width = getHeightfieldSize(image.width()) + 2 * HeightfieldHeight::HEIGHT_BORDER; - int height = getHeightfieldSize(image.height()) + 2 * HeightfieldHeight::HEIGHT_BORDER; - QVector contents(width * height); - quint16* dest = contents.data() + (width + 1) * HeightfieldHeight::HEIGHT_BORDER; - const float CONVERSION_SCALE = 65534.0f / numeric_limits::max(); - for (int i = 0; i < image.height(); i++, dest += width) { - const QRgb* src = (const QRgb*)image.constScanLine(i); - for (quint16* lineDest = dest, *end = dest + image.width(); lineDest != end; lineDest++, src++) { - *lineDest = (qAlpha(*src) < numeric_limits::max()) ? 0 : - (quint16)(qRed(*src) * CONVERSION_SCALE) + CONVERSION_OFFSET; - } - } - emit heightChanged(_height = new HeightfieldHeight(width, contents)); - _clear->setEnabled(true); -} - -void HeightfieldHeightEditor::clear() { - emit heightChanged(_height = HeightfieldHeightPointer()); - _clear->setEnabled(false); -} - -static QByteArray encodeHeightfieldColor(int offsetX, int offsetY, int width, int height, const QByteArray& contents) { - QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0); - qint32* header = (qint32*)inflated.data(); - *header++ = offsetX; - *header++ = offsetY; - *header++ = width; - *header++ = height; - if (!contents.isEmpty()) { - QBuffer buffer(&inflated); - buffer.open(QIODevice::WriteOnly | QIODevice::Append); - QImage((const uchar*)contents.constData(), width, height, width * DataBlock::COLOR_BYTES, - QImage::Format_RGB888).save(&buffer, "JPG"); - } - return qCompress(inflated); -} - -static QByteArray decodeHeightfieldColor(const QByteArray& encoded, int& offsetX, int& offsetY, int& width, int& height) { - QByteArray inflated = qUncompress(encoded); - const qint32* header = (const qint32*)inflated.constData(); - offsetX = *header++; - offsetY = *header++; - width = *header++; - height = *header++; - int payloadSize = inflated.size() - HEIGHTFIELD_DATA_HEADER_SIZE; - if (payloadSize == 0) { - return QByteArray(); - } - QImage image = QImage::fromData((const uchar*)inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE, payloadSize, "JPG"); - if (image.format() != QImage::Format_RGB888) { - image = image.convertToFormat(QImage::Format_RGB888); - } - QByteArray contents(width * height * DataBlock::COLOR_BYTES, 0); - char* dest = contents.data(); - int stride = width * DataBlock::COLOR_BYTES; - for (int y = 0; y < height; y++, dest += stride) { - memcpy(dest, image.constScanLine(y), stride); - } - return contents; -} - -HeightfieldColor::HeightfieldColor(int width, const QByteArray& contents) : - HeightfieldData(width), - _contents(contents) { -} - -HeightfieldColor::HeightfieldColor(Bitstream& in, int bytes) { - read(in, bytes); -} - -HeightfieldColor::HeightfieldColor(Bitstream& in, int bytes, const HeightfieldColorPointer& reference) { - if (!reference) { - read(in, bytes); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - reference->setEncodedDelta(in.readAligned(bytes)); - reference->setDeltaData(DataBlockPointer(this)); - _width = reference->getWidth(); - _contents = reference->getContents(); - - int offsetX, offsetY, width, height; - QByteArray delta = decodeHeightfieldColor(reference->getEncodedDelta(), offsetX, offsetY, width, height); - if (delta.isEmpty()) { - return; - } - if (offsetX == 0) { - _contents = delta; - _width = width; - return; - } - int minX = offsetX - 1; - int minY = offsetY - 1; - const char* src = delta.constData(); - char* dest = _contents.data() + (minY * _width + minX) * DataBlock::COLOR_BYTES; - for (int y = 0; y < height; y++, src += width * DataBlock::COLOR_BYTES, dest += _width * DataBlock::COLOR_BYTES) { - memcpy(dest, src, width * DataBlock::COLOR_BYTES); - } -} - -void HeightfieldColor::write(Bitstream& out) { - QMutexLocker locker(&_encodedMutex); - if (_encoded.isEmpty()) { - _encoded = encodeHeightfieldColor(0, 0, _width, _contents.size() / (_width * DataBlock::COLOR_BYTES), _contents); - } - out << _encoded.size(); - out.writeAligned(_encoded); -} - -void HeightfieldColor::writeDelta(Bitstream& out, const HeightfieldColorPointer& reference) { - if (!reference || reference->getWidth() != _width || reference->getContents().size() != _contents.size()) { - write(out); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) { - int height = _contents.size() / (_width * DataBlock::COLOR_BYTES); - int minX = _width, minY = height; - int maxX = -1, maxY = -1; - const char* src = _contents.constData(); - const char* ref = reference->getContents().constData(); - for (int y = 0; y < height; y++) { - bool difference = false; - for (int x = 0; x < _width; x++, src += DataBlock::COLOR_BYTES, ref += DataBlock::COLOR_BYTES) { - if (src[0] != ref[0] || src[1] != ref[1] || src[2] != ref[2]) { - minX = qMin(minX, x); - maxX = qMax(maxX, x); - difference = true; - } - } - if (difference) { - minY = qMin(minY, y); - maxY = qMax(maxY, y); - } - } - QByteArray delta; - int deltaWidth = 0, deltaHeight = 0; - if (maxX >= minX) { - deltaWidth = maxX - minX + 1; - deltaHeight = maxY - minY + 1; - delta = QByteArray(deltaWidth * deltaHeight * DataBlock::COLOR_BYTES, 0); - char* dest = delta.data(); - src = _contents.constData() + (minY * _width + minX) * DataBlock::COLOR_BYTES; - for (int y = 0; y < deltaHeight; y++, src += _width * DataBlock::COLOR_BYTES, - dest += deltaWidth * DataBlock::COLOR_BYTES) { - memcpy(dest, src, deltaWidth * DataBlock::COLOR_BYTES); - } - } - reference->setEncodedDelta(encodeHeightfieldColor(minX + 1, minY + 1, deltaWidth, deltaHeight, delta)); - reference->setDeltaData(DataBlockPointer(this)); - } - out << reference->getEncodedDelta().size(); - out.writeAligned(reference->getEncodedDelta()); -} - -void HeightfieldColor::read(Bitstream& in, int bytes) { - int offsetX, offsetY, height; - _contents = decodeHeightfieldColor(_encoded = in.readAligned(bytes), offsetX, offsetY, _width, height); -} - -Bitstream& operator<<(Bitstream& out, const HeightfieldColorPointer& value) { - if (value) { - value->write(out); - } else { - out << 0; - } - return out; -} - -Bitstream& operator>>(Bitstream& in, HeightfieldColorPointer& value) { - int size; - in >> size; - if (size == 0) { - value = HeightfieldColorPointer(); - } else { - value = new HeightfieldColor(in, size); - } - return in; -} - -template<> void Bitstream::writeRawDelta(const HeightfieldColorPointer& value, const HeightfieldColorPointer& reference) { - if (value) { - value->writeDelta(*this, reference); - } else { - *this << 0; - } -} - -template<> void Bitstream::readRawDelta(HeightfieldColorPointer& value, const HeightfieldColorPointer& reference) { - int size; - *this >> size; - if (size == 0) { - value = HeightfieldColorPointer(); - } else { - value = new HeightfieldColor(*this, size, reference); - } -} - -HeightfieldColorEditor::HeightfieldColorEditor(QWidget* parent) : - QWidget(parent) { - - QHBoxLayout* layout = new QHBoxLayout(); - setLayout(layout); - - layout->addWidget(_select = new QPushButton("Select")); - connect(_select, &QPushButton::clicked, this, &HeightfieldColorEditor::select); - - layout->addWidget(_clear = new QPushButton("Clear")); - connect(_clear, &QPushButton::clicked, this, &HeightfieldColorEditor::clear); - _clear->setEnabled(false); -} - -void HeightfieldColorEditor::setColor(const HeightfieldColorPointer& color) { - if ((_color = color)) { - _clear->setEnabled(true); - } else { - _clear->setEnabled(false); - } -} - -void HeightfieldColorEditor::select() { - QString result = QFileDialog::getOpenFileName(this, "Select Color Image", - heightfieldDir.get(), - "Images (*.png *.jpg *.bmp)"); - if (result.isNull()) { - return; - } - heightfieldDir.get(QFileInfo(result).path()); - QImage image; - if (!image.load(result)) { - QMessageBox::warning(this, "Invalid Image", "The selected image could not be read."); - return; - } - image = image.convertToFormat(QImage::Format_RGB888); - int width = getHeightfieldSize(image.width()); - int height = getHeightfieldSize(image.height()); - QByteArray contents(width * height * DataBlock::COLOR_BYTES, 0); - char* dest = contents.data(); - for (int i = 0; i < image.height(); i++, dest += width * DataBlock::COLOR_BYTES) { - memcpy(dest, image.constScanLine(i), image.width() * DataBlock::COLOR_BYTES); - } - emit colorChanged(_color = new HeightfieldColor(width, contents)); - _clear->setEnabled(true); -} - -void HeightfieldColorEditor::clear() { - emit colorChanged(_color = HeightfieldColorPointer()); - _clear->setEnabled(false); -} - -static QByteArray encodeHeightfieldMaterial(int offsetX, int offsetY, int width, int height, const QByteArray& contents) { - QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0); - qint32* header = (qint32*)inflated.data(); - *header++ = offsetX; - *header++ = offsetY; - *header++ = width; - *header++ = height; - inflated.append(contents); - return qCompress(inflated); -} - -static QByteArray decodeHeightfieldMaterial(const QByteArray& encoded, int& offsetX, int& offsetY, int& width, int& height) { - QByteArray inflated = qUncompress(encoded); - const qint32* header = (const qint32*)inflated.constData(); - offsetX = *header++; - offsetY = *header++; - width = *header++; - height = *header++; - return inflated.mid(HEIGHTFIELD_DATA_HEADER_SIZE); -} - -HeightfieldMaterial::HeightfieldMaterial(int width, const QByteArray& contents, - const QVector& materials) : - HeightfieldData(width), - _contents(contents), - _materials(materials) { -} - -HeightfieldMaterial::HeightfieldMaterial(Bitstream& in, int bytes) { - read(in, bytes); -} - -HeightfieldMaterial::HeightfieldMaterial(Bitstream& in, int bytes, const HeightfieldMaterialPointer& reference) { - if (!reference) { - read(in, bytes); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - reference->setEncodedDelta(in.readAligned(bytes)); - in.readDelta(_materials, reference->getMaterials()); - reference->setDeltaData(DataBlockPointer(this)); - _width = reference->getWidth(); - _contents = reference->getContents(); - - int offsetX, offsetY, width, height; - QByteArray delta = decodeHeightfieldMaterial(reference->getEncodedDelta(), offsetX, offsetY, width, height); - if (delta.isEmpty()) { - return; - } - if (offsetX == 0) { - _contents = delta; - _width = width; - return; - } - int minX = offsetX - 1; - int minY = offsetY - 1; - const char* src = delta.constData(); - char* dest = _contents.data() + minY * _width + minX; - for (int y = 0; y < height; y++, src += width, dest += _width) { - memcpy(dest, src, width); - } -} - -void HeightfieldMaterial::write(Bitstream& out) { - QMutexLocker locker(&_encodedMutex); - if (_encoded.isEmpty()) { - _encoded = encodeHeightfieldMaterial(0, 0, _width, _contents.size() / _width, _contents); - } - out << _encoded.size(); - out.writeAligned(_encoded); - out << _materials; -} - -void HeightfieldMaterial::writeDelta(Bitstream& out, const HeightfieldMaterialPointer& reference) { - if (!reference) { - write(out); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) { - if (reference->getWidth() != _width || reference->getContents().size() != _contents.size()) { - reference->setEncodedDelta(encodeHeightfieldMaterial(0, 0, _width, _contents.size() / _width, _contents)); - - } else { - int height = _contents.size() / _width; - int minX = _width, minY = height; - int maxX = -1, maxY = -1; - const char* src = _contents.constData(); - const char* ref = reference->getContents().constData(); - for (int y = 0; y < height; y++) { - bool difference = false; - for (int x = 0; x < _width; x++) { - if (*src++ != *ref++) { - minX = qMin(minX, x); - maxX = qMax(maxX, x); - difference = true; - } - } - if (difference) { - minY = qMin(minY, y); - maxY = qMax(maxY, y); - } - } - QByteArray delta; - int deltaWidth = 0, deltaHeight = 0; - if (maxX >= minX) { - deltaWidth = maxX - minX + 1; - deltaHeight = maxY - minY + 1; - delta = QByteArray(deltaWidth * deltaHeight, 0); - char* dest = delta.data(); - src = _contents.constData() + minY * _width + minX; - for (int y = 0; y < deltaHeight; y++, src += _width, dest += deltaWidth) { - memcpy(dest, src, deltaWidth); - } - } - reference->setEncodedDelta(encodeHeightfieldMaterial(minX + 1, minY + 1, deltaWidth, deltaHeight, delta)); - } - reference->setDeltaData(DataBlockPointer(this)); - } - out << reference->getEncodedDelta().size(); - out.writeAligned(reference->getEncodedDelta()); - out.writeDelta(_materials, reference->getMaterials()); -} - -void HeightfieldMaterial::read(Bitstream& in, int bytes) { - int offsetX, offsetY, height; - _contents = decodeHeightfieldMaterial(_encoded = in.readAligned(bytes), offsetX, offsetY, _width, height); - in >> _materials; -} - -Bitstream& operator<<(Bitstream& out, const HeightfieldMaterialPointer& value) { - if (value) { - value->write(out); - } else { - out << 0; - } - return out; -} - -Bitstream& operator>>(Bitstream& in, HeightfieldMaterialPointer& value) { - int size; - in >> size; - if (size == 0) { - value = HeightfieldMaterialPointer(); - } else { - value = new HeightfieldMaterial(in, size); - } - return in; -} - -template<> void Bitstream::writeRawDelta(const HeightfieldMaterialPointer& value, - const HeightfieldMaterialPointer& reference) { - if (value) { - value->writeDelta(*this, reference); - } else { - *this << 0; - } -} - -template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference) { - int size; - *this >> size; - if (size == 0) { - value = HeightfieldMaterialPointer(); - } else { - value = new HeightfieldMaterial(*this, size, reference); - } -} - -MaterialObject::MaterialObject() : - _scaleS(1.0f), - _scaleT(1.0f) { -} - -int getMaterialIndex(const SharedObjectPointer& material, QVector& materials) { - if (!(material && static_cast(material.data())->getDiffuse().isValid())) { - return 0; - } - // first look for a matching existing material, noting the first reusable slot - int firstEmptyIndex = -1; - for (int i = 0; i < materials.size(); i++) { - const SharedObjectPointer& existingMaterial = materials.at(i); - if (existingMaterial) { - if (existingMaterial->equals(material.data())) { - return i + 1; - } - } else if (firstEmptyIndex == -1) { - firstEmptyIndex = i; - } - } - // if nothing found, use the first empty slot or append - if (firstEmptyIndex != -1) { - materials[firstEmptyIndex] = material; - return firstEmptyIndex + 1; - } - if (materials.size() < numeric_limits::max()) { - materials.append(material); - return materials.size(); - } - return -1; -} - -static QHash countIndices(const QByteArray& contents) { - QHash counts; - for (const uchar* src = (const uchar*)contents.constData(), *end = src + contents.size(); src != end; src++) { - if (*src != 0) { - counts[*src]++; - } - } - return counts; -} - -static uchar getMaterialIndex(const SharedObjectPointer& material, QVector& materials, - QByteArray& contents) { - int index = getMaterialIndex(material, materials); - if (index != -1) { - return index; - } - // last resort: find the least-used material and remove it - QHash counts = countIndices(contents); - uchar materialIndex = 0; - int lowestCount = INT_MAX; - for (QHash::const_iterator it = counts.constBegin(); it != counts.constEnd(); it++) { - if (it.value() < lowestCount) { - materialIndex = it.key(); - lowestCount = it.value(); - } - } - contents.replace((char)materialIndex, (char)0); - return materialIndex; -} - -static void clearUnusedMaterials(QVector& materials, const QByteArray& contents) { - QHash counts = countIndices(contents); - for (int i = 0; i < materials.size(); i++) { - if (counts.value(i + 1) == 0) { - materials[i] = SharedObjectPointer(); - } - } - while (!(materials.isEmpty() || materials.last())) { - materials.removeLast(); - } -} - -static QHash countIndices(const QVector& contents) { - QHash counts; - foreach (const StackArray& array, contents) { - if (array.isEmpty()) { - continue; - } - for (const StackArray::Entry* entry = array.getEntryData(), *end = entry + array.getEntryCount(); - entry != end; entry++) { - if (entry->material != 0) { - counts[entry->material]++; - } - } - } - return counts; -} - -static uchar getMaterialIndex(const SharedObjectPointer& material, QVector& materials, - QVector& contents) { - int index = getMaterialIndex(material, materials); - if (index != -1) { - return index; - } - // last resort: find the least-used material and remove it - QHash counts = countIndices(contents); - uchar materialIndex = 0; - int lowestCount = INT_MAX; - for (QHash::const_iterator it = counts.constBegin(); it != counts.constEnd(); it++) { - if (it.value() < lowestCount) { - materialIndex = it.key(); - lowestCount = it.value(); - } - } - for (StackArray* array = contents.data(), *end = array + contents.size(); array != end; array++) { - if (array->isEmpty()) { - continue; - } - for (StackArray::Entry* entry = array->getEntryData(), *end = entry + array->getEntryCount(); - entry != end; entry++) { - if (entry->material == materialIndex) { - entry->material = 0; - } - } - } - return materialIndex; -} - -static void clearUnusedMaterials(QVector& materials, const QVector& contents) { - QHash counts = countIndices(contents); - for (int i = 0; i < materials.size(); i++) { - if (counts.value(i + 1) == 0) { - materials[i] = SharedObjectPointer(); - } - } - while (!(materials.isEmpty() || materials.last())) { - materials.removeLast(); - } -} - -static QByteArray encodeHeightfieldStack(int offsetX, int offsetY, int width, int height, - const QVector& contents) { - QByteArray inflated(HEIGHTFIELD_DATA_HEADER_SIZE, 0); - qint32* header = (qint32*)inflated.data(); - *header++ = offsetX; - *header++ = offsetY; - *header++ = width; - *header++ = height; - foreach (const StackArray& stack, contents) { - quint16 entries = stack.getEntryCount(); - inflated.append((const char*)&entries, sizeof(quint16)); - inflated.append(stack); - } - return qCompress(inflated); -} - -static QVector decodeHeightfieldStack(const QByteArray& encoded, - int& offsetX, int& offsetY, int& width, int& height) { - QByteArray inflated = qUncompress(encoded); - const qint32* header = (const qint32*)inflated.constData(); - offsetX = *header++; - offsetY = *header++; - width = *header++; - height = *header++; - const char* src = inflated.constData() + HEIGHTFIELD_DATA_HEADER_SIZE; - QVector contents(width * height); - for (StackArray* dest = contents.data(), *end = dest + contents.size(); dest != end; dest++) { - int entries = *(const quint16*)src; - src += sizeof(quint16); - if (entries > 0) { - int bytes = StackArray::getSize(entries); - *dest = StackArray(src, bytes); - src += bytes; - } - } - return contents; -} - -StackArray::Entry::Entry() : - color(0), - material(0), - hermiteX(0), - hermiteY(0), - hermiteZ(0) { -} - -bool StackArray::Entry::isZero() const { - return color == 0 && material == 0 && hermiteX == 0 && hermiteY == 0 && hermiteZ == 0; -} - -bool StackArray::Entry::isMergeable(const Entry& other) const { - return color == other.color && material == other.material && hermiteX == 0 && hermiteY == 0 && hermiteZ == 0; -} - -static inline void setHermite(quint32& value, const glm::vec3& normal, float position) { - value = qRgba(normal.x * numeric_limits::max(), normal.y * numeric_limits::max(), - normal.z * numeric_limits::max(), position * numeric_limits::max()); -} - -static inline float getHermite(QRgb value, glm::vec3& normal) { - normal.x = (char)qRed(value) / (float)numeric_limits::max(); - normal.y = (char)qGreen(value) / (float)numeric_limits::max(); - normal.z = (char)qBlue(value) / (float)numeric_limits::max(); - float length = glm::length(normal); - if (length > 0.0f) { - normal /= length; - } - return qAlpha(value) / (float)numeric_limits::max(); -} - -void StackArray::Entry::setHermiteX(const glm::vec3& normal, float position) { - setHermite(hermiteX, normal, position); -} - -float StackArray::Entry::getHermiteX(glm::vec3& normal) const { - return getHermite(hermiteX, normal); -} - -void StackArray::Entry::setHermiteY(const glm::vec3& normal, float position) { - setHermite(hermiteY, normal, position); -} - -float StackArray::Entry::getHermiteY(glm::vec3& normal) const { - return getHermite(hermiteY, normal); -} - -void StackArray::Entry::setHermiteZ(const glm::vec3& normal, float position) { - setHermite(hermiteZ, normal, position); -} - -float StackArray::Entry::getHermiteZ(glm::vec3& normal) const { - return getHermite(hermiteZ, normal); -} - -int StackArray::getEntryAlpha(int y, float heightfieldHeight) const { - int count = getEntryCount(); - if (count != 0) { - int relative = y - getPosition(); - if (relative < count && (relative >= 0 || heightfieldHeight == 0.0f || y < heightfieldHeight)) { - return qAlpha(getEntryData()[qMax(relative, 0)].color); - } - } - return (heightfieldHeight != 0.0f && y <= heightfieldHeight) ? numeric_limits::max() : 0; -} - -StackArray::Entry& StackArray::getEntry(int y, float heightfieldHeight) { - static Entry emptyEntry; - int count = getEntryCount(); - if (count != 0) { - int relative = y - getPosition(); - if (relative < count && (relative >= 0 || heightfieldHeight == 0.0f || y < heightfieldHeight)) { - return getEntryData()[qMax(relative, 0)]; - } - } - return emptyEntry; -} - -const StackArray::Entry& StackArray::getEntry(int y, float heightfieldHeight) const { - static Entry emptyEntry; - int count = getEntryCount(); - if (count != 0) { - int relative = y - getPosition(); - if (relative < count && (relative >= 0 || heightfieldHeight == 0.0f || y < heightfieldHeight)) { - return getEntryData()[qMax(relative, 0)]; - } - } - return emptyEntry; -} - -void StackArray::getExtents(int& minimumY, int& maximumY) const { - int count = getEntryCount(); - if (count > 0) { - int position = getPosition(); - minimumY = qMin(minimumY, position); - maximumY = qMax(maximumY, position + count - 1); - } -} - -bool StackArray::hasSetEntries() const { - int count = getEntryCount(); - if (count > 0) { - for (const Entry* entry = getEntryData(), *end = entry + count; entry != end; entry++) { - if (entry->isSet()) { - return true; - } - } - } - return false; -} - -HeightfieldStack::HeightfieldStack(int width, const QVector& contents, - const QVector& materials) : - HeightfieldData(width), - _contents(contents), - _materials(materials) { -} - -HeightfieldStack::HeightfieldStack(Bitstream& in, int bytes) { - read(in, bytes); -} - -HeightfieldStack::HeightfieldStack(Bitstream& in, int bytes, const HeightfieldStackPointer& reference) { - if (!reference) { - read(in, bytes); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - reference->setEncodedDelta(in.readAligned(bytes)); - in.readDelta(_materials, reference->getMaterials()); - reference->setDeltaData(DataBlockPointer(this)); - _width = reference->getWidth(); - _contents = reference->getContents(); - - int offsetX, offsetY, width, height; - QVector delta = decodeHeightfieldStack(reference->getEncodedDelta(), offsetX, offsetY, width, height); - if (delta.isEmpty()) { - return; - } - if (offsetX == 0) { - _contents = delta; - _width = width; - return; - } - int minX = offsetX - 1; - int minY = offsetY - 1; - const StackArray* src = delta.constData(); - StackArray* dest = _contents.data() + minY * _width + minX; - for (int y = 0; y < height; y++, src += width, dest += _width) { - const StackArray* lineSrc = src; - for (StackArray* lineDest = dest, *end = dest + width; lineDest != end; lineDest++, lineSrc++) { - *lineDest = *lineSrc; - } - } -} - -void HeightfieldStack::write(Bitstream& out) { - QMutexLocker locker(&_encodedMutex); - if (_encoded.isEmpty()) { - _encoded = encodeHeightfieldStack(0, 0, _width, _contents.size() / _width, _contents); - } - out << _encoded.size(); - out.writeAligned(_encoded); - out << _materials; -} - -void HeightfieldStack::writeDelta(Bitstream& out, const HeightfieldStackPointer& reference) { - if (!reference) { - write(out); - return; - } - QMutexLocker locker(&reference->getEncodedDeltaMutex()); - if (reference->getEncodedDelta().isEmpty() || reference->getDeltaData() != this) { - if (reference->getWidth() != _width || reference->getContents().size() != _contents.size()) { - reference->setEncodedDelta(encodeHeightfieldStack(0, 0, _width, _contents.size() / _width, _contents)); - - } else { - int height = _contents.size() / _width; - int minX = _width, minY = height; - int maxX = -1, maxY = -1; - const StackArray* src = _contents.constData(); - const StackArray* ref = reference->getContents().constData(); - for (int y = 0; y < height; y++) { - bool difference = false; - for (int x = 0; x < _width; x++) { - if (*src++ != *ref++) { - minX = qMin(minX, x); - maxX = qMax(maxX, x); - difference = true; - } - } - if (difference) { - minY = qMin(minY, y); - maxY = qMax(maxY, y); - } - } - QVector delta; - int deltaWidth = 0, deltaHeight = 0; - if (maxX >= minX) { - deltaWidth = maxX - minX + 1; - deltaHeight = maxY - minY + 1; - delta = QVector(deltaWidth * deltaHeight); - StackArray* dest = delta.data(); - src = _contents.constData() + minY * _width + minX; - for (int y = 0; y < deltaHeight; y++, src += _width, dest += deltaWidth) { - const StackArray* lineSrc = src; - for (StackArray* lineDest = dest, *end = dest + deltaWidth; lineDest != end; lineDest++, lineSrc++) { - *lineDest = *lineSrc; - } - } - } - reference->setEncodedDelta(encodeHeightfieldStack(minX + 1, minY + 1, deltaWidth, deltaHeight, delta)); - } - reference->setDeltaData(DataBlockPointer(this)); - } - out << reference->getEncodedDelta().size(); - out.writeAligned(reference->getEncodedDelta()); - out.writeDelta(_materials, reference->getMaterials()); -} - -void HeightfieldStack::read(Bitstream& in, int bytes) { - int offsetX, offsetY, height; - _contents = decodeHeightfieldStack(_encoded = in.readAligned(bytes), offsetX, offsetY, _width, height); - in >> _materials; -} - -Bitstream& operator<<(Bitstream& out, const HeightfieldStackPointer& value) { - if (value) { - value->write(out); - } else { - out << 0; - } - return out; -} - -Bitstream& operator>>(Bitstream& in, HeightfieldStackPointer& value) { - int size; - in >> size; - if (size == 0) { - value = HeightfieldStackPointer(); - } else { - value = new HeightfieldStack(in, size); - } - return in; -} - -template<> void Bitstream::writeRawDelta(const HeightfieldStackPointer& value, const HeightfieldStackPointer& reference) { - if (value) { - value->writeDelta(*this, reference); - } else { - *this << 0; - } -} - -template<> void Bitstream::readRawDelta(HeightfieldStackPointer& value, const HeightfieldStackPointer& reference) { - int size; - *this >> size; - if (size == 0) { - value = HeightfieldStackPointer(); - } else { - value = new HeightfieldStack(*this, size, reference); - } -} - -bool HeightfieldStreamState::shouldSubdivide() const { - return base.lod.shouldSubdivide(minimum, size); -} - -bool HeightfieldStreamState::shouldSubdivideReference() const { - return base.referenceLOD.shouldSubdivide(minimum, size); -} - -bool HeightfieldStreamState::becameSubdivided() const { - return base.lod.becameSubdivided(minimum, size, base.referenceLOD); -} - -bool HeightfieldStreamState::becameSubdividedOrCollapsed() const { - return base.lod.becameSubdividedOrCollapsed(minimum, size, base.referenceLOD); -} - -const int X_MAXIMUM_FLAG = 1; -const int Y_MAXIMUM_FLAG = 2; - -static glm::vec2 getNextMinimum(const glm::vec2& minimum, float nextSize, int index) { - return minimum + glm::vec2( - (index & X_MAXIMUM_FLAG) ? nextSize : 0.0f, - (index & Y_MAXIMUM_FLAG) ? nextSize : 0.0f); -} - -void HeightfieldStreamState::setMinimum(const glm::vec2& lastMinimum, int index) { - minimum = getNextMinimum(lastMinimum, size, index); -} - -HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack) : - _height(height), - _color(color), - _material(material), - _stack(stack), - _renderer(NULL) { -} - -HeightfieldNode::HeightfieldNode(const HeightfieldNode& other) : - _height(other.getHeight()), - _color(other.getColor()), - _material(other.getMaterial()), - _stack(other.getStack()), - _renderer(NULL) { - - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i] = other.getChild(i); - } -} - -HeightfieldNode::~HeightfieldNode() { - delete _renderer; -} - -const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION; - -void HeightfieldNode::setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack) { - clearChildren(); - - int heightWidth = height->getWidth(); - if (heightWidth <= HEIGHT_LEAF_SIZE) { - _height = height; - _color = color; - _material = material; - return; - } - int heightHeight = height->getContents().size() / heightWidth; - int innerChildHeightWidth = (heightWidth - HeightfieldHeight::HEIGHT_EXTENSION) / 2; - int innerChildHeightHeight = (heightHeight - HeightfieldHeight::HEIGHT_EXTENSION) / 2; - int childHeightWidth = innerChildHeightWidth + HeightfieldHeight::HEIGHT_EXTENSION; - int childHeightHeight = innerChildHeightHeight + HeightfieldHeight::HEIGHT_EXTENSION; - - for (int i = 0; i < CHILD_COUNT; i++) { - QVector childHeightContents(childHeightWidth * childHeightHeight); - quint16* heightDest = childHeightContents.data(); - bool maximumX = (i & X_MAXIMUM_FLAG), maximumY = (i & Y_MAXIMUM_FLAG); - const quint16* heightSrc = height->getContents().constData() + (maximumY ? innerChildHeightHeight * heightWidth : 0) + - (maximumX ? innerChildHeightWidth : 0); - for (int z = 0; z < childHeightHeight; z++, heightDest += childHeightWidth, heightSrc += heightWidth) { - memcpy(heightDest, heightSrc, childHeightWidth * sizeof(quint16)); - } - - HeightfieldColorPointer childColor; - if (color) { - int colorWidth = color->getWidth(); - int colorHeight = color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - int innerChildColorWidth = (colorWidth - HeightfieldData::SHARED_EDGE) / 2; - int innerChildColorHeight = (colorHeight - HeightfieldData::SHARED_EDGE) / 2; - int childColorWidth = innerChildColorWidth + HeightfieldData::SHARED_EDGE; - int childColorHeight = innerChildColorHeight + HeightfieldData::SHARED_EDGE; - QByteArray childColorContents(childColorWidth * childColorHeight * DataBlock::COLOR_BYTES, 0); - char* dest = childColorContents.data(); - const char* src = color->getContents().constData() + ((maximumY ? innerChildColorHeight * colorWidth : 0) + - (maximumX ? innerChildColorWidth : 0)) * DataBlock::COLOR_BYTES; - for (int z = 0; z < childColorHeight; z++, dest += childColorWidth * DataBlock::COLOR_BYTES, - src += colorWidth * DataBlock::COLOR_BYTES) { - memcpy(dest, src, childColorWidth * DataBlock::COLOR_BYTES); - } - childColor = new HeightfieldColor(childColorWidth, childColorContents); - } - - HeightfieldMaterialPointer childMaterial; - if (material) { - int materialWidth = material->getWidth(); - int materialHeight = material->getContents().size() / materialWidth; - int innerChildMaterialWidth = (materialWidth - HeightfieldData::SHARED_EDGE) / 2; - int innerChildMaterialHeight = (materialHeight - HeightfieldData::SHARED_EDGE) / 2; - int childMaterialWidth = innerChildMaterialWidth + HeightfieldData::SHARED_EDGE; - int childMaterialHeight = innerChildMaterialHeight + HeightfieldData::SHARED_EDGE; - QByteArray childMaterialContents(childMaterialWidth * childMaterialHeight, 0); - QVector childMaterials; - uchar* dest = (uchar*)childMaterialContents.data(); - const uchar* src = (const uchar*)material->getContents().data() + - (maximumY ? innerChildMaterialHeight * materialWidth : 0) + (maximumX ? innerChildMaterialWidth : 0); - QHash materialMap; - for (int z = 0; z < childMaterialHeight; z++, dest += childMaterialWidth, src += materialWidth) { - const uchar* lineSrc = src; - for (uchar* lineDest = dest, *end = dest + childMaterialWidth; lineDest != end; lineDest++, lineSrc++) { - int value = *lineSrc; - if (value != 0) { - int& mapping = materialMap[value]; - if (mapping == 0) { - childMaterials.append(material->getMaterials().at(value - 1)); - mapping = childMaterials.size(); - } - value = mapping; - } - *lineDest = value; - } - } - childMaterial = new HeightfieldMaterial(childMaterialWidth, childMaterialContents, childMaterials); - } - - HeightfieldStackPointer childStack; - if (stack) { - } - - _children[i] = new HeightfieldNode(); - _children[i]->setContents(HeightfieldHeightPointer(new HeightfieldHeight(childHeightWidth, childHeightContents)), - childColor, childMaterial, childStack); - } - - mergeChildren(); -} - -bool HeightfieldNode::isLeaf() const { - for (int i = 0; i < CHILD_COUNT; i++) { - if (_children[i]) { - return false; - } - } - return true; -} - -bool HeightfieldNode::findRayIntersection(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - glm::quat inverseRotation = glm::inverse(rotation); - glm::vec3 inverseScale = 1.0f / scale; - glm::vec3 transformedOrigin = inverseRotation * (origin - translation) * inverseScale; - glm::vec3 transformedDirection = inverseRotation * direction * inverseScale; - float boundsDistance; - if (!Box(glm::vec3(), glm::vec3(1.0f, 1.0f, 1.0f)).findRayIntersection(transformedOrigin, transformedDirection, - boundsDistance)) { - return false; - } - if (!isLeaf()) { - float closestDistance = FLT_MAX; - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - float childDistance; - if (_children[i]->findRayIntersection(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, - nextScale, origin, direction, childDistance)) { - closestDistance = qMin(closestDistance, childDistance); - } - } - if (closestDistance == FLT_MAX) { - return false; - } - distance = closestDistance; - return true; - } - float shortestDistance = FLT_MAX; - float heightfieldDistance; - if (findHeightfieldRayIntersection(transformedOrigin, transformedDirection, boundsDistance, heightfieldDistance)) { - shortestDistance = heightfieldDistance; - } - float rendererDistance; - if (_renderer && _renderer->findRayIntersection(translation, rotation, scale, origin, direction, boundsDistance, - rendererDistance)) { - shortestDistance = qMin(shortestDistance, rendererDistance); - } - if (shortestDistance == FLT_MAX) { - return false; - } - distance = shortestDistance; - return true; -} - -const float HERMITE_GRANULARITY = 1.0f / numeric_limits::max(); - -void HeightfieldNode::getRangeAfterHeightPaint(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float height, float& minimum, float& maximum) const { - if (!_height) { - return; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - int highestHeightX = heightWidth - 1; - int highestHeightZ = heightHeight - 1; - - glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits::max() / scale.y, innerHeightHeight / scale.z); - glm::vec3 center = glm::inverse(rotation) * (position - translation) * inverseScale + glm::vec3(1.0f, 0.0f, 1.0f); - glm::vec3 extents = radius * inverseScale; - - if (center.x + extents.x < 0.0f || center.z + extents.z < 0.0f || - center.x - extents.x > highestHeightX || center.z - extents.z > highestHeightZ) { - return; - } - if (!isLeaf()) { - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - _children[i]->getRangeAfterHeightPaint(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, - nextScale, position, radius, height, minimum, maximum); - } - return; - } - glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - glm::vec3 end = glm::clamp(glm::ceil(center + extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - - const quint16* lineDest = _height->getContents().constData() + (int)start.z * heightWidth + (int)start.x; - float squaredRadius = extents.x * extents.x; - float squaredRadiusReciprocal = 1.0f / squaredRadius; - float multiplierZ = extents.x / extents.z; - float relativeHeight = height * numeric_limits::max() / scale.y; - for (float z = start.z; z <= end.z; z += 1.0f) { - const quint16* dest = lineDest; - for (float x = start.x; x <= end.x; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - float distanceSquared = dx * dx + dz * dz; - if (distanceSquared <= squaredRadius) { - // height falls off towards edges - int value = *dest; - if (value != 0) { - value += relativeHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; - minimum = qMin(minimum, (float)value); - maximum = qMax(maximum, (float)value); - } - } - } - lineDest += heightWidth; - } - - // make sure we increment in multiples of the voxel size - float voxelStep = scale.x / innerHeightWidth; - float heightIncrement = (1.0f - minimum) * scale.y / numeric_limits::max(); - float incrementSteps = heightIncrement / voxelStep; - if (glm::abs(incrementSteps - glm::round(incrementSteps)) > HERMITE_GRANULARITY) { - minimum = 1.0f - voxelStep * glm::ceil(incrementSteps) * numeric_limits::max() / scale.y; - } -} - -HeightfieldNode* HeightfieldNode::paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float height, bool set, bool erase, - float normalizeScale, float normalizeOffset, float granularity) { - if (!_height) { - return this; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - int highestHeightX = heightWidth - 1; - int highestHeightZ = heightHeight - 1; - - glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits::max() / scale.y, innerHeightHeight / scale.z); - glm::vec3 center = glm::inverse(rotation) * (position - translation) * inverseScale + glm::vec3(1.0f, 0.0f, 1.0f); - glm::vec3 extents = radius * inverseScale; - - bool intersects = (center.x + extents.x >= 0.0f && center.z + extents.z >= 0.0f && - center.x - extents.x <= highestHeightX && center.z - extents.z <= highestHeightZ); - if (!intersects && normalizeScale == 1.0f && normalizeOffset == 0.0f) { - return this; - } - if (!isLeaf()) { - HeightfieldNode* newNode = this; - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - HeightfieldNode* newChild = _children[i]->paintHeight(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, - nextScale, position, radius, height, set, erase, normalizeScale, normalizeOffset, granularity); - if (_children[i] != newChild) { - if (newNode == this) { - newNode = new HeightfieldNode(*this); - } - newNode->setChild(i, HeightfieldNodePointer(newChild)); - } - } - if (newNode != this) { - newNode->mergeChildren(true, false); - } - return newNode; - } - QVector newHeightContents = _height->getContents(); - - int stackWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; - QVector newStackContents; - QVector newStackMaterials; - if (_stack) { - stackWidth = _stack->getWidth(); - newStackContents = _stack->getContents(); - newStackMaterials = _stack->getMaterials(); - } - int innerStackWidth = stackWidth - HeightfieldData::SHARED_EDGE; - - // renormalize if necessary - maybeRenormalize(scale, normalizeScale, normalizeOffset, innerStackWidth, newHeightContents, newStackContents); - if (!intersects) { - return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)), - _color, _material, HeightfieldStackPointer(newStackContents.isEmpty() ? NULL : - new HeightfieldStack(stackWidth, newStackContents, newStackMaterials))); - } - - // if the granularity is insufficient, we must subdivide - if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) { - HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents)); - return newNode->paintHeight(translation, rotation, scale, position, radius, height, set, - erase, 1.0f, 0.0f, granularity); - } - - // now apply the actual change - glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - glm::vec3 end = glm::clamp(glm::ceil(center + extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - - quint16* lineDest = newHeightContents.data() + (int)start.z * heightWidth + (int)start.x; - float squaredRadius = extents.x * extents.x; - float squaredRadiusReciprocal = 1.0f / squaredRadius; - float multiplierZ = extents.x / extents.z; - float relativeHeight = height * numeric_limits::max() / scale.y; - quint16 heightValue = erase ? 0 : relativeHeight; - for (float z = start.z; z <= end.z; z += 1.0f) { - quint16* dest = lineDest; - for (float x = start.x; x <= end.x; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - float distanceSquared = dx * dx + dz * dz; - if (distanceSquared <= squaredRadius) { - if (erase || set) { - *dest = heightValue; - - } else { - // height falls off towards edges - int value = *dest; - if (value != 0) { - *dest = value + relativeHeight * (squaredRadius - distanceSquared) * squaredRadiusReciprocal; - } - } - } - } - lineDest += heightWidth; - } - - return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)), - _color, _material, HeightfieldStackPointer(newStackContents.isEmpty() ? NULL : - new HeightfieldStack(stackWidth, newStackContents, newStackMaterials))); -} - -HeightfieldNode* HeightfieldNode::fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float granularity) { - if (!_height) { - return this; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - int highestHeightX = heightWidth - 1; - int highestHeightZ = heightHeight - 1; - - glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits::max() / scale.y, innerHeightHeight / scale.z); - glm::vec3 center = glm::inverse(rotation) * (position - translation) * inverseScale + glm::vec3(1.0f, 0.0f, 1.0f); - glm::vec3 extents = radius * inverseScale; - - if (center.x + extents.x < 0.0f || center.z + extents.z < 0.0f || center.x - extents.x > highestHeightX || - center.z - extents.z > highestHeightZ) { - return this; - } - if (!isLeaf()) { - HeightfieldNode* newNode = this; - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - HeightfieldNode* newChild = _children[i]->fillHeight(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, - nextScale, position, radius, granularity); - if (_children[i] != newChild) { - if (newNode == this) { - newNode = new HeightfieldNode(*this); - } - newNode->setChild(i, HeightfieldNodePointer(newChild)); - } - } - if (newNode != this) { - newNode->mergeChildren(true, false); - } - return newNode; - } - if (!_stack) { - return this; - } - - // if the granularity is insufficient, we must subdivide - QVector newHeightContents = _height->getContents(); - QVector newStackContents = _stack->getContents(); - if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) { - HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents)); - return newNode->fillHeight(translation, rotation, scale, position, radius, granularity); - } - - int stackWidth = _stack->getWidth(); - int stackHeight = newStackContents.size() / stackWidth; - QVector newStackMaterials = _stack->getMaterials(); - - int colorWidth, colorHeight; - QByteArray newColorContents; - if (_color) { - colorWidth = _color->getWidth(); - colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - newColorContents = _color->getContents(); - - } else { - colorWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; - colorHeight = innerHeightHeight + HeightfieldData::SHARED_EDGE; - newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); - } - int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; - int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; - - int materialWidth, materialHeight; - QByteArray newMaterialContents; - QVector newMaterialMaterials; - if (_material) { - materialWidth = _material->getWidth(); - materialHeight = _material->getContents().size() / materialWidth; - newMaterialContents = _material->getContents(); - newMaterialMaterials = _material->getMaterials(); - - } else { - materialWidth = colorWidth; - materialHeight = colorHeight; - newMaterialContents = QByteArray(materialWidth * materialHeight, 0); - } - int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; - int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; - - glm::vec3 start = glm::clamp(glm::floor(center - extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - glm::vec3 end = glm::clamp(glm::ceil(center + extents), glm::vec3(), - glm::vec3((float)highestHeightX, 0.0f, (float)highestHeightZ)); - float voxelStep = scale.x / innerHeightWidth; - float voxelScale = scale.y / (numeric_limits::max() * voxelStep); - - quint16* lineDest = newHeightContents.data() + (int)start.z * heightWidth + (int)start.x; - float squaredRadius = extents.x * extents.x; - float multiplierZ = extents.x / extents.z; - float colorStepX = (float)innerColorWidth / innerHeightWidth; - float colorStepZ = (float)innerColorHeight / innerHeightHeight; - float materialStepX = (float)innerMaterialWidth / innerHeightWidth; - float materialStepZ = (float)innerMaterialHeight / innerHeightHeight; - QHash materialMap; - for (float z = start.z; z <= end.z; z += 1.0f) { - quint16* dest = lineDest; - for (float x = start.x; x <= end.x; x += 1.0f, dest++) { - float dx = x - center.x, dz = (z - center.z) * multiplierZ; - float distanceSquared = dx * dx + dz * dz; - if (distanceSquared <= squaredRadius && x >= 1.0f && z >= 1.0f && x <= stackWidth && z <= stackHeight) { - int stackX = (int)x - 1, stackZ = (int)z - 1; - StackArray* stackDest = newStackContents.data() + stackZ * stackWidth + stackX; - if (stackDest->isEmpty()) { - continue; - } - int y = stackDest->getPosition() + stackDest->getEntryCount() - 1; - for (const StackArray::Entry* entry = stackDest->getEntryData() + stackDest->getEntryCount() - 1; - entry >= stackDest->getEntryData(); entry--, y--) { - if (!entry->isSet()) { - continue; - } - glm::vec3 normal; - int newHeight = qMax((int)((y + entry->getHermiteY(normal)) / voxelScale), 1); - if (newHeight < *dest) { - break; - } - *dest = newHeight; - for (int colorZ = stackZ * colorStepZ; (int)(colorZ / colorStepZ) == stackZ; colorZ++) { - for (int colorX = stackX * colorStepX; (int)(colorX / colorStepX) == stackX; colorX++) { - uchar* colorDest = (uchar*)newColorContents.data() + - (colorZ * colorWidth + colorX) * DataBlock::COLOR_BYTES; - colorDest[0] = qRed(entry->color); - colorDest[1] = qGreen(entry->color); - colorDest[2] = qBlue(entry->color); - } - } - for (int materialZ = stackZ * materialStepZ; (int)(materialZ / materialStepZ) == stackZ; materialZ++) { - for (int materialX = stackX * materialStepX; (int)(materialX / materialStepX) == stackX; - materialX++) { - int material = entry->material; - if (material != 0) { - int& mapping = materialMap[material]; - if (mapping == 0) { - mapping = getMaterialIndex(newStackMaterials.at(material - 1), - newMaterialMaterials, newMaterialContents); - } - material = mapping; - } - newMaterialContents[materialZ * materialWidth + materialX] = material; - } - } - break; - } - stackDest->clear(); - } - } - lineDest += heightWidth; - } - clearUnusedMaterials(newMaterialMaterials, newMaterialContents); - clearUnusedMaterials(newStackMaterials, newStackContents); - - return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)), - HeightfieldColorPointer(new HeightfieldColor(colorWidth, newColorContents)), - HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, newMaterialContents, newMaterialMaterials)), - HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials))); -} - -void HeightfieldNode::getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const Box& editBounds, float& minimum, float& maximum) const { - if (!_height) { - return; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - glm::mat4 baseInverseTransform = glm::mat4_cast(glm::inverse(rotation)) * glm::translate(-translation); - glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits::max() / scale.y, innerHeightHeight / scale.z); - glm::mat4 inverseTransform = glm::translate(glm::vec3(1.0f, 0.0f, 1.0f)) * glm::scale(inverseScale) * baseInverseTransform; - Box transformedBounds = inverseTransform * editBounds; - if (transformedBounds.maximum.x < 0.0f || transformedBounds.maximum.z < 0.0f || - transformedBounds.minimum.x > heightWidth - 1 || transformedBounds.minimum.z > heightHeight - 1) { - return; - } - if (!isLeaf()) { - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - _children[i]->getRangeAfterEdit(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, - nextScale, editBounds, minimum, maximum); - } - return; - } - glm::vec3 start = glm::floor(transformedBounds.minimum); - glm::vec3 end = glm::ceil(transformedBounds.maximum); - - minimum = qMin(minimum, start.y); - maximum = qMax(maximum, end.y); - - // make sure we increment in multiples of the voxel size - float voxelStep = scale.x / innerHeightWidth; - float heightIncrement = (1.0f - minimum) * scale.y / numeric_limits::max(); - float incrementSteps = heightIncrement / voxelStep; - if (glm::abs(incrementSteps - glm::round(incrementSteps)) > HERMITE_GRANULARITY) { - minimum = 1.0f - voxelStep * glm::ceil(incrementSteps) * numeric_limits::max() / scale.y; - } -} - -HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize, - float normalizeScale, float normalizeOffset, float granularity) { - if (!_height) { - return this; - } - int heightWidth = _height->getWidth(); - int heightHeight = _height->getContents().size() / heightWidth; - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - glm::vec3 expansion(1.0f / innerHeightWidth, 0.0f, 1.0f / innerHeightHeight); - Box bounds = glm::translate(translation) * glm::mat4_cast(rotation) * Box(-expansion, scale + expansion); - bool intersects = bounds.intersects(spanner->getBounds()); - if (!intersects && normalizeScale == 1.0f && normalizeOffset == 0.0f) { - return this; - } - if (!isLeaf()) { - HeightfieldNode* newNode = this; - for (int i = 0; i < CHILD_COUNT; i++) { - glm::vec3 nextScale = scale * glm::vec3(0.5f, 1.0f, 0.5f); - HeightfieldNode* newChild = _children[i]->setMaterial(translation + - rotation * glm::vec3(i & X_MAXIMUM_FLAG ? nextScale.x : 0.0f, 0.0f, - i & Y_MAXIMUM_FLAG ? nextScale.z : 0.0f), rotation, nextScale, spanner, - material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity); - if (_children[i] != newChild) { - if (newNode == this) { - newNode = new HeightfieldNode(*this); - } - newNode->setChild(i, HeightfieldNodePointer(newChild)); - } - } - if (newNode != this) { - newNode->mergeChildren(); - } - return newNode; - } - int highestHeightX = heightWidth - 1; - int highestHeightZ = heightHeight - 1; - QVector newHeightContents = _height->getContents(); - - int stackWidth, stackHeight; - QVector newStackContents; - QVector newStackMaterials; - if (_stack) { - stackWidth = _stack->getWidth(); - stackHeight = _stack->getContents().size() / stackWidth; - newStackContents = _stack->getContents(); - newStackMaterials = _stack->getMaterials(); - - } else { - stackWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; - stackHeight = innerHeightHeight + HeightfieldData::SHARED_EDGE; - newStackContents = QVector(stackWidth * stackHeight); - } - int innerStackWidth = stackWidth - HeightfieldData::SHARED_EDGE; - int innerStackHeight = stackHeight - HeightfieldData::SHARED_EDGE; - - // renormalize if necessary - maybeRenormalize(scale, normalizeScale, normalizeOffset, innerStackWidth, newHeightContents, newStackContents); - if (!intersects) { - return new HeightfieldNode(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, newHeightContents)), - _color, _material, HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials))); - } - - // if the granularity is insufficient, we must subdivide - if (scale.x / innerHeightWidth > granularity || scale.z / innerHeightHeight > granularity) { - HeightfieldNodePointer newNode(subdivide(newHeightContents, newStackContents)); - return newNode->setMaterial(translation, rotation, scale, spanner, material, color, - paint, voxelize, 1.0f, 0.0f, granularity); - } - - QVector oldHeightContents = newHeightContents; - QVector oldStackContents = newStackContents; - - int colorWidth, colorHeight; - QByteArray newColorContents; - if (_color) { - colorWidth = _color->getWidth(); - colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - newColorContents = _color->getContents(); - - } else { - colorWidth = innerHeightWidth + HeightfieldData::SHARED_EDGE; - colorHeight = innerHeightHeight + HeightfieldData::SHARED_EDGE; - newColorContents = QByteArray(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); - } - int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; - int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; - - int materialWidth, materialHeight; - QByteArray newMaterialContents; - QVector newMaterialMaterials; - if (_material) { - materialWidth = _material->getWidth(); - materialHeight = _material->getContents().size() / materialWidth; - newMaterialContents = _material->getContents(); - newMaterialMaterials = _material->getMaterials(); - - } else { - materialWidth = colorWidth; - materialHeight = colorHeight; - newMaterialContents = QByteArray(materialWidth * materialHeight, 0); - } - int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; - int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; - - glm::mat4 baseInverseTransform = glm::mat4_cast(glm::inverse(rotation)) * glm::translate(-translation); - glm::vec3 inverseScale(innerHeightWidth / scale.x, numeric_limits::max() / scale.y, innerHeightHeight / scale.z); - glm::mat4 inverseTransform = glm::translate(glm::vec3(1.0f, 0.0f, 1.0f)) * glm::scale(inverseScale) * baseInverseTransform; - Box transformedBounds = inverseTransform * spanner->getBounds(); - glm::mat4 transform = glm::inverse(inverseTransform); - - glm::vec3 start = glm::ceil(transformedBounds.maximum); - glm::vec3 end = glm::floor(transformedBounds.minimum); - - float stepX = 1.0f, stepZ = 1.0f; - if (paint) { - stepX = (float)innerHeightWidth / qMax(innerHeightWidth, qMax(innerColorWidth, innerMaterialWidth)); - stepZ = (float)innerHeightHeight / qMax(innerHeightHeight, qMax(innerColorHeight, innerMaterialHeight)); - - } else { - start.x += 1.0f; - start.z += 1.0f; - end.x -= 1.0f; - end.z -= 1.0f; - } - - float startX = glm::clamp(start.x, 0.0f, (float)highestHeightX), endX = glm::clamp(end.x, 0.0f, (float)highestHeightX); - float startZ = glm::clamp(start.z, 0.0f, (float)highestHeightZ), endZ = glm::clamp(end.z, 0.0f, (float)highestHeightZ); - float voxelStep = scale.x / innerHeightWidth; - float voxelScale = scale.y / (numeric_limits::max() * voxelStep); - int newTop = start.y * voxelScale; - int newBottom = end.y * voxelScale; - glm::vec3 worldStart = glm::vec3(transform * glm::vec4(startX, paint ? 0.0f : newTop / voxelScale, startZ, 1.0f)); - glm::vec3 worldStepX = glm::vec3(transform * glm::vec4(stepX, 0.0f, 0.0f, 0.0f)); - glm::vec3 worldStepY = glm::vec3(transform * glm::vec4(0.0f, 1.0f / voxelScale, 0.0f, 0.0f)); - glm::vec3 worldStepZ = glm::vec3(transform * glm::vec4(0.0f, 0.0f, stepZ, 0.0f)); - QRgb rgba = color.rgba(); - bool erase = (color.alpha() == 0); - uchar materialMaterialIndex = getMaterialIndex(material, newMaterialMaterials, newMaterialContents); - uchar stackMaterialIndex = getMaterialIndex(material, newStackMaterials, newStackContents); - bool hasOwnColors = spanner->hasOwnColors(); - bool hasOwnMaterials = spanner->hasOwnMaterials(); - QHash materialMappings; - for (float z = startZ; z >= endZ; z -= stepZ, worldStart -= worldStepZ) { - quint16* heightDest = newHeightContents.data() + (int)z * heightWidth; - glm::vec3 worldPos = worldStart; - for (float x = startX; x >= endX; x -= stepX, worldPos -= worldStepX) { - quint16* heightLineDest = heightDest + (int)x; - float distance; - glm::vec3 normal; - - float colorX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerColorWidth / innerHeightWidth; - float colorZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerColorHeight / innerHeightHeight; - uchar* colorDest = (colorX >= 0.0f && colorX <= innerColorWidth && colorZ >= 0.0f && colorZ <= innerColorHeight) ? - ((uchar*)newColorContents.data() + ((int)colorZ * colorWidth + (int)colorX) * DataBlock::COLOR_BYTES) : NULL; - - float materialX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerMaterialWidth / innerHeightWidth; - float materialZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerMaterialHeight / innerHeightHeight; - char* materialDest = (materialX >= 0.0f && materialX <= innerMaterialWidth && materialZ >= 0.0f && - materialZ <= innerMaterialHeight) ? (newMaterialContents.data() + - (int)materialZ * materialWidth + (int)materialX) : NULL; - - if (paint && *heightLineDest != 0 && spanner->contains(worldPos + worldStepY * (*heightLineDest * voxelScale))) { - if (colorDest) { - colorDest[0] = qRed(rgba); - colorDest[1] = qGreen(rgba); - colorDest[2] = qBlue(rgba); - } - if (materialDest) { - *materialDest = materialMaterialIndex; - } - } - - float stackX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerStackWidth / innerHeightWidth; - float stackZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerStackHeight / innerHeightHeight; - - if (stackX >= 0.0f && stackX <= innerStackWidth && stackZ >= 0.0f && stackZ <= innerStackHeight) { - StackArray* stackDest = newStackContents.data() + (int)stackZ * stackWidth + (int)stackX; - if (paint) { - if (stackDest->isEmpty() || glm::fract(x) != 0.0f || glm::fract(z) != 0.0f) { - continue; - } - glm::vec3 pos = worldPos + worldStepY * (float)stackDest->getPosition(); - for (StackArray::Entry* entryDest = stackDest->getEntryData(), *end = entryDest + - stackDest->getEntryCount(); entryDest != end; entryDest++, pos += worldStepY) { - if (entryDest->isSet() && spanner->contains(pos)) { - entryDest->color = rgba; - entryDest->material = stackMaterialIndex; - } - } - continue; - } - int prepend = 0, append = 0; - if (!stackDest->isEmpty()) { - int oldBottom = stackDest->getPosition(); - int oldTop = oldBottom + stackDest->getEntryCount() - 1; - prepend = qMax(0, oldBottom - newBottom); - append = qMax(0, newTop - oldTop); - if (prepend != 0 || append != 0) { - StackArray newStack(prepend + stackDest->getEntryCount() + append); - memcpy(newStack.getEntryData() + prepend, stackDest->getEntryData(), - stackDest->getEntryCount() * sizeof(StackArray::Entry)); - for (StackArray::Entry* entryDest = newStack.getEntryData(), *end = entryDest + prepend; - entryDest != end; entryDest++) { - entryDest->color = end->color; - entryDest->material = end->material; - } - *stackDest = newStack; - stackDest->setPosition(qMin(oldBottom, newBottom)); - } - } else { - *stackDest = StackArray(newTop - newBottom + 1); - stackDest->setPosition(newBottom); - prepend = stackDest->getEntryCount(); - } - const quint16* oldHeightLineDest = oldHeightContents.constData() + (int)z * heightWidth + (int)x; - if (*heightLineDest != 0) { - float voxelHeight = *heightLineDest * voxelScale; - float left = oldHeightLineDest[-1] * voxelScale; - float right = oldHeightLineDest[1] * voxelScale; - float down = oldHeightLineDest[-heightWidth] * voxelScale; - float up = oldHeightLineDest[heightWidth] * voxelScale; - float deltaX = (left == 0.0f || right == 0.0f) ? 0.0f : (left - right); - float deltaZ = (up == 0.0f || down == 0.0f) ? 0.0f : (down - up); - for (int i = 0, total = prepend + append; i < total; i++) { - int offset = (i < prepend) ? i : stackDest->getEntryCount() - append + (i - prepend); - int y = stackDest->getPosition() + offset; - StackArray::Entry* entryDest = stackDest->getEntryData() + offset; - if (y > voxelHeight) { - if (y <= right) { - entryDest->setHermiteX(glm::normalize(glm::vec3(voxelHeight - right, 1.0f, deltaZ * 0.5f)), - (right == voxelHeight) ? 0.5f : (y - voxelHeight) / (right - voxelHeight)); - } - if (y <= up) { - entryDest->setHermiteZ(glm::normalize(glm::vec3(deltaX * 0.5f, 1.0f, voxelHeight - up)), - (up == voxelHeight) ? 0.5f : (y - voxelHeight) / (up - voxelHeight)); - } - } else { - if (right != 0.0f && y > right) { - entryDest->setHermiteX(glm::normalize(glm::vec3(voxelHeight - right, 1.0f, deltaZ * 0.5f)), - (right == voxelHeight) ? 0.5f : (y - voxelHeight) / (right - voxelHeight)); - } - if (up != 0.0f && y > up) { - entryDest->setHermiteZ(glm::normalize(glm::vec3(deltaX * 0.5f, 1.0f, voxelHeight - up)), - (up == voxelHeight) ? 0.5f : (y - voxelHeight) / (up - voxelHeight)); - } - if (colorDest) { - entryDest->color = qRgb(colorDest[0], colorDest[1], colorDest[2]); - } - if (materialDest) { - int index = *materialDest; - if (index != 0) { - int& mapping = materialMappings[index]; - if (mapping == 0) { - mapping = getMaterialIndex(newMaterialMaterials.at(index - 1), - newStackMaterials, newStackContents); - } - index = mapping; - } - entryDest->material = index; - } - if (y + 1 > voxelHeight) { - *heightLineDest = 0; - entryDest->setHermiteY(glm::normalize(glm::vec3(deltaX, 2.0f, deltaZ)), voxelHeight - y); - } - } - } - } - StackArray::Entry* entryDest = stackDest->getEntryData() + (newTop - stackDest->getPosition()); - glm::vec3 pos = worldPos; - float voxelHeight = *heightLineDest * voxelScale; - float nextVoxelHeightX = heightLineDest[1] * voxelScale; - float nextVoxelHeightZ = heightLineDest[heightWidth] * voxelScale; - float oldVoxelHeight = *oldHeightLineDest * voxelScale; - float oldNextVoxelHeightX = oldHeightLineDest[1] * voxelScale; - float oldNextVoxelHeightZ = oldHeightLineDest[heightWidth] * voxelScale; - // skip the actual set if voxelizing - for (int y = voxelize ? newBottom - 1 : newTop; y >= newBottom; y--, entryDest--, pos -= worldStepY) { - int oldCurrentAlpha = stackDest->getEntryAlpha(y, oldVoxelHeight); - if (spanner->contains(pos)) { - if (hasOwnColors && !erase) { - entryDest->color = spanner->getColorAt(pos); - - } else { - entryDest->color = rgba; - } - if (hasOwnMaterials && !erase) { - int index = spanner->getMaterialAt(pos); - if (index != 0) { - int& mapping = materialMappings[index]; - if (mapping == 0) { - mapping = getMaterialIndex(spanner->getMaterials().at(index - 1), - newStackMaterials, newStackContents); - } - index = mapping; - } - entryDest->material = index; - - } else { - entryDest->material = stackMaterialIndex; - } - } - - int currentAlpha = stackDest->getEntryAlpha(y, voxelHeight); - bool flipped = (color.alpha() == currentAlpha); - int nextStackX = (int)stackX + 1; - if (nextStackX <= innerStackWidth) { - int nextAlphaX = newStackContents.at((int)stackZ * stackWidth + nextStackX).getEntryAlpha( - y, nextVoxelHeightX); - if (nextAlphaX == currentAlpha) { - entryDest->hermiteX = 0; - - } else { - float oldDistance = flipped ? 0.0f : 1.0f; - if (currentAlpha == oldCurrentAlpha && nextAlphaX == oldStackContents.at((int)stackZ * stackWidth + - nextStackX).getEntryAlpha(y, oldNextVoxelHeightX) && entryDest->hermiteX != 0) { - oldDistance = qAlpha(entryDest->hermiteX) / (float)numeric_limits::max(); - } - if (flipped ? (spanner->intersects(pos + worldStepX, pos, distance, normal) && - (distance = 1.0f - distance) >= oldDistance) : - (spanner->intersects(pos, pos + worldStepX, distance, normal) && - distance <= oldDistance)) { - entryDest->setHermiteX(erase ? -normal : normal, distance); - } - } - } - int nextAlphaY = stackDest->getEntryAlpha(y + 1, voxelHeight); - if (nextAlphaY == currentAlpha) { - entryDest->hermiteY = 0; - - } else { - float oldDistance = flipped ? 0.0f : 1.0f; - if (currentAlpha == oldCurrentAlpha && nextAlphaY == oldStackContents.at((int)stackZ * stackWidth + - (int)stackX).getEntryAlpha(y + 1, oldVoxelHeight) && entryDest->hermiteY != 0) { - oldDistance = qAlpha(entryDest->hermiteY) / (float)numeric_limits::max(); - } - if (flipped ? (spanner->intersects(pos + worldStepY, pos, distance, normal) && - (distance = 1.0f - distance) >= oldDistance) : - (spanner->intersects(pos, pos + worldStepY, distance, normal) && - distance <= oldDistance)) { - entryDest->setHermiteY(erase ? -normal : normal, distance); - } - } - int nextStackZ = (int)stackZ + 1; - if (nextStackZ <= innerStackHeight) { - int nextAlphaZ = newStackContents.at(nextStackZ * stackWidth + (int)stackX).getEntryAlpha( - y, nextVoxelHeightZ); - if (nextAlphaZ == currentAlpha) { - entryDest->hermiteZ = 0; - - } else { - float oldDistance = flipped ? 0.0f : 1.0f; - if (currentAlpha == oldCurrentAlpha && nextAlphaZ == oldStackContents.at(nextStackZ * stackWidth + - (int)stackX).getEntryAlpha(y, oldNextVoxelHeightZ) && entryDest->hermiteZ != 0) { - oldDistance = qAlpha(entryDest->hermiteZ) / (float)numeric_limits::max(); - } - if (flipped ? (spanner->intersects(pos + worldStepZ, pos, distance, normal) && - (distance = 1.0f - distance) >= oldDistance) : - (spanner->intersects(pos, pos + worldStepZ, distance, normal) && - distance <= oldDistance)) { - entryDest->setHermiteZ(erase ? -normal : normal, distance); - } - } - } - } - - // prune zero entries from end, repeated entries from beginning - int endPruneCount = 0; - for (int i = stackDest->getEntryCount() - 1; i >= 0 && stackDest->getEntryData()[i].isZero(); i--) { - endPruneCount++; - } - if (endPruneCount == stackDest->getEntryCount()) { - stackDest->clear(); - - } else { - stackDest->removeEntries(stackDest->getEntryCount() - endPruneCount, endPruneCount); - int beginningPruneCount = 0; - for (int i = 0; i < stackDest->getEntryCount() - 1 && stackDest->getEntryData()[i].isMergeable( - stackDest->getEntryData()[i + 1]); i++) { - beginningPruneCount++; - } - stackDest->removeEntries(0, beginningPruneCount); - stackDest->getPositionRef() += beginningPruneCount; - } - } - } - } - clearUnusedMaterials(newMaterialMaterials, newMaterialContents); - clearUnusedMaterials(newStackMaterials, newStackContents); - - return new HeightfieldNode(paint ? _height : HeightfieldHeightPointer( - new HeightfieldHeight(heightWidth, newHeightContents)), - HeightfieldColorPointer(new HeightfieldColor(colorWidth, newColorContents)), - HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth, newMaterialContents, newMaterialMaterials)), - HeightfieldStackPointer(new HeightfieldStack(stackWidth, newStackContents, newStackMaterials))); -} - -void HeightfieldNode::read(HeightfieldStreamState& state) { - clearChildren(); - - if (!state.shouldSubdivide()) { - state.base.stream >> _height >> _color >> _material >> _stack; - return; - } - bool leaf; - state.base.stream >> leaf; - if (leaf) { - state.base.stream >> _height >> _color >> _material >> _stack; - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new HeightfieldNode(); - _children[i]->read(nextState); - } - mergeChildren(); - } -} - -void HeightfieldNode::write(HeightfieldStreamState& state) const { - if (!state.shouldSubdivide()) { - state.base.stream << _height << _color << _material << _stack; - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - if (leaf) { - state.base.stream << _height << _color << _material << _stack; - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->write(nextState); - } - } -} - -void HeightfieldNode::readDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) { - clearChildren(); - - if (!state.shouldSubdivide()) { - state.base.stream.readDelta(_height, reference->getHeight()); - state.base.stream.readDelta(_color, reference->getColor()); - state.base.stream.readDelta(_material, reference->getMaterial()); - state.base.stream.readDelta(_stack, reference->getStack()); - return; - } - bool leaf; - state.base.stream >> leaf; - if (leaf) { - state.base.stream.readDelta(_height, reference->getHeight()); - state.base.stream.readDelta(_color, reference->getColor()); - state.base.stream.readDelta(_material, reference->getMaterial()); - state.base.stream.readDelta(_stack, reference->getStack()); - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - if (reference->isLeaf() || !state.shouldSubdivideReference()) { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new HeightfieldNode(); - _children[i]->read(nextState); - } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - bool changed; - state.base.stream >> changed; - if (changed) { - _children[i] = new HeightfieldNode(); - _children[i]->readDelta(reference->getChild(i), nextState); - } else { - if (nextState.becameSubdividedOrCollapsed()) { - _children[i] = reference->getChild(i)->readSubdivision(nextState); - - } else { - _children[i] = reference->getChild(i); - } - } - } - } - mergeChildren(); - } -} - -void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) const { - if (!state.shouldSubdivide()) { - state.base.stream.writeDelta(_height, reference->getHeight()); - state.base.stream.writeDelta(_color, reference->getColor()); - state.base.stream.writeDelta(_material, reference->getMaterial()); - state.base.stream.writeDelta(_stack, reference->getStack()); - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - if (leaf) { - state.base.stream.writeDelta(_height, reference->getHeight()); - state.base.stream.writeDelta(_color, reference->getColor()); - state.base.stream.writeDelta(_material, reference->getMaterial()); - state.base.stream.writeDelta(_stack, reference->getStack()); - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - if (reference->isLeaf() || !state.shouldSubdivideReference()) { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->write(nextState); - } - } else { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (_children[i] == reference->getChild(i)) { - state.base.stream << false; - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } - } else { - state.base.stream << true; - _children[i]->writeDelta(reference->getChild(i), nextState); - } - } - } - } -} - -HeightfieldNode* HeightfieldNode::readSubdivision(HeightfieldStreamState& state) { - if (state.shouldSubdivide()) { - if (!state.shouldSubdivideReference()) { - bool leaf; - state.base.stream >> leaf; - if (leaf) { - return isLeaf() ? this : new HeightfieldNode(_height, _color, _material, _stack); - - } else { - HeightfieldNode* newNode = new HeightfieldNode(_height, _color, _material, _stack); - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - newNode->_children[i] = new HeightfieldNode(); - newNode->_children[i]->readSubdivided(nextState, state, this); - } - return newNode; - } - } else if (!isLeaf()) { - HeightfieldNode* node = this; - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdividedOrCollapsed()) { - HeightfieldNode* child = _children[i]->readSubdivision(nextState); - if (_children[i] != child) { - if (node == this) { - node = new HeightfieldNode(*this); - } - node->_children[i] = child; - } - } - } - if (node != this) { - node->mergeChildren(); - } - return node; - } - } else if (!isLeaf()) { - return new HeightfieldNode(_height, _color, _material, _stack); - } - return this; -} - -void HeightfieldNode::writeSubdivision(HeightfieldStreamState& state) const { - if (!state.shouldSubdivide()) { - return; - } - bool leaf = isLeaf(); - if (!state.shouldSubdivideReference()) { - state.base.stream << leaf; - if (!leaf) { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSubdivided(nextState, state, this); - } - } - } else if (!leaf) { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (nextState.becameSubdivided()) { - _children[i]->writeSubdivision(nextState); - } - } - } -} - -void HeightfieldNode::readSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, - const HeightfieldNode* ancestor) { - clearChildren(); - - if (!state.shouldSubdivide()) { - // TODO: subdivision encoding - state.base.stream >> _height >> _color >> _material >> _stack; - return; - } - bool leaf; - state.base.stream >> leaf; - if (leaf) { - state.base.stream >> _height >> _color >> _material >> _stack; - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i] = new HeightfieldNode(); - _children[i]->readSubdivided(nextState, ancestorState, ancestor); - } - mergeChildren(); - } -} - -void HeightfieldNode::writeSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, - const HeightfieldNode* ancestor) const { - if (!state.shouldSubdivide()) { - // TODO: subdivision encoding - state.base.stream << _height << _color << _material << _stack; - return; - } - bool leaf = isLeaf(); - state.base.stream << leaf; - if (leaf) { - state.base.stream << _height << _color << _material << _stack; - - } else { - HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSubdivided(nextState, ancestorState, ancestor); - } - } -} - -void HeightfieldNode::clearChildren() { - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i].reset(); - } -} - -void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) { - if (isLeaf()) { - return; - } - int heightWidth = 0; - int heightHeight = 0; - int colorWidth = 0; - int colorHeight = 0; - int materialWidth = 0; - int materialHeight = 0; - int stackWidth = 0; - int stackHeight = 0; - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldHeightPointer childHeight = _children[i]->getHeight(); - if (childHeight) { - int childHeightWidth = childHeight->getWidth(); - int childHeightHeight = childHeight->getContents().size() / childHeightWidth; - heightWidth = qMax(heightWidth, childHeightWidth); - heightHeight = qMax(heightHeight, childHeightHeight); - } - HeightfieldColorPointer childColor = _children[i]->getColor(); - if (childColor) { - int childColorWidth = childColor->getWidth(); - int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES); - colorWidth = qMax(colorWidth, childColorWidth); - colorHeight = qMax(colorHeight, childColorHeight); - } - HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial(); - if (childMaterial) { - int childMaterialWidth = childMaterial->getWidth(); - int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth; - materialWidth = qMax(materialWidth, childMaterialWidth); - materialHeight = qMax(materialHeight, childMaterialHeight); - } - HeightfieldStackPointer childStack = _children[i]->getStack(); - if (childStack) { - int childStackWidth = childStack->getWidth(); - int childStackHeight = childStack->getContents().size() / childStackWidth; - stackWidth = qMax(stackWidth, childStackWidth); - stackHeight = qMax(stackHeight, childStackHeight); - } - } - if (heightWidth > 0 && height) { - QVector heightContents(heightWidth * heightHeight); - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldHeightPointer childHeight = _children[i]->getHeight(); - if (!childHeight) { - continue; - } - int childHeightWidth = childHeight->getWidth(); - int childHeightHeight = childHeight->getContents().size() / childHeightWidth; - if (childHeightWidth != heightWidth || childHeightHeight != heightHeight) { - qWarning() << "Height dimension mismatch [heightWidth=" << heightWidth << ", heightHeight=" << heightHeight << - ", childHeightWidth=" << childHeightWidth << ", childHeightHeight=" << childHeightHeight << "]"; - continue; - } - int innerHeightWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeightHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION; - int innerQuadrantHeightWidth = innerHeightWidth / 2; - int innerQuadrantHeightHeight = innerHeightHeight / 2; - int quadrantHeightWidth = innerQuadrantHeightWidth + HeightfieldHeight::HEIGHT_EXTENSION - 1; - int quadrantHeightHeight = innerQuadrantHeightHeight + HeightfieldHeight::HEIGHT_EXTENSION - 1; - quint16* dest = heightContents.data() + (i & Y_MAXIMUM_FLAG ? (innerQuadrantHeightHeight + 1) * heightWidth : 0) + - (i & X_MAXIMUM_FLAG ? innerQuadrantHeightWidth + 1 : 0); - const quint16* src = childHeight->getContents().constData(); - for (int z = 0; z < quadrantHeightHeight; z++, dest += heightWidth, src += heightWidth * 2) { - const quint16* lineSrc = src; - for (quint16* lineDest = dest, *end = dest + quadrantHeightWidth; lineDest != end; lineDest++, lineSrc += 2) { - *lineDest = *lineSrc; - } - } - } - _height = new HeightfieldHeight(heightWidth, heightContents); - - } else if (height) { - _height.reset(); - } - if (colorWidth > 0 && colorMaterial) { - QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldColorPointer childColor = _children[i]->getColor(); - if (!childColor) { - continue; - } - int childColorWidth = childColor->getWidth(); - int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES); - if (childColorWidth != colorWidth || childColorHeight != colorHeight) { - qWarning() << "Color dimension mismatch [colorWidth=" << colorWidth << ", colorHeight=" << colorHeight << - ", childColorWidth=" << childColorWidth << ", childColorHeight=" << childColorHeight << "]"; - continue; - } - int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE; - int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE; - int innerQuadrantColorWidth = innerColorWidth / 2; - int innerQuadrantColorHeight = innerColorHeight / 2; - int quadrantColorWidth = innerQuadrantColorWidth + HeightfieldData::SHARED_EDGE; - int quadrantColorHeight = innerQuadrantColorHeight + HeightfieldData::SHARED_EDGE; - char* dest = colorContents.data() + ((i & Y_MAXIMUM_FLAG ? innerQuadrantColorHeight * colorWidth : 0) + - (i & X_MAXIMUM_FLAG ? innerQuadrantColorWidth : 0)) * DataBlock::COLOR_BYTES; - const uchar* src = (const uchar*)childColor->getContents().constData(); - for (int z = 0; z < quadrantColorHeight; z++, dest += colorWidth * DataBlock::COLOR_BYTES, - src += colorWidth * DataBlock::COLOR_BYTES * 2) { - const uchar* lineSrc = src; - for (char* lineDest = dest, *end = dest + quadrantColorWidth * DataBlock::COLOR_BYTES; - lineDest != end; lineDest += DataBlock::COLOR_BYTES, lineSrc += DataBlock::COLOR_BYTES * 2) { - lineDest[0] = lineSrc[0]; - lineDest[1] = lineSrc[1]; - lineDest[2] = lineSrc[2]; - } - } - } - _color = new HeightfieldColor(colorWidth, colorContents); - - } else { - _color.reset(); - } - if (materialWidth > 0 && colorMaterial) { - QByteArray materialContents(materialWidth * materialHeight, 0); - QVector materials; - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial(); - if (!childMaterial) { - continue; - } - int childMaterialWidth = childMaterial->getWidth(); - int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth; - if (childMaterialWidth != materialWidth || childMaterialHeight != materialHeight) { - qWarning() << "Material dimension mismatch [materialWidth=" << materialWidth << ", materialHeight=" << - materialHeight << ", childMaterialWidth=" << childMaterialWidth << ", childMaterialHeight=" << - childMaterialHeight << "]"; - continue; - } - int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE; - int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE; - int innerQuadrantMaterialWidth = innerMaterialWidth / 2; - int innerQuadrantMaterialHeight = innerMaterialHeight / 2; - int quadrantMaterialWidth = innerQuadrantMaterialWidth + HeightfieldData::SHARED_EDGE; - int quadrantMaterialHeight = innerQuadrantMaterialHeight + HeightfieldData::SHARED_EDGE; - uchar* dest = (uchar*)materialContents.data() + - (i & Y_MAXIMUM_FLAG ? innerQuadrantMaterialHeight * materialWidth : 0) + - (i & X_MAXIMUM_FLAG ? innerQuadrantMaterialWidth : 0); - const uchar* src = (const uchar*)childMaterial->getContents().constData(); - QHash materialMap; - for (int z = 0; z < quadrantMaterialHeight; z++, dest += materialWidth, src += materialWidth * 2) { - const uchar* lineSrc = src; - for (uchar* lineDest = dest, *end = dest + quadrantMaterialWidth; lineDest != end; lineDest++, lineSrc += 2) { - int value = *lineSrc; - if (value != 0) { - int& mapping = materialMap[value]; - if (mapping == 0) { - mapping = getMaterialIndex(childMaterial->getMaterials().at(value - 1), - materials, materialContents); - } - value = mapping; - } - *lineDest = value; - } - } - } - _material = new HeightfieldMaterial(materialWidth, materialContents, materials); - - } else { - _material.reset(); - } - if (stackWidth > 0) { - QVector stackContents(stackWidth * stackHeight); - QVector stackMaterials; - for (int i = 0; i < CHILD_COUNT; i++) { - HeightfieldStackPointer childStack = _children[i]->getStack(); - if (!childStack) { - continue; - } - int childStackWidth = childStack->getWidth(); - int childStackHeight = childStack->getContents().size() / childStackWidth; - if (childStackWidth != stackWidth || childStackHeight != stackHeight) { - qWarning() << "Stack dimension mismatch [stackWidth=" << stackWidth << ", stackHeight=" << stackHeight << - ", childStackWidth=" << childStackWidth << ", childStackHeight=" << childStackHeight << "]"; - continue; - } - int innerStackWidth = stackWidth - HeightfieldData::SHARED_EDGE; - int innerStackHeight = stackHeight - HeightfieldData::SHARED_EDGE; - int innerQuadrantStackWidth = innerStackWidth / 2; - int innerQuadrantStackHeight = innerStackHeight / 2; - int quadrantStackWidth = innerQuadrantStackWidth + HeightfieldData::SHARED_EDGE; - int quadrantStackHeight = innerQuadrantStackHeight + HeightfieldData::SHARED_EDGE; - StackArray* dest = stackContents.data() + (i & Y_MAXIMUM_FLAG ? innerQuadrantStackHeight * stackWidth : 0) + - (i & X_MAXIMUM_FLAG ? innerQuadrantStackWidth : 0); - const StackArray* src = childStack->getContents().constData(); - QHash materialMap; - for (int z = 0; z < quadrantStackHeight; z++, dest += stackWidth, src += stackWidth * 2) { - const StackArray* lineSrc = src; - StackArray* lineDest = dest; - for (int x = 0; x < quadrantStackWidth; x++, lineDest++, lineSrc += 2) { - if (lineSrc->isEmpty()) { - continue; - } - int minimumY = lineSrc->getPosition(); - int maximumY = lineSrc->getPosition() + lineSrc->getEntryCount() - 1; - int newMinimumY = minimumY / 2; - int newMaximumY = maximumY / 2; - *lineDest = StackArray(newMaximumY - newMinimumY + 1); - lineDest->setPosition(newMinimumY); - int y = newMinimumY; - for (StackArray::Entry* destEntry = lineDest->getEntryData(), *end = destEntry + lineDest->getEntryCount(); - destEntry != end; destEntry++, y++) { - int srcY = y * 2; - const StackArray::Entry& srcEntry = lineSrc->getEntry(srcY); - destEntry->color = srcEntry.color; - destEntry->material = srcEntry.material; - if (destEntry->material != 0) { - int& mapping = materialMap[destEntry->material]; - if (mapping == 0) { - mapping = getMaterialIndex(childStack->getMaterials().at(destEntry->material - 1), - stackMaterials, stackContents); - } - destEntry->material = mapping; - } - int srcAlpha = qAlpha(srcEntry.color); - glm::vec3 normal; - if (srcAlpha != lineSrc->getEntryAlpha(srcY + 2)) { - const StackArray::Entry& nextSrcEntry = lineSrc->getEntry(srcY + 1); - if (qAlpha(nextSrcEntry.color) == srcAlpha) { - float distance = nextSrcEntry.getHermiteY(normal); - destEntry->setHermiteY(normal, distance * 0.5f + 0.5f); - } else { - float distance = srcEntry.getHermiteY(normal); - destEntry->setHermiteY(normal, distance * 0.5f); - } - } - if (x != quadrantStackWidth - 1 && srcAlpha != lineSrc[2].getEntryAlpha(srcY)) { - const StackArray::Entry& nextSrcEntry = lineSrc[1].getEntry(srcY); - if (qAlpha(nextSrcEntry.color) == srcAlpha) { - float distance = nextSrcEntry.getHermiteX(normal); - destEntry->setHermiteX(normal, distance * 0.5f + 0.5f); - } else { - float distance = srcEntry.getHermiteX(normal); - destEntry->setHermiteX(normal, distance * 0.5f); - } - } - if (z != quadrantStackHeight - 1 && srcAlpha != lineSrc[2 * stackWidth].getEntryAlpha(srcY)) { - const StackArray::Entry& nextSrcEntry = lineSrc[stackWidth].getEntry(srcY); - if (qAlpha(nextSrcEntry.color) == srcAlpha) { - float distance = nextSrcEntry.getHermiteZ(normal); - destEntry->setHermiteZ(normal, distance * 0.5f + 0.5f); - } else { - float distance = srcEntry.getHermiteZ(normal); - destEntry->setHermiteZ(normal, distance * 0.5f); - } - } - } - } - } - } - _stack = new HeightfieldStack(stackWidth, stackContents, stackMaterials); - - } else { - _stack.reset(); - } -} - -QRgb HeightfieldNode::getColorAt(const glm::vec3& location) const { - if (location.x < 0.0f || location.z < 0.0f || location.x > 1.0f || location.z > 1.0f) { - return 0; - } - int width = _color->getWidth(); - const QByteArray& contents = _color->getContents(); - const uchar* src = (const uchar*)contents.constData(); - int height = contents.size() / (width * DataBlock::COLOR_BYTES); - int innerWidth = width - HeightfieldData::SHARED_EDGE; - int innerHeight = height - HeightfieldData::SHARED_EDGE; - - glm::vec3 relative = location * glm::vec3((float)innerWidth, 1.0f, (float)innerHeight); - glm::vec3 floors = glm::floor(relative); - glm::vec3 ceils = glm::ceil(relative); - glm::vec3 fracts = glm::fract(relative); - int floorX = (int)floors.x; - int floorZ = (int)floors.z; - int ceilX = (int)ceils.x; - int ceilZ = (int)ceils.z; - const uchar* upperLeft = src + (floorZ * width + floorX) * DataBlock::COLOR_BYTES; - const uchar* lowerRight = src + (ceilZ * width + ceilX) * DataBlock::COLOR_BYTES; - glm::vec3 interpolatedColor = glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), - glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z); - - // the final vertex (and thus which triangle we check) depends on which half we're on - if (fracts.x >= fracts.z) { - const uchar* upperRight = src + (floorZ * width + ceilX) * DataBlock::COLOR_BYTES; - interpolatedColor = glm::mix(interpolatedColor, glm::mix(glm::vec3(upperRight[0], upperRight[1], upperRight[2]), - glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z), (fracts.x - fracts.z) / (1.0f - fracts.z)); - - } else { - const uchar* lowerLeft = src + (ceilZ * width + floorX) * DataBlock::COLOR_BYTES; - interpolatedColor = glm::mix(glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), - glm::vec3(lowerLeft[0], lowerLeft[1], lowerLeft[2]), fracts.z), interpolatedColor, fracts.x / fracts.z); - } - return qRgb(interpolatedColor.r, interpolatedColor.g, interpolatedColor.b); -} - -int HeightfieldNode::getMaterialAt(const glm::vec3& location) const { - if (location.x < 0.0f || location.z < 0.0f || location.x > 1.0f || location.z > 1.0f) { - return -1; - } - int width = _material->getWidth(); - const QByteArray& contents = _material->getContents(); - const uchar* src = (const uchar*)contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldData::SHARED_EDGE; - int innerHeight = height - HeightfieldData::SHARED_EDGE; - - glm::vec3 relative = location * glm::vec3((float)innerWidth, 1.0f, (float)innerHeight); - return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)]; -} - -void HeightfieldNode::maybeRenormalize(const glm::vec3& scale, float normalizeScale, float normalizeOffset, - int innerStackWidth, QVector& heightContents, QVector& stackContents) { - if (normalizeScale == 1.0f && normalizeOffset == 0.0f) { - return; - } - for (quint16* dest = heightContents.data(), *end = dest + heightContents.size(); dest != end; dest++) { - int value = *dest; - if (value != 0) { - *dest = (value + normalizeOffset) * normalizeScale; - } - } - if (stackContents.isEmpty()) { - return; - } - int stackOffset = glm::round(scale.y * normalizeOffset * normalizeScale * innerStackWidth / - (numeric_limits::max() * scale.x)); - for (StackArray* dest = stackContents.data(), *end = dest + stackContents.size(); dest != end; dest++) { - if (!dest->isEmpty()) { - dest->getPositionRef() += stackOffset; - } - } -} - -bool HeightfieldNode::findHeightfieldRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float boundsDistance, float& distance) const { - if (!_height) { - return false; - } - int width = _height->getWidth(); - const QVector& contents = _height->getContents(); - const quint16* src = contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - int highestX = innerWidth + HeightfieldHeight::HEIGHT_BORDER; - int highestZ = innerHeight + HeightfieldHeight::HEIGHT_BORDER; - - glm::vec3 heightScale((float)innerWidth, (float)numeric_limits::max(), (float)innerHeight); - glm::vec3 dir = direction * heightScale; - glm::vec3 entry = origin * heightScale + dir * boundsDistance; - - entry.x += HeightfieldHeight::HEIGHT_BORDER; - entry.z += HeightfieldHeight::HEIGHT_BORDER; - glm::vec3 floors = glm::floor(entry); - glm::vec3 ceils = glm::ceil(entry); - if (floors.x == ceils.x) { - if (dir.x > 0.0f) { - ceils.x += 1.0f; - } else { - floors.x -= 1.0f; - } - } - if (floors.z == ceils.z) { - if (dir.z > 0.0f) { - ceils.z += 1.0f; - } else { - floors.z -= 1.0f; - } - } - - bool withinBounds = true; - float accumulatedDistance = 0.0f; - while (withinBounds) { - // find the heights at the corners of the current cell - int floorX = qMin(qMax((int)floors.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int floorZ = qMin(qMax((int)floors.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - int ceilX = qMin(qMax((int)ceils.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int ceilZ = qMin(qMax((int)ceils.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - float upperLeft = src[floorZ * width + floorX]; - float upperRight = src[floorZ * width + ceilX]; - float lowerLeft = src[ceilZ * width + floorX]; - float lowerRight = src[ceilZ * width + ceilX]; - - // find the distance to the next x coordinate - float xDistance = FLT_MAX; - if (dir.x > 0.0f) { - xDistance = (ceils.x - entry.x) / dir.x; - } else if (dir.x < 0.0f) { - xDistance = (floors.x - entry.x) / dir.x; - } - - // and the distance to the next z coordinate - float zDistance = FLT_MAX; - if (dir.z > 0.0f) { - zDistance = (ceils.z - entry.z) / dir.z; - } else if (dir.z < 0.0f) { - zDistance = (floors.z - entry.z) / dir.z; - } - - // the exit distance is the lower of those two - float exitDistance = qMin(xDistance, zDistance); - glm::vec3 exit, nextFloors = floors, nextCeils = ceils; - if (exitDistance == FLT_MAX) { - if (dir.y > 0.0f) { - return false; // line points upwards; no collisions possible - } - withinBounds = false; // line points downwards; check this cell only - - } else { - // find the exit point and the next cell, and determine whether it's still within the bounds - exit = entry + exitDistance * dir; - withinBounds = (exit.y >= 0.0f && exit.y <= numeric_limits::max()); - if (exitDistance == xDistance) { - if (dir.x > 0.0f) { - nextFloors.x += 1.0f; - withinBounds &= (nextCeils.x += 1.0f) <= highestX; - } else { - withinBounds &= (nextFloors.x -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.x -= 1.0f; - } - } - if (exitDistance == zDistance) { - if (dir.z > 0.0f) { - nextFloors.z += 1.0f; - withinBounds &= (nextCeils.z += 1.0f) <= highestZ; - } else { - withinBounds &= (nextFloors.z -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.z -= 1.0f; - } - } - // check the vertical range of the ray against the ranges of the cell heights - if (upperLeft == 0 || upperRight == 0 || lowerLeft == 0 || lowerRight == 0 || - qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) || - qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) { - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - continue; - } - } - // having passed the bounds check, we must check against the planes - glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z); - - // first check the triangle including the Z+ segment - glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); - float lowerProduct = glm::dot(lowerNormal, dir); - if (lowerProduct < 0.0f) { - float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.z >= intersection.x) { - distance = boundsDistance + accumulatedDistance + planeDistance; - return true; - } - } - - // then the one with the X+ segment - glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); - float upperProduct = glm::dot(upperNormal, dir); - if (upperProduct < 0.0f) { - float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.x >= intersection.z) { - distance = boundsDistance + accumulatedDistance + planeDistance; - return true; - } - } - - // no joy; continue on our way - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - } - - return false; -} - -static inline float mixHeights(float firstHeight, float secondHeight, float t) { - return (firstHeight == 0.0f) ? secondHeight : (secondHeight == 0.0f ? firstHeight : - glm::mix(firstHeight, secondHeight, t)); -} - -HeightfieldNode* HeightfieldNode::subdivide(const QVector& heightContents, - const QVector& stackContents) const { - HeightfieldNode* newNode = new HeightfieldNode(*this); - int heightWidth = _height->getWidth(); - int heightHeight = heightContents.size() / heightWidth; - newNode->setHeight(HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, heightContents))); - int stackWidth = 0, stackHeight = 0; - QVector stackMaterials; - if (_stack) { - stackWidth = _stack->getWidth(); - stackHeight = stackContents.size() / stackWidth; - stackMaterials = _stack->getMaterials(); - newNode->setStack(HeightfieldStackPointer(new HeightfieldStack(stackWidth, stackContents, stackMaterials))); - } - int colorWidth = 0, colorHeight = 0; - if (_color) { - colorWidth = _color->getWidth(); - colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES); - } - int materialWidth = 0, materialHeight = 0; - QVector materialMaterials; - if (_material) { - materialWidth = _material->getWidth(); - materialHeight = _material->getContents().size() / materialWidth; - materialMaterials = _material->getMaterials(); - } - for (int i = 0; i < CHILD_COUNT; i++) { - QVector childHeightContents(heightWidth * heightHeight); - QByteArray childColorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFFu); - QByteArray childMaterialContents(materialWidth * materialHeight, 0); - QVector childStackContents(stackWidth * stackHeight); - - quint16* heightDest = childHeightContents.data(); - const quint16* heightSrc = heightContents.constData() + (i & Y_MAXIMUM_FLAG ? (heightHeight / 2) * heightWidth : 0) + - (i & X_MAXIMUM_FLAG ? heightWidth / 2 : 0); - for (int z = 0; z < heightHeight; z++) { - float srcZ = z * 0.5f + 0.5f; - float fractZ = glm::fract(srcZ); - const quint16* heightSrcZ = heightSrc + (int)srcZ * heightWidth; - for (int x = 0; x < heightWidth; x++) { - float srcX = x * 0.5f + 0.5f; - float fractX = glm::fract(srcX); - const quint16* heightSrcX = heightSrcZ + (int)srcX; - if (fractZ == 0.0f) { - if (fractX == 0.0f) { - *heightDest++ = heightSrcX[0]; - } else { - *heightDest++ = mixHeights(heightSrcX[0], heightSrcX[1], fractX); - } - } else { - if (fractX == 0.0f) { - *heightDest++ = mixHeights(heightSrcX[0], heightSrcX[heightWidth], fractZ); - } else { - *heightDest++ = mixHeights(mixHeights(heightSrcX[0], heightSrcX[1], fractX), - mixHeights(heightSrcX[heightWidth], heightSrcX[heightWidth + 1], fractX), fractZ); - } - } - } - } - - if (colorWidth != 0) { - char* colorDest = childColorContents.data(); - const uchar* colorSrc = (const uchar*)_color->getContents().constData() + - ((i & Y_MAXIMUM_FLAG ? (colorHeight / 2) * colorWidth : 0) + - (i & X_MAXIMUM_FLAG ? colorWidth / 2 : 0)) * DataBlock::COLOR_BYTES; - for (int z = 0; z < colorHeight; z++) { - float srcZ = z * 0.5f; - float fractZ = glm::fract(srcZ); - const uchar* colorSrcZ = colorSrc + (int)srcZ * colorWidth * DataBlock::COLOR_BYTES; - for (int x = 0; x < colorWidth; x++) { - float srcX = x * 0.5f; - float fractX = glm::fract(srcX); - const uchar* colorSrcX = colorSrcZ + (int)srcX * DataBlock::COLOR_BYTES; - const uchar* nextColorSrcX = colorSrcX + colorWidth * DataBlock::COLOR_BYTES; - if (fractZ == 0.0f) { - if (fractX == 0.0f) { - *colorDest++ = colorSrcX[0]; - *colorDest++ = colorSrcX[1]; - *colorDest++ = colorSrcX[2]; - } else { - *colorDest++ = glm::mix(colorSrcX[0], colorSrcX[3], fractX); - *colorDest++ = glm::mix(colorSrcX[1], colorSrcX[4], fractX); - *colorDest++ = glm::mix(colorSrcX[2], colorSrcX[5], fractX); - } - } else { - if (fractX == 0.0f) { - *colorDest++ = glm::mix(colorSrcX[0], nextColorSrcX[0], fractZ); - *colorDest++ = glm::mix(colorSrcX[1], nextColorSrcX[1], fractZ); - *colorDest++ = glm::mix(colorSrcX[2], nextColorSrcX[2], fractZ); - } else { - *colorDest++ = glm::mix(glm::mix(colorSrcX[0], colorSrcX[3], fractX), - glm::mix(nextColorSrcX[0], nextColorSrcX[3], fractX), fractZ); - *colorDest++ = glm::mix(glm::mix(colorSrcX[1], colorSrcX[4], fractX), - glm::mix(nextColorSrcX[1], nextColorSrcX[4], fractX), fractZ); - *colorDest++ = glm::mix(glm::mix(colorSrcX[2], colorSrcX[5], fractX), - glm::mix(nextColorSrcX[2], nextColorSrcX[5], fractX), fractZ); - } - } - } - } - } - - if (materialWidth != 0) { - char* materialDest = childMaterialContents.data(); - const char* materialSrc = _material->getContents().constData() + - (i & Y_MAXIMUM_FLAG ? (materialHeight / 2) * materialWidth : 0) + - (i & X_MAXIMUM_FLAG ? materialWidth / 2 : 0); - for (int z = 0; z < materialHeight; z++) { - float srcZ = z * 0.5f; - const char* materialSrcZ = materialSrc + (int)srcZ * materialWidth; - for (int x = 0; x < materialWidth; x++) { - float srcX = x * 0.5f; - const char* materialSrcX = materialSrcZ + (int)srcX; - *materialDest++ = *materialSrcX; - } - } - } - - if (stackWidth != 0) { - StackArray* stackDest = childStackContents.data(); - const StackArray* stackSrc = _stack->getContents().constData() + - (i & Y_MAXIMUM_FLAG ? (stackHeight / 2) * stackWidth : 0) + - (i & X_MAXIMUM_FLAG ? stackWidth / 2 : 0); - for (int z = 0; z < stackHeight; z++) { - float srcZ = z * 0.5f; - float fractZ = glm::fract(srcZ); - const StackArray* stackSrcZ = stackSrc + (int)srcZ * stackWidth; - for (int x = 0; x < stackWidth; x++) { - float srcX = x * 0.5f; - float fractX = glm::fract(srcX); - const StackArray* stackSrcX = stackSrcZ + (int)srcX; - if (stackSrcX->isEmpty()) { - stackDest++; - continue; - } - int minimumY = stackSrcX->getPosition() * 2; - int maximumY = (stackSrcX->getPosition() + stackSrcX->getEntryCount() - 1) * 2; - *stackDest = StackArray(maximumY - minimumY + 1); - stackDest->setPosition(minimumY); - for (int y = minimumY; y <= maximumY; y++) { - float srcY = y * 0.5f; - float fractY = glm::fract(srcY); - const StackArray::Entry& srcEntry = stackSrcX->getEntry((int)srcY); - StackArray::Entry& destEntry = stackDest->getEntry(y); - destEntry.color = srcEntry.color; - destEntry.material = srcEntry.material; - if (srcEntry.hermiteX != 0) { - glm::vec3 normal; - float distance = srcEntry.getHermiteX(normal); - if (distance < fractX) { - const StackArray::Entry& nextSrcEntryX = stackSrcX[1].getEntry((int)srcY); - destEntry.color = nextSrcEntryX.color; - destEntry.material = nextSrcEntryX.material; - - } else { - destEntry.setHermiteX(normal, (distance - fractX) / 0.5f); - } - } - if (srcEntry.hermiteY != 0) { - glm::vec3 normal; - float distance = srcEntry.getHermiteY(normal); - if (distance < fractY) { - const StackArray::Entry& nextSrcEntryY = stackSrcX->getEntry((int)srcY + 1); - destEntry.color = nextSrcEntryY.color; - destEntry.material = nextSrcEntryY.material; - - } else { - destEntry.setHermiteY(normal, (distance - fractY) / 0.5f); - } - } - if (srcEntry.hermiteZ != 0) { - glm::vec3 normal; - float distance = srcEntry.getHermiteZ(normal); - if (distance < fractZ) { - const StackArray::Entry& nextSrcEntryZ = stackSrcX[stackWidth].getEntry((int)srcY); - destEntry.color = nextSrcEntryZ.color; - destEntry.material = nextSrcEntryZ.material; - - } else { - destEntry.setHermiteZ(normal, (distance - fractZ) / 0.5f); - } - } - } - stackDest++; - } - } - } - - newNode->setChild(i, HeightfieldNodePointer(new HeightfieldNode( - HeightfieldHeightPointer(new HeightfieldHeight(heightWidth, childHeightContents)), - HeightfieldColorPointer(colorWidth == 0 ? NULL : new HeightfieldColor(colorWidth, childColorContents)), - HeightfieldMaterialPointer(materialWidth == 0 ? NULL : - new HeightfieldMaterial(materialWidth, childMaterialContents, materialMaterials)), - HeightfieldStackPointer(stackWidth == 0 ? NULL : - new HeightfieldStack(stackWidth, childStackContents, stackMaterials))))); - } - return newNode; -} - -AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() { -} - -bool AbstractHeightfieldNodeRenderer::findRayIntersection(const glm::vec3& translation, - const glm::quat& rotation, const glm::vec3& scale, const glm::vec3& origin, const glm::vec3& direction, - float boundsDistance, float& distance) const { - return false; -} - -Heightfield::Heightfield() : - _aspectY(1.0f), - _aspectZ(1.0f) { - - connect(this, &Heightfield::translationChanged, this, &Heightfield::updateBounds); - connect(this, &Heightfield::rotationChanged, this, &Heightfield::updateBounds); - connect(this, &Heightfield::scaleChanged, this, &Heightfield::updateBounds); - connect(this, &Heightfield::aspectYChanged, this, &Heightfield::updateBounds); - connect(this, &Heightfield::aspectZChanged, this, &Heightfield::updateBounds); - updateBounds(); - - connect(this, &Heightfield::heightChanged, this, &Heightfield::updateRoot); - connect(this, &Heightfield::colorChanged, this, &Heightfield::updateRoot); - connect(this, &Heightfield::materialChanged, this, &Heightfield::updateRoot); - connect(this, &Heightfield::stackChanged, this, &Heightfield::updateRoot); - updateRoot(); -} - -void Heightfield::setAspectY(float aspectY) { - if (_aspectY != aspectY) { - emit aspectYChanged(_aspectY = aspectY); - } -} - -void Heightfield::setAspectZ(float aspectZ) { - if (_aspectZ != aspectZ) { - emit aspectZChanged(_aspectZ = aspectZ); - } -} - -void Heightfield::setHeight(const HeightfieldHeightPointer& height) { - if (_height != height) { - emit heightChanged(_height = height); - } -} - -void Heightfield::setColor(const HeightfieldColorPointer& color) { - if (_color != color) { - emit colorChanged(_color = color); - } -} - -void Heightfield::setMaterial(const HeightfieldMaterialPointer& material) { - if (_material != material) { - emit materialChanged(_material = material); - } -} - -void Heightfield::setStack(const HeightfieldStackPointer& stack) { - if (_stack != stack) { - emit stackChanged(_stack = stack); - } -} - -MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const { - // after transforming into unit space, we scale the threshold in proportion to vertical distance - glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ)); - glm::vec3 position = glm::inverse(getRotation()) * (lod.position - getTranslation()) * inverseScale; - const float THRESHOLD_MULTIPLIER = 256.0f; - return MetavoxelLOD(glm::vec3(position.x, position.z, 0.0f), lod.threshold * - qMax(0.5f, glm::abs(position.y * _aspectY - 0.5f)) * THRESHOLD_MULTIPLIER); -} - -SharedObject* Heightfield::clone(bool withID, SharedObject* target) const { - Heightfield* newHeightfield = static_cast(Spanner::clone(withID, target)); - newHeightfield->setHeight(_height); - newHeightfield->setColor(_color); - newHeightfield->setMaterial(_material); - newHeightfield->setRoot(_root); - return newHeightfield; -} - -bool Heightfield::isHeightfield() const { - return true; -} - -float Heightfield::getHeight(const glm::vec3& location) const { - float distance; - glm::vec3 down = getRotation() * glm::vec3(0.0f, -1.0f, 0.0f); - glm::vec3 origin = location - down * (glm::dot(down, location) + getScale() * _aspectY - glm::dot(down, getTranslation())); - if (findRayIntersection(origin, down, distance)) { - return origin.y + distance * down.y; - } - return -FLT_MAX; -} - -bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { - return _root->findRayIntersection(getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * _aspectY, - getScale() * _aspectZ), origin, direction, distance); -} - -Spanner* Heightfield::paintHeight(const glm::vec3& position, float radius, float height, - bool set, bool erase, float granularity) { - // first see if we're going to exceed the range limits - float minimumValue = 1.0f, maximumValue = numeric_limits::max(); - if (set) { - float heightValue = height * numeric_limits::max() / (getScale() * _aspectY); - minimumValue = qMin(minimumValue, heightValue); - maximumValue = qMax(maximumValue, heightValue); - - } else if (!erase) { - _root->getRangeAfterHeightPaint(getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * _aspectY, - getScale() * _aspectZ), position, radius, height, minimumValue, maximumValue); - } - - // normalize if necessary - float normalizeScale, normalizeOffset; - Heightfield* newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset); - newHeightfield->setRoot(HeightfieldNodePointer(_root->paintHeight(newHeightfield->getTranslation(), getRotation(), - glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), position, radius, height, - set, erase, normalizeScale, normalizeOffset, granularity))); - return newHeightfield; -} - -Spanner* Heightfield::fillHeight(const glm::vec3& position, float radius, float granularity) { - Heightfield* newHeightfield = static_cast(clone(true)); - newHeightfield->setRoot(HeightfieldNodePointer(_root->fillHeight(getTranslation(), getRotation(), - glm::vec3(getScale(), getScale() * _aspectY, getScale() * _aspectZ), position, radius, granularity))); - return newHeightfield; -} - -Spanner* Heightfield::setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint, bool voxelize, float granularity) { - // first see if we're going to exceed the range limits, normalizing if necessary - Spanner* spannerData = static_cast(spanner.data()); - float normalizeScale = 1.0f, normalizeOffset = 0.0f; - Heightfield* newHeightfield; - if (paint) { - newHeightfield = static_cast(clone(true)); - } else { - float minimumValue = 1.0f, maximumValue = numeric_limits::max(); - _root->getRangeAfterEdit(getTranslation(), getRotation(), glm::vec3(getScale(), getScale() * _aspectY, - getScale() * _aspectZ), spannerData->getBounds(), minimumValue, maximumValue); - newHeightfield = prepareEdit(minimumValue, maximumValue, normalizeScale, normalizeOffset); - } - newHeightfield->setRoot(HeightfieldNodePointer(_root->setMaterial(newHeightfield->getTranslation(), getRotation(), - glm::vec3(getScale(), getScale() * newHeightfield->getAspectY(), getScale() * _aspectZ), spannerData, - material, color, paint, voxelize, normalizeScale, normalizeOffset, granularity))); - return newHeightfield; -} - -bool Heightfield::hasOwnColors() const { - return _color; -} - -bool Heightfield::hasOwnMaterials() const { - return _material; -} - -QRgb Heightfield::getColorAt(const glm::vec3& point) { - int width = _color->getWidth(); - const QByteArray& contents = _color->getContents(); - const uchar* src = (const uchar*)contents.constData(); - int height = contents.size() / (width * DataBlock::COLOR_BYTES); - int innerWidth = width - HeightfieldData::SHARED_EDGE; - int innerHeight = height - HeightfieldData::SHARED_EDGE; - - glm::vec3 relative = glm::inverse(getRotation()) * (point - getTranslation()) * glm::vec3(innerWidth / getScale(), - 1.0f, innerHeight / (getScale() * _aspectZ)); - if (relative.x < 0.0f || relative.z < 0.0f || relative.x > width - 1 || relative.z > height - 1) { - return 0; - } - glm::vec3 floors = glm::floor(relative); - glm::vec3 ceils = glm::ceil(relative); - glm::vec3 fracts = glm::fract(relative); - int floorX = (int)floors.x; - int floorZ = (int)floors.z; - int ceilX = (int)ceils.x; - int ceilZ = (int)ceils.z; - const uchar* upperLeft = src + (floorZ * width + floorX) * DataBlock::COLOR_BYTES; - const uchar* lowerRight = src + (ceilZ * width + ceilX) * DataBlock::COLOR_BYTES; - glm::vec3 interpolatedColor = glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), - glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z); - - // the final vertex (and thus which triangle we check) depends on which half we're on - if (fracts.x >= fracts.z) { - const uchar* upperRight = src + (floorZ * width + ceilX) * DataBlock::COLOR_BYTES; - interpolatedColor = glm::mix(interpolatedColor, glm::mix(glm::vec3(upperRight[0], upperRight[1], upperRight[2]), - glm::vec3(lowerRight[0], lowerRight[1], lowerRight[2]), fracts.z), (fracts.x - fracts.z) / (1.0f - fracts.z)); - - } else { - const uchar* lowerLeft = src + (ceilZ * width + floorX) * DataBlock::COLOR_BYTES; - interpolatedColor = glm::mix(glm::mix(glm::vec3(upperLeft[0], upperLeft[1], upperLeft[2]), - glm::vec3(lowerLeft[0], lowerLeft[1], lowerLeft[2]), fracts.z), interpolatedColor, fracts.x / fracts.z); - } - return qRgb(interpolatedColor.r, interpolatedColor.g, interpolatedColor.b); -} - -int Heightfield::getMaterialAt(const glm::vec3& point) { - int width = _material->getWidth(); - const QByteArray& contents = _material->getContents(); - const uchar* src = (const uchar*)contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldData::SHARED_EDGE; - int innerHeight = height - HeightfieldData::SHARED_EDGE; - - glm::vec3 relative = glm::inverse(getRotation()) * (point - getTranslation()) * glm::vec3(innerWidth / getScale(), - 1.0f, innerHeight / (getScale() * _aspectZ)); - if (relative.x < 0.0f || relative.z < 0.0f || relative.x > width - 1 || relative.z > height - 1) { - return -1; - } - return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)]; -} - -QVector& Heightfield::getMaterials() { - return _material->getMaterials(); -} - -bool Heightfield::contains(const glm::vec3& point) { - if (!_height) { - return false; - } - int width = _height->getWidth(); - const QVector& contents = _height->getContents(); - const quint16* src = contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - int highestX = innerWidth + HeightfieldHeight::HEIGHT_BORDER; - int highestZ = innerHeight + HeightfieldHeight::HEIGHT_BORDER; - - glm::vec3 relative = glm::inverse(getRotation()) * (point - getTranslation()) * glm::vec3(innerWidth / getScale(), - numeric_limits::max() / (getScale() * _aspectY), innerHeight / (getScale() * _aspectZ)); - if (relative.x < 0.0f || relative.y < 0.0f || relative.z < 0.0f || relative.x > innerWidth || - relative.y > numeric_limits::max() || relative.z > innerHeight) { - return false; - } - relative.x += HeightfieldHeight::HEIGHT_BORDER; - relative.z += HeightfieldHeight::HEIGHT_BORDER; - - // find the bounds of the cell containing the point and the shared vertex heights - glm::vec3 floors = glm::floor(relative); - glm::vec3 ceils = glm::ceil(relative); - glm::vec3 fracts = glm::fract(relative); - int floorX = qMin(qMax((int)floors.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int floorZ = qMin(qMax((int)floors.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - int ceilX = qMin(qMax((int)ceils.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int ceilZ = qMin(qMax((int)ceils.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - float upperLeft = src[floorZ * width + floorX]; - float lowerRight = src[ceilZ * width + ceilX]; - float interpolatedHeight = glm::mix(upperLeft, lowerRight, fracts.z); - - // the final vertex (and thus which triangle we check) depends on which half we're on - if (fracts.x >= fracts.z) { - float upperRight = src[floorZ * width + ceilX]; - interpolatedHeight = glm::mix(interpolatedHeight, glm::mix(upperRight, lowerRight, fracts.z), - (fracts.x - fracts.z) / (1.0f - fracts.z)); - - } else { - float lowerLeft = src[ceilZ * width + floorX]; - interpolatedHeight = glm::mix(glm::mix(upperLeft, lowerLeft, fracts.z), interpolatedHeight, fracts.x / fracts.z); - } - if (interpolatedHeight == 0.0f) { - return false; // ignore zero values - } - - // compare - return relative.y <= interpolatedHeight; -} - -bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal) { - int width = _height->getWidth(); - const QVector& contents = _height->getContents(); - const quint16* src = contents.constData(); - int height = contents.size() / width; - int innerWidth = width - HeightfieldHeight::HEIGHT_EXTENSION; - int innerHeight = height - HeightfieldHeight::HEIGHT_EXTENSION; - int highestX = innerWidth + HeightfieldHeight::HEIGHT_BORDER; - int highestZ = innerHeight + HeightfieldHeight::HEIGHT_BORDER; - - glm::quat inverseRotation = glm::inverse(getRotation()); - glm::vec3 inverseScale(innerWidth / getScale(), numeric_limits::max() / (getScale() * _aspectY), - innerHeight / (getScale() * _aspectZ)); - glm::vec3 direction = end - start; - glm::vec3 dir = inverseRotation * direction * inverseScale; - glm::vec3 entry = inverseRotation * (start - getTranslation()) * inverseScale; - - float boundsDistance; - if (!Box(glm::vec3(), glm::vec3((float)innerWidth, (float)numeric_limits::max(), - (float)innerHeight)).findRayIntersection(entry, dir, boundsDistance) || boundsDistance > 1.0f) { - return false; - } - entry += dir * boundsDistance; - - const float DISTANCE_THRESHOLD = 0.001f; - if (glm::abs(entry.x - 0.0f) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(-1.0f, 0.0f, 0.0f); - distance = boundsDistance; - return true; - - } else if (glm::abs(entry.x - innerWidth) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(1.0f, 0.0f, 0.0f); - distance = boundsDistance; - return true; - - } else if (glm::abs(entry.y - 0.0f) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(0.0f, -1.0f, 0.0f); - distance = boundsDistance; - return true; - - } else if (glm::abs(entry.y - numeric_limits::max()) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(0.0f, 1.0f, 0.0f); - distance = boundsDistance; - return true; - - } else if (glm::abs(entry.z - 0.0f) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(0.0f, 0.0f, -1.0f); - distance = boundsDistance; - return true; - - } else if (glm::abs(entry.z - innerHeight) < DISTANCE_THRESHOLD) { - normal = getRotation() * glm::vec3(0.0f, 0.0f, 1.0f); - distance = boundsDistance; - return true; - } - - entry.x += HeightfieldHeight::HEIGHT_BORDER; - entry.z += HeightfieldHeight::HEIGHT_BORDER; - glm::vec3 floors = glm::floor(entry); - glm::vec3 ceils = glm::ceil(entry); - if (floors.x == ceils.x) { - if (dir.x > 0.0f) { - ceils.x += 1.0f; - } else { - floors.x -= 1.0f; - } - } - if (floors.z == ceils.z) { - if (dir.z > 0.0f) { - ceils.z += 1.0f; - } else { - floors.z -= 1.0f; - } - } - - glm::vec3 normalScale(1.0f / (inverseScale.y * inverseScale.z), 1.0f / (inverseScale.x * inverseScale.z), - 1.0f / (inverseScale.x * inverseScale.y)); - - bool withinBounds = true; - float accumulatedDistance = boundsDistance; - while (withinBounds && accumulatedDistance <= 1.0f) { - // find the heights at the corners of the current cell - int floorX = qMin(qMax((int)floors.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int floorZ = qMin(qMax((int)floors.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - int ceilX = qMin(qMax((int)ceils.x, HeightfieldHeight::HEIGHT_BORDER), highestX); - int ceilZ = qMin(qMax((int)ceils.z, HeightfieldHeight::HEIGHT_BORDER), highestZ); - float upperLeft = src[floorZ * width + floorX]; - float upperRight = src[floorZ * width + ceilX]; - float lowerLeft = src[ceilZ * width + floorX]; - float lowerRight = src[ceilZ * width + ceilX]; - - // find the distance to the next x coordinate - float xDistance = FLT_MAX; - if (dir.x > 0.0f) { - xDistance = (ceils.x - entry.x) / dir.x; - } else if (dir.x < 0.0f) { - xDistance = (floors.x - entry.x) / dir.x; - } - - // and the distance to the next z coordinate - float zDistance = FLT_MAX; - if (dir.z > 0.0f) { - zDistance = (ceils.z - entry.z) / dir.z; - } else if (dir.z < 0.0f) { - zDistance = (floors.z - entry.z) / dir.z; - } - - // the exit distance is the lower of those two - float exitDistance = qMin(xDistance, zDistance); - glm::vec3 exit, nextFloors = floors, nextCeils = ceils; - if (exitDistance == FLT_MAX) { - withinBounds = false; // line points upwards/downwards; check this cell only - - } else { - // find the exit point and the next cell, and determine whether it's still within the bounds - exit = entry + exitDistance * dir; - withinBounds = (exit.y >= 0.0f && exit.y <= numeric_limits::max()); - if (exitDistance == xDistance) { - if (dir.x > 0.0f) { - nextFloors.x += 1.0f; - withinBounds &= (nextCeils.x += 1.0f) <= highestX; - } else { - withinBounds &= (nextFloors.x -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.x -= 1.0f; - } - } - if (exitDistance == zDistance) { - if (dir.z > 0.0f) { - nextFloors.z += 1.0f; - withinBounds &= (nextCeils.z += 1.0f) <= highestZ; - } else { - withinBounds &= (nextFloors.z -= 1.0f) >= HeightfieldHeight::HEIGHT_BORDER; - nextCeils.z -= 1.0f; - } - } - // check the vertical range of the ray against the ranges of the cell heights - if (qMin(entry.y, exit.y) > qMax(qMax(upperLeft, upperRight), qMax(lowerLeft, lowerRight)) || - qMax(entry.y, exit.y) < qMin(qMin(upperLeft, upperRight), qMin(lowerLeft, lowerRight))) { - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - continue; - } - } - // having passed the bounds check, we must check against the planes - glm::vec3 relativeEntry = entry - glm::vec3(floors.x, upperLeft, floors.z); - - // first check the triangle including the Z+ segment - glm::vec3 lowerNormal(lowerLeft - lowerRight, 1.0f, upperLeft - lowerLeft); - float lowerProduct = glm::dot(lowerNormal, dir); - if (lowerProduct != 0.0f) { - float planeDistance = -glm::dot(lowerNormal, relativeEntry) / lowerProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.z >= intersection.x) { - distance = accumulatedDistance + planeDistance; - normal = glm::normalize(getRotation() * (lowerNormal * normalScale)); - return true; - } - } - - // then the one with the X+ segment - glm::vec3 upperNormal(upperLeft - upperRight, 1.0f, upperRight - lowerRight); - float upperProduct = glm::dot(upperNormal, dir); - if (upperProduct != 0.0f) { - float planeDistance = -glm::dot(upperNormal, relativeEntry) / upperProduct; - glm::vec3 intersection = relativeEntry + planeDistance * dir; - if (intersection.x >= 0.0f && intersection.x <= 1.0f && intersection.z >= 0.0f && intersection.z <= 1.0f && - intersection.x >= intersection.z) { - distance = accumulatedDistance + planeDistance; - normal = glm::normalize(getRotation() * (upperNormal * normalScale)); - return true; - } - } - - // no joy; continue on our way - entry = exit; - floors = nextFloors; - ceils = nextCeils; - accumulatedDistance += exitDistance; - } - - return false; -} - -void Heightfield::writeExtra(Bitstream& out) const { - if (getWillBeVoxelized()) { - out << _height << _color << _material << _stack; - return; - } - MetavoxelLOD lod; - if (out.getContext()) { - lod = transformLOD(static_cast(out.getContext())->lod); - } - HeightfieldStreamBase base = { out, lod, lod }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - _root->write(state); -} - -void Heightfield::readExtra(Bitstream& in, bool reread) { - if (getWillBeVoxelized()) { - if (reread) { - HeightfieldHeightPointer height; - HeightfieldColorPointer color; - HeightfieldMaterialPointer material; - HeightfieldStackPointer stack; - in >> height >> color >> material >> stack; - - } else { - in >> _height >> _color >> _material >> _stack; - } - return; - } - MetavoxelLOD lod; - if (in.getContext()) { - lod = transformLOD(static_cast(in.getContext())->lod); - } - HeightfieldStreamBase base = { in, lod, lod }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - - HeightfieldNodePointer root(new HeightfieldNode()); - root->read(state); - if (!reread) { - setRoot(root); - } -} - -void Heightfield::writeExtraDelta(Bitstream& out, const SharedObject* reference) const { - MetavoxelLOD lod, referenceLOD; - if (out.getContext()) { - MetavoxelStreamBase* base = static_cast(out.getContext()); - lod = transformLOD(base->lod); - referenceLOD = transformLOD(base->referenceLOD); - } - HeightfieldStreamBase base = { out, lod, referenceLOD }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - const HeightfieldNodePointer& referenceRoot = static_cast(reference)->getRoot(); - if (_root == referenceRoot) { - out << false; - if (state.becameSubdivided()) { - _root->writeSubdivision(state); - } - } else { - out << true; - _root->writeDelta(referenceRoot, state); - } -} - -void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread) { - MetavoxelLOD lod, referenceLOD; - if (in.getContext()) { - MetavoxelStreamBase* base = static_cast(in.getContext()); - lod = transformLOD(base->lod); - referenceLOD = transformLOD(base->referenceLOD); - } - HeightfieldStreamBase base = { in, lod, referenceLOD }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - - bool changed; - in >> changed; - if (changed) { - HeightfieldNodePointer root(new HeightfieldNode()); - root->readDelta(static_cast(reference)->getRoot(), state); - if (!reread) { - setRoot(root); - } - } else if (state.becameSubdividedOrCollapsed()) { - HeightfieldNodePointer root(_root->readSubdivision(state)); - if (!reread) { - setRoot(root); - } - } else if (!reread) { - setRoot(static_cast(reference)->getRoot()); - } -} - -void Heightfield::maybeWriteSubdivision(Bitstream& out) { - MetavoxelLOD lod, referenceLOD; - if (out.getContext()) { - MetavoxelStreamBase* base = static_cast(out.getContext()); - lod = transformLOD(base->lod); - referenceLOD = transformLOD(base->referenceLOD); - } - HeightfieldStreamBase base = { out, lod, referenceLOD }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - - if (state.becameSubdividedOrCollapsed()) { - out << SharedObjectPointer(this); - _root->writeSubdivision(state); - } -} - -SharedObject* Heightfield::readSubdivision(Bitstream& in) { - MetavoxelLOD lod, referenceLOD; - if (in.getContext()) { - MetavoxelStreamBase* base = static_cast(in.getContext()); - lod = transformLOD(base->lod); - referenceLOD = transformLOD(base->referenceLOD); - } - HeightfieldStreamBase base = { in, lod, referenceLOD }; - HeightfieldStreamState state = { base, glm::vec2(), 1.0f }; - - if (state.becameSubdividedOrCollapsed()) { - HeightfieldNodePointer root(_root->readSubdivision(state)); - if (_root != root) { - Heightfield* newHeightfield = static_cast(clone(true)); - newHeightfield->setRemoteID(getRemoteID()); - newHeightfield->setRemoteOriginID(getRemoteOriginID()); - newHeightfield->setRoot(root); - return newHeightfield; - } - } - return this; -} - -QByteArray Heightfield::getRendererClassName() const { - return "HeightfieldRenderer"; -} - -void Heightfield::updateBounds() { - glm::vec3 extent(getScale(), getScale() * _aspectY, getScale() * _aspectZ); - glm::mat4 rotationMatrix = glm::mat4_cast(getRotation()); - setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(glm::vec3(), extent)); -} - -void Heightfield::updateRoot() { - HeightfieldNodePointer root(new HeightfieldNode()); - if (_height) { - root->setContents(_height, _color, _material, _stack); - } - setRoot(root); -} - -Heightfield* Heightfield::prepareEdit(float minimumValue, float maximumValue, float& normalizeScale, float& normalizeOffset) { - // renormalize if necessary - Heightfield* newHeightfield = static_cast(clone(true)); - if (minimumValue < 1.0f || maximumValue > numeric_limits::max()) { - normalizeScale = (numeric_limits::max() - 1.0f) / (maximumValue - minimumValue); - normalizeOffset = 1.0f - minimumValue; - newHeightfield->setAspectY(_aspectY / normalizeScale); - newHeightfield->setTranslation(getTranslation() - getRotation() * - glm::vec3(0.0f, normalizeOffset * _aspectY * getScale() / (numeric_limits::max() - 1), 0.0f)); - } else { - normalizeScale = 1.0f; - normalizeOffset = 0.0f; - } - return newHeightfield; -} - diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h deleted file mode 100644 index b60a104d68..0000000000 --- a/libraries/metavoxels/src/Spanner.h +++ /dev/null @@ -1,866 +0,0 @@ -// -// Spanner.h -// libraries/metavoxels/src -// -// Created by Andrzej Kapolka on 11/10/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Spanner_h -#define hifi_Spanner_h - -#include - -#include "AttributeRegistry.h" -#include "MetavoxelUtil.h" - -class AbstractHeightfieldNodeRenderer; -class DataBlock; -class Heightfield; -class HeightfieldColor; -class HeightfieldHeight; -class HeightfieldMaterial; -class HeightfieldNode; -class HeightfieldStack; -class SpannerRenderer; - -/// An object that spans multiple octree cells. -class Spanner : public SharedObject { - Q_OBJECT - Q_PROPERTY(Box bounds MEMBER _bounds WRITE setBounds NOTIFY boundsChanged DESIGNABLE false) - Q_PROPERTY(float placementGranularity MEMBER _placementGranularity DESIGNABLE false) - Q_PROPERTY(float voxelizationGranularity MEMBER _voxelizationGranularity DESIGNABLE false) - Q_PROPERTY(bool willBeVoxelized MEMBER _willBeVoxelized DESIGNABLE false) - -public: - - /// Returns the value of the global visit counter and increments it. - static int getAndIncrementNextVisit() { return _nextVisit.fetchAndAddOrdered(1); } - - Spanner(); - - void setBounds(const Box& bounds); - const Box& getBounds() const { return _bounds; } - - void setPlacementGranularity(float granularity) { _placementGranularity = granularity; } - float getPlacementGranularity() const { return _placementGranularity; } - - void setVoxelizationGranularity(float granularity) { _voxelizationGranularity = granularity; } - float getVoxelizationGranularity() const { return _voxelizationGranularity; } - - void setMerged(bool merged) { _merged = merged; } - bool isMerged() const { return _merged; } - - void setWillBeVoxelized(bool willBeVoxelized) { _willBeVoxelized = willBeVoxelized; } - bool getWillBeVoxelized() const { return _willBeVoxelized; } - - /// Checks whether we've visited this object on the current traversal. If we have, returns false. - /// If we haven't, sets the last visit identifier and returns true. - bool testAndSetVisited(int visit); - - /// Returns a pointer to the renderer, creating it if necessary. - SpannerRenderer* getRenderer(); - - /// Checks whether this is a heightfield. - virtual bool isHeightfield() const; - - /// Finds the height at the specified location, or returns -FLT_MAX for none. - virtual float getHeight(const glm::vec3& location) const; - - /// Finds the intersection between the described ray and this spanner. - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - - /// Attempts to modify the spanner's height. - /// \param set whether to set the height as opposed to raising/lowering it - /// \param erase whether to erase height values - /// \return the modified spanner, or this if no modification was performed - virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, - bool set, bool erase, float granularity); - - /// Attempts to fill the spanner's height (adding removing volumetric information). - /// \return the modified spanner, or this if no modification was performed - virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity); - - /// Attempts to "sculpt" or "paint," etc., with the supplied spanner. - /// \return the modified spanner, or this if no modification was performed - virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint, bool voxelize, float granularity); - - /// Checks whether this spanner has its own colors. - virtual bool hasOwnColors() const; - - /// Checks whether this spanner has its own materials. - virtual bool hasOwnMaterials() const; - - /// Checks whether the spanner contains the specified point. - virtual bool contains(const glm::vec3& point); - - /// Retrieves the color at the specified point. - virtual QRgb getColorAt(const glm::vec3& point); - - /// Retrieves the material at the specified point. - virtual int getMaterialAt(const glm::vec3& point); - - /// Retrieves a reference to the list of materials. - virtual QVector& getMaterials(); - - /// Finds the intersection, if any, between the specified line segment and the spanner. - virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal); - -signals: - - void boundsWillChange(); - void boundsChanged(const Box& bounds); - -protected: - - SpannerRenderer* _renderer; - - /// Returns the name of the class to instantiate in order to render this spanner. - virtual QByteArray getRendererClassName() const; - -private: - - Box _bounds; - float _placementGranularity; - float _voxelizationGranularity; - bool _merged; - bool _willBeVoxelized; - QHash _lastVisits; ///< last visit identifiers for each thread - QMutex _lastVisitsMutex; - - static QAtomicInt _nextVisit; ///< the global visit counter -}; - -/// Base class for objects that can render spanners. -class SpannerRenderer : public QObject { - Q_OBJECT - -public: - - Q_INVOKABLE SpannerRenderer(); - - virtual void init(Spanner* spanner); - virtual void simulate(float deltaTime); - virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false); - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - -protected: - - Spanner* _spanner; -}; - -/// An object with a 3D transform. -class Transformable : public Spanner { - Q_OBJECT - Q_PROPERTY(glm::vec3 translation MEMBER _translation WRITE setTranslation NOTIFY translationChanged) - Q_PROPERTY(glm::quat rotation MEMBER _rotation WRITE setRotation NOTIFY rotationChanged) - Q_PROPERTY(float scale MEMBER _scale WRITE setScale NOTIFY scaleChanged) - -public: - - Transformable(); - - void setTranslation(const glm::vec3& translation); - const glm::vec3& getTranslation() const { return _translation; } - - void setRotation(const glm::quat& rotation); - const glm::quat& getRotation() const { return _rotation; } - - void setScale(float scale); - float getScale() const { return _scale; } - -signals: - - void translationChanged(const glm::vec3& translation); - void rotationChanged(const glm::quat& rotation); - void scaleChanged(float scale); - -private: - - glm::vec3 _translation; - glm::quat _rotation; - float _scale; -}; - -/// A transformable object with a color. -class ColorTransformable : public Transformable { - Q_OBJECT - Q_PROPERTY(QColor color MEMBER _color WRITE setColor NOTIFY colorChanged DESIGNABLE false) - -public: - - ColorTransformable(); - - void setColor(const QColor& color); - const QColor& getColor() const { return _color; } - -signals: - - void colorChanged(const QColor& color); - -protected: - - QColor _color; -}; - -/// A sphere. -class Sphere : public ColorTransformable { - Q_OBJECT - -public: - - Q_INVOKABLE Sphere(); - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - virtual bool contains(const glm::vec3& point); - virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal); - -protected: - - virtual QByteArray getRendererClassName() const; - -private slots: - - void updateBounds(); -}; - -/// A cuboid. -class Cuboid : public ColorTransformable { - Q_OBJECT - Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged) - Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged) - -public: - - Q_INVOKABLE Cuboid(); - - void setAspectY(float aspectY); - float getAspectY() const { return _aspectY; } - - void setAspectZ(float aspectZ); - float getAspectZ() const { return _aspectZ; } - - virtual bool contains(const glm::vec3& point); - virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal); - -signals: - - void aspectYChanged(float aspectY); - void aspectZChanged(float aspectZ); - -protected: - - virtual QByteArray getRendererClassName() const; - -private slots: - - void updateBoundsAndPlanes(); - -private: - - float _aspectY; - float _aspectZ; - - static const int PLANE_COUNT = 6; - glm::vec4 _planes[PLANE_COUNT]; -}; - -/// A static 3D model loaded from the network. -class StaticModel : public Transformable { - Q_OBJECT - Q_PROPERTY(QUrl url MEMBER _url WRITE setURL NOTIFY urlChanged) - -public: - - Q_INVOKABLE StaticModel(); - - void setURL(const QUrl& url); - const QUrl& getURL() const { return _url; } - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - -signals: - - void urlChanged(const QUrl& url); - -protected: - - virtual QByteArray getRendererClassName() const; - -private: - - QUrl _url; -}; - -typedef QExplicitlySharedDataPointer DataBlockPointer; - -/// Base class for blocks of data. -class DataBlock : public QSharedData { -public: - - static const int COLOR_BYTES = 3; - - virtual ~DataBlock(); - - void setDeltaData(const DataBlockPointer& deltaData) { _deltaData = deltaData; } - const DataBlockPointer& getDeltaData() const { return _deltaData; } - - void setEncodedDelta(const QByteArray& encodedDelta) { _encodedDelta = encodedDelta; } - const QByteArray& getEncodedDelta() const { return _encodedDelta; } - - QMutex& getEncodedDeltaMutex() { return _encodedDeltaMutex; } - -protected: - - QByteArray _encoded; - QMutex _encodedMutex; - - DataBlockPointer _deltaData; - QByteArray _encodedDelta; - QMutex _encodedDeltaMutex; - - class EncodedSubdivision { - public: - DataBlockPointer ancestor; - QByteArray data; - }; - QVector _encodedSubdivisions; - QMutex _encodedSubdivisionsMutex; -}; - -/// Base class for heightfield data blocks. -class HeightfieldData : public DataBlock { -public: - - static const int SHARED_EDGE; - - HeightfieldData(int width = 0); - - int getWidth() const { return _width; } - -protected: - - int _width; -}; - -typedef QExplicitlySharedDataPointer HeightfieldHeightPointer; - -/// A block of height data associated with a heightfield. -class HeightfieldHeight : public HeightfieldData { -public: - - static const int HEIGHT_BORDER; - static const int HEIGHT_EXTENSION; - - HeightfieldHeight(int width, const QVector& contents); - HeightfieldHeight(Bitstream& in, int bytes); - HeightfieldHeight(Bitstream& in, int bytes, const HeightfieldHeightPointer& reference); - - QVector& getContents() { return _contents; } - - void write(Bitstream& out); - void writeDelta(Bitstream& out, const HeightfieldHeightPointer& reference); - -private: - - void read(Bitstream& in, int bytes); - - QVector _contents; -}; - -Q_DECLARE_METATYPE(HeightfieldHeightPointer) - -Bitstream& operator<<(Bitstream& out, const HeightfieldHeightPointer& value); -Bitstream& operator>>(Bitstream& in, HeightfieldHeightPointer& value); - -template<> void Bitstream::writeRawDelta(const HeightfieldHeightPointer& value, const HeightfieldHeightPointer& reference); -template<> void Bitstream::readRawDelta(HeightfieldHeightPointer& value, const HeightfieldHeightPointer& reference); - -/// Allows editing heightfield height blocks. -class HeightfieldHeightEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged USER true) - -public: - - HeightfieldHeightEditor(QWidget* parent = NULL); - - const HeightfieldHeightPointer& getHeight() const { return _height; } - -signals: - - void heightChanged(const HeightfieldHeightPointer& height); - -public slots: - - void setHeight(const HeightfieldHeightPointer& height); - -private slots: - - void select(); - void clear(); - -private: - - HeightfieldHeightPointer _height; - - QPushButton* _select; - QPushButton* _clear; -}; - -typedef QExplicitlySharedDataPointer HeightfieldColorPointer; - -/// A block of color data associated with a heightfield. -class HeightfieldColor : public HeightfieldData { -public: - - HeightfieldColor(int width, const QByteArray& contents); - HeightfieldColor(Bitstream& in, int bytes); - HeightfieldColor(Bitstream& in, int bytes, const HeightfieldColorPointer& reference); - - QByteArray& getContents() { return _contents; } - - void write(Bitstream& out); - void writeDelta(Bitstream& out, const HeightfieldColorPointer& reference); - -private: - - void read(Bitstream& in, int bytes); - - QByteArray _contents; -}; - -Q_DECLARE_METATYPE(HeightfieldColorPointer) - -Bitstream& operator<<(Bitstream& out, const HeightfieldColorPointer& value); -Bitstream& operator>>(Bitstream& in, HeightfieldColorPointer& value); - -template<> void Bitstream::writeRawDelta(const HeightfieldColorPointer& value, const HeightfieldColorPointer& reference); -template<> void Bitstream::readRawDelta(HeightfieldColorPointer& value, const HeightfieldColorPointer& reference); - -/// Allows editing heightfield color blocks. -class HeightfieldColorEditor : public QWidget { - Q_OBJECT - Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged USER true) - -public: - - HeightfieldColorEditor(QWidget* parent = NULL); - - const HeightfieldColorPointer& getColor() const { return _color; } - -signals: - - void colorChanged(const HeightfieldColorPointer& color); - -public slots: - - void setColor(const HeightfieldColorPointer& color); - -private slots: - - void select(); - void clear(); - -private: - - HeightfieldColorPointer _color; - - QPushButton* _select; - QPushButton* _clear; -}; - -typedef QExplicitlySharedDataPointer HeightfieldMaterialPointer; - -/// A block of material data associated with a heightfield. -class HeightfieldMaterial : public HeightfieldData { -public: - - HeightfieldMaterial(int width, const QByteArray& contents, const QVector& materials); - HeightfieldMaterial(Bitstream& in, int bytes); - HeightfieldMaterial(Bitstream& in, int bytes, const HeightfieldMaterialPointer& reference); - - QByteArray& getContents() { return _contents; } - QVector& getMaterials() { return _materials; } - - void write(Bitstream& out); - void writeDelta(Bitstream& out, const HeightfieldMaterialPointer& reference); - -private: - - void read(Bitstream& in, int bytes); - - QByteArray _contents; - QVector _materials; -}; - -Q_DECLARE_METATYPE(HeightfieldMaterialPointer) - -Bitstream& operator<<(Bitstream& out, const HeightfieldMaterialPointer& value); -Bitstream& operator>>(Bitstream& in, HeightfieldMaterialPointer& value); - -template<> void Bitstream::writeRawDelta(const HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); -template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); - -/// Contains the description of a material. -class MaterialObject : public SharedObject { - Q_OBJECT - Q_PROPERTY(QUrl diffuse MEMBER _diffuse) - Q_PROPERTY(float scaleS MEMBER _scaleS) - Q_PROPERTY(float scaleT MEMBER _scaleT) - -public: - - Q_INVOKABLE MaterialObject(); - - const QUrl& getDiffuse() const { return _diffuse; } - - float getScaleS() const { return _scaleS; } - float getScaleT() const { return _scaleT; } - -private: - - QUrl _diffuse; - float _scaleS; - float _scaleT; -}; - -/// Finds a material index for the supplied material in the provided list, adding an entry if necessary. Returns -1 -/// on failure (no room to add new material). -int getMaterialIndex(const SharedObjectPointer& material, QVector& materials); - -typedef QExplicitlySharedDataPointer HeightfieldStackPointer; - -/// A single column within a stack block. -class StackArray : public QByteArray { -public: - -#pragma pack(push, 1) - /// A single entry within the array. - class Entry { - public: - quint32 color; - uchar material; - quint32 hermiteX; - quint32 hermiteY; - quint32 hermiteZ; - - Entry(); - - bool isSet() const { return qAlpha(color) != 0; } - - bool isZero() const; - bool isMergeable(const Entry& other) const; - - void setHermiteX(const glm::vec3& normal, float position); - float getHermiteX(glm::vec3& normal) const; - - void setHermiteY(const glm::vec3& normal, float position); - float getHermiteY(glm::vec3& normal) const; - - void setHermiteZ(const glm::vec3& normal, float position); - float getHermiteZ(glm::vec3& normal) const; - }; -#pragma pack(pop) - - static int getSize(int entries) { return (entries == 0) ? 0 : sizeof(quint16) + sizeof(Entry) * entries; } - - StackArray() : QByteArray() { } - StackArray(int entries) : QByteArray(getSize(entries), 0) { } - StackArray(const QByteArray& other) : QByteArray(other) { } - StackArray(const char* src, int bytes) : QByteArray(src, bytes) { } - - int getPosition() const { return *(const quint16*)constData(); } - void setPosition(int position) { *(quint16*)data() = position; } - - quint16& getPositionRef() { return *(quint16*)data(); } - - int getEntryCount() const { return isEmpty() ? 0 : (size() - sizeof(quint16)) / sizeof(Entry); } - - Entry* getEntryData() { return (Entry*)(data() + sizeof(quint16)); } - const Entry* getEntryData() const { return (const Entry*)(constData() + sizeof(quint16)); } - - int getEntryAlpha(int y, float heightfieldHeight = 0.0f) const; - - Entry& getEntry(int y, float heightfieldHeight = 0.0f); - const Entry& getEntry(int y, float heightfieldHeight = 0.0f) const; - - void getExtents(int& minimumY, int& maximumY) const; - - bool hasSetEntries() const; - - void removeEntries(int position, int count) { remove(sizeof(quint16) + position * sizeof(Entry), count * sizeof(Entry)); } -}; - -/// A block of stack data associated with a heightfield. -class HeightfieldStack : public HeightfieldData { -public: - - HeightfieldStack(int width, const QVector& contents, const QVector& materials); - HeightfieldStack(Bitstream& in, int bytes); - HeightfieldStack(Bitstream& in, int bytes, const HeightfieldStackPointer& reference); - - QVector& getContents() { return _contents; } - QVector& getMaterials() { return _materials; } - - void write(Bitstream& out); - void writeDelta(Bitstream& out, const HeightfieldStackPointer& reference); - -private: - - void read(Bitstream& in, int bytes); - - QVector _contents; - QVector _materials; -}; - -Q_DECLARE_METATYPE(HeightfieldStackPointer) - -Bitstream& operator<<(Bitstream& out, const HeightfieldStackPointer& value); -Bitstream& operator>>(Bitstream& in, HeightfieldStackPointer& value); - -template<> void Bitstream::writeRawDelta(const HeightfieldStackPointer& value, const HeightfieldStackPointer& reference); -template<> void Bitstream::readRawDelta(HeightfieldStackPointer& value, const HeightfieldStackPointer& reference); - -typedef QExplicitlySharedDataPointer HeightfieldNodePointer; - -/// Holds the base state used in streaming heightfield data. -class HeightfieldStreamBase { -public: - Bitstream& stream; - const MetavoxelLOD& lod; - const MetavoxelLOD& referenceLOD; -}; - -/// Holds the state used in streaming a heightfield node. -class HeightfieldStreamState { -public: - HeightfieldStreamBase& base; - glm::vec2 minimum; - float size; - - bool shouldSubdivide() const; - bool shouldSubdivideReference() const; - bool becameSubdivided() const; - bool becameSubdividedOrCollapsed() const; - - void setMinimum(const glm::vec2& lastMinimum, int index); -}; - -/// A node in a heightfield quadtree. -class HeightfieldNode : public QSharedData { -public: - - static const int CHILD_COUNT = 4; - - HeightfieldNode(const HeightfieldHeightPointer& height = HeightfieldHeightPointer(), - const HeightfieldColorPointer& color = HeightfieldColorPointer(), - const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer(), - const HeightfieldStackPointer& stack = HeightfieldStackPointer()); - - HeightfieldNode(const HeightfieldNode& other); - - ~HeightfieldNode(); - - void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack); - - void setHeight(const HeightfieldHeightPointer& height) { _height = height; } - const HeightfieldHeightPointer& getHeight() const { return _height; } - - void setColor(const HeightfieldColorPointer& color) { _color = color; } - const HeightfieldColorPointer& getColor() const { return _color; } - - void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; } - const HeightfieldMaterialPointer& getMaterial() const { return _material; } - - void setStack(const HeightfieldStackPointer& stack) { _stack = stack; } - const HeightfieldStackPointer& getStack() const { return _stack; } - - void setRenderer(AbstractHeightfieldNodeRenderer* renderer) { _renderer = renderer; } - AbstractHeightfieldNodeRenderer* getRenderer() const { return _renderer; } - - bool isLeaf() const; - - void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; } - const HeightfieldNodePointer& getChild(int index) const { return _children[index]; } - - bool findRayIntersection(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - - void getRangeAfterHeightPaint(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float height, float& minimum, float& maximum) const; - - HeightfieldNode* paintHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float height, bool set, bool erase, - float normalizeScale, float normalizeOffset, float granularity); - - HeightfieldNode* fillHeight(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& position, float radius, float granularity); - - void getRangeAfterEdit(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const Box& editBounds, float& minimum, float& maximum) const; - - HeightfieldNode* setMaterial(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - Spanner* spanner, const SharedObjectPointer& material, const QColor& color, bool paint, bool voxelize, - float normalizeScale, float normalizeOffset, float granularity); - - void read(HeightfieldStreamState& state); - void write(HeightfieldStreamState& state) const; - - void readDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state); - void writeDelta(const HeightfieldNodePointer& reference, HeightfieldStreamState& state) const; - - HeightfieldNode* readSubdivision(HeightfieldStreamState& state); - void writeSubdivision(HeightfieldStreamState& state) const; - - void readSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, - const HeightfieldNode* ancestor); - void writeSubdivided(HeightfieldStreamState& state, const HeightfieldStreamState& ancestorState, - const HeightfieldNode* ancestor) const; - -private: - - void clearChildren(); - void mergeChildren(bool height = true, bool colorMaterial = true); - - QRgb getColorAt(const glm::vec3& location) const; - int getMaterialAt(const glm::vec3& location) const; - - void maybeRenormalize(const glm::vec3& scale, float normalizeScale, float normalizeOffset, int innerStackWidth, - QVector& heightContents, QVector& stackContents); - - bool findHeightfieldRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float boundsDistance, float& distance) const; - - HeightfieldNode* subdivide(const QVector& heightContents, const QVector& stackContents) const; - - HeightfieldHeightPointer _height; - HeightfieldColorPointer _color; - HeightfieldMaterialPointer _material; - HeightfieldStackPointer _stack; - - HeightfieldNodePointer _children[CHILD_COUNT]; - - AbstractHeightfieldNodeRenderer* _renderer; -}; - -/// Base class for heightfield node rendering. -class AbstractHeightfieldNodeRenderer { -public: - - virtual ~AbstractHeightfieldNodeRenderer(); - - virtual bool findRayIntersection(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale, - const glm::vec3& origin, const glm::vec3& direction, float boundsDistance, float& distance) const; -}; - -/// A heightfield represented as a spanner. -class Heightfield : public Transformable { - Q_OBJECT - Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged) - Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged) - Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged STORED false) - Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false) - Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false - DESIGNABLE false) - Q_PROPERTY(HeightfieldStackPointer stack MEMBER _stack WRITE setStack NOTIFY stackChanged STORED false - DESIGNABLE false) - -public: - - Q_INVOKABLE Heightfield(); - - void setAspectY(float aspectY); - float getAspectY() const { return _aspectY; } - - void setAspectZ(float aspectZ); - float getAspectZ() const { return _aspectZ; } - - void setHeight(const HeightfieldHeightPointer& height); - const HeightfieldHeightPointer& getHeight() const { return _height; } - - void setColor(const HeightfieldColorPointer& color); - const HeightfieldColorPointer& getColor() const { return _color; } - - void setMaterial(const HeightfieldMaterialPointer& material); - const HeightfieldMaterialPointer& getMaterial() const { return _material; } - - void setStack(const HeightfieldStackPointer& stack); - const HeightfieldStackPointer& getStack() const { return _stack; } - - void setRoot(const HeightfieldNodePointer& root) { _root = root; } - const HeightfieldNodePointer& getRoot() const { return _root; } - - MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; - - virtual SharedObject* clone(bool withID = false, SharedObject* target = NULL) const; - - virtual bool isHeightfield() const; - - virtual float getHeight(const glm::vec3& location) const; - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; - - virtual Spanner* paintHeight(const glm::vec3& position, float radius, float height, - bool set, bool erase, float granularity); - - virtual Spanner* fillHeight(const glm::vec3& position, float radius, float granularity); - - virtual Spanner* setMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material, - const QColor& color, bool paint, bool voxelize, float granularity); - - virtual bool hasOwnColors() const; - virtual bool hasOwnMaterials() const; - virtual QRgb getColorAt(const glm::vec3& point); - virtual int getMaterialAt(const glm::vec3& point); - virtual QVector& getMaterials(); - - virtual bool contains(const glm::vec3& point); - virtual bool intersects(const glm::vec3& start, const glm::vec3& end, float& distance, glm::vec3& normal); - - virtual void writeExtra(Bitstream& out) const; - virtual void readExtra(Bitstream& in, bool reread); - virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const; - virtual void readExtraDelta(Bitstream& in, const SharedObject* reference, bool reread); - virtual void maybeWriteSubdivision(Bitstream& out); - virtual SharedObject* readSubdivision(Bitstream& in); - -signals: - - void aspectYChanged(float aspectY); - void aspectZChanged(float aspectZ); - void heightChanged(const HeightfieldHeightPointer& height); - void colorChanged(const HeightfieldColorPointer& color); - void materialChanged(const HeightfieldMaterialPointer& material); - void stackChanged(const HeightfieldStackPointer& stack); - -protected: - - virtual QByteArray getRendererClassName() const; - -private slots: - - void updateBounds(); - void updateRoot(); - -private: - - Heightfield* prepareEdit(float minimumValue, float maximumValue, float& normalizeScale, float& normalizeOffset); - - float _aspectY; - float _aspectZ; - - HeightfieldHeightPointer _height; - HeightfieldColorPointer _color; - HeightfieldMaterialPointer _material; - HeightfieldStackPointer _stack; - - HeightfieldNodePointer _root; -}; - -#endif // hifi_Spanner_h diff --git a/libraries/networking/src/Assignment.cpp b/libraries/networking/src/Assignment.cpp index e01edcd003..944041730e 100644 --- a/libraries/networking/src/Assignment.cpp +++ b/libraries/networking/src/Assignment.cpp @@ -27,8 +27,6 @@ Assignment::Type Assignment::typeForNodeType(NodeType_t nodeType) { return Assignment::AgentType; case NodeType::EntityServer: return Assignment::EntityServerType; - case NodeType::MetavoxelServer: - return Assignment::MetavoxelServerType; default: return Assignment::AllTypes; } @@ -133,8 +131,6 @@ const char* Assignment::getTypeName() const { return "agent"; case Assignment::EntityServerType: return "entity-server"; - case Assignment::MetavoxelServerType: - return "metavoxel-server"; default: return "unknown"; } diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 1e620ed32b..a3b810c4ac 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -31,7 +31,7 @@ public: AgentType, UNUSED_0, UNUSED_1, - MetavoxelServerType, + UNUSED_2, EntityServerType, AllTypes }; diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 2a38799707..0304defb55 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -29,7 +29,6 @@ namespace NodeType { void NodeType::init() { TypeNameHash.insert(NodeType::DomainServer, "Domain Server"); TypeNameHash.insert(NodeType::EntityServer, "Entity Server"); - TypeNameHash.insert(NodeType::MetavoxelServer, "Metavoxel Server"); TypeNameHash.insert(NodeType::Agent, "Agent"); TypeNameHash.insert(NodeType::AudioMixer, "Audio Mixer"); TypeNameHash.insert(NodeType::AvatarMixer, "Avatar Mixer"); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index ddda947ff4..fa77540c96 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -31,7 +31,6 @@ typedef quint8 NodeType_t; namespace NodeType { const NodeType_t DomainServer = 'D'; const NodeType_t EntityServer = 'o'; // was ModelServer - const NodeType_t MetavoxelServer = 'm'; const NodeType_t EnvironmentServer = 'E'; const NodeType_t Agent = 'I'; const NodeType_t AudioMixer = 'M'; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index c8f6b6e25c..c9add10e5f 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -79,8 +79,6 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeAudioStreamStats: return 1; - case PacketTypeMetavoxelData: - return 13; default: return 0; } @@ -114,7 +112,6 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeStats); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdiction); PACKET_TYPE_NAME_LOOKUP(PacketTypeJurisdictionRequest); - PACKET_TYPE_NAME_LOOKUP(PacketTypeMetavoxelData); PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarIdentity); PACKET_TYPE_NAME_LOOKUP(PacketTypeAvatarBillboard); PACKET_TYPE_NAME_LOOKUP(PacketTypeDomainConnectRequest); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 44a464201b..c89127058f 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -42,20 +42,20 @@ enum PacketType { PacketTypeMuteEnvironment, PacketTypeAudioStreamStats, PacketTypeDataServerConfirm, // 20 - UNUSED_5, - UNUSED_6, - UNUSED_7, - UNUSED_8, - UNUSED_9, // 25 + UNUSED_1, + UNUSED_2, + UNUSED_3, + UNUSED_4, + UNUSED_5, // 25 PacketTypeOctreeStats, PacketTypeJurisdiction, PacketTypeJurisdictionRequest, - UNUSED_1, - UNUSED_2, // 30 - UNUSED_3, - UNUSED_4, + UNUSED_6, + UNUSED_7, // 30 + UNUSED_8, + UNUSED_9, PacketTypeNoisyMute, - PacketTypeMetavoxelData, + UNUSED_10, PacketTypeAvatarIdentity, // 35 PacketTypeAvatarBillboard, PacketTypeDomainConnectRequest, diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index c375f3eb52..951c36f038 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -24,7 +24,7 @@ class AbstractViewStateInterface; class PostLightingRenderable; -/// Handles deferred lighting for the bits that require it (voxels, metavoxels...) +/// Handles deferred lighting for the bits that require it (voxels...) class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 013f43530c..99d9149c3a 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -7,4 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -link_hifi_libraries(shared octree gpu model fbx entities animation audio physics metavoxels) +link_hifi_libraries(shared octree gpu model fbx entities animation audio physics) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 3bdf9a9fa9..195d3033b9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -324,7 +323,6 @@ void ScriptEngine::init() { registerAnimationTypes(this); registerAvatarTypes(this); registerAudioMetaTypes(this); - Bitstream::registerTypes(this); qScriptRegisterMetaType(this, EntityItemPropertiesToScriptValue, EntityItemPropertiesFromScriptValue); qScriptRegisterMetaType(this, EntityItemIDtoScriptValue, EntityItemIDfromScriptValue); diff --git a/tests/metavoxels/CMakeLists.txt b/tests/metavoxels/CMakeLists.txt deleted file mode 100644 index e6a62dc55c..0000000000 --- a/tests/metavoxels/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(TARGET_NAME metavoxel-tests) - -auto_mtc() - -setup_hifi_project(Network Script Widgets) - -# link in the shared libraries -link_hifi_libraries(metavoxels networking shared) - -copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp deleted file mode 100644 index 938b5470e8..0000000000 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ /dev/null @@ -1,1230 +0,0 @@ -// -// MetavoxelTests.cpp -// tests/metavoxels/src -// -// Created by Andrzej Kapolka on 2/7/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include - -#include - -#include - -#include "MetavoxelTests.h" - -REGISTER_META_OBJECT(TestSharedObjectA) -REGISTER_META_OBJECT(TestSharedObjectB) - -IMPLEMENT_ENUM_METATYPE(TestSharedObjectA, TestEnum) - -MetavoxelTests::MetavoxelTests(int& argc, char** argv) : - QCoreApplication(argc, argv) { -} - -static bool testSpanList() { - SpanList list; - - if (list.getTotalSet() != 0 || !list.getSpans().isEmpty()) { - qDebug() << "Failed empty state test."; - return true; - } - - if (list.set(-5, 15) != 10 || list.getTotalSet() != 0 || !list.getSpans().isEmpty()) { - qDebug() << "Failed initial front set."; - return true; - } - - if (list.set(5, 15) != 0 || list.getTotalSet() != 15 || list.getSpans().size() != 1 || - list.getSpans().at(0).unset != 5 || list.getSpans().at(0).set != 15) { - qDebug() << "Failed initial middle set."; - return true; - } - - if (list.set(25, 5) != 0 || list.getTotalSet() != 20 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 5 || list.getSpans().at(0).set != 15 || - list.getSpans().at(1).unset != 5 || list.getSpans().at(1).set != 5) { - qDebug() << "Failed initial end set."; - return true; - } - - if (list.set(1, 3) != 0 || list.getTotalSet() != 23 || list.getSpans().size() != 3 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 15 || - list.getSpans().at(2).unset != 5 || list.getSpans().at(2).set != 5) { - qDebug() << "Failed second front set."; - return true; - } - SpanList threeSet = list; - - if (list.set(20, 5) != 0 || list.getTotalSet() != 28 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 25) { - qDebug() << "Failed minimal join last two."; - return true; - } - - list = threeSet; - if (list.set(5, 25) != 0 || list.getTotalSet() != 28 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 25) { - qDebug() << "Failed maximal join last two."; - return true; - } - - list = threeSet; - if (list.set(10, 18) != 0 || list.getTotalSet() != 28 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 25) { - qDebug() << "Failed middle join last two."; - return true; - } - - list = threeSet; - if (list.set(10, 18) != 0 || list.getTotalSet() != 28 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 25) { - qDebug() << "Failed middle join last two."; - return true; - } - - list = threeSet; - if (list.set(2, 26) != 0 || list.getTotalSet() != 29 || list.getSpans().size() != 1 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 29) { - qDebug() << "Failed middle join three."; - return true; - } - - list = threeSet; - if (list.set(0, 2) != 4 || list.getTotalSet() != 20 || list.getSpans().size() != 2 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 15 || - list.getSpans().at(1).unset != 5 || list.getSpans().at(1).set != 5) { - qDebug() << "Failed front advance."; - return true; - } - - list = threeSet; - if (list.set(-10, 15) != 20 || list.getTotalSet() != 5 || list.getSpans().size() != 1 || - list.getSpans().at(0).unset != 5 || list.getSpans().at(0).set != 5) { - qDebug() << "Failed middle advance."; - return true; - } - - list = threeSet; - if (list.set(-10, 38) != 30 || list.getTotalSet() != 0 || list.getSpans().size() != 0) { - qDebug() << "Failed end advance."; - return true; - } - - list = threeSet; - if (list.set(-10, 100) != 90 || list.getTotalSet() != 0 || list.getSpans().size() != 0) { - qDebug() << "Failed clobber advance."; - return true; - } - - list = threeSet; - if (list.set(21, 3) != 0 || list.getTotalSet() != 26 || list.getSpans().size() != 4 || - list.getSpans().at(0).unset != 1 || list.getSpans().at(0).set != 3 || - list.getSpans().at(1).unset != 1 || list.getSpans().at(1).set != 15 || - list.getSpans().at(2).unset != 1 || list.getSpans().at(2).set != 3 || - list.getSpans().at(3).unset != 1 || list.getSpans().at(3).set != 5) { - qDebug() << "Failed adding fourth."; - return true; - } - - return false; -} - -static int datagramsSent = 0; -static int datagramsReceived = 0; -static int bytesSent = 0; -static int bytesReceived = 0; -static int maxDatagramsPerPacket = 0; -static int maxBytesPerPacket = 0; -static int groupsSent = 0; -static int maxPacketsPerGroup = 0; -static int highPriorityMessagesSent = 0; -static int highPriorityMessagesReceived = 0; -static int unreliableMessagesSent = 0; -static int unreliableMessagesReceived = 0; -static int reliableMessagesSent = 0; -static int reliableMessagesReceived = 0; -static int streamedBytesSent = 0; -static int streamedBytesReceived = 0; -static int sharedObjectsCreated = 0; -static int sharedObjectsDestroyed = 0; -static int objectMutationsPerformed = 0; -static int scriptObjectsCreated = 0; -static int scriptMutationsPerformed = 0; -static int metavoxelMutationsPerformed = 0; -static int spannerMutationsPerformed = 0; - -static QByteArray createRandomBytes(int minimumSize, int maximumSize) { - QByteArray bytes(randIntInRange(minimumSize, maximumSize), 0); - for (int i = 0; i < bytes.size(); i++) { - bytes[i] = rand(); - } - return bytes; -} - -static QByteArray createRandomBytes() { - const int MIN_BYTES = 4; - const int MAX_BYTES = 16; - return createRandomBytes(MIN_BYTES, MAX_BYTES); -} - -static TestSharedObjectA::TestEnum getRandomTestEnum() { - switch (randIntInRange(0, 2)) { - case 0: return TestSharedObjectA::FIRST_TEST_ENUM; - case 1: return TestSharedObjectA::SECOND_TEST_ENUM; - case 2: - default: return TestSharedObjectA::THIRD_TEST_ENUM; - } -} - -static TestSharedObjectA::TestFlags getRandomTestFlags() { - TestSharedObjectA::TestFlags flags = 0; - if (randomBoolean()) { - flags |= TestSharedObjectA::FIRST_TEST_FLAG; - } - if (randomBoolean()) { - flags |= TestSharedObjectA::SECOND_TEST_FLAG; - } - if (randomBoolean()) { - flags |= TestSharedObjectA::THIRD_TEST_FLAG; - } - return flags; -} - -static QScriptValue createRandomScriptValue(bool complex = false, bool ensureHashOrder = false) { - scriptObjectsCreated++; - switch (randIntInRange(0, complex ? 5 : 3)) { - case 0: - return QScriptValue(QScriptValue::NullValue); - - case 1: - return QScriptValue(randomBoolean()); - - case 2: - return QScriptValue(randFloat()); - - case 3: - return QScriptValue(QString(createRandomBytes())); - - case 4: { - int length = randIntInRange(2, 6); - QScriptValue value = DependencyManager::get()->getEngine()->newArray(length); - for (int i = 0; i < length; i++) { - value.setProperty(i, createRandomScriptValue()); - } - return value; - } - default: { - QScriptValue value = DependencyManager::get()->getEngine()->newObject(); - if (ensureHashOrder) { - // we can't depend on the iteration order, so if we need it to be the same (as when comparing bytes), we - // can only have one property - value.setProperty("foo", createRandomScriptValue()); - } else { - if (randomBoolean()) { - value.setProperty("foo", createRandomScriptValue()); - } - if (randomBoolean()) { - value.setProperty("bar", createRandomScriptValue()); - } - if (randomBoolean()) { - value.setProperty("baz", createRandomScriptValue()); - } - if (randomBoolean()) { - value.setProperty("bong", createRandomScriptValue()); - } - } - return value; - } - } -} - -static TestMessageC createRandomMessageC(bool ensureHashOrder = false) { - TestMessageC message; - message.foo = randomBoolean(); - message.bar = rand(); - message.baz = randFloat(); - message.bong.foo = createRandomBytes(); - message.bong.baz = getRandomTestEnum(); - message.bizzle = createRandomScriptValue(true, ensureHashOrder); - return message; -} - -static bool testSerialization(Bitstream::MetadataType metadataType) { - QByteArray array; - QDataStream outStream(&array, QIODevice::WriteOnly); - Bitstream out(outStream, metadataType); - SharedObjectPointer testObjectWrittenA = new TestSharedObjectA(randFloat(), TestSharedObjectA::SECOND_TEST_ENUM, - TestSharedObjectA::TestFlags(TestSharedObjectA::FIRST_TEST_FLAG | TestSharedObjectA::THIRD_TEST_FLAG)); - out << testObjectWrittenA; - SharedObjectPointer testObjectWrittenB = new TestSharedObjectB(randFloat(), createRandomBytes(), - TestSharedObjectB::THIRD_TEST_ENUM, TestSharedObjectB::SECOND_TEST_FLAG); - out << testObjectWrittenB; - TestMessageC messageWritten = createRandomMessageC(true); - out << QVariant::fromValue(messageWritten); - QByteArray endWritten = "end"; - out << endWritten; - out.flush(); - - QDataStream inStream(array); - Bitstream in(inStream, metadataType); - in.addMetaObjectSubstitution("TestSharedObjectA", &TestSharedObjectB::staticMetaObject); - in.addMetaObjectSubstitution("TestSharedObjectB", &TestSharedObjectA::staticMetaObject); - in.addTypeSubstitution("TestMessageC", TestMessageA::Type); - in.addTypeSubstitution("TestSharedObjectA::TestEnum", "TestSharedObjectB::TestEnum"); - in.addTypeSubstitution("TestSharedObjectB::TestEnum", "TestSharedObjectA::TestEnum"); - in.addTypeSubstitution("TestSharedObjectA::TestFlags", "TestSharedObjectB::TestFlags"); - in.addTypeSubstitution("TestSharedObjectB::TestFlags", "TestSharedObjectA::TestFlags"); - SharedObjectPointer testObjectReadA; - in >> testObjectReadA; - - if (!testObjectReadA || testObjectReadA->metaObject() != &TestSharedObjectB::staticMetaObject) { - qDebug() << "Wrong class for A" << testObjectReadA << metadataType; - return true; - } - if (metadataType == Bitstream::FULL_METADATA && (static_cast(testObjectWrittenA.data())->getFoo() != - static_cast(testObjectReadA.data())->getFoo() || - static_cast(testObjectReadA.data())->getBaz() != TestSharedObjectB::SECOND_TEST_ENUM || - static_cast(testObjectReadA.data())->getBong() != - TestSharedObjectB::TestFlags(TestSharedObjectB::FIRST_TEST_FLAG | TestSharedObjectB::THIRD_TEST_FLAG))) { - QDebug debug = qDebug() << "Failed to transfer shared field from A to B"; - testObjectWrittenA->dump(debug); - testObjectReadA->dump(debug); - return true; - } - - SharedObjectPointer testObjectReadB; - in >> testObjectReadB; - if (!testObjectReadB || testObjectReadB->metaObject() != &TestSharedObjectA::staticMetaObject) { - qDebug() << "Wrong class for B" << testObjectReadB << metadataType; - return true; - } - if (metadataType == Bitstream::FULL_METADATA && (static_cast(testObjectWrittenB.data())->getFoo() != - static_cast(testObjectReadB.data())->getFoo() || - static_cast(testObjectReadB.data())->getBaz() != TestSharedObjectA::THIRD_TEST_ENUM || - static_cast(testObjectReadB.data())->getBong() != TestSharedObjectA::SECOND_TEST_FLAG)) { - QDebug debug = qDebug() << "Failed to transfer shared field from B to A"; - testObjectWrittenB->dump(debug); - testObjectReadB->dump(debug); - return true; - } - - QVariant messageRead; - in >> messageRead; - if (!messageRead.isValid() || messageRead.userType() != TestMessageA::Type) { - qDebug() << "Wrong type for message" << messageRead; - return true; - } - if (metadataType == Bitstream::FULL_METADATA && messageWritten.foo != messageRead.value().foo) { - QDebug debug = qDebug() << "Failed to transfer shared field between messages" << - messageWritten.foo << messageRead.value().foo; - return true; - } - - QByteArray endRead; - in >> endRead; - if (endWritten != endRead) { - qDebug() << "End tag mismatch." << endRead; - return true; - } - - // go back to the beginning and read everything as generics - inStream.device()->seek(0); - Bitstream genericIn(inStream, metadataType, Bitstream::ALL_GENERICS); - genericIn >> testObjectReadA; - genericIn >> testObjectReadB; - genericIn >> messageRead; - genericIn >> endRead; - - // reassign the ids - testObjectReadA->setID(testObjectWrittenA->getID()); - testObjectReadA->setOriginID(testObjectWrittenA->getOriginID()); - testObjectReadB->setID(testObjectWrittenB->getID()); - testObjectReadB->setOriginID(testObjectWrittenB->getOriginID()); - - // write it back out and compare - QByteArray compareArray; - QDataStream compareOutStream(&compareArray, QIODevice::WriteOnly); - Bitstream compareOut(compareOutStream, metadataType); - compareOut << testObjectReadA; - compareOut << testObjectReadB; - compareOut << messageRead; - compareOut << endRead; - compareOut.flush(); - - if (array != compareArray) { - qDebug() << "Mismatch between written/generic written streams."; - return true; - } - - if (metadataType != Bitstream::FULL_METADATA) { - return false; - } - - // now write to JSON - JSONWriter jsonWriter; - jsonWriter << testObjectReadA; - jsonWriter << testObjectReadB; - jsonWriter << messageRead; - jsonWriter << endRead; - QByteArray encodedJson = jsonWriter.getDocument().toJson(); - - // and read from JSON - JSONReader jsonReader(QJsonDocument::fromJson(encodedJson), Bitstream::ALL_GENERICS); - jsonReader >> testObjectReadA; - jsonReader >> testObjectReadB; - jsonReader >> messageRead; - jsonReader >> endRead; - - // reassign the ids - testObjectReadA->setID(testObjectWrittenA->getID()); - testObjectReadA->setOriginID(testObjectWrittenA->getOriginID()); - testObjectReadB->setID(testObjectWrittenB->getID()); - testObjectReadB->setOriginID(testObjectWrittenB->getOriginID()); - - // and back to binary - QByteArray secondCompareArray; - QDataStream secondCompareOutStream(&secondCompareArray, QIODevice::WriteOnly); - Bitstream secondCompareOut(secondCompareOutStream, Bitstream::FULL_METADATA); - secondCompareOut << testObjectReadA; - secondCompareOut << testObjectReadB; - secondCompareOut << messageRead; - secondCompareOut << endRead; - secondCompareOut.flush(); - - if (compareArray != secondCompareArray) { - qDebug() << "Mismatch between written/JSON streams (generics)."; - return true; - } - - // once more, with mapping! - JSONReader secondJSONReader(QJsonDocument::fromJson(encodedJson)); - secondJSONReader >> testObjectReadA; - secondJSONReader >> testObjectReadB; - secondJSONReader >> messageRead; - secondJSONReader >> endRead; - - // reassign the ids - testObjectReadA->setID(testObjectWrittenA->getID()); - testObjectReadA->setOriginID(testObjectWrittenA->getOriginID()); - testObjectReadB->setID(testObjectWrittenB->getID()); - testObjectReadB->setOriginID(testObjectWrittenB->getOriginID()); - - // and back to binary - QByteArray thirdCompareArray; - QDataStream thirdCompareOutStream(&thirdCompareArray, QIODevice::WriteOnly); - Bitstream thirdCompareOut(thirdCompareOutStream, Bitstream::FULL_METADATA); - thirdCompareOut << testObjectReadA; - thirdCompareOut << testObjectReadB; - thirdCompareOut << messageRead; - thirdCompareOut << endRead; - thirdCompareOut.flush(); - - if (compareArray != thirdCompareArray) { - qDebug() << "Mismatch between written/JSON streams (mapped)."; - return true; - } - - return false; -} - -bool MetavoxelTests::run() { - DependencyManager::set(); - - // seed the random number generator so that our tests are reproducible - srand(0xBAAAAABE); - - // register our test attribute - AttributePointer testAttribute = AttributeRegistry::getInstance()->registerAttribute(new FloatAttribute("testAttribute")); - - // check for an optional command line argument specifying a single test - QStringList arguments = this->arguments(); - int test = (arguments.size() > 1) ? arguments.at(1).toInt() : 0; - - if (test == 0 || test == 1) { - qDebug() << "Running SpanList test..."; - qDebug(); - - if (testSpanList()) { - return true; - } - } - - const int SIMULATION_ITERATIONS = 10000; - if (test == 0 || test == 2) { - qDebug() << "Running transmission test..."; - qDebug(); - - // create two endpoints with the same header - TestEndpoint alice, bob; - - alice.setOther(&bob); - bob.setOther(&alice); - - // perform a large number of simulation iterations - for (int i = 0; i < SIMULATION_ITERATIONS; i++) { - if (alice.simulate(i) || bob.simulate(i)) { - return true; - } - } - - qDebug() << "Sent" << highPriorityMessagesSent << "high priority messages, received" << highPriorityMessagesReceived; - qDebug() << "Sent" << unreliableMessagesSent << "unreliable messages, received" << unreliableMessagesReceived; - qDebug() << "Sent" << reliableMessagesSent << "reliable messages, received" << reliableMessagesReceived; - qDebug() << "Sent" << streamedBytesSent << "streamed bytes, received" << streamedBytesReceived; - qDebug() << "Sent" << datagramsSent << "datagrams with" << bytesSent << "bytes, received" << - datagramsReceived << "with" << bytesReceived << "bytes"; - qDebug() << "Max" << maxDatagramsPerPacket << "datagrams," << maxBytesPerPacket << "bytes per packet"; - qDebug() << "Created" << sharedObjectsCreated << "shared objects, destroyed" << sharedObjectsDestroyed; - qDebug() << "Performed" << objectMutationsPerformed << "object mutations"; - qDebug() << "Created" << scriptObjectsCreated << "script objects, mutated" << scriptMutationsPerformed; - qDebug(); - } - - if (test == 0 || test == 3) { - qDebug() << "Running congestion control test..."; - qDebug(); - - // clear the stats - streamedBytesSent = streamedBytesReceived = datagramsSent = bytesSent = 0; - datagramsReceived = bytesReceived = maxDatagramsPerPacket = maxBytesPerPacket = 0; - - // create two endpoints with the same header - TestEndpoint alice(TestEndpoint::CONGESTION_MODE), bob(TestEndpoint::CONGESTION_MODE); - - alice.setOther(&bob); - bob.setOther(&alice); - - // perform a large number of simulation iterations - for (int i = 0; i < SIMULATION_ITERATIONS; i++) { - if (alice.simulate(i) || bob.simulate(i)) { - return true; - } - } - - qDebug() << "Sent" << streamedBytesSent << "streamed bytes, received" << streamedBytesReceived; - qDebug() << "Sent" << datagramsSent << "datagrams in" << groupsSent << "groups with" << bytesSent << - "bytes, received" << datagramsReceived << "with" << bytesReceived << "bytes"; - qDebug() << "Max" << maxDatagramsPerPacket << "datagrams," << maxBytesPerPacket << "bytes per packet"; - qDebug() << "Max" << maxPacketsPerGroup << "packets per group"; - qDebug() << "Average" << (bytesReceived / datagramsReceived) << "bytes per datagram," << - (datagramsSent / groupsSent) << "datagrams per group"; - qDebug() << "Speed:" << (bytesReceived / SIMULATION_ITERATIONS) << "bytes per iteration"; - qDebug() << "Efficiency:" << ((float)streamedBytesReceived / bytesReceived); - } - - if (test == 0 || test == 4) { - qDebug() << "Running serialization test..."; - qDebug(); - - if (testSerialization(Bitstream::HASH_METADATA) || testSerialization(Bitstream::FULL_METADATA)) { - return true; - } - } - - if (test == 0 || test == 5) { - qDebug() << "Running metavoxel data test..."; - qDebug(); - - // clear the stats - datagramsSent = bytesSent = datagramsReceived = bytesReceived = maxDatagramsPerPacket = maxBytesPerPacket = 0; - - // create client and server endpoints - TestEndpoint client(TestEndpoint::METAVOXEL_CLIENT_MODE); - TestEndpoint server(TestEndpoint::METAVOXEL_SERVER_MODE); - - client.setOther(&server); - server.setOther(&client); - - // simulate - for (int i = 0; i < SIMULATION_ITERATIONS; i++) { - if (client.simulate(i) || server.simulate(i)) { - return true; - } - } - - qDebug() << "Sent" << datagramsSent << "datagrams with" << bytesSent << "bytes, received" << - datagramsReceived << "with" << bytesReceived << "bytes"; - qDebug() << "Max" << maxDatagramsPerPacket << "datagrams," << maxBytesPerPacket << "bytes per packet"; - qDebug() << "Performed" << metavoxelMutationsPerformed << "metavoxel mutations," << spannerMutationsPerformed << - "spanner mutations"; - } - - qDebug() << "All tests passed!"; - - return false; -} - -static SharedObjectPointer createRandomSharedObject() { - switch (randIntInRange(0, 2)) { - case 0: return new TestSharedObjectA(randFloat(), getRandomTestEnum(), getRandomTestFlags()); - case 1: return new TestSharedObjectB(); - case 2: - default: return SharedObjectPointer(); - } -} - -class RandomVisitor : public MetavoxelVisitor { -public: - - int leafCount; - - RandomVisitor(); - virtual int visit(MetavoxelInfo& info); -}; - -RandomVisitor::RandomVisitor() : - MetavoxelVisitor(QVector(), QVector() << - AttributeRegistry::getInstance()->getAttribute("testAttribute")), - leafCount(0) { -} - -const float MAXIMUM_LEAF_SIZE = 0.5f; -const float MINIMUM_LEAF_SIZE = 0.25f; - -int RandomVisitor::visit(MetavoxelInfo& info) { - if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) { - return DEFAULT_ORDER; - } - info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline(randFloat())); - leafCount++; - return STOP_RECURSION; -} - -class TestSendRecord : public PacketRecord { -public: - - TestSendRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), - const SharedObjectPointer& localState = SharedObjectPointer()); - - const SharedObjectPointer& getLocalState() const { return _localState; } - -private: - - SharedObjectPointer _localState; -}; - -TestSendRecord::TestSendRecord(int packetNumber, const MetavoxelLOD& lod, const MetavoxelData& data, - const SharedObjectPointer& localState) : - PacketRecord(packetNumber, lod, data), - _localState(localState) { -} - -class TestReceiveRecord : public PacketRecord { -public: - - TestReceiveRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), - const MetavoxelData& data = MetavoxelData(), const SharedObjectPointer& remoteState = SharedObjectPointer()); - - const SharedObjectPointer& getRemoteState() const { return _remoteState; } - -private: - - SharedObjectPointer _remoteState; -}; - -TestReceiveRecord::TestReceiveRecord(int packetNumber, const MetavoxelLOD& lod, - const MetavoxelData& data, const SharedObjectPointer& remoteState) : - PacketRecord(packetNumber, lod, data), - _remoteState(remoteState) { -} - -TestEndpoint::TestEndpoint(Mode mode) : - Endpoint(SharedNodePointer(), new TestSendRecord(), new TestReceiveRecord()), - _mode(mode), - _highPriorityMessagesToSend(0.0f), - _reliableMessagesToSend(0.0f), - _reliableDeltaChannel(NULL), - _reliableDeltaID(0) { - - connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), - SLOT(handleHighPriorityMessage(const QVariant&))); - connect(_sequencer.getReliableInputChannel(), SIGNAL(receivedMessage(const QVariant&, Bitstream&)), - SLOT(handleReliableMessage(const QVariant&, Bitstream&))); - - if (mode == METAVOXEL_CLIENT_MODE) { - _lod = MetavoxelLOD(glm::vec3(), 0.01f); - connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX), - SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleReliableMessage(const QVariant&, Bitstream&))); - return; - } - if (mode == METAVOXEL_SERVER_MODE) { - connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived())); - - _data.expand(); - _data.expand(); - - RandomVisitor visitor; - _data.guide(visitor); - qDebug() << "Created" << visitor.leafCount << "base leaves"; - - _data.insert(AttributeRegistry::getInstance()->getSpannersAttribute(), new Sphere()); - - _sphere = new Sphere(); - static_cast(_sphere.data())->setScale(0.01f); - _data.insert(AttributeRegistry::getInstance()->getSpannersAttribute(), _sphere); - return; - } - // create the object that represents out delta-encoded state - _localState = new TestSharedObjectA(); - - ReliableChannel* secondInput = _sequencer.getReliableInputChannel(1); - secondInput->setMessagesEnabled(false); - connect(&secondInput->getBuffer(), SIGNAL(readyRead()), SLOT(readReliableChannel())); - - // enqueue a large amount of data in a low-priority channel - ReliableChannel* output = _sequencer.getReliableOutputChannel(1); - output->setPriority(0.25f); - output->setMessagesEnabled(false); - QByteArray bytes; - if (mode == CONGESTION_MODE) { - const int HUGE_STREAM_BYTES = 60 * 1024 * 1024; - bytes = createRandomBytes(HUGE_STREAM_BYTES, HUGE_STREAM_BYTES); - - // initialize the pipeline - for (int i = 0; i < 10; i++) { - _pipeline.append(ByteArrayVector()); - } - _remainingPipelineCapacity = 100 * 1024; - - } else { - const int MIN_STREAM_BYTES = 100000; - const int MAX_STREAM_BYTES = 200000; - bytes = createRandomBytes(MIN_STREAM_BYTES, MAX_STREAM_BYTES); - } - _dataStreamed.append(bytes); - output->getBuffer().write(bytes); - streamedBytesSent += bytes.size(); -} - -static QVariant createRandomMessage() { - switch (randIntInRange(0, 2)) { - case 0: { - TestMessageA message = { randomBoolean(), rand(), randFloat() }; - return QVariant::fromValue(message); - } - case 1: { - TestMessageB message = { createRandomBytes(), createRandomSharedObject(), getRandomTestEnum() }; - return QVariant::fromValue(message); - } - default: { - return QVariant::fromValue(createRandomMessageC()); - } - } -} - -static SharedObjectPointer mutate(const SharedObjectPointer& state) { - switch (randIntInRange(0, 4)) { - case 0: { - SharedObjectPointer newState = state->clone(true); - static_cast(newState.data())->setFoo(randFloat()); - objectMutationsPerformed++; - return newState; - } - case 1: { - SharedObjectPointer newState = state->clone(true); - static_cast(newState.data())->setBaz(getRandomTestEnum()); - objectMutationsPerformed++; - return newState; - } - case 2: { - SharedObjectPointer newState = state->clone(true); - static_cast(newState.data())->setBong(getRandomTestFlags()); - objectMutationsPerformed++; - return newState; - } - case 3: { - SharedObjectPointer newState = state->clone(true); - QScriptValue oldValue = static_cast(newState.data())->getBizzle(); - QScriptValue newValue = DependencyManager::get()->getEngine()->newObject(); - for (QScriptValueIterator it(oldValue); it.hasNext(); ) { - it.next(); - newValue.setProperty(it.scriptName(), it.value()); - } - switch (randIntInRange(0, 2)) { - case 0: { - QScriptValue oldArray = oldValue.property("foo"); - int oldLength = oldArray.property(DependencyManager::get()->getLengthString()).toInt32(); - QScriptValue newArray = DependencyManager::get()->getEngine()->newArray(oldLength); - for (int i = 0; i < oldLength; i++) { - newArray.setProperty(i, oldArray.property(i)); - } - newArray.setProperty(randIntInRange(0, oldLength - 1), createRandomScriptValue(true)); - break; - } - case 1: - newValue.setProperty("bar", QScriptValue(randFloat())); - break; - - default: - newValue.setProperty("baz", createRandomScriptValue(true)); - break; - } - static_cast(newState.data())->setBizzle(newValue); - scriptMutationsPerformed++; - objectMutationsPerformed++; - return newState; - } - default: - return state; - } -} - -static bool messagesEqual(const QVariant& firstMessage, const QVariant& secondMessage) { - int type = firstMessage.userType(); - if (secondMessage.userType() != type) { - return false; - } - if (type == TestMessageA::Type) { - return firstMessage.value() == secondMessage.value(); - - } else if (type == TestMessageB::Type) { - TestMessageB first = firstMessage.value(); - TestMessageB second = secondMessage.value(); - return first.foo == second.foo && equals(first.bar, second.bar) && first.baz == second.baz; - - } else if (type == TestMessageC::Type) { - return firstMessage.value() == secondMessage.value(); - - } else { - return firstMessage == secondMessage; - } -} - -class MutateVisitor : public MetavoxelVisitor { -public: - - MutateVisitor(); - virtual int visit(MetavoxelInfo& info); - -private: - - int _mutationsRemaining; -}; - -MutateVisitor::MutateVisitor() : - MetavoxelVisitor(QVector(), QVector() << - AttributeRegistry::getInstance()->getAttribute("testAttribute")), - _mutationsRemaining(randIntInRange(2, 4)) { -} - -int MutateVisitor::visit(MetavoxelInfo& info) { - if (_mutationsRemaining <= 0) { - return STOP_RECURSION; - } - if (info.size > MAXIMUM_LEAF_SIZE || (info.size > MINIMUM_LEAF_SIZE && randomBoolean())) { - return encodeRandomOrder(); - } - info.outputValues[0] = OwnedAttributeValue(_outputs.at(0), encodeInline(randFloat())); - _mutationsRemaining--; - metavoxelMutationsPerformed++; - return STOP_RECURSION; -} - -bool TestEndpoint::simulate(int iterationNumber) { - // update/send our delayed datagrams - for (QList::iterator it = _delayedDatagrams.begin(); it != _delayedDatagrams.end(); ) { - if (it->second-- == 1) { - _other->parseData(it->first); - it = _delayedDatagrams.erase(it); - - } else { - it++; - } - } - - int oldDatagramsSent = datagramsSent; - int oldBytesSent = bytesSent; - if (_mode == CONGESTION_MODE) { - // cycle our pipeline - ByteArrayVector datagrams = _pipeline.takeLast(); - _pipeline.prepend(ByteArrayVector()); - foreach (const QByteArray& datagram, datagrams) { - _sequencer.receivedDatagram(datagram); - datagramsReceived++; - bytesReceived += datagram.size(); - _remainingPipelineCapacity += datagram.size(); - } - int packetCount = _sequencer.notePacketGroup(); - groupsSent++; - maxPacketsPerGroup = qMax(maxPacketsPerGroup, packetCount); - for (int i = 0; i < packetCount; i++) { - oldDatagramsSent = datagramsSent; - oldBytesSent = bytesSent; - - Bitstream& out = _sequencer.startPacket(); - out << QVariant(); - _sequencer.endPacket(); - - maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent); - maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent); - } - return false; - - } else if (_mode == METAVOXEL_CLIENT_MODE) { - Bitstream& out = _sequencer.startPacket(); - - ClientStateMessage state = { _lod }; - out << QVariant::fromValue(state); - _sequencer.endPacket(); - - } else if (_mode == METAVOXEL_SERVER_MODE) { - // make a random change - MutateVisitor visitor; - _data.guide(visitor); - - // perhaps mutate the spanner - if (randomBoolean()) { - SharedObjectPointer oldSphere = _sphere; - _sphere = _sphere->clone(true); - Sphere* newSphere = static_cast(_sphere.data()); - if (randomBoolean()) { - newSphere->setColor(QColor(randomColorValue(), randomColorValue(), randomColorValue())); - } else { - newSphere->setTranslation(newSphere->getTranslation() + glm::vec3(randFloatInRange(-0.01f, 0.01f), - randFloatInRange(-0.01f, 0.01f), randFloatInRange(-0.01f, 0.01f))); - } - _data.replace(AttributeRegistry::getInstance()->getSpannersAttribute(), oldSphere, _sphere); - spannerMutationsPerformed++; - } - - // wait until we have a valid lod before sending - if (!_lod.isValid()) { - return false; - } - // if we're sending a reliable delta, wait until it's acknowledged - if (_reliableDeltaChannel) { - Bitstream& out = _sequencer.startPacket(); - MetavoxelDeltaPendingMessage msg = { _reliableDeltaID }; - out << QVariant::fromValue(msg); - _sequencer.endPacket(); - return false; - } - Bitstream& out = _sequencer.startPacket(); - int start = _sequencer.getOutputStream().getUnderlying().device()->pos(); - out << QVariant::fromValue(MetavoxelDeltaMessage()); - PacketRecord* sendRecord = getLastAcknowledgedSendRecord(); - _data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); - out.flush(); - int end = _sequencer.getOutputStream().getUnderlying().device()->pos(); - if (end > _sequencer.getMaxPacketSize()) { - // we need to send the delta on the reliable channel - _reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - _reliableDeltaChannel->startMessage(); - _reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start); - _reliableDeltaChannel->endMessage(); - - _reliableDeltaWriteMappings = out.getAndResetWriteMappings(); - _reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten(); - _reliableDeltaData = _data; - _reliableDeltaLOD = _lod; - - _sequencer.getOutputStream().getUnderlying().device()->seek(start); - MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID }; - out << QVariant::fromValue(msg); - _sequencer.endPacket(); - - } else { - _sequencer.endPacket(); - } - } else { - // enqueue some number of high priority messages - const float MIN_HIGH_PRIORITY_MESSAGES = 0.0f; - const float MAX_HIGH_PRIORITY_MESSAGES = 2.0f; - _highPriorityMessagesToSend += randFloatInRange(MIN_HIGH_PRIORITY_MESSAGES, MAX_HIGH_PRIORITY_MESSAGES); - while (_highPriorityMessagesToSend >= 1.0f) { - QVariant message = createRandomMessage(); - _highPriorityMessagesSent.append(message); - _sequencer.sendHighPriorityMessage(message); - highPriorityMessagesSent++; - _highPriorityMessagesToSend -= 1.0f; - } - - // and some number of reliable messages - const float MIN_RELIABLE_MESSAGES = 0.0f; - const float MAX_RELIABLE_MESSAGES = 4.0f; - _reliableMessagesToSend += randFloatInRange(MIN_RELIABLE_MESSAGES, MAX_RELIABLE_MESSAGES); - while (_reliableMessagesToSend >= 1.0f) { - QVariant message = createRandomMessage(); - _reliableMessagesSent.append(message); - _sequencer.getReliableOutputChannel()->sendMessage(message); - reliableMessagesSent++; - _reliableMessagesToSend -= 1.0f; - } - - // tweak the local state - _localState = mutate(_localState); - - // send a packet - try { - Bitstream& out = _sequencer.startPacket(); - SequencedTestMessage message = { iterationNumber, createRandomMessage(), _localState }; - _unreliableMessagesSent.append(message); - unreliableMessagesSent++; - out << message; - _sequencer.endPacket(); - - } catch (const QString& message) { - qDebug() << message; - return true; - } - } - maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent); - maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent); - return false; -} - -int TestEndpoint::parseData(const QByteArray& packet) { - if (_mode == CONGESTION_MODE) { - if (packet.size() <= _remainingPipelineCapacity) { - // have to copy the datagram; the one we're passed is a reference to a shared buffer - _pipeline[0].append(QByteArray(packet.constData(), packet.size())); - _remainingPipelineCapacity -= packet.size(); - } - } else { - _sequencer.receivedDatagram(packet); - datagramsReceived++; - bytesReceived += packet.size(); - } - return packet.size(); -} - -void TestEndpoint::sendDatagram(const QByteArray& datagram) { - datagramsSent++; - bytesSent += datagram.size(); - - // some datagrams are dropped - const float DROP_PROBABILITY = 0.1f; - float probabilityMultiplier = (_mode == CONGESTION_MODE) ? 0.01f : 1.0f; - if (randFloat() < DROP_PROBABILITY * probabilityMultiplier) { - return; - } - - // some are received out of order - const float REORDER_PROBABILITY = 0.1f; - if (randFloat() < REORDER_PROBABILITY * probabilityMultiplier) { - const int MIN_DELAY = 2; - const int MAX_DELAY = 5; - // have to copy the datagram; the one we're passed is a reference to a shared buffer - _delayedDatagrams.append(ByteArrayIntPair(QByteArray(datagram.constData(), datagram.size()), - randIntInRange(MIN_DELAY, MAX_DELAY))); - - // and some are duplicated - const float DUPLICATE_PROBABILITY = 0.01f; - if (randFloat() > DUPLICATE_PROBABILITY * probabilityMultiplier) { - return; - } - } - - _delayedDatagrams.append(ByteArrayIntPair(QByteArray(datagram.constData(), datagram.size()), 1)); -} - -void TestEndpoint::readMessage(Bitstream& in) { - if (_mode == CONGESTION_MODE) { - QVariant message; - in >> message; - return; - } - if (_mode == METAVOXEL_CLIENT_MODE) { - QVariant message; - in >> message; - handleMessage(message, in); - return; - } - if (_mode == METAVOXEL_SERVER_MODE) { - QVariant message; - in >> message; - handleMessage(message, in); - return; - } - SequencedTestMessage message; - in >> message; - - _remoteState = message.state; - - for (QList::iterator it = _other->_unreliableMessagesSent.begin(); - it != _other->_unreliableMessagesSent.end(); it++) { - if (it->sequenceNumber == message.sequenceNumber) { - if (!messagesEqual(it->submessage, message.submessage)) { - qDebug() << "Sent/received unreliable message mismatch."; - exit(true); - } - if (!it->state->equals(message.state)) { - qDebug() << "Delta-encoded object mismatch."; - exit(true); - } - _other->_unreliableMessagesSent.erase(_other->_unreliableMessagesSent.begin(), it + 1); - unreliableMessagesReceived++; - return; - } - } - qDebug() << "Received unsent/already sent unreliable message."; - exit(true); -} - -void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) { - int userType = message.userType(); - if (userType == ClientStateMessage::Type) { - ClientStateMessage state = message.value(); - _lod = state.lod; - - } else if (userType == MetavoxelDeltaMessage::Type) { - PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); - _remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, - _remoteDataLOD = getLastAcknowledgedSendRecord()->getLOD()); - in.reset(); - _data = _remoteData; - compareMetavoxelData(); - - } else if (userType == MetavoxelDeltaPendingMessage::Type) { - int id = message.value().id; - if (id > _reliableDeltaID) { - _reliableDeltaID = id; - _reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream()); - _reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD(); - PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); - _remoteDataLOD = receiveRecord->getLOD(); - _remoteData = receiveRecord->getData(); - } - } else if (userType == QMetaType::QVariantList) { - foreach (const QVariant& element, message.toList()) { - handleMessage(element, in); - } - } -} - -PacketRecord* TestEndpoint::maybeCreateSendRecord() const { - if (_reliableDeltaChannel) { - return new TestSendRecord(_sequencer.getOutgoingPacketNumber(), _reliableDeltaLOD, _reliableDeltaData, _localState); - } - return new TestSendRecord(_sequencer.getOutgoingPacketNumber(), _lod, - (_mode == METAVOXEL_CLIENT_MODE) ? MetavoxelData() : _data, _localState); -} - -PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const { - return new TestReceiveRecord(_sequencer.getIncomingPacketNumber(), _remoteDataLOD, _remoteData, _remoteState); -} - -void TestEndpoint::handleHighPriorityMessage(const QVariant& message) { - if (message.userType() == ClearSharedObjectMessage::Type) { - return; - } - if (_other->_highPriorityMessagesSent.isEmpty()) { - throw QString("Received unsent/already sent high priority message."); - } - QVariant sentMessage = _other->_highPriorityMessagesSent.takeFirst(); - if (!messagesEqual(message, sentMessage)) { - throw QString("Sent/received high priority message mismatch."); - } - highPriorityMessagesReceived++; -} - -void TestEndpoint::handleReliableMessage(const QVariant& message, Bitstream& in) { - if (message.userType() == MetavoxelDeltaMessage::Type) { - PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); - _remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _remoteDataLOD = _reliableDeltaLOD); - _sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings()); - in.clearPersistentMappings(); - _data = _remoteData; - compareMetavoxelData(); - _reliableDeltaChannel = NULL; - return; - } - if (message.userType() == ClearSharedObjectMessage::Type || - message.userType() == ClearMainChannelSharedObjectMessage::Type) { - return; - } - if (_other->_reliableMessagesSent.isEmpty()) { - throw QString("Received unsent/already sent reliable message."); - } - QVariant sentMessage = _other->_reliableMessagesSent.takeFirst(); - if (!messagesEqual(message, sentMessage)) { - throw QString("Sent/received reliable message mismatch."); - } - reliableMessagesReceived++; -} - -void TestEndpoint::readReliableChannel() { - CircularBuffer& buffer = _sequencer.getReliableInputChannel(1)->getBuffer(); - QByteArray bytes = buffer.read(buffer.bytesAvailable()); - if (_other->_dataStreamed.size() < bytes.size()) { - throw QString("Received unsent/already sent streamed data."); - } - QByteArray compare = _other->_dataStreamed.readBytes(0, bytes.size()); - _other->_dataStreamed.remove(bytes.size()); - if (compare != bytes) { - throw QString("Sent/received streamed data mismatch."); - } - streamedBytesReceived += bytes.size(); -} - -void TestEndpoint::checkReliableDeltaReceived() { - if (!_reliableDeltaChannel || _reliableDeltaChannel->getOffset() < _reliableDeltaReceivedOffset) { - return; - } - _sequencer.getOutputStream().persistWriteMappings(_reliableDeltaWriteMappings); - _reliableDeltaWriteMappings = Bitstream::WriteMappings(); - _reliableDeltaData = MetavoxelData(); - _reliableDeltaChannel = NULL; -} - -void TestEndpoint::compareMetavoxelData() { - // deep-compare data to sent version - int packetNumber = _sequencer.getIncomingPacketNumber(); - foreach (PacketRecord* record, _other->_sendRecords) { - TestSendRecord* sendRecord = static_cast(record); - if (sendRecord->getPacketNumber() == packetNumber) { - if (!sendRecord->getData().deepEquals(_data, getLastAcknowledgedSendRecord()->getLOD())) { - qDebug() << "Sent/received metavoxel data mismatch."; - exit(true); - } - return; - } - } - qDebug() << "Received metavoxel data with no corresponding send." << packetNumber; - exit(true); -} - -TestSharedObjectA::TestSharedObjectA(float foo, TestEnum baz, TestFlags bong) : - _foo(foo), - _baz(baz), - _bong(bong) { - sharedObjectsCreated++; - - _bizzle = DependencyManager::get()->getEngine()->newObject(); - _bizzle.setProperty("foo", DependencyManager::get()->getEngine()->newArray(4)); -} - -TestSharedObjectA::~TestSharedObjectA() { - sharedObjectsDestroyed++; -} - -void TestSharedObjectA::setFoo(float foo) { - if (_foo != foo) { - emit fooChanged(_foo = foo); - } -} - -TestSharedObjectB::TestSharedObjectB(float foo, const QByteArray& bar, TestEnum baz, TestFlags bong) : - _foo(foo), - _bar(bar), - _baz(baz), - _bong(bong) { - sharedObjectsCreated++; -} - -TestSharedObjectB::~TestSharedObjectB() { - sharedObjectsDestroyed++; -} diff --git a/tests/metavoxels/src/MetavoxelTests.h b/tests/metavoxels/src/MetavoxelTests.h deleted file mode 100644 index ce357fbb90..0000000000 --- a/tests/metavoxels/src/MetavoxelTests.h +++ /dev/null @@ -1,251 +0,0 @@ -// -// MetavoxelTests.h -// tests/metavoxels/src -// -// Created by Andrzej Kapolka on 2/7/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MetavoxelTests_h -#define hifi_MetavoxelTests_h - -#include -#include - -#include -#include - -class SequencedTestMessage; - -/// Tests various aspects of the metavoxel library. -class MetavoxelTests : public QCoreApplication { - Q_OBJECT - -public: - - MetavoxelTests(int& argc, char** argv); - - /// Performs our various tests. - /// \return true if any of the tests failed. - bool run(); -}; - -/// Represents a simulated endpoint. -class TestEndpoint : public Endpoint { - Q_OBJECT - -public: - - enum Mode { BASIC_PEER_MODE, CONGESTION_MODE, METAVOXEL_SERVER_MODE, METAVOXEL_CLIENT_MODE }; - - TestEndpoint(Mode mode = BASIC_PEER_MODE); - - void setOther(TestEndpoint* other) { _other = other; } - - /// Perform a simulation step. - /// \return true if failure was detected - bool simulate(int iterationNumber); - - virtual int parseData(const QByteArray& packet); - -protected: - - virtual void sendDatagram(const QByteArray& data); - virtual void readMessage(Bitstream& in); - - virtual void handleMessage(const QVariant& message, Bitstream& in); - - virtual PacketRecord* maybeCreateSendRecord() const; - virtual PacketRecord* maybeCreateReceiveRecord() const; - -private slots: - - void handleHighPriorityMessage(const QVariant& message); - void handleReliableMessage(const QVariant& message, Bitstream& in); - void readReliableChannel(); - void checkReliableDeltaReceived(); - -private: - - void compareMetavoxelData(); - - Mode _mode; - - SharedObjectPointer _localState; - SharedObjectPointer _remoteState; - - MetavoxelData _data; - MetavoxelLOD _dataLOD; - MetavoxelData _remoteData; - MetavoxelLOD _remoteDataLOD; - MetavoxelLOD _lod; - - SharedObjectPointer _sphere; - - TestEndpoint* _other; - - typedef QPair ByteArrayIntPair; - QList _delayedDatagrams; - - typedef QVector ByteArrayVector; - QList _pipeline; - int _remainingPipelineCapacity; - - float _highPriorityMessagesToSend; - QVariantList _highPriorityMessagesSent; - QList _unreliableMessagesSent; - float _reliableMessagesToSend; - QVariantList _reliableMessagesSent; - CircularBuffer _dataStreamed; - - ReliableChannel* _reliableDeltaChannel; - int _reliableDeltaReceivedOffset; - MetavoxelData _reliableDeltaData; - MetavoxelLOD _reliableDeltaLOD; - Bitstream::WriteMappings _reliableDeltaWriteMappings; - int _reliableDeltaID; -}; - -/// A simple shared object. -class TestSharedObjectA : public SharedObject { - Q_OBJECT - Q_ENUMS(TestEnum) - Q_FLAGS(TestFlag TestFlags) - Q_PROPERTY(float foo READ getFoo WRITE setFoo NOTIFY fooChanged) - Q_PROPERTY(TestEnum baz READ getBaz WRITE setBaz) - Q_PROPERTY(TestFlags bong READ getBong WRITE setBong) - Q_PROPERTY(QScriptValue bizzle READ getBizzle WRITE setBizzle) - -public: - - enum TestEnum { FIRST_TEST_ENUM, SECOND_TEST_ENUM, THIRD_TEST_ENUM }; - - enum TestFlag { NO_TEST_FLAGS = 0x0, FIRST_TEST_FLAG = 0x01, SECOND_TEST_FLAG = 0x02, THIRD_TEST_FLAG = 0x04 }; - Q_DECLARE_FLAGS(TestFlags, TestFlag) - - Q_INVOKABLE TestSharedObjectA(float foo = 0.0f, TestEnum baz = FIRST_TEST_ENUM, TestFlags bong = 0); - virtual ~TestSharedObjectA(); - - void setFoo(float foo); - float getFoo() const { return _foo; } - - void setBaz(TestEnum baz) { _baz = baz; } - TestEnum getBaz() const { return _baz; } - - void setBong(TestFlags bong) { _bong = bong; } - TestFlags getBong() const { return _bong; } - - void setBizzle(const QScriptValue& bizzle) { _bizzle = bizzle; } - const QScriptValue& getBizzle() const { return _bizzle; } - -signals: - - void fooChanged(float foo); - -private: - - float _foo; - TestEnum _baz; - TestFlags _bong; - QScriptValue _bizzle; -}; - -DECLARE_ENUM_METATYPE(TestSharedObjectA, TestEnum) - -/// Another simple shared object. -class TestSharedObjectB : public SharedObject { - Q_OBJECT - Q_ENUMS(TestEnum) - Q_FLAGS(TestFlag TestFlags) - Q_PROPERTY(float foo READ getFoo WRITE setFoo) - Q_PROPERTY(QByteArray bar READ getBar WRITE setBar) - Q_PROPERTY(TestEnum baz READ getBaz WRITE setBaz) - Q_PROPERTY(TestFlags bong READ getBong WRITE setBong) - -public: - - enum TestEnum { ZEROTH_TEST_ENUM, FIRST_TEST_ENUM, SECOND_TEST_ENUM, THIRD_TEST_ENUM, FOURTH_TEST_ENUM }; - - enum TestFlag { NO_TEST_FLAGS = 0x0, ZEROTH_TEST_FLAG = 0x01, FIRST_TEST_FLAG = 0x02, - SECOND_TEST_FLAG = 0x04, THIRD_TEST_FLAG = 0x08, FOURTH_TEST_FLAG = 0x10 }; - Q_DECLARE_FLAGS(TestFlags, TestFlag) - - Q_INVOKABLE TestSharedObjectB(float foo = 0.0f, const QByteArray& bar = QByteArray(), - TestEnum baz = FIRST_TEST_ENUM, TestFlags bong = 0); - virtual ~TestSharedObjectB(); - - void setFoo(float foo) { _foo = foo; } - float getFoo() const { return _foo; } - - void setBar(const QByteArray& bar) { _bar = bar; } - const QByteArray& getBar() const { return _bar; } - - void setBaz(TestEnum baz) { _baz = baz; } - TestEnum getBaz() const { return _baz; } - - void setBong(TestFlags bong) { _bong = bong; } - TestFlags getBong() const { return _bong; } - -private: - - float _foo; - QByteArray _bar; - TestEnum _baz; - TestFlags _bong; -}; - -/// A simple test message. -class TestMessageA { - STREAMABLE - -public: - - STREAM bool foo; - STREAM int bar; - STREAM float baz; -}; - -DECLARE_STREAMABLE_METATYPE(TestMessageA) - -// Another simple test message. -class TestMessageB { - STREAMABLE - -public: - - STREAM QByteArray foo; - STREAM SharedObjectPointer bar; - STREAM TestSharedObjectA::TestEnum baz; -}; - -DECLARE_STREAMABLE_METATYPE(TestMessageB) - -// A test message that demonstrates inheritance and composition. -class TestMessageC : STREAM public TestMessageA { - STREAMABLE - -public: - - STREAM TestMessageB bong; - STREAM QScriptValue bizzle; -}; - -DECLARE_STREAMABLE_METATYPE(TestMessageC) - -/// Combines a sequence number with a submessage; used for testing unreliable transport. -class SequencedTestMessage { - STREAMABLE - -public: - - STREAM int sequenceNumber; - STREAM QVariant submessage; - STREAM SharedObjectPointer state; -}; - -DECLARE_STREAMABLE_METATYPE(SequencedTestMessage) - -#endif // hifi_MetavoxelTests_h diff --git a/tests/metavoxels/src/main.cpp b/tests/metavoxels/src/main.cpp deleted file mode 100644 index 51d4e565b2..0000000000 --- a/tests/metavoxels/src/main.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// -// main.cpp -// tests/metavoxels/src -// -// Created by Andrzej Kapolka on 2/7/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "MetavoxelTests.h" - -int main(int argc, char** argv) { - return MetavoxelTests(argc, argv).run(); -} diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 70457e220a..ffd908741d 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -3,6 +3,6 @@ set(TARGET_NAME octree-tests) setup_hifi_project(Script Network) # link in the shared libraries -link_hifi_libraries(shared octree gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree gpu model fbx networking entities avatars audio animation script-engine physics) copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 003920a442..08fe8fd7f3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,4 @@ # add the tool directories -add_subdirectory(bitstream2json) -add_subdirectory(json2bitstream) add_subdirectory(mtc) add_subdirectory(scribe) diff --git a/tools/bitstream2json/CMakeLists.txt b/tools/bitstream2json/CMakeLists.txt deleted file mode 100644 index 32a5a639ab..0000000000 --- a/tools/bitstream2json/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(TARGET_NAME bitstream2json) -setup_hifi_project(Widgets Script) - -link_hifi_libraries(metavoxels) - -copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/bitstream2json/src/main.cpp b/tools/bitstream2json/src/main.cpp deleted file mode 100644 index 0f299527b0..0000000000 --- a/tools/bitstream2json/src/main.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// main.cpp -// tools/bitstream2json/src -// -// Created by Andrzej Kapolka on 6/17/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -#include - -#include -#include -#include - -#include - -using namespace std; - -int main (int argc, char** argv) { - // need the core application for the script engine - QCoreApplication app(argc, argv); - - if (argc < 3) { - cerr << "Usage: bitstream2json inputfile outputfile [types...]" << endl; - return 0; - } - QFile inputFile(argv[1]); - if (!inputFile.open(QIODevice::ReadOnly)) { - cerr << "Failed to open input file: " << inputFile.errorString().toLatin1().constData() << endl; - return 1; - } - QDataStream inputData(&inputFile); - Bitstream input(inputData, Bitstream::FULL_METADATA, Bitstream::ALL_GENERICS); - - QFile outputFile(argv[2]); - if (!outputFile.open(QIODevice::WriteOnly)) { - cerr << "Failed to open output file: " << outputFile.errorString().toLatin1().constData() << endl; - return 1; - } - JSONWriter output; - - if (argc < 4) { - // default type is a single QVariant - QVariant value; - input >> value; - output << value; - - } else { - for (int i = 3; i < argc; i++) { - int type = QMetaType::type(argv[i]); - if (type == QMetaType::UnknownType) { - cerr << "Unknown type: " << argv[i] << endl; - return 1; - } - const TypeStreamer* streamer = Bitstream::getTypeStreamer(type); - if (!streamer) { - cerr << "Non-streamable type: " << argv[i] << endl; - return 1; - } - QVariant value = streamer->read(input); - output.appendToContents(streamer->getJSONData(output, value)); - } - } - - outputFile.write(output.getDocument().toJson()); - - return 0; -} diff --git a/tools/json2bitstream/CMakeLists.txt b/tools/json2bitstream/CMakeLists.txt deleted file mode 100644 index abda40667c..0000000000 --- a/tools/json2bitstream/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -set(TARGET_NAME json2bitstream) -setup_hifi_project(Widgets Script) - -link_hifi_libraries(metavoxels) - -copy_dlls_beside_windows_executable() \ No newline at end of file diff --git a/tools/json2bitstream/src/main.cpp b/tools/json2bitstream/src/main.cpp deleted file mode 100644 index ff09bcfdc6..0000000000 --- a/tools/json2bitstream/src/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// -// main.cpp -// tools/json2bitstream/src -// -// Created by Andrzej Kapolka on 6/17/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -#include - -#include -#include -#include - -#include - -using namespace std; - -int main (int argc, char** argv) { - // need the core application for the script engine - QCoreApplication app(argc, argv); - - if (argc < 3) { - cerr << "Usage: bitstream2json inputfile outputfile [types...]" << endl; - return 0; - } - QFile inputFile(argv[1]); - if (!inputFile.open(QIODevice::ReadOnly)) { - cerr << "Failed to open input file: " << inputFile.errorString().toLatin1().constData() << endl; - return 1; - } - QJsonParseError error; - QJsonDocument document = QJsonDocument::fromJson(inputFile.readAll(), &error); - if (error.error != QJsonParseError::NoError) { - cerr << "Failed to read input file: " << error.errorString().toLatin1().constData() << endl; - return 1; - } - JSONReader input(document, Bitstream::ALL_GENERICS); - - QFile outputFile(argv[2]); - if (!outputFile.open(QIODevice::WriteOnly)) { - cerr << "Failed to open output file: " << outputFile.errorString().toLatin1().constData() << endl; - return 1; - } - QDataStream outputData(&outputFile); - Bitstream output(outputData, Bitstream::FULL_METADATA); - - if (argc < 4) { - // default type is a single QVariant - QVariant value; - input >> value; - output << value; - - } else { - for (int i = 3; i < argc; i++) { - int type = QMetaType::type(argv[i]); - if (type == QMetaType::UnknownType) { - cerr << "Unknown type: " << argv[i] << endl; - return 1; - } - const TypeStreamer* streamer = Bitstream::getTypeStreamer(type); - if (!streamer) { - cerr << "Non-streamable type: " << argv[i] << endl; - return 1; - } - QVariant value; - streamer->putJSONData(input, input.retrieveNextFromContents(), value); - streamer->write(output, value); - } - } - output.flush(); - - return 0; -} From dd678dbc497ec6b0adf09a0e70fed9cdce105648 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 2 Mar 2015 19:05:13 -0800 Subject: [PATCH 328/341] Use all DDE coefficients to achieve better face control --- interface/src/devices/DdeFaceTracker.cpp | 183 ++++++++++++++++------- interface/src/devices/DdeFaceTracker.h | 4 +- 2 files changed, 128 insertions(+), 59 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 151afd98db..9ebe1ef718 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -17,15 +17,89 @@ #include #include "DdeFaceTracker.h" +#include "FaceshiftConstants.h" static const QHostAddress DDE_FEATURE_POINT_SERVER_ADDR("127.0.0.1"); static const quint16 DDE_FEATURE_POINT_SERVER_PORT = 5555; -static const int NUM_EXPRESSION = 46; -static const int MIN_PACKET_SIZE = (8 + NUM_EXPRESSION) * sizeof(float) + sizeof(int); +static const int NUM_EXPRESSIONS = 46; +static const int MIN_PACKET_SIZE = (8 + NUM_EXPRESSIONS) * sizeof(float) + sizeof(int); static const int MAX_NAME_SIZE = 31; -struct Packet{ +// There's almost but not quite a 1-1 correspondence between DDE's 46 and Faceshift 1.3's 48 packets. +// The best guess at mapping is to: +// - Swap L and R values +// - Skip two Faceshift values: JawChew (22) and LipsLowerDown (37) +static const int DDE_TO_FACESHIFT_MAPPING[] = { + 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, + 16, + 18, 17, + 19, + 23, + 21, + // Skip JawChew + 20, + 25, 24, 27, 26, 29, 28, 31, 30, 33, 32, + 34, 35, 36, + // Skip LipsLowerDown + 38, 39, 40, 41, 42, 43, 44, 45, + 47, 46 +}; + +// The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much +// less than this. +static const float DDE_COEFFICIENT_SCALES[] = { + 4.0f, // EyeBlink_L + 4.0f, // EyeBlink_R + 1.0f, // EyeSquint_L + 1.0f, // EyeSquint_R + 1.0f, // EyeDown_L + 1.0f, // EyeDown_R + 1.0f, // EyeIn_L + 1.0f, // EyeIn_R + 4.0f, // EyeOpen_L + 4.0f, // EyeOpen_R + 1.0f, // EyeOut_L + 1.0f, // EyeOut_R + 1.0f, // EyeUp_L + 1.0f, // EyeUp_R + 3.0f, // BrowsD_L + 3.0f, // BrowsD_R + 3.0f, // BrowsU_C + 3.0f, // BrowsU_L + 3.0f, // BrowsU_R + 1.0f, // JawFwd + 1.5f, // JawLeft + 1.8f, // JawOpen + 1.0f, // JawChew + 1.5f, // JawRight + 1.5f, // MouthLeft + 1.5f, // MouthRight + 1.5f, // MouthFrown_L + 1.5f, // MouthFrown_R + 1.5f, // MouthSmile_L + 1.5f, // MouthSmile_R + 1.0f, // MouthDimple_L + 1.0f, // MouthDimple_R + 1.0f, // LipsStretch_L + 1.0f, // LipsStretch_R + 1.0f, // LipsUpperClose + 1.0f, // LipsLowerClose + 1.0f, // LipsUpperUp + 1.0f, // LipsLowerDown + 1.0f, // LipsUpperOpen + 1.0f, // LipsLowerOpen + 2.5f, // LipsFunnel + 2.0f, // LipsPucker + 1.5f, // ChinLowerRaise + 1.5f, // ChinUpperRaise + 1.0f, // Sneer + 3.0f, // Puff + 1.0f, // CheekSquint_L + 1.0f // CheekSquint_R +}; + +struct Packet { //roughly in mm float focal_length[1]; float translation[3]; @@ -33,8 +107,9 @@ struct Packet{ //quaternion float rotation[4]; - //blendshape coefficients ranging between -0.2 and 1.5 - float expressions[NUM_EXPRESSION]; + // The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much + // less than this. + float expressions[NUM_EXPRESSIONS]; //avatar id selected on the UI int avatar_id; @@ -69,8 +144,10 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) : _previousTranslation(glm::vec3()), _previousRotation(glm::quat()) { - _blendshapeCoefficients.resize(NUM_EXPRESSION); - _previousExpressions.resize(NUM_EXPRESSION); + _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); + _previousCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); + + _blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); @@ -172,66 +249,56 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _headRotation = (rotation + _previousRotation) / 2.0f; _previousRotation = rotation; - // The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much - // less than this.packet.expressions[1] - - // Eye blendshapes - static const float RELAXED_EYE_VALUE = 0.2f; - static const float EYE_OPEN_SCALE = 4.0f; - static const float EYE_BLINK_SCALE = 2.5f; - float leftEye = (packet.expressions[1] + _previousExpressions[1]) / 2.0f - RELAXED_EYE_VALUE; - float rightEye = (packet.expressions[0] + _previousExpressions[0]) / 2.0f - RELAXED_EYE_VALUE; - if (leftEye > 0.0f) { - _blendshapeCoefficients[_leftBlinkIndex] = glm::clamp(EYE_BLINK_SCALE * leftEye, 0.0f, 1.0f); - _blendshapeCoefficients[_leftEyeOpenIndex] = 0.0f; - } else { - _blendshapeCoefficients[_leftBlinkIndex] = 0.0f; - _blendshapeCoefficients[_leftEyeOpenIndex] = glm::clamp(EYE_OPEN_SCALE * -leftEye, 0.0f, 1.0f); + // Translate DDE coefficients to Faceshift compatible coefficients + for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { + _coefficients[DDE_TO_FACESHIFT_MAPPING[i]] = packet.expressions[i]; } - if (rightEye > 0.0f) { - _blendshapeCoefficients[_rightBlinkIndex] = glm::clamp(EYE_BLINK_SCALE * rightEye, 0.0f, 1.0f); - _blendshapeCoefficients[_rightEyeOpenIndex] = 0.0f; - } else { - _blendshapeCoefficients[_rightBlinkIndex] = 0.0f; - _blendshapeCoefficients[_rightEyeOpenIndex] = glm::clamp(EYE_OPEN_SCALE * -rightEye, 0.0f, 1.0f); - } - _previousExpressions[1] = packet.expressions[1]; - _previousExpressions[0] = packet.expressions[0]; - // Eyebrow blendshapes - static const float BROW_UP_SCALE = 3.0f; - static const float BROW_DOWN_SCALE = 3.0f; - float browCenter = (packet.expressions[17] + _previousExpressions[17]) / 2.0f; - if (browCenter > 0) { - float browUp = glm::clamp(BROW_UP_SCALE * browCenter, 0.0f, 1.0f); - _blendshapeCoefficients[_browUpCenterIndex] = browUp; - _blendshapeCoefficients[_browUpLeftIndex] = browUp; + // Use EyeBlink values to control both EyeBlink and EyeOpen + static const float RELAXED_EYE_VALUE = 0.1f; + float leftEye = (_coefficients[_leftBlinkIndex] + _previousCoefficients[_leftBlinkIndex]) / 2.0f; + float rightEye = (_coefficients[_rightBlinkIndex] + _previousCoefficients[_rightBlinkIndex]) / 2.0f; + if (leftEye > RELAXED_EYE_VALUE) { + _coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE; + _coefficients[_leftEyeOpenIndex] = 0.0f; + } else { + _coefficients[_leftBlinkIndex] = 0.0f; + _coefficients[_leftEyeOpenIndex] = RELAXED_EYE_VALUE - leftEye; + } + if (rightEye > RELAXED_EYE_VALUE) { + _coefficients[_rightBlinkIndex] = rightEye - RELAXED_EYE_VALUE; + _coefficients[_rightEyeOpenIndex] = 0.0f; + } else { + _coefficients[_rightBlinkIndex] = 0.0f; + _coefficients[_rightEyeOpenIndex] = RELAXED_EYE_VALUE - rightEye; + } + + // Offset jaw open coefficient + static const float JAW_OPEN_THRESHOLD = 0.16f; + _coefficients[_jawOpenIndex] = _coefficients[_jawOpenIndex] - JAW_OPEN_THRESHOLD; + + // Offset smile coefficients + static const float SMILE_THRESHOLD = 0.18f; + _coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD; + _coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD; + + + // Scale all coefficients + for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { + _blendshapeCoefficients[i] + = glm::clamp(DDE_COEFFICIENT_SCALES[i] * (_coefficients[i] + _previousCoefficients[i]) / 2.0f, 0.0f, 1.0f); + _previousCoefficients[i] = _coefficients[i]; + } + + // Postcondition brow coefficients + if (_blendshapeCoefficients[_browUpCenterIndex] > 0) { _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; - _blendshapeCoefficients[_browUpRightIndex] = browUp; _blendshapeCoefficients[_browDownRightIndex] = 0.0f; } else { - float browDown = glm::clamp(BROW_DOWN_SCALE * -browCenter, 0.0f, 1.0f); _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; - _blendshapeCoefficients[_browDownLeftIndex] = browDown; _blendshapeCoefficients[_browUpRightIndex] = 0.0f; - _blendshapeCoefficients[_browDownRightIndex] = browDown; } - _previousExpressions[17] = packet.expressions[17]; - - // Mouth blendshapes - static const float JAW_OPEN_THRESHOLD = 0.16f; - static const float JAW_OPEN_SCALE = 1.4f; - static const float SMILE_THRESHOLD = 0.18f; - static const float SMILE_SCALE = 1.5f; - float smileLeft = (packet.expressions[24] + _previousExpressions[24]) / 2.0f; - float smileRight = (packet.expressions[23] + _previousExpressions[23]) / 2.0f; - _blendshapeCoefficients[_jawOpenIndex] = glm::clamp(JAW_OPEN_SCALE * (packet.expressions[21] - JAW_OPEN_THRESHOLD), - 0.0f, 1.0f); - _blendshapeCoefficients[_mouthSmileLeftIndex] = glm::clamp(SMILE_SCALE * (smileLeft - SMILE_THRESHOLD), 0.0f, 1.0f); - _blendshapeCoefficients[_mouthSmileRightIndex] = glm::clamp(SMILE_SCALE * (smileRight - SMILE_THRESHOLD), 0.0f, 1.0f); - _previousExpressions[24] = packet.expressions[24]; - _previousExpressions[23] = packet.expressions[23]; } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index cd63639f76..3c95666a6c 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -89,10 +89,12 @@ private: int _jawOpenIndex; + QVector _coefficients; + // Previous values for simple smoothing glm::vec3 _previousTranslation; glm::quat _previousRotation; - QVector _previousExpressions; + QVector _previousCoefficients; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file From e43da005376b302c8f666c4ebafe422eafb35b20 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:13:41 -0800 Subject: [PATCH 329/341] remove xmpp chat support --- CMakeLists.txt | 1 - cmake/externals/qxmpp/CMakeLists.txt | 74 --- cmake/externals/qxmpp/qxmpp.patch | 13 - cmake/modules/FindQxmpp.cmake | 45 -- interface/CMakeLists.txt | 14 +- interface/src/Menu.cpp | 7 - interface/src/XmppClient.cpp | 85 ---- interface/src/XmppClient.h | 57 --- .../GlobalServicesScriptingInterface.cpp | 80 ---- .../GlobalServicesScriptingInterface.h | 19 +- interface/src/ui/ChatWindow.cpp | 420 ------------------ interface/src/ui/ChatWindow.h | 88 ---- interface/src/ui/DialogsManager.cpp | 51 --- interface/src/ui/DialogsManager.h | 6 +- 14 files changed, 4 insertions(+), 956 deletions(-) delete mode 100644 cmake/externals/qxmpp/CMakeLists.txt delete mode 100644 cmake/externals/qxmpp/qxmpp.patch delete mode 100644 cmake/modules/FindQxmpp.cmake delete mode 100644 interface/src/XmppClient.cpp delete mode 100644 interface/src/XmppClient.h delete mode 100644 interface/src/ui/ChatWindow.cpp delete mode 100644 interface/src/ui/ChatWindow.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 75282137dc..af707acf57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,7 +164,6 @@ if (WIN32) endif () option(GET_SDL2 "Get SDL2 library automatically as external project" 0) -option(GET_QXMPP "GET Qxmpp library automatically as external project" 0) if (WIN32) add_paths_to_fixup_libs("${QT_DIR}/bin") diff --git a/cmake/externals/qxmpp/CMakeLists.txt b/cmake/externals/qxmpp/CMakeLists.txt deleted file mode 100644 index c8bbdba6ba..0000000000 --- a/cmake/externals/qxmpp/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -set(EXTERNAL_NAME qxmpp) - -# we need to find qmake inside QT_DIR -find_program(QMAKE_COMMAND NAME qmake PATHS ${QT_DIR}/bin NO_DEFAULT_PATH) - -if (NOT QMAKE_COMMAND) - message(FATAL_ERROR "Could not find qmake. Qxmpp cannot be compiled without qmake.") -endif () - -if (ANDROID) - set(ANDROID_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19") -endif () - -if (WIN32) - find_program(PLATFORM_BUILD_COMMAND nmake PATHS "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin") - - if (NOT PLATFORM_BUILD_COMMAND) - message(FATAL_ERROR "You asked CMake to grap QXmpp and build it, but nmake was not found. Please make sure the folder containing nmake.exe is in your PATH.") - endif () -else () - find_program(PLATFORM_BUILD_COMMAND make) -endif () - -include(ExternalProject) -ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://qxmpp.googlecode.com/files/qxmpp-0.7.6.tar.gz - URL_MD5 ee45a97313306ded2ff0f6618a3ed1e1 - BUILD_IN_SOURCE 1 - PATCH_COMMAND patch -p2 -t -N --verbose < ${CMAKE_CURRENT_SOURCE_DIR}/qxmpp.patch - CONFIGURE_COMMAND ${QMAKE_COMMAND} PREFIX= - BUILD_COMMAND ${PLATFORM_BUILD_COMMAND} - INSTALL_COMMAND ${PLATFORM_BUILD_COMMAND} install - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 -) - -ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - -if (CMAKE_GENERATOR STREQUAL Xcode) - find_program(DITTO_COMMAND ditto) - - ExternalProject_Add_Step( - ${EXTERNAL_NAME} - copy-from-xcode-install - COMMENT "Copying from /tmp/hifi.dst${INSTALL_DIR} to move install to proper location" - COMMAND ${DITTO_COMMAND} /tmp/hifi.dst${INSTALL_DIR} ${INSTALL_DIR} - DEPENDEES install - LOG 1 - ) -endif () - -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE FILEPATH "Path to Qxmpp include directory") - -set(_LIB_DIR ${INSTALL_DIR}/lib) - -if (WIN32) - set(_LIB_EXT "0.lib") - - set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${_LIB_DIR} CACHE PATH "Location of QXmpp DLL") -else () - if (APPLE) - set(_LIB_EXT ".dylib") - else () - set(_LIB_EXT ".so") - endif () - - set(_LIB_PREFIX "lib") -endif () - -set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_LIB_DIR}/${_LIB_PREFIX}qxmpp${_LIB_EXT} CACHE FILEPATH "Path to QXmpp release library") -set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to QXmpp debug library") diff --git a/cmake/externals/qxmpp/qxmpp.patch b/cmake/externals/qxmpp/qxmpp.patch deleted file mode 100644 index ca2f455817..0000000000 --- a/cmake/externals/qxmpp/qxmpp.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/qxmpp-0.7.6/src/src.pro b/qxmpp-0.7.6-patch/src/src.pro -index 954738c..8404c8c 100644 ---- a/qxmpp-0.7.6/src/src.pro -+++ b/qxmpp-0.7.6-patch/src/src.pro -@@ -4,7 +4,7 @@ QT -= gui - - TEMPLATE = lib - --CONFIG += $$QXMPP_LIBRARY_TYPE -+CONFIG += $$QXMPP_LIBRARY_TYPE c++11 - DEFINES += QXMPP_BUILD - DEFINES += $$QXMPP_INTERNAL_DEFINES - INCLUDEPATH += $$QXMPP_INCLUDEPATH $$QXMPP_INTERNAL_INCLUDES diff --git a/cmake/modules/FindQxmpp.cmake b/cmake/modules/FindQxmpp.cmake deleted file mode 100644 index 5caa929427..0000000000 --- a/cmake/modules/FindQxmpp.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# -# FindQxmpp.cmake -# -# Try to find the qxmpp library -# -# You can provide a QXMPP_ROOT_DIR which contains lib and include directories -# -# Once done this will define -# -# QXMPP_FOUND - system found qxmpp -# QXMPP_INCLUDE_DIRS - the qxmpp include directory -# QXMPP_LIBRARIES - Link this to use qxmpp -# -# Created on 3/10/2014 by Stephen Birarda -# Copyright 2014 High Fidelity, Inc. -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("qxmpp") - -find_path(QXMPP_INCLUDE_DIRS qxmpp/QXmppClient.h PATH_SUFFIXES include HINTS ${QXMPP_SEARCH_DIRS}) - -find_library(QXMPP_LIBRARY_RELEASE NAMES qxmpp PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) -find_library(QXMPP_LIBRARY_DEBUG NAMES qxmpp_d PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) - -if (WIN32) - find_path(QXMPP_DLL_PATH NAMES qxmpp.dll PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS}) -endif () - -find_package(Qt5 COMPONENTS Xml REQUIRED) - -include(SelectLibraryConfigurations) -select_library_configurations(QXMPP) - -set(QXMPP_LIBRARIES "${QXMPP_LIBRARY}" Qt5::Xml) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(QXmpp DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_LIBRARY) - -if (QXMPP_DLL_PATH) - add_paths_to_fixup_libs(${QXMPP_DLL_PATH}) -endif () \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index ee41648758..74afc7b208 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "RSSDK") +set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "PrioVR" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) @@ -119,7 +119,7 @@ link_hifi_libraries(shared octree environment gpu model fbx metavoxels networkin audio audio-client animation script-engine physics render-utils entities-renderer) -add_dependency_external_projects(sdl2 qxmpp) +add_dependency_external_projects(sdl2) # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) @@ -175,16 +175,6 @@ if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE) target_link_libraries(${TARGET_NAME} ${CoreMIDI}) endif () -if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32) - if (NOT QXMPP_DLL_PATH) - # if we have no QXmpp DLL path, assume we're linking a static QXmpp on windows - add_definitions(-DQXMPP_STATIC) - else () - # otherwise assume we are linking a dynamic QXmpp - add_definitions(-DQXMPP_SHARED) - endif () -endif () - # include headers for interface and InterfaceConfig. include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes") diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index be5b495fe9..10f5d8f531 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include "Application.h" #include "AccountManager.h" @@ -163,12 +162,6 @@ Menu::Menu() { connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); #endif -#ifdef HAVE_QXMPP - addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, Qt::Key_Backslash, - dialogsManager.data(), SLOT(showChat())); - dialogsManager->setupChat(); -#endif - addActionToQMenuAndActionHash(toolsMenu, MenuOption::ToolWindow, Qt::CTRL | Qt::ALT | Qt::Key_T, diff --git a/interface/src/XmppClient.cpp b/interface/src/XmppClient.cpp deleted file mode 100644 index 7f3c7cf291..0000000000 --- a/interface/src/XmppClient.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// XmppClient.cpp -// interface/src -// -// Created by Dimitar Dobrev on 10/3/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -#include - -#include "XmppClient.h" - -const QString DEFAULT_XMPP_SERVER = "chat.highfidelity.io"; -const QString DEFAULT_CHAT_ROOM = "public@public-chat.highfidelity.io"; - -#ifdef HAVE_QXMPP -XmppClient::XmppClient() : - _xmppClient(), - _xmppMUCManager() -{ - AccountManager& accountManager = AccountManager::getInstance(); - connect(&accountManager, SIGNAL(profileChanged()), this, SLOT(connectToServer())); - connect(&accountManager, SIGNAL(logoutComplete()), this, SLOT(disconnectFromServer())); -} -#else -XmppClient::XmppClient() { - -} -#endif - -XmppClient& XmppClient::getInstance() { - static XmppClient sharedInstance; - return sharedInstance; -} - -void XmppClient::xmppConnected() { -#ifdef HAVE_QXMPP - _publicChatRoom = _xmppMUCManager.addRoom(DEFAULT_CHAT_ROOM); - _publicChatRoom->setNickName(AccountManager::getInstance().getAccountInfo().getUsername()); - _publicChatRoom->join(); - emit joinedPublicChatRoom(); -#endif -} - -#ifdef HAVE_QXMPP -void XmppClient::xmppError(QXmppClient::Error error) { - qDebug() << "Error connnecting to XMPP for user " - << AccountManager::getInstance().getAccountInfo().getUsername() << ": " << error; -} -#endif - -void XmppClient::connectToServer() { -#ifdef HAVE_QXMPP - disconnectFromServer(); - - if (_xmppClient.addExtension(&_xmppMUCManager)) { - connect(&_xmppClient, SIGNAL(connected()), this, SLOT(xmppConnected())); - connect(&_xmppClient, SIGNAL(error(QXmppClient::Error)), this, SLOT(xmppError(QXmppClient::Error))); - } - AccountManager& accountManager = AccountManager::getInstance(); - QString user = accountManager.getAccountInfo().getUsername(); - const QString& password = accountManager.getAccountInfo().getXMPPPassword(); - _xmppClient.connectToServer(user + "@" + DEFAULT_XMPP_SERVER, password); -#endif -} - -void XmppClient::disconnectFromServer() { -#ifdef HAVE_QXMPP - if (_xmppClient.isConnected()) { - _xmppClient.disconnectFromServer(); - } -#endif -} - -XmppClient::XmppClient(const XmppClient& other) { - Q_UNUSED(other); -} - -void XmppClient::operator =(XmppClient const& other) { - Q_UNUSED(other); -} diff --git a/interface/src/XmppClient.h b/interface/src/XmppClient.h deleted file mode 100644 index 2b7a831ff3..0000000000 --- a/interface/src/XmppClient.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// XmppClient.h -// interface/src -// -// Created by Dimitar Dobrev on 10/3/14. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_XmppClient_h -#define hifi_XmppClient_h - -#include - -#ifdef HAVE_QXMPP -#include -#include -#endif - -/// Generalized threaded processor for handling received inbound packets. -class XmppClient : public QObject { - Q_OBJECT -public: - static XmppClient& getInstance(); - -#ifdef HAVE_QXMPP - QXmppClient& getXMPPClient() { return _xmppClient; } - const QXmppMucRoom* getPublicChatRoom() const { return _publicChatRoom; } -#endif - -signals: - void joinedPublicChatRoom(); - -private slots: - void xmppConnected(); -#ifdef HAVE_QXMPP - void xmppError(QXmppClient::Error error); -#endif - - void connectToServer(); - void disconnectFromServer(); - -private: - XmppClient(); - XmppClient(XmppClient const& other); // not implemented - void operator=(XmppClient const& other); // not implemented - -#ifdef HAVE_QXMPP - QXmppClient _xmppClient; - QXmppMucManager _xmppMUCManager; - QXmppMucRoom* _publicChatRoom; -#endif -}; - -#endif // hifi_XmppClient_h diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.cpp b/interface/src/scripting/GlobalServicesScriptingInterface.cpp index 1cceec0e01..478b708e53 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.cpp +++ b/interface/src/scripting/GlobalServicesScriptingInterface.cpp @@ -12,7 +12,6 @@ #include "AccountManager.h" #include "Application.h" #include "ResourceCache.h" -#include "XmppClient.h" #include "GlobalServicesScriptingInterface.h" @@ -20,13 +19,6 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() { AccountManager& accountManager = AccountManager::getInstance(); connect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); connect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); -#ifdef HAVE_QXMPP - const XmppClient& xmppClient = XmppClient::getInstance(); - connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected); - connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected); - const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); - connect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); -#endif // HAVE_QXMPP _downloading = false; connect(Application::getInstance(), &Application::renderingInWorldInterface, @@ -37,30 +29,6 @@ GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() { AccountManager& accountManager = AccountManager::getInstance(); disconnect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged); disconnect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut); -#ifdef HAVE_QXMPP - const XmppClient& xmppClient = XmppClient::getInstance(); - disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected); - disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected); - const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient(); - disconnect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived); - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - disconnect(publicChatRoom, &QXmppMucRoom::participantsChanged, - this, &GlobalServicesScriptingInterface::participantsChanged); -#endif // HAVE_QXMPP -} - -void GlobalServicesScriptingInterface::onConnected() { -#ifdef HAVE_QXMPP - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - connect(publicChatRoom, &QXmppMucRoom::participantsChanged, - this, &GlobalServicesScriptingInterface::participantsChanged, Qt::UniqueConnection); -#endif // HAVE_QXMPP -} - -void GlobalServicesScriptingInterface::participantsChanged() { -#ifdef HAVE_QXMPP - emit GlobalServicesScriptingInterface::onlineUsersChanged(this->getOnlineUsers()); -#endif // HAVE_QXMPP } GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() { @@ -68,62 +36,14 @@ GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance( return &sharedInstance; } -bool GlobalServicesScriptingInterface::isConnected() { -#ifdef HAVE_QXMPP - return XmppClient::getInstance().getXMPPClient().isConnected(); -#else - return false; -#endif // HAVE_QXMPP -} - -QScriptValue GlobalServicesScriptingInterface::chat(const QString& message) { -#ifdef HAVE_QXMPP - if (XmppClient::getInstance().getXMPPClient().isConnected()) { - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - QXmppMessage messageObject; - messageObject.setTo(publicChatRoom->jid()); - messageObject.setType(QXmppMessage::GroupChat); - messageObject.setBody(message); - return XmppClient::getInstance().getXMPPClient().sendPacket(messageObject); - } -#endif // HAVE_QXMPP - return false; -} - QString GlobalServicesScriptingInterface::getMyUsername() { return AccountManager::getInstance().getAccountInfo().getUsername(); } -QStringList GlobalServicesScriptingInterface::getOnlineUsers() { -#ifdef HAVE_QXMPP - if (XmppClient::getInstance().getXMPPClient().isConnected()) { - QStringList usernames; - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - foreach(const QString& participant, XmppClient::getInstance().getPublicChatRoom()->participants()) { - usernames.append(participant.right(participant.count() - 1 - publicChatRoom->jid().count())); - } - return usernames; - } -#endif // HAVE_QXMPP - return QStringList(); -} - void GlobalServicesScriptingInterface::loggedOut() { emit GlobalServicesScriptingInterface::disconnected(QString("logout")); } -#ifdef HAVE_QXMPP -void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& message) { - if (message.type() != QXmppMessage::GroupChat) { - return; - } - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - QString username = message.from().right(message.from().count() - 1 - publicChatRoom->jid().count()); - emit GlobalServicesScriptingInterface::incomingMessage(username, message.body()); -} -#endif // HAVE_QXMPP - - DownloadInfoResult::DownloadInfoResult() : downloading(QList()), pending(0.0f) diff --git a/interface/src/scripting/GlobalServicesScriptingInterface.h b/interface/src/scripting/GlobalServicesScriptingInterface.h index d8b436a6e6..a71446a970 100644 --- a/interface/src/scripting/GlobalServicesScriptingInterface.h +++ b/interface/src/scripting/GlobalServicesScriptingInterface.h @@ -19,13 +19,6 @@ #include #include -#ifdef HAVE_QXMPP - -#include -#include - -#endif // HAVE_QXMPP - class DownloadInfoResult { public: DownloadInfoResult(); @@ -41,30 +34,20 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR class GlobalServicesScriptingInterface : public QObject { Q_OBJECT - Q_PROPERTY(bool isConnected READ isConnected) Q_PROPERTY(QString myUsername READ getMyUsername) - Q_PROPERTY(QStringList onlineUsers READ getOnlineUsers) GlobalServicesScriptingInterface(); ~GlobalServicesScriptingInterface(); public: static GlobalServicesScriptingInterface* getInstance(); - bool isConnected(); QString getMyUsername(); - QStringList getOnlineUsers(); - + public slots: - QScriptValue chat(const QString& message); DownloadInfoResult getDownloadInfo(); void updateDownloadInfo(); private slots: void loggedOut(); - void onConnected(); - void participantsChanged(); -#ifdef HAVE_QXMPP - void messageReceived(const QXmppMessage& message); -#endif // HAVE_QXMPP void checkDownloadInfo(); signals: diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp deleted file mode 100644 index 35e112350a..0000000000 --- a/interface/src/ui/ChatWindow.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// -// ChatWindow.cpp -// interface/src/ui -// -// Created by Dimitar Dobrev on 3/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include -#include -#include "qtimespan.h" - - -#include -#include -#include - -#include "Application.h" -#include "ChatMessageArea.h" -#include "FlowLayout.h" -#include "MainWindow.h" -#include "UIUtil.h" -#include "XmppClient.h" - -#include "ui_chatWindow.h" -#include "ChatWindow.h" - - -const int NUM_MESSAGES_TO_TIME_STAMP = 20; - -const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)"); -const QRegularExpression regexHifiLinks("([#@]\\S+)"); -const QString mentionSoundsPath("/mention-sounds/"); -const QString mentionRegex("@(\\b%1\\b)"); - -ChatWindow::ChatWindow(QWidget* parent) : - QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | - Qt::WindowCloseButtonHint), - _ui(new Ui::ChatWindow), - _numMessagesAfterLastTimeStamp(0), - _mousePressed(false), - _mouseStartPosition(), - _trayIcon(parent), - _effectPlayer(), - _usernameMentionTimestamp("MentionTimestamp", QDateTime()) -{ - setAttribute(Qt::WA_DeleteOnClose, false); - - _ui->setupUi(this); - - FlowLayout* flowLayout = new FlowLayout(0, 4, 4); - _ui->usersWidget->setLayout(flowLayout); - - _ui->messagePlainTextEdit->installEventFilter(this); - _ui->messagePlainTextEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - - QTextCursor cursor(_ui->messagePlainTextEdit->textCursor()); - - cursor.movePosition(QTextCursor::Start); - - QTextBlockFormat format = cursor.blockFormat(); - format.setLineHeight(130, QTextBlockFormat::ProportionalHeight); - - cursor.setBlockFormat(format); - - _ui->messagePlainTextEdit->setTextCursor(cursor); - - if (!AccountManager::getInstance().isLoggedIn()) { - _ui->connectingToXMPPLabel->setText(tr("You must be logged in to chat with others.")); - } - -#ifdef HAVE_QXMPP - const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); - if (xmppClient.isConnected()) { - participantsChanged(); - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); - _ui->connectingToXMPPLabel->hide(); - startTimerForTimeStamps(); - } else { - _ui->numOnlineLabel->hide(); - _ui->usersArea->hide(); - _ui->messagesScrollArea->hide(); - _ui->messagePlainTextEdit->hide(); - connect(&XmppClient::getInstance(), SIGNAL(joinedPublicChatRoom()), this, SLOT(connected())); - } - connect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage))); - connect(&_trayIcon, SIGNAL(messageClicked()), this, SLOT(notificationClicked())); -#endif // HAVE_QXMPP - - QDir mentionSoundsDir(PathUtils::resourcesPath() + mentionSoundsPath); - _mentionSounds = mentionSoundsDir.entryList(QDir::Files); - _trayIcon.setIcon(QIcon( PathUtils::resourcesPath() + "/images/hifi-logo.svg")); -} - -ChatWindow::~ChatWindow() { -#ifdef HAVE_QXMPP - const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); - disconnect(&xmppClient, SIGNAL(joinedPublicChatRoom()), this, SLOT(connected())); - disconnect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage))); - - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - disconnect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); -#endif // HAVE_QXMPP - delete _ui; -} - -void ChatWindow::keyPressEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Escape) { - Application::getInstance()->getWindow()->activateWindow(); - hide(); - } else { - QWidget::keyPressEvent(event); - } -} - -void ChatWindow::showEvent(QShowEvent* event) { - QWidget::showEvent(event); - - if (!event->spontaneous()) { - _ui->messagePlainTextEdit->setFocus(); - } - QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); - int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); - int menuBarHeight = Menu::getInstance()->geometry().height(); - int topMargin = titleBarHeight + menuBarHeight; - - setGeometry(parentGeometry.topRight().x() - size().width() + 1, parentGeometry.topRight().y() + topMargin, - size().width(), parentWidget()->height() - topMargin); - - Application::processEvents(); - - scrollToBottom(); - -#ifdef HAVE_QXMPP - const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); - if (xmppClient.isConnected()) { - participantsChanged(); - } -#endif // HAVE_QXMPP -} - -bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { - if (sender == _ui->messagePlainTextEdit) { - if (event->type() != QEvent::KeyPress) { - return false; - } - QKeyEvent* keyEvent = static_cast(event); - if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && - (keyEvent->modifiers() & Qt::ShiftModifier) == 0) { - QString messageText = _ui->messagePlainTextEdit->document()->toPlainText().trimmed(); - if (!messageText.isEmpty()) { -#ifdef HAVE_QXMPP - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - QXmppMessage message; - message.setTo(publicChatRoom->jid()); - message.setType(QXmppMessage::GroupChat); - message.setBody(messageText); - XmppClient::getInstance().getXMPPClient().sendPacket(message); -#endif // HAVE_QXMPP - QTextCursor cursor = _ui->messagePlainTextEdit->textCursor(); - cursor.select(QTextCursor::Document); - cursor.removeSelectedText(); - } - return true; - } - } else if (event->type() == QEvent::MouseButtonRelease) { - QVariant userVar = sender->property("user"); - if (userVar.isValid()) { - DependencyManager::get()->goToUser(userVar.toString()); - return true; - } - } - return QWidget::eventFilter(sender, event); -} - -void ChatWindow::addTimeStamp() { - QTimeSpan timePassed = QDateTime::currentDateTime() - _lastMessageStamp; - int times[] = { timePassed.daysPart(), timePassed.hoursPart(), timePassed.minutesPart() }; - QString strings[] = { tr("%n day(s)", 0, times[0]), tr("%n hour(s)", 0, times[1]), tr("%n minute(s)", 0, times[2]) }; - QString timeString = ""; - for (int i = 0; i < 3; i++) { - if (times[i] > 0) { - timeString += strings[i] + " "; - } - } - timeString.chop(1); - if (!timeString.isEmpty()) { - QLabel* timeLabel = new QLabel(timeString); - timeLabel->setStyleSheet("color: #333333;" - "background-color: white;" - "font-size: 14px;" - "padding: 4px;"); - timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - timeLabel->setAlignment(Qt::AlignLeft); - - bool atBottom = isNearBottom(); - - _ui->messagesVBoxLayout->addWidget(timeLabel); - _ui->messagesVBoxLayout->parentWidget()->updateGeometry(); - - Application::processEvents(); - _numMessagesAfterLastTimeStamp = 0; - - if (atBottom) { - scrollToBottom(); - } - } -} - -void ChatWindow::startTimerForTimeStamps() { - QTimer* timer = new QTimer(this); - timer->setInterval(10 * 60 * 1000); - connect(timer, SIGNAL(timeout()), this, SLOT(timeout())); - timer->start(); -} - -void ChatWindow::connected() { - _ui->connectingToXMPPLabel->hide(); - _ui->numOnlineLabel->show(); - _ui->usersArea->show(); - _ui->messagesScrollArea->show(); - _ui->messagePlainTextEdit->show(); - _ui->messagePlainTextEdit->setFocus(); -#ifdef HAVE_QXMPP - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); -#endif // HAVE_QXMPP - startTimerForTimeStamps(); -} - -void ChatWindow::timeout() { - if (_numMessagesAfterLastTimeStamp >= NUM_MESSAGES_TO_TIME_STAMP) { - addTimeStamp(); - } -} - -#ifdef HAVE_QXMPP -void ChatWindow::notificationClicked() { - if (parentWidget()->isMinimized()) { - parentWidget()->showNormal(); - } - if (isHidden()) { - show(); - } - - // find last mention - int messageCount = _ui->messagesVBoxLayout->count(); - for (unsigned int i = messageCount; i > 0; i--) { - ChatMessageArea* area = (ChatMessageArea*)_ui->messagesVBoxLayout->itemAt(i - 1)->widget(); - QRegularExpression usernameMention(mentionRegex.arg(AccountManager::getInstance().getAccountInfo().getUsername())); - if (area->toPlainText().contains(usernameMention)) { - int top = area->geometry().top(); - int height = area->geometry().height(); - - QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar(); - verticalScrollBar->setSliderPosition(top - verticalScrollBar->size().height() + height); - return; - } - } - Application::processEvents(); - - scrollToBottom(); -} - -QString ChatWindow::getParticipantName(const QString& participant) { - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - return participant.right(participant.count() - 1 - publicChatRoom->jid().count()); -} - -void ChatWindow::error(QXmppClient::Error error) { - _ui->connectingToXMPPLabel->setText(QString::number(error)); -} - -void ChatWindow::participantsChanged() { - bool atBottom = isNearBottom(); - - QStringList participants = XmppClient::getInstance().getPublicChatRoom()->participants(); - _ui->numOnlineLabel->setText(tr("%1 online now:").arg(participants.count())); - - while (QLayoutItem* item = _ui->usersWidget->layout()->takeAt(0)) { - delete item->widget(); - delete item; - } - foreach (const QString& participant, participants) { - QString participantName = getParticipantName(participant); - QLabel* userLabel = new QLabel(); - userLabel->setText(participantName); - userLabel->setStyleSheet("background-color: palette(light);" - "border-radius: 5px;" - "color: #267077;" - "padding-top: 3px;" - "padding-right: 2px;" - "padding-bottom: 2px;" - "padding-left: 2px;" - "border: 1px solid palette(shadow);" - "font-size: 14px;" - "font-weight: bold"); - userLabel->setProperty("user", participantName); - userLabel->setCursor(Qt::PointingHandCursor); - userLabel->installEventFilter(this); - _ui->usersWidget->layout()->addWidget(userLabel); - } - Application::processEvents(); - - if (atBottom) { - scrollToBottom(); - } -} - -void ChatWindow::messageReceived(const QXmppMessage& message) { - if (message.type() != QXmppMessage::GroupChat) { - return; - } - - // Update background if this is a message from the current user - bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getAccountInfo().getUsername(); - - // Create message area - ChatMessageArea* messageArea = new ChatMessageArea(true); - messageArea->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); - messageArea->setTextInteractionFlags(Qt::TextBrowserInteraction); - messageArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - messageArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - messageArea->setReadOnly(true); - - messageArea->setStyleSheet("QTextBrowser{ padding-bottom: 2px;" - "padding-left: 2px;" - "padding-top: 2px;" - "padding-right: 20px;" - "margin: 0px;" - "color: #333333;" - "font-size: 14px;" - "background-color: rgba(0, 0, 0, 0%);" - "border: 0; }" - "QMenu{ border: 2px outset gray; }"); - - QString userLabel = getParticipantName(message.from()); - if (fromSelf) { - userLabel = "" + userLabel + ": "; - messageArea->setStyleSheet(messageArea->styleSheet() + "background-color: #e1e8ea"); - } else { - userLabel = "" + userLabel + ": "; - } - - messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}"); - QString messageText = message.body().toHtmlEscaped(); - messageText = messageText.replace(regexLinks, "\\1"); - messageText = messageText.replace(regexHifiLinks, "\\1"); - messageArea->setHtml(userLabel + messageText); - - bool atBottom = isNearBottom(); - - _ui->messagesVBoxLayout->addWidget(messageArea); - _ui->messagesVBoxLayout->parentWidget()->updateGeometry(); - Application::processEvents(); - - if (atBottom || fromSelf) { - scrollToBottom(); - } - - ++_numMessagesAfterLastTimeStamp; - if (message.stamp().isValid()) { - _lastMessageStamp = message.stamp().toLocalTime(); - } else { - _lastMessageStamp = QDateTime::currentDateTime(); - } - - QRegularExpression usernameMention(mentionRegex.arg(AccountManager::getInstance().getAccountInfo().getUsername())); - if (message.body().contains(usernameMention)) { - - // Don't show messages already seen in icon tray at start-up. - bool showMessage = _usernameMentionTimestamp.get() < _lastMessageStamp; - if (showMessage) { - _usernameMentionTimestamp.set(_lastMessageStamp); - } - - if (isHidden() && showMessage) { - - if (_effectPlayer.state() != QMediaPlayer::PlayingState) { - // get random sound - QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + - mentionSoundsPath + - _mentionSounds.at(rand() % _mentionSounds.size())); - _effectPlayer.setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); - _effectPlayer.play(); - } - - _trayIcon.show(); - _trayIcon.showMessage(windowTitle(), message.body()); - } - } -} -#endif // HAVE_QXMPP - -bool ChatWindow::isNearBottom() { - QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar(); - return verticalScrollBar->value() >= verticalScrollBar->maximum() - Ui::AUTO_SCROLL_THRESHOLD; -} - -// Scroll chat message area to bottom. -void ChatWindow::scrollToBottom() { - QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar(); - verticalScrollBar->setValue(verticalScrollBar->maximum()); -} - -bool ChatWindow::event(QEvent* event) { - if (event->type() == QEvent::WindowActivate) { - _ui->messagePlainTextEdit->setFocus(); - } - return QWidget::event(event); -} diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h deleted file mode 100644 index b2ee113637..0000000000 --- a/interface/src/ui/ChatWindow.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// ChatWindow.h -// interface/src/ui -// -// Created by Dimitar Dobrev on 3/6/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ChatWindow_h -#define hifi_ChatWindow_h - -#include -#include -#include -#include -#include - -#include -#include - -#include "FramelessDialog.h" - -#ifdef HAVE_QXMPP - -#include -#include - -#endif - -namespace Ui { - - -// Maximum amount the chat can be scrolled up in order to auto scroll. -const int AUTO_SCROLL_THRESHOLD = 20; - - -class ChatWindow; -} - -class ChatWindow : public QWidget { - Q_OBJECT - -public: - ChatWindow(QWidget* parent); - ~ChatWindow(); - -protected: - bool eventFilter(QObject* sender, QEvent* event); - - virtual void keyPressEvent(QKeyEvent *event); - virtual void showEvent(QShowEvent* event); - virtual bool event(QEvent* event); - -private: -#ifdef HAVE_QXMPP - QString getParticipantName(const QString& participant); -#endif - void startTimerForTimeStamps(); - void addTimeStamp(); - bool isNearBottom(); - void scrollToBottom(); - - Ui::ChatWindow* _ui; - int _numMessagesAfterLastTimeStamp; - QDateTime _lastMessageStamp; - bool _mousePressed; - QPoint _mouseStartPosition; - QSystemTrayIcon _trayIcon; - QStringList _mentionSounds; - QMediaPlayer _effectPlayer; - - Setting::Handle _usernameMentionTimestamp; - -private slots: - void connected(); - void timeout(); -#ifdef HAVE_QXMPP - void error(QXmppClient::Error error); - void participantsChanged(); - void messageReceived(const QXmppMessage& message); - void notificationClicked(); -#endif -}; - -#endif // hifi_ChatWindow_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 752e205a6a..9fb5b640b7 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -162,54 +162,3 @@ void DialogsManager::showScriptEditor() { maybeCreateDialog(_scriptEditor); _scriptEditor->raise(); } - -void DialogsManager::setupChat() { -#ifdef HAVE_QXMPP - const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); - connect(&xmppClient, &QXmppClient::connected, this, &DialogsManager::toggleChat); - connect(&xmppClient, &QXmppClient::disconnected, this, &DialogsManager::toggleChat); - - QDir::setCurrent(PathUtils::resourcesPath()); - // init chat window to listen chat - maybeCreateDialog(_chatWindow); -#endif -} - -void DialogsManager::showChat() { - if (AccountManager::getInstance().isLoggedIn()) { - maybeCreateDialog(_chatWindow); - - if (_chatWindow->isHidden()) { - _chatWindow->show(); - } - _chatWindow->raise(); - _chatWindow->activateWindow(); - _chatWindow->setFocus(); - } else { - qApp->getTrayIcon()->showMessage("Interface", - "You need to login to be able to chat with others on this domain."); - } -} - -void DialogsManager::toggleChat() { -#ifdef HAVE_QXMPP - QAction* chatAction = Menu::getInstance()->getActionForOption(MenuOption::Login); - Q_CHECK_PTR(chatAction); - - chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected()); - if (!chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) { - if (_chatWindow->isHidden()) { - _chatWindow->show(); - _chatWindow->raise(); - _chatWindow->activateWindow(); - _chatWindow->setFocus(); - } else { - _chatWindow->hide(); - } - } -#endif -} - - - - diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 465c6829ad..59af539540 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -45,8 +45,6 @@ public: QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } - void setupChat(); - public slots: void toggleAddressBar(); void toggleLoginDialog(); @@ -62,12 +60,10 @@ public slots: void showMetavoxelEditor(); void showMetavoxelNetworkSimulator(); void showScriptEditor(); - void showChat(); - + private slots: void toggleToolWindow(); void hmdToolsClosed(); - void toggleChat(); private: DialogsManager() {} From 379914ce7d5229146f7770e7ed3432331421b622 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:14:13 -0800 Subject: [PATCH 330/341] modify BUILD for removal of qxmpp --- BUILD.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/BUILD.md b/BUILD.md index f2efe05289..3d3a4d055b 100644 --- a/BUILD.md +++ b/BUILD.md @@ -14,12 +14,10 @@ * [gverb](https://github.com/highfidelity/gverb) * [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1 -The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile QXmpp you would pass -DGET_QXMPP=1. +The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile SDL2 you would pass -DGET_SDL2=1. * [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3 * Enables game controller support in Interface -* [QXmpp](https://github.com/qxmpp-project/qxmpp) ~> 0.7.6 - * Enables text chat support in Interface The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project. From b270297406f17379bf48a5479df79e7b27b84bc2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:14:35 -0800 Subject: [PATCH 331/341] remove a missed XmppClient include --- interface/src/ui/DialogsManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 9fb5b640b7..67bf496c42 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include "AddressBarDialog.h" #include "AnimationsDialog.h" From 27b9b345ca509ddb3fa5c5faeb24db3d6de5ca8b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:15:34 -0800 Subject: [PATCH 332/341] remove ChatWindow includes from DialogsManager --- interface/src/ui/DialogsManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 67bf496c42..28920fd13e 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -18,7 +18,6 @@ #include "AttachmentsDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" -#include "ChatWindow.h" #include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" From a893f11ad7b39a04ae16ad14142b9b4525009728 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:17:29 -0800 Subject: [PATCH 333/341] remove load script from message that used xmpp --- .../example/scripts/loadScriptFromMessage.js | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 examples/example/scripts/loadScriptFromMessage.js diff --git a/examples/example/scripts/loadScriptFromMessage.js b/examples/example/scripts/loadScriptFromMessage.js deleted file mode 100644 index c9d067cc3b..0000000000 --- a/examples/example/scripts/loadScriptFromMessage.js +++ /dev/null @@ -1,27 +0,0 @@ -// -// loadScriptFromMessage.js -// examples -// -// Created by Thijs Wenker on 9/15/14. -// Copyright 2014 High Fidelity, Inc. -// -// Filters script links out of incomming messages and prompts you to run the script. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -//Javascript link RegEX -const JS_LINK_REGEX = /https?:\/\/[^ ]+\.js/i; - -function onIncomingMessage(user, message) { - var script_link = JS_LINK_REGEX.exec(message); - if (script_link == null) { - return; - } - if (Window.confirm("@" + user + " sent the following script:\n" + script_link + "\nwould you like to run it?")) { - Script.load(script_link); - } -} - -GlobalServices.incomingMessage.connect(onIncomingMessage); \ No newline at end of file From cf227b94de29482639ef08734c3b00e4e2927381 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:17:53 -0800 Subject: [PATCH 334/341] remove global services example that leveraged xmpp --- .../example/misc/globalServicesExample.js | 57 ------------------- 1 file changed, 57 deletions(-) delete mode 100644 examples/example/misc/globalServicesExample.js diff --git a/examples/example/misc/globalServicesExample.js b/examples/example/misc/globalServicesExample.js deleted file mode 100644 index 3d29b9510e..0000000000 --- a/examples/example/misc/globalServicesExample.js +++ /dev/null @@ -1,57 +0,0 @@ -// -// globalServicesExample.js -// examples -// -// Created by Thijs Wenker on 9/12/14. -// Copyright 2014 High Fidelity, Inc. -// -// Example usage of the GlobalServices object. You could use it to make your own chatbox. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -function onConnected() { - if (GlobalServices.onlineUsers.length > 0) { - sendMessageForm() - return; - } - Script.setTimeout(function() { sendMessageForm(); }, 5000); -} - -function onDisconnected(reason) { - switch(reason) { - case "logout": - Window.alert("logged out!"); - break; - - } -} - -function onOnlineUsersChanged(users) { - print(users); -} - -function onIncommingMessage(user, message) { - print(user + ": " + message); - if (message === "hello") { - GlobalServices.chat("hello, @" + user + "!"); - } -} - -function sendMessageForm() { - var form = - [ - { label: "To:", options: ["(noone)"].concat(GlobalServices.onlineUsers) }, - { label: "Message:", value: "Enter message here" } - ]; - if (Window.form("Send message on public chat", form)) { - GlobalServices.chat(form[0].value == "(noone)" ? form[1].value : "@" + form[0].value + ", " + form[1].value); - - } -} - -GlobalServices.connected.connect(onConnected); -GlobalServices.disconnected.connect(onDisconnected); -GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); -GlobalServices.incomingMessage.connect(onIncommingMessage); \ No newline at end of file From 03de43d451bc6c7dfd8912dcb004efadcc8e5e2c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 10:22:57 -0800 Subject: [PATCH 335/341] simplify notifications.js after chat removal --- examples/notifications.js | 101 +++++++------------------------------- 1 file changed, 18 insertions(+), 83 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 27192ed789..0c2a06c878 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -14,32 +14,28 @@ // This script generates notifications created via a number of ways, such as: // keystroke: // -// "q" returns number of users currently online (for debug purposes) - // CTRL/s for snapshot. // CTRL/m for mic mute and unmute. // System generated notifications: -// Displays users online at startup. // If Screen is resized. -// Triggers notification if @MyUserName is mentioned in chat. -// Announces existing user logging out. -// Announces new user logging in. // If mic is muted for any reason. // // To add a new System notification type: // // 1. Set the Event Connector at the bottom of the script. // example: -// GlobalServices.incomingMessage.connect(onIncomingMessage); +// AudioDevice.muteToggled.connect(onMuteStateChanged); // // 2. Create a new function to produce a text string, do not include new line returns. // example: -// function onIncomingMessage(user, message) { -// //do stuff here; -// var text = "This is a notification"; -// var wrappedText = wordWrap(text); -// createNotification(wrappedText, NotificationType.SNAPSHOT); +// function onMuteStateChanged() { +// var muteState, +// muteString; +// +// muteState = AudioDevice.getMuted() ? "muted" : "unmuted"; +// muteString = "Microphone is now " + muteState; +// createNotification(muteString, NotificationType.MUTE_TOGGLE); // } // // This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown. @@ -54,11 +50,12 @@ // 2. Declare a text string. // 3. Call createNotifications(text, NotificationType) parsing the text. // example: -// var welcome; -// if (key.text == "q") { //queries number of users online -// var welcome = "There are " + GlobalServices.onlineUsers.length + " users online now."; -// createNotification(welcome, NotificationType.USERS_ONLINE); -// } +// if (key.text === "s") { +// if (ctrlIsPressed === true) { +// noteString = "Snapshot taken."; +// createNotification(noteString, NotificationType.SNAPSHOT); +// } +// } Script.include("./libraries/globals.js"); Script.include("./libraries/soundArray.js"); @@ -81,8 +78,6 @@ var frame = 0; var ourWidth = Window.innerWidth; var ourHeight = Window.innerHeight; var text = "placeholder"; -var last_users = GlobalServices.onlineUsers; -var users = []; var ctrlIsPressed = false; var ready = true; var MENU_NAME = 'Tools > Notifications'; @@ -93,19 +88,11 @@ var PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE = "play_notification_sounds_type_" var NotificationType = { UNKNOWN: 0, - USER_JOINS: 1, - USER_LEAVES: 2, - MUTE_TOGGLE: 3, - CHAT_MENTION: 4, - USERS_ONLINE: 5, - SNAPSHOT: 6, - WINDOW_RESIZE: 7, + MUTE_TOGGLE: 1, + SNAPSHOT: 2, + WINDOW_RESIZE: 3, properties: [ - { text: "User Join" }, - { text: "User Leave" }, { text: "Mute Toggle" }, - { text: "Chat Mention" }, - { text: "Users Online" }, { text: "Snapshot" }, { text: "Window Resize" } ], @@ -476,15 +463,9 @@ var STARTUP_TIMEOUT = 500, // ms startingUp = true, startupTimer = null; -// This reports the number of users online at startup -function reportUsers() { - createNotification("Welcome! There are " + GlobalServices.onlineUsers.length + " users online now.", NotificationType.USERS_ONLINE); -} - function finishStartup() { startingUp = false; Script.clearTimeout(startupTimer); - reportUsers(); } function isStartingUp() { @@ -498,42 +479,6 @@ function isStartingUp() { return startingUp; } -// Triggers notification if a user logs on or off -function onOnlineUsersChanged(users) { - var i; - - if (!isStartingUp()) { // Skip user notifications at startup. - for (i = 0; i < users.length; i += 1) { - if (last_users.indexOf(users[i]) === -1.0) { - createNotification(users[i] + " has joined", NotificationType.USER_JOINS); - } - } - - for (i = 0; i < last_users.length; i += 1) { - if (users.indexOf(last_users[i]) === -1.0) { - createNotification(last_users[i] + " has left", NotificationType.USER_LEAVES); - } - } - } - - last_users = users; -} - -// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification. -function onIncomingMessage(user, message) { - var myMessage, - alertMe, - thisAlert; - - myMessage = message; - alertMe = "@" + GlobalServices.myUsername; - thisAlert = user + ": " + myMessage; - - if (myMessage.indexOf(alertMe) > -1.0) { - CreateNotification(wordWrap(thisAlert), NotificationType.CHAT_MENTION); - } -} - // Triggers mic mute notification function onMuteStateChanged() { var muteState, @@ -573,20 +518,12 @@ function keyReleaseEvent(key) { // Triggers notification on specific key driven events function keyPressEvent(key) { - var numUsers, - welcome, - noteString; + var noteString; if (key.key === 16777249) { ctrlIsPressed = true; } - if (key.text === "q") { //queries number of users online - numUsers = GlobalServices.onlineUsers.length; - welcome = "There are " + numUsers + " users online now."; - createNotification(welcome, NotificationType.USERS_ONLINE); - } - if (key.text === "s") { if (ctrlIsPressed === true) { noteString = "Snapshot taken."; @@ -641,8 +578,6 @@ function menuItemEvent(menuItem) { AudioDevice.muteToggled.connect(onMuteStateChanged); Controller.keyPressEvent.connect(keyPressEvent); Controller.mousePressEvent.connect(mousePressEvent); -GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); -GlobalServices.incomingMessage.connect(onIncomingMessage); Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); From 598b791aeed5c2139a5b2906d7885fc0df6885c1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Mar 2015 11:01:47 -0800 Subject: [PATCH 336/341] FIxing the compilation issue for linux --- libraries/render-utils/src/Model.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c7e5b71b22..bbb4dfe8cf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -223,17 +223,21 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, boo } #endif +#if defined(Q_OS_WIN) loc = glGetUniformBlockIndex(program.programId(), "transformObjectBuffer"); if (loc >= 0) { glUniformBlockBinding(program.programId(), loc, gpu::TRANSFORM_OBJECT_SLOT); // locations.materialBufferUnit = 1; } +#endif +#if defined(Q_OS_WIN) loc = glGetUniformBlockIndex(program.programId(), "transformCameraBuffer"); if (loc >= 0) { glUniformBlockBinding(program.programId(), loc, gpu::TRANSFORM_CAMERA_SLOT); // locations.materialBufferUnit = 1; } +#endif //program.link(); if (!program.isLinked()) { From 1b34b80b1a53555fc975acecc30ce05c9de94d41 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 3 Mar 2015 11:05:59 -0800 Subject: [PATCH 337/341] Use BrowsC_U to control both brows' up and down --- interface/src/devices/DdeFaceTracker.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 9ebe1ef718..9d753d228d 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -273,6 +273,12 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _coefficients[_rightEyeOpenIndex] = RELAXED_EYE_VALUE - rightEye; } + // Use BrowsU_C to control both brows' up and down + _coefficients[_browDownLeftIndex] = -_coefficients[_browUpCenterIndex]; + _coefficients[_browDownRightIndex] = -_coefficients[_browUpCenterIndex]; + _coefficients[_browUpLeftIndex] = _coefficients[_browUpCenterIndex]; + _coefficients[_browUpRightIndex] = _coefficients[_browUpCenterIndex]; + // Offset jaw open coefficient static const float JAW_OPEN_THRESHOLD = 0.16f; _coefficients[_jawOpenIndex] = _coefficients[_jawOpenIndex] - JAW_OPEN_THRESHOLD; @@ -290,16 +296,6 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _previousCoefficients[i] = _coefficients[i]; } - // Postcondition brow coefficients - if (_blendshapeCoefficients[_browUpCenterIndex] > 0) { - _blendshapeCoefficients[_browDownLeftIndex] = 0.0f; - _blendshapeCoefficients[_browDownRightIndex] = 0.0f; - } else { - _blendshapeCoefficients[_browUpCenterIndex] = 0.0f; - _blendshapeCoefficients[_browUpLeftIndex] = 0.0f; - _blendshapeCoefficients[_browUpRightIndex] = 0.0f; - } - } else { qDebug() << "[Error] DDE Face Tracker Decode Error"; } From cad21849275b821b33eb4b81635dd5747e5e19ec Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Mar 2015 11:09:11 -0800 Subject: [PATCH 338/341] FIxing the compilation issue for linux --- libraries/gpu/src/gpu/GLBackend.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index fd91e0df0c..0afc1b1204 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -395,8 +395,7 @@ void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { } void GLBackend::initTransform() { -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) glGenBuffers(1, &_transform._transformObjectBuffer); glGenBuffers(1, &_transform._transformCameraBuffer); @@ -413,8 +412,7 @@ void GLBackend::initTransform() { } void GLBackend::killTransform() { -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) glDeleteBuffers(1, &_transform._transformObjectBuffer); glDeleteBuffers(1, &_transform._transformCameraBuffer); #else @@ -443,8 +441,7 @@ void GLBackend::updateTransform() { } if (_transform._invalidView || _transform._invalidProj) { -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW); @@ -454,8 +451,7 @@ void GLBackend::updateTransform() { } if (_transform._invalidModel) { -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0); glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW); @@ -464,15 +460,14 @@ void GLBackend::updateTransform() { #endif } -#if defined(Q_OS_MAC) -#elif defined(Q_OS_WIN) +#if defined(Q_OS_WIN) glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer); glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer); CHECK_GL_ERROR(); #endif -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) || defined(Q_OS_LINUX) // Do it again for fixed pipeline until we can get rid of it if (_transform._invalidProj) { if (_transform._lastMode != GL_PROJECTION) { From a961cd8ff3910bbe892aea62014bf4cbef52470d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 12:17:35 -0800 Subject: [PATCH 339/341] show link to IRC in place of Qxmpp removal --- interface/src/Menu.cpp | 3 +++ interface/src/ui/DialogsManager.cpp | 16 ++++++++++++++++ interface/src/ui/DialogsManager.h | 5 +++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 10f5d8f531..639a88f65f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -161,6 +161,9 @@ Menu::Menu() { SLOT(setEnabled(bool))); connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool))); #endif + + addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, Qt::Key_Backslash, + dialogsManager.data(), SLOT(showIRCLink())); addActionToQMenuAndActionHash(toolsMenu, MenuOption::ToolWindow, diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 28920fd13e..8a33c0e827 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include @@ -160,3 +162,17 @@ void DialogsManager::showScriptEditor() { maybeCreateDialog(_scriptEditor); _scriptEditor->raise(); } + +void DialogsManager::showIRCLink() { + if (!_ircInfoBox) { + _ircInfoBox = new QMessageBox(QMessageBox::NoIcon, + "High Fidelity IRC", + "High Fidelity has an IRC channel on irc.freenode.net at #highfidelity.

Web chat is available at http://webchat.freenode.net/?channels=highfidelity&uio=d4", + QMessageBox::Ok); + _ircInfoBox->setTextFormat(Qt::RichText); + _ircInfoBox->setAttribute(Qt::WA_DeleteOnClose); + _ircInfoBox->show(); + } + + _ircInfoBox->raise(); +} diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 59af539540..1e083431ba 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -25,7 +25,6 @@ class AddressBarDialog; class AnimationsDialog; class AttachmentsDialog; class CachesSizeDialog; -class ChatWindow; class BandwidthDialog; class LodToolsDialog; class LoginDialog; @@ -34,6 +33,7 @@ class MetavoxelNetworkSimulator; class OctreeStatsDialog; class PreferencesDialog; class ScriptEditorWindow; +class QMessageBox; class DialogsManager : public QObject, public Dependency { Q_OBJECT @@ -60,6 +60,7 @@ public slots: void showMetavoxelEditor(); void showMetavoxelNetworkSimulator(); void showScriptEditor(); + void showIRCLink(); private slots: void toggleToolWindow(); @@ -87,7 +88,7 @@ private: QPointer _attachmentsDialog; QPointer _bandwidthDialog; QPointer _cachesSizeDialog; - QPointer _chatWindow; + QPointer _ircInfoBox; QPointer _hmdToolsDialog; QPointer _lodToolsDialog; QPointer _loginDialog; From 3fef8a16224785ef8da4b8c42a22b90ce5fe6484 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 3 Mar 2015 12:41:51 -0800 Subject: [PATCH 340/341] Update Light to set direction when setting orientation --- libraries/model/src/model/Light.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index a9425bed4b..ea77412140 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -44,6 +44,7 @@ void Light::setPosition(const Vec3& position) { } void Light::setOrientation(const glm::quat& orientation) { + setDirection(orientation * glm::vec3(0.0f, 0.0f, -1.0f)); _transform.setRotation(orientation); } From d3682b0297d3ad00621fa7aa6bc542775043c719 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 3 Mar 2015 16:03:47 -0800 Subject: [PATCH 341/341] fix web chat link for IRC --- interface/src/ui/DialogsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 8a33c0e827..dbc8ea4a7e 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -167,7 +167,7 @@ void DialogsManager::showIRCLink() { if (!_ircInfoBox) { _ircInfoBox = new QMessageBox(QMessageBox::NoIcon, "High Fidelity IRC", - "High Fidelity has an IRC channel on irc.freenode.net at #highfidelity.

Web chat is available at http://webchat.freenode.net/?channels=highfidelity&uio=d4", + "High Fidelity has an IRC channel on irc.freenode.net at #highfidelity.

Web chat is available here.", QMessageBox::Ok); _ircInfoBox->setTextFormat(Qt::RichText); _ircInfoBox->setAttribute(Qt::WA_DeleteOnClose);