From 73bfc069da0baa0a21fe6f2d0269b4fc39245c9a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 27 Dec 2016 17:19:55 -0800 Subject: [PATCH] more work on only sending changes --- assignment-client/src/avatars/AvatarMixer.cpp | 4 +- .../src/avatars/AvatarMixerClientData.h | 13 ++ interface/src/Application.cpp | 1 + interface/src/avatar/MyAvatar.cpp | 6 +- interface/src/avatar/MyAvatar.h | 2 +- libraries/avatars/src/AvatarData.cpp | 144 ++++++++++-------- libraries/avatars/src/AvatarData.h | 52 +++---- libraries/avatars/src/HeadData.h | 22 ++- libraries/shared/src/SpatiallyNestable.cpp | 22 ++- libraries/shared/src/SpatiallyNestable.h | 7 + 10 files changed, 174 insertions(+), 99 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f052bb3a53..bdd5db9559 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -400,7 +400,9 @@ void AvatarMixer::broadcastAvatarData() { numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122()); //qDebug() << "about to write data for:" << otherNode->getUUID(); - numAvatarDataBytes += avatarPacketList->write(otherAvatar.toByteArray(detail)); + quint64 lastEncodeForOther = nodeData->getLastOtherAvatarEncodeTime(otherNode->getUUID()); + qDebug() << "about to write data for:" << otherNode->getUUID() << "last encoded at:" << lastEncodeForOther; + numAvatarDataBytes += avatarPacketList->write(otherAvatar.toByteArray(detail, lastEncodeForOther)); avatarPacketList->endSegment(); }); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 78a30d8206..3231a7c944 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -102,6 +102,15 @@ public: const QString& getBaseDisplayName() { return _baseDisplayName; } void setBaseDisplayName(const QString& baseDisplayName) { _baseDisplayName = baseDisplayName; } + quint64 getLastOtherAvatarEncodeTime(QUuid otherAvatar) { + quint64 result = 0; + if (_lastOtherAvatarEncodeTime.find(otherAvatar) != _lastOtherAvatarEncodeTime.end()) { + result = _lastOtherAvatarEncodeTime[otherAvatar]; + } + _lastOtherAvatarEncodeTime[otherAvatar] = usecTimestampNow(); + return result; + } + private: AvatarSharedPointer _avatar { new AvatarData() }; @@ -109,6 +118,10 @@ private: std::unordered_map _lastBroadcastSequenceNumbers; std::unordered_set _hasReceivedFirstPacketsFrom; + // this is a map of the last time we encoded an "other" avatar for + // sending to "this" node + std::unordered_map _lastOtherAvatarEncodeTime; + HRCTime _identityChangeTimestamp; bool _gotIdentity { false }; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b4b0ad10bb..96e9f2f498 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5068,6 +5068,7 @@ void Application::nodeAdded(SharedNodePointer node) const { if (node->getType() == NodeType::AvatarMixer) { // new avatar mixer, send off our identity packet right away getMyAvatar()->sendIdentityPacket(); + getMyAvatar()->resetLastSent(); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index eebcee8e4c..40cc46b272 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -226,7 +226,7 @@ void MyAvatar::simulateAttachments(float deltaTime) { // don't update attachments here, do it in harvestResultsFromPhysicsSimulation() } -QByteArray MyAvatar::toByteArray(AvatarDataDetail dataDetail) { +QByteArray MyAvatar::toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime) { CameraMode mode = qApp->getCamera()->getMode(); _globalPosition = getPosition(); _globalBoundingBoxCorner.x = _characterController.getCapsuleRadius(); @@ -237,12 +237,12 @@ QByteArray MyAvatar::toByteArray(AvatarDataDetail dataDetail) { // fake the avatar position that is sent up to the AvatarMixer glm::vec3 oldPosition = getPosition(); setPosition(getSkeletonPosition()); - QByteArray array = AvatarData::toByteArray(dataDetail); + QByteArray array = AvatarData::toByteArray(dataDetail, lastSentTime); // copy the correct position back setPosition(oldPosition); return array; } - return AvatarData::toByteArray(dataDetail); + return AvatarData::toByteArray(dataDetail, lastSentTime); } void MyAvatar::centerBody() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0e5ce0fe7b..68e65faad7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -333,7 +333,7 @@ private: glm::vec3 getWorldBodyPosition() const; glm::quat getWorldBodyOrientation() const; - QByteArray toByteArray(AvatarDataDetail dataDetail) override; + QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime) override; void simulate(float deltaTime); void updateFromTrackers(float deltaTime); virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ca16854bd8..450c53a329 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -132,6 +132,7 @@ float AvatarData::getTargetScale() const { void AvatarData::setTargetScale(float targetScale) { _targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); + _scaleChanged = usecTimestampNow(); } void AvatarData::setTargetScaleVerbose(float targetScale) { @@ -159,48 +160,47 @@ void AvatarData::lazyInitHeadData() { } -bool AvatarData::avatarLocalPositionChanged() { - return _lastSentLocalPosition != getLocalPosition(); +bool AvatarData::avatarDimensionsChangedSince(quint64 time) { + return _avatarDimensionsChanged >= time; } -bool AvatarData::avatarDimensionsChanged() { - auto avatarDimensions = getPosition() - _globalBoundingBoxCorner; - return _lastSentAvatarDimensions != avatarDimensions; +bool AvatarData::avatarScaleChangedSince(quint64 time) { + return _avatarScaleChanged >= time; } -bool AvatarData::avatarOrientationChanged() { - return _lastSentLocalOrientation != getLocalOrientation(); +bool AvatarData::lookAtPositionChangedSince(quint64 time) { + return _headData->lookAtPositionChangedSince(time); } -bool AvatarData::avatarScaleChanged() { - return _lastSentScale != getDomainLimitedScale(); +bool AvatarData::audioLoudnessChangedSince(quint64 time) { + return _headData->audioLoudnessChangedSince(time); } -bool AvatarData::lookAtPositionChanged() { - return _lastSentLookAt != _headData->_lookAtPosition; +bool AvatarData::sensorToWorldMatrixChangedSince(quint64 time) { + return _sensorToWorldMatrixChanged >= time; } -bool AvatarData::audioLoudnessChanged() { - return _lastSentAudioLoudness != glm::min(_headData->_audioLoudness, MAX_AUDIO_LOUDNESS); -} - -bool AvatarData::sensorToWorldMatrixChanged() { - return _lastSentSensorToWorldMatrix != getSensorToWorldMatrix(); -} - -bool AvatarData::additionalFlagsChanged() { +bool AvatarData::additionalFlagsChangedSince(quint64 time) { return true; // FIXME! } -bool AvatarData::parentInfoChanged() { - return (_lastSentParentID != getParentID()) || (_lastSentParentJointIndex != _parentJointIndex); +bool AvatarData::parentInfoChangedSince(quint64 time) { + return _parentChanged >= time; } -bool AvatarData::faceTrackerInfoChanged() { +bool AvatarData::faceTrackerInfoChangedSince(quint64 time) { return true; // FIXME! } -QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { +QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime) { + + // if no timestamp was included, then assume the avatarData is single instance + // and is tracking its own last encoding time. + if (lastSentTime == 0) { + lastSentTime = _lastToByteArray; + _lastToByteArray = usecTimestampNow(); + } + bool cullSmallChanges = (dataDetail == CullSmallData); bool sendAll = (dataDetail == SendAllData); bool sendMinimum = (dataDetail == MinimumData); @@ -261,18 +261,25 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { // the others will be partial. // we need some way of keeping track of what was sent the last time. + // AvatarDataRegulator + // .lastSent = time + // + // hasAvatarGlobalPosition = (globalPositionChanged > lastSent) + // hasAvatarLocalPosition = (localPositionChanged > lastSent) + // ... bool hasAvatarGlobalPosition = true; // always include global position - bool hasAvatarLocalPosition = sendAll || avatarLocalPositionChanged(); - bool hasAvatarDimensions = sendAll || avatarDimensionsChanged(); - bool hasAvatarOrientation = sendAll || avatarOrientationChanged(); - bool hasAvatarScale = sendAll || avatarScaleChanged(); - bool hasLookAtPosition = sendAll || lookAtPositionChanged(); - bool hasAudioLoudness = sendAll || audioLoudnessChanged(); - bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChanged(); - bool hasAdditionalFlags = sendAll || additionalFlagsChanged(); - bool hasParentInfo = hasParent() && (sendAll || parentInfoChanged()); - bool hasFaceTrackerInfo = hasFaceTracker() && (sendAll || faceTrackerInfoChanged()); + bool hasAvatarLocalPosition = sendAll || tranlationChangedSince(lastSentTime); + bool hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime); + + bool hasAvatarDimensions = sendAll || avatarDimensionsChangedSince(lastSentTime); + bool hasAvatarScale = sendAll || avatarScaleChangedSince(lastSentTime); + bool hasLookAtPosition = sendAll || lookAtPositionChangedSince(lastSentTime); + bool hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime); + bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime); + bool hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime); + bool hasParentInfo = hasParent() && (sendAll || parentInfoChangedSince(lastSentTime)); + bool hasFaceTrackerInfo = hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime)); bool hasJointData = sendAll || !sendMinimum; //qDebug() << __FUNCTION__ << "sendAll:" << sendAll; @@ -294,7 +301,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { | (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0) | (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 0); - qDebug() << __FUNCTION__ << "packetStateFlags:" << packetStateFlags; + qDebug() << __FUNCTION__ << "packetStateFlags:" << packetStateFlags << "lastSentTime:" << lastSentTime; + qDebug() << "..." << "tranlationChangedSince():" << tranlationChangedSince(lastSentTime); + qDebug() << "..." << "rotationChangedSince():" << rotationChangedSince(lastSentTime); + qDebug() << "..." << "lookAtPositionChangedSince():" << lookAtPositionChangedSince(lastSentTime); + qDebug() << "..." << "audioLoudnessChangedSince():" << audioLoudnessChangedSince(lastSentTime); + qDebug() << "..." << "parentInfoChangedSince():" << parentInfoChangedSince(lastSentTime); memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags)); destinationBuffer += sizeof(packetStateFlags); @@ -305,8 +317,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { data->globalPosition[1] = _globalPosition.y; data->globalPosition[2] = _globalPosition.z; destinationBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition); - _lastSentGlobalPosition = _globalPosition; - //qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition; } @@ -321,17 +331,18 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { data->localPosition[1] = localPosition.y; data->localPosition[2] = localPosition.z; destinationBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition); - _lastSentLocalPosition = localPosition; } if (hasAvatarDimensions) { auto data = reinterpret_cast(destinationBuffer); + + // FIXME - make this just dimensions!!! auto avatarDimensions = getPosition() - _globalBoundingBoxCorner; data->avatarDimensions[0] = avatarDimensions.x; data->avatarDimensions[1] = avatarDimensions.y; data->avatarDimensions[2] = avatarDimensions.z; destinationBuffer += sizeof(AvatarDataPacket::AvatarDimensions); - _lastSentAvatarDimensions = avatarDimensions; + qDebug() << "hasAvatarDimensions avatarDimensions:" << avatarDimensions; } if (hasAvatarOrientation) { @@ -342,7 +353,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 1), bodyEulerAngles.x); packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 2), bodyEulerAngles.z); destinationBuffer += sizeof(AvatarDataPacket::AvatarOrientation); - _lastSentLocalOrientation = localOrientation; + qDebug() << "hasAvatarOrientation bodyEulerAngles:" << bodyEulerAngles; } if (hasAvatarScale) { @@ -350,27 +361,25 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { auto scale = getDomainLimitedScale(); packFloatRatioToTwoByte((uint8_t*)(&data->scale), scale); destinationBuffer += sizeof(AvatarDataPacket::AvatarScale); - _lastSentScale = scale; + qDebug() << "hasAvatarScale scale:" << scale; } if (hasLookAtPosition) { auto data = reinterpret_cast(destinationBuffer); - auto lookAt = _headData->_lookAtPosition; + auto lookAt = _headData->getLookAtPosition(); data->lookAtPosition[0] = lookAt.x; data->lookAtPosition[1] = lookAt.y; data->lookAtPosition[2] = lookAt.z; destinationBuffer += sizeof(AvatarDataPacket::LookAtPosition); - _lastSentLookAt = lookAt; - //qDebug() << "hasLookAtPosition lookAt:" << lookAt; + qDebug() << "hasLookAtPosition lookAt:" << lookAt; } if (hasAudioLoudness) { auto data = reinterpret_cast(destinationBuffer); - auto audioLoudness = glm::min(_headData->_audioLoudness, MAX_AUDIO_LOUDNESS); + auto audioLoudness = glm::min(_headData->getAudioLoudness(), MAX_AUDIO_LOUDNESS); packFloatScalarToSignedTwoByteFixed((uint8_t*)&data->audioLoudness, audioLoudness, AUDIO_LOUDNESS_RADIX); destinationBuffer += sizeof(AvatarDataPacket::AudioLoudness); - _lastSentAudioLoudness = audioLoudness; - //qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness; + qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness; } if (hasSensorToWorldMatrix) { @@ -383,7 +392,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { data->sensorToWorldTrans[1] = sensorToWorldMatrix[3][1]; data->sensorToWorldTrans[2] = sensorToWorldMatrix[3][2]; destinationBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix); - _lastSentSensorToWorldMatrix = sensorToWorldMatrix; + qDebug() << "hasSensorToWorldMatrix..."; } QUuid parentID = getParentID(); @@ -415,7 +424,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { } data->flags = flags; destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags); - _lastSentAdditionalFlags = flags; //qDebug() << "hasAdditionalFlags _keyState:" << _keyState; //qDebug() << "hasAdditionalFlags _handState:" << _handState; @@ -430,8 +438,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) { memcpy(parentInfo->parentUUID, referentialAsBytes.data(), referentialAsBytes.size()); parentInfo->parentJointIndex = _parentJointIndex; destinationBuffer += sizeof(AvatarDataPacket::ParentInfo); - _lastSentParentID = parentID; - _lastSentParentJointIndex = _parentJointIndex; } // If it is connected, pack up the data @@ -701,8 +707,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { PACKET_READ_CHECK(AvatarGlobalPosition, sizeof(AvatarDataPacket::AvatarGlobalPosition)); auto data = reinterpret_cast(sourceBuffer); _globalPosition = glm::vec3(data->globalPosition[0], data->globalPosition[1], data->globalPosition[2]); + _globalPositionChanged = usecTimestampNow(); sourceBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition); - //qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition; + qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition; } if (hasAvatarLocalPosition) { @@ -717,7 +724,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } setLocalPosition(position); sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition); - //qDebug() << "hasAvatarLocalPosition position:" << position; + qDebug() << "hasAvatarLocalPosition position:" << position; } if (hasAvatarDimensions) { @@ -726,8 +733,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { // FIXME - this is suspicious looking! _globalBoundingBoxCorner = glm::vec3(data->avatarDimensions[0], data->avatarDimensions[1], data->avatarDimensions[2]); + _avatarDimensionsChanged = usecTimestampNow(); sourceBuffer += sizeof(AvatarDataPacket::AvatarDimensions); - //qDebug() << "hasAvatarDimensions _globalBoundingBoxCorner:" << _globalBoundingBoxCorner; + qDebug() << "hasAvatarDimensions _globalBoundingBoxCorner:" << _globalBoundingBoxCorner; } if (hasAvatarOrientation) { @@ -752,7 +760,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { setLocalOrientation(newOrientation); } sourceBuffer += sizeof(AvatarDataPacket::AvatarOrientation); - //qDebug() << "hasAvatarOrientation newOrientation:" << newOrientation; + qDebug() << "hasAvatarOrientation newOrientation:" << newOrientation; } if (hasAvatarScale) { @@ -768,7 +776,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } setTargetScale(scale); sourceBuffer += sizeof(AvatarDataPacket::AvatarScale); - //qDebug() << "hasAvatarOrientation scale:" << scale; + qDebug() << "hasAvatarOrientation scale:" << scale; } if (hasLookAtPosition) { @@ -781,9 +789,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } return buffer.size(); } - _headData->_lookAtPosition = lookAt; + _headData->setLookAtPosition(lookAt); sourceBuffer += sizeof(AvatarDataPacket::LookAtPosition); - //qDebug() << "hasLookAtPosition lookAt:" << lookAt; + qDebug() << "hasLookAtPosition lookAt:" << lookAt; } if (hasAudioLoudness) { @@ -798,9 +806,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } return buffer.size(); } - _headData->_audioLoudness = audioLoudness; + _headData->setAudioLoudness(audioLoudness); sourceBuffer += sizeof(AvatarDataPacket::AudioLoudness); - //qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness; + qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness; } if (hasSensorToWorldMatrix) { @@ -813,8 +821,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { glm::vec3 sensorToWorldTrans(data->sensorToWorldTrans[0], data->sensorToWorldTrans[1], data->sensorToWorldTrans[2]); glm::mat4 sensorToWorldMatrix = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), sensorToWorldQuat, sensorToWorldTrans); _sensorToWorldMatrixCache.set(sensorToWorldMatrix); + _sensorToWorldMatrixChanged = usecTimestampNow(); sourceBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix); - //qDebug() << "hasSensorToWorldMatrix sensorToWorldMatrix:" << sensorToWorldMatrix; + qDebug() << "hasSensorToWorldMatrix sensorToWorldMatrix:" << sensorToWorldMatrix; } if (hasAdditionalFlags) { @@ -844,8 +853,10 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { //qDebug() << "hasAdditionalFlags _isFaceTrackerConnected:" << _headData->_isFaceTrackerConnected; //qDebug() << "hasAdditionalFlags _isEyeTrackerConnected:" << _headData->_isEyeTrackerConnected; - //qDebug() << "hasAdditionalFlags bitItems:" << bitItems; + qDebug() << "hasAdditionalFlags bitItems:" << bitItems; sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags); + + _additionalFlagsChanged = usecTimestampNow(); } // FIXME -- make sure to handle the existance of a parent vs a change in the parent... @@ -858,8 +869,11 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { QByteArray byteArray((const char*)parentInfo->parentUUID, NUM_BYTES_RFC4122_UUID); _parentID = QUuid::fromRfc4122(byteArray); _parentJointIndex = parentInfo->parentJointIndex; - //qDebug() << "hasParentInfo _parentID:" << _parentID; + qDebug() << "hasParentInfo _parentID:" << _parentID; + _parentChanged = usecTimestampNow(); + } else { + // FIXME - this aint totally right, for switching to parent/no-parent _parentID = QUuid(); } @@ -879,13 +893,13 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { _headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy! memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize); sourceBuffer += coefficientsSize; - //qDebug() << "hasFaceTrackerInfo numCoefficients:" << numCoefficients; + qDebug() << "hasFaceTrackerInfo numCoefficients:" << numCoefficients; } if (hasJointData) { PACKET_READ_CHECK(NumJoints, sizeof(uint8_t)); int numJoints = *sourceBuffer++; - //qDebug() << "hasJointData numJoints:" << numJoints; + qDebug() << "hasJointData numJoints:" << numJoints; const int bytesOfValidity = (int)ceil((float)numJoints / (float)BITS_IN_BYTE); PACKET_READ_CHECK(JointRotationValidityBits, bytesOfValidity); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4bd905bd69..3ebe196ce0 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -412,7 +412,7 @@ public: SendAllData } AvatarDataDetail; - virtual QByteArray toByteArray(AvatarDataDetail dataDetail); + virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime = 0); virtual void doneEncoding(bool cullSmallChanges); /// \return true if an error should be logged @@ -464,10 +464,11 @@ public: void setTargetScaleVerbose(float targetScale); float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); } + void setDomainMinimumScale(float domainMinimumScale) - { _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } - void setDomainMaximumScale(float domainMaximumScale) - { _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } + { _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); } + void setDomainMaximumScale(float domainMaximumScale) + { _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); } // Hand State Q_INVOKABLE void setHandState(char s) { _handState = s; } @@ -602,23 +603,23 @@ public slots: float getTargetScale() { return _targetScale; } + void resetLastSent() { _lastToByteArray = 0; } + protected: void lazyInitHeadData(); - bool avatarLocalPositionChanged(); - bool avatarDimensionsChanged(); - bool avatarOrientationChanged(); - bool avatarScaleChanged(); - bool lookAtPositionChanged(); - bool audioLoudnessChanged(); - bool sensorToWorldMatrixChanged(); - bool additionalFlagsChanged(); + bool avatarDimensionsChangedSince(quint64 time); + bool avatarScaleChangedSince(quint64 time); + bool lookAtPositionChangedSince(quint64 time); + bool audioLoudnessChangedSince(quint64 time); + bool sensorToWorldMatrixChangedSince(quint64 time); + bool additionalFlagsChangedSince(quint64 time); bool hasParent() { return !getParentID().isNull(); } - bool parentInfoChanged(); + bool parentInfoChangedSince(quint64 time); bool hasFaceTracker() { return _headData ? _headData->_isFaceTrackerConnected : false; } - bool faceTrackerInfoChanged(); + bool faceTrackerInfoChangedSince(quint64 time); glm::vec3 _handPosition; virtual const QString& getSessionDisplayNameForTransport() const { return _sessionDisplayName; } @@ -681,17 +682,17 @@ protected: // updates about one avatar to another. glm::vec3 _globalPosition { 0, 0, 0 }; - glm::vec3 _lastSentGlobalPosition { 0, 0, 0 }; - glm::vec3 _lastSentLocalPosition { 0, 0, 0 }; - glm::vec3 _lastSentAvatarDimensions { 0, 0, 0 }; - glm::quat _lastSentLocalOrientation; - float _lastSentScale { 0 }; - glm::vec3 _lastSentLookAt { 0, 0, 0 }; - float _lastSentAudioLoudness { 0 }; - glm::mat4 _lastSentSensorToWorldMatrix; - uint8_t _lastSentAdditionalFlags { 0 }; - QUuid _lastSentParentID; - quint16 _lastSentParentJointIndex { 0 }; + + quint64 _globalPositionChanged { 0 }; + quint64 _avatarDimensionsChanged { 0 }; + quint64 _avatarScaleChanged { 0 }; + quint64 _lookAtChanged { 0 }; + quint64 _audioLoudnessChanged { 0 }; + quint64 _sensorToWorldMatrixChanged { 0 }; + quint64 _additionalFlagsChanged { 0 }; + quint64 _parentChanged { 0 }; + + quint64 _lastToByteArray { 0 }; // tracks the last time we did a toByteArray glm::vec3 _globalBoundingBoxCorner; @@ -710,7 +711,6 @@ protected: int getFauxJointIndex(const QString& name) const; AvatarDataPacket::AvatarInfo _lastAvatarInfo; - glm::mat4 _lastSensorToWorldMatrix; private: friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index af657339ba..cbf6c6bb32 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -19,6 +19,8 @@ #include #include +#include + // degrees const float MIN_HEAD_YAW = -180.0f; const float MAX_HEAD_YAW = 180.0f; @@ -56,7 +58,13 @@ public: void setOrientation(const glm::quat& orientation); float getAudioLoudness() const { return _audioLoudness; } - void setAudioLoudness(float audioLoudness) { _audioLoudness = audioLoudness; } + void setAudioLoudness(float audioLoudness) { + if (audioLoudness != _audioLoudness) { + _audioLoudnessChanged = usecTimestampNow(); + } + _audioLoudness = audioLoudness; + } + bool audioLoudnessChangedSince(quint64 time) { return _audioLoudnessChanged >= time; } float getAudioAverageLoudness() const { return _audioAverageLoudness; } void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; } @@ -66,7 +74,13 @@ public: void setBlendshapeCoefficients(const QVector& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; } const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } - void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; } + void setLookAtPosition(const glm::vec3& lookAtPosition) { + if (_lookAtPosition != lookAtPosition) { + _lookAtPositionChanged = usecTimestampNow(); + } + _lookAtPosition = lookAtPosition; + } + bool lookAtPositionChangedSince(quint64 time) { return _lookAtPositionChanged >= time; } friend class AvatarData; @@ -80,7 +94,11 @@ protected: float _baseRoll; glm::vec3 _lookAtPosition; + quint64 _lookAtPositionChanged { 0 }; + float _audioLoudness; + quint64 _audioLoudnessChanged { 0 }; + bool _isFaceTrackerConnected; bool _isEyeTrackerConnected; float _leftEyeBlink; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index cbe982b959..5045f74b21 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -26,6 +26,9 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : // set flags in _transform _transform.setTranslation(glm::vec3(0.0f)); _transform.setRotation(glm::quat()); + _scaleChanged = usecTimestampNow(); + _translationChanged = usecTimestampNow(); + _rotationChanged = usecTimestampNow(); } SpatiallyNestable::~SpatiallyNestable() { @@ -403,6 +406,7 @@ void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success, bo }); if (success && changed) { locationChanged(tellPhysics); + _translationChanged = usecTimestampNow(); } } @@ -455,6 +459,7 @@ void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& succe }); if (success && changed) { locationChanged(tellPhysics); + _rotationChanged = usecTimestampNow(); } } @@ -653,6 +658,8 @@ void SpatiallyNestable::setTransform(const Transform& transform, bool& success) }); if (success && changed) { locationChanged(); + _translationChanged = usecTimestampNow(); + _rotationChanged = usecTimestampNow(); } } @@ -693,6 +700,7 @@ void SpatiallyNestable::setScale(const glm::vec3& scale) { }); if (changed) { dimensionsChanged(); + _scaleChanged = usecTimestampNow(); } } @@ -715,6 +723,7 @@ void SpatiallyNestable::setScale(float value) { if (changed) { dimensionsChanged(); + _scaleChanged = usecTimestampNow(); } } @@ -743,6 +752,9 @@ void SpatiallyNestable::setLocalTransform(const Transform& transform) { if (changed) { locationChanged(); + _scaleChanged = usecTimestampNow(); + _translationChanged = usecTimestampNow(); + _rotationChanged = usecTimestampNow(); } } @@ -769,6 +781,7 @@ void SpatiallyNestable::setLocalPosition(const glm::vec3& position, bool tellPhy }); if (changed) { locationChanged(tellPhysics); + _translationChanged = usecTimestampNow(); } } @@ -795,6 +808,7 @@ void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) { }); if (changed) { locationChanged(); + _rotationChanged = usecTimestampNow(); } } @@ -850,7 +864,10 @@ void SpatiallyNestable::setLocalScale(const glm::vec3& scale) { changed = true; } }); - dimensionsChanged(); + if (changed) { + dimensionsChanged(); + _scaleChanged = usecTimestampNow(); + } } QList SpatiallyNestable::getChildren() const { @@ -1072,6 +1089,9 @@ void SpatiallyNestable::setLocalTransformAndVelocities( if (changed) { locationChanged(false); + _scaleChanged = usecTimestampNow(); + _translationChanged = usecTimestampNow(); + _rotationChanged = usecTimestampNow(); } } diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index f58e2c906c..3f3de89fce 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -176,6 +176,10 @@ public: const glm::vec3& localVelocity, const glm::vec3& localAngularVelocity); + bool scaleChangedSince(quint64 time) { return _scaleChanged > time; } + bool tranlationChangedSince(quint64 time) { return _translationChanged > time; } + bool rotationChangedSince(quint64 time) { return _rotationChanged > time; } + protected: const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; @@ -199,6 +203,9 @@ protected: mutable bool _queryAACubeSet { false }; bool _missingAncestor { false }; + quint64 _scaleChanged { 0 }; + quint64 _translationChanged { 0 }; + quint64 _rotationChanged { 0 }; private: mutable ReadWriteLockable _transformLock;