remake foundation for CollisionEvents

This commit is contained in:
Andrew Meadows 2015-05-03 09:27:15 -07:00
parent cb37b884d2
commit fef84730bf
5 changed files with 48 additions and 32 deletions

View file

@ -2386,6 +2386,7 @@ void Application::update(float deltaTime) {
if (_physicsEngine.hasOutgoingChanges()) { if (_physicsEngine.hasOutgoingChanges()) {
_entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges()); _entitySimulation.handleOutgoingChanges(_physicsEngine.getOutgoingChanges());
_entitySimulation.handleCollisionEvents(_physicsEngine.getCollisionEvents());
_physicsEngine.dumpStatsIfNecessary(); _physicsEngine.dumpStatsIfNecessary();
} }
} }

View file

@ -11,7 +11,6 @@
#include "EntityMotionState.h" #include "EntityMotionState.h"
#include "PhysicalEntitySimulation.h" #include "PhysicalEntitySimulation.h"
#include "PhysicsEngine.h"
#include "PhysicsHelpers.h" #include "PhysicsHelpers.h"
#include "PhysicsLogging.h" #include "PhysicsLogging.h"
#include "ShapeInfoUtil.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
} }

View file

@ -20,10 +20,10 @@
#include <EntityItem.h> #include <EntityItem.h>
#include <EntitySimulation.h> #include <EntitySimulation.h>
#include "PhysicsEngine.h"
#include "PhysicsTypedefs.h" #include "PhysicsTypedefs.h"
class EntityMotionState; class EntityMotionState;
class PhysicsEngine;
class ShapeManager; class ShapeManager;
class PhysicalEntitySimulation :public EntitySimulation { class PhysicalEntitySimulation :public EntitySimulation {
@ -47,10 +47,9 @@ public:
VectorOfMotionStates& getObjectsToChange(); VectorOfMotionStates& getObjectsToChange();
void handleOutgoingChanges(VectorOfMotionStates& motionStates); void handleOutgoingChanges(VectorOfMotionStates& motionStates);
void handleCollisionEvents(CollisionEvents& collisionEvents);
private: private:
void bump(EntityItem* bumpEntity);
// incoming changes // incoming changes
SetOfEntities _pendingRemoves; // entities to be removed from PhysicsEngine (and their MotionState deleted) 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) SetOfEntities _pendingAdds; // entities to be be added to PhysicsEngine (and a their MotionState created)

View file

@ -237,12 +237,13 @@ void PhysicsEngine::stepSimulation() {
if (_characterController) { if (_characterController) {
_characterController->postSimulation(); _characterController->postSimulation();
} }
computeCollisionEvents(); updateContactMap();
_hasOutgoingChanges = true; _hasOutgoingChanges = true;
} }
} }
void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) { void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) {
// BOOKMARK TODO: move this to PhysicalEntitySimulation
BT_PROFILE("ownershipInfection"); BT_PROFILE("ownershipInfection");
if (_sessionID.isNull()) { if (_sessionID.isNull()) {
return; return;
@ -263,8 +264,9 @@ void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const
} }
} }
void PhysicsEngine::computeCollisionEvents() { void PhysicsEngine::updateContactMap() {
BT_PROFILE("computeCollisionEvents"); BT_PROFILE("updateContactMap");
++_numContactFrames;
// update all contacts every frame // update all contacts every frame
int numManifolds = _collisionDispatcher->getNumManifolds(); int numManifolds = _collisionDispatcher->getNumManifolds();
@ -292,39 +294,31 @@ void PhysicsEngine::computeCollisionEvents() {
doOwnershipInfection(objectA, objectB); doOwnershipInfection(objectA, objectB);
} }
} }
fireCollisionEvents();
++_numContactFrames;
} }
void PhysicsEngine::fireCollisionEvents() { CollisionEvents& PhysicsEngine::getCollisionEvents() {
/* TODO: Andrew to make this work for ObjectMotionStates
const uint32_t CONTINUE_EVENT_FILTER_FREQUENCY = 10; const uint32_t CONTINUE_EVENT_FILTER_FREQUENCY = 10;
_collisionEvents.clear();
// scan known contacts and trigger events // scan known contacts and trigger events
ContactMap::iterator contactItr = _contactMap.begin(); ContactMap::iterator contactItr = _contactMap.begin();
while (contactItr != _contactMap.end()) { while (contactItr != _contactMap.end()) {
ObjectMotionState* A = static_cast<ObjectMotionState*>(contactItr->first._a);
ObjectMotionState* B = static_cast<ObjectMotionState*>(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); 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<ObjectMotionState*>(contactItr->first._a);
ObjectMotionState* B = static_cast<ObjectMotionState*>(contactItr->first._b);
if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) { if (A && A->getType() == MOTION_STATE_TYPE_ENTITY) {
EntityItemID idA = static_cast<EntityMotionState*>(A)->getEntity()->getEntityItemID(); QUuid idA = A->getObjectID();
EntityItemID idB; QUuid idB;
if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) { if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
idB = static_cast<EntityMotionState*>(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) { } else if (B && B->getType() == MOTION_STATE_TYPE_ENTITY) {
EntityItemID idA; QUuid idB = B->getObjectID();
EntityItemID idB = static_cast<EntityMotionState*>(B)->getEntity()->getEntityItemID(); _collisionEvents.push_back(CollisionEvent(type, idB, QUuid()));
emit entityCollisionWithEntity(idA, idB, contactItr->second);
} }
} }
@ -336,7 +330,7 @@ void PhysicsEngine::fireCollisionEvents() {
++contactItr; ++contactItr;
} }
} }
*/ return _collisionEvents;
} }
VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() { VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() {

View file

@ -41,7 +41,21 @@ public:
}; };
typedef std::map<ContactKey, ContactInfo> ContactMap; typedef std::map<ContactKey, ContactInfo> ContactMap;
typedef std::pair<ContactKey, ContactInfo> 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<CollisionEvent> CollisionEvents;
class PhysicsEngine { class PhysicsEngine {
public: public:
@ -64,11 +78,17 @@ public:
void reinsertObject(ObjectMotionState* object); void reinsertObject(ObjectMotionState* object);
void stepSimulation(); void stepSimulation();
void computeCollisionEvents(); void updateContactMap();
void fireCollisionEvents();
bool hasOutgoingChanges() const { return _hasOutgoingChanges; } 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(); 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(); void dumpStatsIfNecessary();
/// \param offset position of simulation origin in domain-frame /// \param offset position of simulation origin in domain-frame
@ -77,6 +97,7 @@ public:
/// \return position of simulation origin in domain-frame /// \return position of simulation origin in domain-frame
const glm::vec3& getOriginOffset() const { return _originOffset; } 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 bump(ObjectMotionState* motionState);
void removeRigidBody(btRigidBody* body); void removeRigidBody(btRigidBody* body);
@ -111,6 +132,7 @@ private:
bool _hasOutgoingChanges = false; bool _hasOutgoingChanges = false;
QUuid _sessionID; QUuid _sessionID;
CollisionEvents _collisionEvents;
}; };
#endif // hifi_PhysicsEngine_h #endif // hifi_PhysicsEngine_h