From 0d514ad6450f46da10d3d2a1b68becfc07f2fb12 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 22 Oct 2015 13:02:08 -0700 Subject: [PATCH 01/28] Thread-safe avatar list access --- interface/src/avatar/AvatarManager.cpp | 8 +++++++- libraries/avatars/src/AvatarHashMap.cpp | 3 +++ libraries/avatars/src/AvatarHashMap.h | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 5f0ac435e0..20fdfdb1e9 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -77,7 +77,10 @@ AvatarManager::AvatarManager(QObject* parent) : void AvatarManager::init() { _myAvatar->init(); - _avatarHash.insert(MY_AVATAR_KEY, _myAvatar); + { + QWriteLocker locker(&_hashLock); + _avatarHash.insert(MY_AVATAR_KEY, _myAvatar); + } connect(DependencyManager::get().data(), &SceneScriptingInterface::shouldRenderAvatarsChanged, this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection); @@ -127,6 +130,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } else if (avatar->shouldDie()) { removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); + QWriteLocker locker(&_hashLock); avatarIterator = _avatarHash.erase(avatarIterator); } else { avatar->startUpdate(); @@ -202,6 +206,7 @@ void AvatarManager::removeAvatar(const QUuid& sessionUUID) { if (avatar != _myAvatar && avatar->isInitialized()) { removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); + QWriteLocker locker(&_hashLock); _avatarHash.erase(avatarIterator); } } @@ -218,6 +223,7 @@ void AvatarManager::clearOtherAvatars() { } else { removeAvatarMotionState(avatar); _avatarFades.push_back(avatarIterator.value()); + QWriteLocker locker(&_hashLock); avatarIterator = _avatarHash.erase(avatarIterator); } } diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 520bb34887..4256e2650e 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -23,6 +23,7 @@ AvatarHashMap::AvatarHashMap() { } bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { + QReadLocker locker(&_hashLock); foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) { glm::vec3 avatarPosition = sharedAvatar->getPosition(); float distance = glm::distance(avatarPosition, position); @@ -43,6 +44,7 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe AvatarSharedPointer avatar = newSharedAvatar(); avatar->setSessionUUID(sessionUUID); avatar->setOwningAvatarMixer(mixerWeakPointer); + QWriteLocker locker(&_hashLock); _avatarHash.insert(sessionUUID, avatar); return avatar; @@ -134,6 +136,7 @@ void AvatarHashMap::processKillAvatar(QSharedPointer packet, SharedNod } void AvatarHashMap::removeAvatar(const QUuid& sessionUUID) { + QWriteLocker locker(&_hashLock); _avatarHash.remove(sessionUUID); } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 804233b76a..142fb1cab5 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -52,6 +52,9 @@ protected: virtual void removeAvatar(const QUuid& sessionUUID); AvatarHash _avatarHash; + // "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write lock. + // If you access from a different thread, it is your responsibility to write- or read-lock the _hashLock. + QReadWriteLock _hashLock; private: QUuid _lastOwnerSessionUUID; From 624ed7c71128cd413f577ca26963c648f7eb9fd8 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 22 Oct 2015 13:14:38 -0700 Subject: [PATCH 02/28] fix comment --- libraries/avatars/src/AvatarHashMap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 142fb1cab5..4af741c8cc 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -52,8 +52,8 @@ protected: virtual void removeAvatar(const QUuid& sessionUUID); AvatarHash _avatarHash; - // "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write lock. - // If you access from a different thread, it is your responsibility to write- or read-lock the _hashLock. + // "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write-lock. + // If you read from a different thread, you must read-lock the _hashLock. (Scripted write access is not supported). QReadWriteLock _hashLock; private: From 7b0b77f4d11eb8b7f40631b111d0dafabfc56b68 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 23 Oct 2015 16:57:27 -0700 Subject: [PATCH 03/28] getAvatarHash => withAvatarHash --- interface/src/avatar/AvatarManager.cpp | 6 +- interface/src/avatar/MyAvatar.cpp | 107 ++++++++++++------------ libraries/avatars/src/AvatarHashMap.cpp | 4 + libraries/avatars/src/AvatarHashMap.h | 3 +- 4 files changed, 65 insertions(+), 55 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 20fdfdb1e9..4352934315 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -355,5 +355,9 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) if (sessionID == _myAvatar->getSessionUUID()) { return std::static_pointer_cast(_myAvatar); } - return getAvatarHash()[sessionID]; + AvatarSharedPointer avatar; + withAvatarHash([&avatar, &sessionID] (const AvatarHash& hash) { + avatar = hash[sessionID]; + }); + return avatar; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5920543dca..c6711c3324 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1018,71 +1018,72 @@ void MyAvatar::updateLookAtTargetAvatar() { const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f; const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; - foreach (const AvatarSharedPointer& avatarPointer, DependencyManager::get()->getAvatarHash()) { - auto avatar = static_pointer_cast(avatarPointer); - bool isCurrentTarget = avatar->getIsLookAtTarget(); - float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); - avatar->setIsLookAtTarget(false); - if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getScale())) { - float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); - if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { - _lookAtTargetAvatar = avatarPointer; - _targetAvatarPosition = avatarPointer->getPosition(); - smallestAngleTo = angleTo; - } - if (isLookingAtMe(avatar)) { + DependencyManager::get()->withAvatarHash([&] (const AvatarHash& hash) { + foreach (const AvatarSharedPointer& avatarPointer, hash) { + auto avatar = static_pointer_cast(avatarPointer); + bool isCurrentTarget = avatar->getIsLookAtTarget(); + float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); + avatar->setIsLookAtTarget(false); + if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getScale())) { + float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); + if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { + _lookAtTargetAvatar = avatarPointer; + _targetAvatarPosition = avatarPointer->getPosition(); + smallestAngleTo = angleTo; + } + if (isLookingAtMe(avatar)) { - // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. - glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. + // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. + glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. - // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) - // Let's get everything to world space: - glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); - glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); - // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. - // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) - // This might be more work than needed for any given use, but as we explore different formulations, we go mad if we don't work in world space. - glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); - glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); - glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); - glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); - auto humanSystem = qApp->getViewFrustum(); - glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); - glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); + // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) + // Let's get everything to world space: + glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); + glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); + // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. + // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) + // This might be more work than needed for any given use, but as we explore different formulations, we go mad if we don't work in world space. + glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); + glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); + glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); + glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); + auto humanSystem = qApp->getViewFrustum(); + glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); + glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); + // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. + // (We will be adding that offset to the camera position, after making some other adjustments.) + glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); - // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. - // (We will be adding that offset to the camera position, after making some other adjustments.) - glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); + // Scale by proportional differences between avatar and human. + float humanEyeSeparationInModelSpace = glm::length(humanLeftEye - humanRightEye); + float avatarEyeSeparation = glm::length(avatarLeftEye - avatarRightEye); + gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; - // Scale by proportional differences between avatar and human. - float humanEyeSeparationInModelSpace = glm::length(humanLeftEye - humanRightEye); - float avatarEyeSeparation = glm::length(avatarLeftEye - avatarRightEye); - gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; + // If the camera is also not oriented with the head, adjust by getting the offset in head-space... + /* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday. + glm::quat avatarHeadOrientation = getHead()->getOrientation(); + glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; + // ... and treat that as though it were in camera space, bringing it back to world space. + // But camera is fudged to make the picture feel like the avatar's orientation. + glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ? + gazeOffset = humanOrientation * gazeOffsetLocalToHead; + glm::vec3 corrected = humanSystem->getPosition() + gazeOffset; + */ - // If the camera is also not oriented with the head, adjust by getting the offset in head-space... - /* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday. - glm::quat avatarHeadOrientation = getHead()->getOrientation(); - glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; - // ... and treat that as though it were in camera space, bringing it back to world space. - // But camera is fudged to make the picture feel like the avatar's orientation. - glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ? - gazeOffset = humanOrientation * gazeOffsetLocalToHead; - glm::vec3 corrected = humanSystem->getPosition() + gazeOffset; - */ + // And now we can finally add that offset to the camera. + glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset; - // And now we can finally add that offset to the camera. - glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset; - - avatar->getHead()->setCorrectedLookAtPosition(corrected); + avatar->getHead()->setCorrectedLookAtPosition(corrected); + } else { + avatar->getHead()->clearCorrectedLookAtPosition(); + } } else { avatar->getHead()->clearCorrectedLookAtPosition(); } - } else { - avatar->getHead()->clearCorrectedLookAtPosition(); } - } + }); auto avatarPointer = _lookAtTargetAvatar.lock(); if (avatarPointer) { static_pointer_cast(avatarPointer)->setIsLookAtTarget(true); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 4256e2650e..3f1e668cd0 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -22,6 +22,10 @@ AvatarHashMap::AvatarHashMap() { connect(DependencyManager::get().data(), &NodeList::uuidChanged, this, &AvatarHashMap::sessionUUIDChanged); } +void AvatarHashMap::withAvatarHash(std::function callback) { + QReadLocker locker(&_hashLock); + callback(_avatarHash); +} bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { QReadLocker locker(&_hashLock); foreach(const AvatarSharedPointer& sharedAvatar, _avatarHash) { diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 4af741c8cc..93364eb1ef 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -30,7 +31,7 @@ class AvatarHashMap : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - const AvatarHash& getAvatarHash() { return _avatarHash; } + void withAvatarHash(std::function); int size() { return _avatarHash.size(); } public slots: From 8d0aaed41ae09f2ef47e0390b3f4e254303dcf3c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 26 Oct 2015 13:50:21 -0700 Subject: [PATCH 04/28] fix bug that was deleting actions with 0 ttl. in js interface, action parameter 'lifetime' is now called 'ttl' --- examples/controllers/handControllerGrab.js | 24 ++++++++--------- examples/grab.js | 8 +++--- interface/src/InterfaceActionFactory.cpp | 3 ++- interface/src/avatar/AvatarActionHold.cpp | 8 +++--- .../entities/src/EntityActionInterface.h | 1 + libraries/physics/src/ObjectAction.cpp | 26 ++++++++++++++----- libraries/physics/src/ObjectAction.h | 9 +++++-- libraries/physics/src/ObjectActionOffset.cpp | 9 ++++--- libraries/physics/src/ObjectActionSpring.cpp | 8 +++--- 9 files changed, 62 insertions(+), 34 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 80fb4c8e40..cb445a0960 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -74,8 +74,8 @@ var MSEC_PER_SEC = 1000.0; // these control how long an abandoned pointer line will hang around var LIFETIME = 10; -var ACTION_LIFETIME = 15; // seconds -var ACTION_LIFETIME_REFRESH = 5; +var ACTION_TTL = 15; // seconds +var ACTION_TTL_REFRESH = 5; var PICKS_PER_SECOND_PER_HAND = 5; var MSECS_PER_SEC = 1000.0; @@ -422,12 +422,12 @@ function MyController(hand, triggerAction) { targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, tag: getTag(), - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } - this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); if (this.actionID !== null) { this.setState(STATE_CONTINUE_DISTANCE_HOLDING); @@ -524,9 +524,9 @@ function MyController(hand, triggerAction) { linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME, - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }); - this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); }; this.nearGrabbing = function() { @@ -579,12 +579,12 @@ function MyController(hand, triggerAction) { timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } else { - this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); this.setState(STATE_CONTINUE_NEAR_GRABBING); if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); @@ -624,16 +624,16 @@ function MyController(hand, triggerAction) { this.currentObjectTime = now; Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); - if (this.actionTimeout - now < ACTION_LIFETIME_REFRESH * MSEC_PER_SEC) { - // if less than a 5 seconds left, refresh the actions lifetime + if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) { + // if less than a 5 seconds left, refresh the actions ttl Entities.updateAction(this.grabbedEntity, this.actionID, { hand: this.hand === RIGHT_HAND ? "right" : "left", timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }); - this.actionTimeout = now + (ACTION_LIFETIME * MSEC_PER_SEC); + this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); } }; diff --git a/examples/grab.js b/examples/grab.js index 1a02911db9..ee6c3c4de5 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -47,7 +47,7 @@ var IDENTITY_QUAT = { z: 0, w: 0 }; -var ACTION_LIFETIME = 10; // seconds +var ACTION_TTL = 10; // seconds function getTag() { return "grab-" + MyAvatar.sessionUUID; @@ -403,7 +403,7 @@ Grabber.prototype.moveEvent = function(event) { var actionArgs = { tag: getTag(), - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }; if (this.mode === "rotate") { @@ -424,7 +424,7 @@ Grabber.prototype.moveEvent = function(event) { targetRotation: this.lastRotation, angularTimeScale: 0.1, tag: getTag(), - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }; } else { @@ -459,7 +459,7 @@ Grabber.prototype.moveEvent = function(event) { targetPosition: this.targetPosition, linearTimeScale: 0.1, tag: getTag(), - lifetime: ACTION_LIFETIME + ttl: ACTION_TTL }; diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp index f814df9a99..67b3b4a649 100644 --- a/interface/src/InterfaceActionFactory.cpp +++ b/interface/src/InterfaceActionFactory.cpp @@ -66,7 +66,8 @@ EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEnt if (action) { action->deserialize(data); if (action->lifetimeIsOver()) { - qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation"; + qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation --" + << action->getExpires() << "<" << usecTimestampNow(); return nullptr; } } diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index d2f5514e10..238e48d2fd 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -243,7 +243,7 @@ QByteArray AvatarActionHold::serialize() const { dataStream << _linearTimeScale; dataStream << _hand; - dataStream << _expires + getEntityServerClockSkew(); + dataStream << localTimeToServerTime(_expires); dataStream << _tag; dataStream << _kinematic; dataStream << _kinematicSetVelocity; @@ -277,8 +277,10 @@ void AvatarActionHold::deserialize(QByteArray serializedArguments) { _angularTimeScale = _linearTimeScale; dataStream >> _hand; - dataStream >> _expires; - _expires -= getEntityServerClockSkew(); + quint64 serverExpires; + dataStream >> serverExpires; + _expires = serverTimeToLocalTime(serverExpires); + dataStream >> _tag; dataStream >> _kinematic; dataStream >> _kinematicSetVelocity; diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index d97b5e8106..b257df3325 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -47,6 +47,7 @@ public: static QString actionTypeToString(EntityActionType actionType); virtual bool lifetimeIsOver() { return false; } + virtual quint64 getExpires() { return 0; } bool locallyAddedButNotYetReceived = false; diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index ce4ebfd22f..b58e37e495 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -85,11 +85,11 @@ bool ObjectAction::updateArguments(QVariantMap arguments) { quint64 previousExpires = _expires; QString previousTag = _tag; - bool lifetimeSet = true; - float lifetime = EntityActionInterface::extractFloatArgument("action", arguments, "lifetime", lifetimeSet, false); - if (lifetimeSet) { + bool ttlSet = true; + float ttl = EntityActionInterface::extractFloatArgument("action", arguments, "ttl", ttlSet, false); + if (ttlSet) { quint64 now = usecTimestampNow(); - _expires = now + (quint64)(lifetime * USECS_PER_SECOND); + _expires = now + (quint64)(ttl * USECS_PER_SECOND); } else { _expires = 0; } @@ -114,10 +114,10 @@ QVariantMap ObjectAction::getArguments() { QVariantMap arguments; withReadLock([&]{ if (_expires == 0) { - arguments["lifetime"] = 0.0f; + arguments["ttl"] = 0.0f; } else { quint64 now = usecTimestampNow(); - arguments["lifetime"] = (float)(_expires - now) / (float)USECS_PER_SECOND; + arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND; } arguments["tag"] = _tag; }); @@ -245,3 +245,17 @@ bool ObjectAction::lifetimeIsOver() { } return false; } + +quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) { + if (timeValue == 0) { + return 0; + } + return timeValue + getEntityServerClockSkew(); +} + +quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) { + if (timeValue == 0) { + return 0; + } + return timeValue - getEntityServerClockSkew(); +} diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 98e58475c6..3c8574f6ff 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -47,11 +47,10 @@ public: virtual void deserialize(QByteArray serializedArguments) = 0; virtual bool lifetimeIsOver(); + virtual quint64 getExpires() { return _expires; } protected: - int getEntityServerClockSkew() const; - virtual btRigidBody* getRigidBody(); virtual glm::vec3 getPosition(); virtual void setPosition(glm::vec3 position); @@ -68,6 +67,12 @@ protected: quint64 _expires; // in seconds since epoch QString _tag; + + quint64 localTimeToServerTime(quint64 timeValue); + quint64 serverTimeToLocalTime(quint64 timeValue); + +private: + int getEntityServerClockSkew() const; }; #endif // hifi_ObjectAction_h diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index b6edf22ffc..2cfd98497b 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -160,7 +160,7 @@ QByteArray ObjectActionOffset::serialize() const { dataStream << _linearDistance; dataStream << _linearTimeScale; dataStream << _positionalTargetSet; - dataStream << _expires + getEntityServerClockSkew(); + dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); @@ -189,8 +189,11 @@ void ObjectActionOffset::deserialize(QByteArray serializedArguments) { dataStream >> _linearDistance; dataStream >> _linearTimeScale; dataStream >> _positionalTargetSet; - dataStream >> _expires; - _expires -= getEntityServerClockSkew(); + + quint64 serverExpires; + dataStream >> serverExpires; + _expires = serverTimeToLocalTime(serverExpires); + dataStream >> _tag; _active = true; }); diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index a74756eb53..c1cd2db5ca 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -198,7 +198,7 @@ QByteArray ObjectActionSpring::serialize() const { dataStream << _rotationalTarget; dataStream << _angularTimeScale; dataStream << _rotationalTargetSet; - dataStream << _expires + getEntityServerClockSkew(); + dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); @@ -232,8 +232,10 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) { dataStream >> _angularTimeScale; dataStream >> _rotationalTargetSet; - dataStream >> _expires; - _expires -= getEntityServerClockSkew(); + quint64 serverExpires; + dataStream >> serverExpires; + _expires = serverTimeToLocalTime(serverExpires); + dataStream >> _tag; _active = true; From 0dff037f5601b011c992a0565f0d3c49291b61e4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 26 Oct 2015 13:55:07 -0700 Subject: [PATCH 05/28] fuck you, const! --- libraries/physics/src/ObjectAction.cpp | 4 ++-- libraries/physics/src/ObjectAction.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index b58e37e495..8ed06aea5d 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -246,14 +246,14 @@ bool ObjectAction::lifetimeIsOver() { return false; } -quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) { +quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const { if (timeValue == 0) { return 0; } return timeValue + getEntityServerClockSkew(); } -quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) { +quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const { if (timeValue == 0) { return 0; } diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 3c8574f6ff..fca446aec4 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -68,8 +68,8 @@ protected: quint64 _expires; // in seconds since epoch QString _tag; - quint64 localTimeToServerTime(quint64 timeValue); - quint64 serverTimeToLocalTime(quint64 timeValue); + quint64 localTimeToServerTime(quint64 timeValue) const; + quint64 serverTimeToLocalTime(quint64 timeValue) const; private: int getEntityServerClockSkew() const; From 4c64da9ce5d22ccf6d98b0dc34a5debd9222130f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 27 Oct 2015 10:27:32 -0700 Subject: [PATCH 06/28] try to avoid negative roll-over when moving to or from server time --- libraries/physics/src/ObjectAction.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index 8ed06aea5d..ff8382a143 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -247,15 +247,29 @@ bool ObjectAction::lifetimeIsOver() { } quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const { + // 0 indicates no expiration if (timeValue == 0) { return 0; } - return timeValue + getEntityServerClockSkew(); + + int serverClockSkew = getEntityServerClockSkew(); + if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) { + return 1; // non-zero but long-expired value to avoid negative roll-over + } + + return timeValue + serverClockSkew; } quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const { + // 0 indicates no expiration if (timeValue == 0) { return 0; } - return timeValue - getEntityServerClockSkew(); + + int serverClockSkew = getEntityServerClockSkew(); + if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) { + return 1; // non-zero but long-expired value to avoid negative roll-over + } + + return timeValue - serverClockSkew; } From ae8938cadcd51cbbe0090b399b270d70cdb87892 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 27 Oct 2015 18:30:35 -0700 Subject: [PATCH 07/28] Fix for local eye tracking in AnimGraph Also moved Rig::updateAnimations() now occurs after Rig::updateFromHeadParameters() and Rig::updateFromHandParameters(). This should remove a frame of lag for head and hand IK targets. Rig::updateFromEyeParameters() occurs after Rig::updateAnimations(). But now the eye JointStates are re-computed, this is the actual fix for the local eye tracking issue. --- interface/src/avatar/SkeletonModel.cpp | 43 +++++++++++++++++++------- libraries/animation/src/Rig.cpp | 35 +++------------------ libraries/animation/src/Rig.h | 19 +++++++----- 3 files changed, 47 insertions(+), 50 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 28c7941c52..c3716aa77a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -114,15 +114,12 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { if (_owningAvatar->isMyAvatar()) { _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation()); } - Model::updateRig(deltaTime, parentTransform); Head* head = _owningAvatar->getHead(); if (_owningAvatar->isMyAvatar()) { MyAvatar* myAvatar = static_cast(_owningAvatar); const FBXGeometry& geometry = _geometry->getFBXGeometry(); Rig::HeadParameters headParams; - headParams.modelRotation = getRotation(); - headParams.modelTranslation = getTranslation(); headParams.enableLean = qApp->getAvatarUpdater()->isHMDMode(); headParams.leanSideways = head->getFinalLeanSideways(); headParams.leanForward = head->getFinalLeanForward(); @@ -156,19 +153,13 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); } - headParams.eyeLookAt = head->getLookAtPosition(); - headParams.eyeSaccade = head->getSaccade(); headParams.leanJointIndex = geometry.leanJointIndex; headParams.neckJointIndex = geometry.neckJointIndex; - headParams.leftEyeJointIndex = geometry.leftEyeJointIndex; - headParams.rightEyeJointIndex = geometry.rightEyeJointIndex; - headParams.isTalking = head->getTimeWithoutTalking() <= 1.5f; _rig->updateFromHeadParameters(headParams, deltaTime); Rig::HandParameters handParams; - const PalmData* leftPalm = getPalmWithIndex(myAvatar->getHand(), LEFT_HAND_INDEX); if (leftPalm && leftPalm->isActive()) { handParams.isLeftEnabled = true; @@ -191,7 +182,28 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromHandParameters(handParams, deltaTime); + // evaluate AnimGraph animation and update jointStates. + Model::updateRig(deltaTime, parentTransform); + + Rig::EyeParameters eyeParams; + eyeParams.worldHeadOrientation = headParams.worldHeadOrientation; + eyeParams.eyeLookAt = head->getLookAtPosition(); + eyeParams.eyeSaccade = head->getSaccade(); + eyeParams.modelRotation = getRotation(); + eyeParams.modelTranslation = getTranslation(); + eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; + eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex; + + _rig->updateFromEyeParameters(eyeParams, deltaTime); + + // rebuild the jointState transform for the eyes only + _rig->updateJointState(eyeParams.leftEyeJointIndex, parentTransform); + _rig->updateJointState(eyeParams.rightEyeJointIndex, parentTransform); + } else { + + Model::updateRig(deltaTime, parentTransform); + // This is a little more work than we really want. // // Other avatars joint, including their eyes, should already be set just like any other joints @@ -208,9 +220,16 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { head->setBasePitch(glm::degrees(-eulers.x)); head->setBaseYaw(glm::degrees(eulers.y)); head->setBaseRoll(glm::degrees(-eulers.z)); - _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex, - getTranslation(), getRotation(), - head->getFinalOrientationInWorldFrame(), head->getCorrectedLookAtPosition()); + + Rig::EyeParameters eyeParams; + eyeParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); + eyeParams.eyeLookAt = head->getCorrectedLookAtPosition(); + eyeParams.eyeSaccade = glm::vec3(0); + eyeParams.modelRotation = getRotation(); + eyeParams.modelTranslation = getTranslation(); + eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; + eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex; + _rig->updateFromEyeParameters(eyeParams, deltaTime); } } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 6fd6f5cbf9..023fcb9800 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -22,34 +22,6 @@ #include "AnimSkeleton.h" #include "IKTarget.h" - -void Rig::HeadParameters::dump() const { - qCDebug(animation, "HeadParameters ="); - qCDebug(animation, " leanSideways = %0.5f", (double)leanSideways); - qCDebug(animation, " leanForward = %0.5f", (double)leanForward); - qCDebug(animation, " torsoTwist = %0.5f", (double)torsoTwist); - glm::vec3 axis = glm::axis(localHeadOrientation); - float theta = glm::angle(localHeadOrientation); - qCDebug(animation, " localHeadOrientation axis = (%.5f, %.5f, %.5f), theta = %0.5f", (double)axis.x, (double)axis.y, (double)axis.z, (double)theta); - axis = glm::axis(worldHeadOrientation); - theta = glm::angle(worldHeadOrientation); - qCDebug(animation, " localHead pitch = %.5f, yaw = %.5f, roll = %.5f", (double)localHeadPitch, (double)localHeadYaw, (double)localHeadRoll); - qCDebug(animation, " localHeadPosition = (%.5f, %.5f, %.5f)", (double)localHeadPosition.x, (double)localHeadPosition.y, (double)localHeadPosition.z); - qCDebug(animation, " isInHMD = %s", isInHMD ? "true" : "false"); - qCDebug(animation, " worldHeadOrientation axis = (%.5f, %.5f, %.5f), theta = %0.5f", (double)axis.x, (double)axis.y, (double)axis.z, (double)theta); - axis = glm::axis(modelRotation); - theta = glm::angle(modelRotation); - qCDebug(animation, " modelRotation axis = (%.5f, %.5f, %.5f), theta = %0.5f", (double)axis.x, (double)axis.y, (double)axis.z, (double)theta); - qCDebug(animation, " modelTranslation = (%.5f, %.5f, %.5f)", (double)modelTranslation.x, (double)modelTranslation.y, (double)modelTranslation.z); - qCDebug(animation, " eyeLookAt = (%.5f, %.5f, %.5f)", (double)eyeLookAt.x, (double)eyeLookAt.y, (double)eyeLookAt.z); - qCDebug(animation, " eyeSaccade = (%.5f, %.5f, %.5f)", (double)eyeSaccade.x, (double)eyeSaccade.y, (double)eyeSaccade.z); - qCDebug(animation, " leanJointIndex = %.d", leanJointIndex); - qCDebug(animation, " neckJointIndex = %.d", neckJointIndex); - qCDebug(animation, " leftEyeJointIndex = %.d", leftEyeJointIndex); - qCDebug(animation, " rightEyeJointIndex = %.d", rightEyeJointIndex); - qCDebug(animation, " isTalking = %s", isTalking ? "true" : "false"); -} - void insertSorted(QList& handles, const AnimationHandlePointer& handle) { for (QList::iterator it = handles.begin(); it != handles.end(); it++) { if (handle->getPriority() > (*it)->getPriority()) { @@ -981,8 +953,6 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { _animVars.unset("lean"); } updateNeckJoint(params.neckJointIndex, params); - updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, - params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); if (_enableAnimGraph) { _animVars.set("isTalking", params.isTalking); @@ -990,6 +960,11 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { } } +void Rig::updateFromEyeParameters(const EyeParameters& params, float dt) { + updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, + params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); +} + static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f); static const glm::vec3 Y_AXIS(0.0f, 1.0f, 0.0f); static const glm::vec3 Z_AXIS(0.0f, 0.0f, 1.0f); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index c9c42cbbb6..7ae0721625 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -57,24 +57,26 @@ public: float leanForward = 0.0f; // degrees float torsoTwist = 0.0f; // degrees bool enableLean = false; - glm::quat modelRotation = glm::quat(); + glm::quat worldHeadOrientation = glm::quat(); glm::quat localHeadOrientation = glm::quat(); float localHeadPitch = 0.0f; // degrees float localHeadYaw = 0.0f; // degrees float localHeadRoll = 0.0f; // degrees glm::vec3 localHeadPosition = glm::vec3(); bool isInHMD = false; + int leanJointIndex = -1; + int neckJointIndex = -1; + bool isTalking = false; + }; + + struct EyeParameters { glm::quat worldHeadOrientation = glm::quat(); glm::vec3 eyeLookAt = glm::vec3(); // world space glm::vec3 eyeSaccade = glm::vec3(); // world space glm::vec3 modelTranslation = glm::vec3(); - int leanJointIndex = -1; - int neckJointIndex = -1; + glm::quat modelRotation = glm::quat(); int leftEyeJointIndex = -1; int rightEyeJointIndex = -1; - bool isTalking = false; - - void dump() const; }; struct HandParameters { @@ -185,8 +187,7 @@ public: bool getEnableAnimGraph() const { return _enableAnimGraph; } void updateFromHeadParameters(const HeadParameters& params, float dt); - void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, - const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade = glm::vec3(0.0f)); + void updateFromEyeParameters(const EyeParameters& params, float dt); void updateFromHandParameters(const HandParameters& params, float dt); @@ -207,6 +208,8 @@ public: void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateNeckJoint(int index, const HeadParameters& params); void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade); + void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, + const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade); QVector _jointStates; int _rootJointIndex = -1; From f91dc93620a331a72953978d6d6b78e7a3964396 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 08:40:38 -0700 Subject: [PATCH 08/28] adjust locking in EntityItem::getActionDataInternal --- libraries/entities/src/EntityItem.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1fd9acc1e2..701732b921 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1790,8 +1790,16 @@ const QByteArray EntityItem::getActionDataInternal() const { const QByteArray EntityItem::getActionData() const { QByteArray result; assertUnlocked(); + + if (_actionDataDirty) { + EntityItem* unconstThis = const_cast(this); + unconstThis->withWriteLock([&] { + getActionDataInternal(); + }); + } + withReadLock([&] { - result = getActionDataInternal(); + result = _allActionsDataCache; }); return result; } From 2b5b4f111823c4858c78be41aa371144c70fc1c3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 09:54:16 -0700 Subject: [PATCH 09/28] avoid unneeded read-lock if action-data was dirty --- libraries/entities/src/EntityItem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 701732b921..08e63fb1d1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1795,6 +1795,7 @@ const QByteArray EntityItem::getActionData() const { EntityItem* unconstThis = const_cast(this); unconstThis->withWriteLock([&] { getActionDataInternal(); + return _allActionsDataCache; }); } From d504f449e4754b3d88030888d1c48d30e5dc019d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 09:55:11 -0700 Subject: [PATCH 10/28] undo last commit -- avoid unneeded read-lock if action-data was dirty --- libraries/entities/src/EntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 08e63fb1d1..701732b921 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1795,7 +1795,6 @@ const QByteArray EntityItem::getActionData() const { EntityItem* unconstThis = const_cast(this); unconstThis->withWriteLock([&] { getActionDataInternal(); - return _allActionsDataCache; }); } From 08a0bf33a49833eb080c42b531634c61ed4e05b7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 09:55:55 -0700 Subject: [PATCH 11/28] avoid unneeded read-lock if action-data was dirty --- libraries/entities/src/EntityItem.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 701732b921..91ea4864df 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1795,12 +1795,13 @@ const QByteArray EntityItem::getActionData() const { EntityItem* unconstThis = const_cast(this); unconstThis->withWriteLock([&] { getActionDataInternal(); + result = _allActionsDataCache; + }); + } else { + withReadLock([&] { + result = _allActionsDataCache; }); } - - withReadLock([&] { - result = _allActionsDataCache; - }); return result; } From f6a0004f26f73ec7c506ec3d7a287fbd6799f29b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 10:45:24 -0700 Subject: [PATCH 12/28] get rid of some useless consts --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 91ea4864df..4d5fb1b180 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1776,7 +1776,7 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { return; } -const QByteArray EntityItem::getActionDataInternal() const { +QByteArray EntityItem::getActionDataInternal() const { if (_actionDataDirty) { bool success; serializeActions(success, _allActionsDataCache); @@ -1787,7 +1787,7 @@ const QByteArray EntityItem::getActionDataInternal() const { return _allActionsDataCache; } -const QByteArray EntityItem::getActionData() const { +QByteArray EntityItem::getActionData() const { QByteArray result; assertUnlocked(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 858dc7e326..9e6430b4c3 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -401,7 +401,7 @@ public: bool removeAction(EntitySimulation* simulation, const QUuid& actionID); bool clearActions(EntitySimulation* simulation); void setActionData(QByteArray actionData); - const QByteArray getActionData() const; + QByteArray getActionData() const; bool hasActions() { return !_objectActions.empty(); } QList getActionIDs() { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; @@ -415,7 +415,7 @@ public: protected: - const QByteArray getActionDataInternal() const; + QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); static bool _sendPhysicsUpdates; From b3734b5ddb3e44c6d5185abb86a3a0eb1992a456 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Oct 2015 10:46:09 -0700 Subject: [PATCH 13/28] Rig: removed redundant method updateEyeJoints() Instead we call updateEyeJoint() twice, once for each eye. --- libraries/animation/src/Rig.cpp | 12 ++++-------- libraries/animation/src/Rig.h | 2 -- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 023fcb9800..8c7fa22c22 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -961,8 +961,10 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { } void Rig::updateFromEyeParameters(const EyeParameters& params, float dt) { - updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, - params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); + updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, + params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); + updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, + params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); } static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f); @@ -1120,12 +1122,6 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { } } -void Rig::updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, - const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) { - updateEyeJoint(leftEyeIndex, modelTranslation, modelRotation, worldHeadOrientation, lookAtSpot, saccade); - updateEyeJoint(rightEyeIndex, modelTranslation, modelRotation, worldHeadOrientation, lookAtSpot, saccade); -} - void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { auto& state = _jointStates[index]; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 7ae0721625..25e823d6bc 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -208,8 +208,6 @@ public: void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateNeckJoint(int index, const HeadParameters& params); void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade); - void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, - const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade); QVector _jointStates; int _rootJointIndex = -1; From 367175b8a64e6ef9e5953861047479fb53a07241 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 28 Oct 2015 10:49:19 -0700 Subject: [PATCH 14/28] Reduce lock time. --- interface/src/avatar/AvatarManager.cpp | 7 +- interface/src/avatar/MyAvatar.cpp | 110 +++++++++++++------------ 2 files changed, 58 insertions(+), 59 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 4352934315..9783590b05 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -355,9 +355,6 @@ AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) if (sessionID == _myAvatar->getSessionUUID()) { return std::static_pointer_cast(_myAvatar); } - AvatarSharedPointer avatar; - withAvatarHash([&avatar, &sessionID] (const AvatarHash& hash) { - avatar = hash[sessionID]; - }); - return avatar; + QReadLocker locker(&_hashLock); + return _avatarHash[sessionID]; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c6711c3324..a69c22813a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1018,72 +1018,74 @@ void MyAvatar::updateLookAtTargetAvatar() { const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f; const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; - DependencyManager::get()->withAvatarHash([&] (const AvatarHash& hash) { - foreach (const AvatarSharedPointer& avatarPointer, hash) { - auto avatar = static_pointer_cast(avatarPointer); - bool isCurrentTarget = avatar->getIsLookAtTarget(); - float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); - avatar->setIsLookAtTarget(false); - if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getScale())) { - float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); - if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { - _lookAtTargetAvatar = avatarPointer; - _targetAvatarPosition = avatarPointer->getPosition(); - smallestAngleTo = angleTo; - } - if (isLookingAtMe(avatar)) { + AvatarHash hash; + DependencyManager::get()->withAvatarHash([&] (const AvatarHash& locked) { + hash = locked; // make a shallow copy and operate on that, to minimize lock time + }); + foreach (const AvatarSharedPointer& avatarPointer, hash) { + auto avatar = static_pointer_cast(avatarPointer); + bool isCurrentTarget = avatar->getIsLookAtTarget(); + float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition); + avatar->setIsLookAtTarget(false); + if (!avatar->isMyAvatar() && avatar->isInitialized() && (distanceTo < GREATEST_LOOKING_AT_DISTANCE * getScale())) { + float angleTo = glm::angle(lookForward, glm::normalize(avatar->getHead()->getEyePosition() - cameraPosition)); + if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) { + _lookAtTargetAvatar = avatarPointer; + _targetAvatarPosition = avatarPointer->getPosition(); + smallestAngleTo = angleTo; + } + if (isLookingAtMe(avatar)) { - // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. - glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. + // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. + glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. - // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) - // Let's get everything to world space: - glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); - glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); - // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. - // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) - // This might be more work than needed for any given use, but as we explore different formulations, we go mad if we don't work in world space. - glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); - glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); - glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); - glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); - auto humanSystem = qApp->getViewFrustum(); - glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); - glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); + // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) + // Let's get everything to world space: + glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); + glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); + // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. + // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) + // This might be more work than needed for any given use, but as we explore different formulations, we go mad if we don't work in world space. + glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); + glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); + glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); + glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); + auto humanSystem = qApp->getViewFrustum(); + glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); + glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); - // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. - // (We will be adding that offset to the camera position, after making some other adjustments.) - glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); + // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. + // (We will be adding that offset to the camera position, after making some other adjustments.) + glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); - // Scale by proportional differences between avatar and human. - float humanEyeSeparationInModelSpace = glm::length(humanLeftEye - humanRightEye); - float avatarEyeSeparation = glm::length(avatarLeftEye - avatarRightEye); - gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; + // Scale by proportional differences between avatar and human. + float humanEyeSeparationInModelSpace = glm::length(humanLeftEye - humanRightEye); + float avatarEyeSeparation = glm::length(avatarLeftEye - avatarRightEye); + gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; - // If the camera is also not oriented with the head, adjust by getting the offset in head-space... - /* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday. - glm::quat avatarHeadOrientation = getHead()->getOrientation(); - glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; - // ... and treat that as though it were in camera space, bringing it back to world space. - // But camera is fudged to make the picture feel like the avatar's orientation. - glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ? - gazeOffset = humanOrientation * gazeOffsetLocalToHead; - glm::vec3 corrected = humanSystem->getPosition() + gazeOffset; - */ + // If the camera is also not oriented with the head, adjust by getting the offset in head-space... + /* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday. + glm::quat avatarHeadOrientation = getHead()->getOrientation(); + glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; + // ... and treat that as though it were in camera space, bringing it back to world space. + // But camera is fudged to make the picture feel like the avatar's orientation. + glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ? + gazeOffset = humanOrientation * gazeOffsetLocalToHead; + glm::vec3 corrected = humanSystem->getPosition() + gazeOffset; + */ - // And now we can finally add that offset to the camera. - glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset; + // And now we can finally add that offset to the camera. + glm::vec3 corrected = qApp->getViewFrustum()->getPosition() + gazeOffset; - avatar->getHead()->setCorrectedLookAtPosition(corrected); + avatar->getHead()->setCorrectedLookAtPosition(corrected); - } else { - avatar->getHead()->clearCorrectedLookAtPosition(); - } } else { avatar->getHead()->clearCorrectedLookAtPosition(); } + } else { + avatar->getHead()->clearCorrectedLookAtPosition(); } - }); + } auto avatarPointer = _lookAtTargetAvatar.lock(); if (avatarPointer) { static_pointer_cast(avatarPointer)->setIsLookAtTarget(true); From a1096510e80dc566ec9be49411099cc11c1584a2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 10:52:01 -0700 Subject: [PATCH 15/28] put some useless consts back --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityItem.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4d5fb1b180..91ea4864df 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1776,7 +1776,7 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { return; } -QByteArray EntityItem::getActionDataInternal() const { +const QByteArray EntityItem::getActionDataInternal() const { if (_actionDataDirty) { bool success; serializeActions(success, _allActionsDataCache); @@ -1787,7 +1787,7 @@ QByteArray EntityItem::getActionDataInternal() const { return _allActionsDataCache; } -QByteArray EntityItem::getActionData() const { +const QByteArray EntityItem::getActionData() const { QByteArray result; assertUnlocked(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 9e6430b4c3..858dc7e326 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -401,7 +401,7 @@ public: bool removeAction(EntitySimulation* simulation, const QUuid& actionID); bool clearActions(EntitySimulation* simulation); void setActionData(QByteArray actionData); - QByteArray getActionData() const; + const QByteArray getActionData() const; bool hasActions() { return !_objectActions.empty(); } QList getActionIDs() { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; @@ -415,7 +415,7 @@ public: protected: - QByteArray getActionDataInternal() const; + const QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); static bool _sendPhysicsUpdates; From 6ae5c540fdeb914ee6538de64f62056ba202ca74 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Oct 2015 11:09:24 -0700 Subject: [PATCH 16/28] SkeletonModel: coding standard fix Replaced glm::vec3(0) with glm::vec3(). --- interface/src/avatar/SkeletonModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c3716aa77a..04be8a1f63 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -224,7 +224,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::EyeParameters eyeParams; eyeParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); eyeParams.eyeLookAt = head->getCorrectedLookAtPosition(); - eyeParams.eyeSaccade = glm::vec3(0); + eyeParams.eyeSaccade = glm::vec3(); eyeParams.modelRotation = getRotation(); eyeParams.modelTranslation = getTranslation(); eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; From 22d6b6df34526da4be267bdafbeeae188c91fdb0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Oct 2015 13:49:52 -0700 Subject: [PATCH 17/28] make withWriteLock and withTryWriteLock const --- libraries/entities/src/EntityItem.cpp | 3 +-- libraries/shared/src/shared/ReadWriteLockable.h | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 91ea4864df..f012ba6eee 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1792,8 +1792,7 @@ const QByteArray EntityItem::getActionData() const { assertUnlocked(); if (_actionDataDirty) { - EntityItem* unconstThis = const_cast(this); - unconstThis->withWriteLock([&] { + withWriteLock([&] { getActionDataInternal(); result = _allActionsDataCache; }); diff --git a/libraries/shared/src/shared/ReadWriteLockable.h b/libraries/shared/src/shared/ReadWriteLockable.h index a7d30d562b..98dff4a841 100644 --- a/libraries/shared/src/shared/ReadWriteLockable.h +++ b/libraries/shared/src/shared/ReadWriteLockable.h @@ -14,7 +14,7 @@ class ReadWriteLockable { public: template - bool withWriteLock(F f, bool require = true) { + bool withWriteLock(F f, bool require = true) const { if (!require) { bool result = _lock.tryLockForWrite(); if (result) { @@ -22,7 +22,7 @@ public: _lock.unlock(); } return result; - } + } QWriteLocker locker(&_lock); f(); @@ -30,7 +30,7 @@ public: } template - bool withTryWriteLock(F f) { + bool withTryWriteLock(F f) const { return withWriteLock(f, false); } From bc0e14cb71275d36459f17f7deb00fdb0bc390b3 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 28 Oct 2015 13:58:44 -0700 Subject: [PATCH 18/28] Don't render avatar's renderBoundingCollisionShapes before the data is there. (Found while trying to repro "Deadlock in AvatarData::nextAttitude() on main thread" https://app.asana.com/0/32622044445063/61023569045356) --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9f4e7ee3cf..00bcf1d271 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -454,7 +454,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { */ bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); - if (renderBounding && shouldRenderHead(renderArgs)) { + if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel.isRenderable()) { _skeletonModel.renderBoundingCollisionShapes(*renderArgs->_batch, 0.7f); } From 6d99a822a3c969993ce1abae47ad08a4c2960cf8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 28 Oct 2015 14:33:50 -0700 Subject: [PATCH 19/28] use a case-insensitive search in allowed editors QStringList --- domain-server/src/DomainGatekeeper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 90b22ffdd8..d360ab4802 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -226,7 +226,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect // if the allowed editors list is empty then everyone can adjust locks bool canAdjustLocks = allowedEditors.empty(); - if (allowedEditors.contains(username)) { + if (allowedEditors.contains(username, Qt::CaseInsensitive)) { // we have a non-empty allowed editors list - check if this user is verified to be in it if (!verifiedUsername) { if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { From 7695afec0af14260393214fbb797a47fd7c540e3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 28 Oct 2015 16:42:17 -0700 Subject: [PATCH 20/28] Fix ScriptEngine crash --- libraries/script-engine/src/ScriptEngine.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 1d6bf32fcc..39f0963112 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -685,9 +685,8 @@ void ScriptEngine::run() { } lastUpdate = now; - if (hadUncauchtExceptions(*this, _fileNameString)) { - stop(); - } + // Debug and clear exceptions + hadUncauchtExceptions(*this, _fileNameString); } stopAllTimers(); // make sure all our timers are stopped if the script is ending From 62e56d3f131443908d05a731a07e6b6472ec9fae Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 28 Oct 2015 16:44:53 -0700 Subject: [PATCH 21/28] Don't go to wrong position on startup/teleport. This fixes one cause of being in the wrong place. https://app.asana.com/0/32622044445063/61787931469907 --- interface/src/avatar/MyAvatar.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f7fad2bd2b..4d860b7acd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -208,6 +208,11 @@ void MyAvatar::update(float deltaTime) { setPosition(_goToPosition); setOrientation(_goToOrientation); _goToPending = false; + // updateFromHMDSensorMatrix (called from paintGL) expects that the sensorToWorldMatrix is updated for any position changes + // that happen between render and Application::update (which calls updateSensorToWorldMatrix to do so). + // However, render/MyAvatar::update/Application::update don't always match (e.g., when using the separate avatar update thread), + // so we update now. It's ok if it updates again in the normal way. + updateSensorToWorldMatrix(); } if (_referential) { From 5acb088c4644d521fa9a66f28e2ecdacdbc4b271 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Oct 2015 16:57:27 -0700 Subject: [PATCH 22/28] FBXReader: More deterministic loading behavior This makes iteration over meshes and connections between them deterministic. [QHash](http://doc.qt.io/qt-5/qhash.html#details) and QMultiHash do not guarantee consistent iteration order. This is problematic for the FBXReader because it could result in different behavior each time a model was loaded. Specifically, This was causing a bug with some avatars that contained multiple-bind poses. The bind pose returned to the application from the FBXReader would be different on different runs. This PR doesn't add support for multiple-bind poses, but it does make the choice of which bind pose is chosen deterministic. This non-determinism was the cause of the Mery avatar having "bug-eyes" 1/12 times. --- libraries/fbx/src/FBXReader.cpp | 115 ++++++++++++++++---------------- libraries/fbx/src/FBXReader.h | 4 +- 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1eda5304e4..d29733f6a3 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -64,7 +64,7 @@ Extents FBXGeometry::getUnscaledMeshExtents() const { glm::vec3 minimum = glm::vec3(offset * glm::vec4(extents.minimum, 1.0f)); glm::vec3 maximum = glm::vec3(offset * glm::vec4(extents.maximum, 1.0f)); Extents scaledExtents = { minimum, maximum }; - + return scaledExtents; } @@ -73,7 +73,7 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const { if (!getUnscaledMeshExtents().containsPoint(point)) { return false; } - + auto checkEachPrimitive = [=](FBXMesh& mesh, QVector indices, int primitiveSize) -> bool { // Check whether the point is "behind" all the primitives. for (int j = 0; j < indices.size(); j += primitiveSize) { @@ -87,11 +87,11 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const { } return true; }; - + // Check that the point is contained in at least one convex mesh. for (auto mesh : meshes) { bool insideMesh = true; - + // To be considered inside a convex mesh, // the point needs to be "behind" all the primitives respective planes. for (auto part : mesh.parts) { @@ -108,7 +108,7 @@ bool FBXGeometry::convexHullContains(const glm::vec3& point) const { return true; } } - + // It wasn't in any mesh, return false. return false; } @@ -194,7 +194,7 @@ public: glm::vec3 rotationMax; // radians }; -glm::mat4 getGlobalTransform(const QMultiHash& _connectionParentMap, +glm::mat4 getGlobalTransform(const QMultiMap& _connectionParentMap, const QHash& models, QString nodeID, bool mixamoHack) { glm::mat4 globalTransform; while (!nodeID.isNull()) { @@ -228,12 +228,12 @@ void printNode(const FBXNode& node, int indentLevel) { int indentLength = 2; QByteArray spaces(indentLevel * indentLength, ' '); QDebug nodeDebug = qDebug(modelformat); - + nodeDebug.nospace() << spaces.data() << node.name.data() << ": "; foreach (const QVariant& property, node.properties) { nodeDebug << property; } - + foreach (const FBXNode& child, node.children) { printNode(child, indentLevel + 1); } @@ -246,7 +246,7 @@ public: glm::mat4 transformLink; }; -void appendModelIDs(const QString& parentID, const QMultiHash& connectionChildMap, +void appendModelIDs(const QString& parentID, const QMultiMap& connectionChildMap, QHash& models, QSet& remainingModels, QVector& modelIDs) { if (remainingModels.contains(parentID)) { modelIDs.append(parentID); @@ -331,7 +331,7 @@ void addBlendshapes(const ExtractedBlendshape& extracted, const QList& connectionParentMap, +QString getTopModelID(const QMultiMap& connectionParentMap, const QHash& models, const QString& modelID) { QString topID = modelID; forever { @@ -342,7 +342,7 @@ QString getTopModelID(const QMultiHash& connectionParentMap, } } return topID; - + outerContinue: ; } } @@ -361,7 +361,7 @@ public: }; bool checkMaterialsHaveTextures(const QHash& materials, - const QHash& textureFilenames, const QMultiHash& _connectionChildMap) { + const QHash& textureFilenames, const QMultiMap& _connectionChildMap) { foreach (const QString& materialID, materials.keys()) { foreach (const QString& childID, _connectionChildMap.values(materialID)) { if (textureFilenames.contains(childID)) { @@ -443,8 +443,8 @@ QByteArray fileOnUrl(const QByteArray& filenameString, const QString& url) { } FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) { - const FBXNode& node = _fbxNode; - QHash meshes; + const FBXNode& node = _fbxNode; + QMap meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; QHash ooChildToParent; @@ -497,7 +497,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QVector humanIKJointIDs(humanIKJointNames.size()); QVariantHash blendshapeMappings = mapping.value("bs").toHash(); - + QMultiHash blendshapeIndices; for (int i = 0;; i++) { QByteArray blendshapeName = FACESHIFT_BLENDSHAPES[i]; @@ -527,7 +527,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QString hifiGlobalNodeID; unsigned int meshIndex = 0; foreach (const FBXNode& child, node.children) { - + if (child.name == "FBXHeaderExtension") { foreach (const FBXNode& object, child.children) { if (object.name == "SceneInfo") { @@ -537,7 +537,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (subsubobject.name == "Author") { geometry.author = subsubobject.properties.at(0).toString(); } - } + } } else if (subobject.name == "Properties70") { foreach (const FBXNode& subsubobject, subobject.children) { if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 && @@ -620,7 +620,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (humanIKJointIndex != -1) { humanIKJointIDs[humanIKJointIndex] = getID(object.properties); } - + glm::vec3 translation; // NOTE: the euler angles as supplied by the FBX file are in degrees glm::vec3 rotationOffset; @@ -709,7 +709,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS // it's a mesh as well as a model mesh = &meshes[getID(object.properties)]; *mesh = extractMesh(object, meshIndex); - + } else if (subobject.name == "Shape") { ExtractedBlendshape blendshape = { subobject.properties.at(0).toString(), extractBlendshape(subobject) }; @@ -720,7 +720,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QString attributetype = subobject.properties.at(0).toString(); if (!attributetype.empty()) { if (attributetype == "Light") { - QString lightprop; + QString lightprop; foreach (const QVariant& vprop, subobject.properties) { lightprop = vprop.toString(); } @@ -731,23 +731,23 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else { QString whatisthat = subobject.name; if (whatisthat == "Shape") { - } + } } #endif } - + // add the blendshapes included in the model, if any if (mesh) { foreach (const ExtractedBlendshape& extracted, blendshapes) { addBlendshapes(extracted, blendshapeIndices.values(extracted.id.toLatin1()), *mesh); } } - + // see FBX documentation, http://download.autodesk.com/us/fbx/20112/FBX_SDK_HELP/index.html model.translation = translation; - model.preTransform = glm::translate(rotationOffset) * glm::translate(rotationPivot); - model.preRotation = glm::quat(glm::radians(preRotation)); + model.preTransform = glm::translate(rotationOffset) * glm::translate(rotationPivot); + model.preRotation = glm::quat(glm::radians(preRotation)); model.rotation = glm::quat(glm::radians(rotation)); model.postRotation = glm::quat(glm::radians(postRotation)); @@ -862,7 +862,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (subobject.name == "RelativeFilename") { filename = subobject.properties.at(0).toByteArray(); filename = fileOnUrl(filename, url); - + } else if (subobject.name == "Content" && !subobject.properties.isEmpty()) { content = subobject.properties.at(0).toByteArray(); } @@ -905,10 +905,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else if (property.properties.at(0) == "Emissive") { material.emissiveColor = getVec3(property.properties, index); - + } else if (property.properties.at(0) == "Shininess") { material.shininess = property.properties.at(index).value(); - + } else if (property.properties.at(0) == "Opacity") { material.opacity = property.properties.at(index).value(); } @@ -1001,7 +1001,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } animationCurves.insert(getID(object.properties), curve); - + } #if defined(DEBUG_FBXREADER) else { @@ -1013,7 +1013,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else { unknown++; } - } + } #endif } } else if (child.name == "Connections") { @@ -1041,14 +1041,14 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("transparentcolor")) { // it should be TransparentColor... - // THis is how Maya assign a texture that affect diffuse color AND transparency ? + // THis is how Maya assign a texture that affect diffuse color AND transparency ? diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("bump")) { bumpTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("normal")) { normalTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("specular") || type.contains("reflection")) { - specularTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + specularTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type == "lcl rotation") { localRotations.insert(getID(connection.properties, 2), getID(connection.properties, 1)); @@ -1097,7 +1097,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else { unknown++; } - } + } #endif } @@ -1142,7 +1142,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } outerBreak: - + // make sure the parent is in the child map QString parent = _connectionParentMap.value(model.key()); if (!_connectionChildMap.contains(parent, model.key())) { @@ -1172,7 +1172,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS frame.translations.resize(modelIDs.size()); geometry.animationFrames.append(frame); } - + // convert the models to joints QVariantList freeJoints = mapping.values("freeJoint"); geometry.hasSkeletonJoints = false; @@ -1181,7 +1181,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS FBXJoint joint; joint.isFree = freeJoints.contains(model.name); joint.parentIndex = model.parentIndex; - + // get the indices of all ancestors starting with the first free one (if any) int jointIndex = geometry.joints.size(); joint.freeLineage.append(jointIndex); @@ -1203,7 +1203,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS joint.rotationMax = model.rotationMax; glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation; if (joint.parentIndex == -1) { - joint.transform = geometry.offset * glm::translate(joint.translation) * joint.preTransform * + joint.transform = geometry.offset * glm::translate(joint.translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; joint.inverseDefaultRotation = glm::inverse(combinedRotation); joint.distanceToParent = 0.0f; @@ -1272,11 +1272,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS geometry.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); geometry.leftToeJointIndex = modelIDs.indexOf(jointLeftToeID); geometry.rightToeJointIndex = modelIDs.indexOf(jointRightToeID); - + foreach (const QString& id, humanIKJointIDs) { geometry.humanIKJointIndices.append(modelIDs.indexOf(id)); } - + // extract the translation component of the neck transform if (geometry.neckJointIndex != -1) { const glm::mat4& transform = geometry.joints.at(geometry.neckJointIndex).transform; @@ -1285,7 +1285,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS geometry.bindExtents.reset(); geometry.meshExtents.reset(); - + // Create the Material Library consolidateFBXMaterials(); geometry.materials = _fbxMaterials; @@ -1293,9 +1293,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS // see if any materials have texture children bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilenames, _connectionChildMap); - for (QHash::iterator it = meshes.begin(); it != meshes.end(); it++) { + for (QMap::iterator it = meshes.begin(); it != meshes.end(); it++) { ExtractedMesh& extracted = it.value(); - + extracted.mesh.meshExtents.reset(); // accumulate local transforms @@ -1335,7 +1335,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } materialIndex++; - + } else if (_textureFilenames.contains(childID)) { FBXTexture texture = getTexture(childID); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { @@ -1360,7 +1360,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS setTangents(extracted.mesh, part.quadIndices.at(i + 2), part.quadIndices.at(i + 3)); setTangents(extracted.mesh, part.quadIndices.at(i + 3), part.quadIndices.at(i)); } - // <= size - 3 in order to prevent overflowing triangleIndices when (i % 3) != 0 + // <= size - 3 in order to prevent overflowing triangleIndices when (i % 3) != 0 // This is most likely evidence of a further problem in extractMesh() for (int i = 0; i <= part.triangleIndices.size() - 3; i += 3) { setTangents(extracted.mesh, part.triangleIndices.at(i), part.triangleIndices.at(i + 1)); @@ -1401,6 +1401,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS joint.bindTransform = cluster.transformLink; joint.bindTransformFoundInCluster = true; + if (fbxCluster.jointIndex == 63) { // Head + qCDebug(modelformat) << "AJT: Head found in cluster, id = " << clusterID; + qCDebug(modelformat) << "AJT: trans = " << extractTranslation(cluster.transformLink); + } + // update the bind pose extents glm::vec3 bindTranslation = extractTranslation(geometry.offset * joint.bindTransform); geometry.bindExtents.addPoint(bindTranslation); @@ -1500,7 +1505,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS glm::vec4& weights = extracted.mesh.clusterWeights[i]; float total = weights.x + weights.y + weights.z + weights.w; if (total != 1.0f && total != 0.0f) { - weights /= total; + weights /= total; } } } else { @@ -1573,7 +1578,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS avgRadius += glm::length(offset - projection * axis); } avgRadius /= (float)points.size(); - + // compute endpoints of capsule in joint-frame glm::vec3 capsuleBegin = avgPoint; glm::vec3 capsuleEnd = avgPoint; @@ -1594,27 +1599,27 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS joint.shapeInfo.radius = avgRadius; } geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString()); - + // Add sitting points QVariantHash sittingPoints = mapping.value("sit").toHash(); for (QVariantHash::const_iterator it = sittingPoints.constBegin(); it != sittingPoints.constEnd(); it++) { SittingPoint sittingPoint; sittingPoint.name = it.key(); - + QVariantList properties = it->toList(); sittingPoint.position = parseVec3(properties.at(0).toString()); sittingPoint.rotation = glm::quat(glm::radians(parseVec3(properties.at(1).toString()))); - + geometry.sittingPoints.append(sittingPoint); } - + // attempt to map any meshes to a named model - for (QHash::const_iterator m = meshIDsToMeshIndices.constBegin(); + for (QHash::const_iterator m = meshIDsToMeshIndices.constBegin(); m != meshIDsToMeshIndices.constEnd(); m++) { - + const QString& meshID = m.key(); int meshIndex = m.value(); - + if (ooChildToParent.contains(meshID)) { const QString& modelID = ooChildToParent.value(meshID); if (modelIDsToNames.contains(modelID)) { @@ -1623,7 +1628,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } } - + return geometryPtr; } @@ -1641,5 +1646,3 @@ FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QStri return reader.extractFBXGeometry(mapping, url); } - - diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 0af7b28136..8014718815 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -413,8 +413,8 @@ public: float _lightmapOffset = 0.0f; float _lightmapLevel; - QMultiHash _connectionParentMap; - QMultiHash _connectionChildMap; + QMultiMap _connectionParentMap; + QMultiMap _connectionChildMap; static glm::vec3 getVec3(const QVariantList& properties, int index); static QVector createVec4Vector(const QVector& doubleVector); From 136747929e76cf2e449b13f3e29e3bab75b78bba Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 28 Oct 2015 17:11:46 -0700 Subject: [PATCH 23/28] Fix typo --- libraries/script-engine/src/ScriptEngine.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 39f0963112..b416b58910 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -96,7 +96,7 @@ static bool hasCorrectSyntax(const QScriptProgram& program) { return true; } -static bool hadUncauchtExceptions(QScriptEngine& engine, const QString& fileName) { +static bool hadUncaughtExceptions(QScriptEngine& engine, const QString& fileName) { if (engine.hasUncaughtException()) { const auto backtrace = engine.uncaughtExceptionBacktrace(); const auto exception = engine.uncaughtException().toString(); @@ -616,7 +616,7 @@ QScriptValue ScriptEngine::evaluate(const QString& sourceCode, const QString& fi const auto result = QScriptEngine::evaluate(program); --_evaluatesPending; - const auto hadUncaughtException = hadUncauchtExceptions(*this, program.fileName()); + const auto hadUncaughtException = hadUncaughtExceptions(*this, program.fileName()); if (_wantSignals) { emit evaluationFinished(result, hadUncaughtException); } @@ -686,7 +686,7 @@ void ScriptEngine::run() { lastUpdate = now; // Debug and clear exceptions - hadUncauchtExceptions(*this, _fileNameString); + hadUncaughtExceptions(*this, _fileNameString); } stopAllTimers(); // make sure all our timers are stopped if the script is ending @@ -1021,7 +1021,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co QScriptEngine sandbox; QScriptValue testConstructor = sandbox.evaluate(program); - if (hadUncauchtExceptions(sandbox, program.fileName())) { + if (hadUncaughtExceptions(sandbox, program.fileName())) { return; } From 4cb5ccab90f3df912f2091c167edf9a79881c4ce Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Oct 2015 13:18:27 +1300 Subject: [PATCH 24/28] Fix audio stats dialog not being sized properly --- interface/src/ui/AudioStatsDialog.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/AudioStatsDialog.cpp b/interface/src/ui/AudioStatsDialog.cpp index e57182e251..a475700e02 100644 --- a/interface/src/ui/AudioStatsDialog.cpp +++ b/interface/src/ui/AudioStatsDialog.cpp @@ -65,11 +65,12 @@ AudioStatsDialog::AudioStatsDialog(QWidget* parent) : // Get statistics from the Audio Client _stats = &DependencyManager::get()->getStats(); - // Create layouter + // Create layout _form = new QFormLayout(); + _form->setSizeConstraint(QLayout::SetFixedSize); QDialog::setLayout(_form); - // Load and initilize all channels + // Load and initialize all channels renderStats(); _audioDisplayChannels = QVector>(1); @@ -80,10 +81,8 @@ AudioStatsDialog::AudioStatsDialog(QWidget* parent) : _downstreamID = addChannel(_form, _downstreamStats, COLOR3); _upstreamInjectedID = addChannel(_form, _upstreamInjectedStats, COLOR0); - connect(averageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateTimerTimeout())); averageUpdateTimer->start(1000); - } int AudioStatsDialog::addChannel(QFormLayout* form, QVector& stats, const unsigned color) { @@ -243,7 +242,6 @@ void AudioStatsDialog::paintEvent(QPaintEvent* event) { } QDialog::paintEvent(event); - setFixedSize(width(), height()); } void AudioStatsDialog::reject() { From 568e5536b8e8f3b3554b6476bfd886389778be95 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Oct 2015 13:18:43 +1300 Subject: [PATCH 25/28] Control bandwidth stats dialog sizing similarly --- interface/src/ui/BandwidthDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/BandwidthDialog.cpp b/interface/src/ui/BandwidthDialog.cpp index e086005783..f07c844894 100644 --- a/interface/src/ui/BandwidthDialog.cpp +++ b/interface/src/ui/BandwidthDialog.cpp @@ -72,8 +72,9 @@ BandwidthDialog::BandwidthDialog(QWidget* parent) : this->setWindowTitle("Bandwidth Details"); - // Create layouter + // Create layout QFormLayout* form = new QFormLayout(); + form->setSizeConstraint(QLayout::SetFixedSize); this->QDialog::setLayout(form); QSharedPointer bandwidthRecorder = DependencyManager::get(); @@ -118,7 +119,6 @@ void BandwidthDialog::paintEvent(QPaintEvent* event) { for (unsigned int i=0; i<_CHANNELCOUNT; i++) _allChannelDisplays[i]->paint(); this->QDialog::paintEvent(event); - this->setFixedSize(this->width(), this->height()); } void BandwidthDialog::reject() { From 7367f2a28cd375a064141c586403dc4514998c27 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Oct 2015 17:55:06 -0700 Subject: [PATCH 26/28] FBXReader: remove debugging logs --- libraries/fbx/src/FBXReader.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index d29733f6a3..f9bb089a9c 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1401,11 +1401,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS joint.bindTransform = cluster.transformLink; joint.bindTransformFoundInCluster = true; - if (fbxCluster.jointIndex == 63) { // Head - qCDebug(modelformat) << "AJT: Head found in cluster, id = " << clusterID; - qCDebug(modelformat) << "AJT: trans = " << extractTranslation(cluster.transformLink); - } - // update the bind pose extents glm::vec3 bindTranslation = extractTranslation(geometry.offset * joint.bindTransform); geometry.bindExtents.addPoint(bindTranslation); From 5e73af927237cc285337338e8efd4f5e354ffe52 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Oct 2015 18:10:41 -0700 Subject: [PATCH 27/28] Rig: Removed dt from updateFromEyeParameters() --- interface/src/avatar/SkeletonModel.cpp | 4 ++-- libraries/animation/src/Rig.cpp | 2 +- libraries/animation/src/Rig.h | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 04be8a1f63..71422f6780 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -194,7 +194,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex; - _rig->updateFromEyeParameters(eyeParams, deltaTime); + _rig->updateFromEyeParameters(eyeParams); // rebuild the jointState transform for the eyes only _rig->updateJointState(eyeParams.leftEyeJointIndex, parentTransform); @@ -229,7 +229,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { eyeParams.modelTranslation = getTranslation(); eyeParams.leftEyeJointIndex = geometry.leftEyeJointIndex; eyeParams.rightEyeJointIndex = geometry.rightEyeJointIndex; - _rig->updateFromEyeParameters(eyeParams, deltaTime); + _rig->updateFromEyeParameters(eyeParams); } } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8c7fa22c22..3fe4c2e83e 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -960,7 +960,7 @@ void Rig::updateFromHeadParameters(const HeadParameters& params, float dt) { } } -void Rig::updateFromEyeParameters(const EyeParameters& params, float dt) { +void Rig::updateFromEyeParameters(const EyeParameters& params) { updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 25e823d6bc..6e0a88d768 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -187,8 +187,7 @@ public: bool getEnableAnimGraph() const { return _enableAnimGraph; } void updateFromHeadParameters(const HeadParameters& params, float dt); - void updateFromEyeParameters(const EyeParameters& params, float dt); - + void updateFromEyeParameters(const EyeParameters& params); void updateFromHandParameters(const HandParameters& params, float dt); virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, From 8c395209e8a73d7822be28aeb8ee33bebb84aa0d Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 28 Oct 2015 21:23:35 -0700 Subject: [PATCH 28/28] Fix Developer->Avatar->Draw Mesh MyAvatar::setEnableMeshVisible -> Model::setVisibleInScene sets a flag that no one was looking at any more. --- libraries/render-utils/src/MeshPartPayload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 30b72891dd..44acb61a52 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -229,7 +229,7 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); - if (!model->_readyWhenAdded) { + if (!model->_readyWhenAdded || !model->_isVisible) { return; // bail asap }