more work on only sending changes

This commit is contained in:
Brad Hefta-Gaub 2016-12-27 17:19:55 -08:00
parent be61052368
commit 73bfc069da
10 changed files with 174 additions and 99 deletions

View file

@ -400,7 +400,9 @@ void AvatarMixer::broadcastAvatarData() {
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122()); numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
//qDebug() << "about to write data for:" << otherNode->getUUID(); //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(); avatarPacketList->endSegment();
}); });

View file

@ -102,6 +102,15 @@ public:
const QString& getBaseDisplayName() { return _baseDisplayName; } const QString& getBaseDisplayName() { return _baseDisplayName; }
void setBaseDisplayName(const QString& baseDisplayName) { _baseDisplayName = 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: private:
AvatarSharedPointer _avatar { new AvatarData() }; AvatarSharedPointer _avatar { new AvatarData() };
@ -109,6 +118,10 @@ private:
std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers; std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers;
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom; std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
// this is a map of the last time we encoded an "other" avatar for
// sending to "this" node
std::unordered_map<QUuid, quint64> _lastOtherAvatarEncodeTime;
HRCTime _identityChangeTimestamp; HRCTime _identityChangeTimestamp;
bool _gotIdentity { false }; bool _gotIdentity { false };

View file

@ -5068,6 +5068,7 @@ void Application::nodeAdded(SharedNodePointer node) const {
if (node->getType() == NodeType::AvatarMixer) { if (node->getType() == NodeType::AvatarMixer) {
// new avatar mixer, send off our identity packet right away // new avatar mixer, send off our identity packet right away
getMyAvatar()->sendIdentityPacket(); getMyAvatar()->sendIdentityPacket();
getMyAvatar()->resetLastSent();
} }
} }

View file

@ -226,7 +226,7 @@ void MyAvatar::simulateAttachments(float deltaTime) {
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation() // 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(); CameraMode mode = qApp->getCamera()->getMode();
_globalPosition = getPosition(); _globalPosition = getPosition();
_globalBoundingBoxCorner.x = _characterController.getCapsuleRadius(); _globalBoundingBoxCorner.x = _characterController.getCapsuleRadius();
@ -237,12 +237,12 @@ QByteArray MyAvatar::toByteArray(AvatarDataDetail dataDetail) {
// fake the avatar position that is sent up to the AvatarMixer // fake the avatar position that is sent up to the AvatarMixer
glm::vec3 oldPosition = getPosition(); glm::vec3 oldPosition = getPosition();
setPosition(getSkeletonPosition()); setPosition(getSkeletonPosition());
QByteArray array = AvatarData::toByteArray(dataDetail); QByteArray array = AvatarData::toByteArray(dataDetail, lastSentTime);
// copy the correct position back // copy the correct position back
setPosition(oldPosition); setPosition(oldPosition);
return array; return array;
} }
return AvatarData::toByteArray(dataDetail); return AvatarData::toByteArray(dataDetail, lastSentTime);
} }
void MyAvatar::centerBody() { void MyAvatar::centerBody() {

View file

@ -333,7 +333,7 @@ private:
glm::vec3 getWorldBodyPosition() const; glm::vec3 getWorldBodyPosition() const;
glm::quat getWorldBodyOrientation() const; glm::quat getWorldBodyOrientation() const;
QByteArray toByteArray(AvatarDataDetail dataDetail) override; QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime) override;
void simulate(float deltaTime); void simulate(float deltaTime);
void updateFromTrackers(float deltaTime); void updateFromTrackers(float deltaTime);
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override; virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;

View file

@ -132,6 +132,7 @@ float AvatarData::getTargetScale() const {
void AvatarData::setTargetScale(float targetScale) { void AvatarData::setTargetScale(float targetScale) {
_targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
_scaleChanged = usecTimestampNow();
} }
void AvatarData::setTargetScaleVerbose(float targetScale) { void AvatarData::setTargetScaleVerbose(float targetScale) {
@ -159,48 +160,47 @@ void AvatarData::lazyInitHeadData() {
} }
bool AvatarData::avatarLocalPositionChanged() { bool AvatarData::avatarDimensionsChangedSince(quint64 time) {
return _lastSentLocalPosition != getLocalPosition(); return _avatarDimensionsChanged >= time;
} }
bool AvatarData::avatarDimensionsChanged() { bool AvatarData::avatarScaleChangedSince(quint64 time) {
auto avatarDimensions = getPosition() - _globalBoundingBoxCorner; return _avatarScaleChanged >= time;
return _lastSentAvatarDimensions != avatarDimensions;
} }
bool AvatarData::avatarOrientationChanged() { bool AvatarData::lookAtPositionChangedSince(quint64 time) {
return _lastSentLocalOrientation != getLocalOrientation(); return _headData->lookAtPositionChangedSince(time);
} }
bool AvatarData::avatarScaleChanged() { bool AvatarData::audioLoudnessChangedSince(quint64 time) {
return _lastSentScale != getDomainLimitedScale(); return _headData->audioLoudnessChangedSince(time);
} }
bool AvatarData::lookAtPositionChanged() { bool AvatarData::sensorToWorldMatrixChangedSince(quint64 time) {
return _lastSentLookAt != _headData->_lookAtPosition; return _sensorToWorldMatrixChanged >= time;
} }
bool AvatarData::audioLoudnessChanged() { bool AvatarData::additionalFlagsChangedSince(quint64 time) {
return _lastSentAudioLoudness != glm::min(_headData->_audioLoudness, MAX_AUDIO_LOUDNESS);
}
bool AvatarData::sensorToWorldMatrixChanged() {
return _lastSentSensorToWorldMatrix != getSensorToWorldMatrix();
}
bool AvatarData::additionalFlagsChanged() {
return true; // FIXME! return true; // FIXME!
} }
bool AvatarData::parentInfoChanged() { bool AvatarData::parentInfoChangedSince(quint64 time) {
return (_lastSentParentID != getParentID()) || (_lastSentParentJointIndex != _parentJointIndex); return _parentChanged >= time;
} }
bool AvatarData::faceTrackerInfoChanged() { bool AvatarData::faceTrackerInfoChangedSince(quint64 time) {
return true; // FIXME! 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 cullSmallChanges = (dataDetail == CullSmallData);
bool sendAll = (dataDetail == SendAllData); bool sendAll = (dataDetail == SendAllData);
bool sendMinimum = (dataDetail == MinimumData); bool sendMinimum = (dataDetail == MinimumData);
@ -261,18 +261,25 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
// the others will be partial. // the others will be partial.
// we need some way of keeping track of what was sent the last time. // 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 hasAvatarGlobalPosition = true; // always include global position
bool hasAvatarLocalPosition = sendAll || avatarLocalPositionChanged(); bool hasAvatarLocalPosition = sendAll || tranlationChangedSince(lastSentTime);
bool hasAvatarDimensions = sendAll || avatarDimensionsChanged(); bool hasAvatarOrientation = sendAll || rotationChangedSince(lastSentTime);
bool hasAvatarOrientation = sendAll || avatarOrientationChanged();
bool hasAvatarScale = sendAll || avatarScaleChanged(); bool hasAvatarDimensions = sendAll || avatarDimensionsChangedSince(lastSentTime);
bool hasLookAtPosition = sendAll || lookAtPositionChanged(); bool hasAvatarScale = sendAll || avatarScaleChangedSince(lastSentTime);
bool hasAudioLoudness = sendAll || audioLoudnessChanged(); bool hasLookAtPosition = sendAll || lookAtPositionChangedSince(lastSentTime);
bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChanged(); bool hasAudioLoudness = sendAll || audioLoudnessChangedSince(lastSentTime);
bool hasAdditionalFlags = sendAll || additionalFlagsChanged(); bool hasSensorToWorldMatrix = sendAll || sensorToWorldMatrixChangedSince(lastSentTime);
bool hasParentInfo = hasParent() && (sendAll || parentInfoChanged()); bool hasAdditionalFlags = sendAll || additionalFlagsChangedSince(lastSentTime);
bool hasFaceTrackerInfo = hasFaceTracker() && (sendAll || faceTrackerInfoChanged()); bool hasParentInfo = hasParent() && (sendAll || parentInfoChangedSince(lastSentTime));
bool hasFaceTrackerInfo = hasFaceTracker() && (sendAll || faceTrackerInfoChangedSince(lastSentTime));
bool hasJointData = sendAll || !sendMinimum; bool hasJointData = sendAll || !sendMinimum;
//qDebug() << __FUNCTION__ << "sendAll:" << sendAll; //qDebug() << __FUNCTION__ << "sendAll:" << sendAll;
@ -294,7 +301,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
| (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0) | (hasFaceTrackerInfo ? AvatarDataPacket::PACKET_HAS_FACE_TRACKER_INFO : 0)
| (hasJointData ? AvatarDataPacket::PACKET_HAS_JOINT_DATA : 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)); memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags));
destinationBuffer += sizeof(packetStateFlags); destinationBuffer += sizeof(packetStateFlags);
@ -305,8 +317,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
data->globalPosition[1] = _globalPosition.y; data->globalPosition[1] = _globalPosition.y;
data->globalPosition[2] = _globalPosition.z; data->globalPosition[2] = _globalPosition.z;
destinationBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition); destinationBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition);
_lastSentGlobalPosition = _globalPosition;
//qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition; //qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition;
} }
@ -321,17 +331,18 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
data->localPosition[1] = localPosition.y; data->localPosition[1] = localPosition.y;
data->localPosition[2] = localPosition.z; data->localPosition[2] = localPosition.z;
destinationBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition); destinationBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
_lastSentLocalPosition = localPosition;
} }
if (hasAvatarDimensions) { if (hasAvatarDimensions) {
auto data = reinterpret_cast<AvatarDataPacket::AvatarDimensions*>(destinationBuffer); auto data = reinterpret_cast<AvatarDataPacket::AvatarDimensions*>(destinationBuffer);
// FIXME - make this just dimensions!!!
auto avatarDimensions = getPosition() - _globalBoundingBoxCorner; auto avatarDimensions = getPosition() - _globalBoundingBoxCorner;
data->avatarDimensions[0] = avatarDimensions.x; data->avatarDimensions[0] = avatarDimensions.x;
data->avatarDimensions[1] = avatarDimensions.y; data->avatarDimensions[1] = avatarDimensions.y;
data->avatarDimensions[2] = avatarDimensions.z; data->avatarDimensions[2] = avatarDimensions.z;
destinationBuffer += sizeof(AvatarDataPacket::AvatarDimensions); destinationBuffer += sizeof(AvatarDataPacket::AvatarDimensions);
_lastSentAvatarDimensions = avatarDimensions; qDebug() << "hasAvatarDimensions avatarDimensions:" << avatarDimensions;
} }
if (hasAvatarOrientation) { if (hasAvatarOrientation) {
@ -342,7 +353,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 1), bodyEulerAngles.x); packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 1), bodyEulerAngles.x);
packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 2), bodyEulerAngles.z); packFloatAngleToTwoByte((uint8_t*)(data->localOrientation + 2), bodyEulerAngles.z);
destinationBuffer += sizeof(AvatarDataPacket::AvatarOrientation); destinationBuffer += sizeof(AvatarDataPacket::AvatarOrientation);
_lastSentLocalOrientation = localOrientation; qDebug() << "hasAvatarOrientation bodyEulerAngles:" << bodyEulerAngles;
} }
if (hasAvatarScale) { if (hasAvatarScale) {
@ -350,27 +361,25 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
auto scale = getDomainLimitedScale(); auto scale = getDomainLimitedScale();
packFloatRatioToTwoByte((uint8_t*)(&data->scale), scale); packFloatRatioToTwoByte((uint8_t*)(&data->scale), scale);
destinationBuffer += sizeof(AvatarDataPacket::AvatarScale); destinationBuffer += sizeof(AvatarDataPacket::AvatarScale);
_lastSentScale = scale; qDebug() << "hasAvatarScale scale:" << scale;
} }
if (hasLookAtPosition) { if (hasLookAtPosition) {
auto data = reinterpret_cast<AvatarDataPacket::LookAtPosition*>(destinationBuffer); auto data = reinterpret_cast<AvatarDataPacket::LookAtPosition*>(destinationBuffer);
auto lookAt = _headData->_lookAtPosition; auto lookAt = _headData->getLookAtPosition();
data->lookAtPosition[0] = lookAt.x; data->lookAtPosition[0] = lookAt.x;
data->lookAtPosition[1] = lookAt.y; data->lookAtPosition[1] = lookAt.y;
data->lookAtPosition[2] = lookAt.z; data->lookAtPosition[2] = lookAt.z;
destinationBuffer += sizeof(AvatarDataPacket::LookAtPosition); destinationBuffer += sizeof(AvatarDataPacket::LookAtPosition);
_lastSentLookAt = lookAt; qDebug() << "hasLookAtPosition lookAt:" << lookAt;
//qDebug() << "hasLookAtPosition lookAt:" << lookAt;
} }
if (hasAudioLoudness) { if (hasAudioLoudness) {
auto data = reinterpret_cast<AvatarDataPacket::AudioLoudness*>(destinationBuffer); auto data = reinterpret_cast<AvatarDataPacket::AudioLoudness*>(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); packFloatScalarToSignedTwoByteFixed((uint8_t*)&data->audioLoudness, audioLoudness, AUDIO_LOUDNESS_RADIX);
destinationBuffer += sizeof(AvatarDataPacket::AudioLoudness); destinationBuffer += sizeof(AvatarDataPacket::AudioLoudness);
_lastSentAudioLoudness = audioLoudness; qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness;
//qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness;
} }
if (hasSensorToWorldMatrix) { if (hasSensorToWorldMatrix) {
@ -383,7 +392,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
data->sensorToWorldTrans[1] = sensorToWorldMatrix[3][1]; data->sensorToWorldTrans[1] = sensorToWorldMatrix[3][1];
data->sensorToWorldTrans[2] = sensorToWorldMatrix[3][2]; data->sensorToWorldTrans[2] = sensorToWorldMatrix[3][2];
destinationBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix); destinationBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix);
_lastSentSensorToWorldMatrix = sensorToWorldMatrix; qDebug() << "hasSensorToWorldMatrix...";
} }
QUuid parentID = getParentID(); QUuid parentID = getParentID();
@ -415,7 +424,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
} }
data->flags = flags; data->flags = flags;
destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags); destinationBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
_lastSentAdditionalFlags = flags;
//qDebug() << "hasAdditionalFlags _keyState:" << _keyState; //qDebug() << "hasAdditionalFlags _keyState:" << _keyState;
//qDebug() << "hasAdditionalFlags _handState:" << _handState; //qDebug() << "hasAdditionalFlags _handState:" << _handState;
@ -430,8 +438,6 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail) {
memcpy(parentInfo->parentUUID, referentialAsBytes.data(), referentialAsBytes.size()); memcpy(parentInfo->parentUUID, referentialAsBytes.data(), referentialAsBytes.size());
parentInfo->parentJointIndex = _parentJointIndex; parentInfo->parentJointIndex = _parentJointIndex;
destinationBuffer += sizeof(AvatarDataPacket::ParentInfo); destinationBuffer += sizeof(AvatarDataPacket::ParentInfo);
_lastSentParentID = parentID;
_lastSentParentJointIndex = _parentJointIndex;
} }
// If it is connected, pack up the data // 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)); PACKET_READ_CHECK(AvatarGlobalPosition, sizeof(AvatarDataPacket::AvatarGlobalPosition));
auto data = reinterpret_cast<const AvatarDataPacket::AvatarGlobalPosition*>(sourceBuffer); auto data = reinterpret_cast<const AvatarDataPacket::AvatarGlobalPosition*>(sourceBuffer);
_globalPosition = glm::vec3(data->globalPosition[0], data->globalPosition[1], data->globalPosition[2]); _globalPosition = glm::vec3(data->globalPosition[0], data->globalPosition[1], data->globalPosition[2]);
_globalPositionChanged = usecTimestampNow();
sourceBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition); sourceBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition);
//qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition; qDebug() << "hasAvatarGlobalPosition _globalPosition:" << _globalPosition;
} }
if (hasAvatarLocalPosition) { if (hasAvatarLocalPosition) {
@ -717,7 +724,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
} }
setLocalPosition(position); setLocalPosition(position);
sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition); sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition);
//qDebug() << "hasAvatarLocalPosition position:" << position; qDebug() << "hasAvatarLocalPosition position:" << position;
} }
if (hasAvatarDimensions) { if (hasAvatarDimensions) {
@ -726,8 +733,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
// FIXME - this is suspicious looking! // FIXME - this is suspicious looking!
_globalBoundingBoxCorner = glm::vec3(data->avatarDimensions[0], data->avatarDimensions[1], data->avatarDimensions[2]); _globalBoundingBoxCorner = glm::vec3(data->avatarDimensions[0], data->avatarDimensions[1], data->avatarDimensions[2]);
_avatarDimensionsChanged = usecTimestampNow();
sourceBuffer += sizeof(AvatarDataPacket::AvatarDimensions); sourceBuffer += sizeof(AvatarDataPacket::AvatarDimensions);
//qDebug() << "hasAvatarDimensions _globalBoundingBoxCorner:" << _globalBoundingBoxCorner; qDebug() << "hasAvatarDimensions _globalBoundingBoxCorner:" << _globalBoundingBoxCorner;
} }
if (hasAvatarOrientation) { if (hasAvatarOrientation) {
@ -752,7 +760,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
setLocalOrientation(newOrientation); setLocalOrientation(newOrientation);
} }
sourceBuffer += sizeof(AvatarDataPacket::AvatarOrientation); sourceBuffer += sizeof(AvatarDataPacket::AvatarOrientation);
//qDebug() << "hasAvatarOrientation newOrientation:" << newOrientation; qDebug() << "hasAvatarOrientation newOrientation:" << newOrientation;
} }
if (hasAvatarScale) { if (hasAvatarScale) {
@ -768,7 +776,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
} }
setTargetScale(scale); setTargetScale(scale);
sourceBuffer += sizeof(AvatarDataPacket::AvatarScale); sourceBuffer += sizeof(AvatarDataPacket::AvatarScale);
//qDebug() << "hasAvatarOrientation scale:" << scale; qDebug() << "hasAvatarOrientation scale:" << scale;
} }
if (hasLookAtPosition) { if (hasLookAtPosition) {
@ -781,9 +789,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
} }
return buffer.size(); return buffer.size();
} }
_headData->_lookAtPosition = lookAt; _headData->setLookAtPosition(lookAt);
sourceBuffer += sizeof(AvatarDataPacket::LookAtPosition); sourceBuffer += sizeof(AvatarDataPacket::LookAtPosition);
//qDebug() << "hasLookAtPosition lookAt:" << lookAt; qDebug() << "hasLookAtPosition lookAt:" << lookAt;
} }
if (hasAudioLoudness) { if (hasAudioLoudness) {
@ -798,9 +806,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
} }
return buffer.size(); return buffer.size();
} }
_headData->_audioLoudness = audioLoudness; _headData->setAudioLoudness(audioLoudness);
sourceBuffer += sizeof(AvatarDataPacket::AudioLoudness); sourceBuffer += sizeof(AvatarDataPacket::AudioLoudness);
//qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness; qDebug() << "hasAudioLoudness audioLoudness:" << audioLoudness;
} }
if (hasSensorToWorldMatrix) { 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::vec3 sensorToWorldTrans(data->sensorToWorldTrans[0], data->sensorToWorldTrans[1], data->sensorToWorldTrans[2]);
glm::mat4 sensorToWorldMatrix = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), sensorToWorldQuat, sensorToWorldTrans); glm::mat4 sensorToWorldMatrix = createMatFromScaleQuatAndPos(glm::vec3(sensorToWorldScale), sensorToWorldQuat, sensorToWorldTrans);
_sensorToWorldMatrixCache.set(sensorToWorldMatrix); _sensorToWorldMatrixCache.set(sensorToWorldMatrix);
_sensorToWorldMatrixChanged = usecTimestampNow();
sourceBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix); sourceBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix);
//qDebug() << "hasSensorToWorldMatrix sensorToWorldMatrix:" << sensorToWorldMatrix; qDebug() << "hasSensorToWorldMatrix sensorToWorldMatrix:" << sensorToWorldMatrix;
} }
if (hasAdditionalFlags) { if (hasAdditionalFlags) {
@ -844,8 +853,10 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
//qDebug() << "hasAdditionalFlags _isFaceTrackerConnected:" << _headData->_isFaceTrackerConnected; //qDebug() << "hasAdditionalFlags _isFaceTrackerConnected:" << _headData->_isFaceTrackerConnected;
//qDebug() << "hasAdditionalFlags _isEyeTrackerConnected:" << _headData->_isEyeTrackerConnected; //qDebug() << "hasAdditionalFlags _isEyeTrackerConnected:" << _headData->_isEyeTrackerConnected;
//qDebug() << "hasAdditionalFlags bitItems:" << bitItems; qDebug() << "hasAdditionalFlags bitItems:" << bitItems;
sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags); sourceBuffer += sizeof(AvatarDataPacket::AdditionalFlags);
_additionalFlagsChanged = usecTimestampNow();
} }
// FIXME -- make sure to handle the existance of a parent vs a change in the parent... // 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); QByteArray byteArray((const char*)parentInfo->parentUUID, NUM_BYTES_RFC4122_UUID);
_parentID = QUuid::fromRfc4122(byteArray); _parentID = QUuid::fromRfc4122(byteArray);
_parentJointIndex = parentInfo->parentJointIndex; _parentJointIndex = parentInfo->parentJointIndex;
//qDebug() << "hasParentInfo _parentID:" << _parentID; qDebug() << "hasParentInfo _parentID:" << _parentID;
_parentChanged = usecTimestampNow();
} else { } else {
// FIXME - this aint totally right, for switching to parent/no-parent
_parentID = QUuid(); _parentID = QUuid();
} }
@ -879,13 +893,13 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
_headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy! _headData->_blendshapeCoefficients.resize(numCoefficients); // make sure there's room for the copy!
memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize); memcpy(_headData->_blendshapeCoefficients.data(), sourceBuffer, coefficientsSize);
sourceBuffer += coefficientsSize; sourceBuffer += coefficientsSize;
//qDebug() << "hasFaceTrackerInfo numCoefficients:" << numCoefficients; qDebug() << "hasFaceTrackerInfo numCoefficients:" << numCoefficients;
} }
if (hasJointData) { if (hasJointData) {
PACKET_READ_CHECK(NumJoints, sizeof(uint8_t)); PACKET_READ_CHECK(NumJoints, sizeof(uint8_t));
int numJoints = *sourceBuffer++; int numJoints = *sourceBuffer++;
//qDebug() << "hasJointData numJoints:" << numJoints; qDebug() << "hasJointData numJoints:" << numJoints;
const int bytesOfValidity = (int)ceil((float)numJoints / (float)BITS_IN_BYTE); const int bytesOfValidity = (int)ceil((float)numJoints / (float)BITS_IN_BYTE);
PACKET_READ_CHECK(JointRotationValidityBits, bytesOfValidity); PACKET_READ_CHECK(JointRotationValidityBits, bytesOfValidity);

View file

@ -412,7 +412,7 @@ public:
SendAllData SendAllData
} AvatarDataDetail; } AvatarDataDetail;
virtual QByteArray toByteArray(AvatarDataDetail dataDetail); virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime = 0);
virtual void doneEncoding(bool cullSmallChanges); virtual void doneEncoding(bool cullSmallChanges);
/// \return true if an error should be logged /// \return true if an error should be logged
@ -464,10 +464,11 @@ public:
void setTargetScaleVerbose(float targetScale); void setTargetScaleVerbose(float targetScale);
float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); } float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); }
void setDomainMinimumScale(float domainMinimumScale) void setDomainMinimumScale(float domainMinimumScale)
{ _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); } { _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); } { _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); _scaleChanged = usecTimestampNow(); }
// Hand State // Hand State
Q_INVOKABLE void setHandState(char s) { _handState = s; } Q_INVOKABLE void setHandState(char s) { _handState = s; }
@ -602,23 +603,23 @@ public slots:
float getTargetScale() { return _targetScale; } float getTargetScale() { return _targetScale; }
void resetLastSent() { _lastToByteArray = 0; }
protected: protected:
void lazyInitHeadData(); void lazyInitHeadData();
bool avatarLocalPositionChanged(); bool avatarDimensionsChangedSince(quint64 time);
bool avatarDimensionsChanged(); bool avatarScaleChangedSince(quint64 time);
bool avatarOrientationChanged(); bool lookAtPositionChangedSince(quint64 time);
bool avatarScaleChanged(); bool audioLoudnessChangedSince(quint64 time);
bool lookAtPositionChanged(); bool sensorToWorldMatrixChangedSince(quint64 time);
bool audioLoudnessChanged(); bool additionalFlagsChangedSince(quint64 time);
bool sensorToWorldMatrixChanged();
bool additionalFlagsChanged();
bool hasParent() { return !getParentID().isNull(); } bool hasParent() { return !getParentID().isNull(); }
bool parentInfoChanged(); bool parentInfoChangedSince(quint64 time);
bool hasFaceTracker() { return _headData ? _headData->_isFaceTrackerConnected : false; } bool hasFaceTracker() { return _headData ? _headData->_isFaceTrackerConnected : false; }
bool faceTrackerInfoChanged(); bool faceTrackerInfoChangedSince(quint64 time);
glm::vec3 _handPosition; glm::vec3 _handPosition;
virtual const QString& getSessionDisplayNameForTransport() const { return _sessionDisplayName; } virtual const QString& getSessionDisplayNameForTransport() const { return _sessionDisplayName; }
@ -681,17 +682,17 @@ protected:
// updates about one avatar to another. // updates about one avatar to another.
glm::vec3 _globalPosition { 0, 0, 0 }; glm::vec3 _globalPosition { 0, 0, 0 };
glm::vec3 _lastSentGlobalPosition { 0, 0, 0 };
glm::vec3 _lastSentLocalPosition { 0, 0, 0 }; quint64 _globalPositionChanged { 0 };
glm::vec3 _lastSentAvatarDimensions { 0, 0, 0 }; quint64 _avatarDimensionsChanged { 0 };
glm::quat _lastSentLocalOrientation; quint64 _avatarScaleChanged { 0 };
float _lastSentScale { 0 }; quint64 _lookAtChanged { 0 };
glm::vec3 _lastSentLookAt { 0, 0, 0 }; quint64 _audioLoudnessChanged { 0 };
float _lastSentAudioLoudness { 0 }; quint64 _sensorToWorldMatrixChanged { 0 };
glm::mat4 _lastSentSensorToWorldMatrix; quint64 _additionalFlagsChanged { 0 };
uint8_t _lastSentAdditionalFlags { 0 }; quint64 _parentChanged { 0 };
QUuid _lastSentParentID;
quint16 _lastSentParentJointIndex { 0 }; quint64 _lastToByteArray { 0 }; // tracks the last time we did a toByteArray
glm::vec3 _globalBoundingBoxCorner; glm::vec3 _globalBoundingBoxCorner;
@ -710,7 +711,6 @@ protected:
int getFauxJointIndex(const QString& name) const; int getFauxJointIndex(const QString& name) const;
AvatarDataPacket::AvatarInfo _lastAvatarInfo; AvatarDataPacket::AvatarInfo _lastAvatarInfo;
glm::mat4 _lastSensorToWorldMatrix;
private: private:
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar); friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);

View file

@ -19,6 +19,8 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <SharedUtil.h>
// degrees // degrees
const float MIN_HEAD_YAW = -180.0f; const float MIN_HEAD_YAW = -180.0f;
const float MAX_HEAD_YAW = 180.0f; const float MAX_HEAD_YAW = 180.0f;
@ -56,7 +58,13 @@ public:
void setOrientation(const glm::quat& orientation); void setOrientation(const glm::quat& orientation);
float getAudioLoudness() const { return _audioLoudness; } 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; } float getAudioAverageLoudness() const { return _audioAverageLoudness; }
void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; } void setAudioAverageLoudness(float audioAverageLoudness) { _audioAverageLoudness = audioAverageLoudness; }
@ -66,7 +74,13 @@ public:
void setBlendshapeCoefficients(const QVector<float>& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; } void setBlendshapeCoefficients(const QVector<float>& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; }
const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } 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; friend class AvatarData;
@ -80,7 +94,11 @@ protected:
float _baseRoll; float _baseRoll;
glm::vec3 _lookAtPosition; glm::vec3 _lookAtPosition;
quint64 _lookAtPositionChanged { 0 };
float _audioLoudness; float _audioLoudness;
quint64 _audioLoudnessChanged { 0 };
bool _isFaceTrackerConnected; bool _isFaceTrackerConnected;
bool _isEyeTrackerConnected; bool _isEyeTrackerConnected;
float _leftEyeBlink; float _leftEyeBlink;

View file

@ -26,6 +26,9 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) :
// set flags in _transform // set flags in _transform
_transform.setTranslation(glm::vec3(0.0f)); _transform.setTranslation(glm::vec3(0.0f));
_transform.setRotation(glm::quat()); _transform.setRotation(glm::quat());
_scaleChanged = usecTimestampNow();
_translationChanged = usecTimestampNow();
_rotationChanged = usecTimestampNow();
} }
SpatiallyNestable::~SpatiallyNestable() { SpatiallyNestable::~SpatiallyNestable() {
@ -403,6 +406,7 @@ void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success, bo
}); });
if (success && changed) { if (success && changed) {
locationChanged(tellPhysics); locationChanged(tellPhysics);
_translationChanged = usecTimestampNow();
} }
} }
@ -455,6 +459,7 @@ void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& succe
}); });
if (success && changed) { if (success && changed) {
locationChanged(tellPhysics); locationChanged(tellPhysics);
_rotationChanged = usecTimestampNow();
} }
} }
@ -653,6 +658,8 @@ void SpatiallyNestable::setTransform(const Transform& transform, bool& success)
}); });
if (success && changed) { if (success && changed) {
locationChanged(); locationChanged();
_translationChanged = usecTimestampNow();
_rotationChanged = usecTimestampNow();
} }
} }
@ -693,6 +700,7 @@ void SpatiallyNestable::setScale(const glm::vec3& scale) {
}); });
if (changed) { if (changed) {
dimensionsChanged(); dimensionsChanged();
_scaleChanged = usecTimestampNow();
} }
} }
@ -715,6 +723,7 @@ void SpatiallyNestable::setScale(float value) {
if (changed) { if (changed) {
dimensionsChanged(); dimensionsChanged();
_scaleChanged = usecTimestampNow();
} }
} }
@ -743,6 +752,9 @@ void SpatiallyNestable::setLocalTransform(const Transform& transform) {
if (changed) { if (changed) {
locationChanged(); locationChanged();
_scaleChanged = usecTimestampNow();
_translationChanged = usecTimestampNow();
_rotationChanged = usecTimestampNow();
} }
} }
@ -769,6 +781,7 @@ void SpatiallyNestable::setLocalPosition(const glm::vec3& position, bool tellPhy
}); });
if (changed) { if (changed) {
locationChanged(tellPhysics); locationChanged(tellPhysics);
_translationChanged = usecTimestampNow();
} }
} }
@ -795,6 +808,7 @@ void SpatiallyNestable::setLocalOrientation(const glm::quat& orientation) {
}); });
if (changed) { if (changed) {
locationChanged(); locationChanged();
_rotationChanged = usecTimestampNow();
} }
} }
@ -850,7 +864,10 @@ void SpatiallyNestable::setLocalScale(const glm::vec3& scale) {
changed = true; changed = true;
} }
}); });
if (changed) {
dimensionsChanged(); dimensionsChanged();
_scaleChanged = usecTimestampNow();
}
} }
QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const { QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const {
@ -1072,6 +1089,9 @@ void SpatiallyNestable::setLocalTransformAndVelocities(
if (changed) { if (changed) {
locationChanged(false); locationChanged(false);
_scaleChanged = usecTimestampNow();
_translationChanged = usecTimestampNow();
_rotationChanged = usecTimestampNow();
} }
} }

View file

@ -176,6 +176,10 @@ public:
const glm::vec3& localVelocity, const glm::vec3& localVelocity,
const glm::vec3& localAngularVelocity); 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: protected:
const NestableType _nestableType; // EntityItem or an AvatarData const NestableType _nestableType; // EntityItem or an AvatarData
QUuid _id; QUuid _id;
@ -199,6 +203,9 @@ protected:
mutable bool _queryAACubeSet { false }; mutable bool _queryAACubeSet { false };
bool _missingAncestor { false }; bool _missingAncestor { false };
quint64 _scaleChanged { 0 };
quint64 _translationChanged { 0 };
quint64 _rotationChanged { 0 };
private: private:
mutable ReadWriteLockable _transformLock; mutable ReadWriteLockable _transformLock;