From b472edbebb045e39660310dc77967933a20c8f29 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 9 Apr 2015 09:26:14 -0700 Subject: [PATCH 01/60] remove debug print for something that no longer exists --- libraries/entities/src/EntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2fb943c0b6..5fae58c5f4 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -766,7 +766,6 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { qCDebug(entities) << " damping:" << _damping; qCDebug(entities) << " velocity AFTER dampingResistance:" << velocity; qCDebug(entities) << " glm::length(velocity):" << glm::length(velocity); - qCDebug(entities) << " velocityEspilon :" << ENTITY_ITEM_EPSILON_VELOCITY_LENGTH; #endif } From e2af93db5f449bcf9f7a9156be771a513c998837 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 11:38:30 -0700 Subject: [PATCH 02/60] some debugging --- libraries/physics/src/EntityMotionState.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index d84daa6b42..f0daaa6b4c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -180,6 +180,11 @@ float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const { } void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) { + + qDebug() << "-------------------------------------------"; + qDebug() << "EntityMotionState::sendUpdate" << _type << _motionType << _isKinematic; + auto nodeList = DependencyManager::get(); + if (!_entity->isKnownID()) { return; // never update entities that are unknown } From eace91e833061a2c058df151517e023bbb3ecbce Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 12:25:44 -0700 Subject: [PATCH 03/60] if an entity is being moved and has no sim-id, set sim-id to local node-id. if it has a sim-id, and it's not the same as the local node's, don't broadcast the change --- libraries/physics/src/EntityMotionState.cpp | 41 +++++++++++++++++++-- libraries/physics/src/EntityMotionState.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index f0daaa6b4c..c2206c90f7 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -179,12 +179,41 @@ float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const { return _entity->computeMass(); } -void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) { - qDebug() << "-------------------------------------------"; - qDebug() << "EntityMotionState::sendUpdate" << _type << _motionType << _isKinematic; +bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { + bool baseResult = this->ObjectMotionState::shouldSendUpdate(simulationFrame); + + if (!baseResult) { + return false; + } + auto nodeList = DependencyManager::get(); + QString myNodeID = nodeList->getSessionUUID().toString(); + QString simulatorID = _entity->getSimulatorID(); + if (simulatorID.isEmpty() && _body->isActive()) { + // The object is moving and nobody thinks they own the motion. set this Node as the simulator + _entity->setSimulatorID(myNodeID); + simulatorID = myNodeID; + } else if (simulatorID == myNodeID && !_body->isActive()) { + // we are the simulator and the object has stopped. give up "simulator" status + _entity->setSimulatorID(""); + simulatorID = ""; + } + + if (simulatorID != myNodeID) { + // some other Node is simulating this, so don't broadcast our computations. + qDebug() << "EntityMotionState::shouldSendUpdate baseResult=" << baseResult << "but" + << simulatorID << "!=" << myNodeID; + return false; + } + + qDebug() << "EntityMotionState::shouldSendUpdate baseResult=" << baseResult; + return baseResult; +} + + +void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) { if (!_entity->isKnownID()) { return; // never update entities that are unknown } @@ -218,6 +247,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ } _sentMoving = ! (zeroSpeed && zeroSpin); + + + qDebug() << "-------------------------------------------"; + qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); + + } else { _sentVelocity = _sentAngularVelocity = glm::vec3(0.0f); _sentMoving = false; diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 7214626fc4..84da86ecae 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -56,6 +56,7 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); virtual float computeMass(const ShapeInfo& shapeInfo) const; + virtual bool shouldSendUpdate(uint32_t simulationFrame); virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame); virtual uint32_t getIncomingDirtyFlags() const; From f42a43e180a0c1a13a8c9a8f4e9593b19a56bbf0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 12:39:40 -0700 Subject: [PATCH 04/60] cause changes to _simulatorID to be broadcast --- libraries/entities/src/EntityItem.cpp | 6 ++++++ libraries/entities/src/EntityItem.h | 1 + libraries/physics/src/EntityMotionState.cpp | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5fae58c5f4..02e525be3d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1194,3 +1194,9 @@ void EntityItem::updateLifetime(float value) { } } +void EntityItem::updateSimulatorID(QString value) { + if (_simulatorID != value) { + _simulatorID = value; + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + } +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8f7feb2ed8..8388985432 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -294,6 +294,7 @@ public: void updateCollisionsWillMove(bool value); void updateLifetime(float value); virtual void updateShapeType(ShapeType type) { /* do nothing */ } + void updateSimulatorID(QString value); uint32_t getDirtyFlags() const { return _dirtyFlags; } void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c2206c90f7..de806bb857 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -193,11 +193,11 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { if (simulatorID.isEmpty() && _body->isActive()) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator - _entity->setSimulatorID(myNodeID); + _entity->updateSimulatorID(myNodeID); simulatorID = myNodeID; } else if (simulatorID == myNodeID && !_body->isActive()) { // we are the simulator and the object has stopped. give up "simulator" status - _entity->setSimulatorID(""); + _entity->updateSimulatorID(""); simulatorID = ""; } From 9c2fec36fdce8617bb6e61ca9416da881a8ec8f8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 12:52:31 -0700 Subject: [PATCH 05/60] adjust debugging, try a different DIRTY flag --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/physics/src/EntityMotionState.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 02e525be3d..023d60e22c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1197,6 +1197,6 @@ void EntityItem::updateLifetime(float value) { void EntityItem::updateSimulatorID(QString value) { if (_simulatorID != value) { _simulatorID = value; - _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; + _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; } } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index de806bb857..32bd36570b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -208,7 +208,6 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { return false; } - qDebug() << "EntityMotionState::shouldSendUpdate baseResult=" << baseResult; return baseResult; } @@ -248,11 +247,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _sentMoving = ! (zeroSpeed && zeroSpin); - - qDebug() << "-------------------------------------------"; qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); - } else { _sentVelocity = _sentAngularVelocity = glm::vec3(0.0f); _sentMoving = false; From 396f6b1987b7aa7aa013d11c372f71340e69556b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 15:22:54 -0700 Subject: [PATCH 06/60] mess with debugging prints --- libraries/entities/src/EntityEditPacketSender.cpp | 2 ++ libraries/entities/src/EntityItem.cpp | 3 ++- libraries/entities/src/EntityItemProperties.h | 1 + libraries/physics/src/EntityMotionState.cpp | 4 ++++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index e94725782d..d2dc367aa3 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -18,6 +18,8 @@ #include "EntityItem.h" +#define WANT_DEBUG 1 + void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, unsigned char* editBuffer, size_t length, int clockSkew) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 023d60e22c..fb8e430959 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -680,6 +680,7 @@ void EntityItem::simulate(const quint64& now) { #ifdef WANT_DEBUG qCDebug(entities) << "********** EntityItem::simulate()"; qCDebug(entities) << " entity ID=" << getEntityItemID(); + qCDebug(entities) << " simulator ID=" << getSimulatorID(); qCDebug(entities) << " now=" << now; qCDebug(entities) << " _lastSimulated=" << _lastSimulated; qCDebug(entities) << " timeElapsed=" << timeElapsed; @@ -1197,6 +1198,6 @@ void EntityItem::updateLifetime(float value) { void EntityItem::updateSimulatorID(QString value) { if (_simulatorID != value) { _simulatorID = value; - _dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE; + _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; } } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 7de0fc0e8b..09a1b17ae5 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -343,6 +343,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, SimulatorID, simulatorID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); debug << " last edited:" << properties.getLastEdited() << "\n"; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 32bd36570b..ca22831d38 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -219,6 +219,10 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ if (_outgoingPacketFlags) { EntityItemProperties properties = _entity->getProperties(); + // if (_outgoingPacketFlags & EntityItem::DIRTY_UPDATEABLE) { + // properties.setSimulatorID(_entity->getSimulatorID()); + // } + if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); _sentPosition = bulletToGLM(worldTrans.getOrigin()); From a30e807051b9f828013106139d8ff9c301ca881b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:20:30 -0700 Subject: [PATCH 07/60] get rid of unneeded updateSimulatorID, set changed simulator id in properties so it gets included in outgoing packet --- libraries/entities/src/EntityItem.cpp | 7 ----- libraries/entities/src/EntityItem.h | 1 - libraries/physics/src/EntityMotionState.cpp | 35 +++++++++++++++------ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index fb8e430959..da98b4f350 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1194,10 +1194,3 @@ void EntityItem::updateLifetime(float value) { _dirtyFlags |= EntityItem::DIRTY_LIFETIME; } } - -void EntityItem::updateSimulatorID(QString value) { - if (_simulatorID != value) { - _simulatorID = value; - _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; - } -} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8388985432..8f7feb2ed8 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -294,7 +294,6 @@ public: void updateCollisionsWillMove(bool value); void updateLifetime(float value); virtual void updateShapeType(ShapeType type) { /* do nothing */ } - void updateSimulatorID(QString value); uint32_t getDirtyFlags() const { return _dirtyFlags; } void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index ca22831d38..17cc06267d 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,13 +191,13 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty() && _body->isActive()) { + if (simulatorID.isEmpty() && _sentMoving) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator - _entity->updateSimulatorID(myNodeID); + // _entity->updateSimulatorID(myNodeID); simulatorID = myNodeID; - } else if (simulatorID == myNodeID && !_body->isActive()) { + } else if (simulatorID == myNodeID && !_sentMoving) { // we are the simulator and the object has stopped. give up "simulator" status - _entity->updateSimulatorID(""); + // _entity->updateSimulatorID(""); simulatorID = ""; } @@ -219,9 +219,9 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ if (_outgoingPacketFlags) { EntityItemProperties properties = _entity->getProperties(); - // if (_outgoingPacketFlags & EntityItem::DIRTY_UPDATEABLE) { - // properties.setSimulatorID(_entity->getSimulatorID()); - // } + + + if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); @@ -250,9 +250,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ } _sentMoving = ! (zeroSpeed && zeroSpin); - - qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); - } else { _sentVelocity = _sentAngularVelocity = glm::vec3(0.0f); _sentMoving = false; @@ -263,6 +260,24 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setAngularVelocity(_sentAngularVelocity); } + + qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); + + auto nodeList = DependencyManager::get(); + QString myNodeID = nodeList->getSessionUUID().toString(); + QString simulatorID = _entity->getSimulatorID(); + + if (simulatorID.isEmpty() && _sentMoving) { + // The object is moving and nobody thinks they own the motion. set this Node as the simulator + _entity->setSimulatorID(myNodeID); + properties.setSimulatorID(myNodeID); + } else if (simulatorID == myNodeID && !_sentMoving) { + // we are the simulator and the object has stopped. give up "simulator" status + _entity->setSimulatorID(""); + properties.setSimulatorID(""); + } + + // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. if (_sentMoving) { _numNonMovingUpdates = 0; From 4677324a87a1ac33cfa5fe0f731f491f1ca36d19 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:30:16 -0700 Subject: [PATCH 08/60] try different login for deciding when to update/clear simulatorID --- libraries/physics/src/EntityMotionState.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 17cc06267d..e776232c01 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,13 +191,11 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty() && _sentMoving) { + if (simulatorID.isEmpty() && baseResult) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator - // _entity->updateSimulatorID(myNodeID); simulatorID = myNodeID; - } else if (simulatorID == myNodeID && !_sentMoving) { + } else if (simulatorID == myNodeID && _numNonMovingUpdates > 0) { // we are the simulator and the object has stopped. give up "simulator" status - // _entity->updateSimulatorID(""); simulatorID = ""; } @@ -262,16 +260,14 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); - auto nodeList = DependencyManager::get(); QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - - if (simulatorID.isEmpty() && _sentMoving) { + if (simulatorID.isEmpty()) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && !_sentMoving) { + } else if (simulatorID == myNodeID && _numNonMovingUpdates > 0) { // we are the simulator and the object has stopped. give up "simulator" status _entity->setSimulatorID(""); properties.setSimulatorID(""); From 256a7f5198893f5ec292f8192b7d26c04215acff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:37:44 -0700 Subject: [PATCH 09/60] try different login for deciding when to update/clear simulatorID --- libraries/physics/src/EntityMotionState.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index e776232c01..617b3b1a9a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -199,10 +199,8 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { simulatorID = ""; } - if (simulatorID != myNodeID) { + if (!simulatorID.isEmpty() && simulatorID != myNodeID) { // some other Node is simulating this, so don't broadcast our computations. - qDebug() << "EntityMotionState::shouldSendUpdate baseResult=" << baseResult << "but" - << simulatorID << "!=" << myNodeID; return false; } From cf6259c5d73999baf1c17ae924803b009527bc2e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:41:38 -0700 Subject: [PATCH 10/60] turn down debugging --- libraries/entities/src/EntityEditPacketSender.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index d2dc367aa3..e94725782d 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -18,8 +18,6 @@ #include "EntityItem.h" -#define WANT_DEBUG 1 - void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType type, unsigned char* editBuffer, size_t length, int clockSkew) { From 05ef357854c9cb4ee312bea7ea8edb41db9abafa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:47:06 -0700 Subject: [PATCH 11/60] debug prints --- libraries/physics/src/EntityMotionState.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 617b3b1a9a..40010e46df 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -215,10 +215,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ if (_outgoingPacketFlags) { EntityItemProperties properties = _entity->getProperties(); - - - - if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); _sentPosition = bulletToGLM(worldTrans.getOrigin()); @@ -263,10 +259,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ QString simulatorID = _entity->getSimulatorID(); if (simulatorID.isEmpty()) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator + qDebug() << "claiming simulator ownership"; _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); } else if (simulatorID == myNodeID && _numNonMovingUpdates > 0) { // we are the simulator and the object has stopped. give up "simulator" status + qDebug() << "releasing simulator ownership"; _entity->setSimulatorID(""); properties.setSimulatorID(""); } From f7c0637952197c7675d8b2363626acc096c13f13 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 13 Apr 2015 16:51:05 -0700 Subject: [PATCH 12/60] oops --- libraries/entities/src/EntityItemProperties.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 09a1b17ae5..7de0fc0e8b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -343,7 +343,6 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, SimulatorID, simulatorID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); debug << " last edited:" << properties.getLastEdited() << "\n"; From abb40ca0805c1db540115c22a2e944130cd97c3a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 14 Apr 2015 09:00:36 -0700 Subject: [PATCH 13/60] cleanup: split stats dump out of stepSimulation --- interface/src/Application.cpp | 1 + libraries/physics/src/PhysicsEngine.cpp | 127 ++++++++++++------------ libraries/physics/src/PhysicsEngine.h | 3 +- 3 files changed, 67 insertions(+), 64 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82447257fb..73be96c26b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2226,6 +2226,7 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("physics"); _myAvatar->relayDriveKeysToCharacterController(); _physicsEngine.stepSimulation(); + _physicsEngine.dumpStatsIfNecessary(); } if (!_aboutToQuit) { diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 50f52a7efc..209e23e006 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -288,77 +288,73 @@ void PhysicsEngine::init(EntityEditPacketSender* packetSender) { } void PhysicsEngine::stepSimulation() { - { - lock(); - CProfileManager::Reset(); - BT_PROFILE("stepSimulation"); - // NOTE: the grand order of operations is: - // (1) pull incoming changes - // (2) step simulation - // (3) synchronize outgoing motion states - // (4) send outgoing packets + lock(); + CProfileManager::Reset(); + BT_PROFILE("stepSimulation"); + // NOTE: the grand order of operations is: + // (1) pull incoming changes + // (2) step simulation + // (3) synchronize outgoing motion states + // (4) send outgoing packets - // This is step (1) pull incoming changes - relayIncomingChangesToSimulation(); - - const int MAX_NUM_SUBSTEPS = 4; - const float MAX_TIMESTEP = (float)MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP; - float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds()); - _clock.reset(); - float timeStep = btMin(dt, MAX_TIMESTEP); - - // TODO: move character->preSimulation() into relayIncomingChanges - if (_characterController) { - if (_characterController->needsRemoval()) { - _characterController->setDynamicsWorld(NULL); - } - _characterController->updateShapeIfNecessary(); - if (_characterController->needsAddition()) { - _characterController->setDynamicsWorld(_dynamicsWorld); - } - _characterController->preSimulation(timeStep); + // This is step (1) pull incoming changes + relayIncomingChangesToSimulation(); + + const int MAX_NUM_SUBSTEPS = 4; + const float MAX_TIMESTEP = (float)MAX_NUM_SUBSTEPS * PHYSICS_ENGINE_FIXED_SUBSTEP; + float dt = 1.0e-6f * (float)(_clock.getTimeMicroseconds()); + _clock.reset(); + float timeStep = btMin(dt, MAX_TIMESTEP); + + // TODO: move character->preSimulation() into relayIncomingChanges + if (_characterController) { + if (_characterController->needsRemoval()) { + _characterController->setDynamicsWorld(NULL); } - - // This is step (2) step simulation - int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP); - _numSubsteps += (uint32_t)numSubsteps; - stepNonPhysicalKinematics(usecTimestampNow()); - unlock(); - - // TODO: make all of this harvest stuff into one function: relayOutgoingChanges() - if (numSubsteps > 0) { - BT_PROFILE("postSimulation"); - // This is step (3) which is done outside of stepSimulation() so we can lock _entityTree. - // - // Unfortunately we have to unlock the simulation (above) before we try to lock the _entityTree - // to avoid deadlock -- the _entityTree may try to lock its EntitySimulation (from which this - // PhysicsEngine derives) when updating/adding/deleting entities so we need to wait for our own - // lock on the tree before we re-lock ourselves. - // - // TODO: untangle these lock sequences. - _entityTree->lockForWrite(); - lock(); - _dynamicsWorld->synchronizeMotionStates(); - - if (_characterController) { - _characterController->postSimulation(); - } - - unlock(); - _entityTree->unlock(); - - computeCollisionEvents(); + _characterController->updateShapeIfNecessary(); + if (_characterController->needsAddition()) { + _characterController->setDynamicsWorld(_dynamicsWorld); } + _characterController->preSimulation(timeStep); } - if (_dumpNextStats) { - _dumpNextStats = false; - CProfileManager::dumpAll(); + + // This is step (2) step simulation + int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP); + _numSubsteps += (uint32_t)numSubsteps; + stepNonPhysicalKinematics(usecTimestampNow()); + unlock(); + + // TODO: make all of this harvest stuff into one function: relayOutgoingChanges() + if (numSubsteps > 0) { + BT_PROFILE("postSimulation"); + // This is step (3) which is done outside of stepSimulation() so we can lock _entityTree. + // + // Unfortunately we have to unlock the simulation (above) before we try to lock the _entityTree + // to avoid deadlock -- the _entityTree may try to lock its EntitySimulation (from which this + // PhysicsEngine derives) when updating/adding/deleting entities so we need to wait for our own + // lock on the tree before we re-lock ourselves. + // + // TODO: untangle these lock sequences. + ObjectMotionState::setSimulationStep(_numSubsteps); + _entityTree->lockForWrite(); + lock(); + _dynamicsWorld->synchronizeMotionStates(); + + if (_characterController) { + _characterController->postSimulation(); + } + + unlock(); + _entityTree->unlock(); + + computeCollisionEvents(); } } void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) { BT_PROFILE("nonPhysicalKinematics"); QSet::iterator stateItr = _nonPhysicalKinematicObjects.begin(); + // TODO?: need to occasionally scan for stopped non-physical kinematics objects while (stateItr != _nonPhysicalKinematicObjects.end()) { ObjectMotionState* motionState = *stateItr; motionState->stepKinematicSimulation(now); @@ -366,8 +362,6 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) { } } -// TODO?: need to occasionally scan for stopped non-physical kinematics objects - void PhysicsEngine::computeCollisionEvents() { BT_PROFILE("computeCollisionEvents"); // update all contacts every frame @@ -445,6 +439,13 @@ void PhysicsEngine::computeCollisionEvents() { } } +void PhysicsEngine::dumpStatsIfNecessary() { + if (_dumpNextStats) { + _dumpNextStats = false; + CProfileManager::dumpAll(); + } +} + // Bullet collision flags are as follows: // CF_STATIC_OBJECT= 1, // CF_KINEMATIC_OBJECT= 2, diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 01717be175..6e1f430237 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -68,9 +68,10 @@ public: void stepSimulation(); void stepNonPhysicalKinematics(const quint64& now); - void computeCollisionEvents(); + void dumpStatsIfNecessary(); + /// \param offset position of simulation origin in domain-frame void setOriginOffset(const glm::vec3& offset) { _originOffset = offset; } From de2e5ae718115c6d299dfe4d6199e796f4604533 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 09:00:48 -0700 Subject: [PATCH 14/60] adjust logic for when to claim or release simulator status --- libraries/physics/src/EntityMotionState.cpp | 25 +++++++-------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 40010e46df..b4394d52d3 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,20 +191,12 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty() && baseResult) { - // The object is moving and nobody thinks they own the motion. set this Node as the simulator - simulatorID = myNodeID; - } else if (simulatorID == myNodeID && _numNonMovingUpdates > 0) { - // we are the simulator and the object has stopped. give up "simulator" status - simulatorID = ""; - } - if (!simulatorID.isEmpty() && simulatorID != myNodeID) { // some other Node is simulating this, so don't broadcast our computations. return false; } - return baseResult; + return true; } @@ -223,6 +215,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _sentRotation = bulletToGLM(worldTrans.getRotation()); properties.setRotation(_sentRotation); } + + const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec + bool zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); + const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec + bool zeroSpin = glm::length2(_sentAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED; if (_outgoingPacketFlags & EntityItem::DIRTY_VELOCITY) { if (_body->isActive()) { @@ -230,13 +227,9 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); // if the speeds are very small we zero them out - const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec - bool zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); if (zeroSpeed) { _sentVelocity = glm::vec3(0.0f); } - const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec - bool zeroSpin = glm::length2(_sentAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED; if (zeroSpin) { _sentAngularVelocity = glm::vec3(0.0f); } @@ -252,24 +245,22 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setAngularVelocity(_sentAngularVelocity); } - qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); auto nodeList = DependencyManager::get(); QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty()) { + if (simulatorID.isEmpty() && _sentMoving) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator qDebug() << "claiming simulator ownership"; _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && _numNonMovingUpdates > 0) { + } else if (simulatorID == myNodeID && zeroSpin && zeroSpin) { // we are the simulator and the object has stopped. give up "simulator" status qDebug() << "releasing simulator ownership"; _entity->setSimulatorID(""); properties.setSimulatorID(""); } - // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. if (_sentMoving) { _numNonMovingUpdates = 0; From d330319ed964d8a9127704803fda9a0bfb66252a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 09:56:39 -0700 Subject: [PATCH 15/60] when a script creates and object, set the local Node as the simulation owner --- libraries/entities/src/EntityScriptingInterface.cpp | 12 ++++++++++-- libraries/physics/src/EntityMotionState.cpp | 5 +++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c41b9a5c41..d0c3457a5c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -65,17 +65,25 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro // The application will keep track of creatorTokenID uint32_t creatorTokenID = EntityItemID::getNextCreatorTokenID(); + // This Node is creating a new object. If it's in motion, set this Node as the simulator. + auto nodeList = DependencyManager::get(); + const QString myNodeID = nodeList->getSessionUUID().toString(); + // QString simulatorID = _entity->getSimulatorID(); + + EntityItemProperties propertiesWithSimID = properties; + propertiesWithSimID.setSimulatorID(myNodeID); + EntityItemID id(NEW_ENTITY, creatorTokenID, false ); // If we have a local entity tree set, then also update it. if (_entityTree) { _entityTree->lockForWrite(); - _entityTree->addEntity(id, properties); + _entityTree->addEntity(id, propertiesWithSimID); _entityTree->unlock(); } // queue the packet - queueEntityMessage(PacketTypeEntityAddOrEdit, id, properties); + queueEntityMessage(PacketTypeEntityAddOrEdit, id, propertiesWithSimID); return id; } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index b4394d52d3..c02748afe3 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -245,11 +245,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setAngularVelocity(_sentAngularVelocity); } - qDebug() << "EntityMotionState::sendUpdate" << _sentMoving << _body->isActive(); + auto nodeList = DependencyManager::get(); QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty() && _sentMoving) { + qDebug() << "EntityMotionState::sendUpdate" << (zeroSpin && zeroSpin) << "me:" << myNodeID << "owner:" << simulatorID; + if (simulatorID.isEmpty() && !(zeroSpin && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator qDebug() << "claiming simulator ownership"; _entity->setSimulatorID(myNodeID); From b5bfbba7595b30e5d6a35a44af6b1401031f3716 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 10:17:54 -0700 Subject: [PATCH 16/60] only set simulationID on scripted entity creation if the entity has velocity or rotation --- libraries/entities/src/EntityScriptingInterface.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index d0c3457a5c..06c5493720 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -68,10 +68,13 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro // This Node is creating a new object. If it's in motion, set this Node as the simulator. auto nodeList = DependencyManager::get(); const QString myNodeID = nodeList->getSessionUUID().toString(); - // QString simulatorID = _entity->getSimulatorID(); EntityItemProperties propertiesWithSimID = properties; - propertiesWithSimID.setSimulatorID(myNodeID); + + // if this object is moving, set this Node as the simulation owner + if (properties.velocityChanged() || properties.rotationChanged()) { + propertiesWithSimID.setSimulatorID(myNodeID); + } EntityItemID id(NEW_ENTITY, creatorTokenID, false ); From 3cf31ff7011cd5315cffbcfb3a38709dd77df11c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 13:32:02 -0700 Subject: [PATCH 17/60] fix to allow modelEntityItems with shape of box into physicsengine. ignore entity updates echoed back to us. stop broadcasting after 3 non-moving updates --- .../src/RenderableModelEntityItem.cpp | 9 +++++++ libraries/entities/src/EntityTree.cpp | 19 --------------- libraries/entities/src/EntityTree.h | 1 - libraries/entities/src/EntityTreeElement.cpp | 11 +++++++-- libraries/physics/src/EntityMotionState.cpp | 24 +++++++++++-------- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1d601d1294..15c0b79b47 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -289,6 +289,10 @@ const QString& RenderableModelEntityItem::getCollisionModelURL() const { bool RenderableModelEntityItem::isReadyToComputeShape() { + if (_shapeType != SHAPE_TYPE_COMPOUND && _shapeType != SHAPE_TYPE_CONVEX_HULL) { + return true; + } + if (!_model) { return false; // hmm... } @@ -316,6 +320,11 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { } void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { + if (_shapeType != SHAPE_TYPE_COMPOUND && _shapeType != SHAPE_TYPE_CONVEX_HULL) { + info.setParams(getShapeType(), 0.5f * getDimensions()); + return; + } + if (_model->getCollisionURL().isEmpty() || _model->getURL().isEmpty()) { info.setParams(getShapeType(), 0.5f * getDimensions()); } else { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ea811389cb..fa53dd2dda 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -69,25 +69,6 @@ bool EntityTree::handlesEditPacketType(PacketType packetType) const { } } -/// Give an EntityItemID and EntityItemProperties, this will either find the correct entity that already exists -/// in the tree or it will create a new entity of the type specified by the properties and return that item. -/// In the case that it creates a new item, the item will be properly added to the tree and all appropriate lookup hashes. -EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties) { - EntityItem* result = NULL; - - // we need to first see if we already have the entity in our tree by finding the containing element of the entity - EntityTreeElement* containingElement = getContainingElement(entityID); - if (containingElement) { - result = containingElement->getEntityWithEntityItemID(entityID); - } - - // if the element does not exist, then create a new one of the specified type... - if (!result) { - result = addEntity(entityID, properties); - } - return result; -} - /// Adds a new entity item to the tree void EntityTree::postAddEntity(EntityItem* entity) { assert(entity); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c49cfb2600..3f01dec408 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -82,7 +82,6 @@ public: virtual void update(); // The newer API... - EntityItem* getOrCreateEntityItem(const EntityItemID& entityID, const EntityItemProperties& properties); void postAddEntity(EntityItem* entityItem); EntityItem* addEntity(const EntityItemID& entityID, const EntityItemProperties& properties); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 51648c4fa6..d6d5c68ff9 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -731,12 +731,19 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int } // If the item already exists in our tree, we want do the following... + // 0) if this node is the simulator for the entity, ignore the update packet // 1) allow the existing item to read from the databuffer // 2) check to see if after reading the item, the containing element is still correct, fix it if needed // // TODO: Do we need to also do this? // 3) remember the old cube for the entity so we can mark it as dirty - if (entityItem) { + auto nodeList = DependencyManager::get(); + QString myNodeID = nodeList->getSessionUUID().toString(); + if (entityItem && entityItem->getSimulatorID() == myNodeID) { + // do nothing, this was echoed back to us + qDebug() << "IGNORING ECHOED ENTITY UPDATE"; + // _myTree->entityChanged(entityItem); + } else if (entityItem) { QString entityScriptBefore = entityItem->getScript(); bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); @@ -750,7 +757,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int if (bestFitBefore != bestFitAfter) { // This is the case where the entity existed, and is in some element in our tree... if (!bestFitBefore && bestFitAfter) { - // This is the case where the entity existed, and is in some element in our tree... + // This is the case where the entity existed, and is in some element in our tree... if (currentContainingElement != this) { currentContainingElement->removeEntityItem(entityItem); addEntityItem(entityItem); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c02748afe3..33f9630e4f 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -216,20 +216,22 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setRotation(_sentRotation); } - const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec - bool zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); - const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec - bool zeroSpin = glm::length2(_sentAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED; - + bool zeroSpeed = true; + bool zeroSpin = true; + if (_outgoingPacketFlags & EntityItem::DIRTY_VELOCITY) { if (_body->isActive()) { _sentVelocity = bulletToGLM(_body->getLinearVelocity()); _sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); // if the speeds are very small we zero them out + const float MINIMUM_EXTRAPOLATION_SPEED_SQUARED = 1.0e-4f; // 1cm/sec + zeroSpeed = (glm::length2(_sentVelocity) < MINIMUM_EXTRAPOLATION_SPEED_SQUARED); if (zeroSpeed) { _sentVelocity = glm::vec3(0.0f); } + const float MINIMUM_EXTRAPOLATION_SPIN_SQUARED = 0.004f; // ~0.01 rotation/sec + zeroSpin = glm::length2(_sentAngularVelocity) < MINIMUM_EXTRAPOLATION_SPIN_SQUARED; if (zeroSpin) { _sentAngularVelocity = glm::vec3(0.0f); } @@ -249,15 +251,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ auto nodeList = DependencyManager::get(); QString myNodeID = nodeList->getSessionUUID().toString(); QString simulatorID = _entity->getSimulatorID(); - qDebug() << "EntityMotionState::sendUpdate" << (zeroSpin && zeroSpin) << "me:" << myNodeID << "owner:" << simulatorID; if (simulatorID.isEmpty() && !(zeroSpin && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator - qDebug() << "claiming simulator ownership"; _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); } else if (simulatorID == myNodeID && zeroSpin && zeroSpin) { // we are the simulator and the object has stopped. give up "simulator" status - qDebug() << "releasing simulator ownership"; _entity->setSimulatorID(""); properties.setSimulatorID(""); } @@ -279,7 +278,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ #ifdef WANT_DEBUG quint64 now = usecTimestampNow(); qCDebug(physics) << "EntityMotionState::sendUpdate()"; - qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID() << "---------------------------------------------"; + qCDebug(physics) << " EntityItemId:" << _entity->getEntityItemID() + << "---------------------------------------------"; qCDebug(physics) << " lastSimulated:" << debugTime(lastSimulated, now); #endif //def WANT_DEBUG @@ -287,12 +287,16 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setLastEdited(_entity->getLastEdited()); } - if (EntityItem::getSendPhysicsUpdates()) { + if (EntityItem::getSendPhysicsUpdates() && _numNonMovingUpdates < 4) { EntityItemID id(_entity->getID()); EntityEditPacketSender* entityPacketSender = static_cast(packetSender); #ifdef WANT_DEBUG qCDebug(physics) << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()..."; #endif + qDebug() << "EntityMotionState::sendUpdate" << (zeroSpin && zeroSpin) + << _sentMoving + << _numNonMovingUpdates + << "me:" << myNodeID << "owner:" << simulatorID; entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties); } else { #ifdef WANT_DEBUG From e25590f00e6b544c00de3ef663dfd7dce0e282af Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 13:37:57 -0700 Subject: [PATCH 18/60] don't give up ownership of simulation until the last packet is sent --- libraries/physics/src/EntityMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 33f9630e4f..1abbe59f8e 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -255,7 +255,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && zeroSpin && zeroSpin) { + } else if (simulatorID == myNodeID && zeroSpin && _numNonMovingUpdates == 3) { // we are the simulator and the object has stopped. give up "simulator" status _entity->setSimulatorID(""); properties.setSimulatorID(""); From b21cc357e4ce0c0412e9d5903e463336df130c33 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 14 Apr 2015 16:08:53 -0700 Subject: [PATCH 19/60] undo stop-sending hack --- libraries/physics/src/EntityMotionState.cpp | 6 ++---- libraries/physics/src/ObjectMotionState.h | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 639df6079f..5d5435eb5e 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -201,8 +201,6 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) { - const int NUM_NONMOVING_UPDATES_TO_SEND = 3; - if (!_entity->isKnownID()) { return; // never update entities that are unknown } @@ -257,7 +255,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && _numNonMovingUpdates == NUM_NONMOVING_UPDATES_TO_SEND) { + } else if (simulatorID == myNodeID && _numNonMovingUpdates == MAX_NUM_NON_MOVING_UPDATES) { // we are the simulator and the object has stopped. give up "simulator" status _entity->setSimulatorID(""); properties.setSimulatorID(""); @@ -289,7 +287,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setLastEdited(_entity->getLastEdited()); } - if (EntityItem::getSendPhysicsUpdates() && _numNonMovingUpdates <= NUM_NONMOVING_UPDATES_TO_SEND) { + if (EntityItem::getSendPhysicsUpdates() /* && _numNonMovingUpdates <= MAX_NUM_NON_MOVING_UPDATES*/) { EntityItemID id(_entity->getID()); EntityEditPacketSender* entityPacketSender = static_cast(packetSender); #ifdef WANT_DEBUG diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index fb402a178d..2e7571df5c 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -47,6 +47,8 @@ const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = EntityItem::DIRTY_POSITION | Entit class OctreeEditPacketSender; +extern const int MAX_NUM_NON_MOVING_UPDATES; + class ObjectMotionState : public btMotionState { public: // The WorldOffset is used to keep the positions of objects in the simulation near the origin, to From afca5440f0c7b5e70966ea1b86422311e773b1a5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 10:58:56 -0700 Subject: [PATCH 20/60] entity-server will automatically clear simulation-owner ID if it doesn't get an update for 2 seconds --- libraries/entities/src/EntityItem.h | 2 +- .../entities/src/SimpleEntitySimulation.cpp | 28 +++++++++++++++++++ .../entities/src/SimpleEntitySimulation.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8f7feb2ed8..946efea39c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -323,7 +323,7 @@ protected: quint64 _lastEdited; // last official local or remote edit time quint64 _lastEditedFromRemote; // last time we received and edit from the server - quint64 _lastEditedFromRemoteInRemoteTime; // last time we received and edit from the server (in server-time-frame) + quint64 _lastEditedFromRemoteInRemoteTime; // last time we received an edit from the server (in server-time-frame) quint64 _created; quint64 _changedOnServer; diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 6d45768c26..6846a38cb0 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -13,8 +13,12 @@ #include "EntityItem.h" #include "SimpleEntitySimulation.h" +#include "EntitiesLogging.h" + +const quint64 AUTO_REMOVE_SIMULATION_OWNER_USEC = 2000000; void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { + // now is usecTimestampNow() QSet::iterator itemItr = _movingEntities.begin(); while (itemItr != _movingEntities.end()) { EntityItem* entity = *itemItr; @@ -27,6 +31,22 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { ++itemItr; } } + + // If an Entity has a simulation owner and we don't get an update for some amount of time, + // clear the owner. This guards against an interface failing to release the Entity when it + // has finished simulating it. + itemItr = _hasSimulationOwnerEntities.begin(); + while (itemItr != _hasSimulationOwnerEntities.end()) { + EntityItem* entity = *itemItr; + if (!entity->getSimulatorID().isEmpty() && + usecTimestampNow() - entity->getLastChangedOnServer() >= AUTO_REMOVE_SIMULATION_OWNER_USEC) { + qCDebug(entities) << "auto-removing simulation owner" << entity->getSimulatorID(); + entity->setSimulatorID(""); + itemItr = _hasSimulationOwnerEntities.erase(itemItr); + } else { + ++itemItr; + } + } } void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) { @@ -35,11 +55,15 @@ void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) { } else if (entity->getCollisionsWillMove()) { _movableButStoppedEntities.insert(entity); } + if (!entity->getSimulatorID().isEmpty()) { + _hasSimulationOwnerEntities.insert(entity); + } } void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) { _movingEntities.remove(entity); _movableButStoppedEntities.remove(entity); + _hasSimulationOwnerEntities.remove(entity); } const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITY | EntityItem::DIRTY_MOTION_TYPE; @@ -55,6 +79,9 @@ void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) { _movingEntities.remove(entity); _movableButStoppedEntities.remove(entity); } + if (!entity->getSimulatorID().isEmpty()) { + _hasSimulationOwnerEntities.insert(entity); + } } entity->clearDirtyFlags(); } @@ -62,5 +89,6 @@ void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) { void SimpleEntitySimulation::clearEntitiesInternal() { _movingEntities.clear(); _movableButStoppedEntities.clear(); + _hasSimulationOwnerEntities.clear(); } diff --git a/libraries/entities/src/SimpleEntitySimulation.h b/libraries/entities/src/SimpleEntitySimulation.h index 92b6a28215..af79ec0131 100644 --- a/libraries/entities/src/SimpleEntitySimulation.h +++ b/libraries/entities/src/SimpleEntitySimulation.h @@ -30,6 +30,7 @@ protected: QSet _movingEntities; QSet _movableButStoppedEntities; + QSet _hasSimulationOwnerEntities; }; #endif // hifi_SimpleEntitySimulation_h From 62b59b7ccc877b1991757f36348ecccc9410e683 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 11:02:12 -0700 Subject: [PATCH 21/60] remove uneeded debug print --- libraries/entities/src/EntityTreeElement.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index d6d5c68ff9..93c69c9c61 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -740,9 +740,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int auto nodeList = DependencyManager::get(); QString myNodeID = nodeList->getSessionUUID().toString(); if (entityItem && entityItem->getSimulatorID() == myNodeID) { - // do nothing, this was echoed back to us - qDebug() << "IGNORING ECHOED ENTITY UPDATE"; - // _myTree->entityChanged(entityItem); + // do nothing, this was echoed back to us by the entity server } else if (entityItem) { QString entityScriptBefore = entityItem->getScript(); bool bestFitBefore = bestFitEntityBounds(entityItem); From 51ac44a9b7388a7d372fc103e2b9198dc91439e5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 11:34:42 -0700 Subject: [PATCH 22/60] try to increase chances the interface gives up simulation ownership --- libraries/physics/src/EntityMotionState.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 5d5435eb5e..db79581812 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -255,7 +255,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && _numNonMovingUpdates == MAX_NUM_NON_MOVING_UPDATES) { + } else if (simulatorID == myNodeID && _numNonMovingUpdates >= MAX_NUM_NON_MOVING_UPDATES - 1) { // we are the simulator and the object has stopped. give up "simulator" status _entity->setSimulatorID(""); properties.setSimulatorID(""); @@ -287,7 +287,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setLastEdited(_entity->getLastEdited()); } - if (EntityItem::getSendPhysicsUpdates() /* && _numNonMovingUpdates <= MAX_NUM_NON_MOVING_UPDATES*/) { + if (EntityItem::getSendPhysicsUpdates()) { EntityItemID id(_entity->getID()); EntityEditPacketSender* entityPacketSender = static_cast(packetSender); #ifdef WANT_DEBUG From c87dca5ba0fdafffd8abb081ee56cac9dc33a7d7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 11:58:12 -0700 Subject: [PATCH 23/60] remove debug print --- libraries/physics/src/EntityMotionState.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index db79581812..655db8fd2f 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -293,10 +293,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ #ifdef WANT_DEBUG qCDebug(physics) << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()..."; #endif - qDebug() << "EntityMotionState::sendUpdate" << (zeroSpin && zeroSpin) - << _sentMoving - << _numNonMovingUpdates - << "me:" << myNodeID << "owner:" << simulatorID; entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties); } else { #ifdef WANT_DEBUG From e3a90b80a490619b5bc051ecd0e195f5e88c102e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 16:04:18 -0700 Subject: [PATCH 24/60] fix typo in comment --- libraries/entities/src/EntityTreeElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 93c69c9c61..c09b1701bc 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -359,7 +359,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData if (extraEncodeData && entityTreeElementExtraEncodeData) { // After processing, if we are PARTIAL or COMPLETED then we need to re-include our extra data. - // Only our patent can remove our extra data in these cases and only after it knows that all of it's + // Only our parent can remove our extra data in these cases and only after it knows that all of its // children have been encoded. // If we weren't able to encode ANY data about ourselves, then we go ahead and remove our element data // since that will signal that the entire element needs to be encoded on the next attempt From 6c4d232ad982a15c9dca39f07d61f54af6ac4aaf Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 15 Apr 2015 16:08:15 -0700 Subject: [PATCH 25/60] respond to code review --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 4 ++-- libraries/entities/src/EntityTreeElement.cpp | 6 ++++-- libraries/entities/src/ModelEntityItem.cpp | 3 +-- libraries/entities/src/SimpleEntitySimulation.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c67e1f04e5..86b0be4dd8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -308,7 +308,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType type = getShapeType(); if (type != SHAPE_TYPE_COMPOUND) { ModelEntityItem::computeShapeInfo(info); - info.setParams(_shapeType, 0.5f * getDimensions()); + info.setParams(type, 0.5f * getDimensions()); } else { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); @@ -410,7 +410,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } glm::vec3 collisionModelDimensions = box.getDimensions(); - info.setParams(_shapeType, collisionModelDimensions, _collisionModelURL); + info.setParams(type, collisionModelDimensions, _collisionModelURL); info.setConvexHulls(_points); } } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index c09b1701bc..3dcd2899d3 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -717,6 +717,10 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesRead += sizeof(numberOfEntities); if (bytesLeftToRead >= (int)(numberOfEntities * expectedBytesPerEntity)) { + // look up the Id of this Node + auto nodeList = DependencyManager::get(); + QString myNodeID = nodeList->getSessionUUID().toString(); + for (uint16_t i = 0; i < numberOfEntities; i++) { int bytesForThisEntity = 0; EntityItemID entityItemID; @@ -737,8 +741,6 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int // // TODO: Do we need to also do this? // 3) remember the old cube for the entity so we can mark it as dirty - auto nodeList = DependencyManager::get(); - QString myNodeID = nodeList->getSessionUUID().toString(); if (entityItem && entityItem->getSimulatorID() == myNodeID) { // do nothing, this was echoed back to us by the entity server } else if (entityItem) { diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index e98f784765..f95eeea8e4 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -296,8 +296,7 @@ void ModelEntityItem::updateShapeType(ShapeType type) { ShapeType ModelEntityItem::getShapeType() const { if (_shapeType == SHAPE_TYPE_COMPOUND) { return hasCollisionModel() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE; - } - else { + } else { return _shapeType; } } diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 6846a38cb0..0406aaa443 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -15,7 +15,7 @@ #include "SimpleEntitySimulation.h" #include "EntitiesLogging.h" -const quint64 AUTO_REMOVE_SIMULATION_OWNER_USEC = 2000000; +const quint64 AUTO_REMOVE_SIMULATION_OWNER_USEC = 2 * USECS_PER_SECOND; void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { // now is usecTimestampNow() From df37b853f750e4433ac9c70c3f89c53a2c14ec29 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 08:57:57 -0700 Subject: [PATCH 26/60] setup test of lockout-period oafter simulator-owner-id change --- libraries/entities/src/EntityItem.cpp | 2 ++ libraries/entities/src/EntityItem.h | 4 +++- libraries/entities/src/EntityTree.cpp | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index da98b4f350..2503e0e30d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -75,6 +75,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _dirtyFlags = 0; _changedOnServer = 0; _element = NULL; + _simulatorIDChangedTime = 0; initFromEntityItemID(entityItemID); } @@ -90,6 +91,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert _dirtyFlags = 0; _changedOnServer = 0; _element = NULL; + _simulatorIDChangedTime = 0; initFromEntityItemID(entityItemID); setProperties(properties); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 946efea39c..8391187860 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -256,7 +256,8 @@ public: void setUserData(const QString& value) { _userData = value; } QString getSimulatorID() const { return _simulatorID; } - void setSimulatorID(const QString& id) { _simulatorID = id; } + void setSimulatorID(const QString& id) { _simulatorID = id; _simulatorIDChangedTime = usecTimestampNow(); } + quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; } const QString& getMarketplaceID() const { return _marketplaceID; } void setMarketplaceID(const QString& value) { _marketplaceID = value; } @@ -352,6 +353,7 @@ protected: bool _locked; QString _userData; QString _simulatorID; // id of Node which is currently responsible for simulating this Entity + quint64 _simulatorIDChangedTime; // when was _simulatorID last updated? QString _marketplaceID; // NOTE: Damping is applied like this: v *= pow(1 - damping, dt) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index fa53dd2dda..ff9d098c01 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -130,6 +130,17 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro } } } else { + if (properties.simulatorIDChanged() && + !entity->getSimulatorID().isEmpty() && + properties.getSimulatorID() != entity->getSimulatorID()) { + // A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this + // if ownership hasn't recently changed. + quint64 now = usecTimestampNow(); + if (now - entity->getSimulatorIDChangedTime() < 0.1 * USECS_PER_SECOND) { // XXX pick time and put in constant + qDebug() << "TOO SOON"; + } + } + QString entityScriptBefore = entity->getScript(); uint32_t preFlags = entity->getDirtyFlags(); UpdateEntityOperator theOperator(this, containingElement, entity, properties); From b30b9a0a3079a8c6d99a55cc54b03f5926350d33 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 12:03:34 -0700 Subject: [PATCH 27/60] don't update _simulatorIDChangedTime unless the value is different than the current one. if a script changes an entity, attempt to claim ownership --- libraries/entities/src/EntityItem.cpp | 7 +++++++ libraries/entities/src/EntityItem.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 17 +++++++++++------ libraries/entities/src/EntityTree.cpp | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2503e0e30d..e8427e0982 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1196,3 +1196,10 @@ void EntityItem::updateLifetime(float value) { _dirtyFlags |= EntityItem::DIRTY_LIFETIME; } } + +void EntityItem::setSimulatorID(const QString& value) { + if (_simulatorID != value) { + _simulatorID = value; + _simulatorIDChangedTime = usecTimestampNow(); + } +} diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8391187860..124d37d762 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -256,7 +256,7 @@ public: void setUserData(const QString& value) { _userData = value; } QString getSimulatorID() const { return _simulatorID; } - void setSimulatorID(const QString& id) { _simulatorID = id; _simulatorIDChangedTime = usecTimestampNow(); } + void setSimulatorID(const QString& value); quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; } const QString& getMarketplaceID() const { return _marketplaceID; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 06c5493720..fa142d3abd 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -66,13 +66,10 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro uint32_t creatorTokenID = EntityItemID::getNextCreatorTokenID(); // This Node is creating a new object. If it's in motion, set this Node as the simulator. - auto nodeList = DependencyManager::get(); - const QString myNodeID = nodeList->getSessionUUID().toString(); - EntityItemProperties propertiesWithSimID = properties; - - // if this object is moving, set this Node as the simulation owner if (properties.velocityChanged() || properties.rotationChanged()) { + auto nodeList = DependencyManager::get(); + const QString myNodeID = nodeList->getSessionUUID().toString(); propertiesWithSimID.setSimulatorID(myNodeID); } @@ -148,12 +145,20 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E entityID.isKnownID = true; } } + + // If this node is changing a physics-related property, claim simulation ownership + EntityItemProperties propertiesWithSimID = properties; + if (properties.velocityChanged() || properties.rotationChanged()) { + auto nodeList = DependencyManager::get(); + const QString myNodeID = nodeList->getSessionUUID().toString(); + propertiesWithSimID.setSimulatorID(myNodeID); + } // If we have a local entity tree set, then also update it. We can do this even if we don't know // the actual id, because we can edit out local entities just with creatorTokenID if (_entityTree) { _entityTree->lockForWrite(); - _entityTree->updateEntity(entityID, properties, canAdjustLocks()); + _entityTree->updateEntity(entityID, propertiesWithSimID, canAdjustLocks()); _entityTree->unlock(); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ff9d098c01..2227107537 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -136,7 +136,7 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro // A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this // if ownership hasn't recently changed. quint64 now = usecTimestampNow(); - if (now - entity->getSimulatorIDChangedTime() < 0.1 * USECS_PER_SECOND) { // XXX pick time and put in constant + if (now - entity->getSimulatorIDChangedTime() < 2 * USECS_PER_SECOND) { // XXX pick time and put in constant qDebug() << "TOO SOON"; } } From 5180e7e7152bcb3d1382ebd4d0d869b71b4bd40c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 16 Apr 2015 13:44:17 -0700 Subject: [PATCH 28/60] measure linear velocity of moving objects --- libraries/physics/src/EntityMotionState.cpp | 18 ++++--- libraries/physics/src/EntityMotionState.h | 4 +- libraries/physics/src/ObjectMotionState.cpp | 57 ++++++++++++++++----- libraries/physics/src/ObjectMotionState.h | 13 ++++- libraries/physics/src/PhysicsEngine.cpp | 4 ++ 5 files changed, 72 insertions(+), 24 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index d84daa6b42..6838d977eb 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -62,6 +62,9 @@ void EntityMotionState::stepKinematicSimulation(quint64 now) { // which is different from physical kinematic motion (inside getWorldTransform()) // which steps in physics simulation time. _entity->simulate(now); + // TODO: we can't use ObjectMotionState::measureVelocityAndAcceleration() here because the entity + // has no RigidBody and the timestep is a little bit out of sync with the physics simulation anyway. + // Hence we must manually measure kinematic velocity and acceleration. } bool EntityMotionState::isMoving() const { @@ -71,7 +74,7 @@ bool EntityMotionState::isMoving() const { // This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC) -// (2) at the beginning of each simulation frame for KINEMATIC RigidBody's -- +// (2) at the beginning of each simulation step for KINEMATIC RigidBody's -- // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { if (_isKinematic) { @@ -89,9 +92,10 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { worldTrans.setRotation(glmToBullet(_entity->getRotation())); } -// This callback is invoked by the physics simulation at the end of each simulation frame... +// This callback is invoked by the physics simulation at the end of each simulation step... // iff the corresponding RigidBody is DYNAMIC and has moved. void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { + measureVelocityAndAcceleration(); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); _entity->setRotation(bulletToGLM(worldTrans.getRotation())); @@ -116,7 +120,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { #endif } -void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) { +void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t step) { if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { if (flags & EntityItem::DIRTY_POSITION) { _sentPosition = _entity->getPosition() - ObjectMotionState::getWorldOffset(); @@ -131,7 +135,7 @@ void EntityMotionState::updateObjectEasy(uint32_t flags, uint32_t frame) { if (flags & EntityItem::DIRTY_VELOCITY) { updateObjectVelocities(); } - _sentFrame = frame; + _sentStep = step; } // TODO: entity support for friction and restitution @@ -179,7 +183,7 @@ float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const { return _entity->computeMass(); } -void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) { +void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) { if (!_entity->isKnownID()) { return; // never update entities that are unknown } @@ -231,7 +235,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ } if (_numNonMovingUpdates <= 1) { // we only update lastEdited when we're sending new physics data - // (i.e. NOT when we just simulate the positions forward, nore when we resend non-moving data) + // (i.e. NOT when we just simulate the positions forward, nor when we resend non-moving data) // NOTE: Andrew & Brad to discuss. Let's make sure we're using lastEdited, lastSimulated, and lastUpdated correctly quint64 lastSimulated = _entity->getLastSimulated(); _entity->setLastEdited(lastSimulated); @@ -264,7 +268,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ // The outgoing flags only itemized WHAT to send, not WHETHER to send, hence we always set them // to the full set. These flags may be momentarily cleared by incoming external changes. _outgoingPacketFlags = DIRTY_PHYSICS_FLAGS; - _sentFrame = frame; + _sentStep = step; } } diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 7214626fc4..710362e056 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -50,13 +50,13 @@ public: virtual void setWorldTransform(const btTransform& worldTrans); // these relay incoming values to the RigidBody - virtual void updateObjectEasy(uint32_t flags, uint32_t frame); + virtual void updateObjectEasy(uint32_t flags, uint32_t step); virtual void updateObjectVelocities(); virtual void computeShapeInfo(ShapeInfo& shapeInfo); virtual float computeMass(const ShapeInfo& shapeInfo) const; - virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame); + virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step); virtual uint32_t getIncomingDirtyFlags() const; virtual void clearIncomingDirtyFlags(uint32_t flags) { _entity->clearDirtyFlags(flags); } diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index c9f416cc37..a66e60e93c 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -22,7 +22,7 @@ const float MAX_FRICTION = 10.0f; const float DEFAULT_RESTITUTION = 0.5f; -// origin of physics simulation in world frame +// origin of physics simulation in world-frame glm::vec3 _worldOffset(0.0f); // static @@ -35,6 +35,12 @@ const glm::vec3& ObjectMotionState::getWorldOffset() { return _worldOffset; } +// static +uint32_t _simulationStep = 0; +void ObjectMotionState::setSimulationStep(uint32_t step) { + assert(step > _simulationStep); + _simulationStep = step; +} ObjectMotionState::ObjectMotionState() : _friction(DEFAULT_FRICTION), @@ -46,12 +52,15 @@ ObjectMotionState::ObjectMotionState() : _sentMoving(false), _numNonMovingUpdates(0), _outgoingPacketFlags(DIRTY_PHYSICS_FLAGS), - _sentFrame(0), + _sentStep(0), _sentPosition(0.0f), _sentRotation(), _sentVelocity(0.0f), _sentAngularVelocity(0.0f), - _sentAcceleration(0.0f) { + _sentAcceleration(0.0f), + _lastSimulationStep(0), + _lastVelocity(0.0f), + _measuredAcceleration(0.0f) } ObjectMotionState::~ObjectMotionState() { @@ -59,6 +68,27 @@ ObjectMotionState::~ObjectMotionState() { assert(_body == NULL); } +void ObjectMotionState::measureVelocityAndAcceleration() { + // try to manually measure the true acceleration of the object + uint32_t numSubsteps = _simulationStep - _lastSimulationStep; + if (numSubsteps > 0) { + float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP); + float invDt = 1.0f / dt; + _lastSimulationStep = _simulationStep; + + // Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt + // hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt + glm::vec3 velocity = bulletToGLM(_body->getLinearVelocity()); + _measuredAcceleration = (velocity / powf(1.0f - _linearDamping, dt) - _lastVelocity) * invDt; + _lastVelocity = velocity; + } +} + +void ObjectMotionState::resetMeasuredVelocityAndAcceleration() { + _lastSimulationStep = _simulationStep; + _lastVelocity = bulletToGLM(_body->getLinearVelocity()); +} + void ObjectMotionState::setFriction(float friction) { _friction = btMax(btMin(fabsf(friction), MAX_FRICTION), 0.0f); } @@ -103,15 +133,16 @@ bool ObjectMotionState::doesNotNeedToSendUpdate() const { return !_body->isActive() && _numNonMovingUpdates > MAX_NUM_NON_MOVING_UPDATES; } -bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) { +bool ObjectMotionState::shouldSendUpdate(uint32_t simulationStep) { assert(_body); - // if we've never checked before, our _sentFrame will be 0, and we need to initialize our state - if (_sentFrame == 0) { - _sentPosition = bulletToGLM(_body->getWorldTransform().getOrigin()); + // if we've never checked before, our _sentStep will be 0, and we need to initialize our state + if (_sentStep == 0) { + btTransform xform = _body->getWorldTransform(); + _sentPosition = bulletToGLM(xform.getOrigin()); + _sentRotation = bulletToGLM(xform.getRotation()); _sentVelocity = bulletToGLM(_body->getLinearVelocity()); - _sentRotation = bulletToGLM(_body->getWorldTransform().getRotation()); _sentAngularVelocity = bulletToGLM(_body->getAngularVelocity()); - _sentFrame = simulationFrame; + _sentStep = simulationStep; return false; } @@ -121,9 +152,9 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) { glm::vec3 wasAngularVelocity = _sentAngularVelocity; #endif - int numFrames = simulationFrame - _sentFrame; - float dt = (float)(numFrames) * PHYSICS_ENGINE_FIXED_SUBSTEP; - _sentFrame = simulationFrame; + int numSteps = simulationStep - _sentStep; + float dt = (float)(numSteps) * PHYSICS_ENGINE_FIXED_SUBSTEP; + _sentStep = simulationStep; bool isActive = _body->isActive(); if (!isActive) { @@ -179,7 +210,7 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) { // Bullet caps the effective rotation velocity inside its rotation integration step, therefore // we must integrate with the same algorithm and timestep in order achieve similar results. - for (int i = 0; i < numFrames; ++i) { + for (int i = 0; i < numSteps; ++i) { _sentRotation = glm::normalize(computeBulletRotationStep(_sentAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _sentRotation); } } diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index fb402a178d..2c77ca6b5e 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -57,9 +57,14 @@ public: static void setWorldOffset(const glm::vec3& offset); static const glm::vec3& getWorldOffset(); + static void setSimulationStep(uint32_t step); + ObjectMotionState(); ~ObjectMotionState(); + void measureVelocityAndAcceleration(); + void resetMeasuredVelocityAndAcceleration(); + // An EASY update does not require the object to be removed and then reinserted into the PhysicsEngine virtual void updateObjectEasy(uint32_t flags, uint32_t frame) = 0; virtual void updateObjectVelocities() = 0; @@ -87,7 +92,7 @@ public: void clearOutgoingPacketFlags(uint32_t flags) { _outgoingPacketFlags &= ~flags; } bool doesNotNeedToSendUpdate() const; - virtual bool shouldSendUpdate(uint32_t simulationFrame); + virtual bool shouldSendUpdate(uint32_t simulationStep); virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0; virtual MotionType computeMotionType() const = 0; @@ -126,12 +131,16 @@ protected: int _numNonMovingUpdates; // RELIABLE_SEND_HACK for "not so reliable" resends of packets for non-moving objects uint32_t _outgoingPacketFlags; - uint32_t _sentFrame; + uint32_t _sentStep; glm::vec3 _sentPosition; // in simulation-frame (not world-frame) glm::quat _sentRotation;; glm::vec3 _sentVelocity; glm::vec3 _sentAngularVelocity; // radians per second glm::vec3 _sentAcceleration; + + uint32_t _lastSimulationStep; + glm::vec3 _lastVelocity; + glm::vec3 _measuredAcceleration; }; #endif // hifi_ObjectMotionState_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 209e23e006..34ac6732a7 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -193,6 +193,9 @@ void PhysicsEngine::relayIncomingChangesToSimulation() { // hence the MotionState has all the knowledge and authority to perform the update. motionState->updateObjectEasy(flags, _numSubsteps); } + if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { + motionState->resetMeasuredVelocityAndAcceleration(); + } } else { // the only way we should ever get here (motionState exists but no body) is when the object // is undergoing non-physical kinematic motion. @@ -508,6 +511,7 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap body->setFriction(motionState->_friction); body->setDamping(motionState->_linearDamping, motionState->_angularDamping); _dynamicsWorld->addRigidBody(body); + motionState->resetMeasuredVelocityAndAcceleration(); } void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) { From b7ca69d4e1c9511d9af93ca8de732c9a39d96017 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 16 Apr 2015 13:46:26 -0700 Subject: [PATCH 29/60] fix typo --- libraries/physics/src/ObjectMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index a66e60e93c..9d9e7e6798 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -60,7 +60,7 @@ ObjectMotionState::ObjectMotionState() : _sentAcceleration(0.0f), _lastSimulationStep(0), _lastVelocity(0.0f), - _measuredAcceleration(0.0f) + _measuredAcceleration(0.0f) { } ObjectMotionState::~ObjectMotionState() { From 619d1ba19110e5b406f9ad5e051dcb9e7446d091 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 16 Apr 2015 14:09:33 -0700 Subject: [PATCH 30/60] rename to measureAcceleration --- libraries/physics/src/EntityMotionState.cpp | 4 ++-- libraries/physics/src/ObjectMotionState.cpp | 4 ++-- libraries/physics/src/ObjectMotionState.h | 4 ++-- libraries/physics/src/PhysicsEngine.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 6838d977eb..871ee21c45 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -62,7 +62,7 @@ void EntityMotionState::stepKinematicSimulation(quint64 now) { // which is different from physical kinematic motion (inside getWorldTransform()) // which steps in physics simulation time. _entity->simulate(now); - // TODO: we can't use ObjectMotionState::measureVelocityAndAcceleration() here because the entity + // TODO: we can't use ObjectMotionState::measureAcceleration() here because the entity // has no RigidBody and the timestep is a little bit out of sync with the physics simulation anyway. // Hence we must manually measure kinematic velocity and acceleration. } @@ -95,7 +95,7 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { // This callback is invoked by the physics simulation at the end of each simulation step... // iff the corresponding RigidBody is DYNAMIC and has moved. void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { - measureVelocityAndAcceleration(); + measureAcceleration(); _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); _entity->setRotation(bulletToGLM(worldTrans.getRotation())); diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 9d9e7e6798..3d790ff7d4 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -68,7 +68,7 @@ ObjectMotionState::~ObjectMotionState() { assert(_body == NULL); } -void ObjectMotionState::measureVelocityAndAcceleration() { +void ObjectMotionState::measureAcceleration() { // try to manually measure the true acceleration of the object uint32_t numSubsteps = _simulationStep - _lastSimulationStep; if (numSubsteps > 0) { @@ -84,7 +84,7 @@ void ObjectMotionState::measureVelocityAndAcceleration() { } } -void ObjectMotionState::resetMeasuredVelocityAndAcceleration() { +void ObjectMotionState::resetMeasuredAcceleration() { _lastSimulationStep = _simulationStep; _lastVelocity = bulletToGLM(_body->getLinearVelocity()); } diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 2c77ca6b5e..c5dd31d1f2 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -62,8 +62,8 @@ public: ObjectMotionState(); ~ObjectMotionState(); - void measureVelocityAndAcceleration(); - void resetMeasuredVelocityAndAcceleration(); + void measureAcceleration(); + void resetMeasuredAcceleration(); // An EASY update does not require the object to be removed and then reinserted into the PhysicsEngine virtual void updateObjectEasy(uint32_t flags, uint32_t frame) = 0; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 34ac6732a7..aa9921be64 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -194,7 +194,7 @@ void PhysicsEngine::relayIncomingChangesToSimulation() { motionState->updateObjectEasy(flags, _numSubsteps); } if (flags & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY)) { - motionState->resetMeasuredVelocityAndAcceleration(); + motionState->resetMeasuredAcceleration(); } } else { // the only way we should ever get here (motionState exists but no body) is when the object @@ -511,7 +511,7 @@ void PhysicsEngine::addObject(const ShapeInfo& shapeInfo, btCollisionShape* shap body->setFriction(motionState->_friction); body->setDamping(motionState->_linearDamping, motionState->_angularDamping); _dynamicsWorld->addRigidBody(body); - motionState->resetMeasuredVelocityAndAcceleration(); + motionState->resetMeasuredAcceleration(); } void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) { From d7059d8f2de924a953d39ab49823a7547cdc7d92 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 14:46:38 -0700 Subject: [PATCH 31/60] add code for uuids in wire protocol. some debugging prints --- examples/dice.js | 2 +- .../entities/src/EntityEditPacketSender.cpp | 9 +++++ libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItem.h | 6 +-- .../entities/src/EntityItemProperties.cpp | 6 +-- libraries/entities/src/EntityItemProperties.h | 5 ++- .../src/EntityItemPropertiesDefaults.h | 2 +- .../entities/src/EntityItemPropertiesMacros.h | 39 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.cpp | 29 ++++++++------ libraries/entities/src/EntityTree.cpp | 2 +- libraries/entities/src/EntityTreeElement.cpp | 2 +- .../entities/src/SimpleEntitySimulation.cpp | 6 +-- libraries/octree/src/OctreePacketData.cpp | 11 ++++++ libraries/octree/src/OctreePacketData.h | 3 ++ libraries/physics/src/EntityMotionState.cpp | 15 +++---- 15 files changed, 104 insertions(+), 35 deletions(-) diff --git a/examples/dice.js b/examples/dice.js index b118a6b289..2b6d4d478e 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -13,7 +13,7 @@ // var isDice = false; -var NUMBER_OF_DICE = 2; +var NUMBER_OF_DICE = 1; var dice = []; var DIE_SIZE = 0.20; diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index e94725782d..6f58a5a626 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -36,6 +36,15 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI unsigned char bufferOut[MAX_PACKET_SIZE]; int sizeOut = 0; + + //// XXX + auto nodeList = DependencyManager::get(); + QUuid myNodeID = nodeList->getSessionUUID(); + QString x = properties.getSimulatorID() == myNodeID ? "me" : properties.getSimulatorID().toString(); + qDebug() << "sending update:" << properties.simulatorIDChanged() << properties.getSimulatorID(); + //// XXX + + if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) { #ifdef WANT_DEBUG qCDebug(entities) << "calling queueOctreeEditMessage()..."; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e8427e0982..94d4d7f8a7 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1197,7 +1197,7 @@ void EntityItem::updateLifetime(float value) { } } -void EntityItem::setSimulatorID(const QString& value) { +void EntityItem::setSimulatorID(const QUuid& value) { if (_simulatorID != value) { _simulatorID = value; _simulatorIDChangedTime = usecTimestampNow(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 124d37d762..634b7e7d3d 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -255,8 +255,8 @@ public: const QString& getUserData() const { return _userData; } void setUserData(const QString& value) { _userData = value; } - QString getSimulatorID() const { return _simulatorID; } - void setSimulatorID(const QString& value); + QUuid getSimulatorID() const { return _simulatorID; } + void setSimulatorID(const QUuid& value); quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; } const QString& getMarketplaceID() const { return _marketplaceID; } @@ -352,7 +352,7 @@ protected: bool _collisionsWillMove; bool _locked; QString _userData; - QString _simulatorID; // id of Node which is currently responsible for simulating this Entity + QUuid _simulatorID; // id of Node which is currently responsible for simulating this Entity quint64 _simulatorIDChangedTime; // when was _simulatorID last updated? QString _marketplaceID; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8a25d59f26..2ea8e5f578 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -307,7 +307,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(animationIsPlaying); COPY_PROPERTY_TO_QSCRIPTVALUE(animationFPS); COPY_PROPERTY_TO_QSCRIPTVALUE(animationFrameIndex); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(animationSettings,getAnimationSettings()); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(animationSettings, getAnimationSettings()); COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel); COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha); COPY_PROPERTY_TO_QSCRIPTVALUE(ignoreForCollisions); @@ -319,7 +319,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(locked); COPY_PROPERTY_TO_QSCRIPTVALUE(textures); COPY_PROPERTY_TO_QSCRIPTVALUE(userData); - COPY_PROPERTY_TO_QSCRIPTVALUE(simulatorID); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(simulatorID, getSimulatorIDAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(text); COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); @@ -403,7 +403,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(locked, setLocked); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(textures, setTextures); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(userData, setUserData); - COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(simulatorID, setSimulatorID); + COPY_PROPERTY_FROM_QSCRIPTVALUE_UUID(simulatorID, setSimulatorID); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(text, setText); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 7de0fc0e8b..3788916807 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -200,7 +200,7 @@ public: DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString); DEFINE_PROPERTY_REF_WITH_SETTER_AND_GETTER(PROP_ANIMATION_SETTINGS, AnimationSettings, animationSettings, QString); DEFINE_PROPERTY_REF(PROP_USER_DATA, UserData, userData, QString); - DEFINE_PROPERTY_REF(PROP_SIMULATOR_ID, SimulatorID, simulatorID, QString); + DEFINE_PROPERTY_REF(PROP_SIMULATOR_ID, SimulatorID, simulatorID, QUuid); DEFINE_PROPERTY_REF(PROP_TEXT, Text, text, QString); DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); @@ -257,6 +257,7 @@ public: const QStringList& getTextureNames() const { return _textureNames; } void setTextureNames(const QStringList& value) { _textureNames = value; } + QString getSimulatorIDAsString() const { return _simulatorID.toString().mid(1,36).toUpper(); } private: QUuid _id; @@ -330,7 +331,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Locked, locked, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Textures, textures, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, UserData, userData, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, SimulatorID, simulatorID, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, SimulatorID, simulatorID, QUuid()); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Text, text, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LineHeight, lineHeight, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, TextColor, textColor, ""); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 4b595ae0b8..001f963ecb 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -23,7 +23,7 @@ const glm::vec3 ENTITY_ITEM_ZERO_VEC3(0.0f); const bool ENTITY_ITEM_DEFAULT_LOCKED = false; const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString(""); const QString ENTITY_ITEM_DEFAULT_MARKETPLACE_ID = QString(""); -const QString ENTITY_ITEM_DEFAULT_SIMULATOR_ID = QString(""); +const QUuid ENTITY_ITEM_DEFAULT_SIMULATOR_ID = QUuid(); const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f; diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index e3e54f5bc8..8b9d9847bd 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -88,6 +88,22 @@ } \ } +// TODO: this doesn't need a length. See OctreePacketData::appendValue(const QUuid& uuid) +#define READ_ENTITY_PROPERTY_UUID(P,O) \ + if (propertyFlags.getHasProperty(P)) { \ + uint16_t length; \ + memcpy(&length, dataAt, sizeof(length)); \ + dataAt += sizeof(length); \ + bytesRead += sizeof(length); \ + QByteArray ba((const char*)dataAt, length); \ + QUuid value = QUUid::fromRfc4122(ba); \ + dataAt += length; \ + bytesRead += length; \ + if (overwriteLocalData) { \ + O(value); \ + } \ + } + #define READ_ENTITY_PROPERTY_COLOR(P,M) \ if (propertyFlags.getHasProperty(P)) { \ if (overwriteLocalData) { \ @@ -127,6 +143,20 @@ properties.O(value); \ } + +// TODO: make a version of this that does a binary unpacking of the uuid +#define READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(P,O) \ + if (propertyFlags.getHasProperty(P)) { \ + uint16_t length; \ + memcpy(&length, dataAt, sizeof(length)); \ + dataAt += sizeof(length); \ + processedBytes += sizeof(length); \ + QUuid value((const char*)dataAt); \ + dataAt += length; \ + processedBytes += length; \ + properties.O(value); \ + } + #define READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(P,O) \ if (propertyFlags.getHasProperty(P)) { \ xColor color; \ @@ -207,6 +237,15 @@ } \ } +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_UUID(P, S) \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + QUuid newValue = P.toVariant().toUuid(); \ + if (_defaultSettings || newValue != _##P) { \ + S(newValue); \ + } \ + } + #define COPY_PROPERTY_FROM_QSCRIPTVALUE_VEC3(P, S) \ QScriptValue P = object.property(#P); \ if (P.isValid()) { \ diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index fa142d3abd..57752dff02 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -60,6 +60,19 @@ void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { } + +void setSimId(EntityItemProperties& propertiesWithSimID) { + if (propertiesWithSimID.velocityChanged() || + propertiesWithSimID.rotationChanged() || + propertiesWithSimID.containsPositionChange()) { + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + propertiesWithSimID.setSimulatorID(myNodeID); + } +} + + + EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& properties) { // The application will keep track of creatorTokenID @@ -67,11 +80,7 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro // This Node is creating a new object. If it's in motion, set this Node as the simulator. EntityItemProperties propertiesWithSimID = properties; - if (properties.velocityChanged() || properties.rotationChanged()) { - auto nodeList = DependencyManager::get(); - const QString myNodeID = nodeList->getSessionUUID().toString(); - propertiesWithSimID.setSimulatorID(myNodeID); - } + setSimId(propertiesWithSimID); EntityItemID id(NEW_ENTITY, creatorTokenID, false ); @@ -146,14 +155,10 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E } } - // If this node is changing a physics-related property, claim simulation ownership + // if this Node is changing a physics-related property, claim simulation ownership. EntityItemProperties propertiesWithSimID = properties; - if (properties.velocityChanged() || properties.rotationChanged()) { - auto nodeList = DependencyManager::get(); - const QString myNodeID = nodeList->getSessionUUID().toString(); - propertiesWithSimID.setSimulatorID(myNodeID); - } - + setSimId(propertiesWithSimID); + // If we have a local entity tree set, then also update it. We can do this even if we don't know // the actual id, because we can edit out local entities just with creatorTokenID if (_entityTree) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 2227107537..07f61de8b4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -131,7 +131,7 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro } } else { if (properties.simulatorIDChanged() && - !entity->getSimulatorID().isEmpty() && + !entity->getSimulatorID().isNull() && properties.getSimulatorID() != entity->getSimulatorID()) { // A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this // if ownership hasn't recently changed. diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 3dcd2899d3..ad268edc6f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -719,7 +719,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int if (bytesLeftToRead >= (int)(numberOfEntities * expectedBytesPerEntity)) { // look up the Id of this Node auto nodeList = DependencyManager::get(); - QString myNodeID = nodeList->getSessionUUID().toString(); + QUuid myNodeID = nodeList->getSessionUUID(); for (uint16_t i = 0; i < numberOfEntities; i++) { int bytesForThisEntity = 0; diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 0406aaa443..2c586ae0af 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -38,7 +38,7 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { itemItr = _hasSimulationOwnerEntities.begin(); while (itemItr != _hasSimulationOwnerEntities.end()) { EntityItem* entity = *itemItr; - if (!entity->getSimulatorID().isEmpty() && + if (!entity->getSimulatorID().isNull() && usecTimestampNow() - entity->getLastChangedOnServer() >= AUTO_REMOVE_SIMULATION_OWNER_USEC) { qCDebug(entities) << "auto-removing simulation owner" << entity->getSimulatorID(); entity->setSimulatorID(""); @@ -55,7 +55,7 @@ void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) { } else if (entity->getCollisionsWillMove()) { _movableButStoppedEntities.insert(entity); } - if (!entity->getSimulatorID().isEmpty()) { + if (!entity->getSimulatorID().isNull()) { _hasSimulationOwnerEntities.insert(entity); } } @@ -79,7 +79,7 @@ void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) { _movingEntities.remove(entity); _movableButStoppedEntities.remove(entity); } - if (!entity->getSimulatorID().isEmpty()) { + if (!entity->getSimulatorID().isNull()) { _hasSimulationOwnerEntities.insert(entity); } } diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 674faa11c3..346d2f1a79 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -411,6 +411,17 @@ bool OctreePacketData::appendValue(const QString& string) { return success; } +bool OctreePacketData::appendValue(const QUuid& uuid) { + // TODO: this doesn't need a length + QByteArray bytes = uuid.toRfc4122(); + uint16_t length = bytes.size(); + bool success = appendValue(length); + if (success) { + success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); + } + return success; +} + bool OctreePacketData::appendValue(const QByteArray& bytes) { bool success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); return success; diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 1c1576f509..992eca99ae 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -166,6 +166,9 @@ public: /// appends a string value to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QString& string); + /// appends a uuid value to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QUuid& uuid); + /// appends a QByteArray value to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QByteArray& bytes); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 655db8fd2f..02d2ed896b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -188,10 +188,10 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { } auto nodeList = DependencyManager::get(); - QString myNodeID = nodeList->getSessionUUID().toString(); - QString simulatorID = _entity->getSimulatorID(); + QUuid myNodeID = nodeList->getSessionUUID(); + QUuid simulatorID = _entity->getSimulatorID(); - if (!simulatorID.isEmpty() && simulatorID != myNodeID) { + if (!simulatorID.isNull() && simulatorID != myNodeID) { // some other Node is simulating this, so don't broadcast our computations. return false; } @@ -249,13 +249,13 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ auto nodeList = DependencyManager::get(); - QString myNodeID = nodeList->getSessionUUID().toString(); - QString simulatorID = _entity->getSimulatorID(); - if (simulatorID.isEmpty() && !(zeroSpeed && zeroSpin)) { + QUuid myNodeID = nodeList->getSessionUUID(); + QUuid simulatorID = _entity->getSimulatorID(); + if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && _numNonMovingUpdates >= MAX_NUM_NON_MOVING_UPDATES - 1) { + } else if (simulatorID == myNodeID && _numNonMovingUpdates >= MAX_NUM_NON_MOVING_UPDATES - 2) { // we are the simulator and the object has stopped. give up "simulator" status _entity->setSimulatorID(""); properties.setSimulatorID(""); @@ -293,6 +293,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ #ifdef WANT_DEBUG qCDebug(physics) << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()..."; #endif + entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties); } else { #ifdef WANT_DEBUG From d7881f18916e6375eef467d1264865aee18f2120 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 15:15:28 -0700 Subject: [PATCH 32/60] adjust logic for releasing ownership of simulation --- libraries/entities/src/EntityEditPacketSender.cpp | 2 +- libraries/physics/src/EntityMotionState.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 6f58a5a626..5f77d1e782 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -41,7 +41,7 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI auto nodeList = DependencyManager::get(); QUuid myNodeID = nodeList->getSessionUUID(); QString x = properties.getSimulatorID() == myNodeID ? "me" : properties.getSimulatorID().toString(); - qDebug() << "sending update:" << properties.simulatorIDChanged() << properties.getSimulatorID(); + qDebug() << "sending update:" << properties.simulatorIDChanged() << x; //// XXX diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 02d2ed896b..9af97d20ad 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -251,14 +251,20 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ auto nodeList = DependencyManager::get(); QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); + + // qDebug() << "XXX me =" << (simulatorID == myNodeID) + // << "_numNonMovingUpdates =" << _numNonMovingUpdates + // << "stopped =" << (zeroSpin && zeroSpeed) + // << "active =" << _body->isActive(); + if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); - } else if (simulatorID == myNodeID && _numNonMovingUpdates >= MAX_NUM_NON_MOVING_UPDATES - 2) { + } else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) { // we are the simulator and the object has stopped. give up "simulator" status - _entity->setSimulatorID(""); - properties.setSimulatorID(""); + _entity->setSimulatorID(QUuid()); + properties.setSimulatorID(QUuid()); } // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. From ea8dcfa5b51207becb9a655ab487f043f83c2b30 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 15:33:43 -0700 Subject: [PATCH 33/60] read UUIDs as UUIDs rather than as strings. more debugging prints --- libraries/entities/src/EntityItem.cpp | 2 +- libraries/entities/src/EntityItemPropertiesMacros.h | 3 ++- libraries/physics/src/EntityMotionState.cpp | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 94d4d7f8a7..5a37baf4a0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -569,7 +569,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA, setUserData); if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) { - READ_ENTITY_PROPERTY_STRING(PROP_SIMULATOR_ID, setSimulatorID); + READ_ENTITY_PROPERTY_UUID(PROP_SIMULATOR_ID, setSimulatorID); } if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) { diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 8b9d9847bd..1611a542c9 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -96,7 +96,8 @@ dataAt += sizeof(length); \ bytesRead += sizeof(length); \ QByteArray ba((const char*)dataAt, length); \ - QUuid value = QUUid::fromRfc4122(ba); \ + QUuid value = QUuid::fromRfc4122(ba); \ + qDebug() << "UUID" << value; \ dataAt += length; \ bytesRead += length; \ if (overwriteLocalData) { \ diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9af97d20ad..c3da5b35d1 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,8 +191,11 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); + qDebug() << "XXX" << simulatorID << myNodeID; + if (!simulatorID.isNull() && simulatorID != myNodeID) { // some other Node is simulating this, so don't broadcast our computations. + qDebug() << "NOT SENDING DUE TO NOT OWNER"; return false; } From 3b2a15f76a2488ef2641272b122b54defef3d5a2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 15:52:48 -0700 Subject: [PATCH 34/60] more debugging --- libraries/entities/src/EntityItemPropertiesMacros.h | 2 +- libraries/octree/src/OctreePacketData.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 1611a542c9..283d09b4be 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -97,7 +97,7 @@ bytesRead += sizeof(length); \ QByteArray ba((const char*)dataAt, length); \ QUuid value = QUuid::fromRfc4122(ba); \ - qDebug() << "UUID" << value; \ + qDebug() << "READING UUID" << (unsigned int)ba[0] << (unsigned int)ba[1] << value << length; \ dataAt += length; \ bytesRead += length; \ if (overwriteLocalData) { \ diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 346d2f1a79..3a12cc646e 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -418,6 +418,7 @@ bool OctreePacketData::appendValue(const QUuid& uuid) { bool success = appendValue(length); if (success) { success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); + qDebug() << "SENDING UUID" << (unsigned int)bytes[0] << (unsigned int)bytes[1] << uuid << length; } return success; } From 1484d6e37fd6796fd46fc004a01463351da3e9f3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 16:10:01 -0700 Subject: [PATCH 35/60] fix READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES to use binary version --- libraries/entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/EntityItemPropertiesMacros.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 2ea8e5f578..e75fa8104f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -798,7 +798,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONS_WILL_MOVE, bool, setCollisionsWillMove); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_USER_DATA, setUserData); - READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_SIMULATOR_ID, setSimulatorID); + READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(PROP_SIMULATOR_ID, setSimulatorID); if (properties.getType() == EntityTypes::Text) { READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXT, setText); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 283d09b4be..ff66a16c6b 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -145,14 +145,15 @@ } -// TODO: make a version of this that does a binary unpacking of the uuid +// TODO: this doesn't need a length. See OctreePacketData::appendValue(const QUuid& uuid) #define READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(P,O) \ if (propertyFlags.getHasProperty(P)) { \ uint16_t length; \ memcpy(&length, dataAt, sizeof(length)); \ dataAt += sizeof(length); \ processedBytes += sizeof(length); \ - QUuid value((const char*)dataAt); \ + QByteArray ba((const char*)dataAt, length); \ + QUuid value = QUuid::fromRfc4122(ba); \ dataAt += length; \ processedBytes += length; \ properties.O(value); \ From f48f9caea48e01a72d86a0ce06caf744989da690 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 16:18:13 -0700 Subject: [PATCH 36/60] cut back on debuging prints --- libraries/entities/src/EntityItemPropertiesMacros.h | 1 - libraries/octree/src/OctreePacketData.cpp | 1 - libraries/physics/src/EntityMotionState.cpp | 8 -------- 3 files changed, 10 deletions(-) diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index ff66a16c6b..4a0b5c210d 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -97,7 +97,6 @@ bytesRead += sizeof(length); \ QByteArray ba((const char*)dataAt, length); \ QUuid value = QUuid::fromRfc4122(ba); \ - qDebug() << "READING UUID" << (unsigned int)ba[0] << (unsigned int)ba[1] << value << length; \ dataAt += length; \ bytesRead += length; \ if (overwriteLocalData) { \ diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 3a12cc646e..346d2f1a79 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -418,7 +418,6 @@ bool OctreePacketData::appendValue(const QUuid& uuid) { bool success = appendValue(length); if (success) { success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); - qDebug() << "SENDING UUID" << (unsigned int)bytes[0] << (unsigned int)bytes[1] << uuid << length; } return success; } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c3da5b35d1..2d38667e6d 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,11 +191,8 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); - qDebug() << "XXX" << simulatorID << myNodeID; - if (!simulatorID.isNull() && simulatorID != myNodeID) { // some other Node is simulating this, so don't broadcast our computations. - qDebug() << "NOT SENDING DUE TO NOT OWNER"; return false; } @@ -255,11 +252,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); - // qDebug() << "XXX me =" << (simulatorID == myNodeID) - // << "_numNonMovingUpdates =" << _numNonMovingUpdates - // << "stopped =" << (zeroSpin && zeroSpeed) - // << "active =" << _body->isActive(); - if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); From ec26b4595ad0722ee276daf763a8e911045e2e83 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 16:27:30 -0700 Subject: [PATCH 37/60] adjust comment --- libraries/physics/src/EntityMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 2d38667e6d..91776b211c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -192,7 +192,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { QUuid simulatorID = _entity->getSimulatorID(); if (!simulatorID.isNull() && simulatorID != myNodeID) { - // some other Node is simulating this, so don't broadcast our computations. + // some other Node owns the simulating of this, so don't broadcast the results of local simulation. return false; } From faf5e7415dabe002296655dfdfdba717e50880f8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 16:32:51 -0700 Subject: [PATCH 38/60] don't explicitly release simulator status --- libraries/physics/src/EntityMotionState.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 91776b211c..d54ee3571a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -258,8 +258,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setSimulatorID(myNodeID); } else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) { // we are the simulator and the object has stopped. give up "simulator" status - _entity->setSimulatorID(QUuid()); - properties.setSimulatorID(QUuid()); + + // XXX the entity server will clear the simulatorID after 2 seconds. if the interface clears + // it here, every node that sees the entity-stopped-moving packets will rebroadcast them. + + // _entity->setSimulatorID(QUuid()); + // properties.setSimulatorID(QUuid()); } // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. @@ -270,7 +274,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ } if (_numNonMovingUpdates <= 1) { // we only update lastEdited when we're sending new physics data - // (i.e. NOT when we just simulate the positions forward, nore when we resend non-moving data) + // (i.e. NOT when we just simulate the positions forward, nor when we resend non-moving data) // NOTE: Andrew & Brad to discuss. Let's make sure we're using lastEdited, lastSimulated, and lastUpdated correctly quint64 lastSimulated = _entity->getLastSimulated(); _entity->setLastEdited(lastSimulated); From 62a45ccebb6e3ea9804217f472e4e1db06a6ebb6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 16 Apr 2015 17:00:36 -0700 Subject: [PATCH 39/60] re-enable code that gives up simulation ownership --- libraries/physics/src/EntityMotionState.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index d54ee3571a..1324603bad 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -258,12 +258,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setSimulatorID(myNodeID); } else if (simulatorID == myNodeID && zeroSpeed && zeroSpin) { // we are the simulator and the object has stopped. give up "simulator" status - - // XXX the entity server will clear the simulatorID after 2 seconds. if the interface clears - // it here, every node that sees the entity-stopped-moving packets will rebroadcast them. - - // _entity->setSimulatorID(QUuid()); - // properties.setSimulatorID(QUuid()); + _entity->setSimulatorID(QUuid()); + properties.setSimulatorID(QUuid()); } // RELIABLE_SEND_HACK: count number of updates for entities at rest so we can stop sending them after some limit. From f77038c52d6a75e7bccbe4f1b1aab520c21026c2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 09:37:48 -0700 Subject: [PATCH 40/60] when ignoring an incoming packet, still read it so the data-stream pointer doesn't get screwed up --- libraries/entities/src/EntityItem.cpp | 5 ++--- libraries/entities/src/EntityItem.h | 3 ++- libraries/entities/src/EntityTreeElement.cpp | 11 +++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5a37baf4a0..3f342c4d86 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -312,7 +312,8 @@ int EntityItem::expectedBytes() { } -int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { +int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, + bool ignoreServerPacket) { if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) { @@ -421,8 +422,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef 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) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 634b7e7d3d..b9def4f1db 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -113,7 +113,8 @@ public: static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); + virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, + bool ignoreServerPacket = false); virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index ad268edc6f..a94891ea7e 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -696,7 +696,6 @@ bool EntityTreeElement::removeEntityItem(EntityItem* entity) { // and dirty path marking in one pass. int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { - // If we're the root, but this bitstream doesn't support root elements with data, then // return without reading any bytes if (this == _myTree->getRoot() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) { @@ -735,20 +734,20 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int } // If the item already exists in our tree, we want do the following... - // 0) if this node is the simulator for the entity, ignore the update packet // 1) allow the existing item to read from the databuffer // 2) check to see if after reading the item, the containing element is still correct, fix it if needed // // TODO: Do we need to also do this? // 3) remember the old cube for the entity so we can mark it as dirty - if (entityItem && entityItem->getSimulatorID() == myNodeID) { - // do nothing, this was echoed back to us by the entity server - } else if (entityItem) { + if (entityItem) { QString entityScriptBefore = entityItem->getScript(); bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); - bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); + // this Node was the original source of this packet, so read it, but ignore it. + bool shouldIgnore = (entityItem && entityItem->getSimulatorID() == myNodeID); + + bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args, shouldIgnore); if (entityItem->getDirtyFlags()) { _myTree->entityChanged(entityItem); } From c69aaa806b0d5f33ba17f969bee8d9ffe671beb7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 09:55:49 -0700 Subject: [PATCH 41/60] if a uuid is null, don't send a uuid of all zeros --- .../entities/src/EntityItemPropertiesMacros.h | 60 +++++++++++-------- libraries/octree/src/OctreePacketData.cpp | 15 +++-- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 4a0b5c210d..be6a221af4 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -88,20 +88,24 @@ } \ } -// TODO: this doesn't need a length. See OctreePacketData::appendValue(const QUuid& uuid) -#define READ_ENTITY_PROPERTY_UUID(P,O) \ - if (propertyFlags.getHasProperty(P)) { \ - uint16_t length; \ - memcpy(&length, dataAt, sizeof(length)); \ - dataAt += sizeof(length); \ - bytesRead += sizeof(length); \ - QByteArray ba((const char*)dataAt, length); \ - QUuid value = QUuid::fromRfc4122(ba); \ - dataAt += length; \ - bytesRead += length; \ - if (overwriteLocalData) { \ - O(value); \ - } \ +#define READ_ENTITY_PROPERTY_UUID(P,O) \ + if (propertyFlags.getHasProperty(P)) { \ + uint16_t length; \ + memcpy(&length, dataAt, sizeof(length)); \ + dataAt += sizeof(length); \ + bytesRead += sizeof(length); \ + QUuid value; \ + if (length == 0) { \ + value = QUuid(); \ + } else { \ + QByteArray ba((const char*)dataAt, length); \ + value = QUuid::fromRfc4122(ba); \ + dataAt += length; \ + bytesRead += length; \ + } \ + if (overwriteLocalData) { \ + O(value); \ + } \ } #define READ_ENTITY_PROPERTY_COLOR(P,M) \ @@ -144,18 +148,22 @@ } -// TODO: this doesn't need a length. See OctreePacketData::appendValue(const QUuid& uuid) -#define READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(P,O) \ - if (propertyFlags.getHasProperty(P)) { \ - uint16_t length; \ - memcpy(&length, dataAt, sizeof(length)); \ - dataAt += sizeof(length); \ - processedBytes += sizeof(length); \ - QByteArray ba((const char*)dataAt, length); \ - QUuid value = QUuid::fromRfc4122(ba); \ - dataAt += length; \ - processedBytes += length; \ - properties.O(value); \ +#define READ_ENTITY_PROPERTY_UUID_TO_PROPERTIES(P,O) \ + if (propertyFlags.getHasProperty(P)) { \ + uint16_t length; \ + memcpy(&length, dataAt, sizeof(length)); \ + dataAt += sizeof(length); \ + processedBytes += sizeof(length); \ + QUuid value; \ + if (length == 0) { \ + value = QUuid(); \ + } else { \ + QByteArray ba((const char*)dataAt, length); \ + value = QUuid::fromRfc4122(ba); \ + dataAt += length; \ + processedBytes += length; \ + } \ + properties.O(value); \ } #define READ_ENTITY_PROPERTY_COLOR_TO_PROPERTIES(P,O) \ diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 346d2f1a79..64947010a0 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -412,14 +412,17 @@ bool OctreePacketData::appendValue(const QString& string) { } bool OctreePacketData::appendValue(const QUuid& uuid) { - // TODO: this doesn't need a length QByteArray bytes = uuid.toRfc4122(); - uint16_t length = bytes.size(); - bool success = appendValue(length); - if (success) { - success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); + if (uuid.isNull()) { + return appendValue((uint16_t)0); // zero length for null uuid + } else { + uint16_t length = bytes.size(); + bool success = appendValue(length); + if (success) { + success = appendRawData((const unsigned char*)bytes.constData(), bytes.size()); + } + return success; } - return success; } bool OctreePacketData::appendValue(const QByteArray& bytes) { From deec577db6695c1a25ef707392af37ae0ea9baaa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 10:21:52 -0700 Subject: [PATCH 42/60] if nodes are fighting over phyics variables, squash physics-related properties in the updates from the loser of the race --- .../entities/src/EntityItemPropertiesMacros.h | 5 +++++ libraries/entities/src/EntityTree.cpp | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index be6a221af4..9cb3449d59 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -338,6 +338,7 @@ T get##N() const { return _##n; } \ void set##N(T value) { _##n = value; _##n##Changed = true; } \ bool n##Changed() const { return _##n##Changed; } \ + void set##N##Changed(bool value) { _##n##Changed = value; } \ private: \ T _##n; \ bool _##n##Changed; @@ -347,6 +348,7 @@ const T& get##N() const { return _##n; } \ void set##N(const T& value) { _##n = value; _##n##Changed = true; } \ bool n##Changed() const { return _##n##Changed; } \ + void set##N##Changed(bool value) { _##n##Changed = value; } \ private: \ T _##n; \ bool _##n##Changed; @@ -356,6 +358,7 @@ const T& get##N() const { return _##n; } \ void set##N(const T& value); \ bool n##Changed() const; \ + void set##N##Changed(bool value) { _##n##Changed = value; } \ private: \ T _##n; \ bool _##n##Changed; @@ -365,6 +368,7 @@ T get##N() const; \ void set##N(const T& value); \ bool n##Changed() const; \ + void set##N##Changed(bool value) { _##n##Changed = value; } \ private: \ T _##n; \ bool _##n##Changed; @@ -376,6 +380,7 @@ bool n##Changed() const { return _##n##Changed; } \ QString get##N##AsString() const; \ void set##N##FromString(const QString& name); \ + void set##N##Changed(bool value) { _##n##Changed = value; } \ private: \ T _##n; \ bool _##n##Changed; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 07f61de8b4..02568ef782 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -24,6 +24,10 @@ #include "EntitiesLogging.h" #include "RecurseOctreeToMapOperator.h" + +const quint64 SIMULATOR_CHANGE_LOCKOUT_PERIOD = 0.2 * USECS_PER_SECOND; + + EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _fbxService(NULL), @@ -108,9 +112,9 @@ bool EntityTree::updateEntity(EntityItem* entity, const EntityItemProperties& pr return updateEntityWithElement(entity, properties, containingElement, allowLockChange); } -bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& properties, +bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemProperties& origProperties, EntityTreeElement* containingElement, bool allowLockChange) { - + EntityItemProperties properties = origProperties; if (!allowLockChange && (entity->getLocked() != properties.getLocked())) { qCDebug(entities) << "Refusing disallowed lock adjustment."; return false; @@ -136,8 +140,13 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro // A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this // if ownership hasn't recently changed. quint64 now = usecTimestampNow(); - if (now - entity->getSimulatorIDChangedTime() < 2 * USECS_PER_SECOND) { // XXX pick time and put in constant - qDebug() << "TOO SOON"; + if (now - entity->getSimulatorIDChangedTime() < SIMULATOR_CHANGE_LOCKOUT_PERIOD) { + qDebug() << "SIMULATOR_CHANGE_LOCKOUT_PERIOD"; + // squash the physics-related changes. + properties.setSimulatorIDChanged(false); + properties.setPositionChanged(false); + properties.setVelocityChanged(false); + properties.setAccelerationChanged(false); } } From 3da2d1680dc1441cac73d7c6e7f0947e1171ca5e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 10:41:11 -0700 Subject: [PATCH 43/60] fix code that causes scripted changes to physics-related entity properties to claim simulation ownership --- libraries/entities/src/EntityScriptingInterface.cpp | 12 ++++-------- libraries/entities/src/EntityTree.cpp | 6 +++--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 57752dff02..392cd92ab6 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -170,18 +170,14 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E // if at this point, we know the id, send the update to the entity server if (entityID.isKnownID) { // make sure the properties has a type, so that the encode can know which properties to include - if (properties.getType() == EntityTypes::Unknown) { + if (propertiesWithSimID.getType() == EntityTypes::Unknown) { EntityItem* entity = _entityTree->findEntityByEntityItemID(entityID); if (entity) { - EntityItemProperties tempProperties = properties; - tempProperties.setType(entity->getType()); - queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, tempProperties); - return entityID; + propertiesWithSimID.setType(entity->getType()); } } - - // if the properties already includes the type, then use it as is - queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, properties); + + queueEntityMessage(PacketTypeEntityAddOrEdit, entityID, propertiesWithSimID); } return entityID; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 02568ef782..7c2f41ed2c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -139,9 +139,9 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro properties.getSimulatorID() != entity->getSimulatorID()) { // A Node is trying to take ownership of the simulation of this entity from another Node. Only allow this // if ownership hasn't recently changed. - quint64 now = usecTimestampNow(); - if (now - entity->getSimulatorIDChangedTime() < SIMULATOR_CHANGE_LOCKOUT_PERIOD) { - qDebug() << "SIMULATOR_CHANGE_LOCKOUT_PERIOD"; + if (usecTimestampNow() - entity->getSimulatorIDChangedTime() < SIMULATOR_CHANGE_LOCKOUT_PERIOD) { + qCDebug(entities) << "simulator_change_lockout_period:" + << entity->getSimulatorID() << "to" << properties.getSimulatorID(); // squash the physics-related changes. properties.setSimulatorIDChanged(false); properties.setPositionChanged(false); From 32ced31f603ec805b25ef67636d6559a1853eef3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 10:57:00 -0700 Subject: [PATCH 44/60] adjust logic related to claiming and releasing simulation ownership during scripted changes to entities --- .../entities/src/EntityScriptingInterface.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 392cd92ab6..6bd988ec90 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -61,13 +61,18 @@ void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { -void setSimId(EntityItemProperties& propertiesWithSimID) { +void setSimId(EntityItemProperties& propertiesWithSimID, EntityItem* entity) { + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + if (propertiesWithSimID.velocityChanged() || propertiesWithSimID.rotationChanged() || propertiesWithSimID.containsPositionChange()) { - auto nodeList = DependencyManager::get(); - const QUuid myNodeID = nodeList->getSessionUUID(); propertiesWithSimID.setSimulatorID(myNodeID); + entity->setSimulatorID(myNodeID); + } else if (entity->getSimulatorID() == myNodeID) { + propertiesWithSimID.setSimulatorID(QUuid()); // give up simulation ownership + entity->setSimulatorID(QUuid()); } } @@ -80,14 +85,14 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro // This Node is creating a new object. If it's in motion, set this Node as the simulator. EntityItemProperties propertiesWithSimID = properties; - setSimId(propertiesWithSimID); EntityItemID id(NEW_ENTITY, creatorTokenID, false ); // If we have a local entity tree set, then also update it. if (_entityTree) { _entityTree->lockForWrite(); - _entityTree->addEntity(id, propertiesWithSimID); + EntityItem* entity = _entityTree->addEntity(id, propertiesWithSimID); + setSimId(propertiesWithSimID, entity); _entityTree->unlock(); } @@ -157,7 +162,6 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E // if this Node is changing a physics-related property, claim simulation ownership. EntityItemProperties propertiesWithSimID = properties; - setSimId(propertiesWithSimID); // If we have a local entity tree set, then also update it. We can do this even if we don't know // the actual id, because we can edit out local entities just with creatorTokenID @@ -174,6 +178,7 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E EntityItem* entity = _entityTree->findEntityByEntityItemID(entityID); if (entity) { propertiesWithSimID.setType(entity->getType()); + setSimId(propertiesWithSimID, entity); } } From d90dec066c52a0d1d57f854f097e63c0514e0127 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 11:12:13 -0700 Subject: [PATCH 45/60] if an entity has no simulatorID, pull it out of list of entities with simulatorIDs --- libraries/entities/src/SimpleEntitySimulation.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index 2c586ae0af..6343ed3e47 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -38,10 +38,11 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) { itemItr = _hasSimulationOwnerEntities.begin(); while (itemItr != _hasSimulationOwnerEntities.end()) { EntityItem* entity = *itemItr; - if (!entity->getSimulatorID().isNull() && - usecTimestampNow() - entity->getLastChangedOnServer() >= AUTO_REMOVE_SIMULATION_OWNER_USEC) { + if (entity->getSimulatorID().isNull()) { + itemItr = _hasSimulationOwnerEntities.erase(itemItr); + } else if (usecTimestampNow() - entity->getLastChangedOnServer() >= AUTO_REMOVE_SIMULATION_OWNER_USEC) { qCDebug(entities) << "auto-removing simulation owner" << entity->getSimulatorID(); - entity->setSimulatorID(""); + entity->setSimulatorID(QUuid()); itemItr = _hasSimulationOwnerEntities.erase(itemItr); } else { ++itemItr; From 07b9d73edf341063b6894f59b8011bb6220c35aa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 11:20:35 -0700 Subject: [PATCH 46/60] bump protocol version --- libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 52153f9e83..4d7979bddf 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_HAVE_ACCELERATION; + return VERSION_ENTITIES_HAVE_UUIDS; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 9fb14854aa..979eb4d451 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -135,6 +135,7 @@ const PacketVersion VERSION_ENTITIES_HAS_COLLISION_MODEL = 12; const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED = 13; const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14; const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15; +const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h From dac57c44da697811fa6890a2c62b5b8c764c29b0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 15:05:47 -0700 Subject: [PATCH 47/60] if measured acceleration is close to zero, send zero to entity server, else send gravity --- .../entities/src/EntityEditPacketSender.cpp | 8 +++---- libraries/entities/src/EntityItem.cpp | 19 ++++----------- libraries/entities/src/EntityItem.h | 4 ++-- libraries/physics/src/EntityMotionState.cpp | 23 ++++++++++++------- libraries/physics/src/ObjectMotionState.cpp | 3 ++- libraries/physics/src/ObjectMotionState.h | 1 + 6 files changed, 28 insertions(+), 30 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 5f77d1e782..478603dedf 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -38,10 +38,10 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI //// XXX - auto nodeList = DependencyManager::get(); - QUuid myNodeID = nodeList->getSessionUUID(); - QString x = properties.getSimulatorID() == myNodeID ? "me" : properties.getSimulatorID().toString(); - qDebug() << "sending update:" << properties.simulatorIDChanged() << x; + // auto nodeList = DependencyManager::get(); + // QUuid myNodeID = nodeList->getSessionUUID(); + // QString x = properties.getSimulatorID() == myNodeID ? "me" : properties.getSimulatorID().toString(); + // qDebug() << "sending update:" << properties.simulatorIDChanged() << x; //// XXX diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 3f342c4d86..b771279efa 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -699,6 +699,7 @@ void EntityItem::simulate(const quint64& now) { qCDebug(entities) << " MOVING...="; qCDebug(entities) << " hasVelocity=" << hasVelocity(); qCDebug(entities) << " hasGravity=" << hasGravity(); + qCDebug(entities) << " hasAcceleration=" << hasAcceleration(); qCDebug(entities) << " hasAngularVelocity=" << hasAngularVelocity(); qCDebug(entities) << " getAngularVelocity=" << getAngularVelocity(); } @@ -788,13 +789,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) { position = newPosition; - // apply gravity - if (hasGravity()) { - // handle resting on surface case, this is definitely a bit of a hack, and it only works on the - // "ground" plane of the domain, but for now it's what we've got - velocity += getGravity() * timeElapsed; - } - + // apply effective acceleration, which will be the same as gravity if the Entity isn't at rest. if (hasAcceleration()) { velocity += getAcceleration() * timeElapsed; } @@ -1151,14 +1146,8 @@ void EntityItem::updateGravity(const glm::vec3& value) { } void EntityItem::updateAcceleration(const glm::vec3& value) { - if (glm::distance(_acceleration, value) > MIN_ACCELERATION_DELTA) { - if (glm::length(value) < MIN_ACCELERATION_DELTA) { - _acceleration = ENTITY_ITEM_ZERO_VEC3; - } else { - _acceleration = value; - } - _dirtyFlags |= EntityItem::DIRTY_VELOCITY; - } + _acceleration = value; + _dirtyFlags |= EntityItem::DIRTY_VELOCITY; } void EntityItem::updateAngularVelocity(const glm::vec3& value) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b9def4f1db..96186b4c91 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -195,8 +195,8 @@ public: void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3 getAcceleration() const { return _acceleration; } /// get acceleration in meters/second - void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second + const glm::vec3 getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second + void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; } float getDamping() const { return _damping; } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index f5468a0978..95a3dff6af 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -18,6 +18,7 @@ #include "PhysicsHelpers.h" #include "PhysicsLogging.h" +static const float MEASURED_ACCELERATION_CLOSE_TO_ZERO = 0.05; QSet* _outgoingEntityList; @@ -166,8 +167,8 @@ void EntityMotionState::updateObjectVelocities() { _sentAngularVelocity = _entity->getAngularVelocity(); setAngularVelocity(_sentAngularVelocity); - _sentAcceleration = _entity->getGravity(); - setGravity(_sentAcceleration); + _sentGravity = _entity->getGravity(); + setGravity(_sentGravity); _body->setActivationState(ACTIVE_TAG); } @@ -191,8 +192,8 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { } auto nodeList = DependencyManager::get(); - QUuid myNodeID = nodeList->getSessionUUID(); - QUuid simulatorID = _entity->getSimulatorID(); + const QUuid& myNodeID = nodeList->getSessionUUID(); + const QUuid& simulatorID = _entity->getSimulatorID(); if (!simulatorID.isNull() && simulatorID != myNodeID) { // some other Node owns the simulating of this, so don't broadcast the results of local simulation. @@ -203,13 +204,18 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { } void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) { - if (!_entity->isKnownID()) { return; // never update entities that are unknown } if (_outgoingPacketFlags) { EntityItemProperties properties = _entity->getProperties(); + if (glm::length(_measuredAcceleration) < MEASURED_ACCELERATION_CLOSE_TO_ZERO) { + _entity->setAcceleration(glm::vec3(0)); + } else { + _entity->setAcceleration(_entity->getGravity()); + } + if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { btTransform worldTrans = _body->getWorldTransform(); _sentPosition = bulletToGLM(worldTrans.getOrigin()); @@ -245,12 +251,13 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _sentMoving = false; } properties.setVelocity(_sentVelocity); - _sentAcceleration = bulletToGLM(_body->getGravity()); - properties.setGravity(_sentAcceleration); + _sentGravity = _entity->getGravity(); + properties.setGravity(_entity->getGravity()); + _sentAcceleration = _entity->getAcceleration(); + properties.setAcceleration(_sentAcceleration); properties.setAngularVelocity(_sentAngularVelocity); } - auto nodeList = DependencyManager::get(); QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 3d790ff7d4..852f2a96bd 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -57,6 +57,7 @@ ObjectMotionState::ObjectMotionState() : _sentRotation(), _sentVelocity(0.0f), _sentAngularVelocity(0.0f), + _sentGravity(0.0f), _sentAcceleration(0.0f), _lastSimulationStep(0), _lastVelocity(0.0f), @@ -174,7 +175,7 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationStep) { // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. - // NOTE: math in done the simulation-frame, which is NOT necessarily the same as the world-frame + // NOTE: math is done the simulation-frame, which is NOT necessarily the same as the world-frame // due to _worldOffset. // compute position error diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 9b5d6e7aa6..ad9ef861b9 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -138,6 +138,7 @@ protected: glm::quat _sentRotation;; glm::vec3 _sentVelocity; glm::vec3 _sentAngularVelocity; // radians per second + glm::vec3 _sentGravity; glm::vec3 _sentAcceleration; uint32_t _lastSimulationStep; From adfc82e1696305daf1b1fdffb532529c6041b94e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 15:10:34 -0700 Subject: [PATCH 48/60] remove commented-out code --- libraries/entities/src/EntityEditPacketSender.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 478603dedf..e94725782d 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -36,15 +36,6 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityItemI unsigned char bufferOut[MAX_PACKET_SIZE]; int sizeOut = 0; - - //// XXX - // auto nodeList = DependencyManager::get(); - // QUuid myNodeID = nodeList->getSessionUUID(); - // QString x = properties.getSimulatorID() == myNodeID ? "me" : properties.getSimulatorID().toString(); - // qDebug() << "sending update:" << properties.simulatorIDChanged() << x; - //// XXX - - if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) { #ifdef WANT_DEBUG qCDebug(entities) << "calling queueOctreeEditMessage()..."; From e9d8c53f7544fabdd1ba062ee19bf1cc1099fab7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 15:18:05 -0700 Subject: [PATCH 49/60] undo dice testing hack --- examples/dice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dice.js b/examples/dice.js index 2b6d4d478e..b118a6b289 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -13,7 +13,7 @@ // var isDice = false; -var NUMBER_OF_DICE = 1; +var NUMBER_OF_DICE = 2; var dice = []; var DIE_SIZE = 0.20; From b3cb9fe9a402a777b5bda2557a15cf016829f242 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 17 Apr 2015 15:33:41 -0700 Subject: [PATCH 50/60] fix comment some more --- libraries/physics/src/ObjectMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 852f2a96bd..3d8e578056 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -175,7 +175,7 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationStep) { // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. - // NOTE: math is done the simulation-frame, which is NOT necessarily the same as the world-frame + // NOTE: math is done in the simulation-frame, which is NOT necessarily the same as the world-frame // due to _worldOffset. // compute position error From fbff3627dcadc06532c91ee370d6d8ae34045498 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 11:13:51 -0700 Subject: [PATCH 51/60] attempt to claim simulation ownership of entities the avatar crashes with --- libraries/physics/src/EntityMotionState.cpp | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 37 ++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 95a3dff6af..37472695c6 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -305,6 +305,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ qCDebug(physics) << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()..."; #endif + qCDebug(physics) << "EntityMotionState::sendUpdate()"; + entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties); } else { #ifdef WANT_DEBUG diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index aa9921be64..af4349a66e 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -23,8 +23,9 @@ uint32_t PhysicsEngine::getNumSubsteps() { return _numSubsteps; } -PhysicsEngine::PhysicsEngine(const glm::vec3& offset) - : _originOffset(offset) { +PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : + _originOffset(offset), + _characterController(NULL) { } PhysicsEngine::~PhysicsEngine() { @@ -367,6 +368,12 @@ void PhysicsEngine::stepNonPhysicalKinematics(const quint64& now) { void PhysicsEngine::computeCollisionEvents() { BT_PROFILE("computeCollisionEvents"); + + const btCollisionObject* characterCollisionObject = + _characterController ? _characterController->getCollisionObject() : NULL; + auto nodeList = DependencyManager::get(); + const QUuid& myNodeID = nodeList->getSessionUUID(); + // update all contacts every frame int numManifolds = _collisionDispatcher->getNumManifolds(); for (int i = 0; i < numManifolds; ++i) { @@ -382,12 +389,34 @@ void PhysicsEngine::computeCollisionEvents() { // which will eventually trigger a CONTACT_EVENT_TYPE_END continue; } - + void* a = objectA->getUserPointer(); void* b = objectB->getUserPointer(); if (a || b) { // the manifold has up to 4 distinct points, but only extract info from the first - _contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset); + const ContactKey& contactKey = ContactKey(a, b); + ContactInfo& contactInfo = _contactMap[contactKey]; + contactInfo.update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset); + + // if our character capsule is colliding with something dynamic, claim simulation ownership. + // do this by setting the entity's simulator-id to NULL, thereby causing EntityMotionState::sendUpdate + // to set ownership to us. + if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) { + ObjectMotionState* B = static_cast(b); + EntityItem* entityB = static_cast(B)->getEntity(); + if (entityB->getSimulatorID() != myNodeID) { + qDebug() << "CLAIMING B"; + entityB->setSimulatorID(NULL); + } + } + if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) { + ObjectMotionState* A = static_cast(a); + EntityItem* entityA = static_cast(A)->getEntity(); + if (entityA->getSimulatorID() != myNodeID) { + qDebug() << "CLAIMING A"; + entityA->setSimulatorID(NULL); + } + } } } } From 88f289f3c1f475e3dd1aaa803f4f0d771606ab6e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 11:19:48 -0700 Subject: [PATCH 52/60] small cleanup and some debugging prints --- libraries/physics/src/PhysicsEngine.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index af4349a66e..88b3a1362c 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -394,25 +394,21 @@ void PhysicsEngine::computeCollisionEvents() { void* b = objectB->getUserPointer(); if (a || b) { // the manifold has up to 4 distinct points, but only extract info from the first - const ContactKey& contactKey = ContactKey(a, b); - ContactInfo& contactInfo = _contactMap[contactKey]; - contactInfo.update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset); + _contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset); // if our character capsule is colliding with something dynamic, claim simulation ownership. // do this by setting the entity's simulator-id to NULL, thereby causing EntityMotionState::sendUpdate // to set ownership to us. if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) { - ObjectMotionState* B = static_cast(b); - EntityItem* entityB = static_cast(B)->getEntity(); - if (entityB->getSimulatorID() != myNodeID) { + EntityItem* entityB = static_cast(b)->getEntity(); + if (!entityB->getSimulatorID().isNull() && entityB->getSimulatorID() != myNodeID) { qDebug() << "CLAIMING B"; entityB->setSimulatorID(NULL); } } if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) { - ObjectMotionState* A = static_cast(a); - EntityItem* entityA = static_cast(A)->getEntity(); - if (entityA->getSimulatorID() != myNodeID) { + EntityItem* entityA = static_cast(a)->getEntity(); + if (!entityA->getSimulatorID().isNull() && entityA->getSimulatorID() != myNodeID) { qDebug() << "CLAIMING A"; entityA->setSimulatorID(NULL); } From 08d300afcd6d80e6ac2cdfdb8653e707d2ce6173 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 11:49:10 -0700 Subject: [PATCH 53/60] use a flag to indicate that simulation ownership should be grabbed --- libraries/entities/src/EntityItem.cpp | 1 + libraries/entities/src/EntityItem.h | 3 +++ libraries/entities/src/EntityTree.cpp | 2 ++ libraries/physics/src/EntityMotionState.cpp | 11 ++++++++++- libraries/physics/src/PhysicsEngine.cpp | 11 +++++------ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index b771279efa..512687d224 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -76,6 +76,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) { _changedOnServer = 0; _element = NULL; _simulatorIDChangedTime = 0; + _shouldClaimSimulationOwnership = false; initFromEntityItemID(entityItemID); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 96186b4c91..3a6a00d2ba 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -259,6 +259,8 @@ public: QUuid getSimulatorID() const { return _simulatorID; } void setSimulatorID(const QUuid& value); quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; } + void setShouldClaimSimulationOwnership(bool value) { _shouldClaimSimulationOwnership = value; } + bool getShouldClaimSimulationOwnership() { return _shouldClaimSimulationOwnership; } const QString& getMarketplaceID() const { return _marketplaceID; } void setMarketplaceID(const QString& value) { _marketplaceID = value; } @@ -355,6 +357,7 @@ protected: QString _userData; QUuid _simulatorID; // id of Node which is currently responsible for simulating this Entity quint64 _simulatorIDChangedTime; // when was _simulatorID last updated? + bool _shouldClaimSimulationOwnership; QString _marketplaceID; // NOTE: Damping is applied like this: v *= pow(1 - damping, dt) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 7c2f41ed2c..85caccbf34 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -147,6 +147,8 @@ bool EntityTree::updateEntityWithElement(EntityItem* entity, const EntityItemPro properties.setPositionChanged(false); properties.setVelocityChanged(false); properties.setAccelerationChanged(false); + } else { + qCDebug(entities) << "allowing simulatorID change"; } } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 37472695c6..74a3d3220c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -191,6 +191,10 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationFrame) { return false; } + if (_entity->getShouldClaimSimulationOwnership()) { + return true; + } + auto nodeList = DependencyManager::get(); const QUuid& myNodeID = nodeList->getSessionUUID(); const QUuid& simulatorID = _entity->getSimulatorID(); @@ -262,7 +266,12 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ QUuid myNodeID = nodeList->getSessionUUID(); QUuid simulatorID = _entity->getSimulatorID(); - if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) { + if (_entity->getShouldClaimSimulationOwnership()) { + _entity->setSimulatorID(myNodeID); + properties.setSimulatorID(myNodeID); + _entity->setShouldClaimSimulationOwnership(false); + } + else if (simulatorID.isNull() && !(zeroSpeed && zeroSpin)) { // The object is moving and nobody thinks they own the motion. set this Node as the simulator _entity->setSimulatorID(myNodeID); properties.setSimulatorID(myNodeID); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 88b3a1362c..c3ed870375 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -397,20 +397,19 @@ void PhysicsEngine::computeCollisionEvents() { _contactMap[ContactKey(a, b)].update(_numContactFrames, contactManifold->getContactPoint(0), _originOffset); // if our character capsule is colliding with something dynamic, claim simulation ownership. - // do this by setting the entity's simulator-id to NULL, thereby causing EntityMotionState::sendUpdate - // to set ownership to us. + // see EntityMotionState::sendUpdate if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) { EntityItem* entityB = static_cast(b)->getEntity(); - if (!entityB->getSimulatorID().isNull() && entityB->getSimulatorID() != myNodeID) { + if (entityB->getSimulatorID() != myNodeID && !entityB->getShouldClaimSimulationOwnership()) { qDebug() << "CLAIMING B"; - entityB->setSimulatorID(NULL); + entityB->setShouldClaimSimulationOwnership(true); } } if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) { EntityItem* entityA = static_cast(a)->getEntity(); - if (!entityA->getSimulatorID().isNull() && entityA->getSimulatorID() != myNodeID) { + if (entityA->getSimulatorID() != myNodeID && !entityA->getShouldClaimSimulationOwnership()) { qDebug() << "CLAIMING A"; - entityA->setSimulatorID(NULL); + entityA->setShouldClaimSimulationOwnership(true); } } } From 56b005a872ea5ac2c0a0cbbc6b2711ff09092bda Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 12:19:36 -0700 Subject: [PATCH 54/60] packets should be ignore if they contain local nodeID, not if local entity contains nodeID --- libraries/entities/src/EntityTreeElement.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index a94891ea7e..60b6c93483 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -745,7 +745,8 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); // this Node was the original source of this packet, so read it, but ignore it. - bool shouldIgnore = (entityItem && entityItem->getSimulatorID() == myNodeID); + // bool shouldIgnore = (entityItem && entityItem->getSimulatorID() == myNodeID); XXX + bool shouldIgnore = false; bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args, shouldIgnore); if (entityItem->getDirtyFlags()) { From d6c8bd94cfbc15b63ca6ef3f05b09403e200a5f0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 15:59:33 -0700 Subject: [PATCH 55/60] clean up some debugging prints --- libraries/entities/src/EntityTreeElement.cpp | 1 + libraries/physics/src/EntityMotionState.cpp | 6 +++--- libraries/physics/src/PhysicsEngine.cpp | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 60b6c93483..9de7329594 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -745,6 +745,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); // this Node was the original source of this packet, so read it, but ignore it. + /// XXX what should be done here? Do we need to ignore packets which show us as simulator owner? XXX // bool shouldIgnore = (entityItem && entityItem->getSimulatorID() == myNodeID); XXX bool shouldIgnore = false; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 74a3d3220c..e188bad613 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -217,7 +217,9 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ if (glm::length(_measuredAcceleration) < MEASURED_ACCELERATION_CLOSE_TO_ZERO) { _entity->setAcceleration(glm::vec3(0)); } else { - _entity->setAcceleration(_entity->getGravity()); + // _entity->setAcceleration(_entity->getGravity()); + // XXX + _entity->setAcceleration(glm::vec3(0)); } if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { @@ -314,8 +316,6 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ qCDebug(physics) << "EntityMotionState::sendUpdate()... calling queueEditEntityMessage()..."; #endif - qCDebug(physics) << "EntityMotionState::sendUpdate()"; - entityPacketSender->queueEditEntityMessage(PacketTypeEntityAddOrEdit, id, properties); } else { #ifdef WANT_DEBUG diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index c3ed870375..a55da0fa8c 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -401,14 +401,12 @@ void PhysicsEngine::computeCollisionEvents() { if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) { EntityItem* entityB = static_cast(b)->getEntity(); if (entityB->getSimulatorID() != myNodeID && !entityB->getShouldClaimSimulationOwnership()) { - qDebug() << "CLAIMING B"; entityB->setShouldClaimSimulationOwnership(true); } } if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) { EntityItem* entityA = static_cast(a)->getEntity(); if (entityA->getSimulatorID() != myNodeID && !entityA->getShouldClaimSimulationOwnership()) { - qDebug() << "CLAIMING A"; entityA->setShouldClaimSimulationOwnership(true); } } From 23f1767634cf0c7a7fc5444ab3933c5ede22d58b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 16:13:28 -0700 Subject: [PATCH 56/60] cleanup --- libraries/physics/src/PhysicsEngine.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index a55da0fa8c..fbfb7914f0 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -371,8 +371,6 @@ void PhysicsEngine::computeCollisionEvents() { const btCollisionObject* characterCollisionObject = _characterController ? _characterController->getCollisionObject() : NULL; - auto nodeList = DependencyManager::get(); - const QUuid& myNodeID = nodeList->getSessionUUID(); // update all contacts every frame int numManifolds = _collisionDispatcher->getNumManifolds(); @@ -400,15 +398,11 @@ void PhysicsEngine::computeCollisionEvents() { // see EntityMotionState::sendUpdate if (objectA == characterCollisionObject && !objectB->isStaticOrKinematicObject() && b) { EntityItem* entityB = static_cast(b)->getEntity(); - if (entityB->getSimulatorID() != myNodeID && !entityB->getShouldClaimSimulationOwnership()) { - entityB->setShouldClaimSimulationOwnership(true); - } + entityB->setShouldClaimSimulationOwnership(true); } if (objectB == characterCollisionObject && !objectA->isStaticOrKinematicObject() && a) { EntityItem* entityA = static_cast(a)->getEntity(); - if (entityA->getSimulatorID() != myNodeID && !entityA->getShouldClaimSimulationOwnership()) { - entityA->setShouldClaimSimulationOwnership(true); - } + entityA->setShouldClaimSimulationOwnership(true); } } } From 61076826580d31fef97ad6240dc3e3154ed0bbbf Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 16:36:56 -0700 Subject: [PATCH 57/60] handle ignoring simulation data echoed back to us differently --- libraries/entities/src/EntityItem.cpp | 27 ++++++++++++++++++-- libraries/entities/src/EntityItem.h | 3 +-- libraries/entities/src/EntityTreeElement.cpp | 11 +------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 512687d224..d221c0bba4 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -313,8 +313,7 @@ int EntityItem::expectedBytes() { } -int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, - bool ignoreServerPacket) { +int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) { @@ -325,6 +324,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef 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 saveGravity = _gravity; + glm::vec3 saveAcceleration = _acceleration; + + // Header bytes // object ID [16 bytes] // ByteCountCoded(type code) [~1 byte] @@ -398,6 +405,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef quint64 lastEditedFromBuffer = 0; quint64 lastEditedFromBufferAdjusted = 0; + bool ignoreServerPacket = false; + // TODO: we could make this encoded as a delta from _created // _lastEdited memcpy(&lastEditedFromBuffer, dataAt, sizeof(lastEditedFromBuffer)); @@ -608,6 +617,20 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef _lastSimulated = now; } } + + + auto nodeList = DependencyManager::get(); + const QUuid& myNodeID = nodeList->getSessionUUID(); + if (_simulatorID == myNodeID) { + // the packet that produced this bitstream originally came from physics simulations performed by + // this node, so our version has to be newer than what the packet contained. + _position = savePosition; + _rotation = saveRotation; + _velocity = saveVelocity; + _gravity = saveGravity; + _acceleration = saveAcceleration; + } + return bytesRead; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3a6a00d2ba..ad856698a2 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -113,8 +113,7 @@ public: static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); - virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, - bool ignoreServerPacket = false); + virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 9de7329594..349bd51372 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -716,10 +716,6 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesRead += sizeof(numberOfEntities); if (bytesLeftToRead >= (int)(numberOfEntities * expectedBytesPerEntity)) { - // look up the Id of this Node - auto nodeList = DependencyManager::get(); - QUuid myNodeID = nodeList->getSessionUUID(); - for (uint16_t i = 0; i < numberOfEntities; i++) { int bytesForThisEntity = 0; EntityItemID entityItemID; @@ -744,12 +740,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bool bestFitBefore = bestFitEntityBounds(entityItem); EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID); - // this Node was the original source of this packet, so read it, but ignore it. - /// XXX what should be done here? Do we need to ignore packets which show us as simulator owner? XXX - // bool shouldIgnore = (entityItem && entityItem->getSimulatorID() == myNodeID); XXX - bool shouldIgnore = false; - - bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args, shouldIgnore); + bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args); if (entityItem->getDirtyFlags()) { _myTree->entityChanged(entityItem); } From 4a5631fca6ad359c802d9df587dfd92f63a680f6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 16:51:28 -0700 Subject: [PATCH 58/60] cleanups, diff minimization --- libraries/entities/src/EntityItem.cpp | 4 ++-- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++-- libraries/physics/src/EntityMotionState.cpp | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d221c0bba4..4875069aae 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -405,8 +405,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef quint64 lastEditedFromBuffer = 0; quint64 lastEditedFromBufferAdjusted = 0; - bool ignoreServerPacket = false; - // TODO: we could make this encoded as a delta from _created // _lastEdited memcpy(&lastEditedFromBuffer, dataAt, sizeof(lastEditedFromBuffer)); @@ -432,6 +430,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qCDebug(entities) << " fromSameServerEdit:" << fromSameServerEdit; #endif + bool ignoreServerPacket = false; + // 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) { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 6bd988ec90..53335beda0 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -65,6 +65,7 @@ void setSimId(EntityItemProperties& propertiesWithSimID, EntityItem* entity) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); + // if this entity has non-zero physics/simulation related values, claim simulation ownership if (propertiesWithSimID.velocityChanged() || propertiesWithSimID.rotationChanged() || propertiesWithSimID.containsPositionChange()) { @@ -83,7 +84,6 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro // The application will keep track of creatorTokenID uint32_t creatorTokenID = EntityItemID::getNextCreatorTokenID(); - // This Node is creating a new object. If it's in motion, set this Node as the simulator. EntityItemProperties propertiesWithSimID = properties; EntityItemID id(NEW_ENTITY, creatorTokenID, false ); @@ -92,6 +92,7 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro if (_entityTree) { _entityTree->lockForWrite(); EntityItem* entity = _entityTree->addEntity(id, propertiesWithSimID); + // This Node is creating a new object. If it's in motion, set this Node as the simulator. setSimId(propertiesWithSimID, entity); _entityTree->unlock(); } @@ -160,7 +161,6 @@ EntityItemID EntityScriptingInterface::editEntity(EntityItemID entityID, const E } } - // if this Node is changing a physics-related property, claim simulation ownership. EntityItemProperties propertiesWithSimID = properties; // If we have a local entity tree set, then also update it. We can do this even if we don't know diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index e188bad613..e689ac21bc 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -217,9 +217,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ if (glm::length(_measuredAcceleration) < MEASURED_ACCELERATION_CLOSE_TO_ZERO) { _entity->setAcceleration(glm::vec3(0)); } else { - // _entity->setAcceleration(_entity->getGravity()); - // XXX - _entity->setAcceleration(glm::vec3(0)); + _entity->setAcceleration(_entity->getGravity()); } if (_outgoingPacketFlags & EntityItem::DIRTY_POSITION) { From c49e2c1804d5627d20c83e9bd752c92d7ba0b8b3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 20 Apr 2015 16:52:29 -0700 Subject: [PATCH 59/60] cleanups, diff minimization --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4875069aae..12fb1ba99d 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -430,7 +430,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef qCDebug(entities) << " fromSameServerEdit:" << fromSameServerEdit; #endif - bool ignoreServerPacket = false; + 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. From cde64893afbdf95ea60d12b7b4c088f259d908fe Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 21 Apr 2015 18:36:06 -0700 Subject: [PATCH 60/60] coding standard --- libraries/entities/src/EntityTree.cpp | 2 +- libraries/physics/src/EntityMotionState.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 85caccbf34..5b15aa26b4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -25,7 +25,7 @@ #include "RecurseOctreeToMapOperator.h" -const quint64 SIMULATOR_CHANGE_LOCKOUT_PERIOD = 0.2 * USECS_PER_SECOND; +const quint64 SIMULATOR_CHANGE_LOCKOUT_PERIOD = (quint64)(0.2f * USECS_PER_SECOND); EntityTree::EntityTree(bool shouldReaverage) : diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index e689ac21bc..e5a12a2b66 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -18,7 +18,7 @@ #include "PhysicsHelpers.h" #include "PhysicsLogging.h" -static const float MEASURED_ACCELERATION_CLOSE_TO_ZERO = 0.05; +static const float MEASURED_ACCELERATION_CLOSE_TO_ZERO = 0.05f; QSet* _outgoingEntityList; @@ -215,7 +215,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ EntityItemProperties properties = _entity->getProperties(); if (glm::length(_measuredAcceleration) < MEASURED_ACCELERATION_CLOSE_TO_ZERO) { - _entity->setAcceleration(glm::vec3(0)); + _entity->setAcceleration(glm::vec3(0.0f)); } else { _entity->setAcceleration(_entity->getGravity()); }