diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f4496424ee..30a248e64d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2386,6 +2386,7 @@ void Application::update(float deltaTime) { if (_physicsEngine.hasOutgoingChanges()) { _entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges()); + _entitySimulation.handleCollisionEvents(_physicsEngine.getCollisionEvents()); _physicsEngine.dumpStatsIfNecessary(); } } diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index d8ed858b83..0f76613cb3 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -11,7 +11,6 @@ #include "EntityMotionState.h" #include "PhysicalEntitySimulation.h" -#include "PhysicsEngine.h" #include "PhysicsHelpers.h" #include "PhysicsLogging.h" #include "ShapeInfoUtil.h" @@ -189,6 +188,7 @@ void PhysicalEntitySimulation::handleOutgoingChanges(VectorOfMotionStates& motio } } -void PhysicalEntitySimulation::bump(EntityItem* bumpEntity) { +void PhysicalEntitySimulation::handleCollisionEvents(CollisionEvents& collisionEvents) { + // BOOKMARK TODO: emit events } diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 1b2689a020..b7c091df82 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -20,10 +20,10 @@ #include #include +#include "PhysicsEngine.h" #include "PhysicsTypedefs.h" class EntityMotionState; -class PhysicsEngine; class ShapeManager; class PhysicalEntitySimulation :public EntitySimulation { @@ -47,10 +47,9 @@ public: VectorOfMotionStates& getObjectsToChange(); void handleOutgoingChanges(VectorOfMotionStates& motionStates); + void handleCollisionEvents(CollisionEvents& collisionEvents); private: - void bump(EntityItem* bumpEntity); - // incoming changes SetOfEntities _pendingRemoves; // entities to be removed from PhysicsEngine (and their MotionState deleted) SetOfEntities _pendingAdds; // entities to be be added to PhysicsEngine (and a their MotionState created) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 92db98a03f..2ff2347f86 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -237,12 +237,13 @@ void PhysicsEngine::stepSimulation() { if (_characterController) { _characterController->postSimulation(); } - computeCollisionEvents(); + updateContactMap(); _hasOutgoingChanges = true; } } void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) { + // BOOKMARK TODO: move this to PhysicalEntitySimulation BT_PROFILE("ownershipInfection"); if (_sessionID.isNull()) { return; @@ -263,8 +264,9 @@ void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const } } -void PhysicsEngine::computeCollisionEvents() { - BT_PROFILE("computeCollisionEvents"); +void PhysicsEngine::updateContactMap() { + BT_PROFILE("updateContactMap"); + ++_numContactFrames; // update all contacts every frame int numManifolds = _collisionDispatcher->getNumManifolds(); @@ -292,39 +294,31 @@ void PhysicsEngine::computeCollisionEvents() { doOwnershipInfection(objectA, objectB); } } - - fireCollisionEvents(); - ++_numContactFrames; } -void PhysicsEngine::fireCollisionEvents() { - /* TODO: Andrew to make this work for ObjectMotionStates +CollisionEvents& PhysicsEngine::getCollisionEvents() { const uint32_t CONTINUE_EVENT_FILTER_FREQUENCY = 10; + _collisionEvents.clear(); // scan known contacts and trigger events ContactMap::iterator contactItr = _contactMap.begin(); while (contactItr != _contactMap.end()) { - ObjectMotionState* A = static_cast(contactItr->first._a); - ObjectMotionState* B = static_cast(contactItr->first._b); - - // TODO: make triggering these events clean and efficient. The code at this context shouldn't - // have to figure out what kind of object (entity, avatar, etc) these are in order to properly - // emit a collision event. - // TODO: enable scripts to filter based on contact event type ContactEventType type = contactItr->second.computeType(_numContactFrames); - if(type != CONTACT_EVENT_TYPE_CONTINUE || _numSubsteps % CONTINUE_EVENT_FILTER_FREQUENCY == 0){ + if(type != CONTACT_EVENT_TYPE_CONTINUE || _numSubsteps % CONTINUE_EVENT_FILTER_FREQUENCY == 0) { + ObjectMotionState* A = static_cast(contactItr->first._a); + ObjectMotionState* B = static_cast(contactItr->first._b); + if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) { - EntityItemID idA = static_cast(A)->getEntity()->getEntityItemID(); - EntityItemID idB; + QUuid idA = A->getObjectID(); + QUuid idB; if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) { - idB = static_cast(B)->getEntity()->getEntityItemID(); + idB = B->getObjectID(); } - emit entityCollisionWithEntity(idA, idB, contactItr->second); + _collisionEvents.push_back(CollisionEvent(type, idA, idB)); } else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) { - EntityItemID idA; - EntityItemID idB = static_cast(B)->getEntity()->getEntityItemID(); - emit entityCollisionWithEntity(idA, idB, contactItr->second); + QUuid idB = B->getObjectID(); + _collisionEvents.push_back(CollisionEvent(type, idB, QUuid())); } } @@ -336,7 +330,7 @@ void PhysicsEngine::fireCollisionEvents() { ++contactItr; } } - */ + return _collisionEvents; } VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() { diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index c470bc0331..91b871f49c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -41,7 +41,21 @@ public: }; typedef std::map ContactMap; -typedef std::pair ContactMapElement; + +class CollisionEvent { +public: + CollisionEvent() : _type(CONTACT_EVENT_TYPE_START), _idA(), _idB() {} + CollisionEvent(ContactEventType type, const QUuid& idA, const QUuid& idB) : _type(type), _idA(idA), _idB(idB) {} + + ContactEventType _type; // START, CONTINUE, or END + QUuid _idA; + QUuid _idB; + // TODO: add is info to contact callback + //glm::vec3 _position; // world-frame + //glm::vec3 _normal; // world-frame +}; + +typedef QVector CollisionEvents; class PhysicsEngine { public: @@ -64,11 +78,17 @@ public: void reinsertObject(ObjectMotionState* object); void stepSimulation(); - void computeCollisionEvents(); - void fireCollisionEvents(); + void updateContactMap(); bool hasOutgoingChanges() const { return _hasOutgoingChanges; } + + /// \return reference to list of changed MotionStates. The list is only valid until beginning of next simulation loop. VectorOfMotionStates& getOutgoingChanges(); + + /// \return reference to list of CollisionEvent's. The list is only valid until beginning of next simulation loop. + CollisionEvents& getCollisionEvents(); + + /// \brief prints timings for last frame if stats have been requested. void dumpStatsIfNecessary(); /// \param offset position of simulation origin in domain-frame @@ -77,6 +97,7 @@ public: /// \return position of simulation origin in domain-frame const glm::vec3& getOriginOffset() const { return _originOffset; } + /// \brief call bump on any objects that touch the object corresponding to motionState void bump(ObjectMotionState* motionState); void removeRigidBody(btRigidBody* body); @@ -111,6 +132,7 @@ private: bool _hasOutgoingChanges = false; QUuid _sessionID; + CollisionEvents _collisionEvents; }; #endif // hifi_PhysicsEngine_h