update Aabb's of static objects when they move

This commit is contained in:
Andrew Meadows 2016-04-11 23:15:22 -07:00
parent dcf28937cf
commit bb59860cfe
7 changed files with 45 additions and 20 deletions

View file

@ -94,7 +94,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
}
// virtual
bool EntityMotionState::handleEasyChanges(uint32_t& flags) {
void EntityMotionState::handleEasyChanges(uint32_t& flags) {
assert(entityTreeIsLocked());
updateServerPhysicsVariables();
ObjectMotionState::handleEasyChanges(flags);
@ -137,8 +137,6 @@ bool EntityMotionState::handleEasyChanges(uint32_t& flags) {
if ((flags & Simulation::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
_body->activate();
}
return true;
}

View file

@ -29,7 +29,7 @@ public:
virtual ~EntityMotionState();
void updateServerPhysicsVariables();
virtual bool handleEasyChanges(uint32_t& flags) override;
virtual void handleEasyChanges(uint32_t& flags) override;
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override;
/// \return PhysicsMotionType based on params set in EntityItem

View file

@ -164,7 +164,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
}
}
bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
void ObjectMotionState::handleEasyChanges(uint32_t& flags) {
if (flags & Simulation::DIRTY_POSITION) {
btTransform worldTrans = _body->getWorldTransform();
btVector3 newPosition = glmToBullet(getObjectPosition());
@ -183,6 +183,10 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
worldTrans.setRotation(newRotation);
}
_body->setWorldTransform(worldTrans);
if (!(flags & HARD_DIRTY_PHYSICS_FLAGS) && _body->isStaticObject()) {
// force activate static body so its Aabb is updated later
_body->activate(true);
}
} else if (flags & Simulation::DIRTY_ROTATION) {
btTransform worldTrans = _body->getWorldTransform();
btQuaternion newRotation = glmToBullet(getObjectRotation());
@ -192,6 +196,10 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
}
worldTrans.setRotation(newRotation);
_body->setWorldTransform(worldTrans);
if (!(flags & HARD_DIRTY_PHYSICS_FLAGS) && _body->isStaticObject()) {
// force activate static body so its Aabb is updated later
_body->activate(true);
}
}
if (flags & Simulation::DIRTY_LINEAR_VELOCITY) {
@ -232,8 +240,6 @@ bool ObjectMotionState::handleEasyChanges(uint32_t& flags) {
if (flags & Simulation::DIRTY_MASS) {
updateBodyMassProperties();
}
return true;
}
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {

View file

@ -50,11 +50,12 @@ const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_MOTION_TY
Simulation::DIRTY_COLLISION_GROUP);
const uint32_t EASY_DIRTY_PHYSICS_FLAGS = (uint32_t)(Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES |
Simulation::DIRTY_MASS | Simulation::DIRTY_MATERIAL |
Simulation::DIRTY_SIMULATOR_ID | Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
Simulation::DIRTY_SIMULATOR_ID | Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY |
Simulation::DIRTY_PHYSICS_ACTIVATION);
// These are the set of incoming flags that the PhysicsEngine needs to hear about:
const uint32_t DIRTY_PHYSICS_FLAGS = (uint32_t)(HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS |
Simulation::DIRTY_PHYSICS_ACTIVATION);
const uint32_t DIRTY_PHYSICS_FLAGS = (uint32_t)(HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS);
// These are the outgoing flags that the PhysicsEngine can affect:
const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = Simulation::DIRTY_TRANSFORM | Simulation::DIRTY_VELOCITIES;
@ -80,7 +81,7 @@ public:
ObjectMotionState(btCollisionShape* shape);
~ObjectMotionState();
virtual bool handleEasyChanges(uint32_t& flags);
virtual void handleEasyChanges(uint32_t& flags);
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine);
void updateBodyMaterialProperties();

View file

@ -49,6 +49,13 @@ void PhysicsEngine::init() {
// default gravity of the world is zero, so each object must specify its own gravity
// TODO: set up gravity zones
_dynamicsWorld->setGravity(btVector3(0.0f, 0.0f, 0.0f));
// By default Bullet will update the Aabb's of all objects every frame, even statics.
// This can waste CPU cycles so we configure Bullet to only update ACTIVE objects here.
// However, this means when a static object is moved we must manually update its Aabb
// in order for its broadphase collision queries to work correctly. Look at how we use
// _activeStaticBodies to track and update the Aabb's of moved static objects.
_dynamicsWorld->setForceUpdateAllAabbs(false);
}
}
@ -188,12 +195,18 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob
stillNeedChange.push_back(object);
}
} else if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
if (object->handleEasyChanges(flags)) {
object->clearIncomingDirtyFlags();
} else {
stillNeedChange.push_back(object);
}
object->handleEasyChanges(flags);
object->clearIncomingDirtyFlags();
}
if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {
_activeStaticBodies.push_back(object->getRigidBody());
}
}
// active static bodies have changed (in an Easy way) and need their Aabbs updated
// but we've configured Bullet to NOT update them automatically (for improved performance)
// so we must do it ourselves
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
_dynamicsWorld->updateSingleAabb(_activeStaticBodies[i]);
}
return stillNeedChange;
}
@ -387,6 +400,12 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() {
const VectorOfMotionStates& PhysicsEngine::getOutgoingChanges() {
BT_PROFILE("copyOutgoingChanges");
// Bullet will not deactivate static objects (it doesn't expect them to be active)
// so we must deactivate them ourselves
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) {
_activeStaticBodies[i]->forceActivationState(ISLAND_SLEEPING);
}
_activeStaticBodies.clear();
_dynamicsWorld->synchronizeMotionStates();
_hasOutgoingChanges = false;
return _dynamicsWorld->getChangedMotionStates();

View file

@ -13,9 +13,9 @@
#define hifi_PhysicsEngine_h
#include <stdint.h>
#include <vector>
#include <QUuid>
#include <QVector>
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
@ -41,7 +41,7 @@ public:
};
typedef std::map<ContactKey, ContactInfo> ContactMap;
typedef QVector<Collision> CollisionEvents;
typedef std::vector<Collision> CollisionEvents;
class PhysicsEngine {
public:
@ -108,6 +108,7 @@ private:
ContactMap _contactMap;
CollisionEvents _collisionEvents;
QHash<QUuid, EntityActionPointer> _objectActions;
std::vector<btRigidBody*> _activeStaticBodies;
glm::vec3 _originOffset;

View file

@ -51,10 +51,10 @@ const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14;
const int16_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS;
// STATIC does not collide with itself (as optimization of physics simulation)
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_STATIC);
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC);
const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT;
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_DEFAULT;
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC;
// MY_AVATAR does not collide with itself
const int16_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR);