mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Switch from timestamp to sequence id for avatar identity
This commit is contained in:
parent
039fdc821f
commit
689a0b5bad
3 changed files with 38 additions and 46 deletions
|
@ -170,13 +170,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);
|
||||||
|
@ -199,7 +199,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
|
||||||
|
@ -1471,13 +1471,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__
|
||||||
|
@ -1500,20 +1500,14 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) {
|
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, const qint64 clockSkew) {
|
||||||
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);
|
||||||
|
@ -1545,9 +1539,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 {
|
||||||
|
@ -1556,13 +1547,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,7 +531,7 @@ 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);
|
||||||
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -784,7 +784,7 @@ protected:
|
||||||
float _audioAverageLoudness { 0.0f };
|
float _audioAverageLoudness { 0.0f };
|
||||||
|
|
||||||
bool _identityDataChanged { false };
|
bool _identityDataChanged { false };
|
||||||
quint64 _identityUpdatedAt { 0 };
|
quint64 _identitySequenceId { 0 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue