allow for asynchronous building of collision shape

This commit is contained in:
Seth Alves 2015-08-21 10:48:26 -07:00
parent af33b051dc
commit 6db0442fda
11 changed files with 75 additions and 24 deletions

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -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() {

View file

@ -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);

View file

@ -173,6 +173,12 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
return _tempVector;
}
void PhysicalEntitySimulation::setObjectsToChange(VectorOfMotionStates& objectsToChange) {
for (auto object : objectsToChange) {
_pendingChanges.insert(static_cast<EntityMotionState*>(object));
}
}
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() {
_tempVector.clear();
for (auto stateItr : _pendingChanges) {

View file

@ -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);

View file

@ -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) {

View file

@ -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();