From 164439b3037af5628b381a3526a9ef074030aa17 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 8 Dec 2015 13:53:39 -0800 Subject: [PATCH] don't enable physics until an entire scene has been received from the entity server and until nearby (to MyAvatar) entities are ready --- interface/src/Application.cpp | 36 +++++++++++++++++++++++++++++++++-- interface/src/Application.h | 2 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c0cfbda15b..4a97fd6275 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -195,6 +195,8 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html"; static const unsigned int THROTTLED_SIM_FRAMERATE = 15; static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; +static const float PHYSICS_READY_RANGE = 3.0f; // how far from avatar to check for entities that aren't ready for simulation + #ifndef __APPLE__ static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); #else @@ -2905,7 +2907,7 @@ void Application::update(float deltaTime) { _avatarUpdate->synchronousProcess(); - { + if (_physicsEnabled) { PerformanceTimer perfTimer("physics"); static VectorOfMotionStates motionStates; @@ -3893,6 +3895,31 @@ void Application::trackIncomingOctreePacket(ReceivedMessage& message, SharedNode } } +bool Application::nearbyEntitiesAreReadyForPhysics() { + // this is used to avoid the following scenario: + // A table has some items sitting on top of it. The items are at rest, meaning they aren't active in bullet. + // Someone logs in close to the table. They receive information about the items on the table before they + // receive information about the table. The items are very close to the avatar's capsule, so they become + // activated in bullet. This causes them to fall to the floor, because the table's shape isn't yet in bullet. + EntityTreePointer entityTree = _entities.getTree(); + if (!entityTree) { + return false; + } + + QVector entities; + entityTree->withReadLock([&] { + AABox box(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE)); + entityTree->findEntities(box, entities); + }); + + foreach (EntityItemPointer entity, entities) { + if (!entity->isReadyToComputeShape()) { + return false; + } + } + return true; +} + int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode) { // But, also identify the sender, and keep track of the contained jurisdiction root for this server @@ -3938,7 +3965,12 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer }); }); - + if (!_physicsEnabled && nearbyEntitiesAreReadyForPhysics()) { + // These stats packets are sent in between full sends of a scene. + // We keep physics disabled until we've recieved a full scene and everything near the avatar in that + // scene is ready to compute its collision shape. + _physicsEnabled = true; + } return statsMessageLength; } diff --git a/interface/src/Application.h b/interface/src/Application.h index ce33f051ef..27df7835e6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -395,6 +395,7 @@ private: bool importSVOFromURL(const QString& urlString); + bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); void trackIncomingOctreePacket(ReceivedMessage& message, SharedNodePointer sendingNode, bool wasStatsPacket); @@ -564,6 +565,7 @@ private: bool _isForeground = true; // starts out assumed to be in foreground bool _inPaint = false; bool _isGLInitialized { false }; + bool _physicsEnabled { false }; }; #endif // hifi_Application_h