Merge branch 'master' of https://github.com/highfidelity/hifi into brown

This commit is contained in:
Sam Gateau 2017-05-18 13:08:35 -07:00
commit a9fcdce95a
6 changed files with 47 additions and 55 deletions

View file

@ -402,7 +402,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity); AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
bool identityChanged = false; bool identityChanged = false;
bool displayNameChanged = false; bool displayNameChanged = false;
avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged, senderNode->getClockSkewUsec()); avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged);
if (identityChanged) { if (identityChanged) {
QMutexLocker nodeDataLocker(&nodeData->getMutex()); QMutexLocker nodeDataLocker(&nodeData->getMutex());
nodeData->flagIdentityChange(); nodeData->flagIdentityChange();
@ -665,12 +665,12 @@ void AvatarMixer::sendStatsPacket() {
void AvatarMixer::run() { void AvatarMixer::run() {
qCDebug(avatars) << "Waiting for connection to domain to request settings from domain-server."; qCDebug(avatars) << "Waiting for connection to domain to request settings from domain-server.";
// wait until we have the domain-server settings, otherwise we bail // wait until we have the domain-server settings, otherwise we bail
DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler(); DomainHandler& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
connect(&domainHandler, &DomainHandler::settingsReceived, this, &AvatarMixer::domainSettingsRequestComplete); connect(&domainHandler, &DomainHandler::settingsReceived, this, &AvatarMixer::domainSettingsRequestComplete);
connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AvatarMixer::domainSettingsRequestFailed); connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AvatarMixer::domainSettingsRequestFailed);
ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer);
} }
@ -695,7 +695,7 @@ void AvatarMixer::domainSettingsRequestComplete() {
// parse the settings to pull out the values we need // parse the settings to pull out the values we need
parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject());
// start our tight loop... // start our tight loop...
start(); start();
} }
@ -745,7 +745,7 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
} else { } else {
qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _slavePool.numThreads() << "threads."; qCDebug(avatars) << "Avatar mixer will automatically determine number of threads to use. Using:" << _slavePool.numThreads() << "threads.";
} }
const QString AVATARS_SETTINGS_KEY = "avatars"; const QString AVATARS_SETTINGS_KEY = "avatars";
static const QString MIN_SCALE_OPTION = "min_avatar_scale"; static const QString MIN_SCALE_OPTION = "min_avatar_scale";

View file

@ -172,13 +172,13 @@ QByteArray AvatarData::toByteArrayStateful(AvatarDataDetail dataDetail) {
AvatarDataPacket::HasFlags hasFlagsOut; AvatarDataPacket::HasFlags hasFlagsOut;
auto lastSentTime = _lastToByteArray; auto lastSentTime = _lastToByteArray;
_lastToByteArray = usecTimestampNow(); _lastToByteArray = usecTimestampNow();
return AvatarData::toByteArray(dataDetail, lastSentTime, getLastSentJointData(), return AvatarData::toByteArray(dataDetail, lastSentTime, getLastSentJointData(),
hasFlagsOut, false, false, glm::vec3(0), nullptr, hasFlagsOut, false, false, glm::vec3(0), nullptr,
&_outboundDataRate); &_outboundDataRate);
} }
QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime, const QVector<JointData>& lastSentJointData, QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime, const QVector<JointData>& lastSentJointData,
AvatarDataPacket::HasFlags& hasFlagsOut, bool dropFaceTracking, bool distanceAdjust, AvatarDataPacket::HasFlags& hasFlagsOut, bool dropFaceTracking, bool distanceAdjust,
glm::vec3 viewerPosition, QVector<JointData>* sentJointDataOut, AvatarDataRate* outboundDataRateOut) const { glm::vec3 viewerPosition, QVector<JointData>* sentJointDataOut, AvatarDataRate* outboundDataRateOut) const {
bool cullSmallChanges = (dataDetail == CullSmallData); bool cullSmallChanges = (dataDetail == CullSmallData);
@ -201,7 +201,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
// FIXME - // FIXME -
// //
// BUG -- if you enter a space bubble, and then back away, the avatar has wrong orientation until "send all" happens... // BUG -- if you enter a space bubble, and then back away, the avatar has wrong orientation until "send all" happens...
// this is an iFrame issue... what to do about that? // this is an iFrame issue... what to do about that?
// //
// BUG -- Resizing avatar seems to "take too long"... the avatar doesn't redraw at smaller size right away // BUG -- Resizing avatar seems to "take too long"... the avatar doesn't redraw at smaller size right away
@ -1473,13 +1473,13 @@ QStringList AvatarData::getJointNames() const {
void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut) { void AvatarData::parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut) {
QDataStream packetStream(data); QDataStream packetStream(data);
packetStream >> identityOut.uuid packetStream >> identityOut.uuid
>> identityOut.skeletonModelURL >> identityOut.skeletonModelURL
>> identityOut.attachmentData >> identityOut.attachmentData
>> identityOut.displayName >> identityOut.displayName
>> identityOut.sessionDisplayName >> identityOut.sessionDisplayName
>> identityOut.avatarEntityData >> identityOut.avatarEntityData
>> identityOut.updatedAt; >> identityOut.sequenceId;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qCDebug(avatars) << __FUNCTION__ qCDebug(avatars) << __FUNCTION__
@ -1501,21 +1501,15 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL; return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
} }
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) { void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged) {
quint64 identityPacketUpdatedAt = identity.updatedAt;
if (identityPacketUpdatedAt <= (uint64_t)(abs(clockSkew))) { // Incoming timestamp is bad - compute our own timestamp if (identity.sequenceId < _identitySequenceId) {
identityPacketUpdatedAt = usecTimestampNow() + clockSkew; qCDebug(avatars) << "Ignoring older identity packet for avatar" << getSessionUUID()
} << "_identitySequenceId (" << _identitySequenceId << ") is greater than" << identity.sequenceId;
// Consider the case where this packet is being processed on Client A, and Client A is connected to Sandbox B.
// If Client A's system clock is *ahead of* Sandbox B's system clock, "clockSkew" will be *negative*.
// If Client A's system clock is *behind* Sandbox B's system clock, "clockSkew" will be *positive*.
if ((_identityUpdatedAt > identityPacketUpdatedAt - clockSkew) && (_identityUpdatedAt != 0)) {
qCDebug(avatars) << "Ignoring late identity packet for avatar " << getSessionUUID()
<< "_identityUpdatedAt (" << _identityUpdatedAt << ") is greater than identityPacketUpdatedAt - clockSkew (" << identityPacketUpdatedAt << "-" << clockSkew << ")";
return; return;
} }
// otherwise, set the identitySequenceId to match the incoming identity
_identitySequenceId = identity.sequenceId;
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) { if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) {
setSkeletonModelURL(identity.skeletonModelURL); setSkeletonModelURL(identity.skeletonModelURL);
@ -1547,9 +1541,6 @@ void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityC
identityChanged = true; identityChanged = true;
} }
// use the timestamp from this identity, since we want to honor the updated times in "server clock"
// this will overwrite any changes we made locally to this AvatarData's _identityUpdatedAt
_identityUpdatedAt = identityPacketUpdatedAt - clockSkew;
} }
QByteArray AvatarData::identityByteArray() const { QByteArray AvatarData::identityByteArray() const {
@ -1558,13 +1549,13 @@ QByteArray AvatarData::identityByteArray() const {
const QUrl& urlToSend = cannonicalSkeletonModelURL(emptyURL); // depends on _skeletonModelURL const QUrl& urlToSend = cannonicalSkeletonModelURL(emptyURL); // depends on _skeletonModelURL
_avatarEntitiesLock.withReadLock([&] { _avatarEntitiesLock.withReadLock([&] {
identityStream << getSessionUUID() identityStream << getSessionUUID()
<< urlToSend << urlToSend
<< _attachmentData << _attachmentData
<< _displayName << _displayName
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName << getSessionDisplayNameForTransport() // depends on _sessionDisplayName
<< _avatarEntityData << _avatarEntityData
<< _identityUpdatedAt; << _identitySequenceId;
}); });
return identityData; return identityData;
@ -2477,11 +2468,11 @@ QScriptValue AvatarEntityMapToScriptValue(QScriptEngine* engine, const AvatarEnt
if (!jsonEntityProperties.isObject()) { if (!jsonEntityProperties.isObject()) {
qCDebug(avatars) << "bad AvatarEntityData in AvatarEntityMap" << QString(entityProperties.toHex()); qCDebug(avatars) << "bad AvatarEntityData in AvatarEntityMap" << QString(entityProperties.toHex());
} }
QVariant variantEntityProperties = jsonEntityProperties.toVariant(); QVariant variantEntityProperties = jsonEntityProperties.toVariant();
QVariantMap entityPropertiesMap = variantEntityProperties.toMap(); QVariantMap entityPropertiesMap = variantEntityProperties.toMap();
QScriptValue scriptEntityProperties = variantMapToScriptValue(entityPropertiesMap, *engine); QScriptValue scriptEntityProperties = variantMapToScriptValue(entityPropertiesMap, *engine);
QString key = entityID.toString(); QString key = entityID.toString();
obj.setProperty(key, scriptEntityProperties); obj.setProperty(key, scriptEntityProperties);
} }
@ -2493,12 +2484,12 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap&
while (itr.hasNext()) { while (itr.hasNext()) {
itr.next(); itr.next();
QUuid EntityID = QUuid(itr.name()); QUuid EntityID = QUuid(itr.name());
QScriptValue scriptEntityProperties = itr.value(); QScriptValue scriptEntityProperties = itr.value();
QVariant variantEntityProperties = scriptEntityProperties.toVariant(); QVariant variantEntityProperties = scriptEntityProperties.toVariant();
QJsonDocument jsonEntityProperties = QJsonDocument::fromVariant(variantEntityProperties); QJsonDocument jsonEntityProperties = QJsonDocument::fromVariant(variantEntityProperties);
QByteArray binaryEntityProperties = jsonEntityProperties.toBinaryData(); QByteArray binaryEntityProperties = jsonEntityProperties.toBinaryData();
value[EntityID] = binaryEntityProperties; value[EntityID] = binaryEntityProperties;
} }
} }

View file

@ -165,15 +165,15 @@ namespace AvatarDataPacket {
const size_t AVATAR_ORIENTATION_SIZE = 6; const size_t AVATAR_ORIENTATION_SIZE = 6;
PACKED_BEGIN struct AvatarScale { PACKED_BEGIN struct AvatarScale {
SmallFloat scale; // avatar's scale, compressed by packFloatRatioToTwoByte() SmallFloat scale; // avatar's scale, compressed by packFloatRatioToTwoByte()
} PACKED_END; } PACKED_END;
const size_t AVATAR_SCALE_SIZE = 2; const size_t AVATAR_SCALE_SIZE = 2;
PACKED_BEGIN struct LookAtPosition { PACKED_BEGIN struct LookAtPosition {
float lookAtPosition[3]; // world space position that eyes are focusing on. float lookAtPosition[3]; // world space position that eyes are focusing on.
// FIXME - unless the person has an eye tracker, this is simulated... // FIXME - unless the person has an eye tracker, this is simulated...
// a) maybe we can just have the client calculate this // a) maybe we can just have the client calculate this
// b) at distance this will be hard to discern and can likely be // b) at distance this will be hard to discern and can likely be
// descimated or dropped completely // descimated or dropped completely
// //
// POTENTIAL SAVINGS - 12 bytes // POTENTIAL SAVINGS - 12 bytes
@ -376,10 +376,10 @@ public:
glm::vec3 getHandPosition() const; glm::vec3 getHandPosition() const;
void setHandPosition(const glm::vec3& handPosition); void setHandPosition(const glm::vec3& handPosition);
typedef enum { typedef enum {
NoData, NoData,
PALMinimum, PALMinimum,
MinimumData, MinimumData,
CullSmallData, CullSmallData,
IncludeSmallData, IncludeSmallData,
SendAllData SendAllData
@ -388,7 +388,7 @@ public:
virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail); virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail);
virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime, const QVector<JointData>& lastSentJointData, virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime, const QVector<JointData>& lastSentJointData,
AvatarDataPacket::HasFlags& hasFlagsOut, bool dropFaceTracking, bool distanceAdjust, glm::vec3 viewerPosition, AvatarDataPacket::HasFlags& hasFlagsOut, bool dropFaceTracking, bool distanceAdjust, glm::vec3 viewerPosition,
QVector<JointData>* sentJointDataOut, AvatarDataRate* outboundDataRateOut = nullptr) const; QVector<JointData>* sentJointDataOut, AvatarDataRate* outboundDataRateOut = nullptr) const;
virtual void doneEncoding(bool cullSmallChanges); virtual void doneEncoding(bool cullSmallChanges);
@ -417,23 +417,23 @@ public:
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time. void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
virtual void updateAttitude() {} // Tell skeleton mesh about changes virtual void updateAttitude() {} // Tell skeleton mesh about changes
glm::quat getHeadOrientation() const { glm::quat getHeadOrientation() const {
lazyInitHeadData(); lazyInitHeadData();
return _headData->getOrientation(); return _headData->getOrientation();
} }
void setHeadOrientation(const glm::quat& orientation) { void setHeadOrientation(const glm::quat& orientation) {
if (_headData) { if (_headData) {
_headData->setOrientation(orientation); _headData->setOrientation(orientation);
} }
} }
void setLookAtPosition(const glm::vec3& lookAtPosition) { void setLookAtPosition(const glm::vec3& lookAtPosition) {
if (_headData) { if (_headData) {
_headData->setLookAtPosition(lookAtPosition); _headData->setLookAtPosition(lookAtPosition);
} }
} }
void setBlendshapeCoefficients(const QVector<float>& blendshapeCoefficients) { void setBlendshapeCoefficients(const QVector<float>& blendshapeCoefficients) {
if (_headData) { if (_headData) {
_headData->setBlendshapeCoefficients(blendshapeCoefficients); _headData->setBlendshapeCoefficients(blendshapeCoefficients);
} }
@ -470,7 +470,7 @@ public:
void setDomainMinimumScale(float domainMinimumScale) void setDomainMinimumScale(float domainMinimumScale)
{ _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); } { _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); }
void setDomainMaximumScale(float domainMaximumScale) void setDomainMaximumScale(float domainMaximumScale)
{ _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); } { _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); }
// Hand State // Hand State
@ -531,14 +531,14 @@ public:
QString displayName; QString displayName;
QString sessionDisplayName; QString sessionDisplayName;
AvatarEntityMap avatarEntityData; AvatarEntityMap avatarEntityData;
quint64 updatedAt; quint64 sequenceId;
}; };
static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut); static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut);
// identityChanged returns true if identity has changed, false otherwise. // identityChanged returns true if identity has changed, false otherwise.
// displayNameChanged returns true if displayName has changed, false otherwise. // displayNameChanged returns true if displayName has changed, false otherwise.
void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew); void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged);
QByteArray identityByteArray() const; QByteArray identityByteArray() const;
@ -548,8 +548,8 @@ public:
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setDisplayName(const QString& displayName); virtual void setDisplayName(const QString& displayName);
virtual void setSessionDisplayName(const QString& sessionDisplayName) { virtual void setSessionDisplayName(const QString& sessionDisplayName) {
_sessionDisplayName = sessionDisplayName; _sessionDisplayName = sessionDisplayName;
markIdentityDataChanged(); markIdentityDataChanged();
} }
@ -626,7 +626,7 @@ public:
bool getIdentityDataChanged() const { return _identityDataChanged; } // has the identity data changed since the last time sendIdentityPacket() was called bool getIdentityDataChanged() const { return _identityDataChanged; } // has the identity data changed since the last time sendIdentityPacket() was called
void markIdentityDataChanged() { void markIdentityDataChanged() {
_identityDataChanged = true; _identityDataChanged = true;
_identityUpdatedAt = usecTimestampNow(); _identitySequenceId++;
} }
float getDensity() const { return _density; } float getDensity() const { return _density; }
@ -786,7 +786,7 @@ protected:
float _audioAverageLoudness { 0.0f }; float _audioAverageLoudness { 0.0f };
bool _identityDataChanged { false }; bool _identityDataChanged { false };
quint64 _identityUpdatedAt { 0 }; quint64 _identitySequenceId { 0 };
float _density; float _density;
private: private:

View file

@ -149,7 +149,7 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
bool identityChanged = false; bool identityChanged = false;
bool displayNameChanged = false; bool displayNameChanged = false;
// In this case, the "sendingNode" is the Avatar Mixer. // In this case, the "sendingNode" is the Avatar Mixer.
avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged, sendingNode->getClockSkewUsec()); avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged);
} }
} }

View file

@ -56,7 +56,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::AvatarData: case PacketType::AvatarData:
case PacketType::BulkAvatarData: case PacketType::BulkAvatarData:
case PacketType::KillAvatar: case PacketType::KillAvatar:
return static_cast<PacketVersion>(AvatarMixerPacketVersion::IdentityPacketsIncludeUpdateTime); return static_cast<PacketVersion>(AvatarMixerPacketVersion::AvatarIdentitySequenceId);
case PacketType::MessagesData: case PacketType::MessagesData:
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData); return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
case PacketType::ICEServerHeartbeat: case PacketType::ICEServerHeartbeat:

View file

@ -234,7 +234,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
VariableAvatarData, VariableAvatarData,
AvatarAsChildFixes, AvatarAsChildFixes,
StickAndBallDefaultAvatar, StickAndBallDefaultAvatar,
IdentityPacketsIncludeUpdateTime IdentityPacketsIncludeUpdateTime,
AvatarIdentitySequenceId
}; };
enum class DomainConnectRequestVersion : PacketVersion { enum class DomainConnectRequestVersion : PacketVersion {