mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 07:57:30 +02:00
cleanup how MotionStates are deleted from physics
also fixed some compile errors removed cruft
This commit is contained in:
parent
9f8b266a03
commit
4cb469dd79
8 changed files with 127 additions and 114 deletions
|
@ -2355,7 +2355,7 @@ void Application::update(float deltaTime) {
|
|||
PerformanceTimer perfTimer("physics");
|
||||
_myAvatar->relayDriveKeysToCharacterController();
|
||||
|
||||
_physicsEngine.removeObjects(_entitySimulation.getObjectsToRemove());
|
||||
_physicsEngine.deleteObjects(_entitySimulation.getObjectsToRemove());
|
||||
_physicsEngine.addObjects(_entitySimulation.getObjectsToAdd());
|
||||
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
virtual void setWorldTransform(const btTransform& worldTrans);
|
||||
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
|
||||
virtual float computeObjectMass(const ShapeInfo& shapeInfo) const;
|
||||
|
||||
bool doesNotNeedToSendUpdate() const;
|
||||
bool remoteSimulationOutOfSync(uint32_t simulationStep);
|
||||
|
|
|
@ -115,15 +115,15 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags) {
|
|||
if (flags & EntityItem::DIRTY_POSITION) {
|
||||
btTransform worldTrans;
|
||||
if (flags & EntityItem::DIRTY_ROTATION) {
|
||||
worldTrans = getObjectTransform();
|
||||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
} else {
|
||||
worldTrans = _body->getWorldTransform();
|
||||
worldTrans.setOrigin(getObjectPosition());
|
||||
}
|
||||
worldTrans.setOrigin(glmToBullet(getObjectPosition()));
|
||||
_body->setWorldTransform(worldTrans);
|
||||
} else {
|
||||
btTransform worldTrans = _body->getWorldTransform();
|
||||
worldTrans.setRotation(getObjectRotation());
|
||||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
_body->setWorldTransform(worldTrans);
|
||||
}
|
||||
|
||||
|
@ -155,14 +155,13 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
if (flags & EntityItem::DIRTY_SHAPE) {
|
||||
// make sure the new shape is valid
|
||||
ShapeInfo shapeInfo;
|
||||
motionState->computeObjectShapeInfo(shapeInfo);
|
||||
computeObjectShapeInfo(shapeInfo);
|
||||
btCollisionShape* newShape = getShapeManager()->getShape(shapeInfo);
|
||||
if (!newShape) {
|
||||
// failed to generate new shape!
|
||||
// remove shape-change flag
|
||||
// failed to generate new shape! --> keep old shape and remove shape-change flag
|
||||
flags &= ~EntityItem::DIRTY_SHAPE;
|
||||
// TODO: force this object out of PhysicsEngine rather than just use the old shape
|
||||
if (flags & HARD_DIRTY_PHYSICS_FLAGS == 0) {
|
||||
if ((flags & HARD_DIRTY_PHYSICS_FLAGS) == 0) {
|
||||
// no HARD flags remain, so do any EASY changes
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
|
@ -170,21 +169,18 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
|
|||
return;
|
||||
}
|
||||
}
|
||||
engine->removeRigidBody(_body);
|
||||
getShapeManager()->removeReference(_shape);
|
||||
getShapeManager()->releaseShape(_shape);
|
||||
_shape = newShape;
|
||||
_body->setShape(_shape);
|
||||
_body->setCollisionShape(_shape);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
engine->addRigidBody(_body, motionType, mass);
|
||||
} else {
|
||||
engine->removeRigidBody(_body);
|
||||
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
|
||||
handleEasyChanges(flags);
|
||||
}
|
||||
engine->addRigidBody(_body, motionType, mass);
|
||||
}
|
||||
engine->reinsertObject(this);
|
||||
}
|
||||
|
||||
void ObjectMotionState::updateBodyMaterialProperties() {
|
||||
|
|
|
@ -90,6 +90,8 @@ public:
|
|||
virtual void clearIncomingDirtyFlags(uint32_t flags) = 0;
|
||||
|
||||
virtual MotionType computeObjectMotionType() const = 0;
|
||||
virtual void computeObjectShapeInfo(ShapeInfo& shapeInfo);
|
||||
|
||||
|
||||
btCollisionShape* getShape() const { return _shape; }
|
||||
btRigidBody* getRigidBody() const { return _body; }
|
||||
|
|
|
@ -59,8 +59,6 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItem* entity) {
|
|||
void* physicsInfo = entity->getPhysicsInfo();
|
||||
if (physicsInfo) {
|
||||
_pendingRemoves.insert(entity);
|
||||
} else {
|
||||
clearEntitySimulation(entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,9 +67,6 @@ void PhysicalEntitySimulation::deleteEntityInternal(EntityItem* entity) {
|
|||
void* physicsInfo = entity->getPhysicsInfo();
|
||||
if (physicsInfo) {
|
||||
_pendingRemoves.insert(entity);
|
||||
} else {
|
||||
clearEntitySimulation(entity);
|
||||
delete entity;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,16 +105,18 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
|
|||
// while it is in the middle of a simulation step. As it is, we're probably in shutdown mode
|
||||
// anyway, so maybe the simulation was already properly shutdown? Cross our fingers...
|
||||
|
||||
_physicsEngine->deleteObjects(_physicalEntities);
|
||||
|
||||
for (auto stateItr : _physicalEntities) {
|
||||
// first disconnect each MotionStates from its Entity
|
||||
for (auto stateItr : _physicalObjects) {
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(&(*stateItr));
|
||||
EntityItem* entity = motionState->getEntity();
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
delete motionState;
|
||||
}
|
||||
|
||||
_physicalEntities.clear();
|
||||
// then delete the objects (aka MotionStates)
|
||||
_physicsEngine->deleteObjects(_physicalObjects);
|
||||
|
||||
// finally clear all lists (which now have only dangling pointers)
|
||||
_physicalObjects.clear();
|
||||
_pendingRemoves.clear();
|
||||
_pendingAdds.clear();
|
||||
_pendingChanges.clear();
|
||||
|
@ -127,7 +124,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
|
|||
// end EntitySimulation overrides
|
||||
|
||||
|
||||
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToRemove() {
|
||||
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToDelete() {
|
||||
_tempVector.clear();
|
||||
for (auto entityItr : _pendingRemoves) {
|
||||
EntityItem* entity = &(*entityItr);
|
||||
|
@ -135,8 +132,12 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToRemove() {
|
|||
_pendingChanges.remove(entity);
|
||||
EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState) {
|
||||
_physicalObjects.remove(motionState);
|
||||
// disconnect EntityMotionState from its Entity
|
||||
// NOTE: EntityMotionState still has a back pointer to its Entity, but is about to be deleted
|
||||
// (by PhysicsEngine) and shouldn't actually access its Entity during this process.
|
||||
entity->setPhysicsInfo(nullptr);
|
||||
_tempVector.push_back(motionState);
|
||||
_physicalEntities.remove(motionState);
|
||||
}
|
||||
}
|
||||
_pendingRemoves.clear();
|
||||
|
@ -158,7 +159,7 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
|
|||
EntityMotionState* motionState = new EntityMotionState(shape, entity);
|
||||
entity->setPhysicsInfo(static_cast<void*>(motionState));
|
||||
motionState->setMass(entity->computeMass());
|
||||
_physicalEntities.insert(motionState);
|
||||
_physicalObjects.insert(motionState);
|
||||
_tempVector.push_back(motionState);
|
||||
entityItr = _pendingAdds.erase(entityItr);
|
||||
} else {
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
void sortEntitiesThatMovedInternal();
|
||||
void clearEntitiesInternal();
|
||||
|
||||
VectorOfMotionStates& getObjectsToRemove();
|
||||
VectorOfMotionStates& getObjectsToDelete();
|
||||
VectorOfMotionStates& getObjectsToAdd();
|
||||
VectorOfMotionStates& getObjectsToChange();
|
||||
|
||||
|
@ -52,15 +52,15 @@ private:
|
|||
void bump(EntityItem* bumpEntity);
|
||||
|
||||
// incoming changes
|
||||
SetOfEntities _pendingRemoves; // entities to be removed from simulation
|
||||
SetOfEntities _pendingAdds; // entities to be be added to simulation
|
||||
SetOfEntities _pendingChanges; // entities already in simulation that need to be changed
|
||||
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 _pendingChanges; // entities already in PhysicsEngine that need their physics changed
|
||||
|
||||
// outgoing changes
|
||||
QSet<EntityMotionState*> _outgoingChanges; // entities for which we need to send updates to entity-server
|
||||
|
||||
SetOfMotionStates _physicalEntities; // MotionStates of entities in PhysicsEngine
|
||||
VectorOfMotionStates _tempVector; // temporary list, valid by reference immediately after call to getObjectsToRemove/Add/Update()
|
||||
SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine
|
||||
VectorOfMotionStates _tempVector; // temporary array, valid by reference immediately after call to getObjectsToRemove/Add/Update()
|
||||
|
||||
ShapeManager* _shapeManager = nullptr;
|
||||
PhysicsEngine* _physicsEngine = nullptr;
|
||||
|
|
|
@ -59,42 +59,113 @@ void PhysicsEngine::init() {
|
|||
}
|
||||
}
|
||||
|
||||
void PhysicsEngine::removeObjects(VectorOfMotionStates& objects) {
|
||||
for (auto object : objects) {
|
||||
assert(object);
|
||||
|
||||
// wake up anything touching this object
|
||||
bump(object);
|
||||
void PhysicsEngine::addObject(ObjectMotionState* motionState) {
|
||||
assert(motionState);
|
||||
|
||||
btRigidBody* body = object->getRigidBody();
|
||||
_dynamicsWorld->removeRigidBody(body);
|
||||
removeContacts(object);
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
float mass = 0.0f;
|
||||
// NOTE: the body may or may not already exist, depending on whether this corresponds to a reinsertion, or a new insertion.
|
||||
btRigidBody* body = motionState->getRigidBody();
|
||||
MotionType motionType = motionState->computeObjectMotionType();
|
||||
motionState->setMotionType(motionType);
|
||||
switch(motionType) {
|
||||
case MOTION_TYPE_KINEMATIC: {
|
||||
if (!body) {
|
||||
btCollisionShape* shape = motionState->getShape();
|
||||
assert(shape);
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
} else {
|
||||
body->setMassProps(mass, inertia);
|
||||
}
|
||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
motionState->updateBodyVelocities();
|
||||
const float KINEMATIC_LINEAR_VELOCITY_THRESHOLD = 0.01f; // 1 cm/sec
|
||||
const float KINEMATIC_ANGULAR_VELOCITY_THRESHOLD = 0.01f; // ~1 deg/sec
|
||||
body->setSleepingThresholds(KINEMATIC_LINEAR_VELOCITY_THRESHOLD, KINEMATIC_ANGULAR_VELOCITY_THRESHOLD);
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_DYNAMIC: {
|
||||
mass = motionState->getMass();
|
||||
btCollisionShape* shape = motionState->getShape();
|
||||
assert(shape);
|
||||
shape->calculateLocalInertia(mass, inertia);
|
||||
if (!body) {
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
} else {
|
||||
body->setMassProps(mass, inertia);
|
||||
}
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
motionState->updateBodyVelocities();
|
||||
// NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds.
|
||||
// (the 2 seconds is determined by: static btRigidBody::gDeactivationTime
|
||||
const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec
|
||||
const float DYNAMIC_ANGULAR_VELOCITY_THRESHOLD = 0.087266f; // ~5 deg/sec
|
||||
body->setSleepingThresholds(DYNAMIC_LINEAR_VELOCITY_THRESHOLD, DYNAMIC_ANGULAR_VELOCITY_THRESHOLD);
|
||||
if (!motionState->isMoving()) {
|
||||
// try to initialize this object as inactive
|
||||
body->forceActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_STATIC:
|
||||
default: {
|
||||
if (!body) {
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
} else {
|
||||
body->setMassProps(mass, inertia);
|
||||
}
|
||||
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
break;
|
||||
}
|
||||
}
|
||||
body->setFlags(BT_DISABLE_WORLD_GRAVITY);
|
||||
motionState->updateBodyMaterialProperties();
|
||||
|
||||
_dynamicsWorld->addRigidBody(body);
|
||||
}
|
||||
|
||||
void PhysicsEngine::removeObject(ObjectMotionState* object) {
|
||||
// wake up anything touching this object
|
||||
bump(object);
|
||||
removeContacts(object);
|
||||
|
||||
btRigidBody* body = object->getRigidBody();
|
||||
assert(body);
|
||||
_dynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
|
||||
void PhysicsEngine::deleteObjects(VectorOfMotionStates& objects) {
|
||||
for (auto object : objects) {
|
||||
removeObject(object);
|
||||
|
||||
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
|
||||
object->setRigidBody(nullptr);
|
||||
delete body;
|
||||
object->releaseShape();
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, but takes a Set instead of a Vector. Only called during teardown.
|
||||
void PhysicsEngine::deleteObjects(SetOfMotionStates& objects) {
|
||||
for (auto object : objects) {
|
||||
assert(object);
|
||||
|
||||
btRigidBody* body = object->getRigidBody();
|
||||
_dynamicsWorld->removeRigidBody(body);
|
||||
removeContacts(object);
|
||||
|
||||
|
||||
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
|
||||
object->setRigidBody(nullptr);
|
||||
delete body;
|
||||
object->releaseShape();
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsEngine::addObjects(VectorOfMotionStates& objects) {
|
||||
for (auto object : objects) {
|
||||
assert(object);
|
||||
addObject(object);
|
||||
}
|
||||
}
|
||||
|
@ -302,62 +373,13 @@ void PhysicsEngine::dumpStatsIfNecessary() {
|
|||
// CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
|
||||
// CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
|
||||
|
||||
void PhysicsEngine::addObject(ObjectMotionState* motionState) {
|
||||
assert(motionState);
|
||||
btCollisionShape* shape = motionState->getShape();
|
||||
assert(shape);
|
||||
|
||||
btVector3 inertia(0.0f, 0.0f, 0.0f);
|
||||
float mass = 0.0f;
|
||||
btRigidBody* body = nullptr;
|
||||
MotionType motionType = motionState->computeObjectMotionType();
|
||||
motionState->setMotionType(motionType);
|
||||
switch(motionType) {
|
||||
case MOTION_TYPE_KINEMATIC: {
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->setCollisionFlags(btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
motionState->updateBodyVelocities();
|
||||
const float KINEMATIC_LINEAR_VELOCITY_THRESHOLD = 0.01f; // 1 cm/sec
|
||||
const float KINEMATIC_ANGULAR_VELOCITY_THRESHOLD = 0.01f; // ~1 deg/sec
|
||||
body->setSleepingThresholds(KINEMATIC_LINEAR_VELOCITY_THRESHOLD, KINEMATIC_ANGULAR_VELOCITY_THRESHOLD);
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_DYNAMIC: {
|
||||
mass = motionState->getMass();
|
||||
shape->calculateLocalInertia(mass, inertia);
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
motionState->updateBodyVelocities();
|
||||
// NOTE: Bullet will deactivate any object whose velocity is below these thresholds for longer than 2 seconds.
|
||||
// (the 2 seconds is determined by: static btRigidBody::gDeactivationTime
|
||||
const float DYNAMIC_LINEAR_VELOCITY_THRESHOLD = 0.05f; // 5 cm/sec
|
||||
const float DYNAMIC_ANGULAR_VELOCITY_THRESHOLD = 0.087266f; // ~5 deg/sec
|
||||
body->setSleepingThresholds(DYNAMIC_LINEAR_VELOCITY_THRESHOLD, DYNAMIC_ANGULAR_VELOCITY_THRESHOLD);
|
||||
if (!motionState->isMoving()) {
|
||||
// try to initialize this object as inactive
|
||||
body->forceActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOTION_TYPE_STATIC:
|
||||
default: {
|
||||
body = new btRigidBody(mass, motionState, shape, inertia);
|
||||
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
|
||||
body->updateInertiaTensor();
|
||||
motionState->setRigidBody(body);
|
||||
break;
|
||||
}
|
||||
}
|
||||
body->setFlags(BT_DISABLE_WORLD_GRAVITY);
|
||||
motionState->updateBodyMaterialProperties();
|
||||
|
||||
_dynamicsWorld->addRigidBody(body);
|
||||
void PhysicsEngine::reinsertObject(ObjectMotionState* object) {
|
||||
removeObject(object);
|
||||
addObject(object);
|
||||
}
|
||||
|
||||
void PhysicsEngine::bump(ObjectMotionState* object) {
|
||||
assert(object);
|
||||
/* TODO: Andrew to implement this
|
||||
// If this node is doing something like deleting an entity, scan for contacts involving the
|
||||
// entity. For each found, flag the other entity involved as being simulated by this node.
|
||||
|
@ -437,11 +459,6 @@ void PhysicsEngine::bump(EntityItem* bumpEntity) {
|
|||
}
|
||||
*/
|
||||
|
||||
void PhysicsEngine::removeRigidBody(btRigidBody* body) {
|
||||
// pull body out of physics engine
|
||||
_dynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
|
||||
void PhysicsEngine::setCharacterController(DynamicCharacterController* character) {
|
||||
if (_characterController != character) {
|
||||
if (_characterController) {
|
||||
|
|
|
@ -51,9 +51,11 @@ public:
|
|||
~PhysicsEngine();
|
||||
void init();
|
||||
|
||||
/// process queue of changed from external sources
|
||||
void removeObjects(VectorOfMotionStates& objects);
|
||||
void deleteObjects(SetOfMotionStates& objects);
|
||||
void addObject(ObjectMotionState* motionState);
|
||||
void removeObject(ObjectMotionState* motionState);
|
||||
|
||||
void deleteObjects(VectorOfMotionStates& objects);
|
||||
void deleteObjects(SetOfMotionStates& objects); // only called during teardown
|
||||
void addObjects(VectorOfMotionStates& objects);
|
||||
void changeObjects(VectorOfMotionStates& objects);
|
||||
|
||||
|
@ -71,10 +73,6 @@ public:
|
|||
/// \return position of simulation origin in domain-frame
|
||||
const glm::vec3& getOriginOffset() const { return _originOffset; }
|
||||
|
||||
/// \param motionState pointer to Object's MotionState
|
||||
/// \return true if Object added
|
||||
void addObject(ObjectMotionState* motionState);
|
||||
|
||||
void bump(ObjectMotionState* motionState);
|
||||
|
||||
void removeRigidBody(btRigidBody* body);
|
||||
|
|
Loading…
Reference in a new issue