Merge pull request #10696 from AndrewMeadows/avoid-ownership-bid-race

ignore remote update younger than recent ownership bid
This commit is contained in:
Seth Alves 2017-06-20 10:42:54 -07:00 committed by GitHub
commit 428dc81083
3 changed files with 43 additions and 25 deletions

View file

@ -386,7 +386,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
return 0; return 0;
} }
qint64 clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; int64_t clockSkew = 0;
uint64_t maxPingRoundTrip = 33333; // two frames periods at 60 fps
if (args.sourceNode) {
clockSkew = args.sourceNode->getClockSkewUsec();
const float MSECS_PER_USEC = 1000;
maxPingRoundTrip += args.sourceNode->getPingMs() * MSECS_PER_USEC;
}
BufferParser parser(data, bytesLeftToRead); BufferParser parser(data, bytesLeftToRead);
@ -653,7 +659,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
const QUuid& myNodeID = nodeList->getSessionUUID(); const QUuid& myNodeID = nodeList->getSessionUUID();
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
// pack SimulationOwner and terse update properties near each other // pack SimulationOwner and terse update properties near each other
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data // NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
// even when we would otherwise ignore the rest of the packet. // even when we would otherwise ignore the rest of the packet.
@ -678,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) { if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) {
// entity-server is trying to clear our ownership (probably at our own request) // entity-server is trying to clear our ownership (probably at our own request)
// but we actually want to own it, therefore we ignore this clear event // but we actually want to own it, therefore we ignore this clear event
// and pretend that we own it (we assume we'll recover it soon) // and pretend that we own it (e.g. we assume we'll receive ownership soon)
// However, for now, when the server uses a newer time than what we sent, listen to what we're told. // However, for now, when the server uses a newer time than what we sent, listen to what we're told.
if (overwriteLocalData) { if (overwriteLocalData) {
@ -690,16 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// recompute weOwnSimulation for later // recompute weOwnSimulation for later
weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
} }
} else if (newSimOwner.getID().isNull() && _simulationOwner.pendingTake(lastEditedFromBufferAdjusted)) { } else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) {
// entity-server is trying to clear someone else's ownership // we sent a bid before this packet could have been sent from the server
// but we want to own it, therefore we ignore this clear event // so we ignore it and pretend we own the object's simulation
// and pretend that we own it (we assume we'll get it soon)
weOwnSimulation = true; weOwnSimulation = true;
if (!_simulationOwner.isNull()) { if (newSimOwner.getID().isNull()) {
// someone else really did own it // entity-server is trying to clear someone else's ownership
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); // but we want to own it, therefore we ignore this clear event
somethingChanged = true; if (!_simulationOwner.isNull()) {
_simulationOwner.clearCurrentOwner(); // someone else really did own it
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true;
_simulationOwner.clearCurrentOwner();
}
} }
} else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) {
// entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem,

View file

@ -23,14 +23,16 @@ const uint16_t ObjectActionTractor::tractorVersion = 1;
ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) : ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer ownerEntity) :
ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity), ObjectAction(DYNAMIC_TYPE_TRACTOR, id, ownerEntity),
_positionalTarget(glm::vec3(0.0f)), _positionalTarget(0.0f),
_desiredPositionalTarget(glm::vec3(0.0f)), _desiredPositionalTarget(0.0f),
_linearTimeScale(FLT_MAX), _linearTimeScale(FLT_MAX),
_positionalTargetSet(true), _positionalTargetSet(false),
_rotationalTarget(glm::quat()), _rotationalTarget(),
_desiredRotationalTarget(glm::quat()), _desiredRotationalTarget(),
_angularTimeScale(FLT_MAX), _angularTimeScale(FLT_MAX),
_rotationalTargetSet(true) { _rotationalTargetSet(true),
_linearVelocityTarget(0.0f)
{
#if WANT_DEBUG #if WANT_DEBUG
qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor"; qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor";
#endif #endif
@ -77,7 +79,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
glm::quat rotation; glm::quat rotation;
glm::vec3 position; glm::vec3 position;
glm::vec3 linearVelocity;
glm::vec3 angularVelocity; glm::vec3 angularVelocity;
bool linearValid = false; bool linearValid = false;
@ -117,7 +118,6 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
linearValid = true; linearValid = true;
linearTractorCount++; linearTractorCount++;
position += positionForAction; position += positionForAction;
linearVelocity += linearVelocityForAction;
} }
} }
} }
@ -126,9 +126,18 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
withWriteLock([&]{ withWriteLock([&]{
if (linearValid && linearTractorCount > 0) { if (linearValid && linearTractorCount > 0) {
position /= linearTractorCount; position /= linearTractorCount;
linearVelocity /= linearTractorCount; if (_positionalTargetSet) {
_lastPositionTarget = _positionalTarget;
} else {
_lastPositionTarget = position;
}
_positionalTarget = position; _positionalTarget = position;
_linearVelocityTarget = linearVelocity; if (deltaTimeStep > EPSILON) {
// blend the new velocity with the old (low-pass filter)
glm::vec3 newVelocity = (1.0f / deltaTimeStep) * (position - _lastPositionTarget);
const float blend = 0.25f;
_linearVelocityTarget = (1.0f - blend) * _linearVelocityTarget + blend * newVelocity;
}
_positionalTargetSet = true; _positionalTargetSet = true;
_active = true; _active = true;
} }
@ -169,19 +178,19 @@ void ObjectActionTractor::updateActionWorker(btScalar deltaTimeStep) {
} }
if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) { if (_linearTimeScale < MAX_TRACTOR_TIMESCALE) {
btVector3 targetVelocity(0.0f, 0.0f, 0.0f); btVector3 offsetVelocity(0.0f, 0.0f, 0.0f);
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget); btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
float offsetLength = offset.length(); float offsetLength = offset.length();
if (offsetLength > FLT_EPSILON) { if (offsetLength > FLT_EPSILON) {
float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED); float speed = glm::min(offsetLength / _linearTimeScale, TRACTOR_MAX_SPEED);
targetVelocity = (-speed / offsetLength) * offset; offsetVelocity = (-speed / offsetLength) * offset;
if (speed > rigidBody->getLinearSleepingThreshold()) { if (speed > rigidBody->getLinearSleepingThreshold()) {
forceBodyNonStatic(); forceBodyNonStatic();
rigidBody->activate(); rigidBody->activate();
} }
} }
// this action is aggresively critically damped and defeats the current velocity // this action is aggresively critically damped and defeats the current velocity
rigidBody->setLinearVelocity(targetVelocity); rigidBody->setLinearVelocity(glmToBullet(_linearVelocityTarget) + offsetVelocity);
} }
if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) { if (_angularTimeScale < MAX_TRACTOR_TIMESCALE) {

View file

@ -36,6 +36,7 @@ protected:
glm::vec3 _positionalTarget; glm::vec3 _positionalTarget;
glm::vec3 _desiredPositionalTarget; glm::vec3 _desiredPositionalTarget;
glm::vec3 _lastPositionTarget;
float _linearTimeScale; float _linearTimeScale;
bool _positionalTargetSet; bool _positionalTargetSet;