Merge branch 'master' of github.com:highfidelity/hifi into head-controller

This commit is contained in:
Seth Alves 2017-06-02 15:29:26 -07:00
commit 8a4ccf5c46
12 changed files with 80 additions and 74 deletions

View file

@ -681,7 +681,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// and pretend that we own it (we assume we'll recover it soon) // and pretend that we own it (we assume we'll recover it soon)
// However, for now, when the server uses a newer time than what we sent, listen to what we're told. // However, for now, when the server uses a newer time than what we sent, listen to what we're told.
if (overwriteLocalData) weOwnSimulation = false; if (overwriteLocalData) {
weOwnSimulation = false;
}
} else if (_simulationOwner.set(newSimOwner)) { } else if (_simulationOwner.set(newSimOwner)) {
markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID);
somethingChanged = true; somethingChanged = true;
@ -1293,27 +1295,15 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c
properties._accelerationChanged = true; properties._accelerationChanged = true;
} }
void EntityItem::pokeSimulationOwnership() { void EntityItem::flagForOwnershipBid(uint8_t priority) {
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE); markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY);
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it // we already own it
_simulationOwner.promotePriority(SCRIPT_POKE_SIMULATION_PRIORITY); _simulationOwner.promotePriority(priority);
} else { } else {
// we don't own it yet // we don't own it yet
_simulationOwner.setPendingPriority(SCRIPT_POKE_SIMULATION_PRIORITY, usecTimestampNow()); _simulationOwner.setPendingPriority(priority, usecTimestampNow());
}
}
void EntityItem::grabSimulationOwnership() {
markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB);
auto nodeList = DependencyManager::get<NodeList>();
if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) {
// we already own it
_simulationOwner.promotePriority(SCRIPT_GRAB_SIMULATION_PRIORITY);
} else {
// we don't own it yet
_simulationOwner.setPendingPriority(SCRIPT_GRAB_SIMULATION_PRIORITY, usecTimestampNow());
} }
} }

View file

@ -321,6 +321,7 @@ public:
void updateSimulationOwner(const SimulationOwner& owner); void updateSimulationOwner(const SimulationOwner& owner);
void clearSimulationOwnership(); void clearSimulationOwnership();
void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp);
uint8_t getPendingOwnershipPriority() const { return _simulationOwner.getPendingPriority(); }
void rememberHasSimulationOwnershipBid() const; void rememberHasSimulationOwnershipBid() const;
QString getMarketplaceID() const; QString getMarketplaceID() const;
@ -394,8 +395,7 @@ public:
void getAllTerseUpdateProperties(EntityItemProperties& properties) const; void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
void pokeSimulationOwnership(); void flagForOwnershipBid(uint8_t priority);
void grabSimulationOwnership();
void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; } void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; }
QString actionsToDebugString(); QString actionsToDebugString();

View file

@ -230,6 +230,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
} }
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
// since we're creating this object we will immediately volunteer to own its simulation
entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
propertiesWithSimID.setLastEdited(entity->getLastEdited()); propertiesWithSimID.setLastEdited(entity->getLastEdited());
} else { } else {
qCDebug(entities) << "script failed to add new Entity to local Octree"; qCDebug(entities) << "script failed to add new Entity to local Octree";
@ -440,7 +442,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
} else { } else {
// we make a bid for simulation ownership // we make a bid for simulation ownership
properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY);
entity->pokeSimulationOwnership(); entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
entity->rememberHasSimulationOwnershipBid(); entity->rememberHasSimulationOwnershipBid();
} }
} }
@ -1194,7 +1196,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
} }
action->setIsMine(true); action->setIsMine(true);
success = entity->addAction(simulation, action); success = entity->addAction(simulation, action);
entity->grabSimulationOwnership(); entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
return false; // Physics will cause a packet to be sent, so don't send from here. return false; // Physics will cause a packet to be sent, so don't send from here.
}); });
if (success) { if (success) {
@ -1210,7 +1212,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) { return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) {
bool success = entity->updateAction(simulation, actionID, arguments); bool success = entity->updateAction(simulation, actionID, arguments);
if (success) { if (success) {
entity->grabSimulationOwnership(); entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY);
} }
return success; return success;
}); });
@ -1224,7 +1226,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid&
success = entity->removeAction(simulation, actionID); success = entity->removeAction(simulation, actionID);
if (success) { if (success) {
// reduce from grab to poke // reduce from grab to poke
entity->pokeSimulationOwnership(); entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY);
} }
return false; // Physics will cause a packet to be sent, so don't send from here. return false; // Physics will cause a packet to be sent, so don't send from here.
}); });

View file

@ -26,12 +26,10 @@ namespace Simulation {
const uint32_t DIRTY_MATERIAL = 0x00400; const uint32_t DIRTY_MATERIAL = 0x00400;
const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine const uint32_t DIRTY_PHYSICS_ACTIVATION = 0x0800; // should activate object in physics engine
const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed const uint32_t DIRTY_SIMULATOR_ID = 0x1000; // the simulatorID has changed
const uint32_t DIRTY_SIMULATION_OWNERSHIP_FOR_POKE = 0x2000; // bid for simulation ownership at "poke" const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = 0x2000; // our own bid priority has changed
const uint32_t DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB = 0x4000; // bid for simulation ownership at "grab"
const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION; const uint32_t DIRTY_TRANSFORM = DIRTY_POSITION | DIRTY_ROTATION;
const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY; const uint32_t DIRTY_VELOCITIES = DIRTY_LINEAR_VELOCITY | DIRTY_ANGULAR_VELOCITY;
const uint32_t DIRTY_SIMULATION_OWNERSHIP_PRIORITY = DIRTY_SIMULATION_OWNERSHIP_FOR_POKE | DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB;
}; };
#endif // hifi_SimulationFlags_h #endif // hifi_SimulationFlags_h

View file

@ -26,9 +26,9 @@ const int SimulationOwner::NUM_BYTES_ENCODED = NUM_BYTES_RFC4122_UUID + 1;
SimulationOwner::SimulationOwner() : SimulationOwner::SimulationOwner() :
_id(), _id(),
_expiry(0), _expiry(0),
_pendingTimestamp(0), _pendingBidTimestamp(0),
_priority(0), _priority(0),
_pendingPriority(0), _pendingBidPriority(0),
_pendingState(PENDING_STATE_NOTHING) _pendingState(PENDING_STATE_NOTHING)
{ {
} }
@ -36,9 +36,9 @@ SimulationOwner::SimulationOwner() :
SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) : SimulationOwner::SimulationOwner(const QUuid& id, quint8 priority) :
_id(id), _id(id),
_expiry(0), _expiry(0),
_pendingTimestamp(0), _pendingBidTimestamp(0),
_priority(priority), _priority(priority),
_pendingPriority(0) _pendingBidPriority(0)
{ {
} }
@ -61,9 +61,9 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) {
void SimulationOwner::clear() { void SimulationOwner::clear() {
_id = QUuid(); _id = QUuid();
_expiry = 0; _expiry = 0;
_pendingTimestamp = 0; _pendingBidTimestamp = 0;
_priority = 0; _priority = 0;
_pendingPriority = 0; _pendingBidPriority = 0;
_pendingState = PENDING_STATE_NOTHING; _pendingState = PENDING_STATE_NOTHING;
} }
@ -102,9 +102,9 @@ bool SimulationOwner::set(const SimulationOwner& owner) {
} }
void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) { void SimulationOwner::setPendingPriority(quint8 priority, const quint64& timestamp) {
_pendingPriority = priority; _pendingBidPriority = priority;
_pendingTimestamp = timestamp; _pendingBidTimestamp = timestamp;
_pendingState = (_pendingPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE; _pendingState = (_pendingBidPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE;
} }
void SimulationOwner::updateExpiry() { void SimulationOwner::updateExpiry() {
@ -113,11 +113,11 @@ void SimulationOwner::updateExpiry() {
} }
bool SimulationOwner::pendingRelease(const quint64& timestamp) { bool SimulationOwner::pendingRelease(const quint64& timestamp) {
return _pendingPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingTimestamp >= timestamp; return _pendingBidPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingBidTimestamp >= timestamp;
} }
bool SimulationOwner::pendingTake(const quint64& timestamp) { bool SimulationOwner::pendingTake(const quint64& timestamp) {
return _pendingPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingTimestamp >= timestamp; return _pendingBidPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingBidTimestamp >= timestamp;
} }
void SimulationOwner::clearCurrentOwner() { void SimulationOwner::clearCurrentOwner() {

View file

@ -66,6 +66,7 @@ public:
bool hasExpired() const { return usecTimestampNow() > _expiry; } bool hasExpired() const { return usecTimestampNow() > _expiry; }
uint8_t getPendingPriority() const { return _pendingBidPriority; }
bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE bool pendingRelease(const quint64& timestamp); // return true if valid pending RELEASE
bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE bool pendingTake(const quint64& timestamp); // return true if valid pending TAKE
void clearCurrentOwner(); void clearCurrentOwner();
@ -84,9 +85,9 @@ public:
private: private:
QUuid _id; // owner QUuid _id; // owner
quint64 _expiry; // time when ownership can transition at equal priority quint64 _expiry; // time when ownership can transition at equal priority
quint64 _pendingTimestamp; // time when pending update was set quint64 _pendingBidTimestamp; // time when pending bid was set
quint8 _priority; // priority of current owner quint8 _priority; // priority of current owner
quint8 _pendingPriority; // priority of pendingTake quint8 _pendingBidPriority; // priority at which we'd like to own it
quint8 _pendingState; // NOTHING, TAKE, or RELEASE quint8 _pendingState; // NOTHING, TAKE, or RELEASE
}; };

View file

@ -65,8 +65,7 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer
_lastStep(0), _lastStep(0),
_loopsWithoutOwner(0), _loopsWithoutOwner(0),
_accelerationNearlyGravityCount(0), _accelerationNearlyGravityCount(0),
_numInactiveUpdates(1), _numInactiveUpdates(1)
_outgoingPriority(0)
{ {
_type = MOTIONSTATE_TYPE_ENTITY; _type = MOTIONSTATE_TYPE_ENTITY;
assert(_entity); assert(_entity);
@ -75,6 +74,8 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer
// we need the side-effects of EntityMotionState::setShape() so we call it explicitly here // we need the side-effects of EntityMotionState::setShape() so we call it explicitly here
// rather than pass the legit shape pointer to the ObjectMotionState ctor above. // rather than pass the legit shape pointer to the ObjectMotionState ctor above.
setShape(shape); setShape(shape);
_outgoingPriority = _entity->getPendingOwnershipPriority();
} }
EntityMotionState::~EntityMotionState() { EntityMotionState::~EntityMotionState() {
@ -84,7 +85,7 @@ EntityMotionState::~EntityMotionState() {
void EntityMotionState::updateServerPhysicsVariables() { void EntityMotionState::updateServerPhysicsVariables() {
assert(entityTreeIsLocked()); assert(entityTreeIsLocked());
if (_entity->getSimulatorID() == Physics::getSessionUUID()) { if (isLocallyOwned()) {
// don't slam these values if we are the simulation owner // don't slam these values if we are the simulation owner
return; return;
} }
@ -136,23 +137,23 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) {
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
} }
_loopsWithoutOwner = 0; _loopsWithoutOwner = 0;
} else if (_entity->getSimulatorID() == Physics::getSessionUUID()) { _numInactiveUpdates = 0;
} else if (isLocallyOwned()) {
// we just inherited ownership, make sure our desired priority matches what we have // we just inherited ownership, make sure our desired priority matches what we have
upgradeOutgoingPriority(_entity->getSimulationPriority()); upgradeOutgoingPriority(_entity->getSimulationPriority());
} else { } else {
_outgoingPriority = 0; _outgoingPriority = 0;
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; _nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
_numInactiveUpdates = 0;
} }
} }
if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) { if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) {
// The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bits really mean "we should bid for ownership because // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bit means one of the following:
// a local script has been changing physics properties, or we should adjust our own ownership priority". // (1) we own it but may need to change the priority OR...
// The desired priority is determined by which bits were set. // (2) we don't own it but should bid (because a local script has been changing physics properties)
if (flags & Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB) { uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority();
_outgoingPriority = SCRIPT_GRAB_SIMULATION_PRIORITY; _outgoingPriority = glm::max(_outgoingPriority, newPriority);
} else {
_outgoingPriority = SCRIPT_POKE_SIMULATION_PRIORITY;
}
// reset bid expiry so that we bid ASAP // reset bid expiry so that we bid ASAP
_nextOwnershipBid = 0; _nextOwnershipBid = 0;
} }
@ -317,7 +318,7 @@ bool EntityMotionState::isCandidateForOwnership() const {
assert(_entity); assert(_entity);
assert(entityTreeIsLocked()); assert(entityTreeIsLocked());
return _outgoingPriority != 0 return _outgoingPriority != 0
|| Physics::getSessionUUID() == _entity->getSimulatorID() || isLocallyOwned()
|| _entity->dynamicDataNeedsTransmit(); || _entity->dynamicDataNeedsTransmit();
} }
@ -491,7 +492,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
return true; return true;
} }
if (_entity->getSimulatorID() != Physics::getSessionUUID()) { if (!isLocallyOwned()) {
// we don't own the simulation // we don't own the simulation
// NOTE: we do not volunteer to own kinematic or static objects // NOTE: we do not volunteer to own kinematic or static objects
@ -599,7 +600,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_
properties.clearSimulationOwner(); properties.clearSimulationOwner();
_outgoingPriority = 0; _outgoingPriority = 0;
_entity->setPendingOwnershipPriority(_outgoingPriority, now); _entity->setPendingOwnershipPriority(_outgoingPriority, now);
} else if (Physics::getSessionUUID() != _entity->getSimulatorID()) { } else if (!isLocallyOwned()) {
// we don't own the simulation for this entity yet, but we're sending a bid for it // we don't own the simulation for this entity yet, but we're sending a bid for it
quint8 bidPriority = glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY); quint8 bidPriority = glm::max<uint8_t>(_outgoingPriority, VOLUNTEER_SIMULATION_PRIORITY);
properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority); properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority);
@ -788,6 +789,10 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma
_entity->computeCollisionGroupAndFinalMask(group, mask); _entity->computeCollisionGroupAndFinalMask(group, mask);
} }
bool EntityMotionState::isLocallyOwned() const {
return _entity->getSimulatorID() == Physics::getSessionUUID();
}
bool EntityMotionState::shouldBeLocallyOwned() const { bool EntityMotionState::shouldBeLocallyOwned() const {
return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) || return (_outgoingPriority > VOLUNTEER_SIMULATION_PRIORITY && _outgoingPriority > _entity->getSimulationPriority()) ||
_entity->getSimulatorID() == Physics::getSessionUUID(); _entity->getSimulatorID() == Physics::getSessionUUID();

View file

@ -79,6 +79,7 @@ public:
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
bool isLocallyOwned() const override;
bool shouldBeLocallyOwned() const override; bool shouldBeLocallyOwned() const override;
friend class PhysicalEntitySimulation; friend class PhysicalEntitySimulation;

View file

@ -146,6 +146,7 @@ public:
void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; } void dirtyInternalKinematicChanges() { _hasInternalKinematicChanges = true; }
void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; } void clearInternalKinematicChanges() { _hasInternalKinematicChanges = false; }
virtual bool isLocallyOwned() const { return false; }
virtual bool shouldBeLocallyOwned() const { return false; } virtual bool shouldBeLocallyOwned() const { return false; }
friend class PhysicsEngine; friend class PhysicsEngine;

View file

@ -129,6 +129,9 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) {
} }
body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT); body->setCollisionFlags(btCollisionObject::CF_STATIC_OBJECT);
body->updateInertiaTensor(); body->updateInertiaTensor();
if (motionState->isLocallyOwned()) {
_activeStaticBodies.insert(body);
}
break; break;
} }
} }
@ -174,19 +177,9 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) {
// frame (because the framerate is faster than our physics simulation rate). When this happens we must scan // frame (because the framerate is faster than our physics simulation rate). When this happens we must scan
// _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer. // _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer.
for (auto object : objects) { for (auto object : objects) {
btRigidBody* body = object->getRigidBody(); std::set<btRigidBody*>::iterator itr = _activeStaticBodies.find(object->getRigidBody());
if (itr != _activeStaticBodies.end()) {
std::vector<btRigidBody*>::reverse_iterator itr = _activeStaticBodies.rbegin(); _activeStaticBodies.erase(itr);
while (itr != _activeStaticBodies.rend()) {
if (body == *itr) {
if (*itr != *(_activeStaticBodies.rbegin())) {
// swap with rbegin
*itr = *(_activeStaticBodies.rbegin());
}
_activeStaticBodies.pop_back();
break;
}
++itr;
} }
} }
} }
@ -245,14 +238,16 @@ VectorOfMotionStates PhysicsEngine::changeObjects(const VectorOfMotionStates& ob
object->clearIncomingDirtyFlags(); object->clearIncomingDirtyFlags();
} }
if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) { if (object->getMotionType() == MOTION_TYPE_STATIC && object->isActive()) {
_activeStaticBodies.push_back(object->getRigidBody()); _activeStaticBodies.insert(object->getRigidBody());
} }
} }
// active static bodies have changed (in an Easy way) and need their Aabbs updated // 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) // but we've configured Bullet to NOT update them automatically (for improved performance)
// so we must do it ourselves // so we must do it ourselves
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) { std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
_dynamicsWorld->updateSingleAabb(_activeStaticBodies[i]); while (itr != _activeStaticBodies.end()) {
_dynamicsWorld->updateSingleAabb(*itr);
++itr;
} }
return stillNeedChange; return stillNeedChange;
} }
@ -496,13 +491,23 @@ const CollisionEvents& PhysicsEngine::getCollisionEvents() {
const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() { const VectorOfMotionStates& PhysicsEngine::getChangedMotionStates() {
BT_PROFILE("copyOutgoingChanges"); BT_PROFILE("copyOutgoingChanges");
_dynamicsWorld->synchronizeMotionStates();
// Bullet will not deactivate static objects (it doesn't expect them to be active) // Bullet will not deactivate static objects (it doesn't expect them to be active)
// so we must deactivate them ourselves // so we must deactivate them ourselves
for (size_t i = 0; i < _activeStaticBodies.size(); ++i) { std::set<btRigidBody*>::const_iterator itr = _activeStaticBodies.begin();
_activeStaticBodies[i]->forceActivationState(ISLAND_SLEEPING); while (itr != _activeStaticBodies.end()) {
btRigidBody* body = *itr;
body->forceActivationState(ISLAND_SLEEPING);
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(body->getUserPointer());
if (motionState) {
_dynamicsWorld->addChangedMotionState(motionState);
}
++itr;
} }
_activeStaticBodies.clear(); _activeStaticBodies.clear();
_dynamicsWorld->synchronizeMotionStates();
_hasOutgoingChanges = false; _hasOutgoingChanges = false;
return _dynamicsWorld->getChangedMotionStates(); return _dynamicsWorld->getChangedMotionStates();
} }

View file

@ -13,6 +13,7 @@
#define hifi_PhysicsEngine_h #define hifi_PhysicsEngine_h
#include <stdint.h> #include <stdint.h>
#include <set>
#include <vector> #include <vector>
#include <QUuid> #include <QUuid>
@ -114,7 +115,7 @@ private:
CollisionEvents _collisionEvents; CollisionEvents _collisionEvents;
QHash<QUuid, EntityDynamicPointer> _objectDynamics; QHash<QUuid, EntityDynamicPointer> _objectDynamics;
QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody; QHash<btRigidBody*, QSet<QUuid>> _objectDynamicsByBody;
std::vector<btRigidBody*> _activeStaticBodies; std::set<btRigidBody*> _activeStaticBodies;
glm::vec3 _originOffset; glm::vec3 _originOffset;

View file

@ -51,6 +51,8 @@ public:
const VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; } const VectorOfMotionStates& getChangedMotionStates() const { return _changedMotionStates; }
const VectorOfMotionStates& getDeactivatedMotionStates() const { return _deactivatedStates; } const VectorOfMotionStates& getDeactivatedMotionStates() const { return _deactivatedStates; }
void addChangedMotionState(ObjectMotionState* motionState) { _changedMotionStates.push_back(motionState); }
private: private:
// call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState() // call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState()
void synchronizeMotionState(btRigidBody* body); void synchronizeMotionState(btRigidBody* body);