From f569169662160fad5029a81854463c8cc395d372 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 13 May 2016 11:01:15 -0700 Subject: [PATCH 01/54] Trying to support ambient occlusion map from blender --- libraries/fbx/src/FBXReader.cpp | 7 ++++++- libraries/fbx/src/FBXReader.h | 2 ++ libraries/fbx/src/FBXReader_Material.cpp | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2df388e1d4..5a57a3c6d8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -924,6 +924,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS // material.emissiveColor = getVec3(property.properties, index); // material.emissiveFactor = 1.0; + } else if (property.properties.at(0) == "AmbientFactor") { + material.ambientFactor = property.properties.at(index).value(); + // Detected just for BLender AO vs lightmap } else if (property.properties.at(0) == "Shininess") { material.shininess = property.properties.at(index).value(); @@ -1126,8 +1129,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("tex_emissive_map")) { emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("ambient")) { + } else if (type.contains("ambientcolor")) { ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("ambientfactor")) { + ambientFactorTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("tex_ao_map")) { occlusionTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c1952fc550..9e960126b5 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -151,6 +151,7 @@ public: float metallic{ 0.0f }; float roughness{ 1.0f }; float emissiveIntensity{ 1.0f }; + float ambientFactor{ 1.0f }; QString materialID; QString name; @@ -436,6 +437,7 @@ public: QHash shininessTextures; QHash emissiveTextures; QHash ambientTextures; + QHash ambientFactorTextures; QHash occlusionTextures; QHash _fbxMaterials; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 11c6dad2f2..3503fe1054 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -175,6 +175,14 @@ void FBXReader::consolidateFBXMaterials() { FBXTexture occlusionTexture; QString occlusionTextureID = occlusionTextures.value(material.materialID); + if (occlusionTextureID.isNull()) { + // 2nd chance + // For blender we use the ambient factor texture ONLY if the ambientFactor value is set to 0 + if (material.ambientFactor == 0.0) { + occlusionTextureID = ambientFactorTextures.value(material.materialID); + } + } + if (!occlusionTextureID.isNull()) { occlusionTexture = getTexture(occlusionTextureID); detectDifferentUVs |= (occlusionTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); @@ -187,6 +195,14 @@ void FBXReader::consolidateFBXMaterials() { FBXTexture ambientTexture; QString ambientTextureID = ambientTextures.value(material.materialID); + if (ambientTextureID.isNull()) { + // 2nd chance + // For blender we use the ambient factor texture ONLY if the ambientFactor value is set to 1 + if (material.ambientFactor == 1.0) { + ambientTextureID = ambientFactorTextures.value(material.materialID); + } + } + if (_loadLightmaps && !ambientTextureID.isNull()) { ambientTexture = getTexture(ambientTextureID); detectDifferentUVs |= (ambientTexture.texcoordSet != 0) || (!ambientTexture.transform.isIdentity()); From 1c06c1a6ab9915b255812d994c1c88886d454a4f Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 13 May 2016 11:09:53 -0700 Subject: [PATCH 02/54] Cleaning up the pr from tthe transform.h file --- libraries/gpu/src/gpu/Transform.h | 36 ------------------------------- 1 file changed, 36 deletions(-) delete mode 100644 libraries/gpu/src/gpu/Transform.h diff --git a/libraries/gpu/src/gpu/Transform.h b/libraries/gpu/src/gpu/Transform.h deleted file mode 100644 index 82974964a8..0000000000 --- a/libraries/gpu/src/gpu/Transform.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Transform.h -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 06/12/2016. -// 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_gpu_Transform_h -#define hifi_gpu_Transform_h - -#include - -#include - -#include "Resource.h" - -namespace gpu { - -class TransformBuffer { -public: - - TransformBuffer() {} - ~TransformBuffer() {} - -protected: - BufferPointer _buffer; -}; -typedef std::shared_ptr TransformBufferPointer; - -}; - - -#endif From c1fa096e78847f9aef8ef95bd730105f5188bb66 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 16 May 2016 15:42:48 -0700 Subject: [PATCH 03/54] adding texcoord 1 on all the material/model and go fetch occlusion map with this uv instead of texcoor0. this allow for separate transforms just for occlusoin map --- libraries/fbx/src/FBXReader_Material.cpp | 8 ++++---- .../src/model-networking/ModelCache.cpp | 4 ++++ libraries/model/src/model/Material.cpp | 4 ++++ libraries/render-utils/src/MaterialTextures.slh | 16 +++++++++------- libraries/render-utils/src/model.slf | 4 +++- libraries/render-utils/src/model.slv | 2 ++ libraries/render-utils/src/model_lightmap.slf | 4 ++-- .../src/model_lightmap_normal_map.slf | 4 ++-- .../src/model_lightmap_normal_specular_map.slf | 4 ++-- .../src/model_lightmap_specular_map.slf | 4 ++-- libraries/render-utils/src/model_normal_map.slf | 4 +++- .../src/model_normal_specular_map.slf | 4 +++- .../render-utils/src/model_specular_map.slf | 4 +++- libraries/render-utils/src/model_translucent.slf | 6 ++++-- .../render-utils/src/model_translucent_unlit.slf | 2 +- libraries/render-utils/src/model_unlit.slf | 4 ++-- libraries/render-utils/src/skin_model.slv | 2 ++ .../render-utils/src/skin_model_normal_map.slv | 2 ++ 18 files changed, 54 insertions(+), 28 deletions(-) diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index e539f849c7..01878d6ccf 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -188,8 +188,8 @@ void FBXReader::consolidateFBXMaterials() { QString occlusionTextureID = occlusionTextures.value(material.materialID); if (occlusionTextureID.isNull()) { // 2nd chance - // For blender we use the ambient factor texture ONLY if the ambientFactor value is set to 0 - if (material.ambientFactor == 0.0) { + // For blender we use the ambient factor texture as AOMap ONLY if the ambientFactor value is > 0.0 + if (material.ambientFactor > 0.0f) { occlusionTextureID = ambientFactorTextures.value(material.materialID); } } @@ -208,8 +208,8 @@ void FBXReader::consolidateFBXMaterials() { QString ambientTextureID = ambientTextures.value(material.materialID); if (ambientTextureID.isNull()) { // 2nd chance - // For blender we use the ambient factor texture ONLY if the ambientFactor value is set to 1 - if (material.ambientFactor == 1.0) { + // For blender we use the ambient factor texture as Lightmap ONLY if the ambientFactor value is set to 0 + if (material.ambientFactor == 0.0f) { ambientTextureID = ambientFactorTextures.value(material.materialID); } } diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 8cd6d9b65e..40388e6123 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -418,6 +418,8 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, c auto map = std::make_shared(); map->setTextureSource(texture->_textureSource); + map->setTextureTransform(fbxTexture.transform); + return map; } @@ -427,6 +429,7 @@ model::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, Textu auto map = std::make_shared(); map->setTextureSource(texture->_textureSource); + return map; } @@ -475,6 +478,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur if (!material.occlusionTexture.filename.isEmpty()) { auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, NetworkTexture::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + map->setTextureTransform(material.occlusionTexture.transform); setTextureMap(MapChannel::OCCLUSION_MAP, map); } diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 53478be536..dbe3cabdeb 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -122,6 +122,10 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur _texMapArrayBuffer.edit()._texcoordTransforms[0] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4()); } + if (channel == MaterialKey::OCCLUSION_MAP) { + _texMapArrayBuffer.edit()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4()); + } + if (channel == MaterialKey::LIGHTMAP_MAP) { // update the texcoord1 with lightmap _texMapArrayBuffer.edit()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4()); diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index f9b1c76104..5cede16e13 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -90,7 +90,7 @@ float fetchOcclusionMap(vec2 uv) { <@endfunc@> -<@func fetchMaterialTextures(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, occlusion)@> +<@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive)@> <@if albedo@> vec4 <$albedo$> = (((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); <@endif@> @@ -106,12 +106,19 @@ float fetchOcclusionMap(vec2 uv) { <@if emissive@> vec3 <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(<$texcoord0$>) : vec3(0.0)); <@endif@> +<@endfunc@> + +<@func fetchMaterialTexturesCoord1(matKey, texcoord1, occlusion, lightmapVal)@> <@if occlusion@> - float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord0$>) : 1.0); + float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord1$>) : 1.0); +<@endif@> +<@if lightmapVal@> + vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>); <@endif@> <@endfunc@> + <@func declareMaterialLightmap()@> <$declareMaterialTexMapArrayBuffer()$> @@ -123,11 +130,6 @@ vec3 fetchLightmapMap(vec2 uv) { } <@endfunc@> -<@func fetchMaterialLightmap(texcoord1, lightmapVal)@> - vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>); -<@endfunc@> - - <@func tangentToViewSpace(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> { vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz); diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index f1dcc942c9..c1f5cb1f88 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -22,12 +22,14 @@ in vec4 _position; in vec3 _normal; in vec3 _color; in vec2 _texCoord0; +in vec2 _texCoord1; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index f1989dcf76..4d36673123 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -22,6 +22,7 @@ out vec3 _color; out float _alpha; out vec2 _texCoord0; +out vec2 _texCoord1; out vec4 _position; out vec3 _normal; @@ -31,6 +32,7 @@ void main(void) { TexMapArray texMapArray = getTexMapArray(); <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index 3afbbfd405..3a8cfde290 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -29,8 +29,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness)$> - <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> packDeferredFragmentLightmap( diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 9ccc6e5352..64c61e255d 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -30,8 +30,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel)$> - <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> vec3 viewNormal; <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$> 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 71909a789f..34a116eac1 100755 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf @@ -30,8 +30,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> - <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> vec3 viewNormal; <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$> diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index 5eefefdc29..4dbc10a834 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -29,8 +29,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> - <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> packDeferredFragmentLightmap( normalize(_normal), diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 519b41e17f..daaa1ed977 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -21,6 +21,7 @@ in vec4 _position; in vec2 _texCoord0; +in vec2 _texCoord1; in vec3 _normal; in vec3 _tangent; in vec3 _color; @@ -28,7 +29,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index 2529596818..dd2d3cc951 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -21,6 +21,7 @@ in vec4 _position; in vec2 _texCoord0; +in vec2 _texCoord1; in vec3 _normal; in vec3 _tangent; in vec3 _color; @@ -28,7 +29,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, occlusionTex)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 3cbb060ab5..f0fe20293c 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -21,6 +21,7 @@ in vec4 _position; in vec2 _texCoord0; +in vec2 _texCoord1; in vec3 _normal; in vec3 _color; @@ -28,7 +29,8 @@ in vec3 _color; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 27a22a9763..8f62a3a3e0 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -25,6 +25,7 @@ <$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> in vec2 _texCoord0; +in vec2 _texCoord1; in vec4 _position; in vec3 _normal; in vec3 _color; @@ -35,7 +36,8 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex)$> + <$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$> float opacity = getMaterialOpacity(mat) * _alpha; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; @@ -61,7 +63,7 @@ void main(void) { _fragColor = vec4(evalGlobalLightingAlphaBlended( cam._viewInverse, 1.0, - 1.0, + occlusionTex, fragPosition, fragNormal, albedo, diff --git a/libraries/render-utils/src/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf index b9d6c64d6f..e2676636bf 100644 --- a/libraries/render-utils/src/model_translucent_unlit.slf +++ b/libraries/render-utils/src/model_translucent_unlit.slf @@ -26,7 +26,7 @@ out vec4 _fragColor; void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = getMaterialOpacity(mat) * _alpha; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf index 50778153fb..3c2e4ae2e0 100644 --- a/libraries/render-utils/src/model_unlit.slf +++ b/libraries/render-utils/src/model_unlit.slf @@ -16,7 +16,7 @@ <@include model/Material.slh@> <@include MaterialTextures.slh@> -<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> +<$declareMaterialTextures(ALBEDO)$> in vec2 _texCoord0; in vec3 _normal; @@ -27,7 +27,7 @@ void main(void) { Material mat = getMaterial(); int matKey = getMaterialKey(mat); - <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex)$> float opacity = 1.0; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index c8501b8ddf..268b203e35 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -24,6 +24,7 @@ out vec4 _position; out vec2 _texCoord0; +out vec2 _texCoord1; out vec3 _normal; out vec3 _color; out float _alpha; @@ -40,6 +41,7 @@ void main(void) { TexMapArray texMapArray = getTexMapArray(); <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> // standard transform TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index db4b206405..05524385ef 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -24,6 +24,7 @@ out vec4 _position; out vec2 _texCoord0; +out vec2 _texCoord1; out vec3 _normal; out vec3 _tangent; out vec3 _color; @@ -42,6 +43,7 @@ void main(void) { TexMapArray texMapArray = getTexMapArray(); <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); From a12e56f8802b0e52d9683a683499aaefb6be2b43 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 16 May 2016 17:43:54 -0700 Subject: [PATCH 04/54] Fix forgotten vertex shader case --- libraries/render-utils/src/model_normal_map.slv | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index ded37923c2..e70d93f909 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -34,6 +34,7 @@ void main(void) { TexMapArray texMapArray = getTexMapArray(); <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$> // standard transform TransformCamera cam = getTransformCamera(); From d06c6e2a5967ef72a8333749623457d6820377f6 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 16 May 2016 17:54:42 -0700 Subject: [PATCH 05/54] Fix forgotten vertex shader case --- libraries/render-utils/src/model_normal_map.slv | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index e70d93f909..494e40ccff 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -22,6 +22,7 @@ out vec4 _position; out vec2 _texCoord0; +out vec2 _texCoord1; out vec3 _normal; out vec3 _tangent; out vec3 _color; From 7bd29c13b0fd28ec27252adf8caa15995ef73185 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 09:09:25 -0700 Subject: [PATCH 06/54] corrected oculus touch rotation and converted hand pose to avatar coordinate system --- .../oculus/src/OculusControllerManager.cpp | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 09ab6ec159..822b751ec4 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -220,12 +220,51 @@ void OculusControllerManager::TouchDevice::focusOutEvent() { void OculusControllerManager::TouchDevice::handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose) { + // When the sensor-to-world rotation is identity the coordinate axes look like this: + // + // user + // forward + // -z + // | + // y| user + // y o----x right + // o-----x user + // | up + // | + // z + // + // Rift + + // From ABOVE the hand canonical axes looks like this: + // + // | | | | y | | | | + // | | | | | | | | | + // | | | | | + // |left | / x---- + \ |right| + // | _/ z \_ | + // | | | | + // | | | | + // + + // So when the user is in Rift space facing the -zAxis with hands outstretched and palms down + // the rotation to align the Touch axes with those of the hands is: + // + // touchToHand = halfTurnAboutY * quaterTurnAboutX auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND; auto& pose = _poseStateMap[poseId]; + + static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y); + static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X); + static const glm::quat touchToHand = yFlip * quarterX; + pose.translation = toGlm(handPose.ThePose.Position); - pose.rotation = toGlm(handPose.ThePose.Orientation); + pose.rotation = toGlm(handPose.ThePose.Orientation)*touchToHand; pose.angularVelocity = toGlm(handPose.AngularVelocity); pose.velocity = toGlm(handPose.LinearVelocity); + + // transform into avatar frame + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + pose = pose.transform(controllerToAvatar); } controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const { From 0035774eb27099076a06c9fed670ed82a8946b3a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 25 May 2016 14:57:34 -0700 Subject: [PATCH 07/54] Fix for models exported from Daz3D. The way post rotations were being applied was incorrect. I guess we've never tried a model that used the Maya Rotate Axis property before... --- libraries/fbx/src/FBXReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 12cd0b0a91..e6f2741098 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -759,7 +759,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS model.preTransform = glm::translate(rotationOffset) * glm::translate(rotationPivot); model.preRotation = glm::quat(glm::radians(preRotation)); model.rotation = glm::quat(glm::radians(rotation)); - model.postRotation = glm::quat(glm::radians(postRotation)); + model.postRotation = glm::inverse(glm::quat(glm::radians(postRotation))); model.postTransform = glm::translate(-rotationPivot) * glm::translate(scaleOffset) * glm::translate(scalePivot) * glm::scale(scale) * glm::translate(-scalePivot); // NOTE: angles from the FBX file are in degrees From 99846677421f44e2a5fe1caea508cc1c431e9ddf Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 10:09:41 -0700 Subject: [PATCH 08/54] touch properly sets pose.valid and further corrected hand rotation --- .../oculus/src/OculusControllerManager.cpp | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 822b751ec4..f19282a8f2 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -183,6 +183,8 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control ++numTrackedControllers; if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) { handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]); + } else { + _poseStateMap[hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND].valid = false; } }); using namespace controller; @@ -250,6 +252,25 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, // the rotation to align the Touch axes with those of the hands is: // // touchToHand = halfTurnAboutY * quaterTurnAboutX + + // Due to how the Touch controllers fit into the palm there is an offset that is different for each hand. + // You can think of this offset as the inverse of the measured rotation when the hands are posed, such that + // the combination (measurement * offset) is identity at this orientation. + // + // Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down) + // + // An approximate offset for the Touch can be obtained by inspection: + // + // Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) + // + // So the full equation is: + // + // Q = combinedMeasurement * touchToHand + // + // Q = (deltaQ * QOffset) * (yFlip * quarterTurnAboutX) + // + // Q = (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX) + auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND; auto& pose = _poseStateMap[poseId]; @@ -257,10 +278,15 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X); static const glm::quat touchToHand = yFlip * quarterX; + static const float sign = (hand == ovrHand_Left ? 1.0f : -1.0f); + static const glm::quat signedQuarterZ = glm::angleAxis(sign * PI_OVER_TWO, Vectors::UNIT_Z); + static const glm::quat signedRotationOffset = glm::inverse(signedQuarterZ) * touchToHand; + pose.translation = toGlm(handPose.ThePose.Position); - pose.rotation = toGlm(handPose.ThePose.Orientation)*touchToHand; + pose.rotation = toGlm(handPose.ThePose.Orientation)*signedRotationOffset; pose.angularVelocity = toGlm(handPose.AngularVelocity); pose.velocity = toGlm(handPose.LinearVelocity); + pose.valid = true; // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; From c9ea85e659302e8df170aa9beb460087a0275278 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 10:50:22 -0700 Subject: [PATCH 09/54] fixed left hand rotation --- plugins/oculus/src/OculusControllerManager.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index f19282a8f2..2fd48bb611 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -278,12 +278,16 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X); static const glm::quat touchToHand = yFlip * quarterX; - static const float sign = (hand == ovrHand_Left ? 1.0f : -1.0f); - static const glm::quat signedQuarterZ = glm::angleAxis(sign * PI_OVER_TWO, Vectors::UNIT_Z); - static const glm::quat signedRotationOffset = glm::inverse(signedQuarterZ) * touchToHand; + static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z); + static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z); + + static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand; + static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; + + auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset); pose.translation = toGlm(handPose.ThePose.Position); - pose.rotation = toGlm(handPose.ThePose.Orientation)*signedRotationOffset; + pose.rotation = toGlm(handPose.ThePose.Orientation)*rotationOffset; pose.angularVelocity = toGlm(handPose.AngularVelocity); pose.velocity = toGlm(handPose.LinearVelocity); pose.valid = true; From 6ca02dcad24d4a1a1fa195120c6e24c47509252c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 12:11:13 -0700 Subject: [PATCH 10/54] expose Controller.triggerHapticPulse to javascript (currently does nothing) --- .../controllers/src/controllers/InputDevice.h | 5 +- .../src/controllers/ScriptingInterface.cpp | 104 +++++++++--------- .../src/controllers/ScriptingInterface.h | 6 +- .../src/controllers/UserInputMapper.cpp | 8 ++ .../src/controllers/UserInputMapper.h | 1 + 5 files changed, 71 insertions(+), 53 deletions(-) diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index afb1f7d1f7..3c8e728f4d 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -51,10 +51,13 @@ public: float getValue(const Input& input) const; float getValue(ChannelType channelType, uint16_t channel) const; - Pose getPoseValue(uint16_t channel) const; + Pose getPoseValue(uint16_t channel) const; const QString& getName() const { return _name; } + // By default, Input Devices do not support haptics + virtual bool triggerHapticPulse(float strength, float duration, bool leftHand) { return false; } + // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas virtual void update(float deltaTime, const InputCalibrationData& inputCalibrationData) {}; diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index c2e64ca19e..a7d9270ddf 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -76,69 +76,73 @@ controller::ScriptingInterface::ScriptingInterface() { namespace controller { - QObject* ScriptingInterface::newMapping(const QString& mappingName) { - auto userInputMapper = DependencyManager::get(); - return new MappingBuilderProxy(*userInputMapper, userInputMapper->newMapping(mappingName)); - } + QObject* ScriptingInterface::newMapping(const QString& mappingName) { + auto userInputMapper = DependencyManager::get(); + return new MappingBuilderProxy(*userInputMapper, userInputMapper->newMapping(mappingName)); + } - void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->enableMapping(mappingName, enable); - } + void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->enableMapping(mappingName, enable); + } - float ScriptingInterface::getValue(const int& source) const { - auto userInputMapper = DependencyManager::get(); - return userInputMapper->getValue(Input((uint32_t)source)); - } + float ScriptingInterface::getValue(const int& source) const { + auto userInputMapper = DependencyManager::get(); + return userInputMapper->getValue(Input((uint32_t)source)); + } - float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { - return getValue(Input(device, source, ChannelType::BUTTON).getID()); - } + float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { + return getValue(Input(device, source, ChannelType::BUTTON).getID()); + } - float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { - return getValue(Input(device, source, ChannelType::AXIS).getID()); - } + float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { + return getValue(Input(device, source, ChannelType::AXIS).getID()); + } - Pose ScriptingInterface::getPoseValue(const int& source) const { - auto userInputMapper = DependencyManager::get(); - return userInputMapper->getPose(Input((uint32_t)source)); - } - - Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { - return getPoseValue(Input(device, source, ChannelType::POSE).getID()); - } + Pose ScriptingInterface::getPoseValue(const int& source) const { + auto userInputMapper = DependencyManager::get(); + return userInputMapper->getPose(Input((uint32_t)source)); + } - QVector ScriptingInterface::getAllActions() { - return DependencyManager::get()->getAllActions(); - } + Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { + return getPoseValue(Input(device, source, ChannelType::POSE).getID()); + } - QString ScriptingInterface::getDeviceName(unsigned int device) { - return DependencyManager::get()->getDeviceName((unsigned short)device); - } + QVector ScriptingInterface::getAllActions() { + return DependencyManager::get()->getAllActions(); + } - QVector ScriptingInterface::getAvailableInputs(unsigned int device) { - return DependencyManager::get()->getAvailableInputs((unsigned short)device); - } + QString ScriptingInterface::getDeviceName(unsigned int device) { + return DependencyManager::get()->getDeviceName((unsigned short)device); + } - int ScriptingInterface::findDevice(QString name) { - return DependencyManager::get()->findDevice(name); - } + QVector ScriptingInterface::getAvailableInputs(unsigned int device) { + return DependencyManager::get()->getAvailableInputs((unsigned short)device); + } - QVector ScriptingInterface::getDeviceNames() { - return DependencyManager::get()->getDeviceNames(); - } + int ScriptingInterface::findDevice(QString name) { + return DependencyManager::get()->findDevice(name); + } - float ScriptingInterface::getActionValue(int action) { - return DependencyManager::get()->getActionState(Action(action)); - } + QVector ScriptingInterface::getDeviceNames() { + return DependencyManager::get()->getDeviceNames(); + } - int ScriptingInterface::findAction(QString actionName) { - return DependencyManager::get()->findAction(actionName); - } + float ScriptingInterface::getActionValue(int action) { + return DependencyManager::get()->getActionState(Action(action)); + } - QVector ScriptingInterface::getActionNames() const { - return DependencyManager::get()->getActionNames(); - } + int ScriptingInterface::findAction(QString actionName) { + return DependencyManager::get()->findAction(actionName); + } + + QVector ScriptingInterface::getActionNames() const { + return DependencyManager::get()->getActionNames(); + } + + bool ScriptingInterface::triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand) const { + return DependencyManager::get()->triggerHapticPulse(device, strength, duration, leftHand); + } void ScriptingInterface::updateMaps() { QVariantMap newHardware; diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index f30212a09e..7f7120a907 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -77,12 +77,14 @@ namespace controller { Q_INVOKABLE QVector getDeviceNames(); Q_INVOKABLE int findAction(QString actionName); Q_INVOKABLE QVector getActionNames() const; - + Q_INVOKABLE float getValue(const int& source) const; Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; Q_INVOKABLE Pose getPoseValue(const int& source) const; - Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + + Q_INVOKABLE bool triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand = true) const; Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index c1ee3ce36c..2c9138e120 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -336,6 +336,14 @@ QVector UserInputMapper::getActionNames() const { return result; } +bool UserInputMapper::triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand) { + Locker locker(_lock); + if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { + return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, leftHand); + } + return false; +} + int actionMetaTypeId = qRegisterMetaType(); int inputMetaTypeId = qRegisterMetaType(); int inputPairMetaTypeId = qRegisterMetaType(); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 9c79415b6e..ac60247e8e 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -89,6 +89,7 @@ namespace controller { void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; } void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; } void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; } + bool triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand); static Input makeStandardInput(controller::StandardButtonChannel button); static Input makeStandardInput(controller::StandardAxisChannel axis); From 642438a2596c8ea6d4d7f3fb7b55c11deb7d4545 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 12:18:56 -0700 Subject: [PATCH 11/54] fix tabs --- .../controllers/src/controllers/InputDevice.h | 6 +- .../src/controllers/ScriptingInterface.cpp | 106 +++++++++--------- .../src/controllers/ScriptingInterface.h | 6 +- .../src/controllers/UserInputMapper.cpp | 10 +- .../src/controllers/UserInputMapper.h | 2 +- 5 files changed, 65 insertions(+), 65 deletions(-) diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 3c8e728f4d..cc158497e0 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -51,12 +51,12 @@ public: float getValue(const Input& input) const; float getValue(ChannelType channelType, uint16_t channel) const; - Pose getPoseValue(uint16_t channel) const; + Pose getPoseValue(uint16_t channel) const; const QString& getName() const { return _name; } - // By default, Input Devices do not support haptics - virtual bool triggerHapticPulse(float strength, float duration, bool leftHand) { return false; } + // By default, Input Devices do not support haptics + virtual bool triggerHapticPulse(float strength, float duration, bool leftHand) { return false; } // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index a7d9270ddf..97b7a9ddd9 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -76,73 +76,73 @@ controller::ScriptingInterface::ScriptingInterface() { namespace controller { - QObject* ScriptingInterface::newMapping(const QString& mappingName) { - auto userInputMapper = DependencyManager::get(); - return new MappingBuilderProxy(*userInputMapper, userInputMapper->newMapping(mappingName)); - } + QObject* ScriptingInterface::newMapping(const QString& mappingName) { + auto userInputMapper = DependencyManager::get(); + return new MappingBuilderProxy(*userInputMapper, userInputMapper->newMapping(mappingName)); + } - void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->enableMapping(mappingName, enable); - } + void ScriptingInterface::enableMapping(const QString& mappingName, bool enable) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->enableMapping(mappingName, enable); + } - float ScriptingInterface::getValue(const int& source) const { - auto userInputMapper = DependencyManager::get(); - return userInputMapper->getValue(Input((uint32_t)source)); - } + float ScriptingInterface::getValue(const int& source) const { + auto userInputMapper = DependencyManager::get(); + return userInputMapper->getValue(Input((uint32_t)source)); + } - float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { - return getValue(Input(device, source, ChannelType::BUTTON).getID()); - } + float ScriptingInterface::getButtonValue(StandardButtonChannel source, uint16_t device) const { + return getValue(Input(device, source, ChannelType::BUTTON).getID()); + } - float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { - return getValue(Input(device, source, ChannelType::AXIS).getID()); - } + float ScriptingInterface::getAxisValue(StandardAxisChannel source, uint16_t device) const { + return getValue(Input(device, source, ChannelType::AXIS).getID()); + } - Pose ScriptingInterface::getPoseValue(const int& source) const { - auto userInputMapper = DependencyManager::get(); - return userInputMapper->getPose(Input((uint32_t)source)); - } + Pose ScriptingInterface::getPoseValue(const int& source) const { + auto userInputMapper = DependencyManager::get(); + return userInputMapper->getPose(Input((uint32_t)source)); + } + + Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { + return getPoseValue(Input(device, source, ChannelType::POSE).getID()); + } - Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { - return getPoseValue(Input(device, source, ChannelType::POSE).getID()); - } + QVector ScriptingInterface::getAllActions() { + return DependencyManager::get()->getAllActions(); + } - QVector ScriptingInterface::getAllActions() { - return DependencyManager::get()->getAllActions(); - } + QString ScriptingInterface::getDeviceName(unsigned int device) { + return DependencyManager::get()->getDeviceName((unsigned short)device); + } - QString ScriptingInterface::getDeviceName(unsigned int device) { - return DependencyManager::get()->getDeviceName((unsigned short)device); - } + QVector ScriptingInterface::getAvailableInputs(unsigned int device) { + return DependencyManager::get()->getAvailableInputs((unsigned short)device); + } - QVector ScriptingInterface::getAvailableInputs(unsigned int device) { - return DependencyManager::get()->getAvailableInputs((unsigned short)device); - } + int ScriptingInterface::findDevice(QString name) { + return DependencyManager::get()->findDevice(name); + } - int ScriptingInterface::findDevice(QString name) { - return DependencyManager::get()->findDevice(name); - } + QVector ScriptingInterface::getDeviceNames() { + return DependencyManager::get()->getDeviceNames(); + } - QVector ScriptingInterface::getDeviceNames() { - return DependencyManager::get()->getDeviceNames(); - } + float ScriptingInterface::getActionValue(int action) { + return DependencyManager::get()->getActionState(Action(action)); + } - float ScriptingInterface::getActionValue(int action) { - return DependencyManager::get()->getActionState(Action(action)); - } + int ScriptingInterface::findAction(QString actionName) { + return DependencyManager::get()->findAction(actionName); + } - int ScriptingInterface::findAction(QString actionName) { - return DependencyManager::get()->findAction(actionName); - } + QVector ScriptingInterface::getActionNames() const { + return DependencyManager::get()->getActionNames(); + } - QVector ScriptingInterface::getActionNames() const { - return DependencyManager::get()->getActionNames(); - } - - bool ScriptingInterface::triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand) const { - return DependencyManager::get()->triggerHapticPulse(device, strength, duration, leftHand); - } + bool ScriptingInterface::triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand) const { + return DependencyManager::get()->triggerHapticPulse(device, strength, duration, leftHand); + } void ScriptingInterface::updateMaps() { QVariantMap newHardware; diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 7f7120a907..cce159a9a7 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -77,14 +77,14 @@ namespace controller { Q_INVOKABLE QVector getDeviceNames(); Q_INVOKABLE int findAction(QString actionName); Q_INVOKABLE QVector getActionNames() const; - + Q_INVOKABLE float getValue(const int& source) const; Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; Q_INVOKABLE Pose getPoseValue(const int& source) const; - Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; - Q_INVOKABLE bool triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand = true) const; + Q_INVOKABLE bool triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand = true) const; Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 2c9138e120..c7c62ad7d9 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -337,11 +337,11 @@ QVector UserInputMapper::getActionNames() const { } bool UserInputMapper::triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand) { - Locker locker(_lock); - if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { - return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, leftHand); - } - return false; + Locker locker(_lock); + if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { + return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, leftHand); + } + return false; } int actionMetaTypeId = qRegisterMetaType(); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index ac60247e8e..b23657fff7 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -89,7 +89,7 @@ namespace controller { void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; } void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; } void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; } - bool triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand); + bool triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand); static Input makeStandardInput(controller::StandardButtonChannel button); static Input makeStandardInput(controller::StandardAxisChannel axis); From 69971a3439163e912a5c677edcf6796ec234687f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 12:20:05 -0700 Subject: [PATCH 12/54] fix one more tab --- libraries/controllers/src/controllers/ScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index cce159a9a7..015ec25454 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -77,7 +77,7 @@ namespace controller { Q_INVOKABLE QVector getDeviceNames(); Q_INVOKABLE int findAction(QString actionName); Q_INVOKABLE QVector getActionNames() const; - + Q_INVOKABLE float getValue(const int& source) const; Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; From bf920c2b80e1041dafec8ca8c7bd19c0bd630ebd Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:16:39 -0700 Subject: [PATCH 13/54] Compact Domain heartbeat JSON --- 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 052a7c0fec..231e9ba014 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1121,7 +1121,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { domainObject[DOMAIN_HEARTBEAT_KEY] = heartbeatObject; - QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson())); + QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Required, From 87e27d9570b9419802ddbed6f664d42baf912db8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:16:02 -0700 Subject: [PATCH 14/54] Factor out metadata generation from heartbeat --- domain-server/src/DomainServer.cpp | 79 ++++++++++++++++-------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 231e9ba014..ae3c26a34d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1067,62 +1067,69 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) sendHeartbeatToMetaverse(newPublicSockAddr.getAddress().toString()); } - -void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { - const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - - auto nodeList = DependencyManager::get(); - const QUuid& domainID = nodeList->getSessionUUID(); - - // setup the domain object to send to the data server - const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; - const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking"; - - QJsonObject domainObject; - if (!networkAddress.isEmpty()) { - domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress; - } - - domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting; - - // add a flag to indicate if this domain uses restricted access - for now that will exclude it from listings - const QString RESTRICTED_ACCESS_FLAG = "restricted"; - - domainObject[RESTRICTED_ACCESS_FLAG] = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - - // figure out the breakdown of currently connected interface clients - int numConnectedUnassigned = 0; - QJsonObject userHostnames; - +QVariantMap getMetadata() { static const QString DEFAULT_HOSTNAME = "*"; + auto nodeList = DependencyManager::get(); + int numConnectedUnassigned = 0; + QVariantMap userHostnames; + + // figure out the breakdown of currently connected interface clients nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { - if (node->getLinkedData()) { - auto nodeData = static_cast(node->getLinkedData()); + auto linkedData = node->getLinkedData(); + if (linkedData) { + auto nodeData = static_cast(linkedData); if (!nodeData->wasAssigned()) { ++numConnectedUnassigned; // increment the count for this hostname (or the default if we don't have one) - auto hostname = nodeData->getPlaceName().isEmpty() ? DEFAULT_HOSTNAME : nodeData->getPlaceName(); + auto placeName = nodeData->getPlaceName(); + auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; userHostnames[hostname] = userHostnames[hostname].toInt() + 1; } } }); - static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + QVariantMap metadata; + static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; + metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; + metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - QJsonObject heartbeatObject; - heartbeatObject[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - heartbeatObject[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + return metadata; +} - domainObject[DOMAIN_HEARTBEAT_KEY] = heartbeatObject; +void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { + auto nodeList = DependencyManager::get(); + const QUuid& domainID = nodeList->getSessionUUID(); + + // Setup the domain object to send to the data server + QJsonObject domainObject; + + if (!networkAddress.isEmpty()) { + static const QString PUBLIC_NETWORK_ADDRESS_KEY = "network_address"; + domainObject[PUBLIC_NETWORK_ADDRESS_KEY] = networkAddress; + } + + static const QString AUTOMATIC_NETWORKING_KEY = "automatic_networking"; + domainObject[AUTOMATIC_NETWORKING_KEY] = _automaticNetworkingSetting; + + // Add a flag to indicate if this domain uses restricted access - + // for now that will exclude it from listings + static const QString RESTRICTED_ACCESS_FLAG = "restricted"; + domainObject[RESTRICTED_ACCESS_FLAG] = + _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + + // Add the metadata to the heartbeat + static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + domainObject[DOMAIN_HEARTBEAT_KEY] = QJsonObject::fromVariantMap(getMetadata()); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); + static const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManagerAuth::Required, QNetworkAccessManager::PutOperation, From 18696144f1c29e383d0bd2056395c6f8573fa19a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:23:47 -0700 Subject: [PATCH 15/54] Move metadata generation to DomainMetadata --- domain-server/src/DomainMetadata.cpp | 51 ++++++++++++++++++++++++++++ domain-server/src/DomainMetadata.h | 21 ++++++++++++ domain-server/src/DomainServer.cpp | 35 ------------------- domain-server/src/DomainServer.h | 1 + 4 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 domain-server/src/DomainMetadata.cpp create mode 100644 domain-server/src/DomainMetadata.h diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp new file mode 100644 index 0000000000..f584198b51 --- /dev/null +++ b/domain-server/src/DomainMetadata.cpp @@ -0,0 +1,51 @@ +// +// DomainMetadata.cpp +// domain-server/src +// +// Created by Zach Pomerantz on 5/25/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include "DomainMetadata.h" + +#include +#include + +#include "DomainServerNodeData.h" + +QVariantMap getMetadata() { + static const QString DEFAULT_HOSTNAME = "*"; + + auto nodeList = DependencyManager::get(); + int numConnectedUnassigned = 0; + QVariantMap userHostnames; + + // figure out the breakdown of currently connected interface clients + nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { + auto linkedData = node->getLinkedData(); + if (linkedData) { + auto nodeData = static_cast(linkedData); + + if (!nodeData->wasAssigned()) { + ++numConnectedUnassigned; + + // increment the count for this hostname (or the default if we don't have one) + auto placeName = nodeData->getPlaceName(); + auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; + userHostnames[hostname] = userHostnames[hostname].toInt() + 1; + } + } + }); + + QVariantMap metadata; + + static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; + metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + + static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; + metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + + return metadata; +} diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h new file mode 100644 index 0000000000..3cd160ce85 --- /dev/null +++ b/domain-server/src/DomainMetadata.h @@ -0,0 +1,21 @@ +// +// DomainMetadata.h +// domain-server/src +// +// Created by Zach Pomerantz on 5/25/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#ifndef hifi_DomainMetadata_h +#define hifi_DomainMetadata_h + +#include + +QVariantMap getMetadata(); + +// TODO: Encapsulate +class DomainMetadata { }; + +#endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ae3c26a34d..f05dfd2c6d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1067,41 +1067,6 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr) sendHeartbeatToMetaverse(newPublicSockAddr.getAddress().toString()); } -QVariantMap getMetadata() { - static const QString DEFAULT_HOSTNAME = "*"; - - auto nodeList = DependencyManager::get(); - int numConnectedUnassigned = 0; - QVariantMap userHostnames; - - // figure out the breakdown of currently connected interface clients - nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { - auto linkedData = node->getLinkedData(); - if (linkedData) { - auto nodeData = static_cast(linkedData); - - if (!nodeData->wasAssigned()) { - ++numConnectedUnassigned; - - // increment the count for this hostname (or the default if we don't have one) - auto placeName = nodeData->getPlaceName(); - auto hostname = placeName.isEmpty() ? DEFAULT_HOSTNAME : placeName; - userHostnames[hostname] = userHostnames[hostname].toInt() + 1; - } - } - }); - - QVariantMap metadata; - - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - - static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - - return metadata; -} - void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { auto nodeList = DependencyManager::get(); const QUuid& domainID = nodeList->getSessionUUID(); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index c39e405380..0f93c50468 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -26,6 +26,7 @@ #include #include "DomainGatekeeper.h" +#include "DomainMetadata.h" #include "DomainServerSettingsManager.h" #include "DomainServerWebSessionData.h" #include "WalletTransaction.h" From b13e7a1a8f48cb61e7862591f5927a04cbf5abe5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 25 May 2016 12:35:52 -0700 Subject: [PATCH 16/54] Encapsulate metadata in DomainMetadata --- domain-server/src/DomainMetadata.cpp | 12 ++++++------ domain-server/src/DomainMetadata.h | 15 ++++++++++++--- domain-server/src/DomainServer.cpp | 2 +- domain-server/src/DomainServer.h | 2 ++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index f584198b51..224fe1939b 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,7 +15,7 @@ #include "DomainServerNodeData.h" -QVariantMap getMetadata() { +void DomainMetadata::generate() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); @@ -39,13 +39,13 @@ QVariantMap getMetadata() { } }); - QVariantMap metadata; - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; + _metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + _metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; - return metadata; +#if DEV_BUILD + qDebug() << "Regenerated domain metadata - users:" << _metadata; +#endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 3cd160ce85..5096f1bb3e 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -12,10 +12,19 @@ #define hifi_DomainMetadata_h #include +#include -QVariantMap getMetadata(); +class DomainMetadata { +public: + QVariantMap toVariantMap() { generate(); return _metadata; } + QJsonObject toJSON() { generate(); return QJsonObject::fromVariantMap(_metadata); } -// TODO: Encapsulate -class DomainMetadata { }; +protected slots: + // TODO: Connect appropriate signals to obviate JIT generation + void generate(); + +protected: + QVariantMap _metadata; +}; #endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f05dfd2c6d..9b1fbb1d84 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1090,7 +1090,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; - domainObject[DOMAIN_HEARTBEAT_KEY] = QJsonObject::fromVariantMap(getMetadata()); + domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.toJSON(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 0f93c50468..0a1df41f50 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -168,6 +168,8 @@ private: DomainServerSettingsManager _settingsManager; + DomainMetadata _metadata; + HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; From 079f6af2cc3c07d881c23d01c2da32f2eb6866b0 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 2 Jun 2016 16:14:46 -0700 Subject: [PATCH 17/54] Fixing the gamma correction for the debug view of occlusion --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 6dfec30b16..dc46b5d897 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -83,7 +83,7 @@ static const std::string DEFAULT_NORMAL_SHADER { static const std::string DEFAULT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - " return vec4(vec3(frag.obscurance), 1.0);" + " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" " }" }; From 681da201fc7dfcec6f9649be1b11972ccab97657 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 2 Jun 2016 16:25:14 -0700 Subject: [PATCH 18/54] COrrect the name of the Unlit dbug view --- scripts/developer/utilities/render/framebuffer.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/developer/utilities/render/framebuffer.qml b/scripts/developer/utilities/render/framebuffer.qml index 0d8d85cc32..1612f59276 100644 --- a/scripts/developer/utilities/render/framebuffer.qml +++ b/scripts/developer/utilities/render/framebuffer.qml @@ -33,7 +33,7 @@ Column { "Roughness", "Metallic", "Emissive", - "Shaded/Lightmapped/Unlit", + "Unlit", "Occlusion", "Lightmap", "Lighting", From 8b76af531bf326a0e707ce4760f4600218611784 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 16:52:17 -0700 Subject: [PATCH 19/54] made touch hand orientation more comfortable, fixed all the touch key mappings, exposed capacitive touch keys for use later --- .../resources/controllers/oculus_touch.json | 36 ++++++-- .../oculus/src/OculusControllerManager.cpp | 86 +++++++++++++++---- 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index cc8c2f8bdc..8cb512a526 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -1,22 +1,42 @@ { "name": "Oculus Touch to Standard", "channels": [ - { "from": "OculusTouch.LY", "filters": "invert", "to": "Standard.LY" }, - { "from": "OculusTouch.LX", "to": "Standard.LX" }, + { "from": "OculusTouch.A", "to": "Standard.A" }, + { "from": "OculusTouch.B", "to": "Standard.B" }, + { "from": "OculusTouch.X", "to": "Standard.X" }, + { "from": "OculusTouch.Y", "to": "Standard.Y" }, + + { "from": "OculusTouch.LY", "filters": "invert", "to": "Standard.LY" }, + { "from": "OculusTouch.LX", "to": "Standard.LX" }, { "from": "OculusTouch.LT", "to": "Standard.LT" }, + { "from": "OculusTouch.LS", "to": "Standard.LS" }, + { "from": "OculusTouch.LG", "to": "Standard.LG" }, + { "from": "OculusTouch.LeftGrip", "to": "Standard.LB" }, + { "from": "OculusTouch.LeftHand", "to": "Standard.LeftHand" }, - { "from": "OculusTouch.RY", "filters": "invert", "to": "Standard.RY" }, - { "from": "OculusTouch.RX", "to": "Standard.RX" }, - + { "from": "OculusTouch.RY", "filters": "invert", "to": "Standard.RY" }, + { "from": "OculusTouch.RX", "to": "Standard.RX" }, { "from": "OculusTouch.RT", "to": "Standard.RT" }, - { "from": "OculusTouch.RB", "to": "Standard.RB" }, { "from": "OculusTouch.RS", "to": "Standard.RS" }, + { "from": "OculusTouch.RG", "to": "Standard.RG" }, + { "from": "OculusTouch.RightGrip", "to": "Standard.RB" }, + { "from": "OculusTouch.RightHand", "to": "Standard.RightHand" }, { "from": "OculusTouch.LeftApplicationMenu", "to": "Standard.Back" }, { "from": "OculusTouch.RightApplicationMenu", "to": "Standard.Start" }, - { "from": "OculusTouch.LeftHand", "to": "Standard.LeftHand" }, - { "from": "OculusTouch.RightHand", "to": "Standard.RightHand" } + { "from": "OculusTouch.LeftPrimaryThumbTouch", "to": "Standard.LeftPrimaryThumbTouch" }, + { "from": "OculusTouch.LeftSecondaryThumbTouch", "to": "Standard.LeftSecondaryThumbTouch" }, + { "from": "OculusTouch.RightPrimaryThumbTouch", "to": "Standard.RightPrimaryThumbTouch" }, + { "from": "OculusTouch.RightSecondaryThumbTouch", "to": "Standard.RightSecondaryThumbTouch" }, + { "from": "OculusTouch.LeftPrimaryIndexTouch", "to": "Standard.LeftPrimaryIndexTouch" }, + { "from": "OculusTouch.RightPrimaryIndexTouch", "to": "Standard.RightPrimaryIndexTouch" }, + { "from": "OculusTouch.LSTouch", "to": "Standard.LSTouch" }, + { "from": "OculusTouch.RSTouch", "to": "Standard.RSTouch" }, + { "from": "OculusTouch.LeftThumbUp", "to": "Standard.LeftThumbUp" }, + { "from": "OculusTouch.RightThumbUp", "to": "Standard.RightThumbUp" }, + { "from": "OculusTouch.LeftIndexPoint", "to": "Standard.LeftIndexPoint" }, + { "from": "OculusTouch.RightIndexPoint", "to": "Standard.RightIndexPoint" } ] } diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 2fd48bb611..e84fdcbfc7 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -120,14 +120,14 @@ static const std::vector> BUTTON_MAP { ovrButton_B, B }, { ovrButton_LThumb, LS }, { ovrButton_RThumb, RS }, - { ovrButton_LShoulder, LB }, - { ovrButton_RShoulder, RB }, + //{ ovrButton_LShoulder, LB }, + //{ ovrButton_RShoulder, RB }, } }; static const std::vector> TOUCH_MAP { { - { ovrTouch_X, LEFT_SECONDARY_THUMB_TOUCH }, + { ovrTouch_X, LEFT_PRIMARY_THUMB_TOUCH }, { ovrTouch_Y, LEFT_SECONDARY_THUMB_TOUCH }, - { ovrTouch_A, RIGHT_SECONDARY_THUMB_TOUCH }, + { ovrTouch_A, RIGHT_PRIMARY_THUMB_TOUCH }, { ovrTouch_B, RIGHT_SECONDARY_THUMB_TOUCH }, { ovrTouch_LIndexTrigger, LEFT_PRIMARY_INDEX_TOUCH }, { ovrTouch_RIndexTrigger, RIGHT_PRIMARY_INDEX_TOUCH }, @@ -173,6 +173,11 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { } void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + // Check past values of button map for hysteresis before clearing map + const float HYSTERESIS_OFFSET = -0.1f; + float LEFT_HYSTERESIS_OFFSET = _buttonPressedMap.find(LEFT_GRIP) != _buttonPressedMap.end() ? HYSTERESIS_OFFSET : 0.0f; + float RIGHT_HYSTERESIS_OFFSET = _buttonPressedMap.find(RIGHT_GRIP) != _buttonPressedMap.end() ? HYSTERESIS_OFFSET : 0.0f; + _poseStateMap.clear(); _buttonPressedMap.clear(); @@ -206,6 +211,16 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control _buttonPressedMap.insert(pair.second); } } + // Map pressed hand triggers to grip buttons + // This is temporary in order to support the grab/equip scripts + const float handTriggerThreshold = 0.9f; + if (inputState.HandTrigger[ovrHand_Left] >= handTriggerThreshold + LEFT_HYSTERESIS_OFFSET) { + _buttonPressedMap.insert(LEFT_GRIP); + } + if (inputState.HandTrigger[ovrHand_Right] >= handTriggerThreshold + RIGHT_HYSTERESIS_OFFSET) { + _buttonPressedMap.insert(RIGHT_GRIP); + } + // Touches for (const auto& pair : TOUCH_MAP) { if (inputState.Touches & pair.first) { @@ -261,7 +276,7 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, // // An approximate offset for the Touch can be obtained by inspection: // - // Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) + // Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) * glm::angleAxis(PI/4.0f, xAxis)) // // So the full equation is: // @@ -280,14 +295,26 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z); static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z); + static const glm::quat eighthX = glm::angleAxis(PI / 4.0f, Vectors::UNIT_X); - static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand; - static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; + static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ * eighthX) * touchToHand; + static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ * eighthX) * touchToHand; + static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches + static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, + CONTROLLER_LENGTH_OFFSET / 2.0f, + CONTROLLER_LENGTH_OFFSET * 2.0f); + static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; + static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; + + auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset); auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset); + glm::quat rotation = toGlm(handPose.ThePose.Orientation); + pose.translation = toGlm(handPose.ThePose.Position); - pose.rotation = toGlm(handPose.ThePose.Orientation)*rotationOffset; + pose.translation += rotation * translationOffset; + pose.rotation = rotation * rotationOffset; pose.angularVelocity = toGlm(handPose.AngularVelocity); pose.velocity = toGlm(handPose.LinearVelocity); pose.valid = true; @@ -300,27 +327,54 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ - // Trackpad analogs + // buttons + makePair(A, "A"), + makePair(B, "B"), + makePair(X, "X"), + makePair(Y, "Y"), + + // trackpad analogs makePair(LX, "LX"), makePair(LY, "LY"), makePair(RX, "RX"), makePair(RY, "RY"), - // trigger analogs + + // triggers makePair(LT, "LT"), makePair(RT, "RT"), - makePair(LB, "LB"), - makePair(RB, "RB"), + // trigger buttons + //makePair(LB, "LB"), + //makePair(RB, "RB"), + // side grip triggers + makePair(LG, "LG"), + makePair(RG, "RG"), + makePair(LEFT_GRIP, "LeftGrip"), + makePair(RIGHT_GRIP, "RightGrip"), + + // joystick buttons makePair(LS, "LS"), makePair(RS, "RS"), + makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), - makePair(LEFT_PRIMARY_THUMB, "LeftPrimaryThumb"), - makePair(LEFT_SECONDARY_THUMB, "LeftSecondaryThumb"), - makePair(RIGHT_PRIMARY_THUMB, "RightPrimaryThumb"), - makePair(RIGHT_SECONDARY_THUMB, "RightSecondaryThumb"), + makePair(LEFT_PRIMARY_THUMB_TOUCH, "LeftPrimaryThumbTouch"), + makePair(LEFT_SECONDARY_THUMB_TOUCH, "LeftSecondaryThumbTouch"), + makePair(RIGHT_PRIMARY_THUMB_TOUCH, "RightPrimaryThumbTouch"), + makePair(RIGHT_SECONDARY_THUMB_TOUCH, "RightSecondaryThumbTouch"), + makePair(LEFT_PRIMARY_INDEX_TOUCH, "LeftPrimaryIndexTouch"), + makePair(RIGHT_PRIMARY_INDEX_TOUCH, "RightPrimaryIndexTouch"), + makePair(LS_TOUCH, "LSTouch"), + makePair(RS_TOUCH, "RSTouch"), + makePair(LEFT_THUMB_UP, "LeftThumbUp"), + makePair(RIGHT_THUMB_UP, "RightThumbUp"), + makePair(LEFT_INDEX_POINT, "LeftIndexPoint"), + makePair(RIGHT_INDEX_POINT, "RightIndexPoint"), + + makePair(BACK, "LeftApplicationMenu"), + makePair(START, "RightApplicationMenu"), }; return availableInputs; } From 85055d82bfe9342cc297d0c0329cb6711aeadc5a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 17:05:58 -0700 Subject: [PATCH 20/54] Regenerate Domain metadata on user (dis)connect --- domain-server/src/DomainMetadata.cpp | 2 +- domain-server/src/DomainMetadata.h | 9 ++++--- domain-server/src/DomainServer.cpp | 36 +++++++++++++++++++--------- domain-server/src/DomainServer.h | 2 ++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 224fe1939b..c45a07e646 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,7 +15,7 @@ #include "DomainServerNodeData.h" -void DomainMetadata::generate() { +void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 5096f1bb3e..f92c40ce61 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -16,12 +16,11 @@ class DomainMetadata { public: - QVariantMap toVariantMap() { generate(); return _metadata; } - QJsonObject toJSON() { generate(); return QJsonObject::fromVariantMap(_metadata); } + QVariantMap toVariantMap() { return _metadata; } + QJsonObject toJSON() { return QJsonObject::fromVariantMap(_metadata); } -protected slots: - // TODO: Connect appropriate signals to obviate JIT generation - void generate(); +public slots: + void usersChanged(); protected: QVariantMap _metadata; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9b1fbb1d84..5a9fc816c5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -97,6 +97,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : // make sure we hear about newly connected nodes from our gatekeeper connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); + // update the metadata when a user (dis)connects + connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged); + connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged); + if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) { // we either read a certificate and private key or were not passed one // and completed login or did not need to @@ -767,12 +771,16 @@ QUrl DomainServer::oauthAuthorizationURL(const QUuid& stateUUID) { } void DomainServer::handleConnectedNode(SharedNodePointer newNode) { - - DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); - + DomainServerNodeData* nodeData = static_cast(newNode->getLinkedData()); + // reply back to the user with a PacketType::DomainList sendDomainListToNode(newNode, nodeData->getSendingSockAddr()); - + + // if this node is a user (unassigned Agent), signal + if (newNode->getType() == NodeType::Agent && !nodeData->wasAssigned()) { + emit userConnected(); + } + // send out this node to our other connected nodes broadcastNewNode(newNode); } @@ -1890,11 +1898,10 @@ void DomainServer::nodeAdded(SharedNodePointer node) { } void DomainServer::nodeKilled(SharedNodePointer node) { - // if this peer connected via ICE then remove them from our ICE peers hash _gatekeeper.removeICEPeer(node->getUUID()); - DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + DomainServerNodeData* nodeData = static_cast(node->getLinkedData()); if (nodeData) { // if this node's UUID matches a static assignment we need to throw it back in the assignment queue @@ -1906,15 +1913,22 @@ void DomainServer::nodeKilled(SharedNodePointer node) { } } - // If this node was an Agent ask DomainServerNodeData to potentially remove the interpolation we stored - nodeData->removeOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, - uuidStringWithoutCurlyBraces(node->getUUID())); - // cleanup the connection secrets that we set up for this node (on the other nodes) foreach (const QUuid& otherNodeSessionUUID, nodeData->getSessionSecretHash().keys()) { SharedNodePointer otherNode = DependencyManager::get()->nodeWithUUID(otherNodeSessionUUID); if (otherNode) { - reinterpret_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + static_cast(otherNode->getLinkedData())->getSessionSecretHash().remove(node->getUUID()); + } + } + + if (node->getType() == NodeType::Agent) { + // if this node was an Agent ask DomainServerNodeData to remove the interpolation we potentially stored + nodeData->removeOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, + uuidStringWithoutCurlyBraces(node->getUUID())); + + // if this node is a user (unassigned Agent), signal + if (!nodeData->wasAssigned()) { + emit userDisconnected(); } } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 0a1df41f50..acda550ce5 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -92,6 +92,8 @@ private slots: signals: void iceServerChanged(); + void userConnected(); + void userDisconnected(); private: void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); From 5c293646b960007ab8dfff83712909db57f84861 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 17:22:39 -0700 Subject: [PATCH 21/54] Segment metadata users --- domain-server/src/DomainMetadata.cpp | 17 +++++++++++------ domain-server/src/DomainMetadata.h | 10 ++++++++-- domain-server/src/DomainServer.cpp | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index c45a07e646..c92303ee7b 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,6 +15,14 @@ #include "DomainServerNodeData.h" +const QString DomainMetadata::USERS_KEY = "users"; +const QString DomainMetadata::USERS_NUM_KEY = "num_users"; +const QString DomainMetadata::USERS_HOSTNAMES_KEY = "users_hostnames"; + +DomainMetadata::DomainMetadata() : + _metadata{{ USERS_KEY, {} }} { +} + void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; @@ -39,13 +47,10 @@ void DomainMetadata::usersChanged() { } }); - static const QString HEARTBEAT_NUM_USERS_KEY = "num_users"; - _metadata[HEARTBEAT_NUM_USERS_KEY] = numConnectedUnassigned; - - static const QString HEARTBEAT_USER_HOSTNAMES_KEY = "user_hostnames"; - _metadata[HEARTBEAT_USER_HOSTNAMES_KEY] = userHostnames; + QVariantMap users = {{ USERS_NUM_KEY, numConnectedUnassigned }, { USERS_HOSTNAMES_KEY, userHostnames }}; + _metadata[USERS_KEY] = users; #if DEV_BUILD - qDebug() << "Regenerated domain metadata - users:" << _metadata; + qDebug() << "Regenerated domain metadata - users:" << users; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index f92c40ce61..ae6dfe10a1 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -15,9 +15,15 @@ #include class DomainMetadata { + static const QString USERS_KEY; + static const QString USERS_NUM_KEY; + static const QString USERS_HOSTNAMES_KEY; + public: - QVariantMap toVariantMap() { return _metadata; } - QJsonObject toJSON() { return QJsonObject::fromVariantMap(_metadata); } + DomainMetadata(); + + QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } + QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS_KEY].toMap()); } public slots: void usersChanged(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5a9fc816c5..c24fd02727 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1098,7 +1098,7 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; - domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.toJSON(); + domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); From 912b35693b32f5302bbdf32a7b9bac531341dc47 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 2 Jun 2016 18:13:33 -0700 Subject: [PATCH 22/54] added vive single pulse haptics --- plugins/openvr/src/ViveControllerManager.cpp | 18 ++++++++++++++++++ plugins/openvr/src/ViveControllerManager.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6e75454b5f..6b19646512 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -442,6 +442,24 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const _poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar); } +// Vive Controllers do not support duration +bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { + auto handRole = leftHand ? vr::TrackedControllerRole_LeftHand : vr::TrackedControllerRole_RightHand; + auto deviceIndex = _system->GetTrackedDeviceIndexForControllerRole(handRole); + + if (_system->IsTrackedDeviceConnected(deviceIndex) && + _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && + _trackedDevicePose[deviceIndex].bPoseIsValid) { + // the documentation says the third argument to TriggerHapticPulse is duration + // but it seems to instead be strength, and is between 0 and 3999 + // https://github.com/ValveSoftware/openvr/wiki/IVRSystem::TriggerHapticPulse + const float MAX_HAPTIC_STRENGTH = 3999.0f; + _system->TriggerHapticPulse(deviceIndex, 0, strength*MAX_HAPTIC_STRENGTH); + return true; + } + return false; +} + controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index bd5d4a39f4..c108d3087f 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -56,6 +56,8 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; + bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand); From e2c4b4d3064707ac5310e755566f8c51e23ce252 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 3 Jun 2016 10:17:08 -0700 Subject: [PATCH 23/54] added haptic support to sdl and touch (needs testing) --- plugins/hifiSdl2/src/Joystick.cpp | 11 ++++++- plugins/hifiSdl2/src/Joystick.h | 3 ++ plugins/hifiSdl2/src/SDL2Manager.cpp | 2 +- .../oculus/src/OculusControllerManager.cpp | 31 +++++++++++++++++++ plugins/oculus/src/OculusControllerManager.h | 11 +++++++ 5 files changed, 56 insertions(+), 2 deletions(-) diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index a109656489..136c021913 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -21,9 +21,10 @@ Joystick::Joystick(SDL_JoystickID instanceId, SDL_GameController* sdlGameControl InputDevice("GamePad"), _sdlGameController(sdlGameController), _sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)), + _sdlHaptic(SDL_HapticOpenFromJoystick(_sdlJoystick)), _instanceId(instanceId) { - + SDL_HapticRumbleInit(_sdlHaptic); } Joystick::~Joystick() { @@ -31,6 +32,7 @@ Joystick::~Joystick() { } void Joystick::closeJoystick() { + SDL_HapticClose(_sdlHaptic); SDL_GameControllerClose(_sdlGameController); } @@ -62,6 +64,13 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { } } +bool Joystick::triggerHapticPulse(float strength, float duration, bool leftHand) { + if (SDL_HapticRumblePlay(_sdlHaptic, strength, duration) != 0) { + return false; + } + return true; +} + controller::Input::NamedVector Joystick::getAvailableInputs() const { using namespace controller; static const Input::NamedVector availableInputs{ diff --git a/plugins/hifiSdl2/src/Joystick.h b/plugins/hifiSdl2/src/Joystick.h index e2eaeaef8b..4f785f85ce 100644 --- a/plugins/hifiSdl2/src/Joystick.h +++ b/plugins/hifiSdl2/src/Joystick.h @@ -36,6 +36,8 @@ public: virtual QString getDefaultMappingConfig() const override; virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; virtual void focusOutEvent() override; + + bool triggerHapticPulse(float strength, float duration, bool leftHand) override; Joystick() : InputDevice("GamePad") {} ~Joystick(); @@ -52,6 +54,7 @@ public: private: SDL_GameController* _sdlGameController; SDL_Joystick* _sdlJoystick; + SDL_Haptic* _sdlHaptic; SDL_JoystickID _instanceId; }; diff --git a/plugins/hifiSdl2/src/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp index 0bdb68f830..09e783864c 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -49,7 +49,7 @@ SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) { } void SDL2Manager::init() { - bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER) == 0); + bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0); if (initSuccess) { int joystickCount = SDL_NumJoysticks(); diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 09ab6ec159..3151db1d90 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -55,6 +55,11 @@ bool OculusControllerManager::activate() { userInputMapper->registerDevice(_touch); } + _leftHapticTimer.setSingleShot(true); + _rightHapticTimer.setSingleShot(true); + connect(&_leftHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(true))); + connect(&_rightHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(false))); + return true; } @@ -105,6 +110,12 @@ void OculusControllerManager::pluginFocusOutEvent() { } } +void OculusControllerManager::stopHapticPulse(bool leftHand) { + if (_touch) { + _touch->stopHapticPulse(leftHand); + } +} + using namespace controller; static const std::vector> BUTTON_MAP { { @@ -228,6 +239,26 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, pose.velocity = toGlm(handPose.LinearVelocity); } +bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { + auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch); + if (ovr_SetControllerVibration(_parent._session, handType, 1.0f, strength) != ovrSuccess) { + return false; + } + + if (leftHand) { + _parent._leftHapticTimer.start(duration); + } else { + _parent._rightHapticTimer.start(duration); + } + + return true; +} + +void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { + auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch); + ovr_SetControllerVibration(_parent._session, handType, 0.0f, 0.0f); +} + controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 980e1286f8..20e5726dff 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -10,6 +10,7 @@ #define hifi__OculusControllerManager #include +#include #include #include @@ -32,6 +33,9 @@ public: void pluginFocusOutEvent() override; void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; +private slots: + void stopHapticPulse(bool leftHand); + private: class OculusInputDevice : public controller::InputDevice { public: @@ -64,6 +68,11 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; + bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + + private: + void stopHapticPulse(bool leftHand); + private: void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); int _trackedControllers { 0 }; @@ -73,6 +82,8 @@ private: ovrSession _session { nullptr }; ovrInputState _inputState {}; RemoteDevice::Pointer _remote; + QTimer _leftHapticTimer; + QTimer _rightHapticTimer; TouchDevice::Pointer _touch; static const QString NAME; }; From c1eab612418a81357e127f9918b4654413007a2f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 3 Jun 2016 11:22:06 -0700 Subject: [PATCH 24/54] sdl haptics aren't working, but might be a bug in sdl: http://stackoverflow.com/questions/23974908/why-is-sdl-hapticopenfromjoystick-not-working-in-sdl-2 --- plugins/hifiSdl2/src/Joystick.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index 136c021913..cf7dde371b 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -24,6 +24,9 @@ Joystick::Joystick(SDL_JoystickID instanceId, SDL_GameController* sdlGameControl _sdlHaptic(SDL_HapticOpenFromJoystick(_sdlJoystick)), _instanceId(instanceId) { + if (!_sdlHaptic) { + qDebug(SDL_GetError()); + } SDL_HapticRumbleInit(_sdlHaptic); } From 9292a9ce0b244579900f66143795ffb4ef29bd2f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 3 Jun 2016 13:56:32 -0700 Subject: [PATCH 25/54] Added MyAvatar.hmdLeanRecenterEnabled property Used to disable the 'room-scale' avatar re-centering code. Disabling this can prevent sliding when the avatar is supposed to be sitting or mounted on a stationary object. Also, removed a bunch of old, unused leaning and torso twisting code. --- interface/src/avatar/Avatar.cpp | 1 - interface/src/avatar/Avatar.h | 1 - interface/src/avatar/Head.cpp | 21 +-------------- interface/src/avatar/Head.h | 9 +------ interface/src/avatar/MyAvatar.cpp | 36 +++++++++----------------- interface/src/avatar/MyAvatar.h | 11 +++++--- interface/src/avatar/SkeletonModel.cpp | 5 ---- interface/src/ui/PreferencesDialog.cpp | 10 ------- libraries/animation/src/Rig.cpp | 14 ---------- libraries/animation/src/Rig.h | 6 ----- libraries/avatars/src/HeadData.cpp | 15 ----------- libraries/avatars/src/HeadData.h | 14 ---------- 12 files changed, 21 insertions(+), 122 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 3e22448386..f46a906af8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -84,7 +84,6 @@ Avatar::Avatar(RigPointer rig) : _acceleration(0.0f), _lastAngularVelocity(0.0f), _lastOrientation(), - _leanScale(0.5f), _worldUpDirection(DEFAULT_UP_DIRECTION), _moving(false), _initialized(false), diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 79952e8f58..064f0a9533 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -210,7 +210,6 @@ protected: glm::vec3 _angularAcceleration; glm::quat _lastOrientation; - float _leanScale; glm::vec3 _worldUpDirection; float _stringLength; bool _moving; ///< set when position is changing diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 3af8b8a423..928f46facb 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -54,8 +54,6 @@ Head::Head(Avatar* owningAvatar) : _deltaPitch(0.0f), _deltaYaw(0.0f), _deltaRoll(0.0f), - _deltaLeanSideways(0.0f), - _deltaLeanForward(0.0f), _isCameraMoving(false), _isLookingAtMe(false), _lookingAtMeStarted(0), @@ -70,7 +68,6 @@ void Head::init() { void Head::reset() { _baseYaw = _basePitch = _baseRoll = 0.0f; - _leanForward = _leanSideways = 0.0f; } void Head::simulate(float deltaTime, bool isMine, bool billboard) { @@ -118,13 +115,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { auto eyeTracker = DependencyManager::get(); _isEyeTrackerConnected = eyeTracker->isTracking(); } - - // Twist the upper body to follow the rotation of the head, but only do this with my avatar, - // since everyone else will see the full joint rotations for other people. - const float BODY_FOLLOW_HEAD_YAW_RATE = 0.1f; - const float BODY_FOLLOW_HEAD_FACTOR = 0.66f; - float currentTwist = getTorsoTwist(); - setTorsoTwist(currentTwist + (getFinalYaw() * BODY_FOLLOW_HEAD_FACTOR - currentTwist) * BODY_FOLLOW_HEAD_YAW_RATE); } if (!(_isFaceTrackerConnected || billboard)) { @@ -301,17 +291,13 @@ void Head::applyEyelidOffset(glm::quat headOrientation) { } } -void Head::relaxLean(float deltaTime) { +void Head::relax(float deltaTime) { // restore rotation, lean to neutral positions const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds float relaxationFactor = 1.0f - glm::min(deltaTime / LEAN_RELAXATION_PERIOD, 1.0f); _deltaYaw *= relaxationFactor; _deltaPitch *= relaxationFactor; _deltaRoll *= relaxationFactor; - _leanSideways *= relaxationFactor; - _leanForward *= relaxationFactor; - _deltaLeanSideways *= relaxationFactor; - _deltaLeanForward *= relaxationFactor; } void Head::setScale (float scale) { @@ -419,8 +405,3 @@ float Head::getFinalPitch() const { float Head::getFinalRoll() const { return glm::clamp(_baseRoll + _deltaRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } - -void Head::addLeanDeltas(float sideways, float forward) { - _deltaLeanSideways += sideways; - _deltaLeanForward += forward; -} diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index e4b8fefea5..33ea180d33 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -59,8 +59,6 @@ public: glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } - float getFinalLeanSideways() const { return _leanSideways + _deltaLeanSideways; } - float getFinalLeanForward() const { return _leanForward + _deltaLeanForward; } glm::quat getEyeRotation(const glm::vec3& eyePosition) const; @@ -91,8 +89,7 @@ public: virtual float getFinalYaw() const; virtual float getFinalRoll() const; - void relaxLean(float deltaTime); - void addLeanDeltas(float sideways, float forward); + void relax(float deltaTime); float getTimeWithoutTalking() const { return _timeWithoutTalking; } @@ -132,10 +129,6 @@ private: float _deltaYaw; float _deltaRoll; - // delta lean angles for lean perturbations (driven by collisions) - float _deltaLeanSideways; - float _deltaLeanForward; - bool _isCameraMoving; bool _isLookingAtMe; quint64 _lookingAtMeStarted; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6fdcd8f797..0f723d29e3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -190,9 +190,6 @@ MyAvatar::MyAvatar(RigPointer rig) : if (!headData->getBlendshapeCoefficients().isEmpty()) { _headData->setBlendshapeCoefficients(headData->getBlendshapeCoefficients()); } - // head lean - _headData->setLeanForward(headData->getLeanForward()); - _headData->setLeanSideways(headData->getLeanSideways()); // head orientation _headData->setLookAtPosition(headData->getLookAtPosition()); } @@ -306,7 +303,7 @@ void MyAvatar::update(float deltaTime) { } Head* head = getHead(); - head->relaxLean(deltaTime); + head->relax(deltaTime); updateFromTrackers(deltaTime); // Get audio loudness data from audio input device @@ -574,16 +571,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) { head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView); head->setDeltaRoll(estimatedRotation.z); } - - // 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); - - const float MAX_LEAN = 45.0f; - head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)), - -MAX_LEAN, MAX_LEAN)); - head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), - -MAX_LEAN, MAX_LEAN)); } glm::vec3 MyAvatar::getLeftHandPosition() const { @@ -692,7 +679,6 @@ void MyAvatar::saveData() { settings.setValue("headPitch", getHead()->getBasePitch()); - settings.setValue("leanScale", _leanScale); settings.setValue("scale", _targetScale); settings.setValue("fullAvatarURL", @@ -809,7 +795,6 @@ void MyAvatar::loadData() { getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f)); - _leanScale = loadSetting(settings, "leanScale", 0.05f); _targetScale = loadSetting(settings, "scale", 1.0f); setScale(glm::vec3(_targetScale)); @@ -2052,14 +2037,17 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix, bool hasDriveInput) { _desiredBodyMatrix = desiredBodyMatrix; - if (!isActive(Rotation) && shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { - activate(Rotation); - } - if (!isActive(Horizontal) && shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { - activate(Horizontal); - } - if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { - activate(Vertical); + + if (myAvatar.getHMDLeanRecenterEnabled()) { + if (!isActive(Rotation) && shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + activate(Rotation); + } + if (!isActive(Horizontal) && shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { + activate(Horizontal); + } + if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { + activate(Vertical); + } } glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d3da32e0ed..a938aea675 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -69,7 +69,6 @@ class MyAvatar : public Avatar { Q_PROPERTY(AudioListenerMode audioListenerModeCustom READ getAudioListenerModeCustom) //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) - Q_PROPERTY(glm::vec3 leftHandPosition READ getLeftHandPosition) Q_PROPERTY(glm::vec3 rightHandPosition READ getRightHandPosition) Q_PROPERTY(glm::vec3 leftHandTipPosition READ getLeftHandTipPosition) @@ -84,6 +83,8 @@ class MyAvatar : public Avatar { Q_PROPERTY(float energy READ getEnergy WRITE setEnergy) + Q_PROPERTY(bool hmdLeanRecenterEnabled READ getHMDLeanRecenterEnabled WRITE setHMDLeanRecenterEnabled) + public: explicit MyAvatar(RigPointer rig); ~MyAvatar(); @@ -123,9 +124,6 @@ public: void setRealWorldFieldOfView(float realWorldFov) { _realWorldFieldOfView.set(realWorldFov); } - void setLeanScale(float scale) { _leanScale = scale; } - float getLeanScale() const { return _leanScale; } - Q_INVOKABLE glm::vec3 getDefaultEyePosition() const; float getRealWorldFieldOfView() { return _realWorldFieldOfView.get(); } @@ -163,6 +161,9 @@ public: Q_INVOKABLE bool getClearOverlayWhenDriving() const { return _clearOverlayWhenDriving; } Q_INVOKABLE void setClearOverlayWhenDriving(bool on) { _clearOverlayWhenDriving = on; } + Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; } + Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } + // get/set avatar data void saveData(); void loadData(); @@ -470,6 +471,8 @@ private: ThreadSafeValueCache _leftHandControllerPoseInSensorFrameCache { controller::Pose() }; ThreadSafeValueCache _rightHandControllerPoseInSensorFrameCache { controller::Pose() }; + bool _hmdLeanRecenterEnabled = true; + float AVATAR_MOVEMENT_ENERGY_CONSTANT { 0.001f }; float AUDIO_ENERGY_CONSTANT { 0.000001f }; float MAX_AVATAR_MOVEMENT_PER_FRAME { 30.0f }; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 5deeb545a1..889f0ef36b 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -106,10 +106,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { MyAvatar* myAvatar = static_cast(_owningAvatar); Rig::HeadParameters headParams; - headParams.enableLean = qApp->isHMDMode(); - headParams.leanSideways = head->getFinalLeanSideways(); - headParams.leanForward = head->getFinalLeanForward(); - headParams.torsoTwist = head->getTorsoTwist(); if (qApp->isHMDMode()) { headParams.isInHMD = true; @@ -131,7 +127,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); } - headParams.leanJointIndex = geometry.leanJointIndex; headParams.neckJointIndex = geometry.neckJointIndex; headParams.isTalking = head->getTimeWithoutTalking() <= 1.5f; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ce7bcc6323..6decef3240 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -129,16 +129,6 @@ void setupPreferences() { preference->setStep(1); preferences->addPreference(preference); } - { - auto getter = [=]()->float { return myAvatar->getLeanScale(); }; - auto setter = [=](float value) { myAvatar->setLeanScale(value); }; - auto preference = new SpinnerPreference(AVATAR_TUNING, "Lean scale (applies to Faceshift users)", getter, setter); - preference->setMin(0); - preference->setMax(99.9f); - preference->setDecimals(2); - preference->setStep(1); - preferences->addPreference(preference); - } { auto getter = [=]()->float { return myAvatar->getUniformScale(); }; auto setter = [=](float value) { myAvatar->setTargetScaleVerbose(value); }; // The hell? diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 9bba9ffc33..b21f5a0e84 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -931,11 +931,6 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) { } void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { - if (params.enableLean) { - updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist); - } else { - _animVars.unset("lean"); - } updateNeckJoint(params.neckJointIndex, params); _animVars.set("isTalking", params.isTalking); @@ -953,15 +948,6 @@ static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f); static const glm::vec3 Y_AXIS(0.0f, 1.0f, 0.0f); static const glm::vec3 Z_AXIS(0.0f, 0.0f, 1.0f); -void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist) { - if (isIndexValid(index)) { - glm::quat absRot = (glm::angleAxis(-RADIANS_PER_DEGREE * leanSideways, Z_AXIS) * - glm::angleAxis(-RADIANS_PER_DEGREE * leanForward, X_AXIS) * - glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, Y_AXIS)); - _animVars.set("lean", absRot); - } -} - void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut, glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 891d9fdb92..e2193e8479 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -42,15 +42,10 @@ public: }; struct HeadParameters { - float leanSideways = 0.0f; // degrees - float leanForward = 0.0f; // degrees - float torsoTwist = 0.0f; // degrees - bool enableLean = false; glm::quat worldHeadOrientation = glm::quat(); // world space (-z forward) glm::quat rigHeadOrientation = glm::quat(); // rig space (-z forward) glm::vec3 rigHeadPosition = glm::vec3(); // rig space bool isInHMD = false; - int leanJointIndex = -1; int neckJointIndex = -1; bool isTalking = false; }; @@ -222,7 +217,6 @@ protected: void applyOverridePoses(); void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut); - void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateNeckJoint(int index, const HeadParameters& params); void computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut, glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const; diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index 1aee85b2cd..72516d9740 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -31,9 +31,6 @@ HeadData::HeadData(AvatarData* owningAvatar) : _baseYaw(0.0f), _basePitch(0.0f), _baseRoll(0.0f), - _leanSideways(0.0f), - _leanForward(0.0f), - _torsoTwist(0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f), _audioLoudness(0.0f), _isFaceTrackerConnected(false), @@ -132,12 +129,6 @@ QJsonObject HeadData::toJson() const { if (getRawOrientation() != quat()) { headJson[JSON_AVATAR_HEAD_ROTATION] = toJsonValue(getRawOrientation()); } - if (getLeanForward() != 0.0f) { - headJson[JSON_AVATAR_HEAD_LEAN_FORWARD] = getLeanForward(); - } - if (getLeanSideways() != 0.0f) { - headJson[JSON_AVATAR_HEAD_LEAN_SIDEWAYS] = getLeanSideways(); - } auto lookat = getLookAtPosition(); if (lookat != vec3()) { vec3 relativeLookAt = glm::inverse(_owningAvatar->getOrientation()) * @@ -171,12 +162,6 @@ void HeadData::fromJson(const QJsonObject& json) { if (json.contains(JSON_AVATAR_HEAD_ROTATION)) { setOrientation(quatFromJsonValue(json[JSON_AVATAR_HEAD_ROTATION])); } - if (json.contains(JSON_AVATAR_HEAD_LEAN_FORWARD)) { - setLeanForward((float)json[JSON_AVATAR_HEAD_LEAN_FORWARD].toDouble()); - } - if (json.contains(JSON_AVATAR_HEAD_LEAN_SIDEWAYS)) { - setLeanSideways((float)json[JSON_AVATAR_HEAD_LEAN_SIDEWAYS].toDouble()); - } if (json.contains(JSON_AVATAR_HEAD_LOOKAT)) { auto relativeLookAt = vec3FromJsonValue(json[JSON_AVATAR_HEAD_LOOKAT]); diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 535aa12847..af657339ba 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -68,17 +68,6 @@ public: const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; } - - float getLeanSideways() const { return _leanSideways; } - float getLeanForward() const { return _leanForward; } - float getTorsoTwist() const { return _torsoTwist; } - virtual float getFinalLeanSideways() const { return _leanSideways; } - virtual float getFinalLeanForward() const { return _leanForward; } - - void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } - void setLeanForward(float leanForward) { _leanForward = leanForward; } - void setTorsoTwist(float torsoTwist) { _torsoTwist = torsoTwist; } - friend class AvatarData; QJsonObject toJson() const; @@ -89,9 +78,6 @@ protected: float _baseYaw; float _basePitch; float _baseRoll; - float _leanSideways; - float _leanForward; - float _torsoTwist; glm::vec3 _lookAtPosition; float _audioLoudness; From 55e5c1f6e0bdbe1e2e23d73296954eaaee371f0b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 2 Jun 2016 18:01:59 -0700 Subject: [PATCH 26/54] Declare metadata descriptors --- domain-server/src/DomainMetadata.cpp | 73 +++++++++++++++++++++++----- domain-server/src/DomainMetadata.h | 30 ++++++++++-- domain-server/src/DomainServer.cpp | 9 ++-- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index c92303ee7b..0481e9911d 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -15,29 +15,77 @@ #include "DomainServerNodeData.h" -const QString DomainMetadata::USERS_KEY = "users"; -const QString DomainMetadata::USERS_NUM_KEY = "num_users"; -const QString DomainMetadata::USERS_HOSTNAMES_KEY = "users_hostnames"; +const QString DomainMetadata::USERS = "users"; +const QString DomainMetadata::USERS_NUM_TOTAL = "num_users"; +const QString DomainMetadata::USERS_NUM_ANON = "num_anon_users"; +const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames"; +// users metadata will appear as (JSON): +// { "num_users": Number, +// "num_anon_users": Number, +// "user_hostnames": { : Number } +// } -DomainMetadata::DomainMetadata() : - _metadata{{ USERS_KEY, {} }} { +const QString DomainMetadata::DESCRIPTORS = "descriptors"; +const QString DomainMetadata::DESCRIPTORS_DESCRIPTION = "description"; +const QString DomainMetadata::DESCRIPTORS_CAPACITY = "capacity"; // parsed from security +const QString DomainMetadata::DESCRIPTORS_RESTRICTION = "restriction"; // parsed from ACL +const QString DomainMetadata::DESCRIPTORS_MATURITY = "maturity"; +const QString DomainMetadata::DESCRIPTORS_HOSTS = "hosts"; +const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; +// descriptors metadata will appear as (JSON): +// { "capacity": Number, +// TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments +// "restriction": String, // enum of either OPEN, RESTRICTED_HIFI, RESTRICTED_ACL +// "maturity": String, // enum corresponding to ESRB ratings +// "hosts": [ String ], // capped list of usernames +// "description": String, // capped description +// TODO: "img": { +// "src": String, +// "type": String, +// "size": Number, +// "updated_at": Number, +// }, +// "tags": [ String ], // capped list of tags +// } + +// metadata will appear as (JSON): +// { users: , descriptors: } +// +// it is meant to be sent to and consumed by an external API + +DomainMetadata::DomainMetadata() { + _metadata[USERS] = {}; + _metadata[DESCRIPTORS] = {}; +} + +void DomainMetadata::setDescriptors(QVariantMap& settings) { + // TODO + + QVariantMap descriptors; + + #if DEV_BUILD || PR_BUILD + qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; +#endif } void DomainMetadata::usersChanged() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); - int numConnectedUnassigned = 0; + int numConnected = 0; + int numConnectedAnonymously = 0; QVariantMap userHostnames; // figure out the breakdown of currently connected interface clients - nodeList->eachNode([&numConnectedUnassigned, &userHostnames](const SharedNodePointer& node) { + nodeList->eachNode([&numConnected, &numConnectedAnonymously, &userHostnames](const SharedNodePointer& node) { auto linkedData = node->getLinkedData(); if (linkedData) { auto nodeData = static_cast(linkedData); if (!nodeData->wasAssigned()) { - ++numConnectedUnassigned; + ++numConnected; + + // TODO: numConnectedAnonymously // increment the count for this hostname (or the default if we don't have one) auto placeName = nodeData->getPlaceName(); @@ -47,10 +95,13 @@ void DomainMetadata::usersChanged() { } }); - QVariantMap users = {{ USERS_NUM_KEY, numConnectedUnassigned }, { USERS_HOSTNAMES_KEY, userHostnames }}; - _metadata[USERS_KEY] = users; + QVariantMap users = { + { USERS_NUM_TOTAL, numConnected }, + { USERS_NUM_ANON, numConnectedAnonymously }, + { USERS_HOSTNAMES, userHostnames }}; + _metadata[USERS] = users; -#if DEV_BUILD +#if DEV_BUILD || PR_BUILD qDebug() << "Regenerated domain metadata - users:" << users; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index ae6dfe10a1..e2f4674afc 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -14,16 +14,36 @@ #include #include -class DomainMetadata { - static const QString USERS_KEY; - static const QString USERS_NUM_KEY; - static const QString USERS_HOSTNAMES_KEY; +class DomainMetadata : public QObject { +Q_OBJECT + + static const QString USERS; + static const QString USERS_NUM_TOTAL; + static const QString USERS_NUM_ANON; + static const QString USERS_HOSTNAMES; + + static const QString DESCRIPTORS; + static const QString DESCRIPTORS_DESCRIPTION; + static const QString DESCRIPTORS_CAPACITY; + static const QString DESCRIPTORS_HOURS; + static const QString DESCRIPTORS_RESTRICTION; + static const QString DESCRIPTORS_MATURITY; + static const QString DESCRIPTORS_HOSTS; + static const QString DESCRIPTORS_TAGS; + static const QString DESCRIPTORS_IMG; + static const QString DESCRIPTORS_IMG_SRC; + static const QString DESCRIPTORS_IMG_TYPE; + static const QString DESCRIPTORS_IMG_SIZE; + static const QString DESCRIPTORS_IMG_UPDATED_AT; public: DomainMetadata(); QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } - QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS_KEY].toMap()); } + QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); } + QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); } + + void setDescriptors(QVariantMap& settings); public slots: void usersChanged(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c24fd02727..88c4e215b2 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -94,13 +94,13 @@ DomainServer::DomainServer(int argc, char* argv[]) : qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); - // make sure we hear about newly connected nodes from our gatekeeper - connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); - // update the metadata when a user (dis)connects connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged); connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged); + // make sure we hear about newly connected nodes from our gatekeeper + connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); + if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) { // we either read a certificate and private key or were not passed one // and completed login or did not need to @@ -116,6 +116,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : optionallyGetTemporaryName(args); } + + // update the metadata with current descriptors + _metadata.setDescriptors(_settingsManager.getSettingsMap()); } DomainServer::~DomainServer() { From 209ace1b867ae8cf64678e3b983c5137e7407ec7 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 11:11:06 -0700 Subject: [PATCH 27/54] Include anonymously connected user metadata --- domain-server/src/DomainMetadata.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 0481e9911d..75ff0d697c 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -85,7 +85,9 @@ void DomainMetadata::usersChanged() { if (!nodeData->wasAssigned()) { ++numConnected; - // TODO: numConnectedAnonymously + if (nodeData->getUsername().isEmpty()) { + ++numConnectedAnonymously; + } // increment the count for this hostname (or the default if we don't have one) auto placeName = nodeData->getPlaceName(); From e04c6e8c44f716ac8497b3e2d6a9f78a63a4b709 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 14:36:43 -0700 Subject: [PATCH 28/54] Add description/hosts/rating to settings UI --- .../resources/describe-settings.json | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index cac0d28e1e..ba00392cd7 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 1.2, + "version": 1.3, "settings": [ { "name": "metaverse", @@ -71,6 +71,76 @@ } ] }, + { + "name": "descriptors", + "label": "Description", + "help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.", + "settings": [ + { + "name": "description", + "label": "Description", + "help": "A description of your domain (256 character limit)." + }, + { + "name": "maturity", + "label": "Maturity", + "help": "A maturity rating, available as a guideline for content on your domain.", + "default": "unrated", + "type": "select", + "options": [ + { + "value": "unrated", + "label": "Unrated" + }, + { + "value": "everyone", + "label": "Everyone" + }, + { + "value": "teen", + "label": "Teen (13+)" + }, + { + "value": "mature", + "label": "Mature (17+)" + }, + { + "value": "adult", + "label": "Adult (18+)" + } + ] + + }, + { + "name": "hosts", + "label": "Hosts", + "type": "table", + "help": "Usernames of hosts who can reliably show your domain to new visitors.", + "numbered": false, + "columns": [ + { + "name": "host", + "label": "Username", + "can_set": true + } + ] + }, + { + "name": "tags", + "label": "Tags", + "type": "table", + "help": "Common categories under which your domain falls.", + "numbered": false, + "columns": [ + { + "name": "tag", + "label": "Tag", + "can_set": true + } + ] + } + ] + }, { "name": "security", "label": "Security", From 2367cb199566d8054a30c3c0435ba9143b7d837d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 3 Jun 2016 15:07:21 -0700 Subject: [PATCH 29/54] fixing input mapping for vive/touch grip button/trigger, script needs fixing --- .../resources/controllers/oculus_touch.json | 6 +-- interface/resources/controllers/vive.json | 4 +- .../src/controllers/StandardControls.h | 8 ++-- .../oculus/src/OculusControllerManager.cpp | 21 +-------- plugins/openvr/src/ViveControllerManager.cpp | 2 +- .../system/controllers/handControllerGrab.js | 47 ++++++++++++++----- 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index 8cb512a526..b59bf54e5b 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -10,16 +10,14 @@ { "from": "OculusTouch.LX", "to": "Standard.LX" }, { "from": "OculusTouch.LT", "to": "Standard.LT" }, { "from": "OculusTouch.LS", "to": "Standard.LS" }, - { "from": "OculusTouch.LG", "to": "Standard.LG" }, - { "from": "OculusTouch.LeftGrip", "to": "Standard.LB" }, + { "from": "OculusTouch.LeftGrip", "to": "Standard.LeftGrip" }, { "from": "OculusTouch.LeftHand", "to": "Standard.LeftHand" }, { "from": "OculusTouch.RY", "filters": "invert", "to": "Standard.RY" }, { "from": "OculusTouch.RX", "to": "Standard.RX" }, { "from": "OculusTouch.RT", "to": "Standard.RT" }, { "from": "OculusTouch.RS", "to": "Standard.RS" }, - { "from": "OculusTouch.RG", "to": "Standard.RG" }, - { "from": "OculusTouch.RightGrip", "to": "Standard.RB" }, + { "from": "OculusTouch.RightGrip", "to": "Standard.RightGrip" }, { "from": "OculusTouch.RightHand", "to": "Standard.RightHand" }, { "from": "OculusTouch.LeftApplicationMenu", "to": "Standard.Back" }, diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index 60a46ba3ce..dc3ca3755e 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -5,7 +5,7 @@ { "from": "Vive.LX", "when": "Vive.LSOuter", "to": "Standard.LX" }, { "from": "Vive.LT", "to": "Standard.LT" }, - { "from": "Vive.LeftGrip", "to": "Standard.LB" }, + { "from": "Vive.LeftGrip", "to": "Standard.LeftGrip" }, { "from": "Vive.LS", "to": "Standard.LS" }, { "from": "Vive.LSTouch", "to": "Standard.LSTouch" }, @@ -13,7 +13,7 @@ { "from": "Vive.RX", "when": "Vive.RSOuter", "to": "Standard.RX" }, { "from": "Vive.RT", "to": "Standard.RT" }, - { "from": "Vive.RightGrip", "to": "Standard.RB" }, + { "from": "Vive.RightGrip", "to": "Standard.RightGrip" }, { "from": "Vive.RS", "to": "Standard.RS" }, { "from": "Vive.RSTouch", "to": "Standard.RSTouch" }, diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h index 79c23bc6ee..d7eb3de2c2 100644 --- a/libraries/controllers/src/controllers/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -66,9 +66,7 @@ namespace controller { RIGHT_SECONDARY_INDEX_TOUCH, RIGHT_INDEX_POINT, - LEFT_GRIP, LEFT_GRIP_TOUCH, - RIGHT_GRIP, RIGHT_GRIP_TOUCH, NUM_STANDARD_BUTTONS @@ -85,9 +83,9 @@ namespace controller { // Triggers LT, RT, - // Grips (Oculus touch squeeze) - LG, - RG, + // Grips + LEFT_GRIP, + RIGHT_GRIP, NUM_STANDARD_AXES, LZ = LT, RZ = RT diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index e84fdcbfc7..9eadb83ea7 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -173,11 +173,6 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { } void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { - // Check past values of button map for hysteresis before clearing map - const float HYSTERESIS_OFFSET = -0.1f; - float LEFT_HYSTERESIS_OFFSET = _buttonPressedMap.find(LEFT_GRIP) != _buttonPressedMap.end() ? HYSTERESIS_OFFSET : 0.0f; - float RIGHT_HYSTERESIS_OFFSET = _buttonPressedMap.find(RIGHT_GRIP) != _buttonPressedMap.end() ? HYSTERESIS_OFFSET : 0.0f; - _poseStateMap.clear(); _buttonPressedMap.clear(); @@ -198,12 +193,12 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control _axisStateMap[LX] = inputState.Thumbstick[ovrHand_Left].x; _axisStateMap[LY] = inputState.Thumbstick[ovrHand_Left].y; _axisStateMap[LT] = inputState.IndexTrigger[ovrHand_Left]; - _axisStateMap[LG] = inputState.HandTrigger[ovrHand_Left]; + _axisStateMap[LEFT_GRIP] = inputState.HandTrigger[ovrHand_Left]; _axisStateMap[RX] = inputState.Thumbstick[ovrHand_Right].x; _axisStateMap[RY] = inputState.Thumbstick[ovrHand_Right].y; _axisStateMap[RT] = inputState.IndexTrigger[ovrHand_Right]; - _axisStateMap[RG] = inputState.HandTrigger[ovrHand_Right]; + _axisStateMap[RIGHT_GRIP] = inputState.HandTrigger[ovrHand_Right]; // Buttons for (const auto& pair : BUTTON_MAP) { @@ -211,16 +206,6 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control _buttonPressedMap.insert(pair.second); } } - // Map pressed hand triggers to grip buttons - // This is temporary in order to support the grab/equip scripts - const float handTriggerThreshold = 0.9f; - if (inputState.HandTrigger[ovrHand_Left] >= handTriggerThreshold + LEFT_HYSTERESIS_OFFSET) { - _buttonPressedMap.insert(LEFT_GRIP); - } - if (inputState.HandTrigger[ovrHand_Right] >= handTriggerThreshold + RIGHT_HYSTERESIS_OFFSET) { - _buttonPressedMap.insert(RIGHT_GRIP); - } - // Touches for (const auto& pair : TOUCH_MAP) { if (inputState.Touches & pair.first) { @@ -348,8 +333,6 @@ controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailabl //makePair(RB, "RB"), // side grip triggers - makePair(LG, "LG"), - makePair(RG, "RG"), makePair(LEFT_GRIP, "LeftGrip"), makePair(RIGHT_GRIP, "RightGrip"), diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6e75454b5f..bddbb91316 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -342,7 +342,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint if (button == vr::k_EButton_ApplicationMenu) { _buttonPressedMap.insert(isLeftHand ? LEFT_APP_MENU : RIGHT_APP_MENU); } else if (button == vr::k_EButton_Grip) { - _buttonPressedMap.insert(isLeftHand ? LEFT_GRIP : RIGHT_GRIP); + _axisStateMap[isLeftHand ? LEFT_GRIP : RIGHT_GRIP] = 1.0f; } else if (button == vr::k_EButton_SteamVR_Trigger) { _buttonPressedMap.insert(isLeftHand ? LT : RT); } else if (button == vr::k_EButton_SteamVR_Touchpad) { diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 06549a38b5..4f4b7e32ad 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -33,6 +33,9 @@ var TRIGGER_OFF_VALUE = 0.15; var BUMPER_ON_VALUE = 0.5; +var GRIP_ON_VALUE = 0.9; +var GRIP_OFF_VALUE = 0.8; + var THUMB_ON_VALUE = 0.5; var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move. @@ -271,6 +274,7 @@ function MyController(hand) { this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; + this.rawGripValue = 0; this.rawBumperValue = 0; this.rawThumbValue = 0; @@ -509,10 +513,10 @@ function MyController(hand) { var searchSphereLocation = Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, this.searchSphereDistance)); this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance, - (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); + (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed())) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); if ((USE_OVERLAY_LINES_FOR_SEARCHING === true) && PICK_WITH_HAND_RAY) { this.overlayLineOn(handPosition, searchSphereLocation, - (this.triggerSmoothedGrab() || this.bumperSqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); + (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed())) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); } } @@ -772,6 +776,10 @@ function MyController(hand) { _this.rawBumperValue = value; }; + this.gripPress = function(value) { + _this.rawGripValue = value; + }; + this.updateSmoothedTrigger = function() { var triggerValue = this.rawTriggerValue; // smooth out trigger value @@ -799,6 +807,14 @@ function MyController(hand) { return _this.rawBumperValue < BUMPER_ON_VALUE; }; + this.gripSqueezed = function() { + return _this.rawGripValue > GRIP_ON_VALUE; + }; + + this.gripReleased = function() { + return _this.rawGripValue < GRIP_OFF_VALUE; + }; + // this.triggerOrBumperSqueezed = function() { // return triggerSmoothedSqueezed() || bumperSqueezed(); // } @@ -820,13 +836,13 @@ function MyController(hand) { }; this.off = function() { - if (this.triggerSmoothedSqueezed() || this.bumperSqueezed()) { + if (this.triggerSmoothedSqueezed() || (this.bumperSqueezed() || this.gripSqueezed())) { this.lastPickTime = 0; var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation; if (this.triggerSmoothedSqueezed()) { this.setState(STATE_SEARCHING); - } else if (this.bumperSqueezed()) { + } else if (this.bumperSqueezed() || this.gripSqueezed()) { this.setState(STATE_HOLD_SEARCHING); } } @@ -839,11 +855,13 @@ function MyController(hand) { this.checkForStrayChildren(); + print("bumper: " + this.bumperReleased() + " grip: " + this.gripReleased()); + if (this.state == STATE_SEARCHING && this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; } - if (this.state == STATE_HOLD_SEARCHING && this.bumperReleased()) { + if (this.state == STATE_HOLD_SEARCHING && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); return; } @@ -1000,7 +1018,7 @@ function MyController(hand) { grabbableData = grabbableDataForCandidate; } } - if ((this.grabbedEntity !== null) && (this.triggerSmoothedGrab() || this.bumperSqueezed())) { + if ((this.grabbedEntity !== null) && (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed()))) { // We are squeezing enough to grab, and we've found an entity that we'll try to do something with. var near = (nearPickedCandidateEntities.indexOf(this.grabbedEntity) >= 0) || minDistance <= NEAR_PICK_MAX_DISTANCE; var isPhysical = this.propsArePhysical(props); @@ -1166,7 +1184,7 @@ function MyController(hand) { }; this.continueDistanceHolding = function() { - if (this.triggerSmoothedReleased() && this.bumperReleased()) { + if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseGrab"); return; @@ -1390,7 +1408,7 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("releaseGrab"); return; } - if (this.state == STATE_HOLD && this.bumperReleased()) { + if (this.state == STATE_HOLD && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseGrab"); return; @@ -1504,7 +1522,7 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("releaseGrab"); return; } - if (this.state == STATE_CONTINUE_HOLD && this.bumperReleased()) { + if (this.state == STATE_CONTINUE_HOLD && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseEquip"); return; @@ -1633,7 +1651,7 @@ function MyController(hand) { }; this.nearTrigger = function() { - if (this.triggerSmoothedReleased() && this.bumperReleased()) { + if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopNearTrigger"); return; @@ -1643,7 +1661,7 @@ function MyController(hand) { }; this.farTrigger = function() { - if (this.triggerSmoothedReleased() && this.bumperReleased()) { + if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopFarTrigger"); return; @@ -1653,7 +1671,7 @@ function MyController(hand) { }; this.continueNearTrigger = function() { - if (this.triggerSmoothedReleased() && this.bumperReleased()) { + if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopNearTrigger"); return; @@ -1662,7 +1680,7 @@ function MyController(hand) { }; this.continueFarTrigger = function() { - if (this.triggerSmoothedReleased() && this.bumperReleased()) { + if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopFarTrigger"); return; @@ -1945,6 +1963,9 @@ mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); +mapping.from([Controller.Standard.RightGrip]).peek().to(rightController.gripPress); +mapping.from([Controller.Standard.LeftGrip]).peek().to(leftController.gripPress); + mapping.from([Controller.Standard.LeftPrimaryThumb]).peek().to(leftController.thumbPress); mapping.from([Controller.Standard.RightPrimaryThumb]).peek().to(rightController.thumbPress); From 09e0a2ced70d03fa1e4e17b74dbd9e25f41c89df Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 3 Jun 2016 14:59:58 -0700 Subject: [PATCH 30/54] Parse basic metadata into DomainMetadata --- domain-server/src/DomainMetadata.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 75ff0d697c..8fdbc2bbd1 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -10,6 +10,7 @@ #include "DomainMetadata.h" +#include #include #include @@ -35,7 +36,7 @@ const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; // descriptors metadata will appear as (JSON): // { "capacity": Number, // TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments -// "restriction": String, // enum of either OPEN, RESTRICTED_HIFI, RESTRICTED_ACL +// "restriction": String, // enum of either open, hifi, or acl // "maturity": String, // enum corresponding to ESRB ratings // "hosts": [ String ], // capped list of usernames // "description": String, // capped description @@ -59,11 +60,25 @@ DomainMetadata::DomainMetadata() { } void DomainMetadata::setDescriptors(QVariantMap& settings) { - // TODO + const QString CAPACITY = "security.maximum_user_capacity"; + const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY); + unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0; - QVariantMap descriptors; + // TODO: Keep parity with ACL development. + const QString RESTRICTION = "security.restricted_access"; + const QString RESTRICTION_OPEN = "open"; + // const QString RESTRICTION_HIFI = "hifi"; + const QString RESTRICTION_ACL = "acl"; + const QVariant* isRestrictedVariant = valueForKeyPath(settings, RESTRICTION); + bool isRestricted = isRestrictedVariant ? isRestrictedVariant->toBool() : false; + QString restriction = isRestricted ? RESTRICTION_ACL : RESTRICTION_OPEN; - #if DEV_BUILD || PR_BUILD + QVariantMap descriptors = settings[DESCRIPTORS].toMap(); + descriptors[DESCRIPTORS_CAPACITY] = capacity; + descriptors[DESCRIPTORS_RESTRICTION] = restriction; + _metadata[DESCRIPTORS] = descriptors; + +#if DEV_BUILD || PR_BUILD qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; #endif } From 4fb8eac8ea7853b54b64a8a07e7a0034dbfe3488 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 3 Jun 2016 18:12:47 -0700 Subject: [PATCH 31/54] much better way of fixing script --- .../system/controllers/handControllerGrab.js | 77 +++++++------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 4f4b7e32ad..986a4c0722 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -33,9 +33,6 @@ var TRIGGER_OFF_VALUE = 0.15; var BUMPER_ON_VALUE = 0.5; -var GRIP_ON_VALUE = 0.9; -var GRIP_OFF_VALUE = 0.8; - var THUMB_ON_VALUE = 0.5; var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move. @@ -274,8 +271,7 @@ function MyController(hand) { this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; - this.rawGripValue = 0; - this.rawBumperValue = 0; + this.rawSecondaryValue = 0; this.rawThumbValue = 0; //for visualizations @@ -513,10 +509,10 @@ function MyController(hand) { var searchSphereLocation = Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, this.searchSphereDistance)); this.searchSphereOn(searchSphereLocation, SEARCH_SPHERE_SIZE * this.searchSphereDistance, - (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed())) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); + (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); if ((USE_OVERLAY_LINES_FOR_SEARCHING === true) && PICK_WITH_HAND_RAY) { this.overlayLineOn(handPosition, searchSphereLocation, - (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed())) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); + (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); } } @@ -772,12 +768,8 @@ function MyController(hand) { _this.rawTriggerValue = value; }; - this.bumperPress = function(value) { - _this.rawBumperValue = value; - }; - - this.gripPress = function(value) { - _this.rawGripValue = value; + this.secondaryPress = function(value) { + _this.rawSecondaryValue = value; }; this.updateSmoothedTrigger = function() { @@ -799,28 +791,20 @@ function MyController(hand) { return this.triggerValue < TRIGGER_OFF_VALUE; }; - this.bumperSqueezed = function() { - return _this.rawBumperValue > BUMPER_ON_VALUE; + this.secondarySqueezed = function() { + return _this.rawSecondaryValue > BUMPER_ON_VALUE; }; - this.bumperReleased = function() { - return _this.rawBumperValue < BUMPER_ON_VALUE; + this.secondaryReleased = function() { + return _this.rawSecondaryValue < BUMPER_ON_VALUE; }; - this.gripSqueezed = function() { - return _this.rawGripValue > GRIP_ON_VALUE; - }; - - this.gripReleased = function() { - return _this.rawGripValue < GRIP_OFF_VALUE; - }; - - // this.triggerOrBumperSqueezed = function() { - // return triggerSmoothedSqueezed() || bumperSqueezed(); + // this.triggerOrsecondarySqueezed = function() { + // return triggerSmoothedSqueezed() || secondarySqueezed(); // } - // this.triggerAndBumperReleased = function() { - // return triggerSmoothedReleased() && bumperReleased(); + // this.triggerAndSecondaryReleased = function() { + // return triggerSmoothedReleased() && secondaryReleased(); // } this.thumbPress = function(value) { @@ -836,13 +820,13 @@ function MyController(hand) { }; this.off = function() { - if (this.triggerSmoothedSqueezed() || (this.bumperSqueezed() || this.gripSqueezed())) { + if (this.triggerSmoothedSqueezed() || this.secondarySqueezed()) { this.lastPickTime = 0; var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation; if (this.triggerSmoothedSqueezed()) { this.setState(STATE_SEARCHING); - } else if (this.bumperSqueezed() || this.gripSqueezed()) { + } else if (this.secondarySqueezed()) { this.setState(STATE_HOLD_SEARCHING); } } @@ -855,13 +839,11 @@ function MyController(hand) { this.checkForStrayChildren(); - print("bumper: " + this.bumperReleased() + " grip: " + this.gripReleased()); - if (this.state == STATE_SEARCHING && this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; } - if (this.state == STATE_HOLD_SEARCHING && (this.bumperReleased() || this.gripReleased())) { + if (this.state == STATE_HOLD_SEARCHING && this.secondaryReleased()) { this.setState(STATE_RELEASE); return; } @@ -1018,7 +1000,7 @@ function MyController(hand) { grabbableData = grabbableDataForCandidate; } } - if ((this.grabbedEntity !== null) && (this.triggerSmoothedGrab() || (this.bumperSqueezed() || this.gripSqueezed()))) { + if ((this.grabbedEntity !== null) && (this.triggerSmoothedGrab() || this.secondarySqueezed())) { // We are squeezing enough to grab, and we've found an entity that we'll try to do something with. var near = (nearPickedCandidateEntities.indexOf(this.grabbedEntity) >= 0) || minDistance <= NEAR_PICK_MAX_DISTANCE; var isPhysical = this.propsArePhysical(props); @@ -1184,7 +1166,7 @@ function MyController(hand) { }; this.continueDistanceHolding = function() { - if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { + if (this.triggerSmoothedReleased() && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseGrab"); return; @@ -1408,7 +1390,7 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("releaseGrab"); return; } - if (this.state == STATE_HOLD && (this.bumperReleased() || this.gripReleased())) { + if (this.state == STATE_HOLD && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseGrab"); return; @@ -1522,7 +1504,7 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("releaseGrab"); return; } - if (this.state == STATE_CONTINUE_HOLD && (this.bumperReleased() || this.gripReleased())) { + if (this.state == STATE_CONTINUE_HOLD && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("releaseEquip"); return; @@ -1651,7 +1633,7 @@ function MyController(hand) { }; this.nearTrigger = function() { - if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { + if (this.triggerSmoothedReleased() && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopNearTrigger"); return; @@ -1661,7 +1643,7 @@ function MyController(hand) { }; this.farTrigger = function() { - if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { + if (this.triggerSmoothedReleased() && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopFarTrigger"); return; @@ -1671,7 +1653,7 @@ function MyController(hand) { }; this.continueNearTrigger = function() { - if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { + if (this.triggerSmoothedReleased() && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopNearTrigger"); return; @@ -1680,7 +1662,7 @@ function MyController(hand) { }; this.continueFarTrigger = function() { - if (this.triggerSmoothedReleased() && (this.bumperReleased() || this.gripReleased())) { + if (this.triggerSmoothedReleased() && this.secondaryReleased()) { this.setState(STATE_RELEASE); this.callEntityMethodOnGrabbed("stopFarTrigger"); return; @@ -1960,11 +1942,10 @@ var mapping = Controller.newMapping(MAPPING_NAME); mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); -mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); -mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); - -mapping.from([Controller.Standard.RightGrip]).peek().to(rightController.gripPress); -mapping.from([Controller.Standard.LeftGrip]).peek().to(leftController.gripPress); +mapping.from([Controller.Standard.RB]).peek().to(rightController.secondaryPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.secondaryPress); +mapping.from([Controller.Standard.LeftGrip]).peek().to(leftController.secondaryPress); +mapping.from([Controller.Standard.RightGrip]).peek().to(rightController.secondaryPress); mapping.from([Controller.Standard.LeftPrimaryThumb]).peek().to(leftController.thumbPress); mapping.from([Controller.Standard.RightPrimaryThumb]).peek().to(rightController.thumbPress); @@ -2057,4 +2038,4 @@ function cleanup() { Reticle.setVisible(true); } Script.scriptEnding.connect(cleanup); -Script.update.connect(update); +Script.update.connect(update); \ No newline at end of file From f51cb7ce0c8b847e27e7d017fb1dd5e392fe5abf Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 10:34:32 -0700 Subject: [PATCH 32/54] trying to add duration support for vive --- plugins/oculus/src/OculusControllerManager.h | 2 - plugins/openvr/src/ViveControllerManager.cpp | 46 +++++++++++++++++--- plugins/openvr/src/ViveControllerManager.h | 17 +++++++- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 20e5726dff..e62c5f45ea 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -72,8 +72,6 @@ private: private: void stopHapticPulse(bool leftHand); - - private: void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); int _trackedControllers { 0 }; friend class OculusControllerManager; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6b19646512..7d66429ed6 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -126,6 +126,11 @@ bool ViveControllerManager::activate() { userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; + _leftHapticTimer.setSingleShot(true); + _rightHapticTimer.setSingleShot(true); + connect(&_leftHapticTimer, SIGNAL(timeout()), this, SLOT(hapticPulseHelper(true))); + connect(&_rightHapticTimer, SIGNAL(timeout()), this, SLOT(hapticPulseHelper(false))); + return true; } @@ -442,7 +447,20 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const _poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar); } -// Vive Controllers do not support duration +void ViveControllerManager::hapticPulseHelper(bool leftHand) { + if (_inputDevice) { + _inputDevice->hapticPulseHelper(leftHand); + } +} + +void ViveControllerManager::InputDevice::hapticPulseHelper(bool leftHand) { + if (leftHand) { + triggerHapticPulse(prevLeftHapticStrength, prevLeftHapticDuration, leftHand); + } else { + triggerHapticPulse(prevRightHapticStrength, prevRightHapticDuration, leftHand); + } +} + bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { auto handRole = leftHand ? vr::TrackedControllerRole_LeftHand : vr::TrackedControllerRole_RightHand; auto deviceIndex = _system->GetTrackedDeviceIndexForControllerRole(handRole); @@ -450,11 +468,29 @@ bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, floa if (_system->IsTrackedDeviceConnected(deviceIndex) && _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && _trackedDevicePose[deviceIndex].bPoseIsValid) { - // the documentation says the third argument to TriggerHapticPulse is duration - // but it seems to instead be strength, and is between 0 and 3999 + // Vive Controllers only support duration up to 4 ms, which is short enough that any variation feels more like strength + const float MAX_HAPTIC_TIME = 3999.0f; // in microseconds + float hapticTime = strength*MAX_HAPTIC_TIME; + if (hapticTime < duration*1000.0f) { + _system->TriggerHapticPulse(deviceIndex, 0, hapticTime); + } + + // Must wait 5 ms before triggering another pulse on this controller // https://github.com/ValveSoftware/openvr/wiki/IVRSystem::TriggerHapticPulse - const float MAX_HAPTIC_STRENGTH = 3999.0f; - _system->TriggerHapticPulse(deviceIndex, 0, strength*MAX_HAPTIC_STRENGTH); + const float HAPTIC_RESET_TIME = 5.0f; + float remainingHapticTime = duration - (hapticTime / 1000.0f + HAPTIC_RESET_TIME); // in milliseconds + if (remainingHapticTime > 0.0f) { + if (leftHand) { + prevLeftHapticStrength = strength; + prevLeftHapticDuration = remainingHapticTime; + _parent._leftHapticTimer.start(remainingHapticTime); + } + else { + prevRightHapticStrength = strength; + prevRightHapticDuration = remainingHapticTime; + _parent._rightHapticTimer.start(remainingHapticTime); + } + } return true; } return false; diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index c108d3087f..67fe43c15a 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -13,6 +13,7 @@ #define hifi__ViveControllerManager #include +#include #include #include @@ -45,10 +46,13 @@ public: void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } +private slots: + void hapticPulseHelper(bool leftHand); + private: class InputDevice : public controller::InputDevice { public: - InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system) {} + InputDevice(ViveControllerManager& parent, vr::IVRSystem*& system) : controller::InputDevice("Vive"), _parent(parent), _system(system) {} private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; @@ -56,6 +60,7 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; + void hapticPulseHelper(bool leftHand); bool triggerHapticPulse(float strength, float duration, bool leftHand) override; void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); @@ -94,6 +99,11 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; + ViveControllerManager& _parent; + float prevLeftHapticStrength; + float prevLeftHapticDuration; + float prevRightHapticStrength; + float prevRightHapticDuration; friend class ViveControllerManager; }; @@ -109,7 +119,10 @@ private: bool _renderControllers { false }; vr::IVRSystem* _system { nullptr }; - std::shared_ptr _inputDevice { std::make_shared(_system) }; + std::shared_ptr _inputDevice { std::make_shared(*this, _system) }; + + QTimer _leftHapticTimer; + QTimer _rightHapticTimer; static const QString NAME; }; From afca0ec2c9542cc39bfd6f141525fb625e3bfa2e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 13:25:05 -0700 Subject: [PATCH 33/54] moved vive pulses to correct thread, works with duration --- plugins/openvr/src/ViveControllerManager.cpp | 65 ++++++++++---------- plugins/openvr/src/ViveControllerManager.h | 29 +++++---- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 7d66429ed6..39b5e620ad 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -125,12 +125,6 @@ bool ViveControllerManager::activate() { auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; - - _leftHapticTimer.setSingleShot(true); - _rightHapticTimer.setSingleShot(true); - connect(&_leftHapticTimer, SIGNAL(timeout()), this, SLOT(hapticPulseHelper(true))); - connect(&_rightHapticTimer, SIGNAL(timeout()), this, SLOT(hapticPulseHelper(false))); - return true; } @@ -250,6 +244,17 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true); handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false); + // handle haptics + { + Locker locker(_lock); + if (_leftHapticDuration > 0.0f) { + hapticsHelper(deltaTime, true); + } + if (_rightHapticDuration > 0.0f) { + hapticsHelper(deltaTime, false); + } + } + int numTrackedControllers = 0; if (leftHandDeviceIndex != vr::k_unTrackedDeviceIndexInvalid) { numTrackedControllers++; @@ -447,27 +452,28 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const _poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar); } -void ViveControllerManager::hapticPulseHelper(bool leftHand) { - if (_inputDevice) { - _inputDevice->hapticPulseHelper(leftHand); - } -} - -void ViveControllerManager::InputDevice::hapticPulseHelper(bool leftHand) { - if (leftHand) { - triggerHapticPulse(prevLeftHapticStrength, prevLeftHapticDuration, leftHand); - } else { - triggerHapticPulse(prevRightHapticStrength, prevRightHapticDuration, leftHand); - } -} - bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { + Locker locker(_lock); + if (leftHand) { + _leftHapticStrength = strength; + _leftHapticDuration = duration; + } else { + _rightHapticStrength = strength; + _rightHapticDuration = duration; + } + return true; +} + +void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool leftHand) { auto handRole = leftHand ? vr::TrackedControllerRole_LeftHand : vr::TrackedControllerRole_RightHand; auto deviceIndex = _system->GetTrackedDeviceIndexForControllerRole(handRole); if (_system->IsTrackedDeviceConnected(deviceIndex) && _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && _trackedDevicePose[deviceIndex].bPoseIsValid) { + float strength = leftHand ? _leftHapticStrength : _rightHapticStrength; + float duration = leftHand ? _leftHapticDuration : _rightHapticDuration; + // Vive Controllers only support duration up to 4 ms, which is short enough that any variation feels more like strength const float MAX_HAPTIC_TIME = 3999.0f; // in microseconds float hapticTime = strength*MAX_HAPTIC_TIME; @@ -478,22 +484,13 @@ bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, floa // Must wait 5 ms before triggering another pulse on this controller // https://github.com/ValveSoftware/openvr/wiki/IVRSystem::TriggerHapticPulse const float HAPTIC_RESET_TIME = 5.0f; - float remainingHapticTime = duration - (hapticTime / 1000.0f + HAPTIC_RESET_TIME); // in milliseconds - if (remainingHapticTime > 0.0f) { - if (leftHand) { - prevLeftHapticStrength = strength; - prevLeftHapticDuration = remainingHapticTime; - _parent._leftHapticTimer.start(remainingHapticTime); - } - else { - prevRightHapticStrength = strength; - prevRightHapticDuration = remainingHapticTime; - _parent._rightHapticTimer.start(remainingHapticTime); - } + float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds + if (leftHand) { + _leftHapticDuration = remainingHapticTime; + } else { + _rightHapticDuration = remainingHapticTime; } - return true; } - return false; } controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 67fe43c15a..9bdbd0370e 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -13,7 +13,6 @@ #define hifi__ViveControllerManager #include -#include #include #include @@ -46,13 +45,10 @@ public: void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } -private slots: - void hapticPulseHelper(bool leftHand); - private: class InputDevice : public controller::InputDevice { public: - InputDevice(ViveControllerManager& parent, vr::IVRSystem*& system) : controller::InputDevice("Vive"), _parent(parent), _system(system) {} + InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system), _leftHapticDuration(0.0f), _rightHapticDuration(0.0f) {} private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; @@ -60,8 +56,8 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - void hapticPulseHelper(bool leftHand); bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + void hapticsHelper(float deltaTime, bool leftHand); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); @@ -97,13 +93,19 @@ private: FilteredStick _filteredLeftStick; FilteredStick _filteredRightStick; + // perform an action when the InputDevice mutex is acquired. + using Locker = std::unique_lock; + template + void withLock(F&& f) { Locker locker(_lock); f(); } + int _trackedControllers { 0 }; vr::IVRSystem*& _system; - ViveControllerManager& _parent; - float prevLeftHapticStrength; - float prevLeftHapticDuration; - float prevRightHapticStrength; - float prevRightHapticDuration; + float _leftHapticStrength; + float _leftHapticDuration; + float _rightHapticStrength; + float _rightHapticDuration; + mutable std::recursive_mutex _lock; + friend class ViveControllerManager; }; @@ -119,10 +121,7 @@ private: bool _renderControllers { false }; vr::IVRSystem* _system { nullptr }; - std::shared_ptr _inputDevice { std::make_shared(*this, _system) }; - - QTimer _leftHapticTimer; - QTimer _rightHapticTimer; + std::shared_ptr _inputDevice { std::make_shared(_system) }; static const QString NAME; }; From e7743cd8e2603927da7099ea6e82e696e237fd1c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 15:03:08 -0700 Subject: [PATCH 34/54] added options for both hands (default), all devices, short pulse, and fixed touch timing mechanism --- .../controllers/src/controllers/InputDevice.h | 8 +++- .../src/controllers/ScriptingInterface.cpp | 18 +++++++- .../src/controllers/ScriptingInterface.h | 5 ++- .../src/controllers/UserInputMapper.cpp | 25 ++++++++++- .../src/controllers/UserInputMapper.h | 4 +- plugins/hifiSdl2/src/Joystick.cpp | 2 +- plugins/hifiSdl2/src/Joystick.h | 2 +- .../oculus/src/OculusControllerManager.cpp | 45 ++++++++++++------- plugins/oculus/src/OculusControllerManager.h | 15 +++++-- plugins/openvr/src/ViveControllerManager.cpp | 10 ++--- plugins/openvr/src/ViveControllerManager.h | 12 ++--- 11 files changed, 105 insertions(+), 41 deletions(-) diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index cc158497e0..10e1a104f4 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -31,6 +31,12 @@ namespace controller { class Endpoint; using EndpointPointer = std::shared_ptr; +enum Hand { + LEFT = 0, + RIGHT, + BOTH +}; + // NOTE: If something inherits from both InputDevice and InputPlugin, InputPlugin must go first. // e.g. class Example : public InputPlugin, public InputDevice // instead of class Example : public InputDevice, public InputPlugin @@ -56,7 +62,7 @@ public: const QString& getName() const { return _name; } // By default, Input Devices do not support haptics - virtual bool triggerHapticPulse(float strength, float duration, bool leftHand) { return false; } + virtual bool triggerHapticPulse(float strength, float duration, controller::Hand hand) { return false; } // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index 97b7a9ddd9..78e9378c18 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -140,8 +140,22 @@ namespace controller { return DependencyManager::get()->getActionNames(); } - bool ScriptingInterface::triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand) const { - return DependencyManager::get()->triggerHapticPulse(device, strength, duration, leftHand); + bool ScriptingInterface::triggerHapticPulse(float strength, float duration, controller::Hand hand) const { + return DependencyManager::get()->triggerHapticPulse(strength, duration, hand); + } + + bool ScriptingInterface::triggerShortHapticPulse(float strength, controller::Hand hand) const { + const float SHORT_HAPTIC_DURATION_MS = 250.0f; + return DependencyManager::get()->triggerHapticPulse(strength, SHORT_HAPTIC_DURATION_MS, hand); + } + + bool ScriptingInterface::triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand) const { + return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, duration, hand); + } + + bool ScriptingInterface::triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand) const { + const float SHORT_HAPTIC_DURATION_MS = 250.0f; + return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, SHORT_HAPTIC_DURATION_MS, hand); } void ScriptingInterface::updateMaps() { diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 015ec25454..713e864561 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -84,7 +84,10 @@ namespace controller { Q_INVOKABLE Pose getPoseValue(const int& source) const; Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; - Q_INVOKABLE bool triggerHapticPulse(unsigned int device, float strength, float duration, bool leftHand = true) const; + Q_INVOKABLE bool triggerHapticPulse(float strength, float duration, controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) const; Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index c7c62ad7d9..921f78c613 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -336,10 +336,19 @@ QVector UserInputMapper::getActionNames() const { return result; } -bool UserInputMapper::triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand) { +bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) { + Locker locker(_lock); + bool toReturn = false; + for (auto device : _registeredDevices) { + toReturn = toReturn || device.second->triggerHapticPulse(strength, duration, hand); + } + return toReturn; +} + +bool UserInputMapper::triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand) { Locker locker(_lock); if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { - return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, leftHand); + return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, hand); } return false; } @@ -348,6 +357,7 @@ int actionMetaTypeId = qRegisterMetaType(); int inputMetaTypeId = qRegisterMetaType(); int inputPairMetaTypeId = qRegisterMetaType(); int poseMetaTypeId = qRegisterMetaType("Pose"); +int handMetaTypeId = qRegisterMetaType(); QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input); void inputFromScriptValue(const QScriptValue& object, Input& input); @@ -355,6 +365,8 @@ QScriptValue actionToScriptValue(QScriptEngine* engine, const Action& action); void actionFromScriptValue(const QScriptValue& object, Action& action); QScriptValue inputPairToScriptValue(QScriptEngine* engine, const Input::NamedPair& inputPair); void inputPairFromScriptValue(const QScriptValue& object, Input::NamedPair& inputPair); +QScriptValue handToScriptValue(QScriptEngine* engine, const controller::Hand& hand); +void handFromScriptValue(const QScriptValue& object, controller::Hand& hand); QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input) { QScriptValue obj = engine->newObject(); @@ -393,12 +405,21 @@ void inputPairFromScriptValue(const QScriptValue& object, Input::NamedPair& inpu inputPair.second = QString(object.property("inputName").toVariant().toString()); } +QScriptValue handToScriptValue(QScriptEngine* engine, const controller::Hand& hand) { + return engine->newVariant((int)hand); +} + +void handFromScriptValue(const QScriptValue& object, controller::Hand& hand) { + hand = Hand(object.toVariant().toInt()); +} + void UserInputMapper::registerControllerTypes(QScriptEngine* engine) { qScriptRegisterSequenceMetaType >(engine); qScriptRegisterSequenceMetaType(engine); qScriptRegisterMetaType(engine, actionToScriptValue, actionFromScriptValue); qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue); qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue); + qScriptRegisterMetaType(engine, handToScriptValue, handFromScriptValue); qScriptRegisterMetaType(engine, Pose::toScriptValue, Pose::fromScriptValue); } diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index b23657fff7..811b621b09 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -89,7 +89,8 @@ namespace controller { void setActionState(Action action, float value) { _actionStates[toInt(action)] = value; } void deltaActionState(Action action, float delta) { _actionStates[toInt(action)] += delta; } void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; } - bool triggerHapticPulse(uint16 deviceID, float strength, float duration, bool leftHand); + bool triggerHapticPulse(float strength, float duration, controller::Hand hand); + bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand); static Input makeStandardInput(controller::StandardButtonChannel button); static Input makeStandardInput(controller::StandardAxisChannel axis); @@ -200,6 +201,7 @@ Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(controller::Input) Q_DECLARE_METATYPE(controller::Action) Q_DECLARE_METATYPE(QVector) +Q_DECLARE_METATYPE(controller::Hand) // Cheating. using UserInputMapper = controller::UserInputMapper; diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index cf7dde371b..c20670d4bb 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -67,7 +67,7 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { } } -bool Joystick::triggerHapticPulse(float strength, float duration, bool leftHand) { +bool Joystick::triggerHapticPulse(float strength, float duration, controller::Hand hand) { if (SDL_HapticRumblePlay(_sdlHaptic, strength, duration) != 0) { return false; } diff --git a/plugins/hifiSdl2/src/Joystick.h b/plugins/hifiSdl2/src/Joystick.h index 4f785f85ce..b37d22de39 100644 --- a/plugins/hifiSdl2/src/Joystick.h +++ b/plugins/hifiSdl2/src/Joystick.h @@ -37,7 +37,7 @@ public: virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; virtual void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; Joystick() : InputDevice("GamePad") {} ~Joystick(); diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 3151db1d90..2e7044bd69 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -55,11 +55,6 @@ bool OculusControllerManager::activate() { userInputMapper->registerDevice(_touch); } - _leftHapticTimer.setSingleShot(true); - _rightHapticTimer.setSingleShot(true); - connect(&_leftHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(true))); - connect(&_rightHapticTimer, SIGNAL(timeout()), this, SLOT(stopHapticPulse(false))); - return true; } @@ -221,6 +216,21 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control _buttonPressedMap.insert(pair.second); } } + + // Haptics + { + Locker locker(_lock); + if (_leftHapticDuration > 0.0f) { + _leftHapticDuration -= deltaTime; + } else { + stopHapticPulse(true); + } + if (_rightHapticDuration > 0.0f) { + _rightHapticDuration -= deltaTime; + } else { + stopHapticPulse(false); + } + } } void OculusControllerManager::TouchDevice::focusOutEvent() { @@ -239,19 +249,22 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, pose.velocity = toGlm(handPose.LinearVelocity); } -bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { - auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch); - if (ovr_SetControllerVibration(_parent._session, handType, 1.0f, strength) != ovrSuccess) { - return false; +bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { + Locker locker(_lock); + bool toReturn = true; + if (hand == controller::BOTH || hand == controller::LEFT) { + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, strength) != ovrSuccess) { + toReturn = false; + } + _leftHapticDuration = duration; } - - if (leftHand) { - _parent._leftHapticTimer.start(duration); - } else { - _parent._rightHapticTimer.start(duration); + if (hand == controller::BOTH || hand == controller::RIGHT) { + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, strength) != ovrSuccess) { + toReturn = false; + } + _rightHapticDuration = duration; } - - return true; + return toReturn; } void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index e62c5f45ea..244fe41f67 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -10,7 +10,6 @@ #define hifi__OculusControllerManager #include -#include #include #include @@ -68,20 +67,28 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; private: void stopHapticPulse(bool leftHand); void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); int _trackedControllers { 0 }; + + // perform an action when the TouchDevice mutex is acquired. + using Locker = std::unique_lock; + template + void withLock(F&& f) { Locker locker(_lock); f(); } + + float _leftHapticDuration { 0.0f }; + float _rightHapticDuration { 0.0f }; + mutable std::recursive_mutex _lock; + friend class OculusControllerManager; }; ovrSession _session { nullptr }; ovrInputState _inputState {}; RemoteDevice::Pointer _remote; - QTimer _leftHapticTimer; - QTimer _rightHapticTimer; TouchDevice::Pointer _touch; static const QString NAME; }; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 39b5e620ad..27b4887edd 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -452,12 +452,13 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const _poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = avatarPose.transform(controllerToAvatar); } -bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, bool leftHand) { +bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); - if (leftHand) { + if (hand == controller::BOTH || hand == controller::LEFT) { _leftHapticStrength = strength; _leftHapticDuration = duration; - } else { + } + if (hand == controller::BOTH || hand == controller::RIGHT) { _rightHapticStrength = strength; _rightHapticDuration = duration; } @@ -481,9 +482,6 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef _system->TriggerHapticPulse(deviceIndex, 0, hapticTime); } - // Must wait 5 ms before triggering another pulse on this controller - // https://github.com/ValveSoftware/openvr/wiki/IVRSystem::TriggerHapticPulse - const float HAPTIC_RESET_TIME = 5.0f; float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds if (leftHand) { _leftHapticDuration = remainingHapticTime; diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 9bdbd0370e..3a2ef1573f 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -48,7 +48,7 @@ public: private: class InputDevice : public controller::InputDevice { public: - InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system), _leftHapticDuration(0.0f), _rightHapticDuration(0.0f) {} + InputDevice(vr::IVRSystem*& system) : controller::InputDevice("Vive"), _system(system) {} private: // Device functions controller::Input::NamedVector getAvailableInputs() const override; @@ -56,7 +56,7 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, bool leftHand) override; + bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; void hapticsHelper(float deltaTime, bool leftHand); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); @@ -100,10 +100,10 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; - float _leftHapticStrength; - float _leftHapticDuration; - float _rightHapticStrength; - float _rightHapticDuration; + float _leftHapticStrength { 0.0f }; + float _leftHapticDuration { 0.0f }; + float _rightHapticStrength { 0.0f }; + float _rightHapticDuration { 0.0f }; mutable std::recursive_mutex _lock; friend class ViveControllerManager; From cea0d74c358cbe61ecd6ad19d53ddc6f08e34b5e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 15:20:10 -0700 Subject: [PATCH 35/54] fix spaces and touch duration --- plugins/oculus/src/OculusControllerManager.cpp | 4 ++-- plugins/openvr/src/ViveControllerManager.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 2e7044bd69..21d97adbda 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -221,12 +221,12 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control { Locker locker(_lock); if (_leftHapticDuration > 0.0f) { - _leftHapticDuration -= deltaTime; + _leftHapticDuration -= deltaTime * 1000.0f; // milliseconds } else { stopHapticPulse(true); } if (_rightHapticDuration > 0.0f) { - _rightHapticDuration -= deltaTime; + _rightHapticDuration -= deltaTime * 1000.0f; // milliseconds } else { stopHapticPulse(false); } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 27b4887edd..8e4b277bd7 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -477,8 +477,8 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef // Vive Controllers only support duration up to 4 ms, which is short enough that any variation feels more like strength const float MAX_HAPTIC_TIME = 3999.0f; // in microseconds - float hapticTime = strength*MAX_HAPTIC_TIME; - if (hapticTime < duration*1000.0f) { + float hapticTime = strength * MAX_HAPTIC_TIME; + if (hapticTime < duration * 1000.0f) { _system->TriggerHapticPulse(deviceIndex, 0, hapticTime); } From b59d597780fd4f3ea7789551e0634395a34aa6c1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 15:35:12 -0700 Subject: [PATCH 36/54] if overlapping calls, haptics take on strength and duration of call that will finish last --- plugins/oculus/src/OculusControllerManager.cpp | 10 ++++++---- plugins/oculus/src/OculusControllerManager.h | 2 ++ plugins/openvr/src/ViveControllerManager.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 21d97adbda..02ac44d77c 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -253,16 +253,18 @@ bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, fl Locker locker(_lock); bool toReturn = true; if (hand == controller::BOTH || hand == controller::LEFT) { - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, strength) != ovrSuccess) { + _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) { toReturn = false; } - _leftHapticDuration = duration; + _leftHapticDuration = std::max(duration, _leftHapticDuration); } if (hand == controller::BOTH || hand == controller::RIGHT) { - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, strength) != ovrSuccess) { + _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) { toReturn = false; } - _rightHapticDuration = duration; + _rightHapticDuration = std::max(duration, _rightHapticDuration); } return toReturn; } diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 244fe41f67..3c5cdeb7c6 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -80,7 +80,9 @@ private: void withLock(F&& f) { Locker locker(_lock); f(); } float _leftHapticDuration { 0.0f }; + float _leftHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; + float _rightHapticStrength { 0.0f }; mutable std::recursive_mutex _lock; friend class OculusControllerManager; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8e4b277bd7..7254117922 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -455,12 +455,12 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); if (hand == controller::BOTH || hand == controller::LEFT) { - _leftHapticStrength = strength; - _leftHapticDuration = duration; + _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; + _leftHapticDuration = std::max(duration, _leftHapticDuration); } if (hand == controller::BOTH || hand == controller::RIGHT) { - _rightHapticStrength = strength; - _rightHapticDuration = duration; + _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; + _rightHapticDuration = std::max(duration, _rightHapticDuration); } return true; } From 1994eabc981ca3b212d0d9298b5b2ee9ef91b96f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 16:22:02 -0700 Subject: [PATCH 37/54] grip buttons on vive and touch will make you active in away.js --- scripts/system/away.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/away.js b/scripts/system/away.js index 2b2ea8a42b..38b0f13c00 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -265,9 +265,11 @@ eventMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(goActive); eventMapping.from(Controller.Standard.LT).peek().to(goActive); eventMapping.from(Controller.Standard.LB).peek().to(goActive); eventMapping.from(Controller.Standard.LS).peek().to(goActive); +eventMapping.from(Controller.Standard.LeftGrip).peek().to(goActive); eventMapping.from(Controller.Standard.RT).peek().to(goActive); eventMapping.from(Controller.Standard.RB).peek().to(goActive); eventMapping.from(Controller.Standard.RS).peek().to(goActive); +eventMapping.from(Controller.Standard.RightGrip).peek().to(goActive); eventMapping.from(Controller.Standard.Back).peek().to(goActive); eventMapping.from(Controller.Standard.Start).peek().to(goActive); Controller.enableMapping(eventMappingName); From 8fa52fa15987067d67243e7f8d80583e6666aa6b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 16:48:21 -0700 Subject: [PATCH 38/54] trying to fix warning in joystick.cpp --- plugins/hifiSdl2/src/Joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index c20670d4bb..69c83e5d23 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -25,7 +25,7 @@ Joystick::Joystick(SDL_JoystickID instanceId, SDL_GameController* sdlGameControl _instanceId(instanceId) { if (!_sdlHaptic) { - qDebug(SDL_GetError()); + qDebug() << SDL_GetError(); } SDL_HapticRumbleInit(_sdlHaptic); } From 7a3cba8580ab1fcfd1bcb04b18007a69b9785a4d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 6 Jun 2016 17:06:59 -0700 Subject: [PATCH 39/54] warning be gone --- plugins/hifiSdl2/src/Joystick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index 69c83e5d23..aa6b358d38 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -25,7 +25,7 @@ Joystick::Joystick(SDL_JoystickID instanceId, SDL_GameController* sdlGameControl _instanceId(instanceId) { if (!_sdlHaptic) { - qDebug() << SDL_GetError(); + qDebug() << QString(SDL_GetError()); } SDL_HapticRumbleInit(_sdlHaptic); } From dd97f16728575b1c0b9c703536e6df7de756a635 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 11:42:58 -0700 Subject: [PATCH 40/54] investigating xbox failure on restart (WIP) --- .../controllers/src/controllers/UserInputMapper.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index c1ee3ce36c..e3a520e6c4 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -77,7 +77,7 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) { } const auto& deviceID = device->_deviceID; - recordDeviceOfType(device->getName()); + //recordDeviceOfType(device->getName()); qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID; @@ -134,6 +134,15 @@ void UserInputMapper::removeDevice(int deviceID) { _mappingsByDevice.erase(mappingsEntry); } + for (const auto& inputMapping : device->getAvailableInputs()) { + const auto& input = inputMapping.first; + auto endpoint = _endpointsByInput.find(input); + if (endpoint != _endpointsByInput.end()) { + _inputsByEndpoint.erase((*endpoint).second); + _endpointsByInput.erase(input); + } + } + _registeredDevices.erase(proxyEntry); emit hardwareChanged(); From ff2405437bbbda73d4caaf6df2efca9c94709be1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 12:19:38 -0700 Subject: [PATCH 41/54] can set strength to 0 --- .../oculus/src/OculusControllerManager.cpp | 26 +++++++++++++------ plugins/openvr/src/ViveControllerManager.cpp | 18 ++++++++++--- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 02ac44d77c..f00b943d7c 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -253,18 +253,28 @@ bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, fl Locker locker(_lock); bool toReturn = true; if (hand == controller::BOTH || hand == controller::LEFT) { - _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) { - toReturn = false; + if (strength == 0.0f) { + _leftHapticStrength = 0.0f; + _leftHapticDuration = 0.0f; + } else { + _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) { + toReturn = false; + } + _leftHapticDuration = std::max(duration, _leftHapticDuration); } - _leftHapticDuration = std::max(duration, _leftHapticDuration); } if (hand == controller::BOTH || hand == controller::RIGHT) { - _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) { - toReturn = false; + if (strength == 0.0f) { + _rightHapticStrength = 0.0f; + _rightHapticDuration = 0.0f; + } else { + _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; + if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) { + toReturn = false; + } + _rightHapticDuration = std::max(duration, _rightHapticDuration); } - _rightHapticDuration = std::max(duration, _rightHapticDuration); } return toReturn; } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 7254117922..74c232af33 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -455,12 +455,22 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); if (hand == controller::BOTH || hand == controller::LEFT) { - _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; - _leftHapticDuration = std::max(duration, _leftHapticDuration); + if (strength == 0.0f) { + _leftHapticStrength = 0.0f; + _leftHapticDuration = 0.0f; + } else { + _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; + _leftHapticDuration = std::max(duration, _leftHapticDuration); + } } if (hand == controller::BOTH || hand == controller::RIGHT) { - _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; - _rightHapticDuration = std::max(duration, _rightHapticDuration); + if (strength == 0.0f) { + _rightHapticStrength = 0.0f; + _rightHapticDuration = 0.0f; + } else { + _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; + _rightHapticDuration = std::max(duration, _rightHapticDuration); + } } return true; } From 2e71a635749350960c2c5d8b171b18a2391b77c0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 13:28:10 -0700 Subject: [PATCH 42/54] cr fixes --- plugins/hifiSdl2/src/Joystick.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index aa6b358d38..e88fe8b958 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -25,9 +25,12 @@ Joystick::Joystick(SDL_JoystickID instanceId, SDL_GameController* sdlGameControl _instanceId(instanceId) { if (!_sdlHaptic) { - qDebug() << QString(SDL_GetError()); + qDebug() << "SDL Haptic Open Failure: " << QString(SDL_GetError()); + } else { + if (SDL_HapticRumbleInit(_sdlHaptic) != 0) { + qDebug() << "SDL Haptic Rumble Init Failure: " << QString(SDL_GetError()); + } } - SDL_HapticRumbleInit(_sdlHaptic); } Joystick::~Joystick() { @@ -35,7 +38,9 @@ Joystick::~Joystick() { } void Joystick::closeJoystick() { - SDL_HapticClose(_sdlHaptic); + if (_sdlHaptic) { + SDL_HapticClose(_sdlHaptic); + } SDL_GameControllerClose(_sdlGameController); } From 5daccba235814bdf3f61ebf5e76813330aa66b69 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 15:14:08 -0700 Subject: [PATCH 43/54] xbox controller works on restart --- libraries/controllers/src/controllers/UserInputMapper.cpp | 6 +++++- libraries/controllers/src/controllers/UserInputMapper.h | 2 +- plugins/hifiSdl2/src/Joystick.cpp | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index e3a520e6c4..9132b9d3a5 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -77,7 +77,7 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) { } const auto& deviceID = device->_deviceID; - //recordDeviceOfType(device->getName()); + recordDeviceOfType(device->getName()); qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID; @@ -126,6 +126,10 @@ void UserInputMapper::removeDevice(int deviceID) { auto device = proxyEntry->second; qCDebug(controllers) << "Unregistering input device <" << device->getName() << "> deviceID = " << deviceID; + if (!_deviceCounts.contains(device->getName())) { + _deviceCounts[device->getName()] -= 1; + } + unloadMappings(device->getDefaultMappingConfigs()); auto mappingsEntry = _mappingsByDevice.find(deviceID); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 9c79415b6e..2c8aabc099 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -142,7 +142,7 @@ namespace controller { std::vector _lastStandardStates = std::vector(); int recordDeviceOfType(const QString& deviceName); - QHash _deviceCounts; + QHash _deviceCounts; static float getValue(const EndpointPointer& endpoint, bool peek = false); static Pose getPose(const EndpointPointer& endpoint, bool peek = false); diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index a109656489..614adff7d6 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -64,7 +64,7 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { controller::Input::NamedVector Joystick::getAvailableInputs() const { using namespace controller; - static const Input::NamedVector availableInputs{ + const Input::NamedVector availableInputs{ makePair(A, "A"), makePair(B, "B"), makePair(X, "X"), From 545dda0a9887652942e6368da1be64a7ace3b441 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 15:15:42 -0700 Subject: [PATCH 44/54] whoops --- libraries/controllers/src/controllers/UserInputMapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 9132b9d3a5..9dbad89a9b 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -126,7 +126,7 @@ void UserInputMapper::removeDevice(int deviceID) { auto device = proxyEntry->second; qCDebug(controllers) << "Unregistering input device <" << device->getName() << "> deviceID = " << deviceID; - if (!_deviceCounts.contains(device->getName())) { + if (_deviceCounts.contains(device->getName())) { _deviceCounts[device->getName()] -= 1; } From 30d8ae36e8db11d17f7e4ea237ed89771630d221 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 7 Jun 2016 16:55:32 -0700 Subject: [PATCH 45/54] Added MyAvatar.characterControllerEnabled property --- interface/src/avatar/MyAvatar.cpp | 26 ++++++++++++++++++++------ interface/src/avatar/MyAvatar.h | 4 ++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0f723d29e3..3495a05962 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -234,7 +234,7 @@ QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) { void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "reset", Q_ARG(bool, andRecenter)); + QMetaObject::invokeMethod(this, "reset", Q_ARG(bool, andRecenter), Q_ARG(bool, andReload), Q_ARG(bool, andHead)); return; } @@ -1816,6 +1816,16 @@ void MyAvatar::updateMotionBehaviorFromMenu() { _motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED; } + setCharacterControllerEnabled(menu->isOptionChecked(MenuOption::EnableCharacterController)); +} + +void MyAvatar::setCharacterControllerEnabled(bool enabled) { + + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setCharacterControllerEnabled", Q_ARG(bool, enabled)); + return; + } + bool ghostingAllowed = true; EntityTreeRenderer* entityTreeRenderer = qApp->getEntities(); if (entityTreeRenderer) { @@ -1824,12 +1834,16 @@ void MyAvatar::updateMotionBehaviorFromMenu() { ghostingAllowed = zone->getGhostingAllowed(); } } - bool checked = menu->isOptionChecked(MenuOption::EnableCharacterController); - if (!ghostingAllowed) { - checked = true; - } + _characterController.setEnabled(ghostingAllowed ? enabled : true); +} - _characterController.setEnabled(checked); +bool MyAvatar::getCharacterControllerEnabled() { + if (QThread::currentThread() != thread()) { + bool result; + QMetaObject::invokeMethod(this, "getCharacterControllerEnabled", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result)); + return result; + } + return _characterController.isEnabled(); } void MyAvatar::clearDriveKeys() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a938aea675..05afe39a32 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -84,6 +84,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(float energy READ getEnergy WRITE setEnergy) Q_PROPERTY(bool hmdLeanRecenterEnabled READ getHMDLeanRecenterEnabled WRITE setHMDLeanRecenterEnabled) + Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled) public: explicit MyAvatar(RigPointer rig); @@ -265,6 +266,9 @@ public: controller::Pose getLeftHandControllerPoseInAvatarFrame() const; controller::Pose getRightHandControllerPoseInAvatarFrame() const; + Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); + Q_INVOKABLE bool getCharacterControllerEnabled(); + public slots: void increaseSize(); void decreaseSize(); From 2c1d20bd1af4abf59a30f86125f5b2c24210b769 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Jun 2016 17:12:24 -0700 Subject: [PATCH 46/54] removed _deviceCounts, cache joystick available inputs, added deadzone to gamepad thumbsticks --- interface/resources/controllers/xbox.json | 8 +- .../src/controllers/UserInputMapper.cpp | 14 --- .../src/controllers/UserInputMapper.h | 3 - plugins/hifiSdl2/src/Joystick.cpp | 94 ++++++++++--------- plugins/hifiSdl2/src/Joystick.h | 2 + 5 files changed, 54 insertions(+), 67 deletions(-) diff --git a/interface/resources/controllers/xbox.json b/interface/resources/controllers/xbox.json index 8c341dff83..fdac70ff33 100644 --- a/interface/resources/controllers/xbox.json +++ b/interface/resources/controllers/xbox.json @@ -1,14 +1,14 @@ { "name": "XBox to Standard", "channels": [ - { "from": "GamePad.LY", "to": "Standard.LY" }, - { "from": "GamePad.LX", "to": "Standard.LX" }, + { "from": "GamePad.LY", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.LY" }, + { "from": "GamePad.LX", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.LX" }, { "from": "GamePad.LT", "to": "Standard.LT" }, { "from": "GamePad.LB", "to": "Standard.LB" }, { "from": "GamePad.LS", "to": "Standard.LS" }, - { "from": "GamePad.RY", "to": "Standard.RY" }, - { "from": "GamePad.RX", "to": "Standard.RX" }, + { "from": "GamePad.RY", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.RY" }, + { "from": "GamePad.RX", "filters": { "type": "deadZone", "min": 0.05 }, "to": "Standard.RX" }, { "from": "GamePad.RT", "to": "Standard.RT" }, { "from": "GamePad.RB", "to": "Standard.RB" }, { "from": "GamePad.RS", "to": "Standard.RS" }, diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 9dbad89a9b..4df460cbea 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -62,14 +62,6 @@ namespace controller { UserInputMapper::~UserInputMapper() { } -int UserInputMapper::recordDeviceOfType(const QString& deviceName) { - if (!_deviceCounts.contains(deviceName)) { - _deviceCounts[deviceName] = 0; - } - _deviceCounts[deviceName] += 1; - return _deviceCounts[deviceName]; -} - void UserInputMapper::registerDevice(InputDevice::Pointer device) { Locker locker(_lock); if (device->_deviceID == Input::INVALID_DEVICE) { @@ -77,8 +69,6 @@ void UserInputMapper::registerDevice(InputDevice::Pointer device) { } const auto& deviceID = device->_deviceID; - recordDeviceOfType(device->getName()); - qCDebug(controllers) << "Registered input device <" << device->getName() << "> deviceID = " << deviceID; for (const auto& inputMapping : device->getAvailableInputs()) { @@ -126,10 +116,6 @@ void UserInputMapper::removeDevice(int deviceID) { auto device = proxyEntry->second; qCDebug(controllers) << "Unregistering input device <" << device->getName() << "> deviceID = " << deviceID; - if (_deviceCounts.contains(device->getName())) { - _deviceCounts[device->getName()] -= 1; - } - unloadMappings(device->getDefaultMappingConfigs()); auto mappingsEntry = _mappingsByDevice.find(deviceID); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 2c8aabc099..f752b05b9f 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -141,9 +141,6 @@ namespace controller { std::vector _poseStates = std::vector(toInt(Action::NUM_ACTIONS)); std::vector _lastStandardStates = std::vector(); - int recordDeviceOfType(const QString& deviceName); - QHash _deviceCounts; - static float getValue(const EndpointPointer& endpoint, bool peek = false); static Pose getPose(const EndpointPointer& endpoint, bool peek = false); diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index 614adff7d6..7233bf3079 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -64,53 +64,55 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { controller::Input::NamedVector Joystick::getAvailableInputs() const { using namespace controller; - const Input::NamedVector availableInputs{ - makePair(A, "A"), - makePair(B, "B"), - makePair(X, "X"), - makePair(Y, "Y"), - // DPad - makePair(DU, "DU"), - makePair(DD, "DD"), - makePair(DL, "DL"), - makePair(DR, "DR"), - // Bumpers - makePair(LB, "LB"), - makePair(RB, "RB"), - // Stick press - makePair(LS, "LS"), - makePair(RS, "RS"), - // Center buttons - makePair(START, "Start"), - makePair(BACK, "Back"), - // Analog sticks - makePair(LX, "LX"), - makePair(LY, "LY"), - makePair(RX, "RX"), - makePair(RY, "RY"), - - // Triggers - makePair(LT, "LT"), - makePair(RT, "RT"), + if (_availableInputs.length() == 0) { + _availableInputs = { + makePair(A, "A"), + makePair(B, "B"), + makePair(X, "X"), + makePair(Y, "Y"), + // DPad + makePair(DU, "DU"), + makePair(DD, "DD"), + makePair(DL, "DL"), + makePair(DR, "DR"), + // Bumpers + makePair(LB, "LB"), + makePair(RB, "RB"), + // Stick press + makePair(LS, "LS"), + makePair(RS, "RS"), + // Center buttons + makePair(START, "Start"), + makePair(BACK, "Back"), + // Analog sticks + makePair(LX, "LX"), + makePair(LY, "LY"), + makePair(RX, "RX"), + makePair(RY, "RY"), - // Aliases, PlayStation style names - makePair(LB, "L1"), - makePair(RB, "R1"), - makePair(LT, "L2"), - makePair(RT, "R2"), - makePair(LS, "L3"), - makePair(RS, "R3"), - makePair(BACK, "Select"), - makePair(A, "Cross"), - makePair(B, "Circle"), - makePair(X, "Square"), - makePair(Y, "Triangle"), - makePair(DU, "Up"), - makePair(DD, "Down"), - makePair(DL, "Left"), - makePair(DR, "Right"), - }; - return availableInputs; + // Triggers + makePair(LT, "LT"), + makePair(RT, "RT"), + + // Aliases, PlayStation style names + makePair(LB, "L1"), + makePair(RB, "R1"), + makePair(LT, "L2"), + makePair(RT, "R2"), + makePair(LS, "L3"), + makePair(RS, "R3"), + makePair(BACK, "Select"), + makePair(A, "Cross"), + makePair(B, "Circle"), + makePair(X, "Square"), + makePair(Y, "Triangle"), + makePair(DU, "Up"), + makePair(DD, "Down"), + makePair(DL, "Left"), + makePair(DR, "Right"), + }; + } + return _availableInputs; } QString Joystick::getDefaultMappingConfig() const { diff --git a/plugins/hifiSdl2/src/Joystick.h b/plugins/hifiSdl2/src/Joystick.h index e2eaeaef8b..fb4d205689 100644 --- a/plugins/hifiSdl2/src/Joystick.h +++ b/plugins/hifiSdl2/src/Joystick.h @@ -53,6 +53,8 @@ private: SDL_GameController* _sdlGameController; SDL_Joystick* _sdlJoystick; SDL_JoystickID _instanceId; + + mutable controller::Input::NamedVector _availableInputs; }; #endif // hifi_Joystick_h From 9926c809179c8d98efdbce5afd497bd59b2ee63c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 8 Jun 2016 18:15:34 -0500 Subject: [PATCH 47/54] Only check user metadata before sending --- domain-server/src/DomainMetadata.cpp | 14 +++++++++++--- domain-server/src/DomainMetadata.h | 10 ++++++++++ domain-server/src/DomainServer.cpp | 5 +++++ domain-server/src/DomainServer.h | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 8fdbc2bbd1..26d2bb87ce 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -79,11 +79,11 @@ void DomainMetadata::setDescriptors(QVariantMap& settings) { _metadata[DESCRIPTORS] = descriptors; #if DEV_BUILD || PR_BUILD - qDebug() << "Regenerated domain metadata - descriptors:" << descriptors; + qDebug() << "Domain metadata descriptors set:" << descriptors; #endif } -void DomainMetadata::usersChanged() { +void DomainMetadata::updateUsers() { static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); @@ -119,6 +119,14 @@ void DomainMetadata::usersChanged() { _metadata[USERS] = users; #if DEV_BUILD || PR_BUILD - qDebug() << "Regenerated domain metadata - users:" << users; + qDebug() << "Domain metadata users updated:" << users; +#endif +} + +void DomainMetadata::usersChanged() { + ++_tic; + +#if DEV_BUILD || PR_BUILD + qDebug() << "Domain metadata users change detected"; #endif } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index e2f4674afc..7d58d43182 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -11,6 +11,8 @@ #ifndef hifi_DomainMetadata_h #define hifi_DomainMetadata_h +#include + #include #include @@ -39,17 +41,25 @@ Q_OBJECT public: DomainMetadata(); + // Returns the last set metadata + // If connected users have changed, metadata may need to be updated + // this should be checked by storing tic = getTic() between calls + // and testing it for equality before the next get (tic == getTic()) QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); } QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); } + uint32_t getTic() { return _tic; } + void setDescriptors(QVariantMap& settings); + void updateUsers(); public slots: void usersChanged(); protected: QVariantMap _metadata; + uint32_t _tic{ 0 }; }; #endif // hifi_DomainMetadata_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 88c4e215b2..0f5498a575 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1101,6 +1101,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { // Add the metadata to the heartbeat static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + auto tic = _metadata.getTic(); + if (_metadataTic != tic) { + _metadataTic = tic; + _metadata.updateUsers(); + } domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index acda550ce5..8b8409ff0a 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -171,6 +171,7 @@ private: DomainServerSettingsManager _settingsManager; DomainMetadata _metadata; + uint32_t _metadataTic{ 0 }; HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; From 5352bd4b76bc711d999897a47589632147d868a5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 9 Jun 2016 17:15:17 +1200 Subject: [PATCH 48/54] Fix height of Load Defaults button --- interface/resources/qml/hifi/dialogs/RunningScripts.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index cbbbec5bff..94b8c1905f 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -261,6 +261,7 @@ Window { HifiControls.Button { text: "Load Defaults" color: hifi.buttons.black + height: 26 onClicked: loadDefaults() } } From ff8d4883b10eafd167d96f6c63b9817bc848a96e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 8 Jun 2016 14:56:18 -0700 Subject: [PATCH 49/54] Attempt to get better logging from pure virtual call crashes --- interface/src/CrashReporter.cpp | 44 +++++++++++++++++++++-- interface/src/FileLogger.cpp | 4 +++ interface/src/FileLogger.h | 1 + libraries/shared/src/GenericQueueThread.h | 27 ++++++++++++-- 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/interface/src/CrashReporter.cpp b/interface/src/CrashReporter.cpp index 1fd534ffac..d683c5e4df 100644 --- a/interface/src/CrashReporter.cpp +++ b/interface/src/CrashReporter.cpp @@ -10,15 +10,20 @@ // -#ifdef HAS_BUGSPLAT #include "CrashReporter.h" +#ifdef _WIN32 +#include #include #include +#include #include - #include +#include "Application.h" + + +#pragma comment(lib, "Dbghelp.lib") // SetUnhandledExceptionFilter can be overridden by the CRT at the point that an error occurs. More information // can be found here: http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li @@ -77,13 +82,43 @@ BOOL redirectLibraryFunctionToFunction(char* library, char* function, void* fn) return bRet; } +void printStackTrace(ULONG framesToSkip = 1) { + QString result; + unsigned int i; + void * stack[100]; + unsigned short frames; + SYMBOL_INFO * symbol; + HANDLE process; + + process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); + frames = CaptureStackBackTrace(framesToSkip, 100, stack, NULL); + symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + + for (i = 0; i < frames; i++) { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + qWarning() << QString("%1: %2 - 0x%0X").arg(QString::number(frames - i - 1), QString(symbol->Name), QString::number(symbol->Address, 16)); + } + + free(symbol); + + // Try to force the log to sync to the filesystem + auto app = qApp; + if (app && app->getLogger()) { + app->getLogger()->sync(); + } +} void handleSignal(int signal) { // Throw so BugSplat can handle throw(signal); } -void handlePureVirtualCall() { +void __cdecl handlePureVirtualCall() { + qWarning() << "Pure virtual function call detected"; + printStackTrace(2); // Throw so BugSplat can handle throw("ERROR: Pure virtual call"); } @@ -107,6 +142,8 @@ _purecall_handler __cdecl noop_set_purecall_handler(_purecall_handler pNew) { return nullptr; } +#ifdef HAS_BUGSPLAT + static const DWORD BUG_SPLAT_FLAGS = MDSF_PREVENTHIJACKING | MDSF_USEGUARDMEMORY; CrashReporter::CrashReporter(QString bugSplatDatabase, QString bugSplatApplicationName, QString version) @@ -133,3 +170,4 @@ CrashReporter::CrashReporter(QString bugSplatDatabase, QString bugSplatApplicati } } #endif +#endif \ No newline at end of file diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index f5f7ce6ebe..50f7d15d6b 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -115,3 +115,7 @@ QString FileLogger::getLogData() { } return result; } + +void FileLogger::sync() { + _persistThreadInstance->waitIdle(); +} diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index e9bae63a73..28ac6fba40 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -28,6 +28,7 @@ public: virtual void addMessage(const QString&) override; virtual QString getLogData() override; virtual void locateLog() override; + void sync(); signals: void rollingLogFile(QString newFilename); diff --git a/libraries/shared/src/GenericQueueThread.h b/libraries/shared/src/GenericQueueThread.h index 28fcdb0ed6..7c1bdccaa7 100644 --- a/libraries/shared/src/GenericQueueThread.h +++ b/libraries/shared/src/GenericQueueThread.h @@ -12,9 +12,10 @@ #include -#include -#include -#include +#include +#include +#include +#include #include "GenericThread.h" #include "NumericalConstants.h" @@ -35,6 +36,25 @@ public: _hasItems.wakeAll(); } + void waitIdle(uint32_t maxWaitMs = UINT32_MAX) { + QElapsedTimer timer; + timer.start(); + + // FIXME this will work as long as the thread doing the wait + // is the only thread which can add work to the queue. + // It would be better if instead we had a queue empty condition to wait on + // that would ensure that we get woken as soon as we're idle the very + // first time the queue was empty. + while (timer.elapsed() < maxWaitMs) { + lock(); + if (!_items.size()) { + unlock(); + return; + } + unlock(); + } + } + protected: virtual void queueItemInternal(const T& t) { _items.push_back(t); @@ -44,6 +64,7 @@ protected: return MSECS_PER_SECOND; } + virtual bool process() { lock(); if (!_items.size()) { From 1aae22f5a59246e795801aa09ecf07bd93ee50af Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 9 Jun 2016 09:35:19 -0700 Subject: [PATCH 50/54] Optimized MyAvatar.getCharacterControllerEnabled() Instead of doing a blocking queued invokeMethod, it just calls into CharacterController.isEnabled() which is now thread-safe. --- interface/src/avatar/MyAvatar.cpp | 11 +++-------- libraries/physics/src/CharacterController.h | 6 ++++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3495a05962..d5c481164c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1253,13 +1253,13 @@ void MyAvatar::prepareForPhysicsSimulation() { void MyAvatar::harvestResultsFromPhysicsSimulation(float deltaTime) { glm::vec3 position = getPosition(); glm::quat orientation = getOrientation(); - if (_characterController.isEnabled()) { + if (_characterController.isEnabledAndReady()) { _characterController.getPositionAndOrientation(position, orientation); } nextAttitude(position, orientation); _bodySensorMatrix = _follow.postPhysicsUpdate(*this, _bodySensorMatrix); - if (_characterController.isEnabled()) { + if (_characterController.isEnabledAndReady()) { setVelocity(_characterController.getLinearVelocity() + _characterController.getFollowVelocity()); } else { setVelocity(getVelocity() + _characterController.getFollowVelocity()); @@ -1642,7 +1642,7 @@ void MyAvatar::updatePosition(float deltaTime) { vec3 velocity = getVelocity(); const float MOVING_SPEED_THRESHOLD_SQUARED = 0.0001f; // 0.01 m/s - if (!_characterController.isEnabled()) { + if (!_characterController.isEnabledAndReady()) { // _characterController is not in physics simulation but it can still compute its target velocity updateMotors(); _characterController.computeNewVelocity(deltaTime, velocity); @@ -1838,11 +1838,6 @@ void MyAvatar::setCharacterControllerEnabled(bool enabled) { } bool MyAvatar::getCharacterControllerEnabled() { - if (QThread::currentThread() != thread()) { - bool result; - QMetaObject::invokeMethod(this, "getCharacterControllerEnabled", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result)); - return result; - } return _characterController.isEnabled(); } diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 2191f46d55..586ea175e6 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -105,8 +106,9 @@ public: void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale); + bool isEnabled() const { return _enabled; } // thread-safe void setEnabled(bool enabled); - bool isEnabled() const { return _enabled && _dynamicsWorld; } + bool isEnabledAndReady() const { return _enabled && _dynamicsWorld; } bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); @@ -167,7 +169,7 @@ protected: btQuaternion _followAngularDisplacement; btVector3 _linearAcceleration; - bool _enabled; + std::atomic_bool _enabled; State _state; bool _isPushingUp; From eee1ba09062216b0032110f5b1e6583a3ee4510c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 9 Jun 2016 10:19:38 -0700 Subject: [PATCH 51/54] trying to get buildability --- interface/src/CrashReporter.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/CrashReporter.cpp b/interface/src/CrashReporter.cpp index d683c5e4df..fce472e311 100644 --- a/interface/src/CrashReporter.cpp +++ b/interface/src/CrashReporter.cpp @@ -10,17 +10,16 @@ // +#include "Application.h" #include "CrashReporter.h" #ifdef _WIN32 -#include #include #include #include #include #include -#include "Application.h" #pragma comment(lib, "Dbghelp.lib") @@ -170,4 +169,4 @@ CrashReporter::CrashReporter(QString bugSplatDatabase, QString bugSplatApplicati } } #endif -#endif \ No newline at end of file +#endif From cd7c6be5906019c64a25876b33fd460f7e9eeefa Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 9 Jun 2016 12:25:21 -0700 Subject: [PATCH 52/54] Fix formatting --- interface/src/CrashReporter.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/interface/src/CrashReporter.cpp b/interface/src/CrashReporter.cpp index fce472e311..596c34ca92 100644 --- a/interface/src/CrashReporter.cpp +++ b/interface/src/CrashReporter.cpp @@ -82,21 +82,15 @@ BOOL redirectLibraryFunctionToFunction(char* library, char* function, void* fn) } void printStackTrace(ULONG framesToSkip = 1) { - QString result; - unsigned int i; - void * stack[100]; - unsigned short frames; - SYMBOL_INFO * symbol; - HANDLE process; - - process = GetCurrentProcess(); + HANDLE process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); - frames = CaptureStackBackTrace(framesToSkip, 100, stack, NULL); - symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + void* stack[100]; + uint16_t frames = CaptureStackBackTrace(framesToSkip, 100, stack, NULL); + SYMBOL_INFO* symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - for (i = 0; i < frames; i++) { + for (uint16_t i = 0; i < frames; ++i) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); qWarning() << QString("%1: %2 - 0x%0X").arg(QString::number(frames - i - 1), QString(symbol->Name), QString::number(symbol->Address, 16)); } From d7079fce8c78dc51af64f9f6646b7d2473cef00f Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 9 Jun 2016 15:07:24 -0700 Subject: [PATCH 53/54] Use shared CPUDetect.h for CPU detection --- libraries/audio/src/AudioHRTF.cpp | 53 ++----------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/libraries/audio/src/AudioHRTF.cpp b/libraries/audio/src/AudioHRTF.cpp index 7fadf073a1..89c929011a 100644 --- a/libraries/audio/src/AudioHRTF.cpp +++ b/libraries/audio/src/AudioHRTF.cpp @@ -119,61 +119,12 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float } } -// -// Detect AVX/AVX2 support -// - -#if defined(_MSC_VER) - -#include - -static bool cpuSupportsAVX() { - int info[4]; - int mask = (1 << 27) | (1 << 28); // OSXSAVE and AVX - - __cpuidex(info, 0x1, 0); - - bool result = false; - if ((info[2] & mask) == mask) { - - if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) { - result = true; - } - } - return result; -} - -#elif defined(__GNUC__) - -#include - -static bool cpuSupportsAVX() { - unsigned int eax, ebx, ecx, edx; - unsigned int mask = (1 << 27) | (1 << 28); // OSXSAVE and AVX - - bool result = false; - if (__get_cpuid(0x1, &eax, &ebx, &ecx, &edx) && ((ecx & mask) == mask)) { - - __asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0)); - if ((eax & 0x6) == 0x6) { - result = true; - } - } - return result; -} - -#else - -static bool cpuSupportsAVX() { - return false; -} - -#endif - // // Runtime CPU dispatch // +#include "CPUDetect.h" + typedef void FIR_1x4_t(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); FIR_1x4_t FIR_1x4_AVX; // separate compilation with VEX-encoding enabled From dd0d594524975d11ba6dac6152a4adf35dcdfcb8 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 9 Jun 2016 16:31:09 -0700 Subject: [PATCH 54/54] cleanup --- libraries/audio/src/AudioHRTF.cpp | 8 +++----- libraries/audio/src/AudioHRTF.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/audio/src/AudioHRTF.cpp b/libraries/audio/src/AudioHRTF.cpp index 89c929011a..e7cf4436c6 100644 --- a/libraries/audio/src/AudioHRTF.cpp +++ b/libraries/audio/src/AudioHRTF.cpp @@ -10,7 +10,6 @@ // #include -#include #include #include @@ -125,13 +124,12 @@ static void FIR_1x4_SSE(float* src, float* dst0, float* dst1, float* dst2, float #include "CPUDetect.h" -typedef void FIR_1x4_t(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); -FIR_1x4_t FIR_1x4_AVX; // separate compilation with VEX-encoding enabled +void FIR_1x4_AVX(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames); static void FIR_1x4(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) { - static FIR_1x4_t* f = cpuSupportsAVX() ? FIR_1x4_AVX : FIR_1x4_SSE; // init on first call - (*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch + static auto f = cpuSupportsAVX() ? FIR_1x4_AVX : FIR_1x4_SSE; + (*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch } // 4 channel planar to interleaved diff --git a/libraries/audio/src/AudioHRTF.h b/libraries/audio/src/AudioHRTF.h index f92f9c1602..d3b6237d0c 100644 --- a/libraries/audio/src/AudioHRTF.h +++ b/libraries/audio/src/AudioHRTF.h @@ -32,7 +32,7 @@ public: // input: mono source // output: interleaved stereo mix buffer (accumulates into existing output) // index: HRTF subject index - // azimuth: clockwise panning angle [0, 360] in degrees + // azimuth: clockwise panning angle in radians // gain: gain factor for distance attenuation // numFrames: must be HRTF_BLOCK in this version //