From 2202b695751a70837e321240581eeab51a955ec1 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 20 Feb 2019 10:18:55 -0700 Subject: [PATCH 01/16] Guard against accidentally calling wrong api/v1/places endpoint spaces --- domain-server/src/DomainServer.cpp | 2 +- libraries/networking/src/AddressManager.cpp | 6 ++++-- scripts/system/interstitialPage.js | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 258038b8f1..85b116129c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2548,7 +2548,7 @@ bool DomainServer::processPendingContent(HTTPConnection* connection, QString ite _pendingFileContent.seek(_pendingFileContent.size()); _pendingFileContent.write(dataChunk); _pendingFileContent.close(); - + // Respond immediately - will timeout if we wait for restore. connection->respond(HTTPConnection::StatusCode200); if (itemName == "restore-file" || itemName == "restore-file-chunk-final" || itemName == "restore-file-chunk-only") { diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 9145b4a79e..f4221e3d49 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -315,7 +315,9 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { // wasn't an address - lookup the place name // we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after - attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path(), trigger); + if (!lookupUrl.host().isNull() && !lookupUrl.host().isEmpty()) { + attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path(), trigger); + } } } @@ -337,7 +339,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { // be loaded over http(s) // lookupUrl.scheme() == URL_SCHEME_HTTP || // lookupUrl.scheme() == HIFI_URL_SCHEME_HTTPS || - // TODO once a file can return a connection refusal if there were to be some kind of load error, we'd + // TODO once a file can return a connection refusal if there were to be some kind of load error, we'd // need to store the previous domain tried in _lastVisitedURL. For now , do not store it. _previousAPILookup.clear(); diff --git a/scripts/system/interstitialPage.js b/scripts/system/interstitialPage.js index 8dd94623b7..8ecc982dab 100644 --- a/scripts/system/interstitialPage.js +++ b/scripts/system/interstitialPage.js @@ -325,6 +325,11 @@ leftMargin: domainNameLeftMargin }; + // check to be sure we are going to look for an actual domain + if (!domain) { + doRequest = false; + } + if (doRequest) { var url = Account.metaverseServerURL + '/api/v1/places/' + domain; request({ From a31b09b204ac32d1cccc3906fdca7e9e9224db55 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 22 Feb 2019 13:17:13 -0800 Subject: [PATCH 02/16] handle models with no materials --- libraries/graphics/src/graphics/Material.h | 4 ++++ libraries/render-utils/src/RenderPipelines.cpp | 8 ++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index fdddf3640a..2fce8e1195 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -462,6 +462,9 @@ public: void setTexturesLoading(bool value) { _texturesLoading = value; } bool areTexturesLoading() const { return _texturesLoading; } + bool isInitialized() const { return _initialized; } + void setInitialized() { _initialized = true; } + int getTextureCount() const { calculateMaterialInfo(); return _textureCount; } size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } @@ -471,6 +474,7 @@ private: gpu::TextureTablePointer _textureTable { std::make_shared() }; bool _needsUpdate { false }; bool _texturesLoading { false }; + bool _initialized { false }; mutable size_t _textureSize { 0 }; mutable int _textureCount { 0 }; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 6f6f2ab856..67c3b526b9 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -382,11 +382,6 @@ void RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Bat void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) { auto& schemaBuffer = multiMaterial.getSchemaBuffer(); - if (multiMaterial.size() == 0) { - schemaBuffer.edit() = graphics::MultiMaterial::Schema(); - return; - } - auto& drawMaterialTextures = multiMaterial.getTextureTable(); multiMaterial.setTexturesLoading(false); @@ -732,6 +727,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial schema._key = (uint32_t)schemaKey._flags.to_ulong(); schemaBuffer.edit() = schema; multiMaterial.setNeedsUpdate(false); + multiMaterial.setInitialized(); } void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { @@ -739,7 +735,7 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: return; } - if (multiMaterial.needsUpdate() || multiMaterial.areTexturesLoading()) { + if (!multiMaterial.isInitialized() || multiMaterial.needsUpdate() || multiMaterial.areTexturesLoading()) { updateMultiMaterial(multiMaterial); } From dbc3ae3793480bf0021341b33863914fffc98f03 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 22 Feb 2019 14:18:59 -0800 Subject: [PATCH 03/16] hmmm not working --- .../entities-renderer/src/RenderableShapeEntityItem.cpp | 4 ++-- libraries/graphics/src/graphics/Material.h | 7 ++----- libraries/render-utils/src/MeshPartPayload.cpp | 6 +++--- libraries/render-utils/src/RenderPipelines.cpp | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index d42a766faa..5f3f4c9e81 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -53,7 +53,7 @@ bool ShapeEntityRenderer::needsRenderUpdate() const { } auto mat = _materials.find("0"); - if (mat != _materials.end() && (mat->second.needsUpdate() || mat->second.areTexturesLoading())) { + if (mat != _materials.end() && mat->second.shouldUpdate()) { return true; } @@ -188,7 +188,7 @@ bool ShapeEntityRenderer::useMaterialPipeline(const graphics::MultiMaterial& mat ShapeKey ShapeEntityRenderer::getShapeKey() { auto mat = _materials.find("0"); - if (mat != _materials.end() && (mat->second.needsUpdate() || mat->second.areTexturesLoading())) { + if (mat != _materials.end() && mat->second.shouldUpdate()) { RenderPipelines::updateMultiMaterial(mat->second); } diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 2fce8e1195..d24e906f98 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -456,15 +456,12 @@ public: graphics::MaterialKey getMaterialKey() const { return graphics::MaterialKey(_schemaBuffer.get()._key); } const gpu::TextureTablePointer& getTextureTable() const { return _textureTable; } - bool needsUpdate() const { return _needsUpdate; } void setNeedsUpdate(bool needsUpdate) { _needsUpdate = needsUpdate; } - void setTexturesLoading(bool value) { _texturesLoading = value; } - bool areTexturesLoading() const { return _texturesLoading; } - - bool isInitialized() const { return _initialized; } void setInitialized() { _initialized = true; } + bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading; } + int getTextureCount() const { calculateMaterialInfo(); return _textureCount; } size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 6409cdd231..b1104b8aad 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -83,7 +83,7 @@ void MeshPartPayload::updateKey(const render::ItemKey& key) { ItemKey::Builder builder(key); builder.withTypeShape(); - if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) { + if (_drawMaterials.shouldUpdate()) { RenderPipelines::updateMultiMaterial(_drawMaterials); } @@ -329,7 +329,7 @@ void ModelMeshPartPayload::updateKey(const render::ItemKey& key) { builder.withDeformed(); } - if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) { + if (_drawMaterials.shouldUpdate()) { RenderPipelines::updateMultiMaterial(_drawMaterials); } @@ -347,7 +347,7 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, PrimitiveMode pr return; } - if (_drawMaterials.needsUpdate() || _drawMaterials.areTexturesLoading()) { + if (_drawMaterials.shouldUpdate()) { RenderPipelines::updateMultiMaterial(_drawMaterials); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 67c3b526b9..83216ddf84 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -735,7 +735,7 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu: return; } - if (!multiMaterial.isInitialized() || multiMaterial.needsUpdate() || multiMaterial.areTexturesLoading()) { + if (multiMaterial.shouldUpdate()) { updateMultiMaterial(multiMaterial); } From d040803391511f864ee5f116e1e082f92682f168 Mon Sep 17 00:00:00 2001 From: Clement Date: Fri, 22 Feb 2019 18:07:26 -0800 Subject: [PATCH 04/16] Delete old nodes with identical socket --- libraries/networking/src/LimitedNodeList.cpp | 176 +++++++++---------- 1 file changed, 84 insertions(+), 92 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 8b9e37569c..eaa02f059e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -645,103 +645,95 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, Node::LocalID localID, bool isReplicated, bool isUpstream, const QUuid& connectionSecret, const NodePermissions& permissions) { - QReadLocker readLocker(&_nodeMutex); - NodeHash::const_iterator it = _nodeHash.find(uuid); + { + QReadLocker readLocker(&_nodeMutex); + NodeHash::const_iterator it = _nodeHash.find(uuid); - if (it != _nodeHash.end()) { - SharedNodePointer& matchingNode = it->second; + if (it != _nodeHash.end()) { + SharedNodePointer& matchingNode = it->second; - matchingNode->setPublicSocket(publicSocket); - matchingNode->setLocalSocket(localSocket); - matchingNode->setPermissions(permissions); - matchingNode->setConnectionSecret(connectionSecret); - matchingNode->setIsReplicated(isReplicated); - matchingNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType)); - matchingNode->setLocalID(localID); + matchingNode->setPublicSocket(publicSocket); + matchingNode->setLocalSocket(localSocket); + matchingNode->setPermissions(permissions); + matchingNode->setConnectionSecret(connectionSecret); + matchingNode->setIsReplicated(isReplicated); + matchingNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType)); + matchingNode->setLocalID(localID); - return matchingNode; - } else { - auto it = _connectionIDs.find(uuid); - if (it == _connectionIDs.end()) { - _connectionIDs[uuid] = INITIAL_CONNECTION_ID; + return matchingNode; } - - // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); - newNode->setIsReplicated(isReplicated); - newNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType)); - newNode->setConnectionSecret(connectionSecret); - newNode->setPermissions(permissions); - newNode->setLocalID(localID); - - // move the newly constructed node to the LNL thread - newNode->moveToThread(thread()); - - if (nodeType == NodeType::AudioMixer) { - LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); - } - - SharedNodePointer newNodePointer(newNode, &QObject::deleteLater); - - // if this is a solo node type, we assume that the DS has replaced its assignment and we should kill the previous node - if (SOLO_NODE_TYPES.count(newNode->getType())) { - // while we still have the read lock, see if there is a previous solo node we'll need to remove - auto previousSoloIt = std::find_if(_nodeHash.cbegin(), _nodeHash.cend(), [newNode](const UUIDNodePair& nodePair){ - return nodePair.second->getType() == newNode->getType(); - }); - - if (previousSoloIt != _nodeHash.cend()) { - // we have a previous solo node, switch to a write lock so we can remove it - readLocker.unlock(); - - QWriteLocker writeLocker(&_nodeMutex); - - auto oldSoloNode = previousSoloIt->second; - - _localIDMap.unsafe_erase(oldSoloNode->getLocalID()); - _nodeHash.unsafe_erase(previousSoloIt); - handleNodeKill(oldSoloNode); - - // convert the current lock back to a read lock for insertion of new node - writeLocker.unlock(); - readLocker.relock(); - } - } - - // insert the new node and release our read lock -#if defined(Q_OS_ANDROID) || (defined(__clang__) && defined(Q_OS_LINUX)) - _nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer)); - _localIDMap.insert(std::pair(localID, newNodePointer)); -#else - _nodeHash.emplace(newNode->getUUID(), newNodePointer); - _localIDMap.emplace(localID, newNodePointer); -#endif - readLocker.unlock(); - - qCDebug(networking) << "Added" << *newNode; - - auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambdas to hold a strong ref - - emit nodeAdded(newNodePointer); - if (newNodePointer->getActiveSocket()) { - emit nodeActivated(newNodePointer); - } else { - connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [this, weakPtr] { - auto sharedPtr = weakPtr.lock(); - if (sharedPtr) { - emit nodeActivated(sharedPtr); - disconnect(sharedPtr.data(), &NetworkPeer::socketActivated, this, 0); - } - }); - } - - // Signal when a socket changes, so we can start the hole punch over. - connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] { - emit nodeSocketUpdated(weakPtr); - }); - - return newNodePointer; } + + auto removeOldNode = [&](auto node) { + if (node) { + QWriteLocker writeLocker(&_nodeMutex); + _localIDMap.unsafe_erase(node->getLocalID()); + _nodeHash.unsafe_erase(node->getUUID()); + handleNodeKill(node); + } + }; + + // if this is a solo node type, we assume that the DS has replaced its assignment and we should kill the previous node + if (SOLO_NODE_TYPES.count(nodeType)) { + removeOldNode(soloNodeOfType(nodeType)); + } + // If there is a new node with the same socket, this is a reconnection, kill the old node + removeOldNode(findNodeWithAddr(publicSocket)); + removeOldNode(findNodeWithAddr(localSocket)); + + auto it = _connectionIDs.find(uuid); + if (it == _connectionIDs.end()) { + _connectionIDs[uuid] = INITIAL_CONNECTION_ID; + } + + // we didn't have this node, so add them + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); + newNode->setIsReplicated(isReplicated); + newNode->setIsUpstream(isUpstream || NodeType::isUpstream(nodeType)); + newNode->setConnectionSecret(connectionSecret); + newNode->setPermissions(permissions); + newNode->setLocalID(localID); + + // move the newly constructed node to the LNL thread + newNode->moveToThread(thread()); + + if (nodeType == NodeType::AudioMixer) { + LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer); + } + + SharedNodePointer newNodePointer(newNode, &QObject::deleteLater); + + + { + QReadLocker readLocker(&_nodeMutex); + // insert the new node and release our read lock + _nodeHash.insert({ newNode->getUUID(), newNodePointer }); + _localIDMap.insert({ localID, newNodePointer }); + } + + qCDebug(networking) << "Added" << *newNode; + + auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambdas to hold a strong ref + + emit nodeAdded(newNodePointer); + if (newNodePointer->getActiveSocket()) { + emit nodeActivated(newNodePointer); + } else { + connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [this, weakPtr] { + auto sharedPtr = weakPtr.lock(); + if (sharedPtr) { + emit nodeActivated(sharedPtr); + disconnect(sharedPtr.data(), &NetworkPeer::socketActivated, this, 0); + } + }); + } + + // Signal when a socket changes, so we can start the hole punch over. + connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] { + emit nodeSocketUpdated(weakPtr); + }); + + return newNodePointer; } std::unique_ptr LimitedNodeList::constructPingPacket(const QUuid& nodeId, PingType_t pingType) { From 8058ad884e343d685ff72e5dff479a6afeb9cfd3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 25 Feb 2019 09:48:41 -0800 Subject: [PATCH 05/16] trying to fix overlay rotation --- interface/src/ui/overlays/Overlays.cpp | 60 +++++++------------------- interface/src/ui/overlays/Overlays.h | 2 +- 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 62a6b88fc0..6d04c4d53a 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -295,14 +295,14 @@ QString Overlays::overlayToEntityType(const QString& type) { } \ } -static QHash savedRotations = QHash(); +static QHash> savedRotations = QHash>(); EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) { - glm::quat rotation; + std::pair rotation; return convertOverlayToEntityProperties(overlayProps, rotation, type, add, id); } -EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id) { +EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair& rotationToSave, const QString& type, bool add, const QUuid& id) { overlayProps["type"] = type; SET_OVERLAY_PROP_DEFAULT(alpha, 0.7); @@ -559,65 +559,33 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove SET_OVERLAY_PROP_DEFAULT(textures, PathUtils::resourcesUrl() + "images/whitePixel.png"); } - { // Overlays did this conversion for rotation - auto iter = overlayProps.find("rotation"); - if (iter != overlayProps.end() && !overlayProps.contains("localRotation")) { - QUuid parentID; - { - auto iter = overlayProps.find("parentID"); - if (iter != overlayProps.end()) { - parentID = iter.value().toUuid(); - } else if (!add) { - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_PARENT_ID; - parentID = DependencyManager::get()->getEntityProperties(id, desiredProperties).getParentID(); - } - } - - int parentJointIndex = -1; - { - auto iter = overlayProps.find("parentJointIndex"); - if (iter != overlayProps.end()) { - parentJointIndex = iter.value().toInt(); - } else if (!add) { - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_PARENT_JOINT_INDEX; - parentJointIndex = DependencyManager::get()->getEntityProperties(id, desiredProperties).getParentJointIndex(); - } - } - - glm::quat rotation = quatFromVariant(iter.value()); - bool success = false; - glm::quat localRotation = SpatiallyNestable::worldToLocal(rotation, parentID, parentJointIndex, false, success); - if (success) { - overlayProps["rotation"] = quatToVariant(localRotation); - } - } - } - if (type == "Text" || type == "Image" || type == "Grid" || type == "Web") { glm::quat originalRotation = ENTITY_ITEM_DEFAULT_ROTATION; + bool local = false; { auto iter = overlayProps.find("rotation"); if (iter != overlayProps.end()) { originalRotation = quatFromVariant(iter.value()); + local = false; } else { iter = overlayProps.find("localRotation"); if (iter != overlayProps.end()) { originalRotation = quatFromVariant(iter.value()); + local = true; } else if (!add) { auto iter2 = savedRotations.find(id); if (iter2 != savedRotations.end()) { - originalRotation = iter2.value(); + originalRotation = iter2.value().first; + local = iter2.value().second; } } } } if (!add) { - savedRotations[id] = originalRotation; + savedRotations[id] = { originalRotation, local }; } else { - rotationToSave = originalRotation; + rotationToSave = { originalRotation, local }; } glm::vec3 dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS; @@ -648,7 +616,11 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove rotation = glm::angleAxis((float)M_PI, rotation * Vectors::UP) * rotation; } - overlayProps["localRotation"] = quatToVariant(rotation); + if (local) { + overlayProps["localRotation"] = quatToVariant(rotation); + } else { + overlayProps["rotation"] = quatToVariant(rotation); + } overlayProps["dimensions"] = vec3toVariant(glm::abs(dimensions)); } } @@ -826,7 +798,7 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { if (type == "rectangle3d") { propertyMap["shape"] = "Quad"; } - glm::quat rotationToSave; + std::pair rotationToSave; QUuid id = DependencyManager::get()->addEntityInternal(convertOverlayToEntityProperties(propertyMap, rotationToSave, entityType, true), entity::HostType::LOCAL); if (entityType == "Text" || entityType == "Image" || entityType == "Grid" || entityType == "Web") { savedRotations[id] = rotationToSave; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 838a38eb54..93efc2bc0b 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -729,7 +729,7 @@ private: QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps); EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id); - EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid()); + EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, std::pair& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid()); private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); From db821487d9ec82f7a051699fc841cea41eceabb9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 25 Feb 2019 11:01:21 -0800 Subject: [PATCH 06/16] don't allow others' grabs to move locked or ungrabbable things --- interface/src/avatar/GrabManager.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/interface/src/avatar/GrabManager.cpp b/interface/src/avatar/GrabManager.cpp index db1337b64d..8273def490 100644 --- a/interface/src/avatar/GrabManager.cpp +++ b/interface/src/avatar/GrabManager.cpp @@ -32,6 +32,17 @@ void GrabManager::simulateGrabs() { bool success; SpatiallyNestablePointer grabbedThing = SpatiallyNestable::findByID(grabbedThingID, success); if (success && grabbedThing) { + auto entity = std::dynamic_pointer_cast(grabbedThing); + if (entity) { + if (entity->getLocked()) { + continue; // even if someone else claims to be grabbing it, don't move a locked thing + } + const GrabPropertyGroup& grabProps = entity->getGrabProperties(); + if (!grabProps.getGrabbable()) { + continue; // even if someone else claims to be grabbing it, don't move non-grabbable + } + } + glm::vec3 finalPosition = acc.finalizePosition(); glm::quat finalOrientation = acc.finalizeOrientation(); grabbedThing->setTransform(createMatFromQuatAndPos(finalOrientation, finalPosition)); From e102ad073eca78e1598e35ff4d1d057febe67c2b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 25 Feb 2019 11:49:38 -0800 Subject: [PATCH 07/16] allow flying in HMD if you would otherwise fall forever --- interface/src/avatar/MyAvatar.cpp | 3 ++- libraries/physics/src/CharacterController.cpp | 22 ++++++++----------- libraries/physics/src/CharacterController.h | 16 ++++++++------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index af261f490b..faa9f88ae9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -932,7 +932,8 @@ void MyAvatar::simulate(float deltaTime, bool inView) { bool isPhysicsEnabled = qApp->isPhysicsEnabled(); bool zoneAllowsFlying = zoneInteractionProperties.first; bool collisionlessAllowed = zoneInteractionProperties.second; - _characterController.setFlyingAllowed((zoneAllowsFlying && _enableFlying) || !isPhysicsEnabled); + _characterController.setZoneFlyingAllowed(zoneAllowsFlying || !isPhysicsEnabled); + _characterController.setComfortFlyingAllowed(_enableFlying); _characterController.setCollisionlessAllowed(collisionlessAllowed); } diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 66ce5f32bf..a5f1a0598f 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -781,18 +781,18 @@ void CharacterController::updateState() { const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight); if ((velocity.dot(_currentUp) <= (jumpSpeed / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) { SET_STATE(State::Ground, "hit ground"); - } else if (_flyingAllowed) { + } else if (_zoneFlyingAllowed) { btVector3 desiredVelocity = _targetVelocity; if (desiredVelocity.length2() < MIN_TARGET_SPEED_SQUARED) { desiredVelocity = btVector3(0.0f, 0.0f, 0.0f); } bool vertTargetSpeedIsNonZero = desiredVelocity.dot(_currentUp) > MIN_TARGET_SPEED; - if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) { + if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) { SET_STATE(State::Hover, "double jump button"); - } else if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) { + } else if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) { SET_STATE(State::Hover, "jump button held"); - } else if (_floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) { - // Transition to hover if we are above the fall threshold + } else if ((!rayHasHit && !_hasSupport) || _floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) { + // Transition to hover if there's no ground beneath us or we are above the fall threshold, regardless of _comfortFlyingAllowed SET_STATE(State::Hover, "above fall threshold"); } } @@ -801,8 +801,10 @@ void CharacterController::updateState() { case State::Hover: btScalar horizontalSpeed = (velocity - velocity.dot(_currentUp) * _currentUp).length(); bool flyingFast = horizontalSpeed > (MAX_WALKING_SPEED * 0.75f); - if (!_flyingAllowed) { - SET_STATE(State::InAir, "flying not allowed"); + if (!_zoneFlyingAllowed) { + SET_STATE(State::InAir, "zone flying not allowed"); + } else if (!_comfortFlyingAllowed && (rayHasHit || _hasSupport || _floorDistance < FLY_TO_GROUND_THRESHOLD)) { + SET_STATE(State::InAir, "comfort flying not allowed"); } else if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) { SET_STATE(State::InAir, "near ground"); } else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) { @@ -847,12 +849,6 @@ bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPositio return true; } -void CharacterController::setFlyingAllowed(bool value) { - if (value != _flyingAllowed) { - _flyingAllowed = value; - } -} - void CharacterController::setCollisionlessAllowed(bool value) { if (value != _collisionlessAllowed) { _collisionlessAllowed = value; diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index d59374a94a..c46c9c8361 100755 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -65,10 +65,10 @@ public: // overrides from btCharacterControllerInterface virtual void setWalkDirection(const btVector3 &walkDirection) override { assert(false); } virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); } - virtual void reset(btCollisionWorld* collisionWorld) override { } - virtual void warp(const btVector3& origin) override { } - virtual void debugDraw(btIDebugDraw* debugDrawer) override { } - virtual void setUpInterpolate(bool value) override { } + virtual void reset(btCollisionWorld* collisionWorld) override {} + virtual void warp(const btVector3& origin) override {} + virtual void debugDraw(btIDebugDraw* debugDrawer) override {} + virtual void setUpInterpolate(bool value) override {} virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override; virtual void preStep(btCollisionWorld *collisionWorld) override; virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override; @@ -90,7 +90,7 @@ public: void preSimulation(); void postSimulation(); - void setPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation); + void setPositionAndOrientation(const glm::vec3& position, const glm::quat& orientation); void getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const; void setParentVelocity(const glm::vec3& parentVelocity); @@ -129,7 +129,8 @@ public: bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); - void setFlyingAllowed(bool value); + void setZoneFlyingAllowed(bool value) { _zoneFlyingAllowed = value; } + void setComfortFlyingAllowed(bool value) { _comfortFlyingAllowed = value; } void setCollisionlessAllowed(bool value); void setPendingFlagsUpdateCollisionMask(){ _pendingFlags |= PENDING_FLAG_UPDATE_COLLISION_MASK; } @@ -212,7 +213,8 @@ protected: uint32_t _pendingFlags { 0 }; uint32_t _previousFlags { 0 }; - bool _flyingAllowed { true }; + bool _zoneFlyingAllowed { true }; + bool _comfortFlyingAllowed { true }; bool _collisionlessAllowed { true }; bool _collisionless { false }; From cff0fd470a43020148f0baf5fa8dc92d4a74a198 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 25 Feb 2019 12:23:03 -0800 Subject: [PATCH 08/16] re-enabled ik off by default on Desktop --- libraries/animation/src/Rig.cpp | 44 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index fcf2cd28a3..372f03c163 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1064,28 +1064,30 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos t += deltaTime; - if (_enableInverseKinematics) { - _animVars.set("ikOverlayAlpha", 1.0f); - _animVars.set("splineIKEnabled", true); - _animVars.set("leftHandIKEnabled", true); - _animVars.set("rightHandIKEnabled", true); - _animVars.set("leftFootIKEnabled", true); - _animVars.set("rightFootIKEnabled", true); - _animVars.set("leftFootPoleVectorEnabled", true); - _animVars.set("rightFootPoleVectorEnabled", true); - } else { - _animVars.set("ikOverlayAlpha", 0.0f); - _animVars.set("splineIKEnabled", false); - _animVars.set("leftHandIKEnabled", false); - _animVars.set("rightHandIKEnabled", false); - _animVars.set("leftFootIKEnabled", false); - _animVars.set("rightFootIKEnabled", false); - _animVars.set("leftHandPoleVectorEnabled", false); - _animVars.set("rightHandPoleVectorEnabled", false); - _animVars.set("leftFootPoleVectorEnabled", false); - _animVars.set("rightFootPoleVectorEnabled", false); + if (_enableInverseKinematics != _lastEnableInverseKinematics) { + if (_enableInverseKinematics) { + _animVars.set("ikOverlayAlpha", 1.0f); + _animVars.set("splineIKEnabled", true); + _animVars.set("leftHandIKEnabled", true); + _animVars.set("rightHandIKEnabled", true); + _animVars.set("leftFootIKEnabled", true); + _animVars.set("rightFootIKEnabled", true); + _animVars.set("leftFootPoleVectorEnabled", true); + _animVars.set("rightFootPoleVectorEnabled", true); + } else { + _animVars.set("ikOverlayAlpha", 0.0f); + _animVars.set("splineIKEnabled", false); + _animVars.set("leftHandIKEnabled", false); + _animVars.set("rightHandIKEnabled", false); + _animVars.set("leftFootIKEnabled", false); + _animVars.set("rightFootIKEnabled", false); + _animVars.set("leftHandPoleVectorEnabled", false); + _animVars.set("rightHandPoleVectorEnabled", false); + _animVars.set("leftFootPoleVectorEnabled", false); + _animVars.set("rightFootPoleVectorEnabled", false); + } + _lastEnableInverseKinematics = _enableInverseKinematics; } - _lastEnableInverseKinematics = _enableInverseKinematics; } _lastForward = forward; _lastPosition = worldPosition; From 363c0cc26f55a7573f997cc8c0dfe91459b3d87b Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 25 Feb 2019 13:03:28 -0800 Subject: [PATCH 09/16] moved the update of last ik to outside the if changed statement --- libraries/animation/src/Rig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 372f03c163..fb7bb15341 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1086,8 +1086,8 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _animVars.set("leftFootPoleVectorEnabled", false); _animVars.set("rightFootPoleVectorEnabled", false); } - _lastEnableInverseKinematics = _enableInverseKinematics; } + _lastEnableInverseKinematics = _enableInverseKinematics; } _lastForward = forward; _lastPosition = worldPosition; From 12dbaa0ea0698ebe4798605956e15695f0896e74 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 25 Feb 2019 14:56:03 -0800 Subject: [PATCH 10/16] changed the condition so that you can turn off ik in hmd mode if you want to for debug purposes --- libraries/animation/src/Rig.cpp | 35 ++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index fb7bb15341..25f154e9fd 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1064,28 +1064,19 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos t += deltaTime; - if (_enableInverseKinematics != _lastEnableInverseKinematics) { - if (_enableInverseKinematics) { - _animVars.set("ikOverlayAlpha", 1.0f); - _animVars.set("splineIKEnabled", true); - _animVars.set("leftHandIKEnabled", true); - _animVars.set("rightHandIKEnabled", true); - _animVars.set("leftFootIKEnabled", true); - _animVars.set("rightFootIKEnabled", true); - _animVars.set("leftFootPoleVectorEnabled", true); - _animVars.set("rightFootPoleVectorEnabled", true); - } else { - _animVars.set("ikOverlayAlpha", 0.0f); - _animVars.set("splineIKEnabled", false); - _animVars.set("leftHandIKEnabled", false); - _animVars.set("rightHandIKEnabled", false); - _animVars.set("leftFootIKEnabled", false); - _animVars.set("rightFootIKEnabled", false); - _animVars.set("leftHandPoleVectorEnabled", false); - _animVars.set("rightHandPoleVectorEnabled", false); - _animVars.set("leftFootPoleVectorEnabled", false); - _animVars.set("rightFootPoleVectorEnabled", false); - } + if (_enableInverseKinematics) { + _animVars.set("ikOverlayAlpha", 1.0f); + } else { + _animVars.set("ikOverlayAlpha", 0.0f); + _animVars.set("splineIKEnabled", false); + _animVars.set("leftHandIKEnabled", false); + _animVars.set("rightHandIKEnabled", false); + _animVars.set("leftFootIKEnabled", false); + _animVars.set("rightFootIKEnabled", false); + _animVars.set("leftHandPoleVectorEnabled", false); + _animVars.set("rightHandPoleVectorEnabled", false); + _animVars.set("leftFootPoleVectorEnabled", false); + _animVars.set("rightFootPoleVectorEnabled", false); } _lastEnableInverseKinematics = _enableInverseKinematics; } From f235d046013de90509d629f7542c97423e6f559c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 25 Feb 2019 15:06:11 -0800 Subject: [PATCH 11/16] trying to fix web crashes --- .../src/RenderableWebEntityItem.cpp | 142 ++++++++++-------- .../src/RenderableWebEntityItem.h | 1 + 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ccd815b74a..0f2c708d17 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -101,21 +101,15 @@ bool WebEntityRenderer::isTransparent() const { } bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { - if (_contextPosition != entity->getWorldPosition()) { - return true; - } - - { - QSharedPointer webSurface; - withReadLock([&] { - webSurface = _webSurface; - }); - if (webSurface && uvec2(getWindowSize(entity)) != toGlm(webSurface->size())) { + if (resultWithReadLock([&] { + if (_webSurface && uvec2(getWindowSize(entity)) != toGlm(_webSurface->size())) { + return true; + } + + if (_contextPosition != entity->getWorldPosition()) { return true; } - } - if(resultWithReadLock([&] { if (_color != entity->getColor()) { return true; } @@ -194,7 +188,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene auto newContentType = getContentType(newSourceURL); ContentType currentContentType; withReadLock([&] { - urlChanged = _sourceURL != newSourceURL; + urlChanged = newSourceURL.isEmpty() || newSourceURL != _tryingToBuildURL; }); currentContentType = _contentType; @@ -206,7 +200,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene } } - withWriteLock([&] { _inputMode = entity->getInputMode(); _dpi = entity->getDPI(); @@ -216,6 +209,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _billboardMode = entity->getBillboardMode(); if (_contentType == ContentType::NoContent) { + _tryingToBuildURL = newSourceURL; + _sourceURL = newSourceURL; return; } @@ -226,10 +221,12 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene if (_webSurface) { if (_webSurface->getRootItem()) { - if (_contentType == ContentType::HtmlContent && urlChanged) { + if (_contentType == ContentType::HtmlContent && _sourceURL != newSourceURL) { _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL); + _sourceURL = newSourceURL; + } else if (_contentType != ContentType::HtmlContent) { + _sourceURL = newSourceURL; } - _sourceURL = newSourceURL; { auto scriptURL = entity->getScriptURL(); @@ -294,20 +291,21 @@ void WebEntityRenderer::doRender(RenderArgs* args) { }); // Try to update the texture - { - QSharedPointer webSurface; - withReadLock([&] { - webSurface = _webSurface; - }); - if (!webSurface) { - return; + OffscreenQmlSurface::TextureAndFence newTextureAndFence; + bool newTextureAvailable = false; + if (!resultWithReadLock([&] { + if (!_webSurface) { + return false; } - OffscreenQmlSurface::TextureAndFence newTextureAndFence; - bool newTextureAvailable = webSurface->fetchTexture(newTextureAndFence); - if (newTextureAvailable) { - _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); - } + newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence); + return true; + })) { + return; + } + + if (newTextureAvailable) { + _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); } static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); @@ -351,6 +349,8 @@ void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const Q _connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) { emit DependencyManager::get()->webEventReceived(entityItemID, message); })); + + _tryingToBuildURL = newSourceURL; } void WebEntityRenderer::destroyWebSurface() { @@ -383,11 +383,16 @@ glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) con void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) { if (_inputMode == WebInputMode::MOUSE) { handlePointerEvent(event); - } else if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->hoverBeginEvent(webEvent, _touchDevice); + return; } + + withReadLock([&] { + if (_webSurface) { + PointerEvent webEvent = event; + webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); + _webSurface->hoverBeginEvent(webEvent, _touchDevice); + } + }); } void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) { @@ -398,34 +403,39 @@ void WebEntityRenderer::hoverLeaveEntity(const PointerEvent& event) { // QML onReleased is only triggered if a click has happened first. We need to send this "fake" mouse move event to properly trigger an onExited. PointerEvent endMoveEvent(PointerEvent::Move, event.getID()); handlePointerEvent(endMoveEvent); - } else if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->hoverEndEvent(webEvent, _touchDevice); - } -} - -void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) { - if (_inputMode == WebInputMode::TOUCH) { - handlePointerEventAsTouch(event); - } else { - handlePointerEventAsMouse(event); - } -} - -void WebEntityRenderer::handlePointerEventAsTouch(const PointerEvent& event) { - if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->handlePointerEvent(webEvent, _touchDevice); - } -} - -void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) { - if (!_webSurface) { return; } + withReadLock([&] { + if (_webSurface) { + PointerEvent webEvent = event; + webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); + _webSurface->hoverEndEvent(webEvent, _touchDevice); + } + }); +} + +void WebEntityRenderer::handlePointerEvent(const PointerEvent& event) { + withReadLock([&] { + if (!_webSurface) { + return; + } + + if (_inputMode == WebInputMode::TOUCH) { + handlePointerEventAsTouch(event); + } else { + handlePointerEventAsMouse(event); + } + }); +} + +void WebEntityRenderer::handlePointerEventAsTouch(const PointerEvent& event) { + PointerEvent webEvent = event; + webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); + _webSurface->handlePointerEvent(webEvent, _touchDevice); +} + +void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) { glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); @@ -459,16 +469,20 @@ void WebEntityRenderer::handlePointerEventAsMouse(const PointerEvent& event) { } void WebEntityRenderer::setProxyWindow(QWindow* proxyWindow) { - if (_webSurface) { - _webSurface->setProxyWindow(proxyWindow); - } + withReadLock([&] { + if (_webSurface) { + _webSurface->setProxyWindow(proxyWindow); + } + }); } QObject* WebEntityRenderer::getEventHandler() { - if (!_webSurface) { - return nullptr; - } - return _webSurface->getEventHandler(); + return resultWithReadLock([&]() -> QObject* { + if (!_webSurface) { + return nullptr; + } + return _webSurface->getEventHandler(); + }); } void WebEntityRenderer::emitScriptEvent(const QVariant& message) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 30b63a72df..0345898b62 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -82,6 +82,7 @@ private: QSharedPointer _webSurface { nullptr }; bool _cachedWebSurface { false }; gpu::TexturePointer _texture; + QString _tryingToBuildURL; glm::u8vec3 _color; float _alpha { 1.0f }; From 6e4ec15c9de9e19a808191fd11e0aafd58cd63c1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 25 Feb 2019 17:14:51 -0800 Subject: [PATCH 12/16] there we go --- libraries/render-utils/src/RenderPipelines.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 83216ddf84..c4a7368f39 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -731,10 +731,6 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial } void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) { - if (multiMaterial.size() == 0) { - return; - } - if (multiMaterial.shouldUpdate()) { updateMultiMaterial(multiMaterial); } From 4d591e0624081af7ff589f64bb0cb0c3d956f5a1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 26 Feb 2019 16:12:12 -0800 Subject: [PATCH 13/16] fix web interaction and debug print filling logs --- .../entities/src/MovingEntitiesOperator.cpp | 6 +- .../system/libraries/entitySelectionTool.js | 107 ++++++++++-------- 2 files changed, 62 insertions(+), 51 deletions(-) diff --git a/libraries/entities/src/MovingEntitiesOperator.cpp b/libraries/entities/src/MovingEntitiesOperator.cpp index 4b908745e0..9dd5a4d206 100644 --- a/libraries/entities/src/MovingEntitiesOperator.cpp +++ b/libraries/entities/src/MovingEntitiesOperator.cpp @@ -55,13 +55,11 @@ void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const qCDebug(entities) << " oldContainingElement->bestFitBounds(newCubeClamped):" << oldContainingElement->bestFitBounds(newCubeClamped); } else { - qCDebug(entities) << " WARNING NO OLD CONTAINING ELEMENT!!!"; + qCDebug(entities) << " WARNING NO OLD CONTAINING ELEMENT for entity" << entity->getEntityItemID(); } } - + if (!oldContainingElement) { - qCDebug(entities) << "UNEXPECTED!!!! attempting to move entity "<< entity->getEntityItemID() - << "that has no containing element. "; return; // bail without adding. } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 767128ca16..269283ea6d 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -708,7 +708,7 @@ SelectionDisplay = (function() { shape: "Cone", solid: true, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true }; var handlePropertiesTranslateArrowCylinders = { @@ -716,7 +716,7 @@ SelectionDisplay = (function() { shape: "Cylinder", solid: true, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true }; var handleTranslateXCone = Overlays.addOverlay("shape", handlePropertiesTranslateArrowCones); @@ -741,7 +741,7 @@ SelectionDisplay = (function() { majorTickMarksAngle: ROTATE_DEFAULT_TICK_MARKS_ANGLE, majorTickMarksLength: 0.1, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true }; var handleRotatePitchRing = Overlays.addOverlay("circle3d", handlePropertiesRotateRings); @@ -766,7 +766,7 @@ SelectionDisplay = (function() { solid: true, innerRadius: 0.9, visible: false, - ignoreRayIntersection: true, + ignorePickIntersection: true, drawInFront: true }); @@ -779,7 +779,7 @@ SelectionDisplay = (function() { visible: false, isFacingAvatar: true, drawInFront: true, - ignoreRayIntersection: true, + ignorePickIntersection: true, dimensions: { x: 0, y: 0 }, lineHeight: 0.0, topMargin: 0, @@ -791,7 +791,7 @@ SelectionDisplay = (function() { var handlePropertiesStretchCubes = { solid: true, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true }; var handleStretchXCube = Overlays.addOverlay("cube", handlePropertiesStretchCubes); @@ -802,18 +802,17 @@ SelectionDisplay = (function() { Overlays.editOverlay(handleStretchZCube, { color: COLOR_BLUE }); var handlePropertiesStretchPanel = { - shape: "Quad", alpha: 0.5, solid: true, visible: false, - ignoreRayIntersection: true, + ignorePickIntersection: true, drawInFront: true }; - var handleStretchXPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel); + var handleStretchXPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); Overlays.editOverlay(handleStretchXPanel, { color: COLOR_RED }); - var handleStretchYPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel); + var handleStretchYPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); Overlays.editOverlay(handleStretchYPanel, { color: COLOR_GREEN }); - var handleStretchZPanel = Overlays.addOverlay("shape", handlePropertiesStretchPanel); + var handleStretchZPanel = Overlays.addOverlay("cube", handlePropertiesStretchPanel); Overlays.editOverlay(handleStretchZPanel, { color: COLOR_BLUE }); var handleScaleCube = Overlays.addOverlay("cube", { @@ -821,7 +820,7 @@ SelectionDisplay = (function() { color: COLOR_SCALE_CUBE, solid: true, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true, borderSize: 1.4 }); @@ -841,7 +840,7 @@ SelectionDisplay = (function() { color: COLOR_GREEN, solid: true, visible: false, - ignoreRayIntersection: false, + ignorePickIntersection: true, drawInFront: true, borderSize: 1.4 }); @@ -854,6 +853,7 @@ SelectionDisplay = (function() { alpha: 0, solid: false, visible: false, + ignorePickIntersection: true, dashed: false }); @@ -865,6 +865,7 @@ SelectionDisplay = (function() { alpha: 0, solid: false, visible: false, + ignorePickIntersection: true, dashed: false }); @@ -877,7 +878,7 @@ SelectionDisplay = (function() { green: 0, blue: 0 }, - ignoreRayIntersection: true // always ignore this + ignorePickIntersection: true // always ignore this }); var yRailOverlay = Overlays.addOverlay("line3d", { visible: false, @@ -888,7 +889,7 @@ SelectionDisplay = (function() { green: 255, blue: 0 }, - ignoreRayIntersection: true // always ignore this + ignorePickIntersection: true // always ignore this }); var zRailOverlay = Overlays.addOverlay("line3d", { visible: false, @@ -899,7 +900,7 @@ SelectionDisplay = (function() { green: 0, blue: 255 }, - ignoreRayIntersection: true // always ignore this + ignorePickIntersection: true // always ignore this }); var allOverlays = [ @@ -972,7 +973,7 @@ SelectionDisplay = (function() { color: COLOR_DEBUG_PICK_PLANE, solid: true, visible: false, - ignoreRayIntersection: true, + ignorePickIntersection: true, drawInFront: false }); var debugPickPlaneHits = []; @@ -1802,6 +1803,7 @@ SelectionDisplay = (function() { isActiveTool(handleRotateYawRing) || isActiveTool(handleRotateRollRing); selectionBoxGeometry.visible = !inModeRotate && !isCameraInsideBox; + selectionBoxGeometry.ignorePickIntersection = !selectionBoxGeometry.visible; Overlays.editOverlay(selectionBox, selectionBoxGeometry); // UPDATE ICON TRANSLATE HANDLE @@ -1811,9 +1813,13 @@ SelectionDisplay = (function() { rotation: rotation }; iconSelectionBoxGeometry.visible = !inModeRotate && isCameraInsideBox; + iconSelectionBoxGeometry.ignorePickIntersection = !iconSelectionBoxGeometry.visible; Overlays.editOverlay(iconSelectionBox, iconSelectionBoxGeometry); } else { - Overlays.editOverlay(iconSelectionBox, { visible: false }); + Overlays.editOverlay(iconSelectionBox, { + visible: false, + ignorePickIntersection: true + }); } // UPDATE DUPLICATOR (CURRENTLY HIDDEN FOR NOW) @@ -1882,7 +1888,7 @@ SelectionDisplay = (function() { // FUNCTION: SET OVERLAYS VISIBLE that.setOverlaysVisible = function(isVisible) { for (var i = 0, length = allOverlays.length; i < length; i++) { - Overlays.editOverlay(allOverlays[i], { visible: isVisible }); + Overlays.editOverlay(allOverlays[i], { visible: isVisible, ignorePickIntersection: !isVisible }); } }; @@ -1894,18 +1900,18 @@ SelectionDisplay = (function() { }; that.setHandleTranslateXVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateXCone, { visible: isVisible }); - Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible }); + Overlays.editOverlay(handleTranslateXCone, { visible: isVisible, ignorePickIntersection: !isVisible }); + Overlays.editOverlay(handleTranslateXCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleTranslateYVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateYCone, { visible: isVisible }); - Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible }); + Overlays.editOverlay(handleTranslateYCone, { visible: isVisible, ignorePickIntersection: !isVisible }); + Overlays.editOverlay(handleTranslateYCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleTranslateZVisible = function(isVisible) { - Overlays.editOverlay(handleTranslateZCone, { visible: isVisible }); - Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible }); + Overlays.editOverlay(handleTranslateZCone, { visible: isVisible, ignorePickIntersection: !isVisible }); + Overlays.editOverlay(handleTranslateZCylinder, { visible: isVisible, ignorePickIntersection: !isVisible }); }; // FUNCTION: SET HANDLE ROTATE VISIBLE @@ -1916,15 +1922,15 @@ SelectionDisplay = (function() { }; that.setHandleRotatePitchVisible = function(isVisible) { - Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible }); + Overlays.editOverlay(handleRotatePitchRing, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleRotateYawVisible = function(isVisible) { - Overlays.editOverlay(handleRotateYawRing, { visible: isVisible }); + Overlays.editOverlay(handleRotateYawRing, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleRotateRollVisible = function(isVisible) { - Overlays.editOverlay(handleRotateRollRing, { visible: isVisible }); + Overlays.editOverlay(handleRotateRollRing, { visible: isVisible, ignorePickIntersection: !isVisible }); }; // FUNCTION: SET HANDLE STRETCH VISIBLE @@ -1935,15 +1941,15 @@ SelectionDisplay = (function() { }; that.setHandleStretchXVisible = function(isVisible) { - Overlays.editOverlay(handleStretchXCube, { visible: isVisible }); + Overlays.editOverlay(handleStretchXCube, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleStretchYVisible = function(isVisible) { - Overlays.editOverlay(handleStretchYCube, { visible: isVisible }); + Overlays.editOverlay(handleStretchYCube, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleStretchZVisible = function(isVisible) { - Overlays.editOverlay(handleStretchZCube, { visible: isVisible }); + Overlays.editOverlay(handleStretchZCube, { visible: isVisible, ignorePickIntersection: !isVisible }); }; // FUNCTION: SET HANDLE SCALE VISIBLE @@ -1953,16 +1959,16 @@ SelectionDisplay = (function() { }; that.setHandleScaleVisible = function(isVisible) { - Overlays.editOverlay(handleScaleCube, { visible: isVisible }); + Overlays.editOverlay(handleScaleCube, { visible: isVisible, ignorePickIntersection: !isVisible }); }; that.setHandleBoundingBoxVisible = function(isVisible) { - Overlays.editOverlay(handleBoundingBox, { visible: isVisible }); + Overlays.editOverlay(handleBoundingBox, { visible: isVisible, ignorePickIntersection: true }); }; // FUNCTION: SET HANDLE DUPLICATOR VISIBLE that.setHandleDuplicatorVisible = function(isVisible) { - Overlays.editOverlay(handleDuplicator, { visible: isVisible }); + Overlays.editOverlay(handleDuplicator, { visible: isVisible, ignorePickIntersection: !isVisible }); }; // FUNCTION: DEBUG PICK PLANE @@ -1975,7 +1981,7 @@ SelectionDisplay = (function() { position: pickPlanePosition, rotation: rotation, dimensions: dimensions, - visible: true + visible: true }); }; @@ -1986,7 +1992,7 @@ SelectionDisplay = (function() { shape: "Sphere", solid: true, visible: true, - ignoreRayIntersection: true, + ignorePickIntersection: true, drawInFront: false, color: COLOR_DEBUG_PICK_PLANE_HIT, position: pickHitPosition, @@ -2082,10 +2088,12 @@ SelectionDisplay = (function() { pushCommandForSelections(duplicatedEntityIDs); if (isConstrained) { Overlays.editOverlay(xRailOverlay, { - visible: false + visible: false, + ignorePickIntersection: true }); Overlays.editOverlay(zRailOverlay, { - visible: false + visible: false, + ignorePickIntersection: true }); } }, @@ -2174,22 +2182,26 @@ SelectionDisplay = (function() { Overlays.editOverlay(xRailOverlay, { start: xStart, end: xEnd, - visible: true + visible: true, + ignorePickIntersection: true }); Overlays.editOverlay(zRailOverlay, { start: zStart, end: zEnd, - visible: true + visible: true, + ignorePickIntersection: true }); isConstrained = true; } } else { if (isConstrained) { Overlays.editOverlay(xRailOverlay, { - visible: false + visible: false, + ignorePickIntersection: true }); Overlays.editOverlay(zRailOverlay, { - visible: false + visible: false, + ignorePickIntersection: true }); isConstrained = false; } @@ -2460,7 +2472,7 @@ SelectionDisplay = (function() { } if (stretchPanel !== null) { - Overlays.editOverlay(stretchPanel, { visible: true }); + Overlays.editOverlay(stretchPanel, { visible: true, ignorePickIntersection: false }); } var stretchCubePosition = Overlays.getProperty(handleStretchCube, "position"); var stretchPanelPosition = Overlays.getProperty(stretchPanel, "position"); @@ -2481,7 +2493,7 @@ SelectionDisplay = (function() { } if (stretchPanel !== null) { - Overlays.editOverlay(stretchPanel, { visible: false }); + Overlays.editOverlay(stretchPanel, { visible: false, ignorePickIntersection: true }); } activeStretchCubePanelOffset = null; @@ -2775,7 +2787,8 @@ SelectionDisplay = (function() { rotation: worldRotation, startAt: 0, endAt: 0, - visible: true + visible: true, + ignorePickIntersection: false }); // editOverlays may not have committed rotation changes. @@ -2805,13 +2818,13 @@ SelectionDisplay = (function() { if (wantDebug) { print("================== " + getMode() + "(addHandleRotateTool onEnd) -> ======================="); } - Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false, ignorePickIntersection: true }); Overlays.editOverlay(selectedHandle, { hasTickMarks: false, solid: true, innerRadius: ROTATE_RING_IDLE_INNER_RADIUS }); - Overlays.editOverlay(handleRotateCurrentRing, { visible: false }); + Overlays.editOverlay(handleRotateCurrentRing, { visible: false, ignorePickIntersection: true }); pushCommandForSelections(); if (wantDebug) { print("================== " + getMode() + "(addHandleRotateTool onEnd) <- ======================="); From 2fd94c6bbcf61d24b047bad5fc0bd35357f35850 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Tue, 26 Feb 2019 15:37:31 -0800 Subject: [PATCH 14/16] fixing login dialog --- interface/src/Application.cpp | 16 ++++++++++++++-- interface/src/Application.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 83b287b7ae..ebc1176ee1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4979,6 +4979,15 @@ void Application::idle() { } } + { + if (_keyboardFocusWaitingOnRenderable && getEntities()->renderableForEntityId(_keyboardFocusedEntity.get())) { + _keyboardFocusWaitingOnRenderable = false; + QUuid entityId = _keyboardFocusedEntity.get(); + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + setKeyboardFocusEntity(entityId); + } + } + { PerformanceTimer perfTimer("pluginIdle"); PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); @@ -5807,7 +5816,7 @@ void Application::setKeyboardFocusEntity(const QUuid& id) { if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { if (id == _loginDialogID) { emit loginDialogFocusEnabled(); - } else { + } else if (!_keyboardFocusWaitingOnRenderable) { // that's the only entity we want in focus; return; } @@ -5824,7 +5833,10 @@ void Application::setKeyboardFocusEntity(const QUuid& id) { if (properties.getVisible()) { auto entities = getEntities(); auto entityId = _keyboardFocusedEntity.get(); - if (entities->wantsKeyboardFocus(entityId)) { + auto entityItemRenderable = entities->renderableForEntityId(entityId); + if (!entityItemRenderable) { + _keyboardFocusWaitingOnRenderable = true; + } else if (entityItemRenderable->wantsKeyboardFocus()) { entities->setProxyWindow(entityId, _window->windowHandle()); if (_keyboardMouseDevice->isActive()) { _keyboardMouseDevice->pluginFocusOutEvent(); diff --git a/interface/src/Application.h b/interface/src/Application.h index afd9f5f12f..c16f260192 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -732,6 +732,7 @@ private: bool _failedToConnectToEntityServer { false }; bool _reticleClickPressed { false }; + bool _keyboardFocusWaitingOnRenderable { false }; int _avatarAttachmentRequest = 0; From bf9e5b9550ce622e39ddbaff655efacb952f73a8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 27 Feb 2019 10:14:28 -0800 Subject: [PATCH 15/16] comment out another log --- interface/src/octree/SafeLanding.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/octree/SafeLanding.cpp b/interface/src/octree/SafeLanding.cpp index 9efad22d09..e56ca984e0 100644 --- a/interface/src/octree/SafeLanding.cpp +++ b/interface/src/octree/SafeLanding.cpp @@ -72,7 +72,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { Locker lock(_lock); EntityItemPointer entity = _entityTree->findEntityByID(entityID); - if (entity && entity->getCreated() < _startTime) { + if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) { _trackedEntities.emplace(entityID, entity); int trackedEntityCount = (int)_trackedEntities.size(); @@ -81,7 +81,7 @@ void SafeLanding::addTrackedEntity(const EntityItemID& entityID) { _maxTrackedEntityCount = trackedEntityCount; _trackedEntityStabilityCount = 0; } - qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); + //qCDebug(interfaceapp) << "Safe Landing: Tracking entity " << entity->getItemName(); } } } From b5f590063364a41f24662929140c7e2d02e04ed0 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 12 Feb 2019 11:49:30 -0800 Subject: [PATCH 16/16] Replace animation scale with scale from avatar default pose This allows avatars to have scale on their joints without being clobbered by animations. Renamed variables for easier maintenance. Also small optimization when no ikNode is present. --- libraries/animation/src/AnimClip.cpp | 83 ++++++++++++++-------------- libraries/animation/src/Rig.cpp | 18 +++--- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 1adc04ee1b..a35e0237d0 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -99,65 +99,64 @@ void AnimClip::copyFromNetworkAnim() { assert(_networkAnim && _networkAnim->isLoaded() && _skeleton); _anim.clear(); - // build a mapping from animation joint indices to skeleton joint indices. + auto avatarSkeleton = getSkeleton(); + + // build a mapping from animation joint indices to avatar joint indices. // by matching joints with the same name. - const HFMModel& hfmModel = _networkAnim->getHFMModel(); - AnimSkeleton animSkeleton(hfmModel); - const auto animJointCount = animSkeleton.getNumJoints(); - const auto skeletonJointCount = _skeleton->getNumJoints(); - std::vector jointMap; - jointMap.reserve(animJointCount); - for (int i = 0; i < animJointCount; i++) { - int skeletonJoint = _skeleton->nameToJointIndex(animSkeleton.getJointName(i)); - jointMap.push_back(skeletonJoint); + const HFMModel& animModel = _networkAnim->getHFMModel(); + AnimSkeleton animSkeleton(animModel); + const int animJointCount = animSkeleton.getNumJoints(); + const int avatarJointCount = avatarSkeleton->getNumJoints(); + std::vector animToAvatarJointIndexMap; + animToAvatarJointIndexMap.reserve(animJointCount); + for (int animJointIndex = 0; animJointIndex < animJointCount; animJointIndex++) { + QString animJointName = animSkeleton.getJointName(animJointIndex); + int avatarJointIndex = avatarSkeleton->nameToJointIndex(animJointName); + animToAvatarJointIndexMap.push_back(avatarJointIndex); } - const int frameCount = hfmModel.animationFrames.size(); - _anim.resize(frameCount); + const int animFrameCount = animModel.animationFrames.size(); + _anim.resize(animFrameCount); - for (int frame = 0; frame < frameCount; frame++) { + for (int frame = 0; frame < animFrameCount; frame++) { - const HFMAnimationFrame& hfmAnimFrame = hfmModel.animationFrames[frame]; + const HFMAnimationFrame& animFrame = animModel.animationFrames[frame]; // init all joints in animation to default pose - // this will give us a resonable result for bones in the model skeleton but not in the animation. - _anim[frame].reserve(skeletonJointCount); - for (int skeletonJoint = 0; skeletonJoint < skeletonJointCount; skeletonJoint++) { - _anim[frame].push_back(_skeleton->getRelativeDefaultPose(skeletonJoint)); + // this will give us a resonable result for bones in the avatar skeleton but not in the animation. + _anim[frame].reserve(avatarJointCount); + for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) { + _anim[frame].push_back(avatarSkeleton->getRelativeDefaultPose(avatarJointIndex)); } - for (int animJoint = 0; animJoint < animJointCount; animJoint++) { - int skeletonJoint = jointMap[animJoint]; + for (int animJointIndex = 0; animJointIndex < animJointCount; animJointIndex++) { + int avatarJointIndex = animToAvatarJointIndexMap[animJointIndex]; - const glm::vec3& hfmAnimTrans = hfmAnimFrame.translations[animJoint]; - const glm::quat& hfmAnimRot = hfmAnimFrame.rotations[animJoint]; + // skip joints that are in the animation but not in the avatar. + if (avatarJointIndex >= 0 && avatarJointIndex < avatarJointCount) { - // skip joints that are in the animation but not in the skeleton. - if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) { + const glm::vec3& animTrans = animFrame.translations[animJointIndex]; + const glm::quat& animRot = animFrame.rotations[animJointIndex]; - AnimPose preRot, postRot; - preRot = animSkeleton.getPreRotationPose(animJoint); - postRot = animSkeleton.getPostRotationPose(animJoint); + const AnimPose& animPreRotPose = animSkeleton.getPreRotationPose(animJointIndex); + AnimPose animPostRotPose = animSkeleton.getPostRotationPose(animJointIndex); + AnimPose animRotPose(glm::vec3(1.0f), animRot, glm::vec3()); - // cancel out scale - preRot.scale() = glm::vec3(1.0f); - postRot.scale() = glm::vec3(1.0f); + // adjust anim scale to equal the scale from the avatar joint. + // we do not support animated scale. + const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex); + animPostRotPose.scale() = avatarDefaultPose.scale(); - AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3()); - - // adjust translation offsets, so large translation animatons on the reference skeleton - // will be adjusted when played on a skeleton with short limbs. - const glm::vec3& hfmZeroTrans = hfmModel.animationFrames[0].translations[animJoint]; - const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint); + // retarget translation from animation to avatar + const glm::vec3& animZeroTrans = animModel.animationFrames[0].translations[animJointIndex]; float boneLengthScale = 1.0f; const float EPSILON = 0.0001f; - if (fabsf(glm::length(hfmZeroTrans)) > EPSILON) { - boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans); + if (fabsf(glm::length(animZeroTrans)) > EPSILON) { + boneLengthScale = glm::length(avatarDefaultPose.trans()) / glm::length(animZeroTrans); } + AnimPose animTransPose = AnimPose(glm::vec3(1.0f), glm::quat(), avatarDefaultPose.trans() + boneLengthScale * (animTrans - animZeroTrans)); - AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans)); - - _anim[frame][skeletonJoint] = trans * preRot * rot * postRot; + _anim[frame][avatarJointIndex] = animTransPose * animPreRotPose * animRotPose * animPostRotPose; } } } @@ -165,7 +164,7 @@ void AnimClip::copyFromNetworkAnim() { // mirrorAnim will be re-built on demand, if needed. _mirrorAnim.clear(); - _poses.resize(skeletonJointCount); + _poses.resize(avatarJointCount); } void AnimClip::buildMirrorAnim() { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 25f154e9fd..0413210776 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1878,13 +1878,15 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo }; std::shared_ptr ikNode = getAnimInverseKinematicsNode(); - for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) { - int index = indexOfJoint(secondaryControllerJointNames[i]); - if ((index >= 0) && (ikNode)) { - if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) { - ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]); - } else { - ikNode->clearSecondaryTarget(index); + if (ikNode) { + for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) { + int index = indexOfJoint(secondaryControllerJointNames[i]); + if (index >= 0) { + if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) { + ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]); + } else { + ikNode->clearSecondaryTarget(index); + } } } } @@ -2177,4 +2179,4 @@ void Rig::initFlow(bool isActive) { _internalFlow.cleanUp(); _networkFlow.cleanUp(); } -} \ No newline at end of file +}