mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-04 03:01:11 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into polyvox
This commit is contained in:
commit
4961c10e17
2 changed files with 277 additions and 294 deletions
|
@ -318,15 +318,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this bitstream indicates that this node is the simulation owner, ignore any physics-related updates.
|
|
||||||
glm::vec3 savePosition = _position;
|
|
||||||
glm::quat saveRotation = _rotation;
|
|
||||||
// glm::vec3 saveVelocity = _velocity;
|
|
||||||
// glm::vec3 saveAngularVelocity = _angularVelocity;
|
|
||||||
// glm::vec3 saveGravity = _gravity;
|
|
||||||
// glm::vec3 saveAcceleration = _acceleration;
|
|
||||||
|
|
||||||
|
|
||||||
// Header bytes
|
// Header bytes
|
||||||
// object ID [16 bytes]
|
// object ID [16 bytes]
|
||||||
// ByteCountCoded(type code) [~1 byte]
|
// ByteCountCoded(type code) [~1 byte]
|
||||||
|
@ -337,299 +328,308 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
const int MINIMUM_HEADER_BYTES = 27;
|
const int MINIMUM_HEADER_BYTES = 27;
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
if (bytesLeftToRead >= MINIMUM_HEADER_BYTES) {
|
if (bytesLeftToRead < MINIMUM_HEADER_BYTES) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int originalLength = bytesLeftToRead;
|
// if this bitstream indicates that this node is the simulation owner, ignore any physics-related updates.
|
||||||
QByteArray originalDataBuffer((const char*)data, originalLength);
|
glm::vec3 savePosition = _position;
|
||||||
|
glm::quat saveRotation = _rotation;
|
||||||
|
glm::vec3 saveVelocity = _velocity;
|
||||||
|
glm::vec3 saveAngularVelocity = _angularVelocity;
|
||||||
|
|
||||||
int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
int originalLength = bytesLeftToRead;
|
||||||
|
QByteArray originalDataBuffer((const char*)data, originalLength);
|
||||||
|
|
||||||
const unsigned char* dataAt = data;
|
int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0;
|
||||||
|
|
||||||
// id
|
const unsigned char* dataAt = data;
|
||||||
QByteArray encodedID = originalDataBuffer.mid(bytesRead, NUM_BYTES_RFC4122_UUID); // maximum possible size
|
|
||||||
_id = QUuid::fromRfc4122(encodedID);
|
|
||||||
dataAt += encodedID.size();
|
|
||||||
bytesRead += encodedID.size();
|
|
||||||
|
|
||||||
// type
|
|
||||||
QByteArray encodedType = originalDataBuffer.mid(bytesRead); // maximum possible size
|
|
||||||
ByteCountCoded<quint32> typeCoder = encodedType;
|
|
||||||
encodedType = typeCoder; // determine true length
|
|
||||||
dataAt += encodedType.size();
|
|
||||||
bytesRead += encodedType.size();
|
|
||||||
quint32 type = typeCoder;
|
|
||||||
_type = (EntityTypes::EntityType)type;
|
|
||||||
|
|
||||||
bool overwriteLocalData = true; // assume the new content overwrites our local data
|
// id
|
||||||
|
QByteArray encodedID = originalDataBuffer.mid(bytesRead, NUM_BYTES_RFC4122_UUID); // maximum possible size
|
||||||
|
_id = QUuid::fromRfc4122(encodedID);
|
||||||
|
dataAt += encodedID.size();
|
||||||
|
bytesRead += encodedID.size();
|
||||||
|
|
||||||
|
// type
|
||||||
|
QByteArray encodedType = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||||
|
ByteCountCoded<quint32> typeCoder = encodedType;
|
||||||
|
encodedType = typeCoder; // determine true length
|
||||||
|
dataAt += encodedType.size();
|
||||||
|
bytesRead += encodedType.size();
|
||||||
|
quint32 type = typeCoder;
|
||||||
|
_type = (EntityTypes::EntityType)type;
|
||||||
|
|
||||||
// _created
|
bool overwriteLocalData = true; // assume the new content overwrites our local data
|
||||||
quint64 createdFromBuffer = 0;
|
|
||||||
memcpy(&createdFromBuffer, dataAt, sizeof(createdFromBuffer));
|
|
||||||
dataAt += sizeof(createdFromBuffer);
|
|
||||||
bytesRead += sizeof(createdFromBuffer);
|
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
// _created
|
||||||
if (_created == UNKNOWN_CREATED_TIME) {
|
quint64 createdFromBuffer = 0;
|
||||||
// we don't yet have a _created timestamp, so we accept this one
|
memcpy(&createdFromBuffer, dataAt, sizeof(createdFromBuffer));
|
||||||
createdFromBuffer -= clockSkew;
|
dataAt += sizeof(createdFromBuffer);
|
||||||
if (createdFromBuffer > now || createdFromBuffer == UNKNOWN_CREATED_TIME) {
|
bytesRead += sizeof(createdFromBuffer);
|
||||||
createdFromBuffer = now;
|
|
||||||
}
|
quint64 now = usecTimestampNow();
|
||||||
_created = createdFromBuffer;
|
if (_created == UNKNOWN_CREATED_TIME) {
|
||||||
|
// we don't yet have a _created timestamp, so we accept this one
|
||||||
|
createdFromBuffer -= clockSkew;
|
||||||
|
if (createdFromBuffer > now || createdFromBuffer == UNKNOWN_CREATED_TIME) {
|
||||||
|
createdFromBuffer = now;
|
||||||
}
|
}
|
||||||
|
_created = createdFromBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
quint64 lastEdited = getLastEdited();
|
||||||
|
float editedAgo = getEditedAgo();
|
||||||
|
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||||
|
QString ageAsString = formatSecondsElapsed(getAge());
|
||||||
|
qCDebug(entities) << "------------------------------------------";
|
||||||
|
qCDebug(entities) << "Loading entity " << getEntityItemID() << " from buffer...";
|
||||||
|
qCDebug(entities) << "------------------------------------------";
|
||||||
|
debugDump();
|
||||||
|
qCDebug(entities) << "------------------------------------------";
|
||||||
|
qCDebug(entities) << " _created =" << _created;
|
||||||
|
qCDebug(entities) << " age=" << getAge() << "seconds - " << ageAsString;
|
||||||
|
qCDebug(entities) << " lastEdited =" << lastEdited;
|
||||||
|
qCDebug(entities) << " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
quint64 lastEditedFromBuffer = 0;
|
||||||
|
quint64 lastEditedFromBufferAdjusted = 0;
|
||||||
|
|
||||||
|
// TODO: we could make this encoded as a delta from _created
|
||||||
|
// _lastEdited
|
||||||
|
memcpy(&lastEditedFromBuffer, dataAt, sizeof(lastEditedFromBuffer));
|
||||||
|
dataAt += sizeof(lastEditedFromBuffer);
|
||||||
|
bytesRead += sizeof(lastEditedFromBuffer);
|
||||||
|
lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew;
|
||||||
|
if (lastEditedFromBufferAdjusted > now) {
|
||||||
|
lastEditedFromBufferAdjusted = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fromSameServerEdit = (lastEditedFromBuffer == _lastEditedFromRemoteInRemoteTime);
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qCDebug(entities) << "data from server **************** ";
|
||||||
|
qCDebug(entities) << " entityItemID:" << getEntityItemID();
|
||||||
|
qCDebug(entities) << " now:" << now;
|
||||||
|
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||||
|
qCDebug(entities) << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
||||||
|
qCDebug(entities) << " clockSkew:" << debugTimeOnly(clockSkew);
|
||||||
|
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||||
|
qCDebug(entities) << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
||||||
|
qCDebug(entities) << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
||||||
|
qCDebug(entities) << " fromSameServerEdit:" << fromSameServerEdit;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool ignoreServerPacket = false; // assume we'll use this server packet
|
||||||
|
|
||||||
|
// If this packet is from the same server edit as the last packet we accepted from the server
|
||||||
|
// we probably want to use it.
|
||||||
|
if (fromSameServerEdit) {
|
||||||
|
// If this is from the same sever packet, then check against any local changes since we got
|
||||||
|
// the most recent packet from this server time
|
||||||
|
if (_lastEdited > _lastEditedFromRemote) {
|
||||||
|
ignoreServerPacket = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If this isn't from the same sever packet, then honor our skew adjusted times...
|
||||||
|
// If we've changed our local tree more recently than the new data from this packet
|
||||||
|
// then we will not be changing our values, instead we just read and skip the data
|
||||||
|
if (_lastEdited > lastEditedFromBufferAdjusted) {
|
||||||
|
ignoreServerPacket = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoreServerPacket) {
|
||||||
|
overwriteLocalData = false;
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
quint64 lastEdited = getLastEdited();
|
qCDebug(entities) << "IGNORING old data from server!!! ****************";
|
||||||
float editedAgo = getEditedAgo();
|
|
||||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
|
||||||
QString ageAsString = formatSecondsElapsed(getAge());
|
|
||||||
qCDebug(entities) << "------------------------------------------";
|
|
||||||
qCDebug(entities) << "Loading entity " << getEntityItemID() << " from buffer...";
|
|
||||||
qCDebug(entities) << "------------------------------------------";
|
|
||||||
debugDump();
|
debugDump();
|
||||||
qCDebug(entities) << "------------------------------------------";
|
|
||||||
qCDebug(entities) << " _created =" << _created;
|
|
||||||
qCDebug(entities) << " age=" << getAge() << "seconds - " << ageAsString;
|
|
||||||
qCDebug(entities) << " lastEdited =" << lastEdited;
|
|
||||||
qCDebug(entities) << " ago=" << editedAgo << "seconds - " << agoAsString;
|
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
quint64 lastEditedFromBuffer = 0;
|
|
||||||
quint64 lastEditedFromBufferAdjusted = 0;
|
|
||||||
|
|
||||||
// TODO: we could make this encoded as a delta from _created
|
|
||||||
// _lastEdited
|
|
||||||
memcpy(&lastEditedFromBuffer, dataAt, sizeof(lastEditedFromBuffer));
|
|
||||||
dataAt += sizeof(lastEditedFromBuffer);
|
|
||||||
bytesRead += sizeof(lastEditedFromBuffer);
|
|
||||||
lastEditedFromBufferAdjusted = lastEditedFromBuffer - clockSkew;
|
|
||||||
if (lastEditedFromBufferAdjusted > now) {
|
|
||||||
lastEditedFromBufferAdjusted = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fromSameServerEdit = (lastEditedFromBuffer == _lastEditedFromRemoteInRemoteTime);
|
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entities) << "data from server **************** ";
|
qCDebug(entities) << "USING NEW data from server!!! ****************";
|
||||||
qCDebug(entities) << " entityItemID:" << getEntityItemID();
|
debugDump();
|
||||||
qCDebug(entities) << " now:" << now;
|
|
||||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
|
||||||
qCDebug(entities) << " lastEditedFromBuffer:" << debugTime(lastEditedFromBuffer, now);
|
|
||||||
qCDebug(entities) << " clockSkew:" << debugTimeOnly(clockSkew);
|
|
||||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
|
||||||
qCDebug(entities) << " _lastEditedFromRemote:" << debugTime(_lastEditedFromRemote, now);
|
|
||||||
qCDebug(entities) << " _lastEditedFromRemoteInRemoteTime:" << debugTime(_lastEditedFromRemoteInRemoteTime, now);
|
|
||||||
qCDebug(entities) << " fromSameServerEdit:" << fromSameServerEdit;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ignoreServerPacket = false; // assume we'll use this server packet
|
// don't allow _lastEdited to be in the future
|
||||||
|
_lastEdited = lastEditedFromBufferAdjusted;
|
||||||
// If this packet is from the same server edit as the last packet we accepted from the server
|
_lastEditedFromRemote = now;
|
||||||
// we probably want to use it.
|
_lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer;
|
||||||
if (fromSameServerEdit) {
|
|
||||||
// If this is from the same sever packet, then check against any local changes since we got
|
|
||||||
// the most recent packet from this server time
|
|
||||||
if (_lastEdited > _lastEditedFromRemote) {
|
|
||||||
ignoreServerPacket = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If this isn't from the same sever packet, then honor our skew adjusted times...
|
|
||||||
// If we've changed our local tree more recently than the new data from this packet
|
|
||||||
// then we will not be changing our values, instead we just read and skip the data
|
|
||||||
if (_lastEdited > lastEditedFromBufferAdjusted) {
|
|
||||||
ignoreServerPacket = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreServerPacket) {
|
// TODO: only send this notification if something ACTUALLY changed (hint, we haven't yet parsed
|
||||||
overwriteLocalData = false;
|
// the properties out of the bitstream (see below))
|
||||||
#ifdef WANT_DEBUG
|
somethingChangedNotification(); // notify derived classes that something has changed
|
||||||
qCDebug(entities) << "IGNORING old data from server!!! ****************";
|
}
|
||||||
debugDump();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
// last updated is stored as ByteCountCoded delta from lastEdited
|
||||||
qCDebug(entities) << "USING NEW data from server!!! ****************";
|
QByteArray encodedUpdateDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||||
debugDump();
|
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
||||||
#endif
|
quint64 updateDelta = updateDeltaCoder;
|
||||||
|
if (overwriteLocalData) {
|
||||||
// don't allow _lastEdited to be in the future
|
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that
|
||||||
_lastEdited = lastEditedFromBufferAdjusted;
|
#ifdef WANT_DEBUG
|
||||||
_lastEditedFromRemote = now;
|
qCDebug(entities) << " _lastUpdated:" << debugTime(_lastUpdated, now);
|
||||||
_lastEditedFromRemoteInRemoteTime = lastEditedFromBuffer;
|
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||||
|
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||||
// TODO: only send this notification if something ACTUALLY changed (hint, we haven't yet parsed
|
#endif
|
||||||
// the properties out of the bitstream (see below))
|
}
|
||||||
somethingChangedNotification(); // notify derived classes that something has changed
|
encodedUpdateDelta = updateDeltaCoder; // determine true length
|
||||||
}
|
dataAt += encodedUpdateDelta.size();
|
||||||
|
bytesRead += encodedUpdateDelta.size();
|
||||||
// last updated is stored as ByteCountCoded delta from lastEdited
|
|
||||||
QByteArray encodedUpdateDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
// Newer bitstreams will have a last simulated and a last updated value
|
||||||
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
||||||
quint64 updateDelta = updateDeltaCoder;
|
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||||
|
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||||
|
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||||
|
quint64 simulatedDelta = simulatedDeltaCoder;
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
_lastUpdated = lastEditedFromBufferAdjusted + updateDelta; // don't adjust for clock skew since we already did that
|
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entities) << " _lastUpdated:" << debugTime(_lastUpdated, now);
|
qCDebug(entities) << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
||||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
encodedUpdateDelta = updateDeltaCoder; // determine true length
|
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||||
dataAt += encodedUpdateDelta.size();
|
dataAt += encodedSimulatedDelta.size();
|
||||||
bytesRead += encodedUpdateDelta.size();
|
bytesRead += encodedSimulatedDelta.size();
|
||||||
|
}
|
||||||
// Newer bitstreams will have a last simulated and a last updated value
|
|
||||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
#ifdef WANT_DEBUG
|
||||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
if (overwriteLocalData) {
|
||||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
qCDebug(entities) << "EntityItem::readEntityDataFromBuffer()... changed entity:" << getEntityItemID();
|
||||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||||
quint64 simulatedDelta = simulatedDeltaCoder;
|
qCDebug(entities) << " getLastSimulated:" << debugTime(getLastSimulated(), now);
|
||||||
|
qCDebug(entities) << " getLastUpdated:" << debugTime(getLastUpdated(), now);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Property Flags
|
||||||
|
QByteArray encodedPropertyFlags = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||||
|
EntityPropertyFlags propertyFlags = encodedPropertyFlags;
|
||||||
|
dataAt += propertyFlags.getEncodedLength();
|
||||||
|
bytesRead += propertyFlags.getEncodedLength();
|
||||||
|
bool useMeters = (args.bitstreamVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS);
|
||||||
|
if (useMeters) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
|
||||||
|
} else {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePositionInDomainUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS
|
||||||
|
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) {
|
||||||
|
if (propertyFlags.getHasProperty(PROP_RADIUS)) {
|
||||||
|
float fromBuffer;
|
||||||
|
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer));
|
||||||
|
dataAt += sizeof(fromBuffer);
|
||||||
|
bytesRead += sizeof(fromBuffer);
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
setRadius(fromBuffer);
|
||||||
#ifdef WANT_DEBUG
|
|
||||||
qCDebug(entities) << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
|
||||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
|
||||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
|
||||||
dataAt += encodedSimulatedDelta.size();
|
|
||||||
bytesRead += encodedSimulatedDelta.size();
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
#ifdef WANT_DEBUG
|
|
||||||
if (overwriteLocalData) {
|
|
||||||
qCDebug(entities) << "EntityItem::readEntityDataFromBuffer()... changed entity:" << getEntityItemID();
|
|
||||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
|
||||||
qCDebug(entities) << " getLastSimulated:" << debugTime(getLastSimulated(), now);
|
|
||||||
qCDebug(entities) << " getLastUpdated:" << debugTime(getLastUpdated(), now);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Property Flags
|
|
||||||
QByteArray encodedPropertyFlags = originalDataBuffer.mid(bytesRead); // maximum possible size
|
|
||||||
EntityPropertyFlags propertyFlags = encodedPropertyFlags;
|
|
||||||
dataAt += propertyFlags.getEncodedLength();
|
|
||||||
bytesRead += propertyFlags.getEncodedLength();
|
|
||||||
bool useMeters = (args.bitstreamVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS);
|
|
||||||
if (useMeters) {
|
if (useMeters) {
|
||||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition);
|
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
||||||
} else {
|
} else {
|
||||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePositionInDomainUnits);
|
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits);
|
||||||
}
|
|
||||||
|
|
||||||
// Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS
|
|
||||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) {
|
|
||||||
if (propertyFlags.getHasProperty(PROP_RADIUS)) {
|
|
||||||
float fromBuffer;
|
|
||||||
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer));
|
|
||||||
dataAt += sizeof(fromBuffer);
|
|
||||||
bytesRead += sizeof(fromBuffer);
|
|
||||||
if (overwriteLocalData) {
|
|
||||||
setRadius(fromBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (useMeters) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions);
|
|
||||||
} else {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
|
|
||||||
if (useMeters) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
|
|
||||||
} else {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits);
|
|
||||||
}
|
|
||||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
|
||||||
if (useMeters) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
|
||||||
} else {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
|
|
||||||
}
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
|
||||||
|
|
||||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_SIMULATOR_ID, QUuid, updateSimulatorID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
|
||||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
|
||||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
|
||||||
|
|
||||||
////////////////////////////////////
|
|
||||||
// WARNING: Do not add stream content here after the subclass. Always add it before the subclass
|
|
||||||
//
|
|
||||||
// NOTE: we had a bad version of the stream that we added stream data after the subclass. We can attempt to recover
|
|
||||||
// by doing this parsing here... but it's not likely going to fully recover the content.
|
|
||||||
//
|
|
||||||
// TODO: Remove this conde once we've sufficiently migrated content past this damaged version
|
|
||||||
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) {
|
|
||||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES))) {
|
|
||||||
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
|
||||||
// closely match where the entities should be if they'd stepped forward in time to "now". The server
|
|
||||||
// is sending us data with a known "last simulated" time. That time is likely in the past, and therefore
|
|
||||||
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
|
||||||
// use our simulation helper routine to get a best estimate of where the entity should be.
|
|
||||||
const float MIN_TIME_SKIP = 0.0f;
|
|
||||||
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
|
||||||
float skipTimeForward = glm::clamp((float)(now - _lastSimulated) / (float)(USECS_PER_SECOND),
|
|
||||||
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
|
||||||
if (skipTimeForward > 0.0f) {
|
|
||||||
#ifdef WANT_DEBUG
|
|
||||||
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
|
||||||
// we don't want the side effect of flag setting.
|
|
||||||
simulateKinematicMotion(skipTimeForward, false);
|
|
||||||
}
|
|
||||||
_lastSimulated = now;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity);
|
||||||
|
if (useMeters) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity);
|
||||||
|
} else {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits);
|
||||||
|
}
|
||||||
|
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration);
|
||||||
|
}
|
||||||
|
|
||||||
|
READ_ENTITY_PROPERTY(PROP_DAMPING, float, updateDamping);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, updateRestitution);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_FRICTION, float, updateFriction);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||||
|
if (useMeters) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||||
|
} else {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees);
|
||||||
|
}
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
||||||
|
|
||||||
|
if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) {
|
||||||
|
// we always accept the server's notion of simulatorID, so we fake overwriteLocalData as true
|
||||||
|
// before we try to READ_ENTITY_PROPERTY it
|
||||||
|
bool temp = overwriteLocalData;
|
||||||
|
overwriteLocalData = true;
|
||||||
|
READ_ENTITY_PROPERTY(PROP_SIMULATOR_ID, QUuid, updateSimulatorID);
|
||||||
|
overwriteLocalData = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||||
|
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData);
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// WARNING: Do not add stream content here after the subclass. Always add it before the subclass
|
||||||
|
//
|
||||||
|
// NOTE: we had a bad version of the stream that we added stream data after the subclass. We can attempt to recover
|
||||||
|
// by doing this parsing here... but it's not likely going to fully recover the content.
|
||||||
|
//
|
||||||
|
// TODO: Remove this conde once we've sufficiently migrated content past this damaged version
|
||||||
|
if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) {
|
||||||
|
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES))) {
|
||||||
|
// NOTE: This code is attempting to "repair" the old data we just got from the server to make it more
|
||||||
|
// closely match where the entities should be if they'd stepped forward in time to "now". The server
|
||||||
|
// is sending us data with a known "last simulated" time. That time is likely in the past, and therefore
|
||||||
|
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
||||||
|
// use our simulation helper routine to get a best estimate of where the entity should be.
|
||||||
|
const float MIN_TIME_SKIP = 0.0f;
|
||||||
|
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
||||||
|
float skipTimeForward = glm::clamp((float)(now - _lastSimulated) / (float)(USECS_PER_SECOND),
|
||||||
|
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
||||||
|
if (skipTimeForward > 0.0f) {
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
||||||
|
// we don't want the side effect of flag setting.
|
||||||
|
simulateKinematicMotion(skipTimeForward, false);
|
||||||
|
}
|
||||||
|
_lastSimulated = now;
|
||||||
|
}
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||||
if (_simulatorID == myNodeID && !_simulatorID.isNull()) {
|
if (overwriteLocalData && _simulatorID == myNodeID && !_simulatorID.isNull()) {
|
||||||
// the packet that produced this bitstream originally came from physics simulations performed by
|
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
|
||||||
// this node, so our version has to be newer than what the packet contained.
|
// rather than accept the values in the packet
|
||||||
_position = savePosition;
|
_position = savePosition;
|
||||||
_rotation = saveRotation;
|
_rotation = saveRotation;
|
||||||
// _velocity = saveVelocity;
|
_velocity = saveVelocity;
|
||||||
// _angularVelocity = saveAngularVelocity;
|
_angularVelocity = saveAngularVelocity;
|
||||||
// _gravity = saveGravity;
|
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
|
||||||
// _acceleration = saveAcceleration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
@ -949,40 +949,25 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
||||||
|
|
||||||
if (somethingChanged) {
|
if (somethingChanged) {
|
||||||
somethingChangedNotification(); // notify derived classes that something has changed
|
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
int elapsed = now - getLastEdited();
|
int elapsed = now - getLastEdited();
|
||||||
qCDebug(entities) << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
qCDebug(entities) << "EntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||||
#endif
|
#endif
|
||||||
if (_created != UNKNOWN_CREATED_TIME) {
|
setLastEdited(now);
|
||||||
setLastEdited(now);
|
somethingChangedNotification(); // notify derived classes that something has changed
|
||||||
|
if (_created == UNKNOWN_CREATED_TIME) {
|
||||||
|
_created = now;
|
||||||
}
|
}
|
||||||
if (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES)) {
|
if (getDirtyFlags() & (EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES)) {
|
||||||
// TODO: Andrew & Brad to discuss. Is this correct? Maybe it is. Need to think through all cases.
|
// anything that sets the transform or velocity must update _lastSimulated which is used
|
||||||
|
// for kinematic extrapolation (e.g. we want to extrapolate forward from this moment
|
||||||
|
// when position and/or velocity was changed).
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// timestamps
|
|
||||||
quint64 timestamp = properties.getCreated();
|
|
||||||
if (_created == UNKNOWN_CREATED_TIME && timestamp != UNKNOWN_CREATED_TIME) {
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
if (timestamp > now) {
|
|
||||||
timestamp = now;
|
|
||||||
}
|
|
||||||
_created = timestamp;
|
|
||||||
|
|
||||||
timestamp = properties.getLastEdited();
|
|
||||||
if (timestamp > now) {
|
|
||||||
timestamp = now;
|
|
||||||
} else if (timestamp < _created) {
|
|
||||||
timestamp = _created;
|
|
||||||
}
|
|
||||||
_lastEdited = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return somethingChanged;
|
return somethingChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,6 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const {
|
||||||
uint32_t thisStep = ObjectMotionState::getWorldSimulationStep();
|
uint32_t thisStep = ObjectMotionState::getWorldSimulationStep();
|
||||||
float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP;
|
float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP;
|
||||||
_entity->simulateKinematicMotion(dt);
|
_entity->simulateKinematicMotion(dt);
|
||||||
_entity->setLastSimulated(usecTimestampNow());
|
|
||||||
|
|
||||||
// bypass const-ness so we can remember the step
|
// bypass const-ness so we can remember the step
|
||||||
const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep;
|
const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep;
|
||||||
|
@ -401,13 +400,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
||||||
properties.setAcceleration(_serverAcceleration);
|
properties.setAcceleration(_serverAcceleration);
|
||||||
properties.setAngularVelocity(_serverAngularVelocity);
|
properties.setAngularVelocity(_serverAngularVelocity);
|
||||||
|
|
||||||
// we only update lastEdited when we're sending new physics data
|
// set the LastEdited of the properties but NOT the entity itself
|
||||||
quint64 lastSimulated = _entity->getLastSimulated();
|
quint64 now = usecTimestampNow();
|
||||||
_entity->setLastEdited(lastSimulated);
|
properties.setLastEdited(now);
|
||||||
properties.setLastEdited(lastSimulated);
|
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
quint64 now = usecTimestampNow();
|
quint64 lastSimulated = _entity->getLastSimulated();
|
||||||
qCDebug(physics) << "EntityMotionState::sendUpdate()";
|
qCDebug(physics) << "EntityMotionState::sendUpdate()";
|
||||||
qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID()
|
qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID()
|
||||||
<< "---------------------------------------------";
|
<< "---------------------------------------------";
|
||||||
|
|
Loading…
Reference in a new issue