From 6db0442fda75b899566619b4dfe467301021948d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 21 Aug 2015 10:48:26 -0700 Subject: [PATCH] allow for asynchronous building of collision shape --- interface/src/Application.cpp | 3 ++- interface/src/avatar/AvatarMotionState.cpp | 9 +++++-- interface/src/avatar/AvatarMotionState.h | 4 ++- libraries/physics/src/EntityMotionState.cpp | 27 +++++++++++++++---- libraries/physics/src/EntityMotionState.h | 8 +++--- libraries/physics/src/ObjectMotionState.cpp | 13 ++++++--- libraries/physics/src/ObjectMotionState.h | 8 +++--- .../physics/src/PhysicalEntitySimulation.cpp | 6 +++++ .../physics/src/PhysicalEntitySimulation.h | 1 + libraries/physics/src/PhysicsEngine.cpp | 18 +++++++++---- libraries/physics/src/PhysicsEngine.h | 2 +- 11 files changed, 75 insertions(+), 24 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5f8b17f178..0b794deb2b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2804,7 +2804,8 @@ void Application::update(float deltaTime) { _entities.getTree()->lockForWrite(); _entitySimulation.lock(); - _physicsEngine.changeObjects(_entitySimulation.getObjectsToChange()); + VectorOfMotionStates stillNeedChange = _physicsEngine.changeObjects(_entitySimulation.getObjectsToChange()); + _entitySimulation.setObjectsToChange(stillNeedChange); _entitySimulation.unlock(); _entities.getTree()->unlock(); diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index b106ee6398..cabe545f5a 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -28,15 +28,20 @@ AvatarMotionState::~AvatarMotionState() { } // virtual -uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() { +uint32_t AvatarMotionState::getIncomingDirtyFlags() { uint32_t dirtyFlags = 0; if (_body && _avatar) { dirtyFlags = _dirtyFlags; - _dirtyFlags = 0; } return dirtyFlags; } +void AvatarMotionState::clearIncomingDirtyFlags() { + if (_body && _avatar) { + _dirtyFlags = 0; + } +} + MotionType AvatarMotionState::computeObjectMotionType() const { // TODO?: support non-DYNAMIC motion for avatars? (e.g. when sitting) return MOTION_TYPE_DYNAMIC; diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index ac813e764c..1c49705f23 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -25,7 +25,8 @@ public: virtual MotionType getMotionType() const { return _motionType; } - virtual uint32_t getAndClearIncomingDirtyFlags(); + virtual uint32_t getIncomingDirtyFlags(); + virtual void clearIncomingDirtyFlags(); virtual MotionType computeObjectMotionType() const; @@ -65,6 +66,7 @@ public: friend class AvatarManager; protected: + virtual bool isReadyToComputeShape() { return true; } virtual btCollisionShape* computeNewShape(); virtual void clearObjectBackPointer(); Avatar* _avatar; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 4e6eb8353c..dc3c0ea4e8 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -99,7 +99,7 @@ void EntityMotionState::updateServerPhysicsVariables() { } // virtual -void EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) { +bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) { assert(entityTreeIsLocked()); updateServerPhysicsVariables(); ObjectMotionState::handleEasyChanges(flags, engine); @@ -131,13 +131,15 @@ void EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) if ((flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) { _body->activate(); } + + return true; } // virtual -void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { +bool EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { updateServerPhysicsVariables(); - ObjectMotionState::handleHardAndEasyChanges(flags, engine); + return ObjectMotionState::handleHardAndEasyChanges(flags, engine); } void EntityMotionState::clearObjectBackPointer() { @@ -222,6 +224,15 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { #endif } + +// virtual and protected +bool EntityMotionState::isReadyToComputeShape() { + if (_entity) { + return _entity->isReadyToComputeShape(); + } + return false; +} + // virtual and protected btCollisionShape* EntityMotionState::computeNewShape() { if (_entity) { @@ -493,12 +504,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q _lastStep = step; } -uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() { +uint32_t EntityMotionState::getIncomingDirtyFlags() { assert(entityTreeIsLocked()); uint32_t dirtyFlags = 0; if (_body && _entity) { dirtyFlags = _entity->getDirtyFlags(); - _entity->clearDirtyFlags(); // we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings int bodyFlags = _body->getCollisionFlags(); bool isMoving = _entity->isMoving(); @@ -510,6 +520,13 @@ uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() { return dirtyFlags; } +void EntityMotionState::clearIncomingDirtyFlags() { + assert(entityTreeIsLocked()); + if (_body && _entity) { + _entity->clearDirtyFlags(); + } +} + // virtual quint8 EntityMotionState::getSimulationPriority() const { if (_entity) { diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 009c931dba..f3a2e80070 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -29,8 +29,8 @@ public: virtual ~EntityMotionState(); void updateServerPhysicsVariables(); - virtual void handleEasyChanges(uint32_t flags, PhysicsEngine* engine); - virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); + virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine); + virtual bool handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); /// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem virtual MotionType computeObjectMotionType() const; @@ -48,7 +48,8 @@ public: bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID); void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step); - virtual uint32_t getAndClearIncomingDirtyFlags(); + virtual uint32_t getIncomingDirtyFlags(); + virtual void clearIncomingDirtyFlags(); void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; } void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; } @@ -91,6 +92,7 @@ protected: bool entityTreeIsLocked() const; #endif + virtual bool isReadyToComputeShape(); virtual btCollisionShape* computeNewShape(); virtual void clearObjectBackPointer(); virtual void setMotionType(MotionType motionType); diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index aeec85f7ea..85bddd0495 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -125,7 +125,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) { } } -void ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) { +bool ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) { if (flags & EntityItem::DIRTY_POSITION) { btTransform worldTrans; if (flags & EntityItem::DIRTY_ROTATION) { @@ -156,11 +156,16 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) if (flags & EntityItem::DIRTY_MASS) { updateBodyMassProperties(); } + + return true; } -void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { +bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { if (flags & EntityItem::DIRTY_SHAPE) { // make sure the new shape is valid + if (!isReadyToComputeShape()) { + return false; + } btCollisionShape* newShape = computeNewShape(); if (!newShape) { qCDebug(physics) << "Warning: failed to generate new shape!"; @@ -172,7 +177,7 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* if (flags & EASY_DIRTY_PHYSICS_FLAGS) { handleEasyChanges(flags, engine); } - return; + return true; } } getShapeManager()->releaseShape(_shape); @@ -192,6 +197,8 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* if (flags & HARD_DIRTY_PHYSICS_FLAGS) { engine->reinsertObject(this); } + + return true; } void ObjectMotionState::updateBodyMaterialProperties() { diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 30394ef5fc..1bdf8b6372 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -71,8 +71,8 @@ public: ObjectMotionState(btCollisionShape* shape); ~ObjectMotionState(); - virtual void handleEasyChanges(uint32_t flags, PhysicsEngine* engine); - virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); + virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine); + virtual bool handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); void updateBodyMaterialProperties(); void updateBodyVelocities(); @@ -92,7 +92,8 @@ public: glm::vec3 getBodyAngularVelocity() const; virtual glm::vec3 getObjectLinearVelocityChange() const; - virtual uint32_t getAndClearIncomingDirtyFlags() = 0; + virtual uint32_t getIncomingDirtyFlags() = 0; + virtual void clearIncomingDirtyFlags() = 0; virtual MotionType computeObjectMotionType() const = 0; @@ -132,6 +133,7 @@ public: friend class PhysicsEngine; protected: + virtual bool isReadyToComputeShape() = 0; virtual btCollisionShape* computeNewShape() = 0; void setMotionType(MotionType motionType); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index f6f02b8573..97cf6a549a 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -173,6 +173,12 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() { return _tempVector; } +void PhysicalEntitySimulation::setObjectsToChange(VectorOfMotionStates& objectsToChange) { + for (auto object : objectsToChange) { + _pendingChanges.insert(static_cast(object)); + } +} + VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() { _tempVector.clear(); for (auto stateItr : _pendingChanges) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 9c439c53b2..dc65128ac5 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -46,6 +46,7 @@ protected: // only called by EntitySimulation public: VectorOfMotionStates& getObjectsToDelete(); VectorOfMotionStates& getObjectsToAdd(); + void setObjectsToChange(VectorOfMotionStates& objectsToChange); VectorOfMotionStates& getObjectsToChange(); void handleOutgoingChanges(VectorOfMotionStates& motionStates, const QUuid& sessionID); diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 022468633f..e8e6f68c6b 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -140,7 +140,7 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { int16_t group = motionState->computeCollisionGroup(); _dynamicsWorld->addRigidBody(body, group, getCollisionMask(group)); - motionState->getAndClearIncomingDirtyFlags(); + motionState->clearIncomingDirtyFlags(); } void PhysicsEngine::removeObject(ObjectMotionState* object) { @@ -188,15 +188,23 @@ void PhysicsEngine::addObjects(VectorOfMotionStates& objects) { } } -void PhysicsEngine::changeObjects(VectorOfMotionStates& objects) { +VectorOfMotionStates PhysicsEngine::changeObjects(VectorOfMotionStates& objects) { + VectorOfMotionStates stillNeedChange; for (auto object : objects) { - uint32_t flags = object->getAndClearIncomingDirtyFlags() & DIRTY_PHYSICS_FLAGS; + uint32_t flags = object->getIncomingDirtyFlags() & DIRTY_PHYSICS_FLAGS; if (flags & HARD_DIRTY_PHYSICS_FLAGS) { - object->handleHardAndEasyChanges(flags, this); + if (object->handleHardAndEasyChanges(flags, this)) { + object->clearIncomingDirtyFlags(); + stillNeedChange.push_back(object); + } } else if (flags & EASY_DIRTY_PHYSICS_FLAGS) { - object->handleEasyChanges(flags, this); + if (object->handleEasyChanges(flags, this)) { + object->clearIncomingDirtyFlags(); + stillNeedChange.push_back(object); + } } } + return stillNeedChange; } void PhysicsEngine::reinsertObject(ObjectMotionState* object) { diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index a974a02e51..67b38323cc 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -60,7 +60,7 @@ public: void deleteObjects(VectorOfMotionStates& objects); void deleteObjects(SetOfMotionStates& objects); // only called during teardown void addObjects(VectorOfMotionStates& objects); - void changeObjects(VectorOfMotionStates& objects); + VectorOfMotionStates changeObjects(VectorOfMotionStates& objects); void reinsertObject(ObjectMotionState* object); void stepSimulation();