From 3578df7a0e296107c786781c957ed41affc02b2f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 19 Dec 2018 13:28:33 -0800 Subject: [PATCH 01/17] material targeting --- .../entities/src/EntityItemProperties.cpp | 12 ++-- libraries/render-utils/src/Model.cpp | 61 +++++++++++++------ libraries/render-utils/src/Model.h | 2 +- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index b6307a83da..72c90092f0 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -779,10 +779,14 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} priority=0 - The priority for applying the material to its parent. Only the highest priority material is * applied, with materials of the same priority randomly assigned. Materials that come with the model have a priority of * 0. - * @property {string|number} parentMaterialName="0" - Selects the submesh or submeshes within the parent to apply the material - * to. If in the format "mat::string", all submeshes with material name "string" are replaced. - * Otherwise the property value is parsed as an unsigned integer, specifying the mesh index to modify. Invalid values are - * parsed to 0. + * @property {string} parentMaterialName="0" - Selects the mesh part or parts within the parent to which to apply the material. + * If in the format "mat::string", all mesh parts with material name "string" are replaced. + * Otherwise the property value is parsed as an unsigned integer, specifying the mesh parth index to modify. If "all", + * all mesh parts will be replaced. If an array (starts with "[" and ends with "]"), the string will be + * split at each "," and each element will be parsed as either a number or a string if it starts with + * "mat::". In other words, "[0,1,mat::string,mat::string2]" will replace mesh parts 1 and 2, and any + * mesh parts with material "string" or "string2". Do not put spaces around the commas. Invalid values + * are parsed to 0. * @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either "uv" or * "projected". In "uv" mode, the material will be evaluated within the UV space of the mesh it is applied to. In * "projected" mode, the 3D transform of the Material Entity will be used to evaluate the texture coordinates for the material. diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9cefbf65a8..f3c6ceb178 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1533,29 +1533,56 @@ bool Model::isRenderable() const { return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } -std::vector Model::getMeshIDsFromMaterialID(QString parentMaterialName) { - // try to find all meshes with materials that match parentMaterialName as a string - // if none, return parentMaterialName as a uint - std::vector toReturn; - const QString MATERIAL_NAME_PREFIX = "mat::"; - if (parentMaterialName.startsWith(MATERIAL_NAME_PREFIX)) { - parentMaterialName.replace(0, MATERIAL_NAME_PREFIX.size(), QString("")); - for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) { - if (_modelMeshMaterialNames[i] == parentMaterialName.toStdString()) { - toReturn.push_back(i); - } - } - } +std::set Model::getMeshIDsFromMaterialID(QString parentMaterialName) { + std::set toReturn; - if (toReturn.empty()) { - toReturn.push_back(parentMaterialName.toUInt()); + const QString all("all"); + if (parentMaterialName == all) { + for (unsigned int i = 0; i < (unsigned int)_modelMeshRenderItemIDs.size(); i++) { + toReturn.insert(i); + } + } else if (!parentMaterialName.isEmpty()) { + auto parseFunc = [this, &toReturn] (QString& target) { + if (target.isEmpty()) { + return; + } + // if target starts with "mat::", try to find all meshes with materials that match target as a string + // otherwise, return target as a uint + const QString MATERIAL_NAME_PREFIX("mat::"); + if (target.startsWith(MATERIAL_NAME_PREFIX)) { + std::string targetStdString = target.replace(0, MATERIAL_NAME_PREFIX.size(), "").toStdString(); + for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) { + if (_modelMeshMaterialNames[i] == targetStdString) { + toReturn.insert(i); + } + } + return; + } + toReturn.insert(target.toUInt()); + }; + + if (parentMaterialName.length() > 2 && parentMaterialName.startsWith("[") && parentMaterialName.endsWith("]")) { + QStringList list = parentMaterialName.split(",", QString::SkipEmptyParts); + for (int i = 0; i < list.length(); i++) { + auto& target = list[i]; + if (i == 0) { + target = target.replace(0, 1, ""); + } + if (i == list.length() - 1) { + target = target.replace(target.length() - 1, 1, ""); + } + parseFunc(target); + } + } else { + parseFunc(parentMaterialName); + } } return toReturn; } void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { - std::vector shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str())); + std::set shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str())); render::Transaction transaction; for (auto shapeID : shapeIDs) { if (shapeID < _modelMeshRenderItemIDs.size()) { @@ -1578,7 +1605,7 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par } void Model::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { - std::vector shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str())); + std::set shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str())); render::Transaction transaction; for (auto shapeID : shapeIDs) { if (shapeID < _modelMeshRenderItemIDs.size()) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 93a0626d28..da06eb7ef0 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -513,7 +513,7 @@ private: void calculateTextureInfo(); - std::vector getMeshIDsFromMaterialID(QString parentMaterialName); + std::set getMeshIDsFromMaterialID(QString parentMaterialName); }; Q_DECLARE_METATYPE(ModelPointer) From 184c11ca44db2d1de369f62d8daddcde31f2b818 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 16 Jan 2019 08:54:29 +1300 Subject: [PATCH 02/17] Fix tablet sometimes not working after domain change --- interface/src/Application.cpp | 4 ++++ interface/src/ui/overlays/Web3DOverlay.cpp | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0e70375e47..128a1a0392 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1200,6 +1200,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle())); connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle())); connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() { + auto tabletScriptingInterface = DependencyManager::get(); + if (tabletScriptingInterface) { + tabletScriptingInterface->setQmlTabletRoot(SYSTEM_TABLET, nullptr); + } getOverlays().deleteOverlay(getTabletScreenID()); getOverlays().deleteOverlay(getTabletHomeButtonID()); getOverlays().deleteOverlay(getTabletFrameID()); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index ec6b62e237..4fe3708ba9 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -134,13 +134,6 @@ void Web3DOverlay::destroyWebSurface() { QQuickItem* rootItem = _webSurface->getRootItem(); - if (rootItem && rootItem->objectName() == "tabletRoot") { - auto tabletScriptingInterface = DependencyManager::get(); - if (tabletScriptingInterface) { - tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr); - } - } - // Fix for crash in QtWebEngineCore when rapidly switching domains // Call stop on the QWebEngineView before destroying OffscreenQMLSurface. if (rootItem) { From 104084d811b373285c8357f659cfb58e331e5380 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 15 Jan 2019 18:56:09 -0800 Subject: [PATCH 03/17] Avatar Mixer Protocol: Normalize translation before compression --- libraries/avatars/src/AvatarData.cpp | 36 +++++++++++++++++++++------- libraries/avatars/src/AvatarData.h | 3 ++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 21e0a6aba2..abd89525fa 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -677,7 +677,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent validityPosition = destinationBuffer; #ifdef WANT_DEBUG - int translationSentCount = 0; unsigned char* beforeTranslations = destinationBuffer; #endif @@ -686,7 +685,13 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent float minTranslation = (distanceAdjust && cullSmallChanges) ? getDistanceBasedMinTranslationDistance(viewerPosition) : AVATAR_MIN_TRANSLATION; - float maxTranslationDimension = 0.0; + float maxTranslationDimension = 0.0f; + const int MAX_NUM_JOINTS = 256; + + assert(numJoints < MAX_NUM_JOINTS); + glm::vec3 translationsSentArray[MAX_NUM_JOINTS]; // 3060 bytes allocated on the stack for performance. + int translationsSent = 0; + i = sendStatus.translationsSent; for (; i < numJoints; ++i) { const JointData& data = joints[i]; @@ -697,15 +702,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (sendAll || last.translationIsDefaultPose || (!cullSmallChanges && last.translation != data.translation) || (cullSmallChanges && glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation)) { validityPosition[i / BITS_IN_BYTE] |= 1 << (i % BITS_IN_BYTE); -#ifdef WANT_DEBUG - translationSentCount++; -#endif maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension); maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension); maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension); - destinationBuffer += - packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); + translationsSentArray[translationsSent++] = data.translation; if (sentJoints) { sentJoints[i].translation = data.translation; @@ -721,6 +722,16 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent } } + + // AJT: TODO make sure size computation is properly up to date! + // Write maxTranslationDimension into packet + memcpy(destinationBuffer, &maxTranslationDimension, sizeof(float)); + destinationBuffer += sizeof(float); + + // Write normalized and compressed translations into packet + for (i = 0; i < translationsSent; ++i) { + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, translationsSentArray[i] / maxTranslationDimension, TRANSLATION_COMPRESSION_RADIX); + } sendStatus.translationsSent = i; // faux joints @@ -766,7 +777,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent #ifdef WANT_DEBUG if (sendAll) { qCDebug(avatars) << "AvatarData::toByteArray" << cullSmallChanges << sendAll - << "rotations:" << rotationSentCount << "translations:" << translationSentCount + << "rotations:" << rotationSentCount << "translations:" << translationsSentCount << "largest:" << maxTranslationDimension << "size:" << (beforeRotations - startPosition) << "+" @@ -1280,6 +1291,13 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } } // 1 + bytesOfValidity bytes + + // AJT: read maxTranslationDimension + float maxTranslationDimension; + PACKET_READ_CHECK(MaxTranslationDimension, sizeof(float)); + memcpy(&maxTranslationDimension, sourceBuffer, sizeof(float)); + sourceBuffer += sizeof(float); + // each joint translation component is stored in 6 bytes. const int COMPRESSED_TRANSLATION_SIZE = 6; PACKET_READ_CHECK(JointTranslation, numValidJointTranslations * COMPRESSED_TRANSLATION_SIZE); @@ -1288,6 +1306,8 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { JointData& data = _jointData[i]; if (validTranslations[i]) { sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); + // un-normalize translation + data.translation *= maxTranslationDimension; _hasNewJointData = true; data.translationIsDefaultPose = false; } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ec5ea4a5d0..8a3014d043 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -277,7 +277,8 @@ namespace AvatarDataPacket { uint8_t rotationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed rotation follows. SixByteQuat rotation[numValidRotations]; // encodeded and compressed by packOrientationQuatToSixBytes() uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows. - SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed() + float maxTranslationDimension; // used to normalize fixed point translation values. + SixByteTrans translation[numValidTranslations]; // normalized and compressed by packFloatVec3ToSignedTwoByteFixed() SixByteQuat leftHandControllerRotation; SixByteTrans leftHandControllerTranslation; From 59fafa1f5cb7079f62e63e1d82505ba30da7b25e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 17 Jan 2019 11:47:12 -0800 Subject: [PATCH 04/17] only do entitlements check once --- plugins/oculus/src/OculusHelpers.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index 29691e73a5..548afb97ab 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -82,15 +82,18 @@ private: } #ifdef OCULUS_APP_ID - if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) { - if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) { - qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError(); - return; - } else { - qCDebug(oculusLog) << "Performing Oculus Platform entitlement check"; - ovr_Entitlement_GetIsViewerEntitled(); + static std::once_flag once; + std::call_once(once, []() { + if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) { + if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) { + qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError(); + return; + } else { + qCDebug(oculusLog) << "Performing Oculus Platform entitlement check"; + ovr_Entitlement_GetIsViewerEntitled(); + } } - } + }); #endif ovrGraphicsLuid luid; From 2bf7ac27451d0fd953d829cd13871d2041ea62ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 15 Jan 2019 11:36:08 -0800 Subject: [PATCH 05/17] fix bug that was introducing a local velocity to an entity when it was parented to a moving avatar --- libraries/entities/src/EntityItemProperties.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1fdff19e38..affd061af1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3833,22 +3833,22 @@ void EntityItemProperties::copySimulationRestrictedProperties(const EntityItemPo setParentJointIndex(entity->getParentJointIndex()); } if (!_localPositionChanged && !_positionChanged) { - setPosition(entity->getWorldPosition()); + setLocalPosition(entity->getLocalPosition()); } if (!_localRotationChanged && !_rotationChanged) { - setRotation(entity->getWorldOrientation()); + setLocalRotation(entity->getLocalOrientation()); } if (!_localVelocityChanged && !_velocityChanged) { - setVelocity(entity->getWorldVelocity()); + setLocalVelocity(entity->getLocalVelocity()); } if (!_localAngularVelocityChanged && !_angularVelocityChanged) { - setAngularVelocity(entity->getWorldAngularVelocity()); + setLocalAngularVelocity(entity->getLocalAngularVelocity()); } if (!_accelerationChanged) { setAcceleration(entity->getAcceleration()); } if (!_localDimensionsChanged && !_dimensionsChanged) { - setDimensions(entity->getScaledDimensions()); + setLocalDimensions(entity->getUnscaledDimensions()); } } From c8e9bff03a18b24ce7168f023509a45aadac94a3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Jan 2019 15:31:04 -0800 Subject: [PATCH 06/17] fix releaseGrab call on grabbed entity when a nearGrab ends --- .../controllerModules/farGrabEntity.js | 4 ++-- .../controllerModules/nearGrabEntity.js | 15 ++++++++------- .../system/libraries/controllerDispatcherUtils.js | 9 ++++++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index dab1aa97af..197a809e91 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -11,7 +11,7 @@ Entities, enableDispatcherModule, disableDispatcherModule, entityIsGrabbable, makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager, - getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGroupParent, + getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGrabbableGroupParent, worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES */ @@ -308,7 +308,7 @@ Script.include("/~/system/libraries/controllers.js"); var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); if (entityIsGrabbable(gtProps)) { // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = findGroupParent(controllerData, gtProps); + var groupRootProps = findGrabbableGroupParent(controllerData, gtProps); if (entityIsGrabbable(groupRootProps)) { return groupRootProps; } diff --git a/scripts/system/controllers/controllerModules/nearGrabEntity.js b/scripts/system/controllers/controllerModules/nearGrabEntity.js index 60a5781ca4..0f8071677c 100644 --- a/scripts/system/controllers/controllerModules/nearGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearGrabEntity.js @@ -8,9 +8,10 @@ /* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, - makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity, - entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, distanceBetweenPointAndEntityBoundingBox, - getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD, NEAR_GRAB_DISTANCE + makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGrabbableGroupParent, Vec3, + cloneEntity, entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, + distanceBetweenPointAndEntityBoundingBox, getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD, + NEAR_GRAB_DISTANCE */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -80,9 +81,6 @@ Script.include("/~/system/libraries/controllers.js"); this.endNearGrabEntity = function () { this.endGrab(); - this.grabbing = false; - this.targetEntityID = null; - var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args); Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ @@ -90,6 +88,9 @@ Script.include("/~/system/libraries/controllers.js"); grabbedEntity: this.targetEntityID, joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" })); + + this.grabbing = false; + this.targetEntityID = null; }; this.getTargetProps = function (controllerData) { @@ -110,7 +111,7 @@ Script.include("/~/system/libraries/controllers.js"); if (entityIsGrabbable(props) || entityIsCloneable(props)) { if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree - var groupRootProps = findGroupParent(controllerData, props); + var groupRootProps = findGrabbableGroupParent(controllerData, props); if (entityIsGrabbable(groupRootProps)) { return groupRootProps; } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 221af07474..43dac435ac 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -46,7 +46,7 @@ makeLaserLockInfo:true, entityHasActions:true, ensureDynamic:true, - findGroupParent:true, + findGrabbableGroupParent:true, BUMPER_ON_VALUE:true, getEntityParents:true, findHandChildEntities:true, @@ -439,7 +439,7 @@ ensureDynamic = function (entityID) { } }; -findGroupParent = function (controllerData, targetProps) { +findGrabbableGroupParent = function (controllerData, targetProps) { while (targetProps.grab.grabDelegateToParent && targetProps.parentID && targetProps.parentID !== Uuid.NULL && @@ -448,6 +448,9 @@ findGroupParent = function (controllerData, targetProps) { if (!parentProps) { break; } + if (!entityIsGrabbable(parentProps)) { + break; + } parentProps.id = targetProps.parentID; targetProps = parentProps; controllerData.nearbyEntityPropertiesByID[targetProps.id] = targetProps; @@ -614,7 +617,7 @@ if (typeof module !== 'undefined') { unhighlightTargetEntity: unhighlightTargetEntity, clearHighlightedEntities: clearHighlightedEntities, makeRunningValues: makeRunningValues, - findGroupParent: findGroupParent, + findGrabbableGroupParent: findGrabbableGroupParent, LEFT_HAND: LEFT_HAND, RIGHT_HAND: RIGHT_HAND, BUMPER_ON_VALUE: BUMPER_ON_VALUE, From 4fbc257be0eb3a1578bc6273c05b148dc89f1a4b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 16 Jan 2019 16:26:40 -0800 Subject: [PATCH 07/17] don't cauterize head-children when they are grabbed --- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 -- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 2 ++ libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cc7742c517..54064e8523 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -773,7 +773,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) { auto headBoneSet = _skeletonModel->getCauterizeBoneSet(); forEachChild([&](SpatiallyNestablePointer object) { bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end(); - if (isChildOfHead) { + if (isChildOfHead && !object->hasGrabs()) { // Cauterize or display children of head per head drawing state. updateChildCauterization(object, !_prevShouldDrawHead); object->forEachDescendant([&](SpatiallyNestablePointer descendant) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 58880acb08..23eb746226 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1869,8 +1869,6 @@ private: bool _enableDebugDrawIKChains { false }; bool _enableDebugDrawDetailedCollision { false }; - mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state? - AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; glm::quat _customListenOrientation; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a6185d7e79..e35a47b821 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -385,6 +385,7 @@ void Avatar::updateGrabs() { entityTree->updateEntityQueryAACube(target, packetSender, force, iShouldTellServer); }); } + _cauterizationNeedsUpdate = true; } _avatarGrabs.remove(grabID); _changedAvatarGrabs.remove(grabID); @@ -402,6 +403,7 @@ void Avatar::updateGrabs() { target->addGrab(grab); // only clear this entry from the _changedAvatarGrabs if we found the entity. changeItr.remove(); + _cauterizationNeedsUpdate = true; } } }); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 4ff3e9cc13..e9359ec8c5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -536,6 +536,8 @@ protected: glm::vec3 _worldUpDirection { Vectors::UP }; bool _moving { false }; ///< set when position is changing + mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state? + // protected methods... bool isLookingAtMe(AvatarSharedPointer avatar) const; void updateGrabs(); From e22024b0dd3086386a5fcf82ddb3490f7ad64c36 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 17 Jan 2019 13:31:11 -0800 Subject: [PATCH 08/17] revert attempted fix for non-zero velocity for hats --- libraries/entities/src/EntityItemProperties.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index affd061af1..1fdff19e38 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3833,22 +3833,22 @@ void EntityItemProperties::copySimulationRestrictedProperties(const EntityItemPo setParentJointIndex(entity->getParentJointIndex()); } if (!_localPositionChanged && !_positionChanged) { - setLocalPosition(entity->getLocalPosition()); + setPosition(entity->getWorldPosition()); } if (!_localRotationChanged && !_rotationChanged) { - setLocalRotation(entity->getLocalOrientation()); + setRotation(entity->getWorldOrientation()); } if (!_localVelocityChanged && !_velocityChanged) { - setLocalVelocity(entity->getLocalVelocity()); + setVelocity(entity->getWorldVelocity()); } if (!_localAngularVelocityChanged && !_angularVelocityChanged) { - setLocalAngularVelocity(entity->getLocalAngularVelocity()); + setAngularVelocity(entity->getWorldAngularVelocity()); } if (!_accelerationChanged) { setAcceleration(entity->getAcceleration()); } if (!_localDimensionsChanged && !_dimensionsChanged) { - setLocalDimensions(entity->getUnscaledDimensions()); + setDimensions(entity->getScaledDimensions()); } } From 74f9a415d364d039d5f5d57635aa412b24bf3959 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 17 Jan 2019 13:58:34 -0800 Subject: [PATCH 09/17] move _cauterizationNeedsUpdate back to MyAvatar --- interface/src/avatar/MyAvatar.cpp | 4 +++- interface/src/avatar/MyAvatar.h | 2 ++ .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 9 +++++---- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 4 +--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 54064e8523..48acf09abb 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -823,7 +823,9 @@ void MyAvatar::simulate(float deltaTime, bool inView) { // and all of its joints, now update our attachements. Avatar::simulateAttachments(deltaTime); relayJointDataToChildren(); - updateGrabs(); + if (updateGrabs()) { + _cauterizationNeedsUpdate = true; + } if (!_skeletonModel->hasSkeleton()) { // All the simulation that can be done has been done diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 23eb746226..58880acb08 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1869,6 +1869,8 @@ private: bool _enableDebugDrawIKChains { false }; bool _enableDebugDrawDetailedCollision { false }; + mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state? + AudioListenerMode _audioListenerMode; glm::vec3 _customListenPosition; glm::quat _customListenOrientation; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index e35a47b821..5933e9adee 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -324,8 +324,8 @@ void Avatar::removeAvatarEntitiesFromTree() { } } -void Avatar::updateGrabs() { - +bool Avatar::updateGrabs() { + bool grabAddedOrRemoved = false; // update the Grabs according to any changes in _avatarGrabData _avatarGrabsLock.withWriteLock([&] { if (_avatarGrabDataChanged) { @@ -385,7 +385,7 @@ void Avatar::updateGrabs() { entityTree->updateEntityQueryAACube(target, packetSender, force, iShouldTellServer); }); } - _cauterizationNeedsUpdate = true; + grabAddedOrRemoved = true; } _avatarGrabs.remove(grabID); _changedAvatarGrabs.remove(grabID); @@ -403,10 +403,11 @@ void Avatar::updateGrabs() { target->addGrab(grab); // only clear this entry from the _changedAvatarGrabs if we found the entity. changeItr.remove(); - _cauterizationNeedsUpdate = true; + grabAddedOrRemoved = true; } } }); + return grabAddedOrRemoved; } void Avatar::accumulateGrabPositions(std::map& grabAccumulators) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index e9359ec8c5..d5431ad2d2 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -536,11 +536,9 @@ protected: glm::vec3 _worldUpDirection { Vectors::UP }; bool _moving { false }; ///< set when position is changing - mutable bool _cauterizationNeedsUpdate; // do we need to scan children and update their "cauterized" state? - // protected methods... bool isLookingAtMe(AvatarSharedPointer avatar) const; - void updateGrabs(); + bool updateGrabs(); void relayJointDataToChildren(); void fade(render::Transaction& transaction, render::Transition::Type type); From 286f23d512b0770975050acaff1ccdb298bef5d1 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 17 Jan 2019 15:19:54 -0800 Subject: [PATCH 10/17] Updated protocol version and fixed bugs --- libraries/animation/src/Rig.cpp | 9 ++- libraries/avatars/src/AvatarData.cpp | 56 +++++++++---------- libraries/avatars/src/AvatarData.h | 1 - .../networking/src/udt/PacketHeaders.cpp | 4 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/shared/src/JointData.h | 2 +- tools/dissectors/3-hf-avatar.lua | 3 + 7 files changed, 39 insertions(+), 39 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 44fdd8797f..c7a342b0eb 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1985,11 +1985,10 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { data.rotation = !_sendNetworkNode ? _internalPoseSet._absolutePoses[i].rot() : _networkPoseSet._absolutePoses[i].rot(); data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot); - // translations are in relative frame but scaled so that they are in meters, - // instead of model units. + // translations are in relative frame. glm::vec3 defaultRelTrans = _animSkeleton->getRelativeDefaultPose(i).trans(); glm::vec3 currentRelTrans = _sendNetworkNode ? _networkPoseSet._relativePoses[i].trans() : _internalPoseSet._relativePoses[i].trans(); - data.translation = geometryToRigScale * currentRelTrans; + data.translation = currentRelTrans; data.translationIsDefaultPose = isEqual(currentRelTrans, defaultRelTrans); } else { data.translationIsDefaultPose = true; @@ -2042,8 +2041,8 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) { if (data.translationIsDefaultPose) { _internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans(); } else { - // JointData translations are in scaled relative-frame so we scale back to regular relative-frame - _internalPoseSet._relativePoses[i].trans() = rigToGeometryScale * data.translation; + // JointData translations are in relative-frame + _internalPoseSet._relativePoses[i].trans() = data.translation; } } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index abd89525fa..b649bd2994 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -73,6 +73,7 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints) totalSize += validityBitsSize; // Orientations mask totalSize += numJoints * sizeof(SixByteQuat); // Orientations totalSize += validityBitsSize; // Translations mask + totalSize += sizeof(float); // maxTranslationDimension totalSize += numJoints * sizeof(SixByteTrans); // Translations size_t NUM_FAUX_JOINT = 2; @@ -612,12 +613,23 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent const int jointBitVectorSize = calcBitVectorSize(numJoints); // Start joints if room for at least the faux joints. - IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, 1 + 2 * jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE) { + IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, 1 + 4 + 2 * jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE) { // Allow for faux joints + translation bit-vector: const ptrdiff_t minSizeForJoint = sizeof(AvatarDataPacket::SixByteQuat) + jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE; auto startSection = destinationBuffer; + // compute maxTranslationDimension before we send any joint data. + float maxTranslationDimension = 0.001f; + for (int i = 0; i < numJoints; ++i) { + const JointData& data = jointData[i]; + if (!data.translationIsDefaultPose) { + maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension); + maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension); + maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension); + } + } + // joint rotation data *destinationBuffer++ = (uint8_t)numJoints; @@ -677,21 +689,19 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent validityPosition = destinationBuffer; #ifdef WANT_DEBUG + int translationSentCount = 0; unsigned char* beforeTranslations = destinationBuffer; #endif memset(destinationBuffer, 0, jointBitVectorSize); destinationBuffer += jointBitVectorSize; // Move pointer past the validity bytes + // write maxTranslationDimension + memcpy(destinationBuffer, &maxTranslationDimension, sizeof(float)); + destinationBuffer += sizeof(float); + float minTranslation = (distanceAdjust && cullSmallChanges) ? getDistanceBasedMinTranslationDistance(viewerPosition) : AVATAR_MIN_TRANSLATION; - float maxTranslationDimension = 0.0f; - const int MAX_NUM_JOINTS = 256; - - assert(numJoints < MAX_NUM_JOINTS); - glm::vec3 translationsSentArray[MAX_NUM_JOINTS]; // 3060 bytes allocated on the stack for performance. - int translationsSent = 0; - i = sendStatus.translationsSent; for (; i < numJoints; ++i) { const JointData& data = joints[i]; @@ -702,11 +712,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (sendAll || last.translationIsDefaultPose || (!cullSmallChanges && last.translation != data.translation) || (cullSmallChanges && glm::distance(data.translation, lastSentJointData[i].translation) > minTranslation)) { validityPosition[i / BITS_IN_BYTE] |= 1 << (i % BITS_IN_BYTE); - maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension); - maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension); - maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension); - - translationsSentArray[translationsSent++] = data.translation; +#ifdef WANT_DEBUG + translationSentCount++; +#endif + destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation / maxTranslationDimension, + TRANSLATION_COMPRESSION_RADIX); if (sentJoints) { sentJoints[i].translation = data.translation; @@ -722,16 +732,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent } } - - // AJT: TODO make sure size computation is properly up to date! - // Write maxTranslationDimension into packet - memcpy(destinationBuffer, &maxTranslationDimension, sizeof(float)); - destinationBuffer += sizeof(float); - - // Write normalized and compressed translations into packet - for (i = 0; i < translationsSent; ++i) { - destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, translationsSentArray[i] / maxTranslationDimension, TRANSLATION_COMPRESSION_RADIX); - } sendStatus.translationsSent = i; // faux joints @@ -777,7 +777,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent #ifdef WANT_DEBUG if (sendAll) { qCDebug(avatars) << "AvatarData::toByteArray" << cullSmallChanges << sendAll - << "rotations:" << rotationSentCount << "translations:" << translationsSentCount + << "rotations:" << rotationSentCount << "translations:" << translationSentCount << "largest:" << maxTranslationDimension << "size:" << (beforeRotations - startPosition) << "+" @@ -796,7 +796,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent outboundDataRateOut->jointDataRate.increment(numBytes); } } - + IF_AVATAR_SPACE(PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS, 1 + 2 * jointBitVectorSize) { auto startSection = destinationBuffer; @@ -1291,10 +1291,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } } // 1 + bytesOfValidity bytes - - // AJT: read maxTranslationDimension + // read maxTranslationDimension float maxTranslationDimension; - PACKET_READ_CHECK(MaxTranslationDimension, sizeof(float)); + PACKET_READ_CHECK(JointMaxTranslationDimension, sizeof(float)); memcpy(&maxTranslationDimension, sourceBuffer, sizeof(float)); sourceBuffer += sizeof(float); @@ -1306,7 +1305,6 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { JointData& data = _jointData[i]; if (validTranslations[i]) { sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); - // un-normalize translation data.translation *= maxTranslationDimension; _hasNewJointData = true; data.translationIsDefaultPose = false; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 8a3014d043..5bca76b513 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -279,7 +279,6 @@ namespace AvatarDataPacket { uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows. float maxTranslationDimension; // used to normalize fixed point translation values. SixByteTrans translation[numValidTranslations]; // normalized and compressed by packFloatVec3ToSignedTwoByteFixed() - SixByteQuat leftHandControllerRotation; SixByteTrans leftHandControllerTranslation; SixByteQuat rightHandControllerRotation; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 642914cd56..5634edca05 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -38,10 +38,10 @@ PacketVersion versionForPacketType(PacketType packetType) { return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: case PacketType::AvatarData: - return static_cast(AvatarMixerPacketVersion::CollisionFlag); + return static_cast(AvatarMixerPacketVersion::SendMaxTranslationDimension); case PacketType::BulkAvatarData: case PacketType::KillAvatar: - return static_cast(AvatarMixerPacketVersion::FasterAvatarEntities); + return static_cast(AvatarMixerPacketVersion::SendMaxTranslationDimension); case PacketType::MessagesData: return static_cast(MessageDataVersion::TextOrBinaryData); // ICE packets diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index f53a287d71..c01b3a47d7 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -312,7 +312,8 @@ enum class AvatarMixerPacketVersion : PacketVersion { GrabTraits, CollisionFlag, AvatarTraitsAck, - FasterAvatarEntities + FasterAvatarEntities, + SendMaxTranslationDimension }; enum class DomainConnectRequestVersion : PacketVersion { diff --git a/libraries/shared/src/JointData.h b/libraries/shared/src/JointData.h index f4c8b89e7a..7a2420262a 100644 --- a/libraries/shared/src/JointData.h +++ b/libraries/shared/src/JointData.h @@ -14,7 +14,7 @@ public: }; // Used by the avatar mixer to describe a single joint -// Translations relative to their parent and are in meters. +// Translations relative to their parent joint // Rotations are absolute (i.e. not relative to parent) and are in rig space. class JointData { public: diff --git a/tools/dissectors/3-hf-avatar.lua b/tools/dissectors/3-hf-avatar.lua index 0fa551c6f8..4fc5f44e66 100644 --- a/tools/dissectors/3-hf-avatar.lua +++ b/tools/dissectors/3-hf-avatar.lua @@ -282,6 +282,9 @@ function decode_avatar_data_packet(buf) i = i + num_validity_bytes result["valid_translations"] = "Valid Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}" + -- TODO: skip maxTranslationDimension + i = i + 4 + -- TODO: skip translations for now i = i + #indices * 6 From e68a8794cecd84744bd959fc3c4a42bfb24605ea Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 17 Jan 2019 16:18:43 -0800 Subject: [PATCH 11/17] Remove unused variable --- libraries/animation/src/Rig.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index c7a342b0eb..7b505f5668 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -2015,7 +2015,6 @@ void Rig::copyJointsFromJointData(const QVector& jointDataVec) { std::vector rotations; rotations.reserve(numJoints); const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform)); - const glm::vec3 rigToGeometryScale(extractScale(_rigToGeometryTransform)); for (int i = 0; i < numJoints; i++) { const JointData& data = jointDataVec.at(i); From 17ac4138b68f118ddab5b9dff3eb7641ef886d3f Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Fri, 18 Jan 2019 13:43:56 -0800 Subject: [PATCH 12/17] typos --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 72c90092f0..51e1db063c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -781,10 +781,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * 0. * @property {string} parentMaterialName="0" - Selects the mesh part or parts within the parent to which to apply the material. * If in the format "mat::string", all mesh parts with material name "string" are replaced. - * Otherwise the property value is parsed as an unsigned integer, specifying the mesh parth index to modify. If "all", + * Otherwise the property value is parsed as an unsigned integer, specifying the mesh part index to modify. If "all", * all mesh parts will be replaced. If an array (starts with "[" and ends with "]"), the string will be * split at each "," and each element will be parsed as either a number or a string if it starts with - * "mat::". In other words, "[0,1,mat::string,mat::string2]" will replace mesh parts 1 and 2, and any + * "mat::". In other words, "[0,1,mat::string,mat::string2]" will replace mesh parts 0 and 1, and any * mesh parts with material "string" or "string2". Do not put spaces around the commas. Invalid values * are parsed to 0. * @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either "uv" or From 9a854291af18811d630a2467f92d998e5bf400aa Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 18 Jan 2019 15:36:38 -0800 Subject: [PATCH 13/17] supress spurious not important AvatarEntity updates --- interface/src/avatar/MyAvatar.cpp | 8 ++++++-- libraries/entities/src/EntityTree.cpp | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e4da94c699..91987e721f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -873,9 +873,13 @@ void MyAvatar::simulate(float deltaTime, bool inView) { collisionlessAllowed = zone->getGhostingAllowed(); } EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); - bool force = false; - bool iShouldTellServer = true; forEachDescendant([&](SpatiallyNestablePointer object) { + // we need to update attached queryAACubes in our own local tree so point-select always works + // however we don't want to flood the update pipeline with AvatarEntity updates, so we assume + // others have all info required to properly update queryAACube of AvatarEntities on their end + EntityItemPointer entity = std::dynamic_pointer_cast(object); + bool iShouldTellServer = !(entity && entity->isAvatarEntity()); + const bool force = false; entityTree->updateEntityQueryAACube(object, packetSender, force, iShouldTellServer); }); }); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b251579b81..4c64a38e26 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -3008,8 +3008,8 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, // if the queryBox has changed, tell the entity-server EntityItemPointer entity = std::dynamic_pointer_cast(object); if (entity) { - bool tellServerThis = tellServer && (entity->getEntityHostType() != entity::HostType::AVATAR); - if ((entity->updateQueryAACube() || force)) { + // NOTE: we rely on side-effects of the entity->updateQueryAACube() call in the following if() conditional: + if (entity->updateQueryAACube() || force) { bool success; AACube newCube = entity->getQueryAACube(success); if (success) { @@ -3017,7 +3017,7 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, } // send an edit packet to update the entity-server about the queryAABox. We do this for domain-hosted // entities as well as for avatar-entities; the packet-sender will route the update accordingly - if (tellServerThis && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) { + if (tellServer && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) { quint64 now = usecTimestampNow(); EntityItemProperties properties = entity->getProperties(); properties.setQueryAACubeDirty(); From 5dbd62cc6711bbfacee6ce3988fc05dfed9524d1 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 18 Jan 2019 17:52:53 -0800 Subject: [PATCH 14/17] code review feedback --- libraries/avatars/src/AvatarData.cpp | 35 +++++++++++++++++++++------- libraries/avatars/src/AvatarData.h | 1 + 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b649bd2994..dcee1a9618 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -54,7 +54,8 @@ using namespace std; const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData"; -static const int TRANSLATION_COMPRESSION_RADIX = 12; +static const int TRANSLATION_COMPRESSION_RADIX = 14; +static const int FAUX_JOINT_COMPRESSION_RADIX = 12; static const int SENSOR_TO_WORLD_SCALE_RADIX = 10; static const float AUDIO_LOUDNESS_SCALE = 1024.0f; static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water @@ -86,6 +87,23 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints) return totalSize; } +size_t AvatarDataPacket::minJointDataSize(size_t numJoints) { + const size_t validityBitsSize = calcBitVectorSize((int)numJoints); + + size_t totalSize = sizeof(uint8_t); // numJoints + + totalSize += validityBitsSize; // Orientations mask + // assume no valid rotations + totalSize += validityBitsSize; // Translations mask + totalSize += sizeof(float); // maxTranslationDimension + // assume no valid translations + + size_t NUM_FAUX_JOINT = 2; + totalSize += NUM_FAUX_JOINT * (sizeof(SixByteQuat) + sizeof(SixByteTrans)); // faux joints + + return totalSize; +} + size_t AvatarDataPacket::maxJointDefaultPoseFlagsSize(size_t numJoints) { const size_t bitVectorSize = calcBitVectorSize((int)numJoints); size_t totalSize = sizeof(uint8_t); // numJoints @@ -612,8 +630,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent assert(numJoints <= 255); const int jointBitVectorSize = calcBitVectorSize(numJoints); - // Start joints if room for at least the faux joints. - IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, 1 + 4 + 2 * jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE) { + // include jointData if there is room for the most minimal section. i.e. no translations or rotations. + IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, AvatarDataPacket::minJointDataSize(numJoints)) { // Allow for faux joints + translation bit-vector: const ptrdiff_t minSizeForJoint = sizeof(AvatarDataPacket::SixByteQuat) + jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE; @@ -621,7 +639,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent // compute maxTranslationDimension before we send any joint data. float maxTranslationDimension = 0.001f; - for (int i = 0; i < numJoints; ++i) { + for (int i = sendStatus.rotationsSent; i < numJoints; ++i) { const JointData& data = jointData[i]; if (!data.translationIsDefaultPose) { maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension); @@ -697,8 +715,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent destinationBuffer += jointBitVectorSize; // Move pointer past the validity bytes // write maxTranslationDimension - memcpy(destinationBuffer, &maxTranslationDimension, sizeof(float)); - destinationBuffer += sizeof(float); + AVATAR_MEMCPY(maxTranslationDimension); float minTranslation = (distanceAdjust && cullSmallChanges) ? getDistanceBasedMinTranslationDistance(viewerPosition) : AVATAR_MIN_TRANSLATION; @@ -738,12 +755,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix()); destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation()); destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(), - TRANSLATION_COMPRESSION_RADIX); + FAUX_JOINT_COMPRESSION_RADIX); Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix()); destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation()); destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(), - TRANSLATION_COMPRESSION_RADIX); + FAUX_JOINT_COMPRESSION_RADIX); IF_AVATAR_SPACE(PACKET_HAS_GRAB_JOINTS, sizeof (AvatarDataPacket::FarGrabJoints)) { // the far-grab joints may range further than 3 meters, so we can't use packFloatVec3ToSignedTwoByteFixed etc @@ -882,7 +899,7 @@ const unsigned char* unpackFauxJoint(const unsigned char* sourceBuffer, ThreadSa glm::vec3 position; Transform transform; sourceBuffer += unpackOrientationQuatFromSixBytes(sourceBuffer, orientation); - sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, TRANSLATION_COMPRESSION_RADIX); + sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, FAUX_JOINT_COMPRESSION_RADIX); transform.setTranslation(position); transform.setRotation(orientation); matrixCache.set(transform.getMatrix()); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5bca76b513..52ab5ba688 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -286,6 +286,7 @@ namespace AvatarDataPacket { }; */ size_t maxJointDataSize(size_t numJoints, bool hasGrabJoints); + size_t minJointDataSize(size_t numJoints); /* struct JointDefaultPoseFlags { From c3a8c71f60d015677b8a18469d58f3c9dd54dc04 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 21 Jan 2019 12:27:14 -0800 Subject: [PATCH 15/17] Add TabletMenu to list of pages that trigger the QmlCommerce bridge --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7b79215cd2..bb2f129385 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2911,6 +2911,7 @@ void Application::initializeUi() { QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" }, QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" }, QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" }, + QUrl{ "hifi/tablet/TabletMenu.qml" }, }, commerceCallback); QmlContextCallback ttsCallback = [](QQmlContext* context) { context->setContextProperty("TextToSpeech", DependencyManager::get().data()); From 3a5d550fa5ff9a89b97cd922a95fb8a8f69407e3 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 22 Jan 2019 17:13:36 -0800 Subject: [PATCH 16/17] Treat QmlCommerce as a singleton class --- interface/src/Application.cpp | 7 ++++--- interface/src/commerce/QmlCommerce.h | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7b79215cd2..b6a47d6c9d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -919,6 +919,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -2598,6 +2599,7 @@ void Application::cleanupBeforeQuit() { DependencyManager::destroy(); // Must be destroyed before TabletScriptingInterface // stop QML + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -2886,7 +2888,7 @@ void Application::initializeUi() { Tooltip::registerType(); UpdateDialog::registerType(); QmlContextCallback commerceCallback = [](QQmlContext* context) { - context->setContextProperty("Commerce", new QmlCommerce()); + context->setContextProperty("Commerce", DependencyManager::get().data()); }; OffscreenQmlSurface::addWhitelistContextHandler({ QUrl{ "hifi/commerce/checkout/Checkout.qml" }, @@ -8014,8 +8016,7 @@ void Application::openUrl(const QUrl& url) const { if (url.scheme() == URL_SCHEME_HIFI) { DependencyManager::get()->handleLookupString(url.toString()); } else if (url.scheme() == URL_SCHEME_HIFIAPP) { - QmlCommerce commerce; - commerce.openSystemApp(url.path()); + DependencyManager::get()->openSystemApp(url.path()); } else { // address manager did not handle - ask QDesktopServices to handle QDesktopServices::openUrl(url); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index ad21899ebf..3a376e748c 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -19,7 +19,9 @@ #include -class QmlCommerce : public QObject { +#include + +class QmlCommerce : public QObject, public Dependency { Q_OBJECT public: From 77293150b738f4373c7cb89c031998c2a43b207e Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 22 Jan 2019 18:05:47 -0800 Subject: [PATCH 17/17] Const declarations to enforce singleton capability --- interface/src/commerce/QmlCommerce.cpp | 12 +++++------- interface/src/commerce/QmlCommerce.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 00acd40e70..5236c5a7fb 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -22,7 +22,9 @@ #include #include "scripting/HMDScriptingInterface.h" -QmlCommerce::QmlCommerce() { +QmlCommerce::QmlCommerce() : + _appsPath(PathUtils::getAppDataPath() + "Apps/") +{ auto ledger = DependencyManager::get(); auto wallet = DependencyManager::get(); connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult); @@ -44,22 +46,18 @@ QmlCommerce::QmlCommerce() { auto accountManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); }); - - _appsPath = PathUtils::getAppDataPath() + "Apps/"; } - - void QmlCommerce::openSystemApp(const QString& appName) { - static QMap systemApps { + static const QMap systemApps { {"GOTO", "hifi/tablet/TabletAddressDialog.qml"}, {"PEOPLE", "hifi/Pal.qml"}, {"WALLET", "hifi/commerce/wallet/Wallet.qml"}, {"MARKET", "/marketplace.html"} }; - static QMap systemInject{ + static const QMap systemInject{ {"MARKET", "/scripts/system/html/js/marketplacesInject.js"} }; diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 3a376e748c..3217b8a1f9 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -100,7 +100,7 @@ protected: Q_INVOKABLE void updateItem(const QString& certificateId); private: - QString _appsPath; + const QString _appsPath; }; #endif // hifi_QmlCommerce_h